*/}}
فهرست منبع

Basic animation structures WIP

YimingWu 1 سال پیش
والد
کامیت
6b6ea70564
8فایلهای تغییر یافته به همراه156 افزوده شده و 1 حذف شده
  1. 86 0
      la_animation.c
  2. 12 0
      la_data.c
  3. 20 0
      la_data.h
  4. 4 0
      la_interface.h
  5. 1 0
      la_kernel.c
  6. 4 1
      la_tns.h
  7. 20 0
      resources/la_properties.c
  8. 9 0
      resources/la_templates.c

+ 86 - 0
la_animation.c

@@ -0,0 +1,86 @@
+/*
+* LaGUI: A graphical application framework.
+* Copyright (C) 2022-2023 Wu Yiming
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "la_5.h"
+
+extern LA MAIN;
+
+int la_GetKeyablePropertyStorageSize(laProp* p);
+
+laAction* laNewAction(char* Name){
+    laAction* aa=memAcquire(sizeof(laAction));
+    if(!Name || !Name[0]){ Name="New Action"; }
+    strSafeSet(&aa->Name,Name);
+    aa->Length=5; aa->FrameCount=120;
+    lstAppendItem(&MAIN.Actions,aa);
+    laNotifyUsers("la.actions");
+    return aa;
+}
+laAnimationChannel* laAnimationEnsureChannel(laAction* aa, void* hyper1, laProp* p){
+    laAnimationChannel* acf=0;
+    int DataSize=la_GetKeyablePropertyStorageSize(p); if(!DataSize) return 0;
+    for(laAnimationChannel* ac=aa->Channels.pFirst;ac;ac=ac->Item.pNext){
+        if(ac->For==hyper1 && ac->Prop==p){ acf=ac; break; }
+    }
+    if(acf) return acf;
+    acf=memAcquire(sizeof(laAnimationChannel));
+    memAssignRef(acf,&acf->For,hyper1); acf->Prop=p;
+    acf->DataSize = DataSize;
+    lstAppendItem(&aa->Channels,acf);
+    return acf;
+}
+laAnimationChannel* laAnimationEnsureFrame(laAnimationChannel* ac, int frame){
+    laAnimationKey* akf=0,*beforeakf=0;
+    for(laAnimationKey* ak=ac->Keys.pFirst;ak;ak=ak->Item.pNext){
+        if(ak->At==frame){ akf=ak; break; } if(ak->At>frame){ beforeakf=ak; break; }
+    }
+    if(!akf){
+        akf=memAcquireSimple(sizeof(laAnimationKey)-sizeof(uint64_t)+ac->DataSize);
+        akf->At=frame;
+        if(beforeakf){ lstInsertItemBefore(&ac->Keys, akf, beforeakf); }
+        lstAppendItem(&ac->Keys, akf);
+    }
+    return akf;
+}
+void laAnimationStoreKeyValue(laAnimationChannel* ac, laAnimationKey* ak){
+    laPropPack PP={0}; laPropStep PS={0};
+    PS.p=ac->Prop; PS.Type='.'; PS.UseInstance=ac->For; PP.LastPs=&PS; PP.EndInstance=ac->For;
+    switch(ac->Prop->PropertyType){
+    case LA_PROP_INT: case LA_PROP_INT | LA_PROP_ARRAY:     laGetIntArray(&PP,(int*)&ak->Data);
+    case LA_PROP_FLOAT: case LA_PROP_FLOAT | LA_PROP_ARRAY: laGetFloatArray(&PP,(real*)&ak->Data);
+    case LA_PROP_ENUM: case LA_PROP_ENUM | LA_PROP_ARRAY:   laGetEnumArray(&PP,(laEnumItem**)&ak->Data);
+    case LA_PROP_SUB: case LA_PROP_OPERATOR: case LA_PROP_STRING: case LA_PROP_RAW: default: return;
+    }
+}
+laAnimationKey* laAnimationInsertKeyFrame(laAction* aa, void* hyper1, laProp* p){
+    laAnimationChannel* ac=laAnimationEnsureChannel(aa,hyper1,p); if(!ac || !ac->For) return;
+    int frame=aa->PlayHead/aa->Length*aa->FrameCount;
+    laAnimationKey* ak=laAnimationEnsureFrame(ac->DataSize,frame);
+    laAnimationStoreKeyValue(ac,ak);
+}
+
+int OPINV_NewAction(laOperator *a, laEvent *e){
+    laNewAction(0);
+    return LA_FINISHED;
+}
+
+void la_RegisterAnimationResources(){
+    laPropContainer *pc; laProp *p; laOperatorType *at; laEnumProp *ep;
+    laCreateOperatorType("LA_new_action", "New Action", "Add a new action",0,0,0,OPINV_NewAction,0,0,0);
+}
+

+ 12 - 0
la_data.c

@@ -713,6 +713,18 @@ laProp* laPropContainerManageable(laPropContainer* pc, int offset_of_dummy_list)
     return pc->SaverDummy;
 }
 
+int la_GetKeyablePropertyStorageSize(laProp* p){
+    switch(p->PropertyType){
+    case LA_PROP_INT: case LA_PROP_FLOAT: case LA_PROP_ENUM:
+        return sizeof(uint64_t);
+    case LA_PROP_INT | LA_PROP_ARRAY: case LA_PROP_FLOAT | LA_PROP_ARRAY: case LA_PROP_ENUM | LA_PROP_ARRAY:
+        if(p->GetLen){ return 0; }
+        return sizeof(uint64_t)*p->Len;
+    case LA_PROP_SUB: case LA_PROP_OPERATOR: case LA_PROP_STRING: case LA_PROP_RAW: default:
+        return 0;
+    }
+}
+
 int la_GetPropertySize(int Type){
     switch (Type){
     case LA_PROP_INT:

+ 20 - 0
la_data.h

@@ -649,6 +649,26 @@ STRUCTURE(laDiffPost){
     laContainerUndoTouchedF Touched;
 };
 
+STRUCTURE(laAction){
+    laListItem Item;
+    laSafeString* Name;
+    laListHandle Channels;
+    int FrameCount;
+    real Length;
+    real PlayHead;
+};
+STRUCTURE(laAnimationChannel){
+    laListItem Item;
+    void* For;
+    laProp* Prop;
+    int DataSize; // sizeof
+    laListHandle Keys;
+};
+STRUCTURE(laAnimationKey){
+    laListItem Item;
+    int At;
+    uint64_t Data; // variable size depending on property;
+};
 
     //STRUCTURE(laUDFFailNode) {
     //	laListItemPointer Item;

+ 4 - 0
la_interface.h

@@ -468,6 +468,8 @@ STRUCTURE(LA){
 
     laDiffPushEverythingF PushEverything;
 
+    laListHandle Actions;
+
     real FontSize;
     real MarginSize;
     int UiRowHeight;
@@ -1634,6 +1636,8 @@ void la_RegisterWindowKeys();
 void la_RegisterGeneralProps();
 void la_RegisterInternalProps();
 
+void la_RegisterAnimationResources();
+
 void la_RegenerateWireColors();
 
 

+ 1 - 0
la_kernel.c

@@ -890,6 +890,7 @@ int laGetReadyWith(int GLMajor, int GLMinor, int BufferSamples){
     la_RegisterMainUiTypes();
     la_RegisterModellingOperators();
     la_RegisterInternalProps();
+    la_RegisterAnimationResources();
     la_RegisterWindowKeys();
 
     laFinalizeUiTemplates();

+ 4 - 1
la_tns.h

@@ -578,6 +578,9 @@ struct _tnsObject
     int ShowOnRender;
     int HideChildren;
 
+    int RotationMode;
+    int IsInstanced;
+
     real GLocation[3];
     real GRotation[3];
     real GScale;
@@ -585,11 +588,11 @@ struct _tnsObject
     real Location[3];
     real Rotation[4];
     real Scale;//Only allow uniform scale
-    u8bit RotationMode;
 
     tnsMatrix44d GlobalTransform;
     tnsMatrix44d SelfTransform;
     tnsMatrix44d DeltaTransform;
+    tnsMatrix44d InstanceTransform;
     //tnsMatrix44d CameraTransform;
 
     tnsObject *Active;  // may be used to store last select info in child objects.

+ 20 - 0
resources/la_properties.c

@@ -1000,6 +1000,8 @@ void la_RegisterInternalProps(){
             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, "actions", "Actions", "All animation actions","la_animation_action",0,0,0,-1,0,0,0,0,0,0,offsetof(LA,Actions),0);
+
             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);
             
@@ -1397,6 +1399,24 @@ void la_RegisterInternalProps(){
             laAddStringProperty(p, "rename", "Rename", "Rename", 0,0,0,0,0,offsetof(laProp, Identifier), 0,0,0,laread_DetachedPropRename, 0);
         }
 
+        p = laAddPropertyContainer("la_animation_action", "Action", "Animation action",0,0,sizeof(laAction),0,0,1);{
+            laAddStringProperty(p,"name","Name","Name of the action",0,0,0,0,1,offsetof(laAction,Name),0,0,0,0,LA_AS_IDENTIFIER);
+            laAddSubGroup(p, "channels", "Channels", "Action channels", "la_animation_channel",0,0,0,-1,0,0,0,0,0,0,offsetof(laAction, Channels),0);
+            laAddFloatProperty(p, "length","Length","Length of the action in seconds",0,0,"s",40,0,0.1,5,0,offsetof(laAction,Length),0,0,0,0,0,0,0,0,0,0,0);
+            laAddFloatProperty(p, "play_head","Play Head","PlayHead position",0,0,"s",40,0,0.1,5,0,offsetof(laAction,PlayHead),0,0,0,0,0,0,0,0,0,0,0);
+            laAddIntProperty(p, "frame_count","Frame Count","Total frame count in the whole length of the action",0,0,0,0,0,0,120,0,offsetof(laAction,FrameCount),0,0,0,0,0,0,0,0,0,0,0);
+        }
+        p = laAddPropertyContainer("la_animation_channel", "Channel", "Animation channel",0,0,sizeof(laAnimationChannel),0,0,1);{
+            laAddSubGroup(p, "keys", "Keys", "Key Frames", "la_animation_key",0,0,0,-1,0,0,0,0,0,0,offsetof(laAnimationChannel, Keys),0);
+            laAddIntProperty(p, "data_size","Data Size","Data size of the channel",0,0,0,0,0,0,0,0,offsetof(laAnimationChannel,DataSize),0,0,0,0,0,0,0,0,0,0,LA_READ_ONLY);
+            laAddSubGroup(p, "prop", "Property", "Property of this channel", "property_item",0,0,0,offsetof(laAnimationChannel, Prop), 0,0,0,0,0,0,0,LA_UDF_REFER | LA_UDF_IGNORE);
+            // XXX: Prop needs a string "container.prop" to be able to be able to r/w.
+            laAddSubGroup(p, "for", "For", "Target data block", "any_pointer",0,0,0,offsetof(laAnimationChannel, For), 0,0,0,0,0,0,0,LA_UDF_REFER);
+        }
+        p = laAddPropertyContainer("la_animation_key", "key", "Animation channel",0,0,sizeof(laAnimationKey),0,0,1);{
+            laAddIntProperty(p, "at","At","Frame number of this key frame",0,0,0,0,0,0,0,0,offsetof(laAnimationKey,At),0,0,0,0,0,0,0,0,0,0,0);
+            // XXX: RAW for r/w.
+        }
     }
 
     // TNS WORLD ============================================================================================

+ 9 - 0
resources/la_templates.c

@@ -1564,8 +1564,17 @@ void laui_Drivers(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *
     laShowItemFull(uil,c,Extra,"page",LA_WIDGET_COLLECTION_SINGLE,0,laui_RackPage,0)->Flags|=LA_UI_FLAGS_NO_DECAL;;
 }
 
+void laui_AnimationActions(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){
+    laColumn* c=laFirstColumn(uil),*cl, *cr;
+    
+    laShowItemFull(uil,c,0,"la.actions",LA_WIDGET_COLLECTION,0,0,0);
+
+    laShowItem(uil,c,0,"LA_new_action");
+}
+
 
 void la_RegisterBuiltinTemplates(){
+    laRegisterUiTemplate("LAUI_animation_actions", "Actions", laui_AnimationActions, 0, 0, 0, 0,15,25);
     laRegisterUiTemplate("LAUI_input_mapper","Input Mapper",laui_InputMapper,0,0,"Controlling",0,0,0);
     laRegisterUiTemplate("LAUI_drivers","Drivers",laui_Drivers,lauidetached_Drivers,0,0,0,0,0);
     laRegisterUiTemplate("LAUI_controllers", "Controllers", laui_GameController, lauidetached_GameController, 0,0,0,0,0);