*/}}
Browse Source

Key insert verify and etc.

YimingWu 1 year ago
parent
commit
f7e30d2a9f
8 changed files with 59 additions and 15 deletions
  1. 16 7
      la_animation.c
  2. 7 0
      la_data.c
  3. 8 1
      la_data.h
  4. 2 2
      la_kernel.c
  5. 11 1
      resources/la_operators.c
  6. 10 1
      resources/la_properties.c
  7. 2 1
      resources/la_templates.c
  8. 3 2
      resources/la_widgets.c

+ 16 - 7
la_animation.c

@@ -54,10 +54,11 @@ void laAnimationUpdateHolderList(){
             ah=memAcquire(sizeof(laActionHolder));
             memAssignRef(ah,&ah->Instance,inst);
             ah->ListHandleOffset=ListOffset;
+            ah->Container=ahp->PP.LastPs->p->SubProp;
             char _id[64]="unamed", *id=_id;
             laTryGetInstanceIdentifier(inst,pa->Base.SubProp,_id,&id);
             strSafeSet(&ah->Name,id);
-            if(FirstIn){ strSafeSet(&ah->CategoryTitle,pa->Base.SubProp->Name); }
+            if(FirstIn){ strSafeSet(&ah->CategoryTitle,pa->Base.SubProp->Name); FirstIn=0; }
             lstAppendItem(&MAIN.Animation->ActionHolders,ah);
             inst=laGetNextInstance(ahp->PP.LastPs->p, inst, &pi);
         }
@@ -69,7 +70,8 @@ laAction* laAnimiationNewAction(laActionHolder* ah, char* Name){
     laAction* aa=memAcquire(sizeof(laAction));
     if(!Name || !Name[0]){ Name="New Action"; }
     strSafeSet(&aa->Name,Name);
-    aa->Length=2; aa->FrameCount=24;
+    aa->Length=2; aa->FrameCount=24; aa->HolderContainer=ah->Container;
+    memAssignRef(aa,&aa->HolderInstance,ah->Instance);
     memAssignRef(MAIN.Animation,&MAIN.Animation->CurrentAction,aa);
     void* lh=((uint8_t*)ah->Instance)+ah->ListHandleOffset;
     lstAppendItem(lh,aa);
@@ -121,8 +123,14 @@ void laAnimationStoreKeyValue(laActionChannel* ac, laActionKey* ak){
     case LA_PROP_SUB: case LA_PROP_OPERATOR: case LA_PROP_STRING: case LA_PROP_RAW: default: return;
     }
 }
-laActionKey* laAnimationInsertKeyFrame(laAction* aa, void* hyper1, laProp* p){
-    if(!aa) return 0;
+laActionKey* laAnimationInsertKeyFrame(laAction* aa, void* hyper1, laProp* p, int* error){
+    if(error) *error=0; if(!aa) return 0;
+    if(!aa->HolderInstance||!aa->HolderContainer){ if(error) *error=1; return 0; }
+    if(aa->HolderContainer->ActionHolderVerify){
+        if(!aa->HolderContainer->ActionHolderVerify(aa->HolderInstance,aa->HolderContainer,hyper1,p->Container)){
+            if(error) *error=2; return 0;
+        }
+    }
     laActionChannel* ac=laAnimationEnsureChannel(aa,hyper1,p); if(!ac || !ac->AP || !ac->AP->For) return;
     int frame=LA_ACTION_FRAME(aa);
     laActionKey* ak=laAnimationEnsureFrame(ac,frame);
@@ -184,7 +192,7 @@ void laui_AnimationSelectAction(laUiList *uil, laPropPack *This, laPropPack *Ope
     laColumn *c = laFirstColumn(uil);
     for(laActionHolderPath* ahp=MAIN.Animation->ActionHolderPaths.pFirst;ahp;ahp=ahp->Item.pNext){
         laShowLabel(uil,c,ahp->PP.LastPs->p->Name,0,0)->Flags|=LA_UI_FLAGS_DISABLED|LA_TEXT_MONO;
-        laShowItemFull(uil,c,0,ahp->OriginalPath,LA_WIDGET_COLLECTION,0,laui_AnimationActionHolder,0)->Flags|=LA_UI_FLAGS_NO_DECAL|LA_UI_FLAGS_NO_GAP;
+        laShowItemFull(uil,c,0,ahp->OriginalPath,LA_WIDGET_COLLECTION,"feedback=NONE",laui_AnimationActionHolder,0)->Flags|=LA_UI_FLAGS_NO_DECAL|LA_UI_FLAGS_NO_GAP;
     }
 }
 
@@ -259,7 +267,7 @@ void la_AnimationMixChannelValue(laActionChannel* ac, void* data, int MixMode, r
     case LA_PROP_INT:  case LA_PROP_INT|LA_PROP_ARRAY: for(int i=0;i<arrlen;i++){ 
             ip[i]=ap->Reset?ipd[i]:(MixMode==LA_ANIMATION_MIX_REPLACE?ipd[i]:(ipd[i]+ip[i]));
         } break;
-    case LA_PROP_FLOAT: case LA_PROP_FLOAT|LA_PROP_ARRAY: for(int i=0;i<arrlen;i++){ 
+    case LA_PROP_FLOAT: case LA_PROP_FLOAT|LA_PROP_ARRAY: for(int i=0;i<arrlen;i++){
             fp[i]=ap->Reset?fpd[i]:(MixMode==LA_ANIMATION_MIX_REPLACE?fpd[i]:(fpd[i]+fp[i]));
         } break;
     case LA_PROP_ENUM: ip[0]=ipd[0]; break;
@@ -272,6 +280,7 @@ void la_AnimationEvaluateActionChannels(laAction* aa){
     int64_t _data[16]; void* data=_data;
     int frame=LA_ACTION_FRAME(aa); real totframe=aa->PlayHead*aa->FrameCount;
     for(laActionChannel* ac=aa->Channels.pFirst;ac;ac=ac->Item.pNext){
+        data=_data;
         laActionKey* ak1=laAnimationGetFrame(ac,frame); if(!ak1) continue;
         laActionKey* ak2=ak1->Item.pNext;
         la_AnimationInterpolateKeys(ac,ak1,ak2,totframe,&data);
@@ -286,7 +295,7 @@ void la_AnimationEvaluateActions(int ClampOffsets){
         laListHandle* lh=((uint8_t*)ah->Instance)+ah->ListHandleOffset;
         for(laAction* aa=lh->pFirst;aa;aa=aa->Item.pNext){
             real preoffset=0,postoffset=aa->Offset/aa->Length;
-            if(ClampOffsets || (MAIN.Animation->PlayStatus!=LA_ANIMATION_STATUS_PAUSED)){
+            if(ClampOffsets || (MAIN.Animation->PlayStatus!=LA_ANIMATION_STATUS_PAUSED) || (aa!=MAIN.Animation->CurrentAction)){
                 while(aa->Offset>aa->Length){ aa->Offset-=aa->Length; }
                 while(aa->Offset<-1e-6){ aa->Offset+=aa->Length; }
                 preoffset=aa->Offset; postoffset=0;

+ 7 - 0
la_data.c

@@ -713,6 +713,10 @@ laProp* laPropContainerManageable(laPropContainer* pc, int offset_of_dummy_list)
     return pc->SaverDummy;
 }
 
+void laContainerAnimationFunctions(laPropContainer* pc, laActionHolderVerifyF ActionHolderVerify){
+    pc->ActionHolderVerify=ActionHolderVerify;
+}
+
 int la_GetKeyablePropertyStorageSize(laProp* p){
     switch(p->PropertyType){
     case LA_PROP_INT: case LA_PROP_FLOAT: case LA_PROP_ENUM:
@@ -1982,6 +1986,7 @@ int laSetRaw(laPropPack *pp, void* data, int _size){
 }
 
 int laTryGetInstanceIdentifier(void* Instance, laPropContainer* pc, char* identifier, char** here){
+    if(!Instance || !pc) return 0;
     laProp* p=la_PropLookupIdentifierItem(&pc->Props);
     if(p){
         laPropPack PP={0}; laPropStep PS={0};
@@ -1991,7 +1996,9 @@ int laTryGetInstanceIdentifier(void* Instance, laPropContainer* pc, char* identi
         elif(p->PropertyType&LA_PROP_FLOAT){ real r[16]={0}; laGetFloatArray(&PP,r); sprintf("(%s=%lf)",p->Identifier,r[0]); }
         elif(p->PropertyType&LA_PROP_ENUM){  laEnumItem *r[16]={0}; laGetEnumArray(&PP,r); sprintf("(%s=%lf)",p->Identifier,r[0]?r[0]->Identifier:"?"); }
         else{ sprintf("(%.6x)",identifier); }
+        return 1;
     }
+    return 0;
 }
 
 int laGetIntRange(laPropPack *pp, int *min, int *max){

+ 8 - 1
la_data.h

@@ -90,6 +90,8 @@ typedef void (*laContainerResetF)(void *);
 typedef void (*laContainerUndoTouchedF)(void *, u64bit hint);
 typedef void (*laContainerpUDFPropagateF)(void *, void* udf, int Force);
 
+typedef int (*laActionHolderVerifyF)(void* Holder, laPropContainer* HolderType, void* inst, laPropContainer* InstType);
+
 #define LA_PROP_GENERAL_ROOT (1<<7)
 #define LA_PROP_SUB (1<<8)
 #define LA_PROP_INT (1<<9)
@@ -153,6 +155,8 @@ STRUCTURE(laPropContainer){
     int Hyper;
     int OtherAlloc;
 
+    laActionHolderVerifyF ActionHolderVerify;
+
     laCanvasTemplate *Template2D;
 
     laListHandle Props;
@@ -686,6 +690,7 @@ STRUCTURE(laAnimation){
 STRUCTURE(laAction){
     laListItem Item;
     laSafeString* Name;
+    void* HolderInstance; laPropContainer* HolderContainer; // only for verification
     laListHandle Channels;
     int FrameCount;
     real Length;
@@ -882,6 +887,8 @@ laPropContainer *laAddPropertyContainer(const char *Identifier, const char *Name
                                         int NodeSize, laContainerPostReadFunc PostRead, laContainerPostReadFunc PostReadIm, int IsHyper);
 laProp* laPropContainerManageable(laPropContainer* pc, int offset_of_dummy_list);
 void laPropContainerExtraFunctions(laPropContainer* pc, laContainerBeforeFreeF BeforeFree, laContainerResetF Reset, laContainerUndoTouchedF Touched, laContainerpUDFPropagateF UDFPropagate, laUiDefineFunc MenuUi);
+void laContainerAnimationFunctions(laPropContainer* pc, laActionHolderVerifyF ActionHolderVerify);
+
 const char *la_GetPropertyTypeString(int Type);
 
 NEED_STRUCTURE(laWidget);
@@ -1050,7 +1057,7 @@ laAction* laAnimiationNewAction(laActionHolder* ah, char* Name);
 laActionChannel* laAnimationEnsureChannel(laAction* aa, void* hyper1, laProp* p);
 laActionChannel* laAnimationEnsureFrame(laActionChannel* ac, int frame);
 void laAnimationStoreKeyValue(laActionChannel* ac, laActionKey* ak);
-laActionKey* laAnimationInsertKeyFrame(laAction* aa, void* hyper1, laProp* p);
+laActionKey* laAnimationInsertKeyFrame(laAction* aa, void* hyper1, laProp* p, int* error);
 
 void laAnimationSetPlayStatus(int PlayStatus);
 void laAnimationSetPlayHead(real time);

+ 2 - 2
la_kernel.c

@@ -3120,7 +3120,7 @@ laPanel *laEnableMessagePanel(laOperator *a, laPanel *Attachment, char *Title, c
     laUiList *uil;
     laColumn *col, *cor, *corl, *corr;
 
-    p = la_NewPanel(0, X, Y, W, 0, 1000, 90, 100, 0, 0, 0, 0, 0);
+    p = la_NewPanel(0, X, Y, W, 0, 1000, 0, 100, 0, 0, 0, 0, 0);
     strSafeSet(&p->Title, Title);
     p->BoundUi = 1;
     p->Mode = LA_PANEL_FLOATING_TOP;
@@ -3134,7 +3134,7 @@ laPanel *laEnableMessagePanel(laOperator *a, laPanel *Attachment, char *Title, c
     laSplitColumn(uil, col, 0.35);
     cor = laRightColumn(col, 200);
 
-    laShowLabel(uil, col, Message, 0, 0);
+    laShowLabel(uil, col, Message, 0, 0)->Flags|=LA_TEXT_USE_NEWLINE|LA_TEXT_LINE_WRAP;
 
     laShowItemFull(uil, cor, 0, "LA_confirm",0,"text=Okay;",0,0)->Flags|=LA_UI_FLAGS_HIGHLIGHT;
 

+ 11 - 1
resources/la_operators.c

@@ -911,7 +911,17 @@ int OPCHK_PropInsertKey(laPropPack *This, laStringSplitor *Instructions){
     else return 0;
 }
 int OPINV_PropInsertKey(laOperator *a, laEvent *e){
-    laAnimationInsertKeyFrame(MAIN.Animation->CurrentAction,a->This->LastPs->UseInstance,a->This->LastPs->p);
+    int err; laAction* aa=MAIN.Animation->CurrentAction;
+    laAnimationInsertKeyFrame(aa,a->This->LastPs->UseInstance,a->This->LastPs->p,&err);
+    if(err==1){
+        laEnableMessagePanel(a,0,"Error","Action holder info missing.\nThis should not happen.",e->x,e->y,100,e);
+    }elif(err==2){
+        char msg[1024]; char _id[128]="unknown container",*id=_id,_idc[128]="unknown object",*idc=_idc;
+        laTryGetInstanceIdentifier(aa->HolderInstance,aa->HolderContainer,_id,&id);
+        laTryGetInstanceIdentifier(a->This->LastPs->UseInstance,a->This->LastPs->p->Container,_idc,&idc);
+        sprintf(msg,"Can't insert key frame into current action.\n\"%s\" doesn't come from an action under \"%s\".",idc,id);
+        laEnableMessagePanel(a,0,"Error",msg,e->x,e->y,100,e);
+    }
     return LA_FINISHED;
 }
 

+ 10 - 1
resources/la_properties.c

@@ -519,6 +519,7 @@ void* laget_CurrentAnimationAction(void* unused_a){
 }
 void* laset_CurrentAnimationAction(void* unused_a, laAction* c){
     memAssignRef(MAIN.Animation,&MAIN.Animation->CurrentAction,c);
+    laNotifyUsers("la.animation.current_action");
 }
 
 void laset_WindowColorSpace(laWindow* w, int space){
@@ -833,6 +834,13 @@ int laget_AnimationActionCurrentFrame(laAction* aa){
     return LA_ACTION_FRAME(aa);
 }
 
+int laaction_VerifyRootObject(void* Parent, laPropContainer* ParentType, void* Child, laPropContainer* ChildType){
+    if(ParentType!=ChildType) return 0;
+    if(ParentType!=TNS_PC_OBJECT_GENERIC) return 0;
+    tnsObject*o=Child; if(o==Parent || o->InRoot==Parent) return 1;
+    return 0;
+}
+
 void lareset_Main(void* Unused){
     return;
 }
@@ -1507,7 +1515,7 @@ void la_RegisterInternalProps(){
     }
 
     p = laAddPropertyContainer("tns_world", "World", "3D World Structure", 0,0,sizeof(tnsWorld), 0,0,2|LA_PROP_OTHER_ALLOC);{
-        sp = laAddSubGroup(p, "root_objects", "Root Objects", "List of all root objects", "tns_object",0,0,0,0,0,0,0,0,0,0,offsetof(tnsWorld, RootObjects), 0);
+        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);
         laSubGroupDetachable(sp, tnsget_detached_FirstRootObject, laget_ListNext);
         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);
     }
@@ -1518,6 +1526,7 @@ void la_RegisterInternalProps(){
 
     p = laAddPropertyContainer("tns_object", "Object", "3D Object Item", 0,0,sizeof(tnsObject), tnspost_Object, 0,2);{
         laPropContainerExtraFunctions(p,0,0,0,tnspropagate_Object,0);
+        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);
         laAddIntProperty(p,"flags","Flags","Flags",0,0,0,0,0,0,0,0,offsetof(tnsObject,Flags),0,0,0,0,0,0,0,0,0,0,LA_READ_ONLY);

+ 2 - 1
resources/la_templates.c

@@ -1583,6 +1583,7 @@ void laui_AnimationActionSimple(laUiList *uil, laPropPack *This, laPropPack *Ext
 }
 void laui_AnimationActionHolder(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *ExtraColumns, int context){
     laColumn* c=laFirstColumn(uil);
+    laShowItemFull(uil,c,This,"identifier",LA_WIDGET_STRING_PLAIN,0,0,0);
     laShowItemFull(uil,c,This,"__actions__",0,0,laui_AnimationActionSimple,0)->Flags|=LA_UI_FLAGS_NO_DECAL;
 }
 void laui_AnimationActionListItem(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *ExtraColumns, int context){
@@ -1621,7 +1622,7 @@ void laui_AnimationActions(laUiList *uil, laPropPack *This, laPropPack *Extra, l
     gu->HeightCoeff=-3; //ui->Flags|=LA_UI_FLAGS_NO_DECAL;
     for(laActionHolderPath* ahp=MAIN.Animation->ActionHolderPaths.pFirst;ahp;ahp=ahp->Item.pNext){
         laShowLabel(gu,gc,ahp->PP.LastPs->p->Name,0,0)->Flags|=LA_UI_FLAGS_DISABLED|LA_TEXT_MONO;
-        laShowItemFull(gu,gc,0,ahp->OriginalPath,LA_WIDGET_COLLECTION,0,laui_AnimationActionHolder,0)->Flags|=LA_UI_FLAGS_NO_DECAL|LA_UI_FLAGS_NO_GAP;
+        laShowItemFull(gu,gc,0,ahp->OriginalPath,LA_WIDGET_COLLECTION,"feedback=NONE",laui_AnimationActionHolder,0)->Flags|=LA_UI_FLAGS_NO_DECAL|LA_UI_FLAGS_NO_GAP;
     }
 
     row=laBeginRow(uil,cl,0,0);

+ 3 - 2
resources/la_widgets.c

@@ -794,16 +794,17 @@ void la_EnumSelectorDraw(laUiItem *ui, int h){
         else{ _W/=ArrLen; }
     }
     
-    int ico=0; char buft[48]={0}; int HasText=0;
+    int UseIco=0,ico=0; char buft[48]={0}; int HasText=0;
     if (ui->ExtraInstructions){
         if (ui->Type->OperatorType->ParseArgs){
-            ui->Type->OperatorType->ParseArgs(ui->Instructions, &ico, buft);
+            ui->Type->OperatorType->ParseArgs(ui->Instructions, &UseIco, buft);
         }
         sprintf(buf,"%s",transLate(buft)); HasText=1;
     }
     for(int i=0;i<ArrLen;i++){
         _L=ui->L; _R=ui->R; _U=ui->U; _B=ui->B; ei = ep->Items.pFirst;
         for(int j=0;j<EnumLen;j++){ if(!HasText)buf[0]=0;
+            ico=UseIco;
             if(IsVertical){
                 if(IsExpand){ _U=ui->U+j*LA_RH; _L=ui->L+i*_W; }
                 else{ _U=ui->U+i*LA_RH;  _L=ui->L; }