*/}}
Browse Source

Nodes and comment and rgb etc changes

Yiming Wu 2 years ago
parent
commit
9b6c06a684
7 changed files with 277 additions and 67 deletions
  1. 4 2
      la_data.c
  2. 27 1
      la_interface.h
  3. 2 5
      la_util.h
  4. 231 53
      resources/la_nodes_basic.c
  5. 1 0
      resources/la_properties.c
  6. 5 3
      resources/la_tns_drivers.c
  7. 7 3
      resources/la_widgets.c

+ 4 - 2
la_data.c

@@ -2744,7 +2744,7 @@ int la_WriteProp(laUDF *udf, laPropPack *pp, int FromThis, int UseInstanceList){
                 if (((laSubProp*)p)->GetType){ pc=((laSubProp*)p)->GetType(inst); need_type=1; }
 
                 if (pc->Hyper == 2){
-                    if(UseInstanceList&&inst!=udf->CurrentH2Instance->Instance){
+                    if((!p->UDFIsSingle) && UseInstanceList&&inst!=udf->CurrentH2Instance->Instance){
                         inst = laGetNextInstance(p, inst, &pi); pp->EndInstance = inst; continue;}
                     if(need_type){  la_WriteString(udf, pc->Identifier); }
                     hi = inst;
@@ -3166,6 +3166,8 @@ int la_ExtractProp(laUDF *udf, laManagedUDF* mUDF, laPropPack *pp, void *ParentI
 
                     printf("add pc %s\n",pc->Identifier);
 
+                    if(pc==LA_PC_SOCKET_OUT || pc==LA_PC_SOCKET_IN){ laMappingRequestRebuild(); laDriverRequestRebuild(); }
+
                     int replaced=0;
                     if (udf){
                         RealSize = RealSize ? RealSize : p->SubProp->NodeSize;
@@ -3471,7 +3473,7 @@ int la_ScanForModifiedRecursive(laPropPack* pp, int ReturnIfAnyMod, int ReturnIf
         }else{
             laMemNodeHyper* m = memGetHead(inst,0);
             if(!m->FromFile || m->FromFile==MAIN.DummyManageUDF){ result|=1; if(rempty)*rempty|=1; if((ReturnIfAnyMod||ReturnIfAnyEmpty)&&result)return result; }
-            if(RegisterToUDF&&m->FromFile&&m->FromFile->udf){ la_IncludeHyper2Instance(m->FromFile->udf, pc, inst); }
+            if((!p->UDFIsSingle)&&RegisterToUDF&&m->FromFile&&m->FromFile->udf){ la_IncludeHyper2Instance(m->FromFile->udf, pc, inst); }
             if(m->Modified){
                 if(m->FromFile && m->FromFile->udf){ m->FromFile->udf->Modified=1; }
                 result|=1; if(ReturnIfAnyMod&&result)return result;

+ 27 - 1
la_interface.h

@@ -208,8 +208,8 @@ STRUCTURE(laLogEntry){
 NEED_STRUCTURE(laManagedUDF);
 
 STRUCTURE(laNodeOutSocket){
-    void* Parent;
     void* Data;
+    void* Parent;
     laSafeString* Label;
     int DataType, ArrLen;
     int RuntimeX, RuntimeY, RuntimePX, RuntimePY;
@@ -939,11 +939,13 @@ STRUCTURE(laWidget){
 #define LA_UI_FLAGS_NODE_CONTAINER (1<<22)
 #define LA_UI_COLLECTION_NO_HIGHLIGHT LA_TEXT_ALIGN_LEFT
 #define LA_TEXT_ONE_LINE       (1<<23)
+#define LA_UI_FLAGS_NO_SCROLL_INACTIVE (1<<24)
 
 #define LA_UI_FLAGS_INT_ICON  (LA_UI_FLAGS_NO_DECAL|LA_UI_FLAGS_NO_EVENT|LA_UI_FLAGS_ICON)
 #define LA_UI_FLAGS_PLAIN     (LA_UI_FLAGS_NO_DECAL|LA_UI_FLAGS_NO_EVENT)
 #define LA_TEXT_ALIGN (LA_TEXT_ALIGN_LEFT|LA_TEXT_ALIGN_CENTER|LA_TEXT_ALIGN_RIGHT|LA_TEXT_ALIGN_AUTO)
 
+
 #define LA_UI_SOCKET_LABEL_N LA_TEXT_ALIGN_LEFT
 #define LA_UI_SOCKET_LABEL_S LA_TEXT_ALIGN_RIGHT
 #define LA_UI_SOCKET_LABEL_W LA_TEXT_ALIGN_CENTER
@@ -1305,6 +1307,8 @@ extern laNodeCategory* LA_NODE_CATEGORY_INPUT;
 extern laNodeCategory* LA_NODE_CATEGORY_MATH;
 extern laNodeCategory* LA_NODE_CATEGORY_ROUTE;
 extern laNodeCategory* LA_NODE_CATEGORY_DRIVER;
+extern laNodeCategory* LA_NODE_CATEGORY_AUX;
+extern laNodeCategory* LA_NODE_CATEGORY_COLOR;
 
 #define LA_VALUES_NODE_FLOAT 0
 #define LA_VALUES_NODE_INT 1
@@ -1326,6 +1330,7 @@ extern laNodeCategory* LA_NODE_CATEGORY_DRIVER;
 #define LA_MATH_NODE_OP_ACOS 10
 #define LA_MATH_NODE_OP_ATAN 11
 #define LA_MATH_NODE_OP_ATAN2 12
+#define LA_MATH_NODE_OP_MOD 13
 
 #define LA_VECTOR_MATH_OP_ADD 0
 #define LA_VECTOR_MATH_OP_SUB 1
@@ -1452,6 +1457,27 @@ STRUCTURE(laVectorMathNode){
     real rOut[4];
     int Operation;
 };
+STRUCTURE(laCommentNode){
+    laBaseNode Base;
+    laSafeString* Content;
+};
+STRUCTURE(laRGB2OKHSLNode){
+    laBaseNode Base;
+    laNodeInSocket *In;
+    laNodeOutSocket* OutH;
+    laNodeOutSocket* OutS;
+    laNodeOutSocket* OutL;
+    real RGB[3];
+    real rOut[3];
+};
+STRUCTURE(laOKHSL2RGBNode){
+    laBaseNode Base;
+    laNodeInSocket *InH;
+    laNodeInSocket *InS;
+    laNodeInSocket *InL;
+    laNodeOutSocket* Out;
+    real rOut[3];
+};
 
 STRUCTURE(laNodeCategory){
     laListItem Item;

+ 2 - 5
la_util.h

@@ -340,10 +340,8 @@ STRUCTURE(laTranslationMatch) {
 	char * Target;
 	char * Replacement;
 };
-
-
 NEED_STRUCTURE(laBaseNode);
-typedef void (*laBaseNodeInitF)(laBaseNode*);
+typedef void (*laBaseNodeInitF)(laBaseNode*, int NoCreate);
 typedef void (*laBaseNodeDestroyF)(laBaseNode*);
 typedef int (*laBaseNodeVisitF)(laBaseNode*, laListHandle*);
 typedef int (*laBaseNodeEvalF)(laBaseNode*);
@@ -365,8 +363,7 @@ STRUCTURE(laBaseNode){
     laSafeString* Name;
     laBaseNodeType* Type;
     laNodeRack* InRack;
-    int Gap;
-    int Eval;
+    int Gap; int Eval; int InitDone;
 };
 
 

+ 231 - 53
resources/la_nodes_basic.c

@@ -13,9 +13,13 @@ laBaseNodeType LA_IDN_COMBINE;
 laBaseNodeType LA_IDN_VALUES;
 laBaseNodeType LA_IDN_MATRIX;
 laBaseNodeType LA_IDN_MATH;
+laBaseNodeType LA_IDN_SMALL_MATH;
 laBaseNodeType LA_IDN_MAPPER;
 laBaseNodeType LA_IDN_RANDOM;
 laBaseNodeType LA_IDN_VECTOR_MATH;
+laBaseNodeType LA_IDN_COMMENT;
+laBaseNodeType LA_IDN_RGB2OKHSL;
+laBaseNodeType LA_IDN_OKHSL2RGB;
 
 laPropContainer* LA_PC_IDN_GENERIC;
 laPropContainer* LA_PC_IDN_KEYBOARD;
@@ -28,19 +32,26 @@ laPropContainer* LA_PC_IDN_COMBINE;
 laPropContainer* LA_PC_IDN_VALUES;
 laPropContainer* LA_PC_IDN_MATRIX;
 laPropContainer* LA_PC_IDN_MATH;
+laPropContainer* LA_PC_IDN_SMALL_MATH;
 laPropContainer* LA_PC_IDN_MAPPER;
 laPropContainer* LA_PC_IDN_RANDOM;
 laPropContainer* LA_PC_IDN_VECTOR_MATH;
+laPropContainer* LA_PC_IDN_COMMENT;
+laPropContainer* LA_PC_IDN_RGB2OKHSL;
+laPropContainer* LA_PC_IDN_OKHSL2RGB;
 
 laNodeCategory* LA_NODE_CATEGORY_INPUT;
 laNodeCategory* LA_NODE_CATEGORY_MATH;
 laNodeCategory* LA_NODE_CATEGORY_ROUTE;
+laNodeCategory* LA_NODE_CATEGORY_AUX;
 laNodeCategory* LA_NODE_CATEGORY_DRIVER;
+laNodeCategory* LA_NODE_CATEGORY_COLOR;
 
 #define LA_IDN_CONTROLLER_RESET_SOCKET(ns)\
     {ns->IntVal[0]=0; ns->Out->DataType=LA_PROP_INT; ns->Offset=0; ns->Out->Data=&ns->IntVal;}
 
-void IDN_ControllerInit(laInputControllerNode* n){
+void IDN_ControllerInit(laInputControllerNode* n, int NoCreate){
+    if(NoCreate){return;}
     for(int i=0;i<8;i++){ n->Sockets[i].Out=laCreateOutSocket(n, "out", 0); n->Sockets[i].Parent=n; }
     strSafeSet(&n->Base.Name,"Controller Output");
 }
@@ -114,7 +125,8 @@ void laui_ControllerNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laC
     }
 }
 
-void IDN_InputVisualizeInit(laInputVisualizerNode* n){
+void IDN_InputVisualizeInit(laInputVisualizerNode* n, int NoCreate){
+    if(NoCreate){return;}
     n->In=laCreateInSocket("IN", 0);
     strSafeSet(&n->Base.Name,"Input Visualizer");
 }
@@ -160,7 +172,8 @@ void laui_InputVisualizeNode(laUiList *uil, laPropPack *This, laPropPack *Extra,
     }laEndCondition(uil,b2);
 }
 
-void IDN_SplitInit(laSplitNode* n){
+void IDN_SplitInit(laSplitNode* n, int NoCreate){
+    if(NoCreate){return;}
     n->In=laCreateInSocket("in", 0); strSafeSet(&n->Base.Name,"Split");
     for(int i=0;i<8;i++){ char str[4]; sprintf(str,"%d",i); n->Out[i].Out=laCreateOutSocket(n,str,0); }
 }
@@ -210,7 +223,8 @@ void laui_SplitNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn
     laEndRow(uil,b);
 }
 
-void IDN_SwitchInit(laSwitchNode* n){
+void IDN_SwitchInit(laSwitchNode* n, int NoCreate){
+    if(NoCreate){return;}
     n->SwitchIn=laCreateInSocket("sw in",0); n->Out=laCreateOutSocket(n,"out",0); strSafeSet(&n->Base.Name,"Switch");
     for(int i=0;i<8;i++){ char str[4]; sprintf(str,"%d",i); n->In[i].In=laCreateInSocket(n,str); }
 }
@@ -269,9 +283,11 @@ void laui_SwitchNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColum
     laEndRow(uil,b);
 }
 
-void IDN_CombineInit(laCombineNode* n){
-    n->Out=laCreateOutSocket(n,"F",0);n->OutInt=laCreateOutSocket(n,"I",0);n->OutEnum=laCreateOutSocket(n,"E",0); strSafeSet(&n->Base.Name,"Combine");
-    for(int i=0;i<8;i++){ char str[4]; sprintf(str,"%d",i); n->In[i].In=laCreateInSocket(n,str); }
+void IDN_CombineInit(laCombineNode* n, int NoCreate){
+    if(!NoCreate){
+        n->Out=laCreateOutSocket(n,"F",0);n->OutInt=laCreateOutSocket(n,"I",0);n->OutEnum=laCreateOutSocket(n,"E",0); strSafeSet(&n->Base.Name,"Combine");
+        for(int i=0;i<8;i++){ char str[4]; sprintf(str,"%d",i); n->In[i].In=laCreateInSocket(n,str); }
+    }
     n->Out->Data=n->Values; n->OutInt->Data=n->ValuesI; n->OutEnum->Data=n->ValuesI;
     n->Out->DataType=LA_PROP_FLOAT|LA_PROP_ARRAY; n->OutInt->DataType=LA_PROP_INT|LA_PROP_ARRAY; n->OutEnum->DataType=LA_PROP_ENUM|LA_PROP_ARRAY;
 }
@@ -322,7 +338,8 @@ void laui_CombineNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColu
     laEndRow(uil,b);
 }
 
-void IDN_ValuesInit(laValuesNode* n){
+void IDN_ValuesInit(laValuesNode* n, int NoCreate){
+    if(NoCreate){return;}
     strSafeSet(&n->Base.Name,"Values");
     for(int i=0;i<8;i++){ char str[4]; sprintf(str,"%d",i); n->Out[i].Out=laCreateOutSocket(n,str,0); }
 }
@@ -367,9 +384,11 @@ void laui_ValuesNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColum
     }
 }
 
-void IDN_MatrixInit(laMatrixNode* n){
-    strSafeSet(&n->Base.Name,"Matrix");
-    n->InL=laCreateInSocket("l",0); n->InR=laCreateInSocket("r",0); n->Out=laCreateOutSocket(n,"MAT",LA_PROP_FLOAT|LA_PROP_ARRAY);
+void IDN_MatrixInit(laMatrixNode* n, int NoCreate){
+    if(!NoCreate){
+        strSafeSet(&n->Base.Name,"Matrix");
+        n->InL=laCreateInSocket("l",0); n->InR=laCreateInSocket("r",0); n->Out=laCreateOutSocket(n,"MAT",LA_PROP_FLOAT|LA_PROP_ARRAY);
+    }
     n->Out->ArrLen=16; n->Out->Data=n->Mat;
 }
 void IDN_MatrixDestroy(laMatrixNode* n){
@@ -413,10 +432,12 @@ void laui_MatrixNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColum
     laEndRow(uil,b);
 }
 
-void IDN_MathInit(laMathNode* n){
-    strSafeSet(&n->Base.Name,"Math");
-    n->InL=laCreateInSocket("l",0); n->InR=laCreateInSocket("r",0);
-    n->Out=laCreateOutSocket(n,"F",LA_PROP_FLOAT); n->OutInt=laCreateOutSocket(n,"I",LA_PROP_INT);
+void IDN_MathInit(laMathNode* n, int NoCreate){
+    if(!NoCreate){
+        strSafeSet(&n->Base.Name,"Math");
+        n->InL=laCreateInSocket("l",0); n->InR=laCreateInSocket("r",0);
+        n->Out=laCreateOutSocket(n,"F",LA_PROP_FLOAT); n->OutInt=laCreateOutSocket(n,"I",LA_PROP_INT);
+    }
     n->Out->Data=&n->Value; n->OutInt->Data=&n->ValueI;
 }
 void IDN_MathDestroy(laMathNode* n){
@@ -451,6 +472,7 @@ int IDN_MathEval(laMathNode* n){
     case LA_MATH_NODE_OP_ACOS: n->Value=acos(vl); break;
     case LA_MATH_NODE_OP_ATAN: n->Value=atan(vl); break;
     case LA_MATH_NODE_OP_ATAN2: n->Value=atan2(vl,vr); break;
+    case LA_MATH_NODE_OP_MOD: n->Value=fmod(vl,vr); break;
     }
     n->ValueI=(int)n->Value;
     return 1;
@@ -472,11 +494,26 @@ void laui_MathNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn
     laShowNodeSocket(uil,c,This,"out",0)->Flags|=LA_UI_SOCKET_LABEL_W;
     laEndRow(uil,b);
 }
+void laui_SmallMathNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){
+    laColumn* c=laFirstColumn(uil); laMathNode*n=This->EndInstance;
+    laColumn* cl,*cr; laSplitColumn(uil,c,0.4); cl=laLeftColumn(c,3); cr=laRightColumn(c,0);
+    laUiItem*b,*b2;
+    LA_BASE_NODE_HEADER(uil,c,This);
+
+    b=laBeginRow(uil,c,0,0);
+    laShowNodeSocket(uil,c,This,"in_l",0);laShowNodeSocket(uil,c,This,"in_r",0);
+    laShowSeparator(uil,c)->Expand=1;laShowItem(uil,c,This,"operation");
+    laShowNodeSocket(uil,c,This,"out",0)->Flags|=LA_UI_SOCKET_LABEL_W;
+    laEndRow(uil,b);
+}
 
-void IDN_MapperInit(laMapperNode* n){
-    strSafeSet(&n->Base.Name,"Mapper");
-    n->In=laCreateInSocket("IN",LA_PROP_FLOAT); n->Out=laCreateOutSocket(n,"OUT",LA_PROP_FLOAT);n->Out->Data=&n->rOut;
-    n->Mapper=laValueMapperInit();
+void IDN_MapperInit(laMapperNode* n, int NoCreate){
+    if(!NoCreate){
+        strSafeSet(&n->Base.Name,"Mapper");
+        n->In=laCreateInSocket("IN",LA_PROP_FLOAT); n->Out=laCreateOutSocket(n,"OUT",LA_PROP_FLOAT);
+        n->Mapper=laValueMapperInit();
+    }
+    n->Out->Data=&n->rOut;
 }
 void IDN_MapperDestroy(laMapperNode* n){
     strSafeDestroy(&n->Base.Name);
@@ -514,8 +551,11 @@ void laui_MapperNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColum
     laEndRow(uil,b);
 }
 
-void IDN_RandomInit(laRandomNode* n){
-    strSafeSet(&n->Base.Name,"Random"); n->Out=laCreateOutSocket(n,"RAND",LA_PROP_FLOAT); n->Out->Data=&n->rOut; n->Min=0; n->Max=1;
+void IDN_RandomInit(laRandomNode* n, int NoCreate){
+    if(!NoCreate){
+        strSafeSet(&n->Base.Name,"Random"); n->Out=laCreateOutSocket(n,"RAND",LA_PROP_FLOAT);
+    }
+    n->Out->Data=&n->rOut; n->Min=0; n->Max=1;
 }
 void IDN_RandomDestroy(laRandomNode* n){
     strSafeDestroy(&n->Base.Name); laDestroyOutSocket(n->Out);
@@ -539,10 +579,12 @@ void laui_RandomNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColum
     laEndRow(uil,b);
 }
 
-void IDN_VectorMathInit(laVectorMathNode* n){
-    strSafeSet(&n->Base.Name,"Math");
-    n->InL=laCreateInSocket("l",0); n->InR=laCreateInSocket("r",0);
-    n->Out=laCreateOutSocket(n,"OUT",LA_PROP_FLOAT);
+void IDN_VectorMathInit(laVectorMathNode* n, int NoCreate){
+    if(!NoCreate){
+        strSafeSet(&n->Base.Name,"Math");
+        n->InL=laCreateInSocket("l",0); n->InR=laCreateInSocket("r",0);
+        n->Out=laCreateOutSocket(n,"OUT",LA_PROP_FLOAT);
+    }
     n->Out->Data=n->rOut;
 }
 void IDN_VectorMathDestroy(laVectorMathNode* n){
@@ -593,6 +635,108 @@ void laui_VectorMathNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laC
     laEndRow(uil,b);
 }
 
+void IDN_CommentInit(laCommentNode* n, int NoCreate){
+    if(NoCreate){return;}
+    strSafeSet(&n->Base.Name,"Math"); strSafeSet(&n->Content,"");
+}
+void IDN_CommentDestroy(laCommentNode* n){
+    strSafeDestroy(&n->Base.Name); strSafeDestroy(&n->Content); 
+}
+int IDN_CommentVisit(laCommentNode* n, laListHandle* l){
+    LA_GUARD_THIS_NODE(n); n->Base.Eval=LA_DAG_FLAG_PERM; lstAppendPointer(l, n);
+    return LA_DAG_FLAG_PERM;
+}
+int IDN_CommentEval(laCommentNode* n){ return 1; }
+void laui_CommentNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){
+    laColumn* c=laFirstColumn(uil); laCommentNode*n=This->EndInstance;
+    LA_BASE_NODE_HEADER(uil,c,This);
+    
+    laShowItemFull(uil,c,This,"content",LA_WIDGET_STRING_MULTI,0,0,0)->Flags|=LA_UI_FLAGS_NO_SCROLL_INACTIVE;
+}
+
+void IDN_RGB2OKHSLInit(laRGB2OKHSLNode* n, int NoCreate){
+    if(!NoCreate){
+        strSafeSet(&n->Base.Name,"RGB to OKHL"); n->In=laCreateInSocket("IN",LA_PROP_FLOAT);
+        n->OutH=laCreateOutSocket(n,"H",LA_PROP_FLOAT);
+        n->OutS=laCreateOutSocket(n,"S",LA_PROP_FLOAT);
+        n->OutL=laCreateOutSocket(n,"L",LA_PROP_FLOAT);
+        tnsVectorSet3(n->RGB,0.2,0.2,0.2);
+    }
+    n->OutH->Data=&n->rOut[0]; n->OutS->Data=&n->rOut[1]; n->OutL->Data=&n->rOut[2];
+}
+void IDN_RGB2OKHSLDestroy(laRGB2OKHSLNode* n){
+    strSafeDestroy(&n->Base.Name);
+    laDestroyInSocket(n->In); laDestroyOutSocket(n->OutH); laDestroyOutSocket(n->OutS); laDestroyOutSocket(n->OutL);
+}
+int IDN_RGB2OKHSLVisit(laRGB2OKHSLNode* n, laListHandle* l){
+    LA_GUARD_THIS_NODE(n);
+    if(LA_SRC_AND_PARENT(n->In)){ laBaseNode* bn=n->In->Source->Parent; LA_VISIT_NODE(bn); }
+    n->Base.Eval=LA_DAG_FLAG_PERM;
+    lstAppendPointer(l, n);
+    return LA_DAG_FLAG_PERM;
+}
+int IDN_RGB2OKHSLEval(laRGB2OKHSLNode* n){
+    real* in=n->RGB;
+    if(LA_SRC_AND_PARENT(n->In) && (n->In->Source->DataType==(LA_PROP_FLOAT|LA_PROP_ARRAY) && n->In->Source->ArrLen>=3)){ in=n->In->Source->Data; }
+    tnsRGB2HCY(in, n->rOut);
+    return 1;
+}
+void laui_RGB2OKHSLNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){
+    laColumn* c=laFirstColumn(uil); laRGB2OKHSLNode*n=This->EndInstance;
+    laUiItem*b,*b2;
+    LA_BASE_NODE_HEADER(uil,c,This);
+
+    b=laBeginRow(uil,c,0,0);
+    laShowNodeSocket(uil,c,This,"in",0); laShowNodeSocket(uil,c,This,"color",0); laShowSeparator(uil,c)->Expand=1;
+    laShowItem(uil,c,This,"out_h")->Flags|=LA_UI_SOCKET_LABEL_W;
+    laShowItem(uil,c,This,"out_s")->Flags|=LA_UI_SOCKET_LABEL_W;
+    laShowItem(uil,c,This,"out_l")->Flags|=LA_UI_SOCKET_LABEL_W;
+    laEndRow(uil,b);
+}
+
+void IDN_OKHSL2RGBInit(laOKHSL2RGBNode* n, int NoCreate){
+    if(!NoCreate){
+        strSafeSet(&n->Base.Name,"OKHL to RGB"); n->Out=laCreateOutSocket(n,"RGB",LA_PROP_FLOAT|LA_PROP_ARRAY);
+        n->InH=laCreateInSocket("H",LA_PROP_FLOAT);
+        n->InS=laCreateInSocket("S",LA_PROP_FLOAT);
+        n->InL=laCreateInSocket("L",LA_PROP_FLOAT);
+    }
+    n->Out->ArrLen=3; n->Out->Data=n->rOut;
+}
+void IDN_OKHSL2RGBDestroy(laOKHSL2RGBNode* n){
+    strSafeDestroy(&n->Base.Name);
+    laDestroyInSocket(n->InH); laDestroyInSocket(n->InS); laDestroyInSocket(n->InL); laDestroyOutSocket(n->Out);
+}
+int IDN_OKHSL2RGBVisit(laOKHSL2RGBNode* n, laListHandle* l){
+    LA_GUARD_THIS_NODE(n);
+    if(LA_SRC_AND_PARENT(n->InH)){ laBaseNode* bn=n->InH->Source->Parent; LA_VISIT_NODE(bn); }
+    if(LA_SRC_AND_PARENT(n->InS)){ laBaseNode* bn=n->InS->Source->Parent; LA_VISIT_NODE(bn); }
+    if(LA_SRC_AND_PARENT(n->InL)){ laBaseNode* bn=n->InL->Source->Parent; LA_VISIT_NODE(bn); }
+    n->Base.Eval=LA_DAG_FLAG_PERM;
+    lstAppendPointer(l, n);
+    return LA_DAG_FLAG_PERM;
+}
+int IDN_OKHSL2RGBEval(laOKHSL2RGBNode* n){
+    real in[3]={0,0,0};
+    if(LA_SRC_AND_PARENT(n->InH) && (n->InH->Source->DataType&LA_PROP_FLOAT)){ in[0]=*((real*)n->InH->Source->Data); }
+    if(LA_SRC_AND_PARENT(n->InS) && (n->InS->Source->DataType&LA_PROP_FLOAT)){ in[1]=*((real*)n->InS->Source->Data); }
+    if(LA_SRC_AND_PARENT(n->InL) && (n->InL->Source->DataType&LA_PROP_FLOAT)){ in[2]=*((real*)n->InL->Source->Data); }
+    tnsHCY2RGB(in, n->rOut);
+    return 1;
+}
+void laui_OKHSL2RGBNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){
+    laColumn* c=laFirstColumn(uil); laOKHSL2RGBNode*n=This->EndInstance;
+    laUiItem*b,*b2;
+    LA_BASE_NODE_HEADER(uil,c,This);
+
+    b=laBeginRow(uil,c,0,0);
+    laShowItem(uil,c,This,"in_h")->Flags|=LA_UI_SOCKET_LABEL_E;
+    laShowItem(uil,c,This,"in_s")->Flags|=LA_UI_SOCKET_LABEL_E;
+    laShowItem(uil,c,This,"in_l")->Flags|=LA_UI_SOCKET_LABEL_E;
+    laShowSeparator(uil,c)->Expand=1; laShowNodeSocket(uil,c,This,"out",0)->Flags|=LA_UI_SOCKET_LABEL_W; 
+    laEndRow(uil,b);
+}
+
 
 
 int OPINV_AddInputMapperPage(laOperator* a, laEvent *e){
@@ -619,7 +763,7 @@ int OPINV_RebuildInputMapping(laOperator* a, laEvent *e){
 
 laBaseNode* la_CreateNode(laNodeRack* ir, laBaseNodeType* NodeType){
     laBaseNode* bn=memAcquire(NodeType->NodeSize);
-    bn->Type=NodeType; NodeType->Init(bn); lstAppendItem(&ir->Nodes, bn); bn->InRack=ir;
+    bn->Type=NodeType; NodeType->Init(bn, 0); bn->InitDone=1; lstAppendItem(&ir->Nodes, bn); bn->InRack=ir;
     laNotifyInstanceUsers(ir); laRecordInstanceDifferences(ir,"la_node_rack"); laPushDifferences("Add Node", 0);
     return bn;
 }
@@ -958,29 +1102,32 @@ void la_RegisterInputMapperOperators(){
     laAddEnumItemAs(p,"MUL", "Multiply", "L x R", LA_MATRIX_NODE_OP_MUL, 0);
     laAddEnumItemAs(p,"INV", "Invert", "Invert L or R", LA_MATRIX_NODE_OP_INV, 0);
 
-    pc=laAddPropertyContainer("la_math_node", "Math", "Math node",0,laui_MathNode,sizeof(laMathNode),0,0,1);
-    LA_PC_IDN_MATH=pc; laPropContainerExtraFunctions(pc,0,0,0,0,laui_DefaultNodeOperationsPropUiDefine);
-    laAddSubGroup(pc,"base","Base","Base node","la_base_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
-    laAddFloatProperty(pc, "vl", "L", "Left value", 0,0,0,0,0,0,0,0,offsetof(laMathNode, ValueL),0,0,0,0,0,0,0,0,0,0,0);
-    laAddFloatProperty(pc, "vr", "R", "Right value", 0,0,0,0,0,0,0,0,offsetof(laMathNode, ValueR),0,0,0,0,0,0,0,0,0,0,0);
-    laAddSubGroup(pc,"in_l", "L","Left input","la_in_socket",0,0,0,offsetof(laMathNode, InL),0,0,0,0,0,0,0,LA_UDF_SINGLE);
-    laAddSubGroup(pc,"in_r", "R","Right input","la_in_socket",0,0,0,offsetof(laMathNode, InR),0,0,0,0,0,0,0,LA_UDF_SINGLE);
-    laAddSubGroup(pc,"out", "Out","Output value","la_out_socket",0,0,0,offsetof(laMathNode, Out),0,0,0,0,0,0,0,LA_UDF_SINGLE);
-    laAddSubGroup(pc,"out_int", "Out Int","Output value in Integer","la_out_socket",0,0,0,offsetof(laMathNode, OutInt),0,0,0,0,0,0,0,LA_UDF_SINGLE);
-    p=laAddEnumProperty(pc,"operation", "Operation", "Operation", 0,0,0,0,0,offsetof(laMathNode, Operation),0,0,0,0,0,0,0,0,0,0);
-    laAddEnumItemAs(p,"ADD", "Add", "L + R", LA_MATH_NODE_OP_ADD, 0);
-    laAddEnumItemAs(p,"SUB", "Subtract", "L - R", LA_MATH_NODE_OP_SUB, 0);
-    laAddEnumItemAs(p,"MUL", "Multiply", "L x R", LA_MATH_NODE_OP_MUL, 0);
-    laAddEnumItemAs(p,"DIV", "Divide", "L / R", LA_MATH_NODE_OP_DIV, 0);
-    laAddEnumItemAs(p,"POW", "Power", "pow(L,R)", LA_MATH_NODE_OP_POW, 0);
-    laAddEnumItemAs(p,"LOG", "Log", "log(L)base(R)", LA_MATH_NODE_OP_LOG, 0);
-    laAddEnumItemAs(p,"SIN", "Sine", "sin(L)", LA_MATH_NODE_OP_SIN, 0);
-    laAddEnumItemAs(p,"COS", "Cosine", "cos(L)", LA_MATH_NODE_OP_COS, 0);
-    laAddEnumItemAs(p,"TAN", "Tangent", "tan(L)", LA_MATH_NODE_OP_TAN, 0);
-    laAddEnumItemAs(p,"ASIN", "Arcsin", "asin(L)", LA_MATH_NODE_OP_ASIN, 0);
-    laAddEnumItemAs(p,"ACOS", "Arccosine", "acos(L)", LA_MATH_NODE_OP_ACOS, 0);
-    laAddEnumItemAs(p,"ATAN", "Arctangent", "atan(L)", LA_MATH_NODE_OP_ATAN, 0);
-    laAddEnumItemAs(p,"ATAN2", "Atan2", "atan2(L,R) where L or R can be zero", LA_MATH_NODE_OP_ATAN2, 0);
+#define REGISTER_MATH_NODE\
+    laPropContainerExtraFunctions(pc,0,0,0,0,laui_DefaultNodeOperationsPropUiDefine);\
+    laAddSubGroup(pc,"base","Base","Base node","la_base_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);\
+    laAddFloatProperty(pc, "vl", "L", "Left value", 0,0,0,0,0,0,0,0,offsetof(laMathNode, ValueL),0,0,0,0,0,0,0,0,0,0,0);\
+    laAddFloatProperty(pc, "vr", "R", "Right value", 0,0,0,0,0,0,0,0,offsetof(laMathNode, ValueR),0,0,0,0,0,0,0,0,0,0,0);\
+    laAddSubGroup(pc,"in_l", "L","Left input","la_in_socket",0,0,0,offsetof(laMathNode, InL),0,0,0,0,0,0,0,LA_UDF_SINGLE);\
+    laAddSubGroup(pc,"in_r", "R","Right input","la_in_socket",0,0,0,offsetof(laMathNode, InR),0,0,0,0,0,0,0,LA_UDF_SINGLE);\
+    laAddSubGroup(pc,"out", "Out","Output value","la_out_socket",0,0,0,offsetof(laMathNode, Out),0,0,0,0,0,0,0,LA_UDF_SINGLE);\
+    laAddSubGroup(pc,"out_int", "Out Int","Output value in Integer","la_out_socket",0,0,0,offsetof(laMathNode, OutInt),0,0,0,0,0,0,0,LA_UDF_SINGLE);\
+    p=laAddEnumProperty(pc,"operation", "Operation", "Operation", 0,0,0,0,0,offsetof(laMathNode, Operation),0,0,0,0,0,0,0,0,0,0);\
+    laAddEnumItemAs(p,"ADD", "Add", "L + R", LA_MATH_NODE_OP_ADD, 0);\
+    laAddEnumItemAs(p,"SUB", "Subtract", "L - R", LA_MATH_NODE_OP_SUB, 0);\
+    laAddEnumItemAs(p,"MUL", "Multiply", "L x R", LA_MATH_NODE_OP_MUL, 0);\
+    laAddEnumItemAs(p,"DIV", "Divide", "L / R", LA_MATH_NODE_OP_DIV, 0);\
+    laAddEnumItemAs(p,"POW", "Power", "pow(L,R)", LA_MATH_NODE_OP_POW, 0);\
+    laAddEnumItemAs(p,"LOG", "Log", "log(L)base(R)", LA_MATH_NODE_OP_LOG, 0);\
+    laAddEnumItemAs(p,"SIN", "Sine", "sin(L)", LA_MATH_NODE_OP_SIN, 0);\
+    laAddEnumItemAs(p,"COS", "Cosine", "cos(L)", LA_MATH_NODE_OP_COS, 0);\
+    laAddEnumItemAs(p,"TAN", "Tangent", "tan(L)", LA_MATH_NODE_OP_TAN, 0);\
+    laAddEnumItemAs(p,"ASIN", "Arcsin", "asin(L)", LA_MATH_NODE_OP_ASIN, 0);\
+    laAddEnumItemAs(p,"ACOS", "Arccosine", "acos(L)", LA_MATH_NODE_OP_ACOS, 0);\
+    laAddEnumItemAs(p,"ATAN", "Arctangent", "atan(L)", LA_MATH_NODE_OP_ATAN, 0);\
+    laAddEnumItemAs(p,"ATAN2", "Atan2", "atan2(L,R) where L or R can be zero", LA_MATH_NODE_OP_ATAN2, 0);\
+    laAddEnumItemAs(p,"MOD", "Mod", "L \% R", LA_MATH_NODE_OP_MOD, 0);
+    pc=laAddPropertyContainer("la_math_node", "Math", "Math node",0,laui_MathNode,sizeof(laMathNode),0,0,1); LA_PC_IDN_MATH=pc; REGISTER_MATH_NODE
+    pc=laAddPropertyContainer("la_small_math_node", "Small Math", "Small Math node",0,laui_SmallMathNode,sizeof(laMathNode),0,0,1); LA_PC_IDN_SMALL_MATH=pc; REGISTER_MATH_NODE
 
     pc=laAddPropertyContainer("la_mapper_node", "Mapper", "Mapper node",0,laui_MapperNode,sizeof(laMapperNode),0,0,1);
     LA_PC_IDN_MAPPER=pc; laPropContainerExtraFunctions(pc,0,0,0,0,laui_DefaultNodeOperationsPropUiDefine);
@@ -1014,7 +1161,30 @@ void la_RegisterInputMapperOperators(){
     laAddEnumItemAs(p,"POW", "Power", "pow(L,R)", LA_VECTOR_MATH_OP_POW, 0);
     laAddEnumItemAs(p,"LOG", "Log", "log(L)base(R)", LA_VECTOR_MATH_OP_LOG, 0);
     laAddEnumItemAs(p,"NORM", "Normalize", "Normalize(L)", LA_VECTOR_MATH_OP_NORMALIZE, 0);
-    
+
+    pc=laAddPropertyContainer("la_comment_node", "Comment", "Comment",0,laui_CommentNode,sizeof(laCommentNode),0,0,1);
+    LA_PC_IDN_COMMENT=pc; laPropContainerExtraFunctions(pc,0,0,0,0,laui_DefaultNodeOperationsPropUiDefine);
+    laAddSubGroup(pc,"base","Base","Base node","la_base_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
+    laAddStringProperty(pc,"content","Content","Content of the comment",LA_WIDGET_STRING_MULTI,0,0,0,1,offsetof(laCommentNode,Content),0,0,0,0,0);
+
+    pc=laAddPropertyContainer("la_rgb_to_okhsl_node", "RGB 2 OKHSL", "RGB color to OKHSL values",0,laui_RGB2OKHSLNode,sizeof(laRGB2OKHSLNode),0,0,1);
+    LA_PC_IDN_RGB2OKHSL=pc; laPropContainerExtraFunctions(pc,0,0,0,0,laui_DefaultNodeOperationsPropUiDefine);
+    laAddSubGroup(pc,"base","Base","Base node","la_base_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
+    laAddSubGroup(pc,"in", "In","Input color","la_in_socket",0,0,0,offsetof(laRGB2OKHSLNode, In),0,0,0,0,0,0,0,LA_UDF_SINGLE);
+    laAddSubGroup(pc,"out_h", "H","Hue","la_out_socket",0,0,0,offsetof(laRGB2OKHSLNode, OutH),0,0,0,0,0,0,0,LA_UDF_SINGLE);
+    laAddSubGroup(pc,"out_s", "S","Chroma","la_out_socket",0,0,0,offsetof(laRGB2OKHSLNode, OutS),0,0,0,0,0,0,0,LA_UDF_SINGLE);
+    laAddSubGroup(pc,"out_l", "L","Brightness","la_out_socket",0,0,0,offsetof(laRGB2OKHSLNode, OutL),0,0,0,0,0,0,0,LA_UDF_SINGLE);
+    laAddFloatProperty(pc, "color", "Color", "Default color", LA_WIDGET_FLOAT_COLOR,0,0,0,0,0,0,0,offsetof(laRGB2OKHSLNode, RGB),0,0,3,0,0,0,0,0,0,0,0);
+   
+    pc=laAddPropertyContainer("la_okhsl_to_rgb_node", "OKHSL 2 RGB", "OKHSL values to RGB color",0,laui_OKHSL2RGBNode,sizeof(laOKHSL2RGBNode),0,0,1);
+    LA_PC_IDN_OKHSL2RGB=pc; laPropContainerExtraFunctions(pc,0,0,0,0,laui_DefaultNodeOperationsPropUiDefine);
+    laAddSubGroup(pc,"base","Base","Base node","la_base_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
+    laAddSubGroup(pc,"out", "Out","Output color","la_out_socket",0,0,0,offsetof(laOKHSL2RGBNode, Out),0,0,0,0,0,0,0,LA_UDF_SINGLE);
+    laAddSubGroup(pc,"in_h", "H","Hue","la_in_socket",0,0,0,offsetof(laOKHSL2RGBNode, InH),0,0,0,0,0,0,0,LA_UDF_SINGLE);
+    laAddSubGroup(pc,"in_s", "S","Chroma","la_in_socket",0,0,0,offsetof(laOKHSL2RGBNode, InS),0,0,0,0,0,0,0,LA_UDF_SINGLE);
+    laAddSubGroup(pc,"in_l", "L","Brightness","la_in_socket",0,0,0,offsetof(laOKHSL2RGBNode, InL),0,0,0,0,0,0,0,LA_UDF_SINGLE);
+   
+typedef laMathNode laSmallMathNode;
     LA_IDN_REGISTER("Controller",L'🕹',LA_IDN_CONTROLLER,LA_PC_IDN_CONTROLLER, IDN_ControllerInit, IDN_ControllerDestroy, IDN_ControllerVisit, IDN_ControllerEval, laInputControllerNode);
     LA_IDN_REGISTER("Visualizer",L'🔍',LA_IDN_VISUALIZER,LA_PC_IDN_VISUALIZER, IDN_InputVisualizeInit, IDN_InputVisualizeDestroy, IDN_InputVisualizeVisit, IDN_InputVisualizerEval, laInputVisualizerNode);
     LA_IDN_REGISTER("Split",L'⚟',LA_IDN_SPLIT,LA_PC_IDN_SPLIT, IDN_SplitInit, IDN_SplitDestroy, IDN_SplitVisit, IDN_SplitEval, laSplitNode);
@@ -1023,17 +1193,25 @@ void la_RegisterInputMapperOperators(){
     LA_IDN_REGISTER("Values",0,LA_IDN_VALUES,LA_PC_IDN_VALUES, IDN_ValuesInit, IDN_ValuesDestroy, IDN_ValuesVisit, IDN_ValuesEval, laValuesNode);
     LA_IDN_REGISTER("Matrix",0,LA_IDN_MATRIX,LA_PC_IDN_MATRIX, IDN_MatrixInit, IDN_MatrixDestroy, IDN_MatrixVisit, IDN_MatrixEval, laMatrixNode);
     LA_IDN_REGISTER("Math",0,LA_IDN_MATH,LA_PC_IDN_MATH, IDN_MathInit, IDN_MathDestroy, IDN_MathVisit, IDN_MathEval, laMathNode);
+    LA_IDN_REGISTER("Small Math",0,LA_IDN_SMALL_MATH,LA_PC_IDN_SMALL_MATH, IDN_MathInit, IDN_MathDestroy, IDN_MathVisit, IDN_MathEval, laSmallMathNode);
     LA_IDN_REGISTER("Mapper",0,LA_IDN_MAPPER,LA_PC_IDN_MAPPER, IDN_MapperInit, IDN_MapperDestroy, IDN_MapperVisit, IDN_MapperEval, laMapperNode);
     LA_IDN_REGISTER("Random",0,LA_IDN_RANDOM,LA_PC_IDN_RANDOM, IDN_RandomInit, IDN_RandomDestroy, IDN_RandomVisit, IDN_RandomEval, laRandomNode);
-    LA_IDN_REGISTER("Math",0,LA_IDN_VECTOR_MATH,LA_PC_IDN_VECTOR_MATH, IDN_VectorMathInit, IDN_VectorMathDestroy, IDN_VectorMathVisit, IDN_VectorMathEval, laVectorMathNode);
+    LA_IDN_REGISTER("Vector Math",0,LA_IDN_VECTOR_MATH,LA_PC_IDN_VECTOR_MATH, IDN_VectorMathInit, IDN_VectorMathDestroy, IDN_VectorMathVisit, IDN_VectorMathEval, laVectorMathNode);
+    LA_IDN_REGISTER("Comment",0,LA_IDN_COMMENT,LA_PC_IDN_COMMENT, IDN_CommentInit, IDN_CommentDestroy, IDN_CommentVisit, IDN_CommentEval, laCommentNode);
+    LA_IDN_REGISTER("RGB to OKHSL",0,LA_IDN_RGB2OKHSL,LA_PC_IDN_RGB2OKHSL, IDN_RGB2OKHSLInit, IDN_RGB2OKHSLDestroy, IDN_RGB2OKHSLVisit, IDN_RGB2OKHSLEval, laRGB2OKHSLNode);
+    LA_IDN_REGISTER("OKHSL to RGB",0,LA_IDN_OKHSL2RGB,LA_PC_IDN_OKHSL2RGB, IDN_OKHSL2RGBInit, IDN_OKHSL2RGBDestroy, IDN_OKHSL2RGBVisit, IDN_OKHSL2RGBEval, laOKHSL2RGBNode);
     
     LA_NODE_CATEGORY_INPUT=laAddNodeCategory("Input",0,LA_RACK_TYPE_INPUT);
     LA_NODE_CATEGORY_MATH=laAddNodeCategory("Math",0,LA_RACK_TYPE_ALL);
+    LA_NODE_CATEGORY_COLOR=laAddNodeCategory("Color",0,LA_RACK_TYPE_ALL);
     LA_NODE_CATEGORY_ROUTE=laAddNodeCategory("Route",0,LA_RACK_TYPE_ALL);
+    LA_NODE_CATEGORY_AUX=laAddNodeCategory("Auxiliary",0,LA_RACK_TYPE_ALL);
 
     laNodeCategoryAddNodeTypes(LA_NODE_CATEGORY_INPUT, &LA_IDN_CONTROLLER,0);
-    laNodeCategoryAddNodeTypes(LA_NODE_CATEGORY_MATH, &LA_IDN_MATH,&LA_IDN_VECTOR_MATH,&LA_IDN_MAPPER,&LA_IDN_RANDOM,&LA_IDN_MATRIX,0);
+    laNodeCategoryAddNodeTypes(LA_NODE_CATEGORY_MATH, &LA_IDN_MATH, &LA_IDN_SMALL_MATH,&LA_IDN_VECTOR_MATH,&LA_IDN_MAPPER,&LA_IDN_RANDOM,&LA_IDN_MATRIX,0);
     laNodeCategoryAddNodeTypes(LA_NODE_CATEGORY_ROUTE, &LA_IDN_SPLIT, &LA_IDN_SWITCH, &LA_IDN_COMBINE, &LA_IDN_VALUES, &LA_IDN_VISUALIZER,0);
+    laNodeCategoryAddNodeTypes(LA_NODE_CATEGORY_AUX, &LA_IDN_COMMENT,0);
+    laNodeCategoryAddNodeTypes(LA_NODE_CATEGORY_COLOR, &LA_IDN_RGB2OKHSL, &LA_IDN_OKHSL2RGB,0);
 
     MAIN.tNodeIn=laCreateInSocket("TIN",0);
     MAIN.tNodeOut=laCreateOutSocket(0,"TOUT",0);
@@ -1047,7 +1225,7 @@ void laMappingRequestEval(){ MAIN.InputMapping->NeedEval=1; }
 int la_RunInputMapping(){
     MAIN.InputMapping->NeedEval = 0;
     for(laListItemPointer*lip=MAIN.InputMapping->Eval.pFirst;lip;lip=lip->pNext){
-        laBaseNode* n=lip->p; n->Type->Eval(n);
+        laBaseNode* n=lip->p; if(!n->InitDone){ n->Type->Init(n,1); n->InitDone=1; } n->Type->Eval(n);
     }
     return 1;
 }

+ 1 - 0
resources/la_properties.c

@@ -1220,6 +1220,7 @@ void la_RegisterInternalProps(){
             laAddStringProperty(p, "label", "Label", "Socket's label", 0, 0, 0, 0, 1, offsetof(laNodeOutSocket, Label), 0, 0, 0, 0, LA_AS_IDENTIFIER);
             laAddIntProperty(p, "data_type", "Data type", "User defined data type", 0, 0, 0, 0, 0, 0, 0, 0, offsetof(laNodeOutSocket, DataType), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,LA_READ_ONLY);
             laAddIntProperty(p, "array_length", "Array Length", "Array length of data", 0, 0, 0, 0, 0, 0, 0, 0, offsetof(laNodeOutSocket, ArrLen), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,LA_READ_ONLY);
+            laAddSubGroup(p, "parent", "Parent", "Parent node", "la_base_node",0, 0, 0, offsetof(laNodeOutSocket, Parent), 0, 0, 0, 0, 0, 0, 0, LA_UDF_REFER);
         } LA_PC_SOCKET_OUT = p;
         p = laAddPropertyContainer("la_in_socket", "Input Socket", "Input socket for nodest", 0, 0, sizeof(laNodeInSocket), 0, 0, 1);{
             laAddStringProperty(p, "label", "Label", "Socket's label", 0, 0, 0, 0, 1, offsetof(laNodeInSocket, Label), 0, 0, 0, 0, LA_AS_IDENTIFIER);

+ 5 - 3
resources/la_tns_drivers.c

@@ -9,7 +9,8 @@ laBaseNodeType TNS_IDN_MAKE_TRANSFORM;
 laPropContainer* TNS_PC_IDN_TRANSFORM;
 laPropContainer* TNS_PC_IDN_MAKE_TRANSFORM;
 
-void IDN_TransformInit(tnsTransformNode* n){
+void IDN_TransformInit(tnsTransformNode* n, int NoCreate){
+    if(NoCreate){return;}
     n->Mat=laCreateInSocket("MAT",0); strSafeSet(&n->Base.Name,"Transform");
 }
 void IDN_TransformDestroy(tnsTransformNode* n){
@@ -43,7 +44,8 @@ void tnsui_TransformNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laC
     laShowItem(uil,cr,This,"target");
 }
 
-void IDN_MakeTransformInit(tnsMakeTransformNode* n){
+void IDN_MakeTransformInit(tnsMakeTransformNode* n, int NoCreate){
+    if(NoCreate){return;}
     n->Out=laCreateOutSocket(n,"MAT",0); strSafeSet(&n->Base.Name,"Make Transform");
     n->Loc=laCreateInSocket("LOC",0); 
     n->Rot=laCreateInSocket("ROT",0);  n->Angle=laCreateInSocket("ANGLE",0); n->UseRot[2]=1;
@@ -171,7 +173,7 @@ void laDriverRequestEval(){ MAIN.Drivers->NeedEval=1; }
 int la_RunDrivers(){
     MAIN.Drivers->NeedEval = 0;
     for(laListItemPointer*lip=MAIN.Drivers->Eval.pFirst;lip;lip=lip->pNext){
-        laBaseNode* n=lip->p; n->Type->Eval(n);
+        laBaseNode* n=lip->p; if(!n->InitDone){ n->Type->Init(n,1); n->InitDone=1; } n->Type->Eval(n);
     }
     return 1;
 }

+ 7 - 3
resources/la_widgets.c

@@ -2460,9 +2460,12 @@ int OPMOD_MultiString(laOperator *a, laEvent *e){
         laRedrawCurrentPanel();
         if (la_ProcessTextEdit(e, se, ui)) return LA_RUNNING;
     }
-
-    if(e->Type==LA_MOUSE_WHEEL_DOWN){ strMoveView(se, MAIN.ScrollingSpeed, 0); laRedrawCurrentPanel(); return LA_RUNNING; }
-    elif(e->Type==LA_MOUSE_WHEEL_UP){ strMoveView(se, -MAIN.ScrollingSpeed, 0); laRedrawCurrentPanel(); return LA_RUNNING; }
+    
+    int NoInactiveScroll=ui->Flags&LA_UI_FLAGS_NO_SCROLL_INACTIVE;
+    if((!NoInactiveScroll) || (ui->State==LA_UI_ACTIVE)){
+        if(e->Type==LA_MOUSE_WHEEL_DOWN){ strMoveView(se, MAIN.ScrollingSpeed, 0); laRedrawCurrentPanel(); return LA_RUNNING; }
+        elif(e->Type==LA_MOUSE_WHEEL_UP){ strMoveView(se, -MAIN.ScrollingSpeed, 0); laRedrawCurrentPanel(); return LA_RUNNING; }
+    }
 
     if (e->Type == LA_L_MOUSE_DOWN){
         if (ui->State == LA_UI_NORMAL){
@@ -2825,6 +2828,7 @@ laValueMapper* laValueMapperDestroy(laValueMapper* vm){
 }
 real laValueMapperEvaluate(laValueMapper* vm, real x){
     if(fabs(vm->InRange[1]-vm->InRange[0])<1e-7) return 0;
+    x=tnsGetRatiod(vm->InRange[0],vm->InRange[1],x);
     laValueMapperPoint* vmp,*NextVMP;
     real ey=0;
     for(vmp=vm->Points.pFirst;vmp;vmp=vmp->Item.pNext){