*/}}
Browse Source

Play duplicate basics

YimingWu 1 year ago
parent
commit
f4e8bf86e7
8 changed files with 161 additions and 117 deletions
  1. 5 10
      la_interface.h
  2. 13 10
      la_tns.h
  3. 45 14
      la_tns_kernel.c
  4. 2 2
      resources/la_modelling.c
  5. 4 4
      resources/la_properties.c
  6. 1 2
      resources/la_templates.c
  7. 84 66
      resources/la_widgets.c
  8. 7 9
      resources/la_widgets_viewers.c

+ 5 - 10
la_interface.h

@@ -912,17 +912,14 @@ STRUCTURE(laCanvasExtra){
 
     laUiItem *ParentUi;
 
-    real ZoomX;
-    real ZoomY;
+    real ZoomX,ZoomY;
 
-    real PanX;
-    real PanY;
+    real PanX,PanY;
 
     int DrawCursor;
     real OnX, TargetX;
     real OnY, TargetY;
-    real ClickedX;
-    real ClickedY;
+    real ClickedX,ClickedY;
 
     int LW,ShowLegend,UiMode;
 
@@ -948,18 +945,16 @@ STRUCTURE(laCanvasExtra){
 
     //3d==========
 
-
     tnsOffscreen *OffScrShadow;
 
     tnsCamera *ViewingCamera; //Always create this one;
     tnsCamera *UsingCamera;
     int Layers[20];
-    int DisplayMode;
+
+    int AsPlayer;
 
     int ShowFloorGrid;
     int ShowAxis[3];
-
-    int LineDrawingMode;
 };
 
 NEED_STRUCTURE(laUiConditionNode);

+ 13 - 10
la_tns.h

@@ -420,7 +420,8 @@ typedef struct _tnsObject tnsObject;
 #define TNS_OBJECT_LIGHT  (1<<2)
 #define TNS_OBJECT_MESH   (1<<3)
 
-#define TNS_OBJECT_FLAGS_SELECTED 1
+#define TNS_OBJECT_FLAGS_SELECTED (1<<0)
+#define TNS_OBJECT_FLAGS_PLAY_DUPLICATE (1<<1)
 
 NEED_STRUCTURE(tnsBatch)
 
@@ -429,7 +430,7 @@ NEED_STRUCTURE(tnsBatch)
 #define TNS_EVAL_LAYER_OUTLINE (1<<2)
 #define TNS_EVAL_LAYER_SELECTION (1<<3)
 
-#define TNS_EvAL_MODE_INIT   (1<<0)
+#define TNS_EVAL_MODE_INIT   (1<<0)
 #define TNS_EVAL_MODE_ALWAYS (1<<1)
 #define TNS_EvAL_MODE_DEINIT (1<<2)
 
@@ -457,7 +458,7 @@ STRUCTURE(tnsEvaluatedInstance){
 };
 STRUCTURE(tnsEvaluateData){
     int Done;
-    int EvaluateMode;
+    int SceneEvaluateMode;
     tnsObject *Active;
     int FillOutline;
     int FillSelectionID;
@@ -505,8 +506,6 @@ STRUCTURE(tnsObject){
     tnsMatrix44d GlobalTransform;
     tnsMatrix44d SelfTransform;
     tnsMatrix44d DeltaTransform;
-    tnsMatrix44d InstanceTransform;
-    //tnsMatrix44d CameraTransform;
 
     tnsObject *Active;  // may be used to store last select info in child objects.
     tnsObject *InRoot;
@@ -518,6 +517,8 @@ STRUCTURE(tnsObject){
     laListHandle Actions;
 
     tnsEvaluateData Evaluated; // runtime
+    tnsEvaluateData EvaluatedPlay;
+    tnsObject* PlayDuplicate;
 };
 
 NEED_STRUCTURE(laNodeInSocket);
@@ -573,8 +574,7 @@ struct _tnsMaterial
 STRUCTURE(tnsInstancer){
     tnsObject Base;
     
-    tnsObject* DefaultInstance;
-    tnsObject* RuntimeInstance;
+    tnsObject* Instance;
 };
 
 STRUCTURE(tnsCamera){
@@ -979,7 +979,7 @@ void tnsSelfTransformValueChanged(tnsObject* o);
 void tnsDeltaTransformValueChanged(tnsObject* o);
 void tnsGlobalTransformValueChanged(tnsObject* o);
 
-void tnsExtractDeltaTransformValue(tnsObject *o);
+void tnsExtrtnsEnsurePlayDuplicateactDeltaTransformValue(tnsObject *o);
 void tnsExtractSelfTransformValue(tnsObject *o);
 void tnsExtractGlobalTransformValue(tnsObject *o);
 
@@ -1111,11 +1111,14 @@ void tnsApplyModelMatrix(tnsMatrix44d m);
 
 void tnsLookAt(tnsObject *o, tnsVector3d Target, tnsVector3d Up);
 
+tnsObject* tnsEnsurePlayDuplicate(tnsObject* o);
+void tnsFreePlayDuplicate(tnsObject* o);
+
 void tnsInvalidateEvaluation(tnsObject* o);
 void tnsFreeEvaluatedArray(tnsEvaluateData* ed);
 void tnsEvaluateThisObject(tnsObject *o, tnsEvaluateData* ed);
 void tnsSetObjectTreeEvaluationArgs(tnsObject* from, tnsObject* Active, int FillOutline, int FillSelectionID);
-void tnsEvaluateObjectTree(tnsObject* from, tnsEvaluateData* UseED);
+void tnsEvaluateObjectTree(tnsObject* from, tnsEvaluateData* UseED, int EvaluatePlay);
 void tnsAddEvaluatedInstance(tnsEvaluateData* ed, tnsObject* ob, tnsDrawEvaluatedInstanceF Draw, int Layer, 
     int IsActive, int MeshSelectionType, int InstanceSelectionID);
 void tnsDrawLayer(tnsEvaluateData* ed,int Layer,void* CustomData);
@@ -1127,7 +1130,7 @@ void tnsEvaluateSyncNode(tnsEvaluateData* ed, tnsObject* ob);
 void tnsEnsureEvalueatedScene(tnsEvaluateData* ed, tnsObject* root);
 void tnsPrintEvaluatedNode(tnsEvaluatedNode* en,int level);
 
-void tnsDrawObjectTree(tnsObject* from, int Layers,void* CustomData);
+void tnsDrawObjectTree(tnsObject* from, int Layers,void* CustomData, int DrawRuntime);
 void tnsDrawObjectOrigins(tnsObject *from, tnsObject *active, int AllOrigins);
 void tnsDrawCursor(tnsObject* root);
 void tnsDrawScene(int W, int H, tnsObject *root);

+ 45 - 14
la_tns_kernel.c

@@ -3736,15 +3736,17 @@ void tnsEvaluateInstancerObject(tnsInstancer* o, tnsEvaluateData* ed){
     int origid=ed->OverrideID; ed->OverrideID = o->Base.SelectID;
     tnsEvaluateEmptyObject(o,ed);
     int origoutline=ed->FillOutline; ed->FillOutline=0;
-    if(o->DefaultInstance){
+    if(o->Instance){
+        tnsObject* inst=o->Instance;
+        inst=tnsEnsurePlayDuplicate(inst);
         tnsPushEvaluateMatrixWith(ed,o->Base.GlobalTransform);
-        tnsEvaluateObjectTree(o->DefaultInstance, ed);
+        tnsEvaluateObjectTree(inst, ed, ed->SceneEvaluateMode);
         tnsPopEvaluateMatrix(ed);
     }
     ed->OverrideID=origid; ed->FillOutline=origoutline;
 }
 void tnsEvaluateThisObject(tnsObject *o, tnsEvaluateData* ed){
-    if(ed->EvaluateMode){ tnsEvaluateSyncNode(ed,o); }
+    if(ed->SceneEvaluateMode){ tnsEvaluateSyncNode(ed,o); }
     if (!o->Show) return;
     switch (o->Type){
     case TNS_OBJECT_MESH: tnsEvaluateMeshObject(o, ed); break;
@@ -3754,6 +3756,29 @@ void tnsEvaluateThisObject(tnsObject *o, tnsEvaluateData* ed){
     }
 }
 
+tnsObject* tnsEnsurePlayDuplicate(tnsObject* o){
+    if(o->Flags&TNS_OBJECT_FLAGS_PLAY_DUPLICATE) return o;
+    if(o->PlayDuplicate) return o->PlayDuplicate;
+    int obsize=tnsSizeOfObject(o);
+    tnsObject* dup=memAcquireHyper(obsize);
+    memcpy(dup,o,obsize); o->PlayDuplicate=dup;
+    dup->ChildObjects.pFirst=dup->ChildObjects.pLast=0;
+    for(laListItemPointer* lip=o->ChildObjects.pFirst;lip;lip=lip->pNext){
+        tnsObject*co=lip->p; tnsEnsurePlayDuplicate(co);
+        lstAppendPointer(&dup->ChildObjects,co->PlayDuplicate);
+        co->PlayDuplicate->ParentObject=o->ParentObject?dup:0; //objects directly under root doesn't have parent object
+    }
+    dup->Flags|=TNS_OBJECT_FLAGS_PLAY_DUPLICATE;
+    return o->PlayDuplicate;
+}
+void tnsFreePlayDuplicate(tnsObject* o){
+    for(laListItemPointer* lip=o->ChildObjects.pFirst;lip;lip=lip->pNext){
+        tnsFreePlayDuplicate(lip);
+    }
+    memFree(o->PlayDuplicate);
+    o->PlayDuplicate=0;
+}
+
 void tnsAddEvaluatedInstance(tnsEvaluateData* ed, tnsObject* ob, tnsDrawEvaluatedInstanceF Draw, int Layer, 
     int IsActive, int MeshSelectionType, int InstanceSelectionID){
     tnsEvaluatedInstance* ei;
@@ -3839,10 +3864,11 @@ void tnsPrintEvaluatedNode(tnsEvaluatedNode* en,int level){
     }
     if(level==0){printf("\n");}
 }
-void tnsEvaluateObjectTree(tnsObject* from, tnsEvaluateData* UseED){
+void tnsEvaluateObjectTree(tnsObject* from, tnsEvaluateData* UseED, int EvaluatePlay){
     if(!from) return;
-    tnsEvaluateData* ed=UseED?UseED:(from->InRoot?(&from->InRoot->Evaluated):(&from->Evaluated));
-    //ed->EvaluateMode=TNS_EVAL_MODE_ALWAYS;
+    tnsObject* UseRoot=from->InRoot?from->InRoot:from;
+    tnsEvaluateData* ed=UseED?UseED:(EvaluatePlay?&UseRoot->EvaluatedPlay:&UseRoot->Evaluated);
+    ed->SceneEvaluateMode=EvaluatePlay;
     if(ed->Done) return;
     elif(!UseED){ ed->NextCommand=ed->NextOverlay=ed->NextSelection=ed->NextOutline=ed->NextMat=0;
         if(!ed->Commands) arrInitLength(&ed->Commands,16,&ed->MaxCommand,sizeof(tnsEvaluatedInstance));
@@ -3853,21 +3879,25 @@ void tnsEvaluateObjectTree(tnsObject* from, tnsEvaluateData* UseED){
         tnsLoadIdentity44d(ed->MatArr[0]); ed->NextMat=1;
     }
     tnsEvaluatedNode* CP,*CC;
-    if(ed->EvaluateMode){ if(!UseED){ tnsEnsureEvalueatedScene(ed,from); }
+    if(ed->SceneEvaluateMode){
+        from=tnsEnsurePlayDuplicate(from);
+        if(!UseED){ tnsEnsureEvalueatedScene(ed,from); }
         CP=ed->Scene->CurrentParent; CC=ed->Scene->CurrentChild;
     }
 
     tnsEvaluateThisObject(from, ed);
     
-    if(ed->EvaluateMode){ ed->Scene->CurrentParent=ed->Scene->CurrentChild; ed->Scene->CurrentChild=ed->Scene->CurrentParent->Children.pFirst; }
+    if(ed->SceneEvaluateMode){ ed->Scene->CurrentParent=ed->Scene->CurrentChild; ed->Scene->CurrentChild=ed->Scene->CurrentParent->Children.pFirst; }
 
     for (laListItemPointer* lip=from->ChildObjects.pFirst;lip;lip=lip->pNext){
-        tnsObject *o=lip->p; if (o){ tnsEvaluateObjectTree(o,ed); }
-        if(ed->EvaluateMode){ ed->Scene->CurrentChild=ed->Scene->CurrentChild?ed->Scene->CurrentChild->Item.pNext:0; }
+        tnsObject *o=lip->p; if (o){ tnsEvaluateObjectTree(o,ed,EvaluatePlay); }
+        if(ed->SceneEvaluateMode){ ed->Scene->CurrentChild=ed->Scene->CurrentChild?ed->Scene->CurrentChild->Item.pNext:0; }
     }
 
-    if(ed->EvaluateMode){ tnsEvaluateSyncNode(ed, 0); ed->Scene->CurrentParent=CP; ed->Scene->CurrentChild=CC; }
-    if(!UseED){ ed->Done=1; /* tnsPrintEvaluatedNode(ed->Scene->Root,0); */  }
+    if(ed->SceneEvaluateMode){ tnsEvaluateSyncNode(ed, 0); ed->Scene->CurrentParent=CP; ed->Scene->CurrentChild=CC; }
+    if(!UseED){ ed->Done=1;
+        if(ed->Scene){ tnsPrintEvaluatedNode(ed->Scene->Root,0);}
+    }
 }
 void tnsDrawLayer(tnsEvaluateData* ed,int Layer,void* CustomData){
     tnsEvaluatedInstance* ei; int next=0;
@@ -3883,9 +3913,10 @@ void tnsDrawLayer(tnsEvaluateData* ed,int Layer,void* CustomData){
         ei++;
     }
 }
-void tnsDrawObjectTree(tnsObject* from, int Layers,void* CustomData){
+void tnsDrawObjectTree(tnsObject* from, int Layers,void* CustomData, int DrawRuntime){
     if(!from) return;
-    tnsEvaluateData* ed=&from->Evaluated; if(!ed->Done) return;
+    tnsEvaluateData* ed=DrawRuntime?&from->EvaluatedPlay:&from->Evaluated;
+    if(!ed->Done) return;
     if(Layers&TNS_EVAL_LAYER_SOLID){ tnsDrawLayer(ed,TNS_EVAL_LAYER_SOLID,CustomData); }
     if(Layers&TNS_EVAL_LAYER_OUTLINE){ tnsDrawLayer(ed,TNS_EVAL_LAYER_OUTLINE,CustomData);}
     if(Layers&TNS_EVAL_LAYER_OVERLAY){ tnsDrawLayer(ed,TNS_EVAL_LAYER_OVERLAY,CustomData);}

+ 2 - 2
resources/la_modelling.c

@@ -118,8 +118,8 @@ void la_PopulateSelectDataObjects(MSelectData* sd, tnsObject* root, tnsCamera* c
     tnsApplyCameraView(w,h,camera);
     glClearColor(0,0,0,0); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
     glEnable(GL_DEPTH_TEST);
-    tnsInvalidateEvaluation(root); tnsSetObjectTreeEvaluationArgs(root,root->Active,1,1); tnsEvaluateObjectTree(root,0);
-    tnsDrawObjectTree(root,TNS_EVAL_LAYER_SELECTION,0);
+    tnsInvalidateEvaluation(root); tnsSetObjectTreeEvaluationArgs(root,root->Active,1,1); tnsEvaluateObjectTree(root,0,0);
+    tnsDrawObjectTree(root,TNS_EVAL_LAYER_SELECTION,0,0);
     glDisable(GL_DEPTH_TEST);
     tnsEnableShaderv(T->immShader);
 }

+ 4 - 4
resources/la_properties.c

@@ -540,8 +540,8 @@ void *tnsget_World(void *unused,void *unused2){
 }
 void *tnsread_World(void *unused, void *inst){
 }
-void tnsset_InstancerDefaultInstance(tnsInstancer *o, tnsObject* value){
-    o->DefaultInstance=value; tnsInvalidateEvaluation(o); laNotifyUsers("tns.world");
+void tnsset_InstancerInstance(tnsInstancer *o, tnsObject* value){
+    o->Instance=value; tnsInvalidateEvaluation(o); laNotifyUsers("tns.world");
 }
 void *tnsget_detached_FirstRootObject(void *UNUSED1, void *UNUSED2){
     return T->World->RootObjects.pFirst;
@@ -1037,8 +1037,8 @@ void la_RegisterTNSProps(){
         TNS_PC_OBJECT_INSTANCER=p;
         laAddStringProperty(p, "name", "Object Name", "The Name Of The Object", 0,0,0,0,1, offsetof(tnsObject, Name), 0,0,0,0,LA_AS_IDENTIFIER);
         laAddSubGroup(p, "base", "Base", "Object base", "tns_object",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
-        laAddSubGroup(p, "default_instance", "Instance", "Default instance to be used during editing", "tns_object",0,0,0,offsetof(tnsInstancer, DefaultInstance),tnsget_detached_FirstRootObject,0,laget_ListNext,tnsset_InstancerDefaultInstance,0,0,0,LA_UDF_REFER);
-        laAddSubGroup(p, "runtime_instance", "Runtime Instance", "Runtime instance, not saved", "tns_object",0,0,0,offsetof(tnsInstancer, RuntimeInstance),0,0,0,0,0,0,0,LA_UDF_REFER|LA_UDF_IGNORE|LA_READ_ONLY);
+        laAddSubGroup(p, "instance", "Instance", "Root object to be referenced", "tns_object",0,0,0,offsetof(tnsInstancer, Instance),tnsget_detached_FirstRootObject,0,laget_ListNext,tnsset_InstancerInstance,0,0,0,LA_UDF_REFER);
+        //laAddSubGroup(p, "runtime_instance", "Runtime Instance", "Runtime instance, not saved", "tns_object",0,0,0,offsetof(tnsInstancer, RuntimeInstance),0,0,0,0,0,0,0,LA_UDF_REFER|LA_UDF_IGNORE|LA_READ_ONLY);
     }
     p = laAddPropertyContainer("tns_mesh_object", "Mesh Object", "Mesh object", 0,tnsui_MeshObjectProperties,sizeof(tnsMeshObject), tnspost_Object, 0,2);{
         laPropContainerExtraFunctions(p,0,0,tnstouched_Object,0/*tnspropagate_Object*/,0);

+ 1 - 2
resources/la_templates.c

@@ -1669,8 +1669,7 @@ void tnsui_MeshObjectProperties(laUiList *uil, laPropPack *This, laPropPack *UNU
 void tnsui_InstancerObjectProperties(laUiList *uil, laPropPack *This, laPropPack *UNUSED_Extra, laColumn *UNUSED_Colums, int context){
     laColumn* c=laFirstColumn(uil), *cl,*cr;
     laSplitColumn(uil,c,0.5); cl=laLeftColumn(c,5); cr=laRightColumn(c,0);
-    laShowLabel(uil,cl,"Instance",0,0); laShowItemFull(uil,cr,This,"default_instance",LA_WIDGET_COLLECTION_SELECTOR,0,laui_IdentifierOnly,0);
-    laShowLabel(uil,cl,"Runtime",0,0); laShowItemFull(uil,cr,This,"runtime_instance",LA_WIDGET_COLLECTION_SELECTOR,0,laui_IdentifierOnly,0);
+    laShowLabel(uil,cl,"Instance",0,0); laShowItemFull(uil,cr,This,"instance",LA_WIDGET_COLLECTION_SELECTOR,0,laui_IdentifierOnly,0);
 }
 void tnsui_BaseObjectProperties(laUiList *uil, laPropPack *This, laPropPack *UNUSED_Extra, laColumn *UNUSED_Colums, int context){
     laColumn* c=laFirstColumn(uil); laUiItem* g; laUiList* gu; laColumn* gc,*gcl,*gcr;

+ 84 - 66
resources/la_widgets.c

@@ -2727,79 +2727,97 @@ int OPMOD_TabSelector(laOperator *a, laEvent *e){
     
     return LA_RUNNING_PASS;
 }
-int OPMOD_Collection(laOperator *a, laEvent *e){
-    laUiItem *ui = a->Instance;
-    laGeneralUiExtraData *uit = a->CustomData;
-    laListHandle Locals = {0};
-    laUiList *uil;
-    int lx = e->x, ly = e->y;
-    int at = 0;
-    laUiList* ToUil = a->ToPanel->MenuRefer?a->ToPanel->MenuRefer:&a->ToPanel->UI;
-
-    if (!laIsInUiItem(ui, e->x, e->y) /* || e->y>(ui->Subs.pFirst?((laUiList*)ui->Subs.pFirst)->HeightCoeff:10000)*/){
-        return LA_FINISHED_PASS;
-    }
-
-    laLocalToPanel(a, &lx, &ly); if(a->ToPanel && ly<a->ToPanel->TitleBar.B){ return LA_FINISHED_PASS; }
-    uil = la_DetectUiListRecursive(ToUil, lx, ly, 10000, 0, 0, 0, 0, 0);
-    if (uil != ((laUiListDrawItem *)a->LocalUiLists.pFirst)->Target){
-        //printf("EXIT\n");
-        return LA_FINISHED;
-    }
-
-    if (e->Type & LA_MOUSE_EVENT){
-        laUiList *sub;
-        laUiItem *tui;
-        int LimHeight = 10000;
-        int UIB = ui->B, UIU = ui->U;
-        int t = 0;
-        void *Active = ui->PP.EndInstance;
-        if (ui->Subs.pFirst) LimHeight = (int)((laUiList *)ui->Subs.pFirst)->HeightCoeff;
-        if (LimHeight > 0) UIB = LimHeight;
-        laPanelToLocal(a, &t, &UIB);
-        for (sub = ui->Subs.pFirst; sub; sub = sub->Item.pNext){
-            ui->PP.EndInstance = sub->Instance;
-            if ((tui = la_DetectUiItemRecursive(sub, e->x, e->y, UIB, &Locals, 0))){
-                if (tui && !a->Child && tui->Type->OperatorType){
-                    //printf("invui %d\n", tui);
-                    laSetOperatorLocalizer(a->ToPanel);
-                    laInvokeUiP(a, tui->Type->OperatorType, e, tui, &Locals, 0);
-                }
-            }
-            lstClearPointer(&Locals);
+int OPMOD_Collection(laOperator *a, laEvent *e) {
+  laUiItem *ui = a->Instance;
+  laGeneralUiExtraData *uit = a->CustomData;
+  laListHandle Locals = {0};
+  laUiList *uil;
+  int lx = e->x, ly = e->y;
+  int at = 0;
+  laUiList *ToUil =
+      a->ToPanel->MenuRefer ? a->ToPanel->MenuRefer : &a->ToPanel->UI;
+
+  if (!laIsInUiItem(ui, e->x, e->y) /* || e->y>(ui->Subs.pFirst?((laUiList*)ui->Subs.pFirst)->HeightCoeff:10000)*/){
+    return LA_FINISHED_PASS;
+  }
+
+  laLocalToPanel(a, &lx, &ly);
+  if (a->ToPanel && ly < a->ToPanel->TitleBar.B) {
+    return LA_FINISHED_PASS;
+  }
+  uil = la_DetectUiListRecursive(ToUil, lx, ly, 10000, 0, 0, 0, 0, 0);
+  if (uil != ((laUiListDrawItem *)a->LocalUiLists.pFirst)->Target) {
+    // printf("EXIT\n");
+    return LA_FINISHED;
+  }
+
+  if (e->Type & LA_MOUSE_EVENT) {
+    laUiList *sub;
+    laUiItem *tui;
+    int LimHeight = 10000;
+    int UIB = ui->B, UIU = ui->U;
+    int t = 0;
+    void *Active = ui->PP.EndInstance;
+    if (ui->Subs.pFirst)
+      LimHeight = (int)((laUiList *)ui->Subs.pFirst)->HeightCoeff;
+    if (LimHeight > 0)
+      UIB = LimHeight;
+    laPanelToLocal(a, &t, &UIB);
+    for (sub = ui->Subs.pFirst; sub; sub = sub->Item.pNext) {
+      ui->PP.EndInstance = sub->Instance;
+      if ((tui = la_DetectUiItemRecursive(sub, e->x, e->y, UIB, &Locals, 0))) {
+        if (tui && !a->Child && tui->Type->OperatorType) {
+          // printf("invui %d\n", tui);
+          laSetOperatorLocalizer(a->ToPanel);
+          laInvokeUiP(a, tui->Type->OperatorType, e, tui, &Locals, 0);
         }
-        ui->PP.EndInstance = Active;
+      }
+      lstClearPointer(&Locals);
     }
+    ui->PP.EndInstance = Active;
+  }
 
-    if (e->Type == LA_L_MOUSE_DOWN && (!laIsPropertyReadOnly(&ui->PP)) && ui->Type!=_LA_UI_COLLECTION_SINGLE){
-        laUiList *uil;
-        for (uil = ui->Subs.pFirst; uil; uil = uil->Item.pNext){
-            if (a->ConfirmData) return LA_RUNNING_PASS;
-            if (laIsInBound(e->x, e->y, uil->L, uil->R, uil->U, uil->B)){
-                laRecalcCurrentPanel();
-                laPropPack PP={0}; la_CopyPropPack(&ui->PP, &PP); //needed because layout can be switched after set active.
-                char* cmd; if ((!(cmd = strGetArgumentString(ui->Instructions, "feedback"))) || (!strSame(cmd, "NONE"))) {
-                    laConfirmInt(a, 0, LA_CONFIRM_DATA);
-                }
-                laSetActiveInstance(ui->PP.LastPs->p, ui->PP.LastPs->UseInstance, uil->Instance);
-                laRecordAndPushProp(&PP,0); laMarkPropChanged(&PP);
-                return LA_RUNNING_PASS;
-            }
+  if (e->Type == LA_L_MOUSE_DOWN && (!laIsPropertyReadOnly(&ui->PP)) &&
+      ui->Type != _LA_UI_COLLECTION_SINGLE) {
+    laUiList *uil;
+    for (uil = ui->Subs.pFirst; uil; uil = uil->Item.pNext) {
+      if (a->ConfirmData)
+        return LA_RUNNING_PASS;
+      if (laIsInBound(e->x, e->y, uil->L, uil->R, uil->U, uil->B)) {
+        laRecalcCurrentPanel();
+        laPropPack PP = {0};
+        la_CopyPropPack(
+            &ui->PP,
+            &PP); // needed because layout can be switched after set active.
+        char *cmd;
+        if ((!(cmd = strGetArgumentString(ui->Instructions, "feedback"))) ||
+            (!strSame(cmd, "NONE"))) {
+          laConfirmInt(a, 0, LA_CONFIRM_DATA);
         }
-        return LA_RUNNING;
+        laSetActiveInstance(ui->PP.LastPs->p, ui->PP.LastPs->UseInstance,
+                            uil->Instance);
+        laRecordAndPushProp(&PP, 0);
+        laMarkPropChanged(&PP);
+        return LA_RUNNING_PASS;
+      }
     }
-    elif (e->Type == LA_R_MOUSE_DOWN) {
-        laUiList* uil;
-        for (uil = ui->Subs.pFirst; uil; uil = uil->Item.pNext) {
-            if (laIsInBound(e->x, e->y, uil->L, uil->R, uil->U, uil->B)) {
-                ui->PP.EndInstance=uil->Instance; lx=e->x, ly=e->y; laLocalToWindow(a,a->ToPanel,&lx,&ly);
-                laEnablePropertyPanel(a->ToPanel,a,0,0,laui_IdentifierOnly,&ui->PP,lx,lx,ly,0,0,e);
-            }
-        }
-        return LA_RUNNING;
+    return LA_RUNNING;
+  }
+  elif (e->Type == LA_R_MOUSE_DOWN) {
+    laUiList *uil;
+    for (uil = ui->Subs.pFirst; uil; uil = uil->Item.pNext) {
+      if (laIsInBound(e->x, e->y, uil->L, uil->R, uil->U, uil->B)) {
+        ui->PP.EndInstance = uil->Instance;
+        lx = e->x, ly = e->y;
+        laLocalToWindow(a, a->ToPanel, &lx, &ly);
+        laEnablePropertyPanel(a->ToPanel, a, 0, 0, laui_IdentifierOnly, &ui->PP,
+                              lx, lx, ly, 0, 0, e);
+      }
     }
+    return LA_RUNNING;
+  }
 
-    return LA_RUNNING_PASS;
+  return LA_RUNNING_PASS;
 }
 int OPMOD_CollectionSelector(laOperator *a, laEvent *e){
     laUiItem *ui = a->Instance;

+ 7 - 9
resources/la_widgets_viewers.c

@@ -121,7 +121,7 @@ void la_RootObjectDraw(laBoxedTheme *bt, tnsObject *root, laUiItem* ui){
         //tnsVertexArray3d(p, 4); tnsPackAs(GL_TRIANGLE_FAN);
 
         //tnsUseNoTexture();
-        //if (!e->LineDrawingMode && e->ShowFloorGrid){
+        //if (e->ShowFloorGrid){
         //    tnsColor4dv(laThemeColor(bt,LA_BT_BORDER));
         //    tnsDrawFloor(e->ViewingCamera->Base.GLocation, e->ViewingCamera->ZMax, e->ShowAxis);
         //    tnsFlush();
@@ -154,25 +154,25 @@ void la_RootObjectDraw(laBoxedTheme *bt, tnsObject *root, laUiItem* ui){
 
     if(root){
         tnsSetObjectTreeEvaluationArgs(root,root->Active,1,1);
-        tnsEvaluateObjectTree(root, 0);
+        tnsEvaluateObjectTree(root,0, e->AsPlayer?TNS_EVAL_MODE_ALWAYS:0);
 
         glEnable(GL_DEPTH_TEST); glDisable(GL_BLEND);
 
         tnsUseShader(T->immShader); tnsEnableShaderv(T->immShader); tnsUseNoTexture();
         tnsUnbindTexture(); tnsUniformUseTexture(T->immShader,0,0); tnsUseMultiplyColor(0);
-        tnsDrawObjectTree(root,TNS_EVAL_LAYER_SOLID,0);
+        tnsDrawObjectTree(root,TNS_EVAL_LAYER_SOLID,0,e->AsPlayer);
         
         glLineWidth(3); 
         tnsUniformUseOffset(T->immShader,1);
         glDepthMask(GL_FALSE); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
-        tnsDrawObjectTree(root,TNS_EVAL_LAYER_OUTLINE,0);
+        tnsDrawObjectTree(root,TNS_EVAL_LAYER_OUTLINE,0,e->AsPlayer);
         glDepthMask(GL_TRUE); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
         tnsUniformUseOffset(T->immShader,0);
         glLineWidth(1);
         glDisable(GL_POLYGON_OFFSET_LINE);
     }
 
-    if (!e->LineDrawingMode && e->ShowFloorGrid){
+    if (e->ShowFloorGrid){
         tnsUseNoTexture();
         real* color=laThemeColor(bt,LA_BT_BORDER); tnsColor4d(LA_COLOR3(color),0.4);
         tnsDrawFloor(e->ViewingCamera->Base.GLocation, e->ViewingCamera->ZMax, e->ShowAxis);
@@ -182,7 +182,7 @@ void la_RootObjectDraw(laBoxedTheme *bt, tnsObject *root, laUiItem* ui){
     la3DObjectDrawExtra de={0}; de.MeshEditType=e->SelectMode;
 
     if(e->SelectThrough){ glClear(GL_DEPTH_BUFFER_BIT); }
-    tnsDrawObjectTree(root,TNS_EVAL_LAYER_OVERLAY,&de);
+    tnsDrawObjectTree(root,TNS_EVAL_LAYER_OVERLAY,&de,e->AsPlayer);
 
     if(root){
         glDisable(GL_DEPTH_TEST);
@@ -196,7 +196,7 @@ void la_RootObjectDraw(laBoxedTheme *bt, tnsObject *root, laUiItem* ui){
     //laInvoke(0,"M_select",e,&ui->ExtraPP,0,0);
 
     //glColorMask(GL_FALSE, GL_FALSE,GL_FALSE,GL_FALSE);
-    //tnsEvaluateObjectTree(e->CurrentScene, 0);
+    //tnsEvaluateObjectTree(e->CurrentScene, 0,0);
 
     tnsFlush();
     //glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
@@ -599,8 +599,6 @@ void la_3DViewInit(laUiItem *ui){
     e->ShowAxis[1] = 1;
     e->ShowFloorGrid = 1;
 
-    //e->DisplayMode = LA_3D_VIEW_DISPLAY_WIRE;
-
     e->HeightCoeff = 10;
 
     laFirstColumn(laAddTabPage(ui, "New Group"));