*/}}

la_animation.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. /*
  2. * LaGUI: A graphical application framework.
  3. * Copyright (C) 2022-2023 Wu Yiming
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include "la_5.h"
  19. extern LA MAIN;
  20. int la_GetKeyablePropertyStorageSize(laProp* p);
  21. laAction* laAnimiationNewAction(char* Name){
  22. laAction* aa=memAcquire(sizeof(laAction));
  23. if(!Name || !Name[0]){ Name="New Action"; }
  24. strSafeSet(&aa->Name,Name);
  25. aa->Length=5; aa->FrameCount=120;
  26. lstAppendItem(&MAIN.Actions,aa);
  27. laNotifyUsers("la.actions");
  28. return aa;
  29. }
  30. laAnimationChannel* laAnimationEnsureChannel(laAction* aa, void* hyper1, laProp* p){
  31. laAnimationChannel* acf=0;
  32. int DataSize=la_GetKeyablePropertyStorageSize(p); if(!DataSize) return 0;
  33. for(laAnimationChannel* ac=aa->Channels.pFirst;ac;ac=ac->Item.pNext){
  34. if(ac->For==hyper1 && ac->Prop==p){ acf=ac; break; }
  35. }
  36. if(acf) return acf;
  37. acf=memAcquire(sizeof(laAnimationChannel));
  38. memAssignRef(acf,&acf->For,hyper1); acf->Prop=p;
  39. acf->DataSize = DataSize;
  40. lstAppendItem(&aa->Channels,acf);
  41. return acf;
  42. }
  43. laAnimationChannel* laAnimationEnsureFrame(laAnimationChannel* ac, int frame){
  44. laAnimationKey* akf=0,*beforeakf=0;
  45. for(laAnimationKey* ak=ac->Keys.pFirst;ak;ak=ak->Item.pNext){
  46. if(ak->At==frame){ akf=ak; break; } if(ak->At>frame){ beforeakf=ak; break; }
  47. }
  48. if(!akf){
  49. akf=memAcquireSimple(sizeof(laAnimationKey)-sizeof(uint64_t)+ac->DataSize);
  50. akf->At=frame;
  51. if(beforeakf){ lstInsertItemBefore(&ac->Keys, akf, beforeakf); }
  52. lstAppendItem(&ac->Keys, akf);
  53. }
  54. return akf;
  55. }
  56. void laAnimationStoreKeyValue(laAnimationChannel* ac, laAnimationKey* ak){
  57. laPropPack PP={0}; laPropStep PS={0};
  58. PS.p=ac->Prop; PS.Type='.'; PS.UseInstance=ac->For; PP.LastPs=&PS; PP.EndInstance=ac->For;
  59. switch(ac->Prop->PropertyType){
  60. case LA_PROP_INT: case LA_PROP_INT | LA_PROP_ARRAY: laGetIntArray(&PP,(int*)&ak->Data);
  61. case LA_PROP_FLOAT: case LA_PROP_FLOAT | LA_PROP_ARRAY: laGetFloatArray(&PP,(real*)&ak->Data);
  62. case LA_PROP_ENUM: case LA_PROP_ENUM | LA_PROP_ARRAY: laGetEnumArray(&PP,(laEnumItem**)&ak->Data);
  63. case LA_PROP_SUB: case LA_PROP_OPERATOR: case LA_PROP_STRING: case LA_PROP_RAW: default: return;
  64. }
  65. }
  66. laAnimationKey* laAnimationInsertKeyFrame(laAction* aa, void* hyper1, laProp* p){
  67. laAnimationChannel* ac=laAnimationEnsureChannel(aa,hyper1,p); if(!ac || !ac->For) return;
  68. int frame=aa->PlayHead/aa->Length*aa->FrameCount;
  69. laAnimationKey* ak=laAnimationEnsureFrame(ac->DataSize,frame);
  70. laAnimationStoreKeyValue(ac,ak);
  71. }
  72. void laAnimationSetPlayStatus(int PlayStatus){
  73. if(PlayStatus>3||PlayStatus<0) PlayStatus=0; MAIN.AnimationPlayStatus=PlayStatus;
  74. if(PlayStatus) laRecordTime(&MAIN.AnimationTimeOrigin);
  75. laNotifyUsers("la.animation_play_status");
  76. }
  77. void laAnimationSetPlayHead(real time){
  78. MAIN.AnimationPlayHead=time;
  79. }
  80. int OPINV_AnimationNewAction(laOperator *a, laEvent *e){
  81. laAnimiationNewAction(0);
  82. return LA_FINISHED;
  83. }
  84. int OPINV_AnimationPlayAction(laOperator *a, laEvent *e){
  85. char* str=strGetArgumentString(a->ExtraInstructionsP, "mode");
  86. int PlayStatus=LA_ANIMATION_STATUS_PAUSED;
  87. if(strSame(str,"forward")){ PlayStatus=LA_ANIMATION_STATUS_PLAY_FWD; }
  88. elif(strSame(str,"reverse")){ if(MAIN.AnimationPlayHead>0) PlayStatus=LA_ANIMATION_STATUS_PLAY_REV; }
  89. laAnimationSetPlayStatus(PlayStatus);
  90. return LA_FINISHED;
  91. }
  92. int OPINV_AnimationResetTime(laOperator *a, laEvent *e){
  93. laAnimationSetPlayHead(0);
  94. return LA_FINISHED;
  95. }
  96. void la_AnimationEvaluateActions(){
  97. /* ehh well */
  98. }
  99. void la_AnimationPreFrame(){
  100. if(MAIN.AnimationPlayHead<0){
  101. MAIN.AnimationPlayHead=0; laAnimationSetPlayStatus(0);
  102. laNotifyUsers("la.animation_play_head");
  103. }
  104. if(MAIN.AnimationPlayStatus){
  105. la_AnimationEvaluateActions();
  106. }
  107. }
  108. void la_AnimationPostFrame(){
  109. laTimeRecorder cur={0};
  110. if(MAIN.AnimationPlayStatus){ laRecordTime(&cur);
  111. real td=laTimeElapsedSecondsf(&cur,&MAIN.AnimationTimeOrigin);
  112. laRecordTime(&MAIN.AnimationTimeOrigin);
  113. if(MAIN.AnimationPlayStatus==LA_ANIMATION_STATUS_PLAY_REV){ td*=-1; }
  114. MAIN.AnimationPlayHead+=td; laNotifyUsers("la.animation_play_head");
  115. }
  116. }
  117. void la_RegisterAnimationResources(){
  118. laPropContainer *pc; laProp *p; laOperatorType *at; laEnumProp *ep;
  119. laCreateOperatorType("LA_animation_new_action", "New Action", "Add a new action",0,0,0,OPINV_AnimationNewAction,0,0,0);
  120. laCreateOperatorType("LA_animation_set_play_status", "Set Play", "Set global animation player status",0,0,0,OPINV_AnimationPlayAction,0,0,0);
  121. laCreateOperatorType("LA_animation_reset_time", "Reset Time", "Reset Time",0,0,0,OPINV_AnimationResetTime,0,U'🡄',0);
  122. }