source: cpp/frams/model/modelparts.h @ 1139

Last change on this file since 1139 was 1122, checked in by Maciej Komosinski, 4 years ago

Stick thickness when converting "ball-and-stick" models to "solid-shape" models consistent with the traditional visualization of sticks in GUI

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