*/}}
Bläddra i källkod

Keyboard driver trigger

YimingWu 1 år sedan
förälder
incheckning
87b3b2e0aa
8 ändrade filer med 157 tillägg och 91 borttagningar
  1. 1 1
      la_data.c
  2. 7 3
      la_interface.h
  3. 1 1
      la_kernel.c
  4. 5 0
      la_tns.h
  5. 11 5
      la_tns_kernel.c
  6. 47 2
      resources/la_nodes_basic.c
  7. 4 2
      resources/la_properties.c
  8. 81 77
      resources/la_templates.c

+ 1 - 1
la_data.c

@@ -1838,7 +1838,7 @@ laEnumItem *laGetEnumFromIdentifier(laEnumProp *p, char *Identifier){
     for (ei = p->Items.pFirst; ei; ei = ei->Item.pNext){
         if (!strcmp(ei->Identifier, Identifier)) return ei;
     }
-    return 0;
+    return p->Items.pFirst;
 }
 int laEnumHasIcon(laPropPack *pp){
     laEnumProp *p = pp->LastPs->p;

+ 7 - 3
la_interface.h

@@ -327,6 +327,7 @@ STRUCTURE(LA){
     u8bit LastControllerKey, LastControllerKeyDevice, ControllerHasNewKey;
     u8bit LastControllerAxis, LastControllerAxisDevice, ControllerHasNewAxis;
 
+    laEvent* CurrentInputEvent;
     laInputProcessF InputProcess;
     laListHandle Windows;
     laListHandle WastedPanels;
@@ -1624,9 +1625,6 @@ 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
-
 NEED_STRUCTURE(tnsObject)
 STRUCTURE(laRackPage){
     laListItem Item;
@@ -1651,6 +1649,12 @@ STRUCTURE(laNodeRack){
     int RackType;
     laNodeRack* Duplicated;
 };
+STRUCTURE(laKeyboardNode){
+    laBaseNode Base;
+    laNodeOutSocket* IsKey; int iIsKey;
+    laNodeOutSocket* KeyDown; int iKeyDown;
+    laNodeOutSocket* Key; int iKey;
+};
 NEED_STRUCTURE(laInputControllerNode);
 STRUCTURE(laInputControllerNodeSocket){
     laInputControllerNode* Parent;

+ 1 - 1
la_kernel.c

@@ -7382,7 +7382,7 @@ int la_HandleSingleEvent(laEvent *e, laListHandle *Operators){
     int Result = 0;
     laConfirmData *ConfirmData = 0, *NextConfirmData = 0;
 
-    if(MAIN.InputProcess){ MAIN.InputProcess(e); }
+    if(MAIN.InputProcess){ MAIN.CurrentInputEvent=e; MAIN.InputProcess(e); MAIN.CurrentInputEvent=0; }
 
     a = Operators->pFirst;
 

+ 5 - 0
la_tns.h

@@ -583,6 +583,11 @@ NEED_STRUCTURE(laNodeInSocket);
 NEED_STRUCTURE(laNodeOutSocket);
 NEED_STRUCTURE(laAction);
 
+#define TNS_PAGE_TRIGGER_PROCESS 0
+#define TNS_PAGE_TRIGGER_KEYBOARD 1
+#define TNS_PAGE_TRIGGER_MOUSE 2
+#define TNS_PAGE_TRIGGER_CONTROLLER 3
+
 STRUCTURE(tnsTransformNode){
     laBaseNode Base;
     laNodeInSocket* Mat;

+ 11 - 5
la_tns_kernel.c

@@ -3908,11 +3908,11 @@ eval_inst_cleanup:
     ed->OverrideID=origid; ed->FillOutline=origoutline;
 }
 
-void tnsRunNode(tnsEvaluatedNode* en, char* func, tnsObject* root){
+void tnsRunNode(tnsEvaluatedNode* en, int func, tnsObject* root){
     T->Runtime.CurrentEN = en;
     tnsObject* ob=root; // should be the same as en->Target.
     for(laRackPage* rp=ob->Drivers->Pages.pFirst;rp;rp=rp->Item.pNext){
-        if(!rp->Eval.pFirst) continue;
+        if(!rp->Eval.pFirst || rp->TriggerMode!=func) continue;
         laRunPage(rp, 1);
     }
 }
@@ -3929,7 +3929,7 @@ void tnsEvaluateThisObject(tnsObject *o, tnsEvaluateData* ed){
             CP=ed->Scene->CurrentParent; CC=ed->Scene->CurrentChild;
             ed->Scene->CurrentParent=ed->Scene->CurrentChild; ed->Scene->CurrentChild=ed->Scene->CurrentParent->Children.pFirst;
         }elif(o->Type==TNS_OBJECT_ROOT){ tnsEvaluatedNode* en=ed->Scene->CurrentChild;
-            tnsRunNode(en,"any",o);
+            tnsRunNode(en,TNS_PAGE_TRIGGER_PROCESS,o);
 #ifdef LA_WITH_LUAJIT
             tnsLuaEnsureNode(ed->L,en->LuaID,o);
             tnsLuaRunNode(ed->L,en,"run",o);
@@ -4282,10 +4282,16 @@ int tnsEvaluateObjectTreeEvent(tnsEvaluateData* ed_play, tnsEvaluatedNode* en, l
     for(tnsEvaluatedNode* lip=en->Children.pFirst;lip;lip=lip->Item.pNext){
         if(tnsEvaluateObjectTreeEvent(ed_play, lip, e)){ stop=1; }
     }
-    //tnsRunNode(en,"input",en->Target);
+    if(en->Target->Type==TNS_OBJECT_ROOT){
+        if(e->type&LA_KEYBOARD_EVENT){
+            tnsRunNode(en,TNS_PAGE_TRIGGER_KEYBOARD,en->Target);
+        }elif(e->type&LA_MOUSE_EVENT){
+            tnsRunNode(en,TNS_PAGE_TRIGGER_MOUSE,en->Target);
+        }
 #ifdef LA_WITH_LUAJIT
-    if(!stop){ return tnsLuaRunNodeEvent(ed_play->L,en,en->Target,e); }
+        if(!stop){ return tnsLuaRunNodeEvent(ed_play->L,en,en->Target,e); }
 #endif
+    }
 }
 void tnsDrawLayer(tnsEvaluateData* ed,int Layer,void* CustomData){
     tnsEvaluatedInstance* ei; int next=0;

+ 47 - 2
resources/la_nodes_basic.c

@@ -74,6 +74,43 @@ void la_PageClearBranch(laRackPage* rp, int mask);
 #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_KeyboardInit(laKeyboardNode* n, int NoCreate){
+    if(NoCreate){return;}
+    n->KeyDown=laCreateOutSocket(n,"DOWN",LA_PROP_INT); n->Key=laCreateOutSocket(n,"KEY",LA_PROP_INT);
+    n->IsKey=laCreateOutSocket(n,"IS",LA_PROP_INT);
+    strSafeSet(&n->Base.Name,"Keyboard");
+}
+void IDN_KeyboardDestroy(laKeyboardNode* n){
+    laDestroyOutSocket(n->KeyDown); laDestroyOutSocket(n->Key); laDestroyOutSocket(n->IsKey); strSafeDestroy(&n->Base.Name);
+}
+int IDN_KeyboardVisit(laKeyboardNode* n, laNodeVisitInfo* vi){
+    LA_GUARD_THIS_NODE(n,vi); LA_ADD_THIS_NODE(n,vi);
+    n->Key->Data = &n->iKey; n->KeyDown->Data = &n->iKeyDown; n->IsKey->Data=&n->iIsKey;
+    return LA_DAG_FLAG_PERM;
+}
+int IDN_KeyboardEval(laKeyboardNode* n){
+    laEvent* e=MAIN.CurrentInputEvent;
+    if(!e || !(e->type&LA_KEYBOARD_EVENT)){ n->iKey=0; n->iKeyDown=0; n->iIsKey=0; return 1; }
+    if(e->type&LA_STATE_DOWN){ n->iKeyDown=1; }else{ n->iKeyDown=0; }
+    n->iKey = e->key; n->iIsKey=1;
+    return 1;
+}
+void IDN_KeyboardCopy(laKeyboardNode* new, laKeyboardNode* old, int DoRematch){
+    if(DoRematch){ return; }
+    LA_IDN_OLD_DUPL(Key); LA_IDN_OLD_DUPL(KeyDown); LA_IDN_OLD_DUPL(IsKey);
+}
+void laui_KeyboardNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){
+    laColumn* c=laFirstColumn(uil); laKeyboardNode*n=This->EndInstance;
+    LA_BASE_NODE_HEADER(uil,c,This);
+
+    laUiItem* b=laBeginRow(uil,c,0,0);
+    laShowNodeSocket(uil,c,This,"is_key",0)->Flags|=LA_UI_SOCKET_LABEL_E;
+    laShowLabel(uil,c,"Key",0,0)->Expand=1;
+    laShowNodeSocket(uil,c,This,"key",0)->Flags|=LA_UI_SOCKET_LABEL_W;
+    laShowNodeSocket(uil,c,This,"key_down",0)->Flags|=LA_UI_SOCKET_LABEL_W;
+    laEndRow(uil,b);
+}
+
 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; }
@@ -1167,7 +1204,7 @@ void la_RegisterBasicNodes(){
     laOperatorType *at;
     laEnumProp *ep;
 
-    LA_NODE_CATEGORY_INPUT=laEnsureNodeCategory("Input",0,LA_RACK_TYPE_INPUT);
+    LA_NODE_CATEGORY_INPUT=laEnsureNodeCategory("Input",0,LA_RACK_TYPE_INPUT|LA_RACK_TYPE_DRIVER);
     LA_NODE_CATEGORY_MATH=laEnsureNodeCategory("Math",0,LA_RACK_TYPE_ALL);
     LA_NODE_CATEGORY_COLOR=laEnsureNodeCategory("Color",0,LA_RACK_TYPE_ALL);
     LA_NODE_CATEGORY_ROUTE=laEnsureNodeCategory("Route",0,LA_RACK_TYPE_ALL);
@@ -1204,6 +1241,13 @@ void la_RegisterBasicNodes(){
     laAddOperatorProperty(pc,"delete","Delete","Delete node","LA_delete_node",0,0);
     laAddSubGroup(pc,"in_rack","In Rack","The rack this node is in","la_node_rack",0,0,0,offsetof(laBaseNode,InRack),0,0,0,0,0,0,0,LA_UDF_REFER);
 
+    pc=laAddPropertyContainer("la_keyboard_node", "Keyboard Node", "Output keyboard events",0,laui_KeyboardNode,sizeof(laKeyboardNode),lapost_Node,0,1);
+    LA_PC_IDN_KEYBOARD=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,"is_key","Is Key","Is keyboard event","la_out_socket",0,0,0,offsetof(laKeyboardNode, IsKey),0,0,0,0,0,0,0,LA_UDF_SINGLE);
+    laAddSubGroup(pc,"key","Key","Key value","la_out_socket",0,0,0,offsetof(laKeyboardNode, Key),0,0,0,0,0,0,0,LA_UDF_SINGLE);
+    laAddSubGroup(pc,"key_down","Key Down","Key is down or not","la_out_socket",0,0,0,offsetof(laKeyboardNode, KeyDown),0,0,0,0,0,0,0,LA_UDF_SINGLE);
+    
     pc=laAddPropertyContainer("la_input_controller_node", "Controller output", "Output controller values",0,laui_ControllerNode,sizeof(laInputControllerNode),lapost_Node,0,1);
     LA_PC_IDN_CONTROLLER=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);
@@ -1446,6 +1490,7 @@ void la_RegisterBasicNodes(){
     laAddSubGroup(pc,"index", "Index","Index output","la_out_socket",0,0,0,offsetof(laLoopIndexNode, Out),0,0,0,0,0,0,0,LA_UDF_SINGLE);
     
 typedef laMathNode laSmallMathNode;
+    LA_IDN_REGISTER("Keyboard",U'K',LA_IDN_KEYBOARD,LA_PC_IDN_KEYBOARD, IDN_Keyboard, laKeyboardNode);
     LA_IDN_REGISTER("Controller",U'🕹',LA_IDN_CONTROLLER,LA_PC_IDN_CONTROLLER, IDN_Controller, laInputControllerNode);
     LA_IDN_REGISTER("Visualizer",U'🔍',LA_IDN_VISUALIZER,LA_PC_IDN_VISUALIZER, IDN_InputVisualizer, laInputVisualizerNode);
     LA_IDN_REGISTER("Split",U'⚟',LA_IDN_SPLIT,LA_PC_IDN_SPLIT, IDN_Split, laSplitNode);
@@ -1464,7 +1509,7 @@ typedef laMathNode laSmallMathNode;
     LA_IDN_REGISTER("Loop",0,LA_IDN_LOOP,LA_PC_IDN_LOOP, IDN_Loop, laLoopNode);
     LA_IDN_REGISTER("Loop Index",0,LA_IDN_LOOP_INDEX,LA_PC_IDN_LOOP_INDEX, IDN_LoopIndex, laLoopIndexNode);
 
-    laNodeCategoryAddNodeTypes(LA_NODE_CATEGORY_INPUT, &LA_IDN_CONTROLLER,0);
+    laNodeCategoryAddNodeTypes(LA_NODE_CATEGORY_INPUT, &LA_IDN_KEYBOARD,&LA_IDN_CONTROLLER,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, &LA_IDN_VALUES,0);
     laNodeCategoryAddNodeTypes(LA_NODE_CATEGORY_ROUTE, &LA_IDN_SPLIT, &LA_IDN_SWITCH, &LA_IDN_COMBINE, &LA_IDN_LOOP, &LA_IDN_LOOP_INDEX,0);
     laNodeCategoryAddNodeTypes(LA_NODE_CATEGORY_AUX, &LA_IDN_COMMENT, &LA_IDN_VISUALIZER,0);

+ 4 - 2
resources/la_properties.c

@@ -1607,8 +1607,10 @@ void la_RegisterInternalProps(){
                 laAddSubGroup(p, "parent_object", "Parent Object", "Parent object of this page","tns_object",0,0,0,offsetof(laRackPage,ParentObject),0,0,0,0,0,0,0,LA_READ_ONLY|LA_UDF_REFER);
             }
             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);
+            laAddEnumItemAs(ep, "PROCESS", "onProcess", "Run this page during idle frame processing of the node",TNS_PAGE_TRIGGER_PROCESS,0);
+            laAddEnumItemAs(ep, "KEYBOARD", "onKeyboard", "This page is run when keyboard event is recieved",TNS_PAGE_TRIGGER_KEYBOARD,0);
+            laAddEnumItemAs(ep, "MOUSE", "onMouse", "This page is run when mouse event is recieved",TNS_PAGE_TRIGGER_KEYBOARD,0);
+            laAddEnumItemAs(ep, "CONTROLLER", "onController", "This page is run when controller event is recieved",TNS_PAGE_TRIGGER_KEYBOARD,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,L'📃');

+ 81 - 77
resources/la_templates.c

@@ -1640,7 +1640,9 @@ void laui_DriverListItem(laUiList *uil, laPropPack *This, laPropPack *Extra, laC
     laUiItem* b=laBeginRow(uil,c,0,0);
     laShowItem(uil,c,This,"use_script")->Flags|=LA_UI_FLAGS_ICON|LA_UI_FLAGS_NO_DECAL|LA_UI_FLAGS_CYCLE;
     laShowItem(uil,c,This,"identifier")->Flags|=LA_UI_FLAGS_PLAIN;
-    laShowItem(uil,c,This,"trigger")->Flags|=LA_UI_FLAGS_PLAIN;
+    laUiItem* b4=laOnConditionThat(uil,c,laNot(laPropExpression(This,"use_script")));{
+        laShowItem(uil,c,This,"trigger")->Flags|=LA_UI_FLAGS_PLAIN;
+    }laEndCondition(uil,b4);
     laEndRow(uil,b);
 }
 void laui_Drivers(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){
@@ -1651,31 +1653,33 @@ void laui_Drivers(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *
     laShowItemFull(uil,cll,Extra,"detached",0,0,0,0)->Flags|=LA_UI_FLAGS_HIGHLIGHT|LA_UI_FLAGS_ICON;
 
 #define ADD_PAGE \
-    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"));{\
-            laUiItem* cp=laShowItemFull(uil,cr,&rb->PP,"drivers.current_page",LA_WIDGET_COLLECTION_SELECTOR,0,laui_DriverListItem,0);\
-                cp->Flags|=LA_UI_COLLECTION_SIMPLE_SELECTOR;\
-            laShowItem(uil,cr,&cp->PP,"name");\
-            laShowItem(uil,cr,&rb->PP,"add_driver_page")->Flags|=LA_UI_FLAGS_ICON|LA_UI_FLAGS_EXIT_WHEN_TRIGGERED;\
-            laShowItem(uil,cr,&cp->PP,"remove_driver_page")->Flags|=LA_UI_FLAGS_ICON;\
-            laShowSeparator(uil,cr);\
-            laShowItem(uil,cr,&cp->PP,"trigger");\
-            laShowItemFull(uil,cr,&cp->PP,"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|LA_UI_FLAGS_EXIT_WHEN_TRIGGERED;\
-        }laEndCondition(uil,b3);\
-        laEndRow(uil,b);\
-    }laEndCondition(uil,b2);\
-    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,&rb->PP,"drivers.current_page.script",0,0,0,0)->Extra->HeightCoeff=-2;\
-        }laElse(uil,b3);{\
-            laShowItemFull(uil,c,&rb->PP,"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;\
+    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"));{ \
+            laUiItem* cp=laShowItemFull(uil,cr,&rb->PP,"drivers.current_page",LA_WIDGET_COLLECTION_SELECTOR,0,laui_DriverListItem,0); \
+                cp->Flags|=LA_UI_COLLECTION_SIMPLE_SELECTOR; \
+            laShowItem(uil,cr,&cp->PP,"name"); \
+            laShowItem(uil,cr,&rb->PP,"add_driver_page")->Flags|=LA_UI_FLAGS_ICON|LA_UI_FLAGS_EXIT_WHEN_TRIGGERED; \
+            laShowItem(uil,cr,&cp->PP,"remove_driver_page")->Flags|=LA_UI_FLAGS_ICON; \
+            laShowSeparator(uil,cr); \
+            laShowItemFull(uil,cr,&cp->PP,"use_script",0,"icon=📃",0,0) \
+                ->Flags|=LA_UI_FLAGS_HIGHLIGHT|LA_UI_FLAGS_CYCLE|LA_UI_FLAGS_ICON; \
+            laUiItem* b4=laOnConditionThat(uil,cl,laNot(laPropExpression(&cp->PP,"use_script")));{ \
+                laShowItem(uil,cr,&cp->PP,"trigger"); \
+            }laEndCondition(uil,b4); \
+        }laElse(uil,b3);{ \
+            laShowItem(uil,cr,&rb->PP,"add_driver_page")->Flags|=LA_UI_FLAGS_ICON|LA_UI_FLAGS_EXIT_WHEN_TRIGGERED; \
+        }laEndCondition(uil,b3); \
+        laEndRow(uil,b); \
+    }laEndCondition(uil,b2); \
+    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,&rb->PP,"drivers.current_page.script",0,0,0,0)->Extra->HeightCoeff=-2; \
+        }laElse(uil,b3);{ \
+            laShowItemFull(uil,c,&rb->PP,"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);
 
     laUiItem* b1=laOnConditionThat(uil,c,laPropExpression(Extra,"detached"));{
@@ -1699,38 +1703,38 @@ void laui_Materials(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn
     laShowItemFull(uil,cl,Extra,"detached",0,0,0,0)->Flags|=LA_UI_FLAGS_HIGHLIGHT|LA_UI_FLAGS_ICON;
 
 #define ADD_PAGE(SEL) \
-    laUiItem* b=laBeginRow(uil,cr,0,0);\
-    laUiItem* b2=laOnConditionThat(uil,cr,laPropExpression(&rb->PP,""));{\
-        laUiItem* cp=laShowInvisibleItem(uil,cr,&rb->PP,"shader_page");\
-        if(SEL){\
-            laShowItemFull(uil,cr,&rb->PP,"",LA_WIDGET_COLLECTION_SELECTOR,0,laui_IdentifierOnly,0)\
-                ->Flags|=LA_UI_COLLECTION_SIMPLE_SELECTOR;\
-        }\
-        laShowItem(uil,cr,&rb->PP,"name");\
-        laShowItem(uil,cr,0,"M_new_material")->Flags|=LA_UI_FLAGS_ICON;\
-        laShowItem(uil,cr,&rb->PP,"remove")->Flags|=LA_UI_FLAGS_ICON;\
-        laShowSeparator(uil,cr)->Expand=1;\
-        laShowItemFull(uil,cr,&cp->PP,"use_script",0,"icon=📃;text=GLSL",0,0)\
-            ->Flags|=LA_UI_FLAGS_HIGHLIGHT|LA_UI_FLAGS_CYCLE;\
-        laShowItem(uil,cr,&rb->PP,"refresh");\
-        laShowSeparator(uil,cr);\
-        laShowItem(uil,cr,&rb->PP,"as_library")->Flags|=LA_UI_FLAGS_HIGHLIGHT|LA_UI_FLAGS_CYCLE;\
-    }laElse(uil,b2);{\
-        if(SEL){\
-            laShowItemFull(uil,cr,&rb->PP,"",LA_WIDGET_COLLECTION_SELECTOR,"text=Select",laui_IdentifierOnly,0)\
-                ->Flags|=LA_UI_COLLECTION_SIMPLE_SELECTOR|LA_UI_FLAGS_EXPAND;\
-            laShowItem(uil,cr,0,"M_new_material")->Flags|=LA_UI_FLAGS_ICON;\
-        }\
-    }laEndCondition(uil,b2);\
-    laEndRow(uil,b);\
-    b2=laOnConditionThat(uil,c,laPropExpression(&rb->PP,"shader_page"));{\
-        laUiItem* b3=laOnConditionThat(uil,c,laPropExpression(&rb->PP,"shader_page.use_script"));{\
-            laShowItemFull(uil,c,&rb->PP,"shader_page.script",0,0,0,0)->Extra->HeightCoeff=-2;\
-        }laElse(uil,b3);{\
-            laShowItemFull(uil,c,&rb->PP,"shader_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 shader page.",0,0)->Flags|=LA_TEXT_ALIGN_CENTER;\
+    laUiItem* b=laBeginRow(uil,cr,0,0); \
+    laUiItem* b2=laOnConditionThat(uil,cr,laPropExpression(&rb->PP,""));{ \
+        laUiItem* cp=laShowInvisibleItem(uil,cr,&rb->PP,"shader_page"); \
+        if(SEL){ \
+            laShowItemFull(uil,cr,&rb->PP,"",LA_WIDGET_COLLECTION_SELECTOR,0,laui_IdentifierOnly,0) \
+                ->Flags|=LA_UI_COLLECTION_SIMPLE_SELECTOR; \
+        } \
+        laShowItem(uil,cr,&rb->PP,"name"); \
+        laShowItem(uil,cr,0,"M_new_material")->Flags|=LA_UI_FLAGS_ICON; \
+        laShowItem(uil,cr,&rb->PP,"remove")->Flags|=LA_UI_FLAGS_ICON; \
+        laShowSeparator(uil,cr)->Expand=1; \
+        laShowItemFull(uil,cr,&cp->PP,"use_script",0,"icon=📃;text=GLSL",0,0) \
+            ->Flags|=LA_UI_FLAGS_HIGHLIGHT|LA_UI_FLAGS_CYCLE; \
+        laShowItem(uil,cr,&rb->PP,"refresh"); \
+        laShowSeparator(uil,cr); \
+        laShowItem(uil,cr,&rb->PP,"as_library")->Flags|=LA_UI_FLAGS_HIGHLIGHT|LA_UI_FLAGS_CYCLE; \
+    }laElse(uil,b2);{ \
+        if(SEL){ \
+            laShowItemFull(uil,cr,&rb->PP,"",LA_WIDGET_COLLECTION_SELECTOR,"text=Select",laui_IdentifierOnly,0) \
+                ->Flags|=LA_UI_COLLECTION_SIMPLE_SELECTOR|LA_UI_FLAGS_EXPAND; \
+            laShowItem(uil,cr,0,"M_new_material")->Flags|=LA_UI_FLAGS_ICON; \
+        } \
+    }laEndCondition(uil,b2); \
+    laEndRow(uil,b); \
+    b2=laOnConditionThat(uil,c,laPropExpression(&rb->PP,"shader_page"));{ \
+        laUiItem* b3=laOnConditionThat(uil,c,laPropExpression(&rb->PP,"shader_page.use_script"));{ \
+            laShowItemFull(uil,c,&rb->PP,"shader_page.script",0,0,0,0)->Extra->HeightCoeff=-2; \
+        }laElse(uil,b3);{ \
+            laShowItemFull(uil,c,&rb->PP,"shader_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 shader page.",0,0)->Flags|=LA_TEXT_ALIGN_CENTER; \
     }laEndCondition(uil,b2);
 
     laUiItem* b1=laOnConditionThat(uil,c,laPropExpression(Extra,"detached"));{
@@ -2064,28 +2068,28 @@ void tnsui_ObjectProperties(laUiList *uil, laPropPack *This, laPropPack *Extra,
     laShowItemFull(uil,c,Extra,"detached",0,0,0,0)->Flags|=LA_UI_FLAGS_HIGHLIGHT|LA_UI_FLAGS_ICON;
 
 #define ADD_PAGE1(base,path) \
-    laUiItem* rb=laShowItemFull(uil,c,base,path,LA_WIDGET_COLLECTION_SELECTOR,0,laui_IdentifierOnly,0);\
-        rb->Flags|=LA_UI_COLLECTION_SIMPLE_SELECTOR;\
-    laUiItem* b2=laOnConditionThat(uil,c,laPropExpression(&rb->PP,""));{\
-        laShowItem(uil,c,&rb->PP,"name")->Flags|=LA_UI_FLAGS_NO_DECAL;\
-        laUiItem* b3=laOnConditionThat(uil,c,laPropExpression(&rb->PP,"active"));{\
-            laShowLabel(uil,c,"⯈",0,0); laShowItem(uil,c,&rb->PP,"active.name")->Flags|=LA_UI_FLAGS_NO_DECAL;\
-        }laEndCondition(uil,b3);\
-    }laEndCondition(uil,b2);\
-    laEndRow(uil,b);\
-    b=laBeginRow(uil,c,0,0);\
-    laShowItemFull(uil,c,Extra,"page",0,0,0,0)->Flags|=LA_UI_FLAGS_EXPAND;\
-    laEndRow(uil,b);\
-    b=laOnConditionThat(uil,c,laNot(laPropExpression(Extra,"page")));{\
-        laShowItemFull(uil,c,base,path ".as_root_object",LA_WIDGET_COLLECTION_SINGLE,0,0,0)->Flags|=LA_UI_FLAGS_NO_DECAL;\
+    laUiItem* rb=laShowItemFull(uil,c,base,path,LA_WIDGET_COLLECTION_SELECTOR,0,laui_IdentifierOnly,0); \
+        rb->Flags|=LA_UI_COLLECTION_SIMPLE_SELECTOR; \
+    laUiItem* b2=laOnConditionThat(uil,c,laPropExpression(&rb->PP,""));{ \
+        laShowItem(uil,c,&rb->PP,"name")->Flags|=LA_UI_FLAGS_NO_DECAL; \
+        laUiItem* b3=laOnConditionThat(uil,c,laPropExpression(&rb->PP,"active"));{ \
+            laShowLabel(uil,c,"⯈",0,0); laShowItem(uil,c,&rb->PP,"active.name")->Flags|=LA_UI_FLAGS_NO_DECAL; \
+        }laEndCondition(uil,b3); \
+    }laEndCondition(uil,b2); \
+    laEndRow(uil,b); \
+    b=laBeginRow(uil,c,0,0); \
+    laShowItemFull(uil,c,Extra,"page",0,0,0,0)->Flags|=LA_UI_FLAGS_EXPAND; \
+    laEndRow(uil,b); \
+    b=laOnConditionThat(uil,c,laNot(laPropExpression(Extra,"page")));{ \
+        laShowItemFull(uil,c,base,path ".as_root_object",LA_WIDGET_COLLECTION_SINGLE,0,0,0)->Flags|=LA_UI_FLAGS_NO_DECAL; \
     }laElse(uil,b);
 
 #define ADD_PAGE2 \
-    laUiItem* b3=laOnConditionThat(uil,c,laPropExpression(&actui->PP,""));{\
-        tnsui_BaseObjectProperties(uil,&actui->PP,0,0,0);\
-    }laElse(uil,b3);{\
-        laShowLabel(uil,c,"No active object.",0,0)->Flags|=LA_TEXT_ALIGN_CENTER|LA_UI_FLAGS_DISABLED;;\
-    }laEndCondition(uil,b3);\
+    laUiItem* b3=laOnConditionThat(uil,c,laPropExpression(&actui->PP,""));{ \
+        tnsui_BaseObjectProperties(uil,&actui->PP,0,0,0); \
+    }laElse(uil,b3);{ \
+        laShowLabel(uil,c,"No active object.",0,0)->Flags|=LA_TEXT_ALIGN_CENTER|LA_UI_FLAGS_DISABLED;; \
+    }laEndCondition(uil,b3); \
     laEndCondition(uil,b);
 
     laUiItem* b0=laOnConditionThat(uil,c,laPropExpression(Extra,"detached"));{