*/}}
Parcourir la source

2d on 3d sort of works I guess

YimingWu il y a 1 an
Parent
commit
e44a723e91

+ 1 - 1
la_interface.h

@@ -1884,7 +1884,7 @@ void tnsui_InstancerObjectProperties(laUiList *uil, laPropPack *This, laPropPack
 void tnsui_BaseObjectProperties(laUiList *uil, laPropPack *This, laPropPack *UNUSED_Extra, laColumn *UNUSED_Colums, int context);
 void tnsui_RootObjectProperties(laUiList *uil, laPropPack *This, laPropPack *UNUSED_Extra, laColumn *UNUSED_Colums, int context);
 
-void tnsui_DefaultObjectPropUiDefine(laUiList *uil, laPropPack *This, laPropPack *OperatorProps, laColumn *UNUSED, int context);
+void tnsui_RootObjectMenuUi(laUiList *uil, laPropPack *This, laPropPack *OperatorProps, laColumn *UNUSED, int context);
 
 int OPINV_UiItem(laOperator *a, laEvent *e);
 int OPEXT_UiItem(laOperator *a, int ExitCode);

+ 1 - 1
la_kernel.c

@@ -3228,7 +3228,7 @@ laPanel *laEnablePropertyPanel(laPanel *Attachment, laOperator *a, laPropPack *O
     if (!def){
         if (This && This->LastPs->p){
             if(This->LastPs->p->UiDefine) def = This->LastPs->p->UiDefine;
-            elif(This->LastPs->p->SubProp&&This->LastPs->p->SubProp->UiDefine) def = This->LastPs->p->SubProp->UiDefine;
+            elif(This->LastPs->p->SubProp&&This->LastPs->p->SubProp->MenuUiDefine) def = This->LastPs->p->SubProp->MenuUiDefine;
         }
         if((!def) && (sub=la_EnsureSubTarget(This->LastPs->p,This->EndInstance)) && sub->MenuUiDefine) def=sub->MenuUiDefine;
         if(!def) def = FallBackUiDefine?FallBackUiDefine:laui_DefaultPropUiDefine;

+ 5 - 0
la_tns.h

@@ -251,6 +251,7 @@ struct _tnsMain {
     real SetUseHalftone;
     real SetHalftoneSize;
     float SetViewPos[3];
+    float SetViewDir[3];
     
     tnsShader* StateShader;
 
@@ -458,6 +459,7 @@ NEED_STRUCTURE(tnsBatch)
 #define TNS_EVAL_LAYER_SELECTION (1<<3)
 #define TNS_EVAL_LAYER_NO_2D     (1<<4)
 #define TNS_EVAL_LAYER_BACKDROP  (1<<5)
+#define TNS_EVAL_LAYER_SHOW_2D   (1<<6)
 
 #define TNS_EVAL_MODE_INIT   (1<<0)
 #define TNS_EVAL_MODE_ALWAYS (1<<1)
@@ -486,6 +488,7 @@ STRUCTURE(tnsEvaluatedInstance){
     int IsActive;
     int MeshSelectionType;
     int InstanceSelectionID;
+    int DrawnIn2D;
     tnsDrawEvaluatedInstanceF Draw;
 };
 STRUCTURE(tnsEvaluateData){
@@ -495,6 +498,7 @@ STRUCTURE(tnsEvaluateData){
     int FillOutline;
     int FillSelectionID;
     int OverrideID;
+    int State2D,Has2D;
     laListHandle ParentStack;
     tnsEvaluatedInstance* Backdrop; int NextBackdrop, MaxBackdrop;
     tnsEvaluatedInstance* Commands; int NextCommand, MaxCommand;
@@ -1226,6 +1230,7 @@ void tnsGetCameraProjection(tnsMatrix44d* mat, int w, int h, tnsCamera* Camera);
 void tnsGetCameraViewProjection(tnsMatrix44d* mat, int w, int h, tnsCamera* Camera);
 void tnsApplyCameraView(int W, int H, tnsCamera *Camera, tnsMatrix44d out_optional_view, tnsMatrix44d out_optional_projection);
 void tnsApplyShadowCameraView(tnsLight *Light);
+void tnsSetCameraViewDir(tnsVector3d dir);
 
 void tnsApplyModelMatrix(tnsMatrix44d m);
 

+ 26 - 12
la_tns_kernel.c

@@ -474,6 +474,7 @@ int tnsEnableShaderv(tnsShader *shader){
 
     if(s->iUseNormal) glUniform1i(s->iUseNormal,T->SetUseNormal);
     if(s->uViewPos) glUniform3fv(s->uViewPos,1,T->SetViewPos);
+    if(s->uViewDir) glUniform3fv(s->uViewDir,1,T->SetViewDir);
     if(s->iUseHalftone) glUniform1f(s->iUseHalftone,T->SetUseHalftone);
     if(s->iHalftoneSize) glUniform1f(s->iHalftoneSize,T->SetHalftoneSize);
     //if(s->iTextureMode) glUniform1i(s->iTextureMode,T->StateTextureMode);
@@ -3666,6 +3667,7 @@ void tnsApplyCameraView(int W, int H, tnsCamera *Camera, tnsMatrix44d out_option
     tnsInverse44d(inv, Camera->Base.GlobalTransform);
     tnsMultiply44d(result, mat, inv);
     memcpy(mat, result, sizeof(tnsMatrix44d));
+    tnsVector3d dir={0,0,0}; tnsSetCameraViewDir(dir);
 
     if (current_shader = T->CurrentShader){
         tnsShaderApplyView(current_shader, result);
@@ -3693,6 +3695,10 @@ void tnsApplyShadowCameraView(tnsLight *Light){
         tnsShaderApplyShadowMatrix(current_shader,mat);
     }
 }
+void tnsSetCameraViewDir(tnsVector3d dir){
+    tnsVectorSet3v(T->SetViewDir, dir);
+    if(T->BindedShader && T->BindedShader->uViewDir>-1){ glUniform3f(T->BindedShader->uViewDir,LA_COLOR3(dir)); }
+}
 
 void tnsApplyModelMatrix(tnsMatrix44d m){
     tnsShader *current_shader = 0; real *mat;
@@ -3784,20 +3790,26 @@ void tnsPushEvaluateMatrixWith(tnsEvaluateData* ed, tnsMatrix44d mat){
     tnsMultiply44d(new, ed->MatArr[ed->NextMat-1], mat);
     ed->NextMat++;
 }
+void tnsPushEvaluate2DMatrixWith(tnsEvaluateData* ed, tnsMatrix44d mat){
+    arrEnsureLength(&ed->MatArr,ed->NextMat,&ed->MaxMat,sizeof(tnsMatrix44d)); if(ed->NextMat<1) return;
+    real* new=ed->MatArr[ed->NextMat]; tnsCopyMatrix44d(mat,new); ed->NextMat++;
+}
 void tnsPopEvaluateMatrix(tnsEvaluateData* ed){ ed->NextMat--; }
 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->Instance){
-        tnsObject* inst=o->Instance;
+    if(o->Instance){ int PrevState2D=ed->State2D;
+        tnsRootObject* inst=o->Instance; if(inst->Base.Type==TNS_OBJECT_ROOT&&inst->Is2D){ ed->State2D=1; }
         if(ed->SceneEvaluateMode){ inst=tnsEnsurePlayDuplicate(inst); }
         for(laListItemPointer* lip=ed->ParentStack.pFirst;lip;lip=lip->pNext){
             if(lip->p == inst || lip->p==o->Instance){ goto eval_inst_cleanup; }
         }
-        tnsPushEvaluateMatrixWith(ed,o->Base.GlobalTransform);
+        if(ed->State2D){ tnsPushEvaluate2DMatrixWith(ed,o->Base.GlobalTransform); }
+        else{ tnsPushEvaluateMatrixWith(ed,o->Base.GlobalTransform); }
         tnsEvaluateObjectTree(inst, ed, ed->SceneEvaluateMode);
         tnsPopEvaluateMatrix(ed);
+        ed->State2D=PrevState2D;
     }
 eval_inst_cleanup:
     ed->OverrideID=origid; ed->FillOutline=origoutline;
@@ -3967,7 +3979,7 @@ void tnsAddEvaluatedInstance(tnsEvaluateData* ed, tnsObject* ob, tnsDrawEvaluate
     }else{ return; }
     ei->IsActive=IsActive; ei->MeshSelectionType=MeshSelectionType;
     ei->InstanceSelectionID=ed->OverrideID?ed->OverrideID:InstanceSelectionID;
-    ei->Draw=Draw; ei->Object=ob;
+    ei->Draw=Draw; ei->Object=ob; ei->DrawnIn2D=ed->State2D; if(ed->State2D){ ed->Has2D=1; }
     tnsMultiply44d(ei->Mat,ed->MatArr[ed->NextMat-1],ob->GlobalTransform);
 }
 void tnsFreeEvaluatedArray(tnsEvaluateData* ed){
@@ -4066,7 +4078,7 @@ void tnsEvaluateObjectTree(tnsObject* from, tnsEvaluateData* UseED, int Evaluate
         if(!ed->Overlays) arrInitLength(&ed->Overlays,16,&ed->MaxOverlay,sizeof(tnsEvaluatedInstance));
         if(!ed->Selections) arrInitLength(&ed->Selections,16,&ed->MaxSelection,sizeof(tnsEvaluatedInstance));
         if(!ed->MatArr) arrInitLength(&ed->MatArr,8,&ed->MaxMat,sizeof(tnsMatrix44d));
-        tnsLoadIdentity44d(ed->MatArr[0]); ed->NextMat=1;
+        tnsLoadIdentity44d(ed->MatArr[0]); ed->NextMat=1; ed->Has2D=0;
     }
     tnsEvaluatedNode* CP,*CC;
     if(ed->SceneEvaluateMode){
@@ -4093,7 +4105,8 @@ void tnsEvaluateObjectTree(tnsObject* from, tnsEvaluateData* UseED, int Evaluate
 }
 void tnsDrawLayer(tnsEvaluateData* ed,int Layer,void* CustomData){
     tnsEvaluatedInstance* ei; int next=0;
-    int No2D=Layer&TNS_EVAL_LAYER_NO_2D; Layer&=(~TNS_EVAL_LAYER_NO_2D);
+    int No2D=Layer&TNS_EVAL_LAYER_NO_2D; int Do2D=Layer&TNS_EVAL_LAYER_SHOW_2D;
+    Layer&=(~(TNS_EVAL_LAYER_SHOW_2D|TNS_EVAL_LAYER_NO_2D));
     if(Layer==TNS_EVAL_LAYER_SOLID){ ei=ed->Commands; next=ed->NextCommand; }
     elif(Layer==TNS_EVAL_LAYER_BACKDROP){ ei=ed->Backdrop; next=ed->NextBackdrop; }
     elif(Layer==TNS_EVAL_LAYER_OUTLINE){ ei=ed->Outlines; next=ed->NextOutline; }
@@ -4102,6 +4115,7 @@ void tnsDrawLayer(tnsEvaluateData* ed,int Layer,void* CustomData){
     else{ return; } if(!next){ return; }
     for(int i=0;i<next;i++){
         if(No2D && ei->Object->Type==TNS_OBJECT_SHAPE){ ei++; continue; }
+        if((Do2D && (!ei->DrawnIn2D)) || ((!Do2D) && ei->DrawnIn2D)){ ei++; continue; }
         tnsPushMatrix(); tnsApplyModelMatrix(ei->Mat);
         ei->Draw(ei,CustomData);
         tnsPopMatrix();
@@ -4111,12 +4125,12 @@ void tnsDrawLayer(tnsEvaluateData* ed,int Layer,void* CustomData){
 void tnsDrawObjectTree(tnsObject* from, int Layers,void* CustomData, int DrawRuntime){
     if(!from) return;
     tnsEvaluateData* ed=DrawRuntime?&from->EvaluatedPlay:&from->Evaluated;
-    if(!ed->Done) return;
-    if(Layers&TNS_EVAL_LAYER_BACKDROP){ tnsDrawLayer(ed,TNS_EVAL_LAYER_BACKDROP,CustomData); }
-    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);}
-    if(Layers&TNS_EVAL_LAYER_SELECTION){ tnsDrawLayer(ed,TNS_EVAL_LAYER_SELECTION,CustomData); }
+    if(!ed->Done) return; int Do2D=Layers&TNS_EVAL_LAYER_SHOW_2D;
+    if(Layers&TNS_EVAL_LAYER_BACKDROP){ tnsDrawLayer(ed,TNS_EVAL_LAYER_BACKDROP|Do2D,CustomData); }
+    if(Layers&TNS_EVAL_LAYER_SOLID){ tnsDrawLayer(ed,TNS_EVAL_LAYER_SOLID|Do2D,CustomData); }
+    if(Layers&TNS_EVAL_LAYER_OUTLINE){ tnsDrawLayer(ed,TNS_EVAL_LAYER_OUTLINE|Do2D,CustomData);}
+    if(Layers&TNS_EVAL_LAYER_OVERLAY){ tnsDrawLayer(ed,TNS_EVAL_LAYER_OVERLAY|Do2D,CustomData);}
+    if(Layers&TNS_EVAL_LAYER_SELECTION){ tnsDrawLayer(ed,TNS_EVAL_LAYER_SELECTION|Do2D,CustomData); }
 }
 
 void tnsDrawSingleObjectOrigin(tnsObject* o){

+ 1 - 1
resources/la_modelling.c

@@ -1911,7 +1911,7 @@ int OPINV_NewRootObject(laOperator *a, laEvent *e){
 }
 int OPCHK_RemoveRootObjects(laPropPack *This, laStringSplitor *ss){
     if(This && This->EndInstance){
-        if(la_EnsureSubTarget(This->LastPs->p,0)!=TNS_PC_OBJECT_GENERIC) return 0;
+        if(la_EnsureSubTarget(This->LastPs->p,0)!=TNS_PC_OBJECT_ROOT) return 0;
         if(((tnsObject*)This->EndInstance)->Type!=TNS_OBJECT_ROOT) return 0;
     }else{ if(!T->World->ActiveRoot) return 0; }
     return 1;

+ 4 - 5
resources/la_properties.c

@@ -1021,7 +1021,7 @@ void la_RegisterGeneralProps(){
     laAddOperatorProperty(p, "restore", "Restore Default", "Restore Default Value", "LA_string_set_default", U'⭯', 0);
     laAddOperatorProperty(p, "get_folder_path", "Get Folder Path", "Get a folder path", "LA_string_get_folder_path", U'📁', 0);
     laAddOperatorProperty(p, "get_file_path", "Get File Path", "Get a file path", "LA_string_get_file_path", U'🖹', 0);
-    p->UiDefine=laui_StringPropUiDefine;
+    p->MenuUiDefine=laui_StringPropUiDefine;
 
     p = la_SetGeneralRoot(&MAIN.GeneralOperatorSub, "__general_operator__", "Genral Operator Operations", "Genral Operator Operations");
 
@@ -1081,7 +1081,7 @@ void la_RegisterTNSProps(){
     if(!MAIN.InitArgs.HasWorldObjects) return;
 
     p = laAddPropertyContainer("tns_world", "World", "3D World Structure", 0,0,sizeof(tnsWorld),tnspost_World,0,1);{
-        sp = laAddSubGroup(p, "root_objects", "Root Objects", "List of all root objects", "tns_object",0,0,0,-1,0,0,0,0,0,0,offsetof(tnsWorld, RootObjects), 0);
+        sp = laAddSubGroup(p, "root_objects", "Root Objects", "List of all root objects", "tns_root_object",0,0,0,-1,0,0,0,0,0,0,offsetof(tnsWorld, RootObjects), 0);
         laSubGroupDetachable(sp, tnsget_detached_FirstRootObject, laget_ListNext);
         laAddSubGroup(p, "active_root", "Active Root Object", "Global active root object", "tns_object",0,0,0,offsetof(tnsWorld,ActiveRoot),tnsget_detached_FirstRootObject,0,laget_ListNext,0,0,0,0,LA_UDF_REFER);
         sp = laAddSubGroup(p, "objects", "Objects", "List of all objects", "tns_object",tnsget_ObjectType, 0,0,-1,0,0,0,0,0,0,offsetof(tnsWorld, AllObjects), 0);
@@ -1125,7 +1125,6 @@ void la_RegisterTNSProps(){
     }
 
     p = laAddPropertyContainer("tns_object", "Object", "3D Object Item", 0,tnsui_BaseObjectProperties,sizeof(tnsObject), tnspost_Object, 0,2);{
-        laPropContainerExtraFunctions(p,0,0,0,tnspropagate_Object,tnsui_DefaultObjectPropUiDefine);
         laContainerAnimationFunctions(p,laaction_VerifyRootObject);
         TNS_PC_OBJECT_GENERIC=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);
@@ -1170,12 +1169,11 @@ void la_RegisterTNSProps(){
         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|LA_HIDE_IN_SAVE);
         laAddOperatorProperty(p, "add_driver_page", "Add Page", "Add a driver page","LA_add_driver_page",'+',0);
-        laAddOperatorProperty(p, "remove_root", "Remove root", "Remove the root node","M_remove_root",L'🗴',0);
         laAddSubGroup(p, "as_mesh", "As Mesh", "As mesh object", "tns_mesh_object",0,0,0,-1,0,tnsget_ObjectAsMesh,0,0,0,0,0,LA_UDF_REFER|LA_READ_ONLY|LA_UDF_IGNORE);
         laAddSubGroup(p, "as_root_object", "As Root Object", "As root object", "tns_root_object",0,0,0,-1,0,tnsget_ObjectAsRoot,0,0,0,0,0,LA_UDF_REFER|LA_READ_ONLY|LA_UDF_IGNORE);
     }
     p = laAddPropertyContainer("tns_root_object", "Root Object", "Root object", 0, tnsui_RootObjectProperties,sizeof(tnsRootObject), 0,0,2);{
-        laPropContainerExtraFunctions(p,0,0,tnstouched_Object,0/*tnspropagate_Object*/,0);
+        laPropContainerExtraFunctions(p,0,0,tnstouched_Object,tnspropagate_Object,tnsui_RootObjectMenuUi);
         TNS_PC_OBJECT_ROOT=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);
@@ -1184,6 +1182,7 @@ void la_RegisterTNSProps(){
             laAddEnumItemAs(ep, "3D", "3D", "Root object is in 3D", 0, 0);
             laAddEnumItemAs(ep, "2D", "2D", "Root object is in 2D", 1, 0);
         }
+        laAddOperatorProperty(p, "remove_root", "Remove root", "Remove the root node","M_remove_root",L'🗴',0);
     }
     p = laAddPropertyContainer("tns_instancer", "Instancer", "Instance placeholder object", U'📎', tnsui_InstancerObjectProperties,sizeof(tnsInstancer), 0,0,2);{
         laPropContainerExtraFunctions(p,0,0,tnstouched_Object,0/*tnspropagate_Object*/,0);

+ 4 - 6
resources/la_templates.c

@@ -2018,7 +2018,7 @@ void tnsui_ObjectHierachy(laUiList *uil, laPropPack *This, laPropPack *Extra, la
     laUiItem* r=laBeginRow(uil,cr,0,0);
     laShowItemFull(uil,cr,This,"name",0,0,0,0)->Flags|=LA_UI_FLAGS_NO_DECAL;
     laEndRow(uil,r);
-    char* prop=context?"base.children":"children";
+    char* prop="base.children";
     laUiItem* b2=laOnConditionThat(uil,cl,laPropExpression(This,prop));{
         laUiItem* b=laOnConditionToggle(uil,cl,0,0,0,0,0);{ b->Flags|=LA_UI_FLAGS_NO_DECAL;
             b->State=LA_UI_ACTIVE;
@@ -2039,12 +2039,10 @@ void tnsui_WorldHierachy(laUiList *uil, laPropPack *This, laPropPack *Extra, laC
         laShowItemFull(gu,gc,0,"tns.world.root_objects",0,0,tnsui_ObjectHierachy,0)->Flags|=LA_UI_FLAGS_NO_DECAL;
     }
 }
-void tnsui_DefaultObjectPropUiDefine(laUiList *uil, laPropPack *This, laPropPack *OperatorProps, laColumn *UNUSED, int context){
+void tnsui_RootObjectMenuUi(laUiList *uil, laPropPack *This, laPropPack *OperatorProps, laColumn *UNUSED, int context){
     laColumn* c=laFirstColumn(uil);
-    char* prop=context?"base":"";
-    laUiItem* base=laShowInvisibleItem(uil,c,This,prop);
-    laShowItemFull(uil, c, &base->PP, "name",LA_WIDGET_STRING_PLAIN,0,0,0);
-    laShowItemFull(uil, c, &base->PP, "remove_root",0,0,0,0);
+    laShowItemFull(uil, c, This, "name",LA_WIDGET_STRING_PLAIN,0,0,0);
+    laShowItemFull(uil, c, This, "remove_root",0,0,0,0);
     laShowItemFull(uil, c, 0, "M_new_root",0,0,0,0);
 }
 

+ 8 - 2
resources/la_tns_shaders.cpp

@@ -671,6 +671,7 @@ uniform float HCYGamma;
 
 uniform vec3 uObjectPos;
 uniform vec3 uViewPos;
+uniform vec3 uViewDir;
 in vec4 fColor;
 in vec2 fUV;
 flat in vec3 fNormal;
@@ -725,7 +726,9 @@ void main(){
 		color.a=HalftoneSingle(color.a,htsize,rad(7),0);
 		if(color.a==0) discard;
         float light_factor=dot(fNormal,vec3(0,0,1));
-        float view=dot(fNormal,fGPos-uViewPos);
+		vec3 vd=uViewDir;
+		if(length(uViewDir)<0.5){ vd=fGPos-uViewPos; }
+        float view=dot(fNormal,vd);
         float factor=abs(light_factor);
         if(light_factor*view>0){ factor=0; }
         color=vec4(color.rgb*mix(0.2,1.,factor),color.a);
@@ -759,6 +762,7 @@ uniform float HalftoneSize;
 
 uniform vec3 uObjectPos;
 uniform vec3 uViewPos;
+uniform vec3 uViewDir;
 in vec4 fColor;
 in vec2 fUV;
 flat in vec3 fNormal;
@@ -780,7 +784,9 @@ void main(){
 		color.a=HalftoneSingle(color.a,htsize,rad(7),0);
 		if(color.a==0) discard;
         float light_factor=dot(fNormal,vec3(0,0,1));
-        float view=dot(fNormal,fGPos-uViewPos);
+		vec3 vd=uViewDir;
+		if(len(uViewDir)<0.5){ vd=fGPos-uViewPos; }
+        float view=dot(fNormal,vd);
         float factor=abs(light_factor);
         if(light_factor*view>0){ factor=0; }
         color=vec4(color.rgb*mix(0.2,1.,factor),color.a);

+ 49 - 24
resources/la_widgets_viewers.c

@@ -27,7 +27,13 @@ extern tnsFontManager *FM;
 
 void la_SetCanvasOrtho(laCanvasExtra* e,int W, int H){
     real x2=(real)W*e->ZoomX/2,y2=(real)H*e->ZoomY/2;
-    tnsOrtho(e->PanX-x2,e->PanX+x2,e->PanY-y2,e->PanY+y2,100,-100);
+    tnsOrtho(e->PanX-x2,e->PanX+x2,e->PanY-y2,e->PanY+y2,-100,100);
+    tnsVector3d dir={0,0,-1}; tnsSetCameraViewDir(dir);
+}
+void la_SetCanvasOrthoFixed(laCanvasExtra* e,int W, int H){
+    real x2=(real)W/LA_RH/2,y2=(real)H/LA_RH/2;
+    tnsOrtho(-x2,+x2,-y2,+y2,-100,100);
+    tnsVector3d dir={0,0,-1}; tnsSetCameraViewDir(dir);
 }
 void la_BeginNVG(NVGcontext* vg,laCanvasExtra* e,int W,int H, int Is2D){
     nvgBeginFrame(vg,W,H,1);
@@ -39,6 +45,13 @@ void la_BeginNVG(NVGcontext* vg,laCanvasExtra* e,int W,int H, int Is2D){
         nvgScale(vg,1,-1);
     }
 }
+void la_BeginNVGFixed(NVGcontext* vg,laCanvasExtra* e,int W,int H){
+    nvgBeginFrame(vg,W,H,1); nvgTranslate(vg,W/2,H/2); nvgScale(vg,LA_RH,LA_RH);
+}
+void la_BeginNVGDynamic(NVGcontext* vg,laCanvasExtra* e,int W,int H, int Is2D, int OverrideFixed){
+    if(OverrideFixed)la_BeginNVGFixed(vg,e,W,H);
+    else la_BeginNVG(vg,e,W,H,Is2D);
+}
 
 void la_RootObjectDrawFullscreenQuad(tnsOffscreen* DeferredOffScr,tnsCamera* c, real Aspect){
     real FOV = c->FOV;
@@ -167,32 +180,46 @@ void la_RootObjectDraw(laBoxedTheme *bt, tnsObject *root, laUiItem* ui){
     tnsPushMatrix(); tnsPopMatrix(); //those are necessary when ui is the first in list;
 
     if(root){
+        tnsPushMatrix();
         if(!e->AsPlayer){
             tnsSetObjectTreeEvaluationArgs(root,root->Active,1,1);
             tnsEvaluateObjectTree(root,0,0);
         }
 
-        la_BeginNVG(vg,e,W,H,ro->Is2D);
-        tnsDrawObjectTree(root,TNS_EVAL_LAYER_BACKDROP,&de,e->AsPlayer);
-        nvgEndFrame(vg); tnsRestoreFromNanoVG();
-        la_BeginNVG(vg,e,W,H,ro->Is2D);
-
-        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,&de,e->AsPlayer);
-        
-        glLineWidth(7); 
-        tnsUniformUseOffset(T->immShader,-100);
-        glDepthMask(GL_FALSE); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
-        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);
+        for(int i=0;i<2;i++){
+            int Do2DInstance=(i==1)?TNS_EVAL_LAYER_SHOW_2D:0;
+            int Is2D=(i==1)?1:ro->Is2D;
+            if (Do2DInstance){
+                la_SetCanvasOrthoFixed(e,W,H); de.PointScale=1.0f/LA_RH; de.Is3D=0;
+                tnsResetViewMatrix(); tnsShaderApplyView(T->BindedShader,tnsGetViewMatrix());
+            }
+            la_BeginNVGDynamic(vg,e,W,H,Is2D,Do2DInstance);
+            tnsDrawObjectTree(root,TNS_EVAL_LAYER_BACKDROP|Do2DInstance,&de,e->AsPlayer);
+            nvgEndFrame(vg); tnsRestoreFromNanoVG();
+            la_BeginNVGDynamic(vg,e,W,H,Is2D,Do2DInstance);
+
+            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|Do2DInstance,&de,e->AsPlayer);
+            
+            glLineWidth(7);  tnsUniformUseOffset(T->immShader,-100);
+            glDepthMask(GL_FALSE); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+            tnsDrawObjectTree(root,TNS_EVAL_LAYER_OUTLINE|Do2DInstance,0,e->AsPlayer);
+            glDepthMask(GL_TRUE); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+            glLineWidth(1); tnsUniformUseOffset(T->immShader,0);
+            glDisable(GL_POLYGON_OFFSET_LINE);
+
+            tnsEvaluateData* ed=e->AsPlayer?(&root->EvaluatedPlay):(&root->Evaluated);
+            if(!ed->Has2D){ break; }
+            nvgEndFrame(vg); tnsRestoreFromNanoVG();
+        }
+        tnsPopMatrix();
     }
 
+    if(!(ro && ro->Is2D)){ de.Is3D=1; tnsVector3d dir={0,0,0}; tnsSetCameraViewDir(dir); }
+
     if (e->ShowFloorGrid){
         tnsUseNoTexture();
         real* color=laThemeColor(bt,LA_BT_BORDER); tnsColor4d(LA_COLOR3(color),0.4);
@@ -205,11 +232,9 @@ void la_RootObjectDraw(laBoxedTheme *bt, tnsObject *root, laUiItem* ui){
 
     if(root && (!e->AsPlayer)){
         glDisable(GL_DEPTH_TEST);
-        tnsDrawCursor(root);
-        glPointSize(8);
+        glPointSize(8); tnsDrawCursor(root);
         tnsDrawObjectOrigins(root,root->Active,0); tnsFlush();
-        glPointSize(1);
-        glEnable(GL_DEPTH_TEST);
+        glPointSize(1); glEnable(GL_DEPTH_TEST);
     }
 
     //laInvoke(0,"M_select",e,&ui->ExtraPP,0,0);