*/}}
1
0
Pārlūkot izejas kodu

2d instance hook point

YimingWu 1 gadu atpakaļ
vecāks
revīzija
17bdf5dcab

+ 14 - 2
la_tns.h

@@ -498,7 +498,7 @@ STRUCTURE(tnsEvaluateData){
     int FillOutline;
     int FillSelectionID;
     int OverrideID;
-    int State2D,Has2D;
+    int State2D,Has2D; int W,H;
     laListHandle ParentStack;
     tnsEvaluatedInstance* Backdrop; int NextBackdrop, MaxBackdrop;
     tnsEvaluatedInstance* Commands; int NextCommand, MaxCommand;
@@ -597,10 +597,22 @@ STRUCTURE(tnsRootObject){
     tnsObject* ActiveCamera;
 };
 
+#define TNS_INSTANCER_HOOK_TL 1
+#define TNS_INSTANCER_HOOK_TC 2
+#define TNS_INSTANCER_HOOK_TR 3
+#define TNS_INSTANCER_HOOK_CL 4
+#define TNS_INSTANCER_HOOK_CC 5
+#define TNS_INSTANCER_HOOK_CR 6
+#define TNS_INSTANCER_HOOK_BL 7
+#define TNS_INSTANCER_HOOK_BC 8
+#define TNS_INSTANCER_HOOK_BR 9
+
 STRUCTURE(tnsInstancer){
     tnsObject Base;
     
     tnsObject* Instance;
+
+    int Hook; real HookOffset[2];
 };
 
 STRUCTURE(tnsCamera){
@@ -1243,7 +1255,7 @@ void tnsInvalidateEvaluation(tnsObject* o);
 void tnsInvalidatePlayEvaluation(tnsObject* o);
 void tnsFreeEvaluatedArray(tnsEvaluateData* ed);
 void tnsEvaluateThisObject(tnsObject *o, tnsEvaluateData* ed);
-void tnsSetObjectTreeEvaluationArgs(tnsObject* from, tnsObject* Active, int FillOutline, int FillSelectionID);
+void tnsSetObjectTreeEvaluationArgs(tnsObject* from, tnsObject* Active, int FillOutline, int FillSelectionID, int W, int H);
 void tnsEvaluateObjectTree(tnsObject* from, tnsEvaluateData* UseED, int EvaluatePlay);
 void tnsAddEvaluatedInstance(tnsEvaluateData* ed, tnsObject* ob, tnsDrawEvaluatedInstanceF Draw, int Layer, 
     int IsActive, int MeshSelectionType, int InstanceSelectionID);

+ 14 - 5
la_tns_kernel.c

@@ -3790,7 +3790,16 @@ void tnsPushEvaluateMatrixWith(tnsEvaluateData* ed, tnsMatrix44d mat){
     tnsMultiply44d(new, ed->MatArr[ed->NextMat-1], mat);
     ed->NextMat++;
 }
-void tnsPushEvaluate2DMatrixWith(tnsEvaluateData* ed, tnsMatrix44d mat){
+void tnsPushEvaluate2DMatrixWith(tnsEvaluateData* ed,tnsInstancer* o){
+    real* mat=o->Base.GlobalTransform; tnsMatrix44d tmat; int Hook=o->Hook;
+    if(Hook){ real X=0,Y=0;
+        if(Hook==TNS_INSTANCER_HOOK_TL||Hook==TNS_INSTANCER_HOOK_CL||Hook==TNS_INSTANCER_HOOK_BL){ X=-(real)ed->W/2/LA_RH; }
+        if(Hook==TNS_INSTANCER_HOOK_TR||Hook==TNS_INSTANCER_HOOK_CR||Hook==TNS_INSTANCER_HOOK_BR){ X=(real)ed->W/2/LA_RH; }
+        if(Hook==TNS_INSTANCER_HOOK_TL||Hook==TNS_INSTANCER_HOOK_TC||Hook==TNS_INSTANCER_HOOK_TR){ Y=(real)ed->H/2/LA_RH; }
+        if(Hook==TNS_INSTANCER_HOOK_BL||Hook==TNS_INSTANCER_HOOK_BC||Hook==TNS_INSTANCER_HOOK_BR){ Y=-(real)ed->H/2/LA_RH; }
+        X+=o->HookOffset[0]; Y+=o->HookOffset[1];
+        tnsMakeTranslationMatrix44d(tmat,X,Y,0); mat=tmat;
+    }
     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++;
 }
@@ -3805,7 +3814,7 @@ void tnsEvaluateInstancerObject(tnsInstancer* o, tnsEvaluateData* ed){
         for(laListItemPointer* lip=ed->ParentStack.pFirst;lip;lip=lip->pNext){
             if(lip->p == inst || lip->p==o->Instance){ goto eval_inst_cleanup; }
         }
-        if(ed->State2D){ tnsPushEvaluate2DMatrixWith(ed,o->Base.GlobalTransform); }
+        if(ed->State2D){ tnsPushEvaluate2DMatrixWith(ed,o); }
         else{ tnsPushEvaluateMatrixWith(ed,o->Base.GlobalTransform); }
         tnsEvaluateObjectTree(inst, ed, ed->SceneEvaluateMode);
         tnsPopEvaluateMatrix(ed);
@@ -3990,17 +3999,17 @@ void tnsFreeEvaluatedArray(tnsEvaluateData* ed){
     arrFree(&ed->Overlays,&ed->MaxOverlay);
     arrFree(&ed->Selections,&ed->MaxSelection);
 }
-void tnsInvalidateEvaluation(tnsObject* o){
+void tnsInvalidateEvaluation(tnsObject* o){ if(!o) return;
     if(o->InRoot) o->InRoot->Evaluated.Done=0; else o->Evaluated.Done=0;
 }
 void tnsInvalidatePlayEvaluation(tnsObject* o){
     if(o->InRoot) o->InRoot->EvaluatedPlay.Done=0; else o->EvaluatedPlay.Done=0;
 }
-void tnsSetObjectTreeEvaluationArgs(tnsObject* from, tnsObject* Active, int FillOutline, int FillSelectionID){
+void tnsSetObjectTreeEvaluationArgs(tnsObject* from, tnsObject* Active, int FillOutline, int FillSelectionID, int W, int H){
     tnsEvaluateData* ed=&from->Evaluated; int set=0;
 #define SETARG(a)\
     if(ed->a==0 && a!=0){ set=1; } ed->a=a;
-    SETARG(Active); SETARG(FillOutline); SETARG(FillSelectionID);
+    SETARG(Active); SETARG(FillOutline); SETARG(FillSelectionID); SETARG(W); SETARG(H);
     if(set) ed->Done=0;
 }
 tnsEvaluatedNode* tnsAcquireEvaluateNode(tnsEvaluateData* ed){

+ 1 - 1
la_tns_shape.c

@@ -199,7 +199,7 @@ int tnsShapeExtrudeSelected(tnsShapeObject* so, int DupliOnly){
 
 void tnsShapeEnterEditMode(tnsShapeObject* so){
     if(so->Mode==TNS_MESH_EDIT_MODE) return;
-    so->Mode = TNS_MESH_EDIT_MODE;
+    so->Mode = TNS_MESH_EDIT_MODE; tnsShapeRefreshIndex(so);
     tnsInvalidateEvaluation(so);
 }
 void tnsShapeLeaveEditMode(tnsShapeObject* so){

+ 1 - 1
resources/la_modelling.c

@@ -133,7 +133,7 @@ void la_PopulateSelectDataObjects(MSelectData* sd, tnsObject* root, laCanvasExtr
     la_BeginNVG(vg,e,w,h,ro->Is2D);
 
     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,0);
+    tnsInvalidateEvaluation(root); tnsSetObjectTreeEvaluationArgs(root,root->Active,1,1,w,h); tnsEvaluateObjectTree(root,0,0);
     tnsDrawObjectTree(root,TNS_EVAL_LAYER_SELECTION,&de,0);
     tnsDrawObjectOrigins(root,root->Active,1); tnsFlush();
     glDisable(GL_DEPTH_TEST); 

+ 19 - 0
resources/la_properties.c

@@ -557,6 +557,12 @@ void *tnsread_World(void *unused, void *inst){
 void tnsset_InstancerInstance(tnsInstancer *o, tnsObject* value){
     o->Instance=value; tnsInvalidateEvaluation(o); laNotifyUsers("tns.world");
 }
+void tnsset_InstancerHook(tnsInstancer *o, int Hook){ laNotifyUsers("tns.world");
+    o->Hook=Hook; laNotifyInstanceUsers(o); tnsInvalidateEvaluation(o); tnsInvalidateEvaluation(o->Instance);
+}
+void tnssetarr_InstancerHookOffset(tnsInstancer *o, real* arr){ laNotifyUsers("tns.world");
+    tnsVectorSet2v(o->HookOffset,arr); laNotifyInstanceUsers(o); tnsInvalidateEvaluation(o); tnsInvalidateEvaluation(o->Instance);
+}
 void *tnsget_detached_FirstRootObject(void *UNUSED1, void *UNUSED2){
     return T->World->RootObjects.pFirst;
 }
@@ -1190,6 +1196,19 @@ void la_RegisterTNSProps(){
         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, "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);
+        ep = laAddEnumProperty(p, "hook", "Hook", "Hook position of the 2d instance", 0,0,0,0,0,offsetof(tnsInstancer, Hook), 0,tnsset_InstancerHook,0,0,0,0,0,0,0,0);{
+            laAddEnumItemAs(ep, "NONE", "None", "Doesn't hook to anything, use instancer x,y coordinates", 0, 0);
+            laAddEnumItemAs(ep, "TL", "Top Left", "Hook to top left", TNS_INSTANCER_HOOK_TL, L'🡤');
+            laAddEnumItemAs(ep, "TC", "Top Center", "Hook to top center", TNS_INSTANCER_HOOK_TC, L'🡡');
+            laAddEnumItemAs(ep, "TR", "Top Right", "Hook to top right", TNS_INSTANCER_HOOK_TR, L'🡥');
+            laAddEnumItemAs(ep, "CL", "Center Left", "Hook to center left", TNS_INSTANCER_HOOK_CL, L'🡠');
+            laAddEnumItemAs(ep, "CC", "Center", "Hook to center", TNS_INSTANCER_HOOK_CC, L'🞆');
+            laAddEnumItemAs(ep, "CR", "Center Right", "Hook to center right", TNS_INSTANCER_HOOK_CR, L'🡢');
+            laAddEnumItemAs(ep, "BL", "Bottom Left", "Hook to bottom left", TNS_INSTANCER_HOOK_BL, L'🡧');
+            laAddEnumItemAs(ep, "BC", "Bottom Center", "Hook to bottom center", TNS_INSTANCER_HOOK_BC, L'🡣');
+            laAddEnumItemAs(ep, "BR", "Bottom Right", "Hook to bottom right", TNS_INSTANCER_HOOK_BR, L'🡦');
+        }
+        laAddFloatProperty(p, "hook_offset", "Hook Offset", "Offset of the 2d hook point", 0,0,"X,Y",0,0,0,0,0,offsetof(tnsInstancer, HookOffset),0,0,2,0,0,0,0,tnssetarr_InstancerHookOffset,0,0,0);
     }
     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);

+ 5 - 0
resources/la_templates.c

@@ -1922,6 +1922,11 @@ void tnsui_InstancerObjectProperties(laUiList *uil, laPropPack *This, laPropPack
     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,"instance",LA_WIDGET_COLLECTION_SELECTOR,0,laui_IdentifierOnly,0);
+    laUiItem* b=laOnConditionThat(uil,c,laAnd(laPropExpression(This,"instance"),laPropExpression(This,"instance.__self.as_root_object.is_2d")));
+    laShowSeparator(uil,c);
+    laShowLabel(uil,cl,"Hook",0,0); laShowItemFull(uil,cr,This,"hook",0,0,0,0);
+    laShowLabel(uil,cl,"Offsets",0,0); laShowItemFull(uil,cr,This,"hook_offset",0,0,0,0)->Flags|=LA_UI_FLAGS_TRANSPOSE;
+    laEndCondition(uil,b);
 }
 void tnsui_RootObjectProperties(laUiList *uil, laPropPack *This, laPropPack *UNUSED_Extra, laColumn *UNUSED_Colums, int context){
     laColumn* c=laFirstColumn(uil), *cl,*cr;

+ 1 - 1
resources/la_widgets_viewers.c

@@ -182,7 +182,7 @@ void la_RootObjectDraw(laBoxedTheme *bt, tnsObject *root, laUiItem* ui){
     if(root){
         tnsPushMatrix();
         if(!e->AsPlayer){
-            tnsSetObjectTreeEvaluationArgs(root,root->Active,1,1);
+            tnsSetObjectTreeEvaluationArgs(root,root->Active,1,1,W,H);
             tnsEvaluateObjectTree(root,0,0);
         }