source: cpp/gdk/modelparts.h @ 94

Last change on this file since 94 was 81, checked in by Maciej Komosinski, 12 years ago

improved parsing of properties (e.g. in f0 genotypes)

  • Property svn:eol-style set to native
File size: 15.8 KB
Line 
1// This file is a part of the Framsticks GDK library.
2// Copyright (C) 2002-2011  Szymon Ulatowski.  See LICENSE.txt for details.
3// Refer to http://www.framsticks.com/ for further information.
4
5#ifndef _MODELPARTS_H_
6#define _MODELPARTS_H_
7
8#include "3d.h"
9#include "genoconv.h"
10
11#include "extvalue.h"
12#include "list.h"
13#include "sstring.h"
14#include "sstringutils.h"
15#include "param.h"
16#include "syntparam.h"
17#include "usertags.h"
18#include "paramtabobj.h"
19
20#include <stdio.h>
21
22//#define MODEL_V1_COMPATIBLE
23
24class Model;
25class IRange;
26class MultiRange;
27
28typedef UserTags<Model,void*,5> ModelUserTags;
29
30/** Common base for model elements. */
31class PartBase
32{
33public:
34SString vis_style;
35PartBase(const SString& s):vis_style(s),mapped(0) {}
36~PartBase();
37static const SString& getDefaultStyle(){static SString s("none"); return s;}
38MultiRange *mapped;
39enum PartBaseFlags { Selected=1 };
40long flags;
41Model *owner;   ///< backlink to the model
42
43SString info;
44
45Model &getModel() const {return *owner;}
46
47ModelUserTags userdata;
48
49void notifyMappingChange();
50
51void clearMapping();
52MultiRange* getMapping() {return mapped;}
53void setMapping(const IRange &mr);
54void addMapping(const IRange &mr);
55void setMapping(const MultiRange &mr);
56void addMapping(const MultiRange &mr);
57
58void setInfo(const SString& name,const SString& value);
59void setInfo(const SString& name,int value);
60void setInfo(const SString& name,double value);
61SString getInfo(const SString& name);
62};
63
64/// Part is the only real physical object in the framsticks creature.
65/// You can use this class for querying and adjusting constructed
66/// model properties
67class Part: public PartBase
68{
69friend class Model;
70static const SString& getDefaultStyle();
71Part(double _mass,double _size,double _density,double _friction,double _ingest,double _assim)
72        :mass(_mass),size(_size),density(_density),friction(_friction),ingest(_ingest),assim(_assim),
73        PartBase(getDefaultStyle())
74        {}
75public:
76// base properties - have special meaning and therefore are often accessed directly for convenience
77Pt3D p;    ///< 3d coordinates of the part
78Orient o;  ///< orientation in 3d space (rotation matrix)
79/// ParamInterface object is preferred way to get/set other properties.
80ParamInterface &extraProperties();
81ParamInterface &properties();
82long refno;
83Pt3D rot;
84
85///
86double mass,size,density,friction,ingest,assim;
87Pt3D food;
88//SList points; // collistion points
89//Slist neurons; // "select * from owner->neurons where part=this" ;-)
90
91Pt3D vcolor;
92double vsize;
93
94Part();
95Part(const Part& src):PartBase(getDefaultStyle()) {operator=(src);}
96void operator=(const Part& src);
97
98static Param& getStaticParam();
99};
100
101/// Imaginary connection between two parts.
102/// Joint has no mass nor intertia but can transfer forces.
103class Joint: public PartBase
104{
105friend class Model;
106static const SString& getDefaultStyle();
107Joint(double _stamina,double _stif,double _rotstif,double _d)
108        :stamina(_stamina),stif(_stif),rotstif(_rotstif),PartBase(getDefaultStyle())
109        {d=Pt3D(_d,0,0);}
110public:
111// base properties:
112long p1_refno,p2_refno; ///< parts' reference numbers
113
114Part *part1,*part2;     ///< references to parts
115class Pt3D d;           ///< position delta between parts
116class Pt3D rot; ///< orientation delta between parts expressed as 3 angles
117
118Joint();
119Joint(const Joint& src):PartBase(getDefaultStyle()) {operator=(src);}
120void operator=(const Joint& src);
121
122/** connect two parts with this joint.
123    p2 position will be adjusted if delta option is in effect.
124    @see isDelta()
125  */
126void attachToParts(Part* p1,Part* p2);
127/// @see attachToParts(Part*,Part*)
128void attachToParts(int p1,int p2);
129
130/** discard delta information but don't disable delta flag.
131    delta will be calculated from parts positions during final consistency check.
132 */
133void resetDelta();
134
135/** enable or disable delta option.
136    delta value is not changed.
137 */
138void useDelta(int false_or_true);
139
140/** @return 1 if delta option is in effect.
141    @see useDelta(), resetDelta(), useDelta()
142*/
143int isDelta();
144
145/// ParamInterface object is preferred way to get/set other properties.
146ParamInterface &extraProperties();
147ParamInterface &properties();
148
149// do not touch these:
150long refno; ///< this joint's reference number
151double stamina;
152double stif,rotstif;    ///< stiffness for moving and bending forces
153class Orient o; ///< orientation delta between parts as rotation matrix
154/** flag: generated f0 should include delta data.
155    set by 'singlestep' if j: attributes use delta option */
156int usedelta;
157Pt3D vcolor;
158
159static Param& getStaticParam();
160};
161
162#define JOINT_DELTA_MARKER 99999.0
163
164////////////////// NN /////////////////
165
166class NeuroClass;
167
168typedef UserTags<NeuroClass,void*,5> NeuroClassUserTags;
169
170/** Information about neuron class.
171 */
172class NeuroClass
173{
174bool ownedvectordata;
175void operator=(const NeuroClass& nosuchthich){}
176  public:
177SString name,longname,description;
178ParamEntry *props;
179long prefinputs,prefoutput;
180long preflocation;
181int *vectordata;
182long visualhints;
183
184void *impl;
185bool active;
186int genactive;
187NeuroClassUserTags userdata;
188
189//////////////////////
190~NeuroClass();
191NeuroClass();
192NeuroClass(ParamEntry *_props,SString _description,
193           int _prefinputs,int _prefoutput,int _preflocation,int *_vectordata,bool own_vd=1,int vhints=0);
194/** class name for use in Neuro::setClassName(), Neuro::setDetails() (former 'moredata' field),
195    eg. "N","-",G" */
196const SString& getName() {return name;}
197/** human friendly name, eg. "Neuron","Link","Gyroscope"  */
198const SString& getLongName() {return longname;}
199/** long description */
200const SString& getDescription() {return description;}
201ParamEntry* getParamTab() {return props;}
202
203/** NeuroClass specific properties, recognized by all neurons of this class */
204Param getProperties() {return Param(props);}
205
206/** preferred number of inputs, -1 = no preference (any number will go).
207    extra inputs may be ignored by the object (depends on the class).
208 */
209int getPreferredInputs() {return prefinputs;}
210
211/** @return 0 if this object doesn't provide useful output signal. */
212int getPreferredOutput() {return prefoutput;}
213
214/** @return 0 if the object doesn't need any assignment to the body element.
215    @return 1 = it likes to be attached to the Part ( @see Neuro::attachToPart() )
216    @return 2 = the object prefers to have the Joint ( @see Neuro::attachToJoint() )
217 */
218int getPreferredLocation() {return preflocation;}
219/** vector drawing to be used in neuro net diagram.
220    interpretation:
221       {   
222           LEN = datalength (excluding this number)
223           NL = number_of_lines
224line#1 ->  NS = number_of_segments, x1,y1, x2,y2, ... xNS-1,yNS-1,
225         ...
226line#NL -> NS = number_of_segments, x1,y1, x2,y2, ... xNS-1,yNS-1,
227       }
228 */
229int* getSymbolGlyph()
230 {return vectordata;}
231void setSymbolGlyph(int *data,bool owned=1)
232 {if (vectordata&&ownedvectordata) delete []vectordata;
233 vectordata=data; ownedvectordata=owned;}
234/** additional information about how the neuron should be drawn
235    used by structure view (and maybe some other components).
236    return value is defined by the enum Hint
237    @see enum Hint
238 */
239int getVisualHints()
240 {return visualhints;}
241
242enum Hint
243        /** don't draw neurons of this class */
244 { Invisible=1,
245        /** don't draw classname label below the neuron */
246   DontShowClass=2,
247        /** draw the neuron at the first part when attached to joint (default is in the middle) */
248   AtFirstPart=4,
249        /** draw the neuron at the second part when attached to joint (default is in the middle) */
250   AtSecondPart=8,
251        /** use effector colour for this neuro unit */
252   EffectorClass=16,
253        /** use receptor colour for this neuro unit */
254   ReceptorClass=32,
255   V1BendMuscle=64,
256   V1RotMuscle=128,
257 };
258
259/** textual summary, automatically generated from other properties (like the neuro class tooltip) */
260SString getSummary();
261};
262
263class Neuro;
264
265#ifdef MODEL_V1_COMPATIBLE
266class NeuroItem;
267
268/** for compatibility with old Neuro/NeuroItem  */
269class OldItems
270{
271Neuro &neuro;
272SList syntitems; ///< to be deleted
273SList items;
274int listok;
275  public:
276OldItems(Neuro &n):neuro(n),listok(0) {}
277~OldItems() {freelist();}
278void buildlist();
279void freelist();
280
281int getItemCount();
282NeuroItem *getNeuroItem(int i);
283NeuroItem *addNewNeuroItem();
284int findNeuroItem(NeuroItem *n);
285};
286#endif
287
288/** Single processing unit in framsticks NN.  */
289class Neuro: public PartBase
290{
291friend class Model;
292static const SString& getDefaultStyle();
293
294struct NInput { Neuro *n; double weight; SString *info;
295        NInput(Neuro *_n,double w,SString *i=0):n(_n),weight(w),info(i) {} };
296
297SListTempl<NInput> inputs;
298
299NeuroClass *myclass;
300bool knownclass;
301SString myclassname, myclassparams;
302/** set myclass and make knownclass=true */
303void checkClass();
304
305SString** inputInfo(int i);
306
307public:
308enum NeuroFlags { HoldState=2 };
309ParamInterface &properties();
310ParamInterface &extraProperties();
311
312void setInputInfo(int i,const SString& name,const SString &value);
313void setInputInfo(int i,const SString& name,int value);
314void setInputInfo(int i,const SString& name,double value);
315SString getInputInfo(int i);
316SString getInputInfo(int i,const SString& name);
317
318NeuroClass* getClass();
319void setClass(NeuroClass*);
320
321SString getClassParams() {return myclassparams;}
322void setClassParams(const SString& cp) {myclassparams=cp;}
323
324SString getClassName();
325void setClassName(const SString& clazz);
326
327/** return neuro unit details encoded as <CLASS> ":" <PROPERTIES>
328   
329    new Neuro can be created as root object (without parent) or can be
330    the child of existing Neuro. Children of the Neuro are its inputs.
331    Standard framsticks neuron calculates the sum of all input units - other processing
332    units don't have to treat them equally and can even ignore some of them.
333    There are hints about expected inputs in the class database, @see getClass
334
335    Application should not assume anything about classes and its properties
336    except for two standard classes: (information about all current classes
337    can be retrieved with getClass/getClassProperties methods)
338    - getClassName()="N" is the standard framsticks neuron, accepts any number of inputs,
339      compatible with old Neuro object
340    - getClassName()="-" is the neuron link, compatible with old Neuro-Neuro link
341      (NeuroItem with empty details)
342    Empty details defaults to "-" if the parent unit is specified,
343    and "N" if the unit has no parent.
344 */
345SString getDetails();
346
347/** details = classname + ":" + classparams
348    @see getDetails()
349 */
350void setDetails(const SString&);
351
352#define STATRICKCLASS Neuro
353PARAMGETDEF(details) {arg1->setString(getDetails());}
354PARAMSETDEF(details) {setDetails(arg1->getString());return PSET_CHANGED;}
355PARAMGETDEF(inputCount);
356PARAMPROCDEF(p_getInputNeuroDef);
357PARAMPROCDEF(p_getInputNeuroIndex);
358PARAMPROCDEF(p_getInputWeight);
359PARAMGETDEF(classObject);
360#undef STATRICKCLASS
361
362///@param handle_defaults_when_saving see SyntParam
363SyntParam classProperties(bool handle_defaults_when_saving=true);
364// base properties:
365long refno; ///< unique reference number (former 'neuro' refno)
366
367long part_refno; ///< can be used by some items as the part ref#
368long joint_refno; ///< can be used by some items as the joint ref#
369
370Pt3D pos,rot;   ///< default = zero
371
372ModelUserTags userdata;
373
374Neuro();
375Neuro(double _state,double _inertia,double _force,double _sigmo);
376Neuro(const Neuro& src):PartBase(getDefaultStyle()) {operator=(src);}
377
378~Neuro();
379
380void operator=(const Neuro& src);
381
382/** Attach this Neuro to the specified Part or detach it from the body if p==NULL.
383    Neuro can be attached to either Part or Joint, but not both.
384    @see getPart()
385 */
386void attachToPart(Part* p) {part=p; joint=0;}
387
388/** Attach this Neuro to the specified Joint or detach it from the body if p==NULL.
389    Neuro can be attached to either Part or Joint, but not both.
390    @see getJoint()
391 */
392void attachToJoint(Joint* j) {joint=j; part=0;}
393
394void attachToPart(int i);
395void attachToJoint(int i);
396
397/** @return Part the Neuro is attached to, or NULL if it has no defined location on the body.
398    @see attachToPart()
399 */
400Part *getPart() {return part;}
401
402/** @return Joint the Neuro is attached to, or NULL if it has no defined location on the body.
403    @see attachToJoint()
404 */
405Joint *getJoint() {return joint;}
406
407int isOldEffector();
408int isOldReceptor();
409int isOldNeuron();
410int isNNConnection();
411
412/** @return the number of inputs connected to this Neuro.
413    Functions like getInput(), getInputWeight() will accept connection number [0..InputCount-1]
414 */
415int getInputCount() const {return inputs.size();}
416
417/// @return the number of output connections (including possible self-connections)
418int getOutputsCount() const;
419
420/** @return the Neuro connected as i-th input */
421Neuro* getInput(int i) const {return (i>=inputs.size())?0:inputs(i).n;}
422/** @return the Neuro connected as i-th input.
423    @param weight
424 */
425Neuro* getInput(int i,float &weight) const;
426/** @return connectin weight for i-th input */
427float getInputWeight(int i) const;
428/** change connection weight for i-th input */
429void setInputWeight(int i,float weight);
430/** connect i-th input with another neuron */
431void setInput(int i,Neuro*n);
432/** connect i-th input with another neuron */
433void setInput(int i,Neuro*n,float weight);
434/** add new input. @return its reference number */
435int addInput(Neuro* child,float weight=1.0,const SString* info=0);
436/** @return reference number [0..InputCount-1] of the input
437   or -1 if 'child' is not connected with this Neuro.*/
438int findInput(Neuro* child) const;
439void removeInput(int refno);
440/**    @return reference number of the child connection, like findInput() */
441int removeInput(Neuro* child);
442
443int findInputs(SList& result,const char* classname=0,const Part* part=0,const Joint* joint=0) const;
444int findOutputs(SList& result,const char* classname=0,const Part* part=0,const Joint* joint=0) const;
445
446/* class database retrieval */
447static int getClassCount();
448/** @return Neuro class name.
449    @param classindex 0 .. getClassCount()
450 */
451static SString getClassName(int classindex);
452static NeuroClass* getClass(int classindex);
453static NeuroClass* getClass(const SString& classname);
454static int getClassIndex(const NeuroClass*nc);
455
456#ifdef MODEL_V1_COMPATIBLE
457friend class OldItems;
458long neuro_refno; ///< parent ref# (called neuro_refno for compatibility with old Neuro class), @see moredata
459long conn_refno; ///< the other neuron ref# in N-N connections, can be used by some other items
460double weight; ///< weight of the N-N connection and (all?) receptors
461double inertia,force,sigmo; //!!!
462
463/** @deprecated provided only for compatibility with old Neuro/NeuroItem classes.
464    use getInputCount() instead. @sa getInputCount() */
465int getItemCount() {return oldItems().getItemCount();}
466
467/** @deprecated provided only for compatibility with old Neuro/NeuroItem classes.
468    use getInput() instead. @sa getInput() */
469NeuroItem* getNeuroItem(int i) {return oldItems().getNeuroItem(i);}
470#endif
471
472  protected:
473#ifdef MODEL_V1_COMPATIBLE
474/** old Neuro compatibility */
475OldItems* olditems;
476OldItems& oldItems() {if (!olditems) olditems=new OldItems(*this); return *olditems;}
477void invalidateOldItems() {if (olditems) olditems->freelist();}
478#endif
479
480  public:
481
482// not really private, but you should not access those directly
483double state;
484
485/** may reference parent neuron if parentcount is exacty 1. parent is invalid otherwise. @sa parentcount */
486Neuro *parent;
487int parentcount; ///< @sa parent
488
489Part *part;     ///< link to the Part
490Joint *joint;   ///< link to the Joint - required by some objects (eg.muscles)
491Orient o;       ///< rotation matrix calculated from "rot"
492static ParamEntry emptyParamTab[];
493static Param& getStaticParam();
494};
495
496#ifdef MODEL_V1_COMPATIBLE
497class NeuroItem;
498
499/// for compatibility with old NeuroItem class.
500class NeuroItem: public Neuro
501{
502public:
503NeuroItem() {}
504};
505#endif
506
507class NeuroExt: public Neuro
508{
509  public:
510#define STATRICKCLASS NeuroExt
511PARAMGETDEF(neuroclass);
512PARAMSETDEF(neuroclass);
513#undef STATRICKCLASS
514static ParamEntry *getParamTab();
515};
516
517class NeuroConn
518{
519  public:
520int n1_refno,n2_refno;
521double weight;
522SString info;
523NeuroConn();
524};
525
526extern ParamEntry f0_part_paramtab[],f0_joint_paramtab[],f0_nodeltajoint_paramtab[],f0_neuro_paramtab[],f0_neuroconn_paramtab[],f0_neuroitem_paramtab[];
527
528#endif
Note: See TracBrowser for help on using the repository browser.