*/}}
Browse Source

Move drivers to object

YimingWu 1 year ago
parent
commit
f6a7291dd0
10 changed files with 150 additions and 97 deletions
  1. 2 2
      la_data.c
  2. 12 6
      la_interface.h
  3. 33 30
      la_kernel.c
  4. 3 1
      la_tns.h
  5. 5 0
      la_tns_kernel.c
  6. 8 8
      resources/la_nodes_basic.c
  7. 22 7
      resources/la_properties.c
  8. 34 15
      resources/la_templates.c
  9. 11 17
      resources/la_tns_drivers.c
  10. 20 11
      resources/la_widgets.c

+ 2 - 2
la_data.c

@@ -3238,7 +3238,7 @@ int la_ExtractProp(laUDF *udf, laManagedUDF* mUDF, laPropPack *pp, void *ParentI
 
                     if(p->UDFReadProgress){ laShowProgress((real)i/NumItems,-1); } //printf("add pc %s\n",pc->Identifier);
 
-                    if(pc==LA_PC_SOCKET_OUT || pc==LA_PC_SOCKET_IN){ laMappingRequestRebuild(); laDriverRequestRebuild(); }
+                    if(pc==LA_PC_SOCKET_OUT || pc==LA_PC_SOCKET_IN){ laGraphRequestRebuild(); }
 
                     int replaced=0;
                     if (udf){
@@ -4560,7 +4560,7 @@ void laRecordCustomDifferences(void* Data, laDiffCommandUndoF Undo, laDiffComman
 }
 int laRecordDifferences(laPropPack* base, char* path){
     laPropPack PP={0};
-    la_GetPropFromPath(&PP,base,path,0);
+    if(!la_GetPropFromPath(&PP,base,path,0)) return 0;
     la_StepPropPack(&PP);
     //laPropPackToLocal(&LocalPP, &PP);
     int success=0;

+ 12 - 6
la_interface.h

@@ -257,7 +257,6 @@ NEED_STRUCTURE(laNodeCategory);
 STRUCTURE(laRackPageCollection){
     laRackPage* CurrentPage;
     laListHandle Pages;
-    int NeedEval,NeedRebuild;
 };
 
 typedef laBaseNodeType* (*laGetBaseNodeTypeF)(char* str);
@@ -514,8 +513,10 @@ STRUCTURE(LA){
 
     laListHandle MediaFiles;
 
+    int GraphNeedsRebuild; // current mechanism only allows global.
+    int InputNeedsEval;
     laRackPageCollection* InputMapping;
-    laRackPageCollection* Drivers;
+    //laRackPageCollection* Drivers;
     laListHandle NodeCategories;
     laNodeCategory* CurrentNodeCategory;
     int FilterNodeCategory;
@@ -532,6 +533,7 @@ STRUCTURE(LA){
 
     //pthread_spinlock_t csMediaPlay;
 
+    int DetachedViewSwitch;
     int example_int;
     laSafeString* example_string;
 };
@@ -1046,6 +1048,7 @@ STRUCTURE(laWidget){
 #define LA_UI_IMAGE_FULL_W     LA_TEXT_MONO
 #define LA_UI_MIN_WIDTH        LA_UI_FLAGS_COLOR_SPACE_CLAY
 #define LA_UI_FLAGS_NO_LABEL   (1<<29)
+#define LA_UI_COLLECTION_SIMPLE_SELECTOR LA_UI_FLAGS_CYCLE
 
 #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)
@@ -1364,14 +1367,11 @@ void la_RegisterInputMapperOperators();
 int laRebuildPageEval(laRackPage* rp);
 int laRunPage(laRackPage* rp, uint64_t mask);
 
-void laMappingRequestRebuild();
+void laGraphRequestRebuild();
 void laMappingRequestEval();
 int la_RebuildInputMapping();
 int la_RunInputMapping();
 
-void laDriverRequestRebuild();
-void laDriverRequestEval();
-int la_RebuildDriverEval();
 int la_RunDrivers();
 
 void lapost_Node(laBaseNode *bn);
@@ -1460,13 +1460,19 @@ extern laNodeCategory* LA_NODE_CATEGORY_COLOR;
 #define LA_VECTOR_MATH_OP_LEN 8
 #define LA_VECTOR_MATH_OP_NORMALIZE 9
 
+#define LA_PAGE_TRIGGER_ALWAYS 0
+#define LA_PAGE_TRIGGER_NONE   1
+
 STRUCTURE(laRackPage){
     laListItem Item;
     laSafeString* Name;
     laListHandle Racks;
     laListHandle Eval;
     laListHandle AlwaysBranchers;
+    laSafeString* Script;
     int RackType;
+    int TriggerMode;
+    int UseScript;
 };
 #define LA_RACK_TYPE_INPUT (1<<0)
 #define LA_RACK_TYPE_DRIVER (1<<1)

+ 33 - 30
la_kernel.c

@@ -845,7 +845,7 @@ int laGetReadyWith(int GLMajor, int GLMinor, int BufferSamples){
     arrEnsureLength(&MAIN.NodeTypes,0,&MAIN.NodeTypeMax,sizeof(laBaseNode*));
 
     MAIN.InputMapping=memAcquire(sizeof(laRackPageCollection));
-    MAIN.Drivers=memAcquire(sizeof(laRackPageCollection));
+    //MAIN.Drivers=memAcquire(sizeof(laRackPageCollection));
     
     MAIN.Animation=memAcquire(sizeof(laAnimation));
 
@@ -5084,34 +5084,39 @@ int la_UpdateUiListRecursive(laUiList *uil, int U, int L, int R, int B, int Fast
                 if(Spread){ ui->TR=ER-Spread*LA_RH; if(ui->TR>MaxR) MaxR=ui->TR; }
                 if (!WaitAnimation){ ui->L = ui->TL; ui->R = ui->TR; ui->U = ui->TU; ui->B = ui->TB = MaxB; }
             }else if (ui->Type == _LA_UI_COLLECTION_SELECTOR || ui->Type == _LA_UI_COLLECTION_SINGLE){
-                void *TInstance = laGetActiveInstanceStrict(ui->PP.LastPs->p, ui->PP.LastPs->UseInstance);
-                ui->PP.EndInstance = TInstance;
-                laUiTemplate *Template = ui->Template ? ui->Template : laGetPropertyUiDefine(&ui->PP, TInstance);
-                if(!Template) Template=laui_SubPropInfoDefault;
-                //ui->Template = Template;
-                int EraseWidth=(ui->Type == _LA_UI_COLLECTION_SELECTOR)?LA_RH:0;
-                if (!ui->Subs.pFirst && TInstance){
-                    la_AddInstancePage(ui, TInstance, 0);
-                    la_CalcUiTopInfluence(&uil->Columns, ui);
-                    laMakeUiListFromTemplate(ui->Page, Template, &ParentPanel->PP, &ParentPanel->PropLinkPP, &ui->PP, 0, &uil->Columns, ui->TemplateContext);
-                    SubB = la_UpdateUiListRecursive(ui->Page, ui->TB+(NoDecal?0:bt->TM), ui->TL+(NoDecal?0:bt->LM), ui->TR-(NoDecal?0:bt->RM)-EraseWidth, B, Fast, ParentPanel);
-                    ui->TB = SubB + (NoDecal?0:bt->TM);
-                }else if (ui->Subs.pFirst){
-                    if (!TInstance || TInstance != ui->Page->Instance){
-                        la_DestroyTabPage(ui, ui->Subs.pFirst, 0);
-                        ui->Page = 0;
-                        if (TInstance){
-                            la_AddInstancePage(ui, TInstance, 0);
-                            la_CalcUiTopInfluence(&uil->Columns, ui);
-                            laMakeUiListFromTemplate(ui->Page, Template, &ParentPanel->PP, &ParentPanel->PropLinkPP, &ui->PP, 0, &uil->Columns, ui->TemplateContext);
-                            SubB = la_UpdateUiListRecursive(ui->Page, ui->TB+(NoDecal?0:bt->TM), ui->TL+(NoDecal?0:bt->LM), ui->TR-(NoDecal?0:bt->RM)-EraseWidth, B, Fast, ParentPanel);
-                            ui->TB = SubB + (NoDecal?0:bt->TM);
-                        }else
-                            ui->TB = ui->TU + LA_RH + bt->BM;
-                    }else{
+                if(ui->Flags&LA_UI_COLLECTION_SIMPLE_SELECTOR){
+                    ui->TB=ui->TU+LA_RH;
+                }else{
+                    void *TInstance = laGetActiveInstanceStrict(ui->PP.LastPs->p, ui->PP.LastPs->UseInstance);
+                    ui->PP.EndInstance = TInstance;
+                    laUiTemplate *Template = ui->Template ? ui->Template : laGetPropertyUiDefine(&ui->PP, TInstance);
+                    if(!Template) Template=laui_SubPropInfoDefault;
+                    //ui->Template = Template;
+                    int EraseWidth=(ui->Type == _LA_UI_COLLECTION_SELECTOR)?LA_RH:0;
+                    if (!ui->Subs.pFirst && TInstance){
+                        la_AddInstancePage(ui, TInstance, 0);
+                        la_CalcUiTopInfluence(&uil->Columns, ui);
+                        laMakeUiListFromTemplate(ui->Page, Template, &ParentPanel->PP, &ParentPanel->PropLinkPP, &ui->PP, 0, &uil->Columns, ui->TemplateContext);
                         SubB = la_UpdateUiListRecursive(ui->Page, ui->TB+(NoDecal?0:bt->TM), ui->TL+(NoDecal?0:bt->LM), ui->TR-(NoDecal?0:bt->RM)-EraseWidth, B, Fast, ParentPanel);
                         ui->TB = SubB + (NoDecal?0:bt->TM);
+                    }else if (ui->Subs.pFirst){
+                        if (!TInstance || TInstance != ui->Page->Instance){
+                            la_DestroyTabPage(ui, ui->Subs.pFirst, 0);
+                            ui->Page = 0;
+                            if (TInstance){
+                                la_AddInstancePage(ui, TInstance, 0);
+                                la_CalcUiTopInfluence(&uil->Columns, ui);
+                                laMakeUiListFromTemplate(ui->Page, Template, &ParentPanel->PP, &ParentPanel->PropLinkPP, &ui->PP, 0, &uil->Columns, ui->TemplateContext);
+                                SubB = la_UpdateUiListRecursive(ui->Page, ui->TB+(NoDecal?0:bt->TM), ui->TL+(NoDecal?0:bt->LM), ui->TR-(NoDecal?0:bt->RM)-EraseWidth, B, Fast, ParentPanel);
+                                ui->TB = SubB + (NoDecal?0:bt->TM);
+                            }else
+                                ui->TB = ui->TU + LA_RH + bt->BM;
+                        }else{
+                            SubB = la_UpdateUiListRecursive(ui->Page, ui->TB+(NoDecal?0:bt->TM), ui->TL+(NoDecal?0:bt->LM), ui->TR-(NoDecal?0:bt->RM)-EraseWidth, B, Fast, ParentPanel);
+                            ui->TB = SubB + (NoDecal?0:bt->TM);
+                        }
                     }
+
                 }
                 if (ui->TB-ui->TU<LA_RH) ui->TB = ui->TU + LA_RH;
                 if (!WaitAnimation){
@@ -7201,10 +7206,8 @@ void laMainLoop(){
 
         la_UpdateControllerStatus();
 
-        if(MAIN.InputMapping->NeedRebuild){ la_RebuildInputMapping(); }
-        if(MAIN.InputMapping->NeedEval){ la_RunInputMapping(); }
-        if(MAIN.Drivers->NeedRebuild){ la_RebuildDriverEval(); }
-        if(MAIN.Drivers->NeedEval){ la_RunDrivers(); }
+        if(MAIN.GraphNeedsRebuild){ la_RebuildInputMapping(); MAIN.InputNeedsEval = 0; }
+        if(MAIN.InputNeedsEval){ la_RunInputMapping(); }
 
         for (w=MAIN.Windows.pFirst;w;w = NextW){
             NextW = w->Item.pNext;

+ 3 - 1
la_tns.h

@@ -592,6 +592,8 @@ STRUCTURE(tnsEvaluateData){
     tnsEvaluatedInstance* Selections; int NextSelection, MaxSelection;
 };
 
+NEED_STRUCTURE(laRackPageCollection);
+
 STRUCTURE(tnsObject){
     laListItem Item;
 
@@ -633,7 +635,7 @@ STRUCTURE(tnsObject){
     tnsObject *ParentObject;   // reused as root active sun.
     laListHandle ChildObjects;
 
-    laListHandle Drivers; // rack
+    laRackPageCollection* Drivers; // rack
 
     laListHandle Actions;
 

+ 5 - 0
la_tns_kernel.c

@@ -3549,6 +3549,8 @@ tnsObject *tnsCreateRootObject(char *name){
 
     w->ActiveRoot = o; // XXX: same here
 
+    o->Drivers=memAcquireHyper(sizeof(laRackPageCollection));
+
     return o;
 }
 void tnsDestroyRootObject(tnsObject *root){
@@ -3558,6 +3560,9 @@ void tnsDestroyRootObject(tnsObject *root){
 
     tnsFreeEvaluatedArray(&root->Evaluated);
 
+    //XXX: destroy rack page; and then release memory;
+    o->Drivers=0; memLeave(o->Drivers); 
+
     lstRemoveItem(&w->RootObjects, root);
     while (lstPopPointerLeave(&root->ChildObjects));
     strSafeDestroy(&root->Name);

+ 8 - 8
resources/la_nodes_basic.c

@@ -900,7 +900,8 @@ void laui_LoopIndexNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laCo
 int OPINV_AddInputMapperPage(laOperator* a, laEvent *e){
     laRackPage* dp=memAcquireHyper(sizeof(laRackPage));
     strSafeSet(&dp->Name,"New Page");
-    lstAppendItem(&MAIN.InputMapping->Pages, dp); MAIN.InputMapping->CurrentPage=dp; dp->RackType=LA_RACK_TYPE_INPUT;
+    lstAppendItem(&MAIN.InputMapping->Pages, dp);
+    memAssignRef(MAIN.InputMapping,&MAIN.InputMapping->CurrentPage,dp); dp->RackType=LA_RACK_TYPE_INPUT;
     laNotifyUsers("la.input_mapping"); laRecordAndPush(0,"la.input_mapping","Add Page", 0);
     return LA_FINISHED;
 }
@@ -915,7 +916,7 @@ int OPINV_AddNodesRack(laOperator* a, laEvent *e){
 
 }
 int OPINV_RebuildInputMapping(laOperator* a, laEvent *e){
-    laMappingRequestRebuild();
+    laGraphRequestRebuild();
     return LA_FINISHED;
 }
 
@@ -990,7 +991,7 @@ int OPINV_DeleteNode(laOperator* a, laEvent *e){
     laNodeRack* parent=n->InRack;
 
     lstRemoveItem(&n->InRack->Nodes, n); n->Type->Destroy(n); memLeave(n);
-    laMappingRequestRebuild(); laDriverRequestRebuild();
+    laGraphRequestRebuild();
     laNotifyInstanceUsers(parent); laRecordInstanceDifferences(parent,"la_node_rack"); laPushDifferences("Delete Node", 0);
 
     return LA_FINISHED;
@@ -1059,7 +1060,7 @@ void laset_InputNodeUserID(laInputControllerNode* n, int i){
 }
 void laset_InputControllerNodeSocketWhich(laInputControllerNodeSocket* s, char* str){
     strSafeSet(&s->Which, str);
-    laNotifyUsers("la.input_racks"); laMappingRequestRebuild();
+    laNotifyUsers("la.input_racks"); laGraphRequestRebuild();
 }
 int laget_SocketEnumArrayLength(laInputControllerNodeSocket* s){
     return s->Out->ArrLen?s->Out->ArrLen:1;
@@ -1410,8 +1411,8 @@ typedef laMathNode laSmallMathNode;
     MAIN.tNodeOut=laCreateOutSocket(0,"TOUT",0);
 }
 
-void laMappingRequestRebuild(){ MAIN.InputMapping->NeedRebuild=1; }
-void laMappingRequestEval(){ MAIN.InputMapping->NeedEval=1; }
+void laGraphRequestRebuild(){ MAIN.GraphNeedsRebuild=1; }
+void laMappingRequestEval(){ MAIN.InputNeedsEval=1; }
 
 int __DEBUG_PAGE_EVAL__=1;
 
@@ -1463,11 +1464,10 @@ int laRunPage(laRackPage* rp, uint64_t mask){
 }
 
 int la_RunInputMapping(){
-    MAIN.InputMapping->NeedEval = 0;
+    MAIN.InputNeedsEval = 0;
     return laRunPage(MAIN.InputMapping->CurrentPage, 1);
 }
 int la_RebuildInputMapping(){
-    MAIN.InputMapping->NeedRebuild = 0;
     return laRebuildPageEval(MAIN.InputMapping->CurrentPage);
 }
 

+ 22 - 7
resources/la_properties.c

@@ -508,12 +508,15 @@ void laread_ConditionNodeType(laUiConditionNode *ucn, int Type){
     ucn->Type = Type;
 }
 
-void* laget_FirstDriverPage(void* unused, void* unused2){
-    return MAIN.Drivers->Pages.pFirst;
+void* laget_FirstDriverPage(laRackPageCollection* rpc, void* unused2){
+    return rpc->Pages.pFirst;
 }
 void* laget_CurrentRackPage(laRackPageCollection* c){
     return c->CurrentPage;
 }
+void laset_CurrentRackPage(laRackPageCollection* c,laRackPage* rp){
+    memAssignRef(c,&c->CurrentPage,rp);
+}
 void* laget_CurrentAnimationAction(void* unused_a){
     return MAIN.Animation->CurrentAction;
 }
@@ -753,7 +756,7 @@ void lapost_DetachedProp(laProp *Prop){
 }
 
 void latouched_NodeInSocket(void* unused, int hint){
-    laDriverRequestRebuild(); laMappingRequestRebuild();
+    laGraphRequestRebuild();
 }
 
 int lafilter_NodeCategory(void* unused, laNodeCategory* c){
@@ -1024,13 +1027,16 @@ void la_RegisterInternalProps(){
             laSubGroupExtraFunctions(sp,lafilter_NodeCategory,0,0,0);
 
             laAddSubGroup(p, "input_mapping", "Input Mapping", "Input mapping page collection","la_input_mapping_collection",0,0,0,offsetof(LA,InputMapping),0,0,0,0,0,0,0,LA_UDF_SINGLE);
-            laAddSubGroup(p, "drivers", "Drivers", "Driver page collection","la_driver_collection",0,0,0,offsetof(LA,Drivers),0,0,0,0,0,0,0,LA_UDF_SINGLE);
-
+            
             laAddSubGroup(p, "animation", "Animation", "Animation data","la_animation",0,0,0,offsetof(LA,Animation),0,0,0,0,0,0,0,LA_UDF_SINGLE);
 
             laAddStringProperty(p, "identifier", "Identifier", "Identifier", 0,0,0,0,0,0,0,laget_MainIdentifier, 0,0,LA_AS_IDENTIFIER|LA_READ_ONLY);
             laAddSubGroup(p, "test_ucn", "TEST UCN", "---", "udf_content_node",0,0,0,offsetof(LA, TEST_Link), 0,0,0,0,0,0,0,0);
             
+            ep=laAddEnumProperty(p, "detached_view_switch", "View Detached", "Use detached view on panels", LA_WIDGET_ENUM_HIGHLIGHT,0,0,0,0,offsetof(LA, DetachedViewSwitch),0,0,0,0,0,0,0,0,0,LA_UDF_IGNORE);
+            laAddEnumItemAs(ep, "LINKED", "Linked", "View is linked to global current states", 0, U'🔗');
+            laAddEnumItemAs(ep, "DETACHED", "Detached", "View is detached from global states and is pinned to panel", 1, U'📌');
+
             laAddIntProperty(p, "example_int", "Example Integer", "Example integer", 0,0,0,100,0,1, 50,0,offsetof(LA, example_int), 0,0,0,0,0,0,0,0,0,0,0);
             laAddStringProperty(p, "example_string", "Example String", "Example string", 0,0,0,0,1, offsetof(LA,example_string), 0,0,0,0,0);
             laAddStringProperty(p, "unknown_prop", "Unknown Property", "Placeholder for unknown property, probably due to a wrong property path, or not setting LA_AS_IDENTIFIER in any of the properties.",
@@ -1049,8 +1055,8 @@ void la_RegisterInternalProps(){
         }
         p = laAddPropertyContainer("la_driver_collection", "Driver Collection", "Driver collection", 0,0,sizeof(laRackPageCollection), 0,0,1);{
             laAddSubGroup(p, "pages", "Pages", "Rack pages","la_rack_page",0,0,0,-1,0,laget_CurrentRackPage,0,0,0,0,offsetof(laRackPageCollection,Pages),0);
-            sp=laAddSubGroup(p, "current_page", "Current Page", "Current page","la_rack_page",0,0,0,offsetof(laRackPageCollection,CurrentPage),0,0,0,0,0,0,0,LA_UDF_REFER);
-            laSubGroupDetachable(sp,laget_FirstDriverPage,laget_ListNext);
+            sp=laAddSubGroup(p, "current_page", "Current Page", "Current page","la_rack_page",0,0,0,offsetof(laRackPageCollection,CurrentPage),laget_FirstDriverPage,0,laget_ListNext,laset_CurrentRackPage,0,0,0,LA_UDF_REFER);
+            //laSubGroupDetachable(sp,laget_FirstDriverPage,laget_ListNext);
         }
 
         p = laAddPropertyContainer("la_rack_page", "Rack Page", "A page of nodes", 0,laui_IdentifierOnly, sizeof(laRackPage), 0,0,2);{
@@ -1059,6 +1065,13 @@ void la_RegisterInternalProps(){
             laAddIntProperty(p,"type", "Type", "Type of the rack", 0,0,0,0,0,0,0,0,offsetof(laRackPage,RackType),0,0,0,0,0,0,0,0,0,0,LA_READ_ONLY);
             laAddIntProperty(p,"has_rack", "Has Rack", "Has rack", 0,0,0,0,0,0,0,0,offsetof(laRackPage,Racks.pFirst),0,0,0,0,0,0,0,0,0,0,LA_READ_ONLY|LA_UDF_IGNORE);
             laAddSubGroup(p, "racks", "Racks", "Racks for nodes","la_node_rack",0,0,0,-1,0,0,0,0,0,0,offsetof(laRackPage,Racks),0);
+            ep=laAddEnumProperty(p, "trigger", "Trigger", "Trigger evaluation on event",0,0,0,0,0,offsetof(laRackPage,TriggerMode),0,0,0,0,0,0,0,0,0,0);
+            laAddEnumItemAs(ep, "ALWAYS", "Always", "Always evalueave this page",LA_PAGE_TRIGGER_ALWAYS,0);
+            laAddEnumItemAs(ep, "NONE", "None", "This page is only evaluated when called from other pages",LA_PAGE_TRIGGER_NONE,0);
+            ep=laAddEnumProperty(p, "use_script", "Use Script", "Use script instead of nodes",0,0,0,0,0,offsetof(laRackPage,UseScript),0,0,0,0,0,0,0,0,0,0);
+            laAddEnumItemAs(ep, "NODES", "Nodes", "Use nodes to express logic",0,0);
+            laAddEnumItemAs(ep, "SCRIPT", "Script", "Use scripts to express logic",1,0);
+            laAddStringProperty(p, "script", "Script", "Script content",LA_WIDGET_STRING_MULTI,0,0,0,1,offsetof(laRackPage, Script), 0,0,0,0,0);
             laAddOperatorProperty(p,"add_rack","Add Rack", "Add a rack into the page", "LA_add_rack", '+', 0);
         }
 
@@ -1567,6 +1580,8 @@ void la_RegisterInternalProps(){
         laAddSubGroup(p, "parent", "Parent", "Object parent", "tns_object",0,0,0,offsetof(tnsObject, ParentObject), 0,0,0,0,0,0,0,LA_UDF_REFER);
         laAddSubGroup(p, "children", "Children", "The Children Of This Object", "tns_child_object",0,0,0,-1, 0,0,0,0,0,0,offsetof(tnsObject, ChildObjects), 0);
         laAddSubGroup(p, "__actions__", "Actions", "Animation actions", "la_animation_action",0,0,0,-1,0,laget_CurrentAnimationAction,0,laset_CurrentAnimationAction,0,0,offsetof(tnsObject, Actions), 0);
+        laAddSubGroup(p, "drivers", "Drivers", "Driver page collection","la_driver_collection",0,0,0,offsetof(tnsObject,Drivers),0,0,0,0,0,0,0,LA_UDF_SINGLE);
+        laAddOperatorProperty(p, "add_driver_page", "Add Page", "Add a driver page","LA_add_driver_page",'+',0);
     }
     p = laAddPropertyContainer("tns_mesh_object", "Mesh Object", "Mesh object", 0,0,sizeof(tnsMeshObject), tnspost_Object, 0,2);{
         laPropContainerExtraFunctions(p,0,0,tnstouched_Object,0/*tnspropagate_Object*/,0);

+ 34 - 15
resources/la_templates.c

@@ -1542,26 +1542,45 @@ void laui_InputMapper(laUiList *uil, laPropPack *This, laPropPack *Extra, laColu
     laShowItemFull(uil,c,0,"la.input_mapping.current_page",LA_WIDGET_COLLECTION_SINGLE,0,laui_RackPage,0)->Flags|=LA_UI_FLAGS_NO_DECAL;
 }
 void lauidetached_Drivers(laPanel* p){
-    la_MakeDetachedProp(p, "la.drivers.current_page", "page");
+    la_MakeDetachedProp(p, "la.detached_view_switch", "detached");
+    la_MakeDetachedProp(p, "tns.world.root_objects", "root_object");
 }
 void laui_Drivers(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){
-    laColumn* c=laFirstColumn(uil),*cl, *cr;
-    laSplitColumn(uil,c,0.6); cl=laLeftColumn(c,0); cr=laRightColumn(c,0);
-    
-    laUiItem* b=laBeginRow(uil,cl,0,0);
-    laUiItem* b2=laOnConditionThat(uil,cl,laPropExpression(0,"la.drivers.pages"));{
-        laUiItem* b3=laOnConditionThat(uil,cl,laPropExpression(Extra,"page"));{
-            laShowItem(uil,cr,Extra,"page.name")->Expand=1;
-            laShowItem(uil,c,Extra,"LA_driver_rebuild")->Flags|=LA_UI_FLAGS_ICON;
+    laColumn* c=laFirstColumn(uil),*cl, *cr,*cll,*clr;
+    laSplitColumn(uil,c,0.35); cl=laLeftColumn(c,7); cr=laRightColumn(c,0);
+    laSplitColumn(uil,cl,0.4); cll=laLeftColumn(cl,1); clr=laRightColumn(cl,0);
+
+    laShowItemFull(uil,cll,Extra,"detached",0,0,0,0)->Flags|=LA_UI_FLAGS_HIGHLIGHT|LA_UI_FLAGS_ICON;
+    laUiItem* rb=laShowItemFull(uil,clr,Extra,"root_object",LA_WIDGET_COLLECTION_SELECTOR,0,laui_IdentifierOnly,0);
+
+    laUiItem* b2=laOnConditionThat(uil,cl,laPropExpression(&rb->PP,""));{
+
+        laUiItem* b=laBeginRow(uil,cr,0,0);
+        laUiItem* b3=laOnConditionThat(uil,cl,laPropExpression(&rb->PP,"drivers.current_page"));{
+            laShowItemFull(uil,cr,&rb->PP,"drivers.current_page",LA_WIDGET_COLLECTION_SELECTOR,0,laui_IdentifierOnly,0)
+                ->Flags|=LA_UI_COLLECTION_SIMPLE_SELECTOR;
+            laShowItem(uil,cr,&rb->PP,"drivers.current_page.name");
+            laShowItem(uil,cr,&rb->PP,"add_driver_page")->Flags|=LA_UI_FLAGS_ICON;
+            laShowSeparator(uil,cr);
+            laShowItem(uil,cr,&rb->PP,"drivers.current_page.trigger");
+            laShowItemFull(uil,cr,&rb->PP,"drivers.current_page.use_script",0,"icon=📃",0,0)
+                ->Flags|=LA_UI_FLAGS_HIGHLIGHT|LA_UI_FLAGS_CYCLE|LA_UI_FLAGS_ICON;
+        }laElse(uil,b3);{
+            laShowItem(uil,cr,&rb->PP,"add_driver_page")->Flags|=LA_UI_FLAGS_ICON;
         }laEndCondition(uil,b3);
+        laEndRow(uil,b);
+
     }laEndCondition(uil,b2);
-    laShowItem(uil,cl,0,"LA_add_driver_page")->Flags|=LA_UI_FLAGS_ICON;
-    laEndRow(uil,b);
-    b2=laOnConditionThat(uil,cr,laPropExpression(0,"la.drivers.pages"));{
-        laShowItemFull(uil,cr,Extra,"page",LA_WIDGET_COLLECTION_SELECTOR,0,0,0);
+
+    b2=laOnConditionThat(uil,c,laPropExpression(&rb->PP,"drivers.current_page"));{
+        laUiItem* b3=laOnConditionThat(uil,c,laPropExpression(&rb->PP,"drivers.current_page.use_script"));{
+            laShowItemFull(uil,c,Extra,"root_object.drivers.current_page.script",0,0,0,0)->Extra->HeightCoeff=-2;
+        }laElse(uil,b3);{
+            laShowItemFull(uil,c,Extra,"root_object.drivers.current_page",LA_WIDGET_COLLECTION_SINGLE,0,laui_RackPage,0)->Flags|=LA_UI_FLAGS_NO_DECAL;;
+        }laEndCondition(uil,b3);
+    }laElse(uil,b2);{
+        laShowLabel(uil,c,"Select or add a logic page.",0,0)->Flags|=LA_TEXT_ALIGN_CENTER;
     }laEndCondition(uil,b2);
-    
-    laShowItemFull(uil,c,Extra,"page",LA_WIDGET_COLLECTION_SINGLE,0,laui_RackPage,0)->Flags|=LA_UI_FLAGS_NO_DECAL;;
 }
 
 

+ 11 - 17
resources/la_tns_drivers.c

@@ -131,16 +131,21 @@ void tnsui_MakeTransformNode(laUiList *uil, laPropPack *This, laPropPack *Extra,
     laEndRow(uil,b);
 }
 
-
+int OPCHK_AddDriverPage(laPropPack *This, laStringSplitor *ss){
+    if (This && la_EnsureSubTarget(This->LastPs->p,0) == TNS_PC_OBJECT_GENERIC) return 1;
+    return 0;
+}
 int OPINV_AddDriverPage(laOperator* a, laEvent *e){
-    laRackPage* dp=memAcquire(sizeof(laRackPage));
+    tnsObject* ob=a->This?a->This->EndInstance:0; if(!ob || !ob->Drivers) return LA_CANCELED;
+    laRackPage* dp=memAcquireHyper(sizeof(laRackPage));
     strSafeSet(&dp->Name,"New Page");
-    lstAppendItem(&MAIN.Drivers->Pages, dp); MAIN.Drivers->CurrentPage=dp; dp->RackType=LA_RACK_TYPE_DRIVER;
-    laNotifyUsers("la.drivers.pages"); laRecordAndPush(0,"la.drivers","Add page", 0);
+    lstAppendItem(&ob->Drivers->Pages, dp);
+    memAssignRef(ob->Drivers,&ob->Drivers->CurrentPage,dp); dp->RackType=LA_RACK_TYPE_DRIVER;
+    laNotifyInstanceUsers(ob->Drivers); laRecordAndPush(a->This,"","Add driver page", 0);
     return LA_FINISHED;
 }
 int OPINV_RebuildDrivers(laOperator* a, laEvent *e){
-    laDriverRequestRebuild();
+    laGraphRequestRebuild();
     return LA_FINISHED;
 }
 
@@ -153,7 +158,7 @@ void tns_RegisterNodes(){
     laOperatorType *at;
     laEnumProp *ep;
 
-    laCreateOperatorType("LA_add_driver_page", "New Page", "Add a driver page", 0,0,0,OPINV_AddDriverPage,0,'+',0);
+    laCreateOperatorType("LA_add_driver_page", "New Page", "Add a driver page",OPCHK_AddDriverPage,0,0,OPINV_AddDriverPage,0,'+',0);
     laCreateOperatorType("LA_driver_rebuild", "Rebuild Drivers", "Rebuild drivers for evaluation",0,0,0,OPINV_RebuildDrivers,0,U'⭮',0);
 
     pc=laAddPropertyContainer("tns_transform_node", "Transform", "Transform objects",0,tnsui_TransformNode,sizeof(tnsTransformNode),lapost_Node,0,1);
@@ -184,14 +189,3 @@ void tns_RegisterNodes(){
     laNodeCategoryAddNodeTypes(LA_NODE_CATEGORY_DRIVER, &TNS_IDN_TRANSFORM,0);
 }
 
-void laDriverRequestRebuild(){ MAIN.Drivers->NeedRebuild=1; }
-void laDriverRequestEval(){ MAIN.Drivers->NeedEval=1; }
-
-int la_RunDrivers(){
-    MAIN.Drivers->NeedEval = 0;
-    return laRunPage(MAIN.Drivers->CurrentPage, 1);
-}
-int la_RebuildDriverEval(){
-    MAIN.Drivers->NeedRebuild = 0;
-    return laRebuildPageEval(MAIN.Drivers->CurrentPage);
-}

+ 20 - 11
resources/la_widgets.c

@@ -348,6 +348,8 @@ void la_CollectionSelectorDraw(laUiItem *ui, int h){
     real Color[16] = {0};
     tnsVector4d Transp = {0};
     int CrossDraw = 0;
+    int Simple=ui->Flags&LA_UI_COLLECTION_SIMPLE_SELECTOR;
+    if(Simple){ CrossDraw=0; }
 
     if (!ui->State) ui->State = LA_UI_NORMAL;
 
@@ -357,7 +359,9 @@ void la_CollectionSelectorDraw(laUiItem *ui, int h){
     tnsVertex2d(ui->R, ui->B); tnsVertex2d(ui->L, ui->B);
     tnsPackAs(GL_TRIANGLE_FAN);
 
-    CrossDraw = laGetActiveInstanceStrict(ui->PP.LastPs->p, ui->PP.LastPs->UseInstance) ? 1 : 0;
+    if(!Simple){
+        CrossDraw = laGetActiveInstanceStrict(ui->PP.LastPs->p, ui->PP.LastPs->UseInstance) ? 1 : 0;
+    }
 
     if (CrossDraw){
         tnsVectorCopy4d(laThemeColor(bt,LA_BT_BORDER), Transp);
@@ -366,12 +370,9 @@ void la_CollectionSelectorDraw(laUiItem *ui, int h){
         tnsMakeLinerGradient4dv(Color, 2, Transp, laThemeColor(bt,LA_BT_BORDER));
         tnsMakeLinerGradient4dv(&Color[8], 2, Transp, laThemeColor(bt,LA_BT_BORDER));
         //tnsMakeLinerGradient4dv(&Color[8], 2, laThemeColor(bt, LA_BT_BORDER), Transp);
-        tnsVertex2d(ui->R - LA_RH, ui->U);
-        tnsVertex2d(ui->R, ui->U);
-        tnsVertex2d(ui->R - LA_RH, ui->B);
-        tnsVertex2d(ui->R, ui->B);
+        tnsVertex2d(ui->R - LA_RH, ui->U); tnsVertex2d(ui->R, ui->U);
+        tnsVertex2d(ui->R - LA_RH, ui->B); tnsVertex2d(ui->R, ui->B);
         tnsColorArray4d(Color, 4);
-
         tnsPackAs(GL_TRIANGLE_STRIP);
     }
 
@@ -385,6 +386,9 @@ void la_CollectionSelectorDraw(laUiItem *ui, int h){
     if (CrossDraw){
         tnsDrawStringAuto("🧹", laThemeColor(bt,ui->State|LA_BT_TEXT), ui->R - LA_RH, ui->R, ui->U, 0);
     }
+    if(Simple){
+        tnsDrawStringAuto("⯆", laThemeColor(bt,ui->State|LA_BT_TEXT), ui->L, ui->R, ui->U, LA_TEXT_ALIGN_CENTER);
+    }
 }
 void la_EmptyDraw(laUiItem *ui, int h){
     char temp[128] = {0};
@@ -990,9 +994,10 @@ void la_MultiStringDraw(laUiItem *ui, int h){
     int NumberWidth=bt->LM;
 
 
-    if(!ui->Extra->Edit){
+    if((!ui->Extra->Edit) || (ui->Extra->Ptr1!=ui->PP.EndInstance)){
         laGetString(&ui->PP, _temp, &temp);
         strBeginEdit(&ui->Extra->Edit, temp);
+        ui->Extra->Ptr1=ui->PP.EndInstance;
     }
 
     laStringEdit* se=ui->Extra->Edit;
@@ -2729,6 +2734,7 @@ int OPMOD_CollectionSelector(laOperator *a, laEvent *e){
     int NoTooltip=ui->Flags&LA_UI_FLAGS_NO_TOOLTIP;
     int at = 0;
     int ReadOnly=laIsPropertyReadOnly(&ui->PP);
+    int Simple=ui->Flags&LA_UI_COLLECTION_SIMPLE_SELECTOR;
 
     if (a->ConfirmData /* && a->ConfirmData->Mode == LA_CONFIRM_DATA*/){
         ui->State = LA_UI_NORMAL;
@@ -2753,10 +2759,12 @@ int OPMOD_CollectionSelector(laOperator *a, laEvent *e){
         int GX = ui->L, GY = ui->B, GR = ui->R, t = 0;
         if(ReadOnly){ return LA_FINISHED; }
 
-        if (e->x >= TNS_MAX2(ui->R - LA_RH,(ui->R+ui->L)/2) && e->x < ui->R){
-            laSetActiveInstance(ui->PP.LastPs->p, ui->PP.LastPs->UseInstance, 0);
-            laRecordAndPushProp(&ui->PP,0); laMarkPropChanged(&ui->PP);
-            return LA_FINISHED;
+        if(!Simple){
+            if (e->x >= TNS_MAX2(ui->R - LA_RH,(ui->R+ui->L)/2) && e->x < ui->R){
+                laSetActiveInstance(ui->PP.LastPs->p, ui->PP.LastPs->UseInstance, 0);
+                laRecordAndPushProp(&ui->PP,0); laMarkPropChanged(&ui->PP);
+                return LA_FINISHED;
+            }
         }
 
         laLocalToWindow(a, a->ToPanel, &GX, &GY);
@@ -2820,6 +2828,7 @@ int OPMOD_NodeSocket(laOperator *a, laEvent *e){
 
     if ((!uit->Dragging) && (!laIsInUiItem(ui, e->x, e->y))){ return LA_FINISHED_PASS; }
 
+    if (e->Type==LA_TIME_IDLE){ return LA_RUNNING_PASS; }
     if (e->Type == LA_L_MOUSE_DOWN){
         uit->Dragging=1; MAIN.NextWireColor+=3;
         if(pc==LA_PC_SOCKET_IN)   {