source: cpp/frams/model/modelparts.cpp @ 659

Last change on this file since 659 was 640, checked in by Maciej Komosinski, 8 years ago

Introduced a separate function to provide a human-friendly description of a given param-item type

  • Property svn:eol-style set to native
File size: 17.4 KB
Line 
1// This file is a part of Framsticks SDK.  http://www.framsticks.com/
2// Copyright (C) 1999-2015  Maciej Komosinski and Szymon Ulatowski.
3// See LICENSE.txt for details.
4
5#include <stdlib.h>
6#include <math.h>
7#include <stdio.h>
8#include <string.h>
9#include <ctype.h>
10#include <time.h>
11#include <errno.h>
12
13///////////////////////////////     MODELPARTS.CPP     ///////////////
14
15#include "modelparts.h"
16#include "model.h"
17
18#include <common/nonstd.h>
19#include <frams/param/param.h>
20#include <frams/neuro/neurolibrary.h>
21#include <frams/util/multirange.h>
22#include <frams/util/extvalue.h>
23#include <frams/param/paramobj.h>
24
25#include F0_DEFASSIGN_FILE
26
27#ifndef SDK_WITHOUT_FRAMS
28#include <frams/neuro/neuroclsobject.h>
29#endif
30
31template<>
32char ModelUserTags::reg[5]={0};
33
34/////////////////////////
35
36PartBase::~PartBase()
37{if (mapped) delete mapped;}
38
39void PartBase::notifyMappingChange()
40{
41if (owner) owner->partmappingchanged=1;
42}
43
44void PartBase::setMapping(const IRange &r)
45{
46if (mapped) (*mapped)=r;
47else mapped=new MultiRange(r);
48notifyMappingChange();
49}
50
51void PartBase::clearMapping()
52{
53if (mapped) {delete mapped; mapped=0;}
54}
55
56void PartBase::addMapping(const IRange &r)
57{
58if (mapped) mapped->add(r);
59else mapped=new MultiRange(r);
60notifyMappingChange();
61}
62
63void PartBase::setMapping(const MultiRange &mr)
64{
65if (mapped) (*mapped)=mr;
66else mapped=new MultiRange(mr);
67notifyMappingChange();
68}
69
70void PartBase::addMapping(const MultiRange &mr)
71{
72if (mapped) mapped->add(mr);
73else mapped=new MultiRange(mr);
74notifyMappingChange();
75}
76
77void PartBase::setInfo(const SString& name,const SString& value)
78{
79strSetField(info,name,value);
80}
81
82void PartBase::setInfo(const SString& name,int value)
83{
84setInfo(name,SString::valueOf(value));
85}
86
87void PartBase::setInfo(const SString& name,double value)
88{
89setInfo(name,SString::valueOf(value));
90}
91
92SString PartBase::getInfo(const SString& name)
93{
94return strGetField(info,name);
95}
96
97/////////////////////////
98
99NeuroClass::NeuroClass(ParamEntry *_props,SString _description,
100                       int _prefinputs,int _prefoutput,int _preflocation,
101                       int *_vectordata,bool own_vd,int vhints)
102        :ownedvectordata(own_vd),
103         name(_props->name),longname(_props->id),description(_description),
104         props(_props),ownedprops(false),
105         prefinputs(_prefinputs),
106         prefoutput(_prefoutput),
107         preflocation(_preflocation),
108         vectordata(_vectordata),
109         visualhints(vhints),impl_count(0),/*impl(0),*/active(1),genactive(0)
110{}
111
112NeuroClass::~NeuroClass()
113{
114setSymbolGlyph(0,0);
115if (props && ownedprops)
116        ParamObject::freeParamTab(props);
117}
118
119NeuroClass::NeuroClass()
120        :ownedvectordata(0),
121         name("Invalid"),
122         props(empty_paramtab),ownedprops(false),
123         prefinputs(0), prefoutput(0),
124         preflocation(0), vectordata(0),
125         visualhints(0),impl_count(0), /*impl(0),*/ active(1), genactive(0)
126{}
127
128SString NeuroClass::getSummary()
129{
130SString t;
131t=getDescription();
132if (t.len()) t+="\n\n";
133t+="Characteristics:\n";
134if(getPreferredInputs())
135        {
136        if (getPreferredInputs()<0) t+="   supports any number of inputs\n";
137        else if (getPreferredInputs()==1) t+="   uses single input\n";
138        else t+=SString::sprintf("   uses %d inputs\n",getPreferredInputs());
139        }
140else t+="   does not use inputs\n";
141if(getPreferredOutput())
142        t+="   provides output value\n";
143else
144        t+="   does not provide output value\n";
145switch(getPreferredLocation())
146        {
147        case 0: t+="   does not require location in body\n"; break;
148        case 1: t+="   should be located on a Part\n"; break;
149        case 2: t+="   should be located on a Joint\n"; break;
150        }
151Param p=getProperties();
152if (p.getPropCount())
153        {
154        if (t.len()) t+="\n\n";
155        t+="Properties:\n";
156        const char *h;
157        int i;
158        for(i=0;i<p.getPropCount();i++)
159                {
160                if (i) t+="\n";
161                t+="   "; t+=p.name(i); t+=" ("; t+=p.id(i); t+=") ";
162                t+=p.describeType(i);
163                if (h=p.help(i)) if (*h) {t+=" - "; t+=h;}
164                }
165        }
166return t;
167}
168
169/////////////////////////
170
171/////////////////////////////////////
172
173Neuro::Neuro(double _state,double _inertia,double _force,double _sigmo)
174        :PartBase(getDefaultStyle()),state(_state)
175#ifdef MODEL_V1_COMPATIBLE
176,inertia(_inertia),force(_force),sigmo(_sigmo)
177#endif
178{
179#ifdef MODEL_V1_COMPATIBLE
180olditems=0;
181#endif
182flags=0;
183myclass=0;
184knownclass=1;
185part_refno=-1; joint_refno=-1;
186}
187
188Neuro::Neuro(void):PartBase(getDefaultStyle())
189{
190defassign();
191state=0.0;
192myclass=NULL;
193myclassname="N";//default d="N" but f0.def is unable to set this (d is GETSET, not a regular FIELD)
194knownclass=0;
195refno=0;
196pos=Pt3D_0; rot=Pt3D_0;
197parent=0; part=0; joint=0;
198parentcount=0;
199#ifdef MODEL_V1_COMPATIBLE
200olditems=0;
201#endif
202flags=0;
203part_refno=-1; joint_refno=-1;
204}
205
206
207Neuro::~Neuro()
208{
209#ifdef MODEL_V1_COMPATIBLE
210if (olditems) delete olditems;
211#endif
212int i;
213for(i=0;i<inputs.size();i++)
214        {
215        NInput &ni=inputs(i);
216        if (ni.info) delete ni.info;
217        }
218}
219
220SString** Neuro::inputInfo(int i)
221{
222if (i>=getInputCount()) return 0;
223return &inputs(i).info;
224}
225
226void Neuro::setInputInfo(int i,const SString& name,const SString &value)
227{
228SString **s=inputInfo(i);
229if (!s) return;
230if (!*s) *s=new SString();
231strSetField(**s,name,value);
232}
233
234void Neuro::setInputInfo(int i,const SString& name,int value)
235{
236setInputInfo(i,name,SString::valueOf(value));
237}
238
239void Neuro::setInputInfo(int i,const SString& name,double value)
240{
241setInputInfo(i,name,SString::valueOf(value));
242}
243
244SString Neuro::getInputInfo(int i)
245{
246SString **s=inputInfo(i);
247if (!s) return SString();
248if (!*s) return SString();
249return **s;
250}
251
252SString Neuro::getInputInfo(int i,const SString& name)
253{
254SString **s=inputInfo(i);
255if (!s) return SString();
256if (!*s) return SString();
257return strGetField(**s,name);
258}
259
260void Neuro::operator=(const Neuro& src)
261{
262refno=src.refno;
263#ifdef MODEL_V1_COMPATIBLE
264neuro_refno=-1;
265conn_refno=-1;
266force=src.force;
267sigmo=src.sigmo;
268inertia=src.inertia;
269weight=src.weight;
270olditems=0;
271#endif
272state=src.state;
273part_refno=-1;
274joint_refno=-1;
275pos=src.pos; rot=src.rot;
276parent=0; part=0; joint=0;
277parentcount=0;
278flags=0;
279myclass=src.myclass;
280knownclass=src.knownclass;
281myclassname=src.myclassname;
282myclassparams=src.myclassparams;
283}
284
285void Neuro::attachToPart(int i)
286{attachToPart((i>=0)?owner->getPart(i):0);}
287
288void Neuro::attachToJoint(int i)
289{attachToJoint((i>=0)?owner->getJoint(i):0);}
290
291int Neuro::getClassCount()
292{return NeuroLibrary::staticlibrary.getClassCount();}
293
294NeuroClass* Neuro::getClass(int classindex)
295{return NeuroLibrary::staticlibrary.getClass(classindex);}
296
297NeuroClass* Neuro::getClass(const SString& classname)
298{return NeuroLibrary::staticlibrary.findClass(classname);}
299
300int Neuro::getClassIndex(const NeuroClass*nc)
301{return NeuroLibrary::staticlibrary.classes.find((void*)nc);}
302
303NeuroClass* Neuro::getClass()
304{
305checkClass();
306return myclass;
307}
308
309void Neuro::setClass(NeuroClass* cl)
310{
311myclass=cl;
312myclassname=cl->getName();
313knownclass=1;
314}
315
316SString Neuro::getClassName(int classindex)
317{
318NeuroClass *cl=NeuroLibrary::staticlibrary.getClass(classindex);
319return cl? cl->getName() : SString();
320}
321
322void Neuro::setDetails(const SString& details)
323{
324int colon=details.indexOf(':');
325if (colon>=0) {myclassname=details.substr(0,colon); myclassparams=details.substr(colon+1);}
326else {myclassname=details; myclassparams=0;}
327knownclass=0;
328}
329
330SString Neuro::getDetails()
331{
332SString ret=getClassName();
333if (myclassparams.len()) {if (!ret.len()) ret="N"; ret+=":"; ret+=myclassparams;}
334return ret;
335}
336
337void Neuro::checkClass()
338{
339if (knownclass) return;
340myclass=getClass(myclassname);
341knownclass=1;
342}
343
344SyntParam Neuro::classProperties(bool handle_defaults_when_saving)
345{
346NeuroClass *cl=getClass();
347ParamEntry *pe = cl ? cl->getParamTab() : emptyParamTab;
348return SyntParam(pe,&myclassparams,handle_defaults_when_saving);
349}
350
351SString Neuro::getClassName()
352{
353return myclassname;
354}
355
356void Neuro::setClassName(const SString& clazz)
357{
358myclassname=clazz;
359knownclass=0;
360}
361
362int Neuro::addInput(Neuro* child,double weight,const SString *info)
363{
364inputs+=NInput(child,weight,(info&&(info->len()))?new SString(*info):0);
365child->parentcount++;
366if (child->parentcount==1) {child->parent=this;}
367return inputs.size()-1;
368}
369
370int Neuro::findInput(Neuro* child) const
371{
372for(int i=0;i<inputs.size();i++)
373        if (inputs(i).n==child) return i;
374return -1;
375}
376
377Neuro* Neuro::getInput(int i,double &weight) const
378{
379if (i>=getInputCount()) return 0;
380NInput &inp=inputs(i);
381weight=inp.weight;
382return inp.n;
383}
384
385double Neuro::getInputWeight(int i) const
386{
387return inputs(i).weight;
388}
389
390void Neuro::setInputWeight(int i,double w)
391{
392inputs(i).weight=w;
393}
394
395void Neuro::setInput(int i,Neuro* n)
396{
397NInput &inp=inputs(i);
398inp.n=n;
399}
400
401void Neuro::setInput(int i,Neuro* n,double w)
402{
403NInput &inp=inputs(i);
404inp.n=n;
405inp.weight=w;
406}
407
408void Neuro::removeInput(int refno)
409{
410Neuro *child=getInput(refno);
411child->parentcount--;
412if (child->parent==this) child->parent=0;
413SString *s=inputs(refno).info;
414if (s) delete s;
415inputs.remove(refno);
416}
417
418int Neuro::removeInput(Neuro* child)
419{
420int i=findInput(child);
421if (i>=0) removeInput(i);
422return i;
423}
424
425int Neuro::getOutputsCount() const
426{
427   int c=0;
428   for(int i=0;i<owner->getNeuroCount();i++)
429     for(int j=0;j<owner->getNeuro(i)->getInputCount();j++) c+=owner->getNeuro(i)->getInput(j)==this;
430   return c;
431}
432
433int Neuro::isOldEffector()
434{
435static SString bend("|"),rot("@");
436return ((getClassName()==bend)||(getClassName()==rot));
437}
438
439int Neuro::isOldReceptor()
440{
441static SString g("G"),t("T"),s("S");
442return ((getClassName()==g)||(getClassName()==t)||(getClassName()==s));
443}
444
445int Neuro::isOldNeuron()
446{
447static SString n("N");
448return (getClassName()==n);
449}
450
451int Neuro::isNNConnection()
452{
453static SString conn("-");
454return (getClassName()==conn);
455}
456
457int Neuro::findInputs(SList& result,const char* classname,const Part* part,const Joint* joint) const
458{
459Neuro *nu;
460SString cn(classname);
461int n0=result.size();
462for(int i=0;nu=getInput(i);i++)
463        {
464        if (part)
465                if (nu->part != part) continue;
466        if (joint)
467                if (nu->joint != joint) continue;
468        if (classname)
469                if (nu->getClassName() != cn) continue;
470        result+=(void*)nu;
471        }
472return result.size()-n0;
473}
474
475int Neuro::findOutputs(SList& result,const char* classname,const Part* part,const Joint* joint) const
476{ // not very efficient...
477Neuro *nu,*inp;
478SString cn(classname);
479SList found;
480int n0=result.size();
481for(int i=0;nu=getModel().getNeuro(i);i++)
482        {
483        if (part)
484                if (nu->part != part) continue;
485        if (joint)
486                if (nu->joint != joint) continue;
487        if (classname)
488                if (inp->getClassName() != cn) continue;
489        for (int j=0;inp=nu->getInput(j);j++)
490                if (inp==this)
491                        {
492                        result+=(void*)nu;
493                        break;
494                        }
495        }
496return result.size()-n0;
497}
498
499void Neuro::get_inputCount(PARAMGETARGS)
500{ret->setInt(inputs.size());}
501
502void Neuro::p_getInputNeuroDef(ExtValue *args,ExtValue *ret)
503{
504int i=args->getInt();
505if ((i<0)||(i>=inputs.size()))
506        ret->setEmpty();
507else
508        ret->setObject(ExtObject(&Neuro::getStaticParam(),inputs(i).n));
509}
510
511void Neuro::p_getInputWeight(ExtValue *args,ExtValue *ret)
512{
513int i=args->getInt();
514if ((i<0)||(i>=inputs.size()))
515        ret->setEmpty();
516else
517        ret->setDouble(inputs(i).weight);
518}
519
520void Neuro::p_getInputNeuroIndex(ExtValue *args,ExtValue *ret)
521{
522int i=args->getInt();
523if ((i<0)||(i>=inputs.size()))
524        ret->setInt(-1);
525else
526        ret->setInt(inputs(i).n->refno);
527}
528
529void Neuro::get_classObject(PARAMGETARGS)
530{
531#ifndef SDK_WITHOUT_FRAMS
532NeuroClassExt::makeStaticObject(ret,getClass());
533#endif
534}
535
536/////// old items
537#ifdef MODEL_V1_COMPATIBLE
538void OldItems::buildlist()
539{ // guaranteed to work only for old NN layouts
540 // (neurons,neuro connections, old receptors and effectors)
541if (listok) return;
542 // inputs can contain both neuroitem connections (details="") and direct neuron references (details="N")
543 // in OldItems we create neuroitems freom direct references
544for(int i=0;i<neuro.getInputCount();i++)
545        {
546        float w;
547        Neuro *n=neuro.getInput(i,w);
548        if (n->isOldNeuron())
549                {
550                Neuro *ni=new Neuro();
551                ni->setClassName("-");
552                ni->weight=w;
553                ni->neuro_refno=neuro.refno;
554                ni->conn_refno=n->refno;
555                items+=ni;
556                syntitems+=ni;
557                }
558        else
559                {
560                items+=n;
561                n->weight=w;
562                }
563        }
564SList outputs;
565neuro.findOutputs(outputs);
566FOREACH(Neuro*,n,outputs)
567        {
568        if (n->isNNConnection() || n->isOldNeuron())
569                outputs-=n;
570        }
571items+=outputs;
572listok=1;
573}
574
575void OldItems::freelist()
576{
577FOREACH(Neuro*,n,syntitems)
578        delete n;
579syntitems.clear();
580items.clear();
581listok=0;
582}
583
584int OldItems::getItemCount()
585{
586buildlist();
587return items.size();
588}
589
590NeuroItem *OldItems::getNeuroItem(int i)
591{
592buildlist();
593return (NeuroItem*)items(i);
594}
595
596NeuroItem *OldItems::addNewNeuroItem()
597{
598Neuro *nu=neuro.getModel().addNewNeuro();
599nu->setClassName("-");
600if (listok) items+=nu;
601neuro.addInput(nu);
602return (NeuroItem*)nu;
603}
604
605int OldItems::findNeuroItem(NeuroItem *ni)
606{
607buildlist();
608return items.find((void*)ni);
609}
610#endif
611
612///////////////////////////////////////
613
614SString Part::getDefaultStyle()
615{return SString("part");}
616SString Joint::getDefaultStyle()
617{return SString("joint");}
618/*
619const SString& Neuro::getDefaultStyle()
620{static SString s("neuro"); return s;}
621const SString& NeuroItem::getDefaultStyle()
622{static SString s("neuroitem"); return s;}
623*/
624SString Neuro::getDefaultStyle()
625{return SString("neuro");}
626
627Part::Part(enum Shape s):PartBase(getDefaultStyle())
628{
629o=Orient_1;
630p=Pt3D_0;
631rot=Pt3D_0;
632flags=0;
633defassign();
634shape=s;
635mass=1;
636}
637
638void Part::operator=(const Part& src)
639{
640p=src.p; o=src.o;
641flags=src.flags;
642mass=src.mass; density=src.density;
643friction=src.friction;
644ingest=src.ingest;
645assim=src.assim;
646size=src.size;
647rot=src.rot;
648refno=src.refno;
649vcolor=src.vcolor;
650vsize=src.vsize;
651vis_style=src.vis_style;
652shape=src.shape;
653scale=src.scale;
654hollow=src.hollow;
655}
656
657void Part::setOrient(const Orient &_o)
658{
659o=_o;
660rot.getAngles(o.x,o.z);
661}
662
663void Part::setRot(const Pt3D &r)
664{
665rot=r;
666o=Orient_1;
667o.rotate(rot);
668}
669
670void Part::setPositionAndRotationFromAxis(const Pt3D &p1,const Pt3D &p2)
671{
672Pt3D x=p2-p1;
673Pt3D dir(x.y,x.z,x.x);
674p=p1+x*0.5;
675rot.getAngles(x,dir);
676}
677
678Param& Part::getStaticParam()
679{
680static Param p(f0_part_paramtab,0,"Part");
681return p;
682}
683
684
685///////////////////////////
686
687Joint::Joint():PartBase(getDefaultStyle())
688{
689rot=Pt3D_0;
690defassign();
691d.x=JOINT_DELTA_MARKER;
692d.y=JOINT_DELTA_MARKER;
693d.z=JOINT_DELTA_MARKER;
694part1=0; part2=0;
695flags=0;
696usedelta=0;
697}
698
699void Joint::operator=(const Joint& src)
700{
701rot=src.rot;
702d=src.d;
703shape=src.shape;
704stamina=src.stamina;
705stif=src.stif; rotstif=src.rotstif;
706vis_style=src.vis_style;
707vcolor=src.vcolor;
708part1=0; part2=0;
709flags=src.flags;
710usedelta=src.usedelta;
711refno=src.refno;
712}
713
714void Joint::attachToParts(Part* p1,Part* p2)
715{
716part1=p1;
717part2=p2;
718if (p1 && p2)
719        {
720        o=rot;
721        if (usedelta)
722                {
723                p1->o.transform(p2->o,o);
724//              p2->o.x=p1->o/o.x; p2->o.y=p1->o/o.y; p2->o.z=p1->o/o.z;
725                p2->p=p2->o.transform(d)+p1->p;
726                }
727        }
728}
729
730void Joint::attachToParts(int p1,int p2)
731{
732attachToParts((p1>=0)?owner->getPart(p1):0,(p2>=0)?owner->getPart(p2):0);
733}
734
735void Joint::resetDelta()
736{
737d=Pt3D(JOINT_DELTA_MARKER,JOINT_DELTA_MARKER,JOINT_DELTA_MARKER);
738}
739
740void Joint::resetDeltaMarkers()
741{
742if (d.x==JOINT_DELTA_MARKER) d.x=0;
743if (d.y==JOINT_DELTA_MARKER) d.y=0;
744if (d.z==JOINT_DELTA_MARKER) d.z=0;
745}
746
747void Joint::useDelta(bool use)
748{
749usedelta=use;
750}
751
752bool Joint::isDelta()
753{
754return usedelta;
755}
756
757Param& Joint::getStaticParam()
758{
759static Param p(f0_joint_paramtab,0,"Joint");
760return p;
761}
762
763
764/////////////////////////////////////////////////////////////////
765/////////////////////////////////////////////////////////////////
766
767#include F0_CLASSES_FILE
768
769#ifdef MODEL_V1_COMPATIBLE
770
771#define FIELDSTRUCT Neuro
772ParamEntry f0_old_neuro_tab[]=
773{
774{"Connections",2,6,"n",},
775{"Other properties",},
776{"p",0,0,"part ref#","d",FIELD(part_refno),},
777{"j",0,0,"joint ref#","d",FIELD(joint_refno),},
778{"s",1,0,"state","f",FIELD(state),},
779{"in",1,0,"Inertia","f",FIELD(inertia),},
780{"fo",1,0,"Force","f",FIELD(force),},
781{"si",1,0,"Sigmoid","f",FIELD(sigmo),},
782{0,0,0,},
783};
784#undef FIELDSTRUCT
785
786#define FIELDSTRUCT NeuroItem
787ParamEntry f0_neuroitem_paramtab[]=
788{
789{"Connections",3,12,"ni",},
790{"Geometry",},
791{"Other",},
792{"n",0,0,"neuron ref#","d",FIELD(neuro_refno),},
793{"c",2,0,"connection ref#","d",FIELD(conn_refno),},
794{"w",2,0,"connection weight","f",FIELD(weight),},
795{"p",0,0,"part ref#","d",FIELD(part_refno),},
796{"j",0,0,"joint ref#","d",FIELD(joint_refno),},
797{"px",1,0,"position.x","f",FIELD(pos.x),},
798{"py",1,0,"position.y","f",FIELD(pos.y),},
799{"pz",1,0,"position.z","f",FIELD(pos.z),},
800{"rx",1,0,"rotation.x","f",FIELD(rot.x),},
801{"ry",1,0,"rotation.y","f",FIELD(rot.y),},
802{"rz",1,0,"rotation.z","f",FIELD(rot.z),},
803{"d",2,0,"item details","s",GETSET(details),},
804{0,0,0,},
805};
806#undef FIELDSTRUCT
807#endif
808
809////////////////////////////////////////
810
811ParamEntry Neuro::emptyParamTab[]=
812{
813{"Undefined Neuro",1,0,"?",},
814{0,0,0,},
815};
816
817Param Part::extraProperties()
818{
819return Param(f0_part_xtra_paramtab,this);
820}
821
822Param Joint::extraProperties()
823{
824return Param(f0_joint_xtra_paramtab,this);
825}
826
827Param Neuro::extraProperties()
828{
829return Param(f0_neuro_xtra_paramtab,this);
830}
831
832Param Part::properties()
833{
834return Param(f0_part_paramtab,this);
835}
836
837Param Joint::properties()
838{
839return Param(usedelta?f0_joint_paramtab:f0_nodeltajoint_paramtab,this);
840}
841
842Param Neuro::properties()
843{
844return Param(f0_neuro_paramtab,this);
845}
846
847class NeuroExtParamTab: public ParamTab
848{
849  public:
850NeuroExtParamTab():ParamTab(f0_neuro_paramtab)
851        {
852#define FIELDSTRUCT NeuroExt
853        ParamEntry entry={"class",2,0,"neuro class","s",GETSET(neuroclass)};
854#undef FIELDSTRUCT
855        add(&entry);
856
857#define FIELDSTRUCT Neuro
858        ParamEntry entry2={"state",2,0,"state","f",FIELD(state)};
859#undef FIELDSTRUCT
860        add(&entry2);
861        }
862};
863
864Param& Neuro::getStaticParam()
865{
866static Param p(f0_neuro_paramtab,0,"NeuroDef");
867return p;
868}
869
870////////////////////////
871
872NeuroConn::NeuroConn()
873{
874defassign();
875}
876
877//////////////////////////////////////
878
879ParamEntry *NeuroExt::getParamTab()
880{
881static NeuroExtParamTab tab;
882return tab.getParamTab();
883}
884
885void NeuroExt::get_neuroclass(PARAMGETARGS)
886{ret->setString(getClassName());}
887
888int NeuroExt::set_neuroclass(PARAMSETARGS)
889{setClassName(arg->getString());return PSET_CHANGED;}
890
891
Note: See TracBrowser for help on using the repository browser.