Index: cpp/gdk/conv_f1.cpp
===================================================================
--- cpp/gdk/conv_f1.cpp	(revision 94)
+++ cpp/gdk/conv_f1.cpp	(revision 95)
@@ -1,4 +1,4 @@
 // This file is a part of the Framsticks GDK library.
-// Copyright (C) 2002-2011  Szymon Ulatowski.  See LICENSE.txt for details.
+// Copyright (C) 2002-2013  Szymon Ulatowski.  See LICENSE.txt for details.
 // Refer to http://www.framsticks.com/ for further information.
 
@@ -25,6 +25,9 @@
 SList neuro_f1_to_f0; // neuro_f1_to_f0(f1_refno) = actual neuro pointer
 Neuro *last_f1_neuro;
-	struct Connection { int n1,n2; double w;
-		Connection(int _n1,int _n2, double _w):n1(_n1),n2(_n2),w(_w) {} };
+SyntParam *neuro_cls_param;
+
+struct Connection { int n1,n2; double w;
+Connection(int _n1,int _n2, double _w):n1(_n1),n2(_n2),w(_w) {} };
+
 SListTempl<Connection> connections;
 int usemapping;
@@ -39,6 +42,7 @@
 void growConnection(const char* begin,const char* colon,const char* end,F1Props& props);
 int countBranches(const char*g,SList &out);
-void addClassParam(const SString& newparam);
+SyntParam* lastNeuroClassParam();
 void addClassParam(const char* name,double value);
+void addClassParam(const char* name,const char* value);
 
 const MultiRange* makeRange(const char*g) {return makeRange(g,g);}
@@ -226,19 +230,37 @@
 }
 
-void Builder::addClassParam(const SString& newparam)
-{
-SString allparams=last_f1_neuro->getClassParams();
-if (allparams.len()) allparams+=',';
-allparams+=newparam;
-last_f1_neuro->setClassParams(allparams);
-}
+SyntParam* Builder::lastNeuroClassParam()
+{
+if (!neuro_cls_param)
+	{
+	NeuroClass *cls=last_f1_neuro->getClass();
+	if (cls)
+		{
+		neuro_cls_param=new SyntParam(last_f1_neuro->classProperties());
+// this is equivalent to:
+//		SyntParam tmp=last_f1_neuro->classProperties();
+//		neuro_cls_param=new SyntParam(tmp);
+// interestingly, some compilers eliminate the call to new SyntParam,
+// realizing that a copy constructor is redundant when the original object is
+// temporary. there are no side effect of such optimization, as long as the
+// copy-constructed object is exact equivalent of the original.
+		}
+	}
+return neuro_cls_param;
+}
+
 void Builder::addClassParam(const char* name,double value)
 {
-SString t;
-sprintf(t.directWrite(30),"%s=%g",name,value);
-t.endWrite();
-addClassParam(t);
-}
-
+lastNeuroClassParam();
+if (neuro_cls_param)
+	neuro_cls_param->setDoubleById(name,value);
+}
+
+void Builder::addClassParam(const char* name,const char* value)
+{
+lastNeuroClassParam();
+if (neuro_cls_param)
+	neuro_cls_param->setById(name,ExtValue(value));
+}
 
 int Builder::countBranches(const char*g,SList &out)
@@ -286,4 +308,5 @@
 const char*neuroend=skipNeuro(t);
 last_f1_neuro=model.addNewNeuro();
+neuro_cls_param=NULL;
 last_f1_neuro->attachToPart(getLastPart());
 const MultiRange *mr=makeRange(t-1,neuroend+1);
@@ -354,4 +377,16 @@
 					else if (cls->getPreferredLocation()==1)
 						last_f1_neuro->attachToPart(getLastPart());
+
+					lastNeuroClassParam();
+					//special handling: muscle properties (can be overwritten by subsequent property assignments)
+					if (!strcmp(cls->getName(),"|"))
+						{
+						neuro_cls_param->setDoubleById("p",lastjoint_muscle_power);
+						neuro_cls_param->setDoubleById("r",props.bendrange);
+						}
+					else if (!strcmp(cls->getName(),"@"))
+						{
+						neuro_cls_param->setDoubleById("p",lastjoint_muscle_power);
+						}
 					}
 				}
@@ -364,4 +399,5 @@
 	t++;
 	}
+SAFEDELETE(neuro_cls_param);
 return t;
 }
@@ -419,17 +455,12 @@
 	if (usemapping) out->setMapping(*makeRange(begin,end-1));
 	}
-else if (*begin=='!') addClassParam("fo",max(0.0,min(1.0,atof(colon+1))));
-else if (*begin=='=') addClassParam("in",max(0.0,min(1.0,atof(colon+1))));
+else if (*begin=='!') addClassParam("fo",atof(colon+1));
+else if (*begin=='=') addClassParam("in",atof(colon+1));
 else if (*begin=='/') addClassParam("si",atof(colon+1));
-/*else if (*begin=='!') last_f1_neuro->force=max(0.0,min(1.0,atof(colon+1)));
-else if (*begin=='=') last_f1_neuro->inertia=max(0.0,min(1.0,atof(colon+1)));
-else if (*begin=='/') last_f1_neuro->sigmo=atof(colon+1);
-*/
 else if (islower(begin[0]))
 	{
-	SString newparam(begin,end-begin);
-	trim(newparam);
-	newparam.directWrite()[colon-begin]='='; // ':' -> '='
-	addClassParam(newparam);
-	}
-}
+	SString name(begin,colon-begin);
+	SString value(colon+1,end-(colon+1));
+	addClassParam(name,value);
+	}
+}
