|
@@ -19,17 +19,62 @@
|
|
#include "la_5.h"
|
|
#include "la_5.h"
|
|
|
|
|
|
extern LA MAIN;
|
|
extern LA MAIN;
|
|
|
|
+extern tnsMain* T;
|
|
|
|
|
|
int la_GetKeyablePropertyStorageSize(laProp* p);
|
|
int la_GetKeyablePropertyStorageSize(laProp* p);
|
|
void la_AnimationEvaluateActions(int ClampOffsets);
|
|
void la_AnimationEvaluateActions(int ClampOffsets);
|
|
|
|
+void laget_AnimationActionHolderCategory(void* a_unused, laActionHolder* ah, char* copy, char** ptr);
|
|
|
|
+void laui_AnimationActionHolder(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *ExtraColumns, int context);
|
|
|
|
+
|
|
|
|
+int laAnimationRegisterHolderPath(const char* Path){
|
|
|
|
+ laPropPack PP={0}; if(!la_GetPropFromPath(&PP,0,Path,0)){ la_FreePropStepCache(PP.Go); return 0; }
|
|
|
|
+ la_EnsureSubTarget(PP.LastPs->p,0);
|
|
|
|
+ if((!PP.LastPs->p->SubProp) || (!la_PropLookup(&PP.LastPs->p->SubProp->Props,"__actions__"))){
|
|
|
|
+ la_FreePropStepCache(PP.Go); return 0;
|
|
|
|
+ }
|
|
|
|
+ laActionHolderPath* ahp=memAcquire(sizeof(laActionHolderPath));
|
|
|
|
+ ahp->OriginalPath=Path;
|
|
|
|
+ la_CopyPropPack(&PP,&ahp->PP); lstAppendItem(&MAIN.Animation->ActionHolderPaths,ahp);
|
|
|
|
+ la_FreePropStepCache(PP.Go);
|
|
|
|
+ return 1;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void laAnimationUpdateHolderList(){
|
|
|
|
+ laActionHolder* ah;
|
|
|
|
+ while(ah=lstPopItem(&MAIN.Animation->ActionHolders)){
|
|
|
|
+ strSafeDestroy(&ah->Name); strSafeDestroy(&ah->CategoryTitle); memFree(ah);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ for(laActionHolderPath* ahp=MAIN.Animation->ActionHolderPaths.pFirst;ahp;ahp=ahp->Item.pNext){
|
|
|
|
+ la_StepPropPack(&ahp->PP); laSubProp* pa=ahp->PP.LastPs->p; la_EnsureSubTarget(pa,0); laPropIterator pi={0};
|
|
|
|
+ int ListOffset=0; laSubProp* paa=la_PropLookup(&pa->Base.SubProp->Props,"__actions__");
|
|
|
|
+ if((!paa) || (!paa->ListHandleOffset)){ continue; } ListOffset=paa->ListHandleOffset;
|
|
|
|
+ void* inst=laGetInstance(ahp->PP.LastPs->p,ahp->PP.LastPs->UseInstance,&pi); int FirstIn=1;
|
|
|
|
+ while(inst){
|
|
|
|
+ ah=memAcquire(sizeof(laActionHolder));
|
|
|
|
+ memAssignRef(ah,&ah->Instance,inst);
|
|
|
|
+ ah->ListHandleOffset=ListOffset;
|
|
|
|
+ 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); }
|
|
|
|
+ lstAppendItem(&MAIN.Animation->ActionHolders,ah);
|
|
|
|
+ inst=laGetNextInstance(ahp->PP.LastPs->p, inst, &pi);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ laNotifyUsers("la.animation.action_holders");
|
|
|
|
+}
|
|
|
|
|
|
-laAction* laAnimiationNewAction(char* Name){
|
|
|
|
|
|
+laAction* laAnimiationNewAction(laActionHolder* ah, char* Name){
|
|
laAction* aa=memAcquire(sizeof(laAction));
|
|
laAction* aa=memAcquire(sizeof(laAction));
|
|
if(!Name || !Name[0]){ Name="New Action"; }
|
|
if(!Name || !Name[0]){ Name="New Action"; }
|
|
strSafeSet(&aa->Name,Name);
|
|
strSafeSet(&aa->Name,Name);
|
|
aa->Length=2; aa->FrameCount=24;
|
|
aa->Length=2; aa->FrameCount=24;
|
|
memAssignRef(MAIN.Animation,&MAIN.Animation->CurrentAction,aa);
|
|
memAssignRef(MAIN.Animation,&MAIN.Animation->CurrentAction,aa);
|
|
- lstAppendItem(&MAIN.Animation->Actions,aa); laNotifyUsers("la.animation.actions");
|
|
|
|
|
|
+ void* lh=((uint8_t*)ah->Instance)+ah->ListHandleOffset;
|
|
|
|
+ lstAppendItem(lh,aa);
|
|
|
|
+ laNotifyInstanceUsers(ah->Instance);
|
|
|
|
+ laNotifyUsers("la.animation.current_action");
|
|
return aa;
|
|
return aa;
|
|
}
|
|
}
|
|
laActionProp* laAnimationEnsureProp(void* hyper1, laProp* p){
|
|
laActionProp* laAnimationEnsureProp(void* hyper1, laProp* p){
|
|
@@ -95,11 +140,55 @@ void laAnimationSetPlayHead(real time){
|
|
MAIN.Animation->PlayHead=time;
|
|
MAIN.Animation->PlayHead=time;
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
|
|
+STRUCTURE(laNewActionData){
|
|
|
|
+ laActionHolder* SelectedHolder;
|
|
|
|
+};
|
|
|
|
+laActionHolder* laget_AnimationFirstActionHolder(void* unused1, void* unused2){
|
|
|
|
+ return MAIN.Animation->ActionHolders.pFirst;
|
|
|
|
+}
|
|
|
|
+void laset_AnimationNewActionSetHolder(laNewActionData *np, laActionHolder *ah, int State){
|
|
|
|
+ np->SelectedHolder = ah;
|
|
|
|
+}
|
|
int OPINV_AnimationNewAction(laOperator *a, laEvent *e){
|
|
int OPINV_AnimationNewAction(laOperator *a, laEvent *e){
|
|
- laAnimiationNewAction(0);
|
|
|
|
- return LA_FINISHED;
|
|
|
|
|
|
+ laAnimationUpdateHolderList();
|
|
|
|
+ laNewActionData* np= CreateNew(laNewActionData);
|
|
|
|
+ a->CustomData = np;
|
|
|
|
+ laEnableOperatorPanel(a, 0, e->x-50,e->y-50,500,500,10000,0,0,0,0,0,0,0,e);
|
|
|
|
+ return LA_RUNNING;
|
|
|
|
+}
|
|
|
|
+int OPMOD_AnimationNewAction(laOperator *a, laEvent *e){
|
|
|
|
+ laNewActionData* np=a->CustomData;
|
|
|
|
+
|
|
|
|
+ if(!a->ConfirmData) return LA_RUNNING;
|
|
|
|
+
|
|
|
|
+ if(a->ConfirmData->Mode == LA_CONFIRM_CANCEL||a->ConfirmData->Mode == LA_CONFIRM_OK){ if(np) free(np); return LA_CANCELED; }
|
|
|
|
+
|
|
|
|
+ if(a->ConfirmData->Mode == LA_CONFIRM_DATA){
|
|
|
|
+ if (!np || !np->SelectedHolder){ if(np) free(np); return LA_CANCELED; }
|
|
|
|
+ laAnimiationNewAction(np->SelectedHolder,0); free(np);
|
|
|
|
+ return LA_FINISHED;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return LA_RUNNING;
|
|
}
|
|
}
|
|
|
|
+void laui_AnimationNewAction(laUiList *uil, laPropPack *This, laPropPack *OperatorProps, laColumn *UNUSED, int context){
|
|
|
|
+ laColumn *c = laFirstColumn(uil);
|
|
|
|
+ laUiItem* ui=laShowItem(uil, c, OperatorProps, "holder");ui->SymbolID=3; ui->Flags|=LA_UI_FLAGS_NO_DECAL;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int OPINV_AnimationSelectAction(laOperator *a, laEvent *e){
|
|
|
|
+ laEnableOperatorPanel(a, 0, e->x-50,e->y-50,500,500,10000,0,0,0,0,0,0,0,e);
|
|
|
|
+ return LA_RUNNING;
|
|
|
|
+}
|
|
|
|
+void laui_AnimationSelectAction(laUiList *uil, laPropPack *This, laPropPack *OperatorProps, laColumn *UNUSED, int context){
|
|
|
|
+ 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;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
int OPINV_AnimationPlayAction(laOperator *a, laEvent *e){
|
|
int OPINV_AnimationPlayAction(laOperator *a, laEvent *e){
|
|
char* str=strGetArgumentString(a->ExtraInstructionsP, "mode");
|
|
char* str=strGetArgumentString(a->ExtraInstructionsP, "mode");
|
|
int PlayStatus=LA_ANIMATION_STATUS_PAUSED;
|
|
int PlayStatus=LA_ANIMATION_STATUS_PAUSED;
|
|
@@ -192,23 +281,28 @@ void la_AnimationEvaluateActionChannels(laAction* aa){
|
|
void la_AnimationEvaluateActions(int ClampOffsets){
|
|
void la_AnimationEvaluateActions(int ClampOffsets){
|
|
int any=0;
|
|
int any=0;
|
|
la_AnimationMarkPropReset();
|
|
la_AnimationMarkPropReset();
|
|
- for(laAction* aa=MAIN.Animation->Actions.pFirst;aa;aa=aa->Item.pNext){
|
|
|
|
- real preoffset=0,postoffset=aa->Offset/aa->Length;
|
|
|
|
- if(ClampOffsets || (MAIN.Animation->PlayStatus!=LA_ANIMATION_STATUS_PAUSED)){
|
|
|
|
- while(aa->Offset>aa->Length){ aa->Offset-=aa->Length; }
|
|
|
|
- while(aa->Offset<-1e-6){ aa->Offset+=aa->Length; }
|
|
|
|
- preoffset=aa->Offset; postoffset=0;
|
|
|
|
|
|
+ for(laActionHolder* ah=MAIN.Animation->ActionHolders.pFirst;ah;ah=ah->Item.pNext){
|
|
|
|
+ if(!ah->Instance) continue;
|
|
|
|
+ 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)){
|
|
|
|
+ while(aa->Offset>aa->Length){ aa->Offset-=aa->Length; }
|
|
|
|
+ while(aa->Offset<-1e-6){ aa->Offset+=aa->Length; }
|
|
|
|
+ preoffset=aa->Offset; postoffset=0;
|
|
|
|
+ }
|
|
|
|
+ real UseTime=MAIN.Animation->PlayHead-preoffset;
|
|
|
|
+ int repeats=UseTime/aa->Length;
|
|
|
|
+ real remaining=UseTime-repeats*aa->Length;
|
|
|
|
+ while(remaining<0){ remaining+=aa->Length; }
|
|
|
|
+ if(aa->PlayMode==LA_ANIMATION_PLAY_MODE_REPEAT){ aa->PlayHead=remaining/aa->Length-postoffset; }
|
|
|
|
+ elif(aa->PlayMode==LA_ANIMATION_PLAY_MODE_HOLD){ aa->PlayHead=((UseTime>aa->Length)?1.0:(UseTime<0?0:UseTime/aa->Length))-postoffset; }
|
|
|
|
+ elif(aa->PlayMode==LA_ANIMATION_PLAY_MODE_BOUNCE){ real t=remaining/aa->Length; aa->PlayHead=((repeats%2)?(1-t):t)-postoffset; }
|
|
|
|
+ any=1;
|
|
|
|
+ la_AnimationEvaluateActionChannels(aa);
|
|
}
|
|
}
|
|
- real UseTime=MAIN.Animation->PlayHead-preoffset;
|
|
|
|
- int repeats=UseTime/aa->Length;
|
|
|
|
- real remaining=UseTime-repeats*aa->Length;
|
|
|
|
- while(remaining<0){ remaining+=aa->Length; }
|
|
|
|
- if(aa->PlayMode==LA_ANIMATION_PLAY_MODE_REPEAT){ aa->PlayHead=remaining/aa->Length-postoffset; }
|
|
|
|
- elif(aa->PlayMode==LA_ANIMATION_PLAY_MODE_HOLD){ aa->PlayHead=((UseTime>aa->Length)?1.0:(UseTime<0?0:UseTime/aa->Length))-postoffset; }
|
|
|
|
- elif(aa->PlayMode==LA_ANIMATION_PLAY_MODE_BOUNCE){ real t=remaining/aa->Length; aa->PlayHead=((repeats%2)?(1-t):t)-postoffset; }
|
|
|
|
- any=1;
|
|
|
|
- la_AnimationEvaluateActionChannels(aa);
|
|
|
|
}
|
|
}
|
|
|
|
+
|
|
for(laActionProp* ap=MAIN.Animation->Props.pFirst;ap;ap=ap->Item.pNext){ if(ap->Reset){ continue; }
|
|
for(laActionProp* ap=MAIN.Animation->Props.pFirst;ap;ap=ap->Item.pNext){ if(ap->Reset){ continue; }
|
|
la_AnimationSetPropValue(ap);
|
|
la_AnimationSetPropValue(ap);
|
|
}
|
|
}
|
|
@@ -548,7 +642,16 @@ void la_AnimationActionDrawOverlay(laUiItem *ui, int h){
|
|
void la_RegisterAnimationResources(){
|
|
void la_RegisterAnimationResources(){
|
|
laPropContainer *pc; laProp *p; laOperatorType *at; laEnumProp *ep;
|
|
laPropContainer *pc; laProp *p; laOperatorType *at; laEnumProp *ep;
|
|
|
|
|
|
- laCreateOperatorType("LA_animation_new_action", "New Action", "Add a new action",0,0,0,OPINV_AnimationNewAction,0,U'🞦',0);
|
|
|
|
|
|
+ at=laCreateOperatorType("LA_animation_new_action", "New Action", "Add a new action",0,0,0,OPINV_AnimationNewAction,OPMOD_AnimationNewAction,U'🞦',0);
|
|
|
|
+ pc = laDefineOperatorProps(at, 0);
|
|
|
|
+ p = laAddSubGroup(pc, "holder", "Holder", "Action holder to add the new action into", "la_animation_action_holder",
|
|
|
|
+ 0, 0, laui_IdentifierOnly, -1, laget_AnimationFirstActionHolder, 0, laget_ListNext, 0, 0, laset_AnimationNewActionSetHolder,0,0);
|
|
|
|
+ laSubGroupExtraFunctions(p,0,0,0,laget_AnimationActionHolderCategory);
|
|
|
|
+ at->UiDefine=laui_AnimationNewAction;
|
|
|
|
+
|
|
|
|
+ at=laCreateOperatorType("LA_animation_select_action", "Select Action", "Select an action",0,0,0,OPINV_AnimationSelectAction,OPMOD_FinishOnData,U'⯆',0);
|
|
|
|
+ at->UiDefine=laui_AnimationSelectAction;
|
|
|
|
+
|
|
laCreateOperatorType("LA_animation_set_play_status", "Set Play", "Set global animation player status",0,0,0,OPINV_AnimationPlayAction,0,0,0);
|
|
laCreateOperatorType("LA_animation_set_play_status", "Set Play", "Set global animation player status",0,0,0,OPINV_AnimationPlayAction,0,0,0);
|
|
laCreateOperatorType("LA_animation_reset_time", "Reset Time", "Reset Time",0,0,0,OPINV_AnimationResetTime,0,U'🡄',0);
|
|
laCreateOperatorType("LA_animation_reset_time", "Reset Time", "Reset Time",0,0,0,OPINV_AnimationResetTime,0,U'🡄',0);
|
|
|
|
|