Index: /cpp/frams/_demos/genomanipulation.cpp
===================================================================
--- /cpp/frams/_demos/genomanipulation.cpp	(revision 976)
+++ /cpp/frams/_demos/genomanipulation.cpp	(revision 977)
@@ -195,4 +195,31 @@
 			printf(" (getPreferredInputs()) ");
 			printf(cl->getPreferredOutput() ? "and provides meaningful output signal (getPreferredOutput()==1).\n" : "and doesn't provide useful output signal (getPreferredOutput()==0).\n");
+			printf("Instances of '%s' can be used in models having ", cl->getName().c_str());
+			if (cl->getSupportedShapeTypes() == NeuroClass::SUPPORTED_SHAPE_ALL)
+				printf("any shape types.\n");
+			else
+				{
+				printf("shape types:");
+				for(int i=Model::SHAPE_FIRST; i<= Model::SHAPE_LAST; i++)
+					if (cl->isShapeTypeSupported((Model::ShapeType)i))
+						printf(" '%s'",Model::getShapeTypeName((Model::ShapeType)i));
+				printf(".\n");
+				}
+			if (cl->preflocation == NeuroClass::PREFER_JOINT)
+				{
+				printf("Instances of '%s' can be attached to Joints having ", cl->getName().c_str());
+				if (cl->getSupportedJointShapes() == NeuroClass::SUPPORTED_JOINT_ALL)
+					printf("any shapes");
+				else
+					{
+					printf("shapes:");
+					for(int i=Joint::SHAPE_FIRST; i<= Joint::SHAPE_LAST; i++)
+						if (cl->isJointShapeSupported((Joint::Shape)i))
+							printf(" '%s'",Joint::getShapeName((Joint::Shape)i));
+					}
+				printf(".\n");
+				}
+			else if (cl->preflocation == NeuroClass::PREFER_PART)
+				printf("Instances of '%s' can be attached to Parts.\n", cl->getName().c_str());
 
 			SyntParam p = n->classProperties();
Index: /cpp/frams/genetics/genman.cpp
===================================================================
--- /cpp/frams/genetics/genman.cpp	(revision 976)
+++ /cpp/frams/genetics/genman.cpp	(revision 977)
@@ -20,4 +20,7 @@
 #ifdef USE_GENMAN_f0
 #include "f0/f0_oper.h"
+#endif
+#ifdef USE_GENMAN_f0s
+#include "f0s/f0s_oper.h"
 #endif
 #ifdef USE_GENMAN_f0FUZZY
@@ -132,4 +135,7 @@
 #ifdef USE_GENMAN_f0
 	oper_fx_list.push_back(new Geno_f0);
+#endif
+#ifdef USE_GENMAN_f0s
+	oper_fx_list.push_back(new Geno_f0s);
 #endif
 #ifdef USE_GENMAN_f0FUZZY
Index: /cpp/frams/model/modelparts.cpp
===================================================================
--- /cpp/frams/model/modelparts.cpp	(revision 976)
+++ /cpp/frams/model/modelparts.cpp	(revision 977)
@@ -107,4 +107,5 @@
 	preflocation(_preflocation),
 	supported_shape_types(sup_shapes),
+	supported_joint_shapes(sup_joints),
 	vectordata(_vectordata),
 	visualhints(vhints), impl_count(0),/*impl(0),*/active(1), genactive(0)
@@ -624,4 +625,17 @@
 }
 
+const char* Part::getShapeName(Shape sh)
+{
+	switch (sh)
+	{
+	case SHAPE_BALL_AND_STICK: return "ball-and-stick";
+	case SHAPE_ELLIPSOID: return "ellipsoid";
+	case SHAPE_CUBOID: return "cuboid";
+	case SHAPE_CYLINDER: return "cylinder";
+
+	default:
+		return "unknown shape";
+	}
+}
 
 ///////////////////////////
@@ -709,4 +723,19 @@
 }
 
+const char* Joint::getShapeName(Shape sh)
+{
+	switch (sh)
+	{
+	case SHAPE_BALL_AND_STICK: return "ball-and-stick";
+	case SHAPE_FIXED: return "fixed";
+	case SHAPE_HINGE_X: return "hinge x";
+	case SHAPE_HINGE_XY: return "hinge xy";
+
+	default:
+		return "unknown shape";
+	}
+}
+
+
 /////////////////////////////////////////////////////////////////
 
Index: /cpp/frams/model/modelparts.h
===================================================================
--- /cpp/frams/model/modelparts.h	(revision 976)
+++ /cpp/frams/model/modelparts.h	(revision 977)
@@ -34,7 +34,8 @@
 {
 public:
-	enum ShapeType { SHAPE_BALL_AND_STICK = 0, SHAPE_SOLIDS = 1, SHAPE_UNKNOWN, SHAPE_ILLEGAL }; ///< 0 and 1 have special significance - these values allow for bit operations.
-};
-
+	enum ShapeType { SHAPE_BALL_AND_STICK = 0, SHAPE_SOLIDS = 1, SHAPE_UNKNOWN, SHAPE_ILLEGAL, ///< 0 and 1 have special significance - these values allow for bit operations.
+			 SHAPE_FIRST = SHAPE_BALL_AND_STICK, SHAPE_LAST = SHAPE_SOLIDS // for iteration
+	}; 
+};
 
 /** Common base for model elements. */
@@ -95,5 +96,9 @@
 	///
 	paInt shape;///default=old Framsticks compatible, do not mix with shapes>0
-	enum Shape { SHAPE_BALL_AND_STICK = 0, SHAPE_ELLIPSOID = 1, SHAPE_CUBOID = 2, SHAPE_CYLINDER = 3 };
+	enum Shape { SHAPE_BALL_AND_STICK = 0, SHAPE_ELLIPSOID = 1, SHAPE_CUBOID = 2, SHAPE_CYLINDER = 3,
+		     SHAPE_FIRST = SHAPE_BALL_AND_STICK, SHAPE_LAST = SHAPE_CYLINDER // for iteration
+	};
+	static const char* getShapeName(Shape sh);
+
 	double mass, size, density, friction, ingest, assim, hollow;
 	Pt3D scale;
@@ -149,7 +154,9 @@
 		SHAPE_FIXED = 1, ///< merge parts into one physical entity
 		SHAPE_HINGE_X = 2, ///< hinge connection, revolving around X axis defined by hinge_pos and hinge_rot
-		SHAPE_HINGE_XY = 3 ///< double hinge connection, revolving around X and Y axes defined by hinge_pos and hinge_rot
+		SHAPE_HINGE_XY = 3, ///< double hinge connection, revolving around X and Y axes defined by hinge_pos and hinge_rot
+		SHAPE_FIRST = SHAPE_BALL_AND_STICK, SHAPE_LAST = SHAPE_HINGE_XY // for iteration
 	};
 	paInt shape;///< values of type Shape (paInt for integration with Param)
+	static const char* getShapeName(Shape sh);
 	class Pt3D hinge_pos; ///< hinge position (relative to part1) for HINGE_X and HINGE_XY
 	class Pt3D hinge_rot; ///< hinge orientation (relative to part1) for HINGE_X and HINGE_XY
@@ -223,4 +230,6 @@
 	paInt preflocation;
 
+	enum PrefLocation { PREFER_UNATTACHED=0, PREFER_PART=1, PREFER_JOINT=2 };
+	
 	static constexpr int SUPPORTED_SHAPE_BALL_AND_STICK = 1;
 	static constexpr int SUPPORTED_SHAPE_SOLIDS = 2;
@@ -233,5 +242,5 @@
 	static constexpr int SUPPORTED_JOINT_HINGE_XY = 8;
 	static constexpr int SUPPORTED_JOINT_ALL = SUPPORTED_JOINT_BALL_AND_STICK + SUPPORTED_JOINT_FIXED + SUPPORTED_JOINT_HINGE_X + SUPPORTED_JOINT_HINGE_XY;
-	paInt supported_joint_types; //< bitfield of 'Joint::shape' values: NeuroClass::SUPPORTED_JOINT_xxx = 1 << JOINT::SHAPE_xxx
+	paInt supported_joint_shapes; //< bitfield of 'Joint::shape' values: NeuroClass::SUPPORTED_JOINT_xxx = 1 << JOINT::SHAPE_xxx
 
 	int *vectordata;
@@ -286,6 +295,6 @@
 	int getSupportedShapeTypes() { return (int)supported_shape_types; }
 	bool isShapeTypeSupported(ModelEnum::ShapeType t) { return (1 << (int)t) & supported_shape_types; }
-	int getSupportedJointTypes() { return (int)supported_joint_types; }
-	bool isJointTypeSupported(Joint::Shape t) { return (1 << (int)t) & supported_joint_types; }
+	int getSupportedJointShapes() { return (int)supported_joint_shapes; }
+	bool isJointShapeSupported(Joint::Shape t) { return (1 << (int)t) & supported_joint_shapes; }
 	int *getSymbolGlyph()
 	{
