*/}}

la_nodes_basic.c 85 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374
  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. extern struct _tnsMain *T;
  21. laBaseNodeType LA_IDN_KEYBOARD;
  22. laBaseNodeType LA_IDN_MOUSE;
  23. laBaseNodeType LA_IDN_CONTROLLER;
  24. laBaseNodeType LA_IDN_VISUALIZER;
  25. laBaseNodeType LA_IDN_SPLIT;
  26. laBaseNodeType LA_IDN_SWITCH;
  27. laBaseNodeType LA_IDN_COMBINE;
  28. laBaseNodeType LA_IDN_VALUES;
  29. laBaseNodeType LA_IDN_MATRIX;
  30. laBaseNodeType LA_IDN_MATH;
  31. laBaseNodeType LA_IDN_SMALL_MATH;
  32. laBaseNodeType LA_IDN_MAPPER;
  33. laBaseNodeType LA_IDN_RANDOM;
  34. laBaseNodeType LA_IDN_VECTOR_MATH;
  35. laBaseNodeType LA_IDN_COMMENT;
  36. laBaseNodeType LA_IDN_RGB2OKHSL;
  37. laBaseNodeType LA_IDN_OKHSL2RGB;
  38. laPropContainer* LA_PC_IDN_GENERIC;
  39. laPropContainer* LA_PC_IDN_KEYBOARD;
  40. laPropContainer* LA_PC_IDN_MOUSE;
  41. laPropContainer* LA_PC_IDN_CONTROLLER;
  42. laPropContainer* LA_PC_IDN_VISUALIZER;
  43. laPropContainer* LA_PC_IDN_SPLIT;
  44. laPropContainer* LA_PC_IDN_SWITCH;
  45. laPropContainer* LA_PC_IDN_COMBINE;
  46. laPropContainer* LA_PC_IDN_VALUES;
  47. laPropContainer* LA_PC_IDN_MATRIX;
  48. laPropContainer* LA_PC_IDN_MATH;
  49. laPropContainer* LA_PC_IDN_SMALL_MATH;
  50. laPropContainer* LA_PC_IDN_MAPPER;
  51. laPropContainer* LA_PC_IDN_RANDOM;
  52. laPropContainer* LA_PC_IDN_VECTOR_MATH;
  53. laPropContainer* LA_PC_IDN_COMMENT;
  54. laPropContainer* LA_PC_IDN_RGB2OKHSL;
  55. laPropContainer* LA_PC_IDN_OKHSL2RGB;
  56. laNodeCategory* LA_NODE_CATEGORY_INPUT;
  57. laNodeCategory* LA_NODE_CATEGORY_MATH;
  58. laNodeCategory* LA_NODE_CATEGORY_ROUTE;
  59. laNodeCategory* LA_NODE_CATEGORY_AUX;
  60. laNodeCategory* LA_NODE_CATEGORY_DRIVER;
  61. laNodeCategory* LA_NODE_CATEGORY_COLOR;
  62. #define LA_IDN_CONTROLLER_RESET_SOCKET(ns) \
  63. {ns->IntVal[0]=0; ns->Out->DataType=LA_PROP_INT; ns->Offset=0; ns->Out->Data=&ns->IntVal;}
  64. void IDN_ControllerInit(laInputControllerNode* n, int NoCreate){
  65. if(NoCreate){return;}
  66. for(int i=0;i<8;i++){ n->Sockets[i].Out=laCreateOutSocket(n, "out", 0); n->Sockets[i].Parent=n; }
  67. strSafeSet(&n->Base.Name,"Controller Output");
  68. }
  69. void IDN_ControllerDestroy(laInputControllerNode* n){
  70. for(int i=0;i<8;i++){ laDestroyOutSocket(n->Sockets[i].Out); }
  71. strSafeDestroy(&n->Base.Name);
  72. }
  73. int IDN_ControllerVisit(laInputControllerNode* n, laNodeVisitInfo* vi){
  74. laController* c=la_FindControllerWithID(n->UserID);
  75. if(!c){ for(int i=0;i<8;i++){ laInputControllerNodeSocket* ns=&n->Sockets[i]; LA_IDN_CONTROLLER_RESET_SOCKET(ns); } return LA_DAG_FLAG_PERM; }
  76. else{
  77. for(int i=0;i<8;i++){ laInputControllerNodeSocket* ns=&n->Sockets[i];
  78. if(!ns->Which || !ns->Which->Ptr){ LA_IDN_CONTROLLER_RESET_SOCKET(ns); continue; }
  79. laPropContainer*pc=la_EnsureSubTarget(LA_PROP_CONTROLLER, c);
  80. laProp* p=la_PropLookup(&pc->Props, n->Sockets[i].Which->Ptr);
  81. if((!p)||(!p->Offset)||
  82. ((p->PropertyType!=LA_PROP_INT)&&(p->PropertyType!=LA_PROP_ENUM)&&
  83. (p->PropertyType!=(LA_PROP_INT|LA_PROP_ARRAY))&&(p->PropertyType!=(LA_PROP_ENUM|LA_PROP_ARRAY)))){ LA_IDN_CONTROLLER_RESET_SOCKET(ns); continue; }
  84. if(p->PropertyType==LA_PROP_INT){ ns->Out->DataType=LA_PROP_FLOAT; ns->Out->Data=&ns->RealVal; ns->Out->ArrLen=1; }
  85. elif(p->PropertyType==(LA_PROP_INT|LA_PROP_ARRAY)){ ns->Out->DataType=(LA_PROP_FLOAT|LA_PROP_ARRAY); ns->Out->Data=&ns->RealVal; ns->Out->ArrLen=p->Len; }
  86. elif(p->PropertyType==LA_PROP_ENUM){ ns->Out->DataType=LA_PROP_ENUM; ns->Out->Data=&ns->IntVal; ns->Out->ArrLen=1; }
  87. elif(p->PropertyType==(LA_PROP_ENUM|LA_PROP_ARRAY)){ ns->Out->DataType=(LA_PROP_ENUM|LA_PROP_ARRAY); ns->Out->Data=&ns->IntVal; ns->Out->ArrLen=p->Len; }
  88. ns->Offset=p->Offset;
  89. }
  90. }
  91. LA_ADD_THIS_NODE(n,vi);
  92. return LA_DAG_FLAG_PERM;
  93. }
  94. int IDN_ControllerEval(laInputControllerNode* n){
  95. laNotifyInstanceUsers(n);
  96. laController* c=la_FindControllerWithID(n->UserID); if(!c){
  97. for(int i=0;i<8;i++){ laInputControllerNodeSocket* ns=&n->Sockets[i]; LA_IDN_CONTROLLER_RESET_SOCKET(ns); } return 1;
  98. }
  99. for(int i=0;i<8;i++){ laInputControllerNodeSocket* ns=&n->Sockets[i];
  100. int *addr=((char*)c)+ns->Offset; char* addc=addr;
  101. if(ns->Out->DataType==LA_PROP_FLOAT){ ns->RealVal[0]=(real)(*addr)/32767.0; }
  102. if(ns->Out->DataType==(LA_PROP_FLOAT|LA_PROP_ARRAY)){ for(int a=0;a<ns->Out->ArrLen;a++) ns->RealVal[a]=((real)addr[a])/32767.0; }
  103. elif(ns->Out->DataType==LA_PROP_ENUM){ ns->IntVal[0]=(*addc); }
  104. elif(ns->Out->DataType==(LA_PROP_ENUM|LA_PROP_ARRAY)){ for(int a=0;a<ns->Out->ArrLen;a++) ns->IntVal[a]=addc[a]; }
  105. }
  106. return 1;
  107. }
  108. void laui_ControllerNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){
  109. laColumn* c=laFirstColumn(uil); laInputControllerNode*n=This->EndInstance;
  110. laColumn* cl,*cr;
  111. LA_BASE_NODE_HEADER(uil,c,This);
  112. laSplitColumn(uil,c,0.3); cl=laLeftColumn(c,0); cr=laRightColumn(c,0);
  113. laUiItem* b=laBeginRow(uil,c,0,0);
  114. laShowItem(uil,c,This,"base.name")->Expand=1;
  115. laShowItem(uil,c,This,"user_id");
  116. laEndRow(uil,b);
  117. char* buf[128],buf2[128];
  118. for(int i=0;i<8;i++){
  119. sprintf(buf,"out%d.which",i); laShowItem(uil,cl,This,buf);
  120. laUiItem* b=laBeginRow(uil,cr,0,0);
  121. sprintf(buf2,"out%d.out.data_type",i);
  122. laUiItem* b2=laOnConditionThat(uil,cr,laEqual(laPropExpression(This,buf2),laIntExpression(LA_PROP_FLOAT)));{
  123. sprintf(buf,"out%d.axis",i); laShowItem(uil,cr,This,buf)->Expand=1;
  124. }laElse(uil,b2);{
  125. laUiItem* b3=laOnConditionThat(uil,cr,laEqual(laPropExpression(This,buf2),laIntExpression(LA_PROP_FLOAT|LA_PROP_ARRAY)));{
  126. sprintf(buf,"out%d.axis2d",i); laUiItem* aui=laShowItem(uil,cr,This,buf);aui->Expand=1;aui->Flags|=LA_UI_FLAGS_TRANSPOSE;aui->Extra->HeightCoeff=1;
  127. }laElse(uil,b3);{
  128. sprintf(buf,"out%d.switch",i); laUiItem* sui=laShowItem(uil,cr,This,buf);sui->Expand=1;sui->Flags|=LA_UI_FLAGS_TRANSPOSE;
  129. }laEndCondition(uil,b3);
  130. }laEndCondition(uil,b2);
  131. sprintf(buf,"out%d.out",i); laShowNodeSocket(uil,cr,This,buf,0);
  132. laEndRow(uil,b);
  133. }
  134. }
  135. void IDN_InputVisualizeInit(laInputVisualizerNode* n, int NoCreate){
  136. if(NoCreate){return;}
  137. n->In=laCreateInSocket("IN", 0);
  138. strSafeSet(&n->Base.Name,"Input Visualizer");
  139. }
  140. void IDN_InputVisualizeDestroy(laInputVisualizerNode* n){
  141. laDestroyInSocket(n->In);
  142. strSafeDestroy(&n->Base.Name);
  143. }
  144. int IDN_InputVisualizeVisit(laInputVisualizerNode* n, laNodeVisitInfo* vi){
  145. LA_GUARD_THIS_NODE(n,vi);
  146. if(LA_SRC_AND_PARENT(n->In)){ laBaseNode* sn=n->In->Source->Parent;LA_VISIT_NODE(sn,vi); }
  147. LA_ADD_THIS_NODE(n,vi);
  148. return LA_DAG_FLAG_PERM;
  149. }
  150. int IDN_InputVisualizerEval(laInputVisualizerNode* n){
  151. if(!n->In->Source) return 0;
  152. laNodeOutSocket* os=n->In->Source; int arrlen=1;
  153. switch(os->DataType){
  154. case LA_PROP_FLOAT|LA_PROP_ARRAY:
  155. case LA_PROP_FLOAT: if(os->ArrLen)arrlen=os->ArrLen; memcpy(n->RealVal,os->Data,sizeof(real)*arrlen); n->In->ArrLen=arrlen; break;
  156. case LA_PROP_ENUM|LA_PROP_ARRAY:
  157. case LA_PROP_ENUM: if(os->ArrLen)arrlen=os->ArrLen; memcpy(n->IntVal,os->Data,sizeof(int)*arrlen); n->In->ArrLen=arrlen; break;
  158. default: n->IntVal[0]=0; n->In->ArrLen=1; break;
  159. }
  160. n->In->DataType=os->DataType;
  161. laNotifyInstanceUsers(n);
  162. return 1;
  163. }
  164. void laui_InputVisualizeNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){
  165. laColumn* c=laFirstColumn(uil); laInputVisualizerNode*n=This->EndInstance;
  166. LA_BASE_NODE_HEADER(uil,c,This);
  167. laColumn* cl,*cr; laSplitColumn(uil,c,0.4); cl=laLeftColumn(c,1); cr=laRightColumn(c,0);
  168. laShowNodeSocket(uil,cl,This,"in",0);
  169. laUiItem* b2=laOnConditionThat(uil,cr,laEqual(laPropExpression(This,"in.data_type"),laIntExpression(LA_PROP_FLOAT)));{
  170. laShowItem(uil,cr,This,"axis");
  171. }laElse(uil,b2);{
  172. laUiItem* b3=laOnConditionThat(uil,cr,laEqual(laPropExpression(This,"in.data_type"),laIntExpression(LA_PROP_FLOAT|LA_PROP_ARRAY)));{
  173. laUiItem* aui=laShowItem(uil,cr,This,"axis2d");
  174. }laElse(uil,b3);{
  175. laUiItem* sui=laShowItem(uil,cr,This,"switch");
  176. }laEndCondition(uil,b3);
  177. }laEndCondition(uil,b2);
  178. }
  179. void IDN_SplitInit(laSplitNode* n, int NoCreate){
  180. if(NoCreate){return;}
  181. n->In=laCreateInSocket("in", 0); strSafeSet(&n->Base.Name,"Split");
  182. for(int i=0;i<8;i++){ char str[4]; sprintf(str,"%d",i); n->Out[i].Out=laCreateOutSocket(n,str,0); }
  183. }
  184. void IDN_SplitDestroy(laSplitNode* n){
  185. laDestroyInSocket(n->In); strSafeDestroy(&n->Base.Name);
  186. for(int i=0;i<8;i++){ laDestroyOutSocket(n->Out[i].Out); }
  187. }
  188. int IDN_SplitVisit(laSplitNode* n, laNodeVisitInfo* vi){
  189. LA_GUARD_THIS_NODE(n,vi);
  190. if(LA_SRC_AND_PARENT(n->In)){ laBaseNode* sn=n->In->Source->Parent; LA_VISIT_NODE(sn,vi); }
  191. LA_ADD_THIS_NODE(n,vi);
  192. return LA_DAG_FLAG_PERM;
  193. }
  194. int IDN_SplitEval(laSplitNode* n){
  195. if(!n->In->Source) return 0;
  196. laNodeOutSocket* os=n->In->Source; int arrlen=1;
  197. switch(os->DataType){
  198. case LA_PROP_FLOAT|LA_PROP_ARRAY:
  199. case LA_PROP_FLOAT: if(os->ArrLen) n->ArrLen=os->ArrLen;
  200. for(int i=0;i<TNS_MIN2(n->ArrLen,8);i++){ n->Out[i].Out->DataType=LA_PROP_FLOAT; n->Out[i].Out->Data=&n->RealVal[i]; }
  201. memcpy(n->RealVal,os->Data,sizeof(real)*n->ArrLen); n->In->ArrLen=arrlen; break;
  202. case LA_PROP_ENUM|LA_PROP_ARRAY:
  203. case LA_PROP_ENUM: if(os->ArrLen) n->ArrLen=os->ArrLen;
  204. for(int i=0;i<TNS_MIN2(n->ArrLen,8);i++){ n->Out[i].Out->DataType=LA_PROP_ENUM; n->Out[i].Out->Data=&n->IntVal[i]; }
  205. memcpy(n->IntVal,os->Data,sizeof(int)*n->ArrLen); n->In->ArrLen=arrlen; break;
  206. default:
  207. for(int i=0;i<TNS_MIN2(n->ArrLen,8);i++){ n->Out[i].Out->DataType=LA_PROP_ENUM; n->Out[i].Out->Data=&n->IntVal[i]; }
  208. n->IntVal[0]=0; n->In->ArrLen=1; break;
  209. }
  210. n->In->DataType=os->DataType;
  211. return 1;
  212. }
  213. void laui_SplitNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){
  214. laColumn* c=laFirstColumn(uil); laSplitNode*n=This->EndInstance;
  215. laColumn* cl,*cr; laSplitColumn(uil,c,0.4); cl=laLeftColumn(c,1); cr=laRightColumn(c,0);
  216. LA_BASE_NODE_HEADER(uil,c,This);
  217. laUiItem* b=laBeginRow(uil,c,0,0);
  218. laShowNodeSocket(uil,c,This,"in",0);
  219. laShowItemFull(uil,c,This,"array_length",LA_WIDGET_INT_PLAIN,0,0,0);
  220. laShowLabel(uil,c,"🡲",0,0)->Expand=1;
  221. for(int i=0;i<8;i++){
  222. char* buf[128]; sprintf(buf,"out%d.out",i); laShowNodeSocket(uil,cr,This,buf,0);
  223. }
  224. laEndRow(uil,b);
  225. }
  226. void IDN_SwitchInit(laSwitchNode* n, int NoCreate){
  227. if(NoCreate){return;}
  228. n->SwitchIn=laCreateInSocket("sw in",0); n->Out=laCreateOutSocket(n,"out",0); strSafeSet(&n->Base.Name,"Switch");
  229. for(int i=0;i<8;i++){ char str[4]; sprintf(str,"%d",i); n->In[i].In=laCreateInSocket(n,str); }
  230. }
  231. void IDN_SwitchDestroy(laSwitchNode* n){
  232. laDestroyInSocket(n->SwitchIn); laDestroyOutSocket(n->Out); strSafeDestroy(&n->Base.Name);
  233. for(int i=0;i<8;i++){ laDestroyInSocket(n->In[i].In); }
  234. }
  235. int IDN_SwitchVisit(laSwitchNode* n, laNodeVisitInfo* vi){
  236. LA_GUARD_THIS_NODE(n,vi); n->MaxUsed=0; n->Page=vi->Page;
  237. for(int i=0;i<8;i++){ if(n->In[i].In->Source){ n->MaxUsed=i+2; } }
  238. uint64_t OrigBranch=vi->Branch; int NextBranch=vi->NextBranch;
  239. vi->NextBranch+=n->MaxUsed; n->BranchSW=(1<<(NextBranch-1));
  240. if(OrigBranch==1){ lstAppendPointer(vi->br,n); }
  241. for(int i=0;i<8;i++){
  242. if(n->In[i].In->Source){
  243. vi->Branch=OrigBranch|(1<<(NextBranch+i));
  244. laBaseNode* sn=n->In[i].In->Source->Parent; LA_VISIT_NODE(sn,vi);
  245. }
  246. }
  247. vi->Branch=OrigBranch|n->BranchSW;
  248. laBaseNode* sw=n->SwitchIn->Source?n->SwitchIn->Source->Parent:0; if(sw){ LA_VISIT_NODE(sw,vi); }
  249. vi->Branch=OrigBranch;
  250. LA_ADD_THIS_NODE(n,vi);
  251. return LA_DAG_FLAG_PERM;
  252. }
  253. int IDN_SwitchEval(laSwitchNode* n){
  254. int sw=n->Switch;
  255. if(n->SwitchIn->Source){
  256. laRunPage(n->Page,n->BranchSW);
  257. laNodeOutSocket* os=n->SwitchIn->Source; int* id; real* fd;
  258. switch(os->DataType){
  259. case LA_PROP_ARRAY|LA_PROP_ENUM:
  260. id=os->Data; for(int i=0;i<os->ArrLen;i++){ if(id[i]){sw=i; break;} } break;
  261. case LA_PROP_ENUM: case LA_PROP_INT: case LA_PROP_INT|LA_PROP_ARRAY:
  262. id=os->Data; sw=*id; break;
  263. case LA_PROP_FLOAT: case LA_PROP_FLOAT|LA_PROP_ARRAY:
  264. fd=os->Data; sw=(int)(*fd); break;
  265. default: sw=0; break;
  266. }
  267. }
  268. laRunPage(n->Page,(n->BranchSW<<(sw+1)));
  269. TNS_CLAMP(sw,0,7);
  270. laSwitchNodeInSocket *is=&n->In[sw];
  271. if(is->In->Source){ n->Out->Data=is->In->Source->Data; n->Out->DataType=is->In->Source->DataType; n->Out->ArrLen=is->In->Source->ArrLen; }
  272. else{ n->Out->Data=&n->TempVal; n->Out->DataType=LA_PROP_FLOAT; n->Out->ArrLen=1; }
  273. return 1;
  274. }
  275. void laui_SwitchNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){
  276. laColumn* c=laFirstColumn(uil); laSwitchNode*n=This->EndInstance;
  277. laColumn* cl,*cr; laSplitColumn(uil,c,0.4); cl=laLeftColumn(c,1); cr=laRightColumn(c,0);
  278. LA_BASE_NODE_HEADER(uil,c,This);
  279. laUiItem* b=laBeginRow(uil,c,0,0);
  280. for(int i=0;i<8;i++){
  281. char* buf[128]; sprintf(buf,"in%d.in",i); laShowNodeSocket(uil,cr,This,buf,0);
  282. } laShowSeparator(uil,c)->Expand=1;
  283. laEndRow(uil,b);
  284. b=laBeginRow(uil,c,0,0);
  285. laShowItem(uil,c,This,"switch_in");
  286. laUiItem* b2=laOnConditionThat(uil,c,laNot(laPropExpression(This,"switch_in.source")));{
  287. laShowItem(uil,c,This,"switch");
  288. };laEndCondition(uil,b2);
  289. laShowSeparator(uil,c)->Expand=1;
  290. laShowNodeSocket(uil,c,This,"out",0);
  291. laEndRow(uil,b);
  292. }
  293. void IDN_CombineInit(laCombineNode* n, int NoCreate){
  294. if(!NoCreate){
  295. n->Out=laCreateOutSocket(n,"F",0);n->OutInt=laCreateOutSocket(n,"I",0);n->OutEnum=laCreateOutSocket(n,"E",0); strSafeSet(&n->Base.Name,"Combine");
  296. for(int i=0;i<8;i++){ char str[4]; sprintf(str,"%d",i); n->In[i].In=laCreateInSocket(n,str); }
  297. }
  298. n->Out->Data=n->Values; n->OutInt->Data=n->ValuesI; n->OutEnum->Data=n->ValuesI;
  299. n->Out->DataType=LA_PROP_FLOAT|LA_PROP_ARRAY; n->OutInt->DataType=LA_PROP_INT|LA_PROP_ARRAY; n->OutEnum->DataType=LA_PROP_ENUM|LA_PROP_ARRAY;
  300. }
  301. void IDN_CombineDestroy(laCombineNode* n){
  302. laDestroyOutSocket(n->Out);laDestroyOutSocket(n->OutInt);laDestroyOutSocket(n->OutEnum); strSafeDestroy(&n->Base.Name);
  303. for(int i=0;i<8;i++){ laDestroyInSocket(n->In[i].In); }
  304. }
  305. int IDN_CombineVisit(laCombineNode* n, laNodeVisitInfo* vi){
  306. LA_GUARD_THIS_NODE(n,vi);
  307. for(int i=0;i<8;i++){ if(LA_SRC_AND_PARENT(n->In[i].In)){ laBaseNode* sn=n->In[i].In->Source->Parent; LA_VISIT_NODE(sn,vi); } }
  308. LA_ADD_THIS_NODE(n,vi);
  309. return LA_DAG_FLAG_PERM;
  310. }
  311. int IDN_CombineEval(laCombineNode* n){
  312. int maxlen=0;
  313. for(int i=0;i<8;i++){ laNodeInSocket *is=n->In[i].In;
  314. if(LA_SRC_AND_PARENT(is)){
  315. if((is->Source->DataType&LA_PROP_FLOAT) && is->Source->Data){ n->Values[i]=*((real*)is->Source->Data); }
  316. elif((is->Source->DataType&LA_PROP_INT) && is->Source->Data){ n->Values[i]=*((int*)is->Source->Data); }
  317. elif((is->Source->DataType&LA_PROP_ENUM) && is->Source->Data){ n->Values[i]=*((int*)is->Source->Data); }
  318. else n->Values[i]=0;
  319. maxlen=i+1;
  320. }
  321. else n->Values[i]=0;
  322. n->ValuesI[i]=n->Values[i];
  323. }
  324. n->Out->ArrLen=n->OutInt->ArrLen=n->OutEnum->ArrLen=maxlen;
  325. return 1;
  326. }
  327. void laui_CombineNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){
  328. laColumn* c=laFirstColumn(uil); laCombineNode*n=This->EndInstance;
  329. laColumn* cl,*cr; laSplitColumn(uil,c,0.4); cl=laLeftColumn(c,1); cr=laRightColumn(c,0);
  330. LA_BASE_NODE_HEADER(uil,c,This);
  331. laUiItem* b=laBeginRow(uil,c,0,0);
  332. for(int i=0;i<8;i++){
  333. char* buf[128]; sprintf(buf,"in%d.in",i); laShowNodeSocket(uil,cr,This,buf,0);
  334. } laShowSeparator(uil,c)->Expand=1;
  335. laEndRow(uil,b);
  336. b=laBeginRow(uil,c,0,0);
  337. laUiItem* lu=laShowLabel(uil,c,"Combine 🡲",0,0); lu->Expand=1; lu->Flags|=LA_TEXT_ALIGN_RIGHT;
  338. laShowNodeSocket(uil,c,This,"out_enum",0)->Flags|=LA_UI_SOCKET_LABEL_W;
  339. laShowNodeSocket(uil,c,This,"out_int",0)->Flags|=LA_UI_SOCKET_LABEL_W;
  340. laShowNodeSocket(uil,c,This,"out",0)->Flags|=LA_UI_SOCKET_LABEL_W;
  341. laEndRow(uil,b);
  342. }
  343. void IDN_ValuesInit(laValuesNode* n, int NoCreate){
  344. if(NoCreate){return;}
  345. strSafeSet(&n->Base.Name,"Values");
  346. for(int i=0;i<8;i++){ char str[4]; sprintf(str,"%d",i); n->Out[i].Out=laCreateOutSocket(n,str,0); }
  347. }
  348. void IDN_ValuesDestroy(laValuesNode* n){
  349. strSafeDestroy(&n->Base.Name);
  350. for(int i=0;i<8;i++){ laDestroyOutSocket(n->Out[i].Out); }
  351. }
  352. int IDN_ValuesVisit(laValuesNode* n, laNodeVisitInfo* vi){
  353. LA_GUARD_THIS_NODE(n,vi);
  354. LA_ADD_THIS_NODE(n,vi);
  355. return LA_DAG_FLAG_PERM;
  356. }
  357. int IDN_ValuesEval(laValuesNode* n){
  358. for(int i=0;i<8;i++){ laNodeOutSocket *is=n->Out[i].Out;
  359. if(n->Modes[i]==LA_VALUES_NODE_FLOAT){ is->Data=&n->Values[i]; is->DataType=LA_PROP_FLOAT; }
  360. if(n->Modes[i]==LA_VALUES_NODE_INT){ is->Data=&n->ValuesI[i]; is->DataType=LA_PROP_INT; }
  361. if(n->Modes[i]==LA_VALUES_NODE_ENUM){ is->Data=&n->ValuesE[i]; is->DataType=LA_PROP_ENUM; }
  362. }
  363. return 1;
  364. }
  365. void laui_ValuesNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){
  366. laColumn* c=laFirstColumn(uil); laValuesNode*n=This->EndInstance;
  367. laUiItem*b,*b2;
  368. LA_BASE_NODE_HEADER(uil,c,This);
  369. laColumn* cl,*cr; laSplitColumn(uil,c,0.4); cl=laLeftColumn(c,3); cr=laRightColumn(c,0);
  370. for(int i=0;i<8;i++){
  371. char* bufm[32]; sprintf(bufm,"mode%d",i); laShowItem(uil,cl,This,bufm);
  372. b=laBeginRow(uil,cr,0,0);
  373. b2=laOnConditionThat(uil,cr,laEqual(laPropExpression(This,bufm),laIntExpression(LA_VALUES_NODE_FLOAT)));{
  374. char* buf[32]; sprintf(buf,"value%d",i); laShowItem(uil,cr,This,buf)->Expand=1;
  375. }laEndCondition(uil,b2);
  376. b2=laOnConditionThat(uil,cr,laEqual(laPropExpression(This,bufm),laIntExpression(LA_VALUES_NODE_INT)));{
  377. char* buf[32]; sprintf(buf,"valuei%d",i); laShowItem(uil,cr,This,buf)->Expand=1;
  378. }laEndCondition(uil,b2);
  379. b2=laOnConditionThat(uil,cr,laEqual(laPropExpression(This,bufm),laIntExpression(LA_VALUES_NODE_ENUM)));{
  380. char* buf[32]; sprintf(buf,"valuee%d",i); laUiItem* eui=laShowItem(uil,cr,This,buf); eui->Expand=1; eui->Flags|=LA_UI_FLAGS_HIGHLIGHT;
  381. }laEndCondition(uil,b2);
  382. sprintf(bufm,"out%d.out",i); laShowNodeSocket(uil,cr,This,bufm,0);
  383. laEndRow(uil,b);
  384. }
  385. }
  386. void IDN_MatrixInit(laMatrixNode* n, int NoCreate){
  387. if(!NoCreate){
  388. strSafeSet(&n->Base.Name,"Matrix");
  389. n->InL=laCreateInSocket("l",0); n->InR=laCreateInSocket("r",0); n->Out=laCreateOutSocket(n,"MAT",LA_PROP_FLOAT|LA_PROP_ARRAY);
  390. }
  391. n->Out->ArrLen=16; n->Out->Data=n->Mat;
  392. }
  393. void IDN_MatrixDestroy(laMatrixNode* n){
  394. strSafeDestroy(&n->Base.Name);
  395. laDestroyInSocket(n->InL); laDestroyInSocket(n->InR); laDestroyOutSocket(n->Out);
  396. }
  397. int IDN_MatrixVisit(laMatrixNode* n, laNodeVisitInfo* vi){
  398. LA_GUARD_THIS_NODE(n,vi);
  399. if(LA_SRC_AND_PARENT(n->InL)){ laBaseNode* bn=n->InL->Source->Parent; LA_VISIT_NODE(bn,vi); }
  400. if(LA_SRC_AND_PARENT(n->InR)){ laBaseNode* bn=n->InR->Source->Parent; LA_VISIT_NODE(bn,vi); }
  401. LA_ADD_THIS_NODE(n,vi);
  402. return LA_DAG_FLAG_PERM;
  403. }
  404. int IDN_MatrixEval(laMatrixNode* n){
  405. int hasl=LA_SRC_AND_PARENT(n->InL),hasr=LA_SRC_AND_PARENT(n->InR);
  406. if((!hasl) && (!hasr)){ tnsLoadIdentity44d(n->Mat); return 0; }
  407. if(hasl&&((n->InL->Source->DataType!=(LA_PROP_FLOAT|LA_PROP_ARRAY))||n->InL->Source->ArrLen!=16)){tnsLoadIdentity44d(n->Mat); return 0;}
  408. if(hasr&&((n->InR->Source->DataType!=(LA_PROP_FLOAT|LA_PROP_ARRAY))||n->InR->Source->ArrLen!=16)){tnsLoadIdentity44d(n->Mat); return 0;}
  409. if(n->Operation==LA_MATRIX_NODE_OP_INV){
  410. real* mat; if(hasl)mat=n->InL->Source->Data;else mat=n->InR->Source->Data;
  411. tnsInverse44d(n->Mat, mat);
  412. }else{
  413. if(!hasl) { memcpy(n->Mat,n->InR->Source->Data,sizeof(tnsMatrix44d)); }
  414. elif(!hasr) { memcpy(n->Mat,n->InL->Source->Data,sizeof(tnsMatrix44d)); }
  415. else{
  416. tnsMultiply44d(n->Mat,n->InL->Source->Data,n->InR->Source->Data);
  417. }
  418. }
  419. return 1;
  420. }
  421. void laui_MatrixNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){
  422. laColumn* c=laFirstColumn(uil); laMatrixNode*n=This->EndInstance;
  423. laColumn* cl,*cr; laSplitColumn(uil,c,0.4); cl=laLeftColumn(c,3); cr=laRightColumn(c,0);
  424. laUiItem*b,*b2;
  425. LA_BASE_NODE_HEADER(uil,c,This);
  426. b=laBeginRow(uil,c,0,0);
  427. laShowNodeSocket(uil,c,This,"in_l",0); laShowNodeSocket(uil,c,This,"in_r",0); laShowItem(uil,c,This,"operation");
  428. laShowSeparator(uil,c)->Expand=1; laShowNodeSocket(uil,c,This,"out",0)->Flags|=LA_UI_SOCKET_LABEL_W;
  429. laEndRow(uil,b);
  430. }
  431. void IDN_MathInit(laMathNode* n, int NoCreate){
  432. if(!NoCreate){
  433. strSafeSet(&n->Base.Name,"Math");
  434. n->InL=laCreateInSocket("l",0); n->InR=laCreateInSocket("r",0);
  435. n->Out=laCreateOutSocket(n,"F",LA_PROP_FLOAT); n->OutInt=laCreateOutSocket(n,"I",LA_PROP_INT);
  436. }
  437. n->Out->Data=&n->Value; n->OutInt->Data=&n->ValueI;
  438. }
  439. void IDN_MathDestroy(laMathNode* n){
  440. strSafeDestroy(&n->Base.Name); laDestroyInSocket(n->InL); laDestroyInSocket(n->InR); laDestroyOutSocket(n->Out); laDestroyOutSocket(n->OutInt);
  441. }
  442. int IDN_MathVisit(laMathNode* n, laNodeVisitInfo* vi){
  443. LA_GUARD_THIS_NODE(n,vi);
  444. if(LA_SRC_AND_PARENT(n->InL)){ laBaseNode* bn=n->InL->Source->Parent; LA_VISIT_NODE(bn,vi); }
  445. if(LA_SRC_AND_PARENT(n->InR)){ laBaseNode* bn=n->InR->Source->Parent; LA_VISIT_NODE(bn,vi); }
  446. LA_ADD_THIS_NODE(n,vi);
  447. return LA_DAG_FLAG_PERM;
  448. }
  449. #define LA_GET_SRC_AS_FLOAT(var, socket) \
  450. {if(socket->Source->DataType&LA_PROP_FLOAT) var=*((real*)socket->Source->Data);\
  451. if(socket->Source->DataType&(LA_PROP_INT|LA_PROP_ENUM)) var=*((int*)socket->Source->Data);}
  452. int IDN_MathEval(laMathNode* n){
  453. real vl=n->ValueL;real vr=n->ValueR;
  454. int hasl=LA_SRC_AND_PARENT(n->InL),hasr=LA_SRC_AND_PARENT(n->InR);
  455. if(hasl){ LA_GET_SRC_AS_FLOAT(vl,n->InL) } if(hasr){ LA_GET_SRC_AS_FLOAT(vr,n->InR) }
  456. switch(n->Operation){
  457. case LA_MATH_NODE_OP_ADD: default: n->Value=vl+vr; break;
  458. case LA_MATH_NODE_OP_SUB: n->Value=vl-vr; break;
  459. case LA_MATH_NODE_OP_MUL: n->Value=vl*vr; break;
  460. case LA_MATH_NODE_OP_DIV: if(vr)n->Value=vl/vr;else n->Value=0; break;
  461. case LA_MATH_NODE_OP_POW: n->Value=pow(vl,vr); break;
  462. case LA_MATH_NODE_OP_LOG: n->Value=log2(vl)/log2(vr); break;
  463. case LA_MATH_NODE_OP_SIN: n->Value=sin(vl); break;
  464. case LA_MATH_NODE_OP_COS: n->Value=cos(vl); break;
  465. case LA_MATH_NODE_OP_TAN: n->Value=tan(vl); break;
  466. case LA_MATH_NODE_OP_ASIN: n->Value=asin(vl); break;
  467. case LA_MATH_NODE_OP_ACOS: n->Value=acos(vl); break;
  468. case LA_MATH_NODE_OP_ATAN: n->Value=atan(vl); break;
  469. case LA_MATH_NODE_OP_ATAN2: n->Value=atan2(vl,vr); break;
  470. case LA_MATH_NODE_OP_MOD: n->Value=fmod(vl,vr); break;
  471. }
  472. n->ValueI=(int)n->Value;
  473. return 1;
  474. }
  475. void laui_MathNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){
  476. laColumn* c=laFirstColumn(uil); laMathNode*n=This->EndInstance;
  477. laColumn* cl,*cr; laSplitColumn(uil,c,0.4); cl=laLeftColumn(c,3); cr=laRightColumn(c,0);
  478. laUiItem*b,*b2;
  479. LA_BASE_NODE_HEADER(uil,c,This);
  480. b=laBeginRow(uil,c,0,0);
  481. laShowNodeSocket(uil,c,This,"in_l",0); b=laOnConditionThat(uil,c,laNot(laPropExpression(This,"in_l.source")));{ laShowItem(uil,c,This,"vl"); }laEndCondition(uil,b);
  482. laShowSeparator(uil,c)->Expand=1; laShowItem(uil,c,This,"operation");
  483. laEndRow(uil,b);
  484. b=laBeginRow(uil,c,0,0);
  485. laShowNodeSocket(uil,c,This,"in_r",0); b=laOnConditionThat(uil,c,laNot(laPropExpression(This,"in_r.source")));{ laShowItem(uil,c,This,"vr");}laEndCondition(uil,b);
  486. laShowSeparator(uil,c)->Expand=1;
  487. laShowNodeSocket(uil,c,This,"out_int",0)->Flags|=LA_UI_SOCKET_LABEL_W;
  488. laShowNodeSocket(uil,c,This,"out",0)->Flags|=LA_UI_SOCKET_LABEL_W;
  489. laEndRow(uil,b);
  490. }
  491. void laui_SmallMathNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){
  492. laColumn* c=laFirstColumn(uil); laMathNode*n=This->EndInstance;
  493. laColumn* cl,*cr; laSplitColumn(uil,c,0.4); cl=laLeftColumn(c,3); cr=laRightColumn(c,0);
  494. laUiItem*b,*b2;
  495. LA_BASE_NODE_HEADER(uil,c,This);
  496. b=laBeginRow(uil,c,0,0);
  497. laShowNodeSocket(uil,c,This,"in_l",0);laShowNodeSocket(uil,c,This,"in_r",0);
  498. laShowSeparator(uil,c)->Expand=1;laShowItem(uil,c,This,"operation");
  499. laShowNodeSocket(uil,c,This,"out",0)->Flags|=LA_UI_SOCKET_LABEL_W;
  500. laEndRow(uil,b);
  501. }
  502. void IDN_MapperInit(laMapperNode* n, int NoCreate){
  503. if(!NoCreate){
  504. strSafeSet(&n->Base.Name,"Mapper");
  505. n->Mapper=laValueMapperInit();
  506. }
  507. if(!n->In) n->In=laCreateInSocket("IN",LA_PROP_FLOAT); if(!n->Out) n->Out=laCreateOutSocket(n,"OUT",LA_PROP_FLOAT);
  508. if(!n->InMin) n->InMin=laCreateInSocket("[IN",LA_PROP_FLOAT); if(!n->InMax) n->InMax=laCreateInSocket("IN]",LA_PROP_FLOAT);
  509. if(!n->OutMin) n->OutMin=laCreateInSocket("[OUT",LA_PROP_FLOAT); if(!n->OutMax) n->OutMax=laCreateInSocket("OUT]",LA_PROP_FLOAT);
  510. n->Out->Data=&n->rOut;
  511. }
  512. void IDN_MapperDestroy(laMapperNode* n){
  513. strSafeDestroy(&n->Base.Name);
  514. laDestroyInSocket(n->In); laDestroyOutSocket(n->Out);
  515. laDestroyInSocket(n->InMin); laDestroyInSocket(n->InMax); laDestroyInSocket(n->OutMin); laDestroyInSocket(n->OutMax);
  516. laValueMapperDestroy(n->Mapper);
  517. }
  518. int IDN_MapperVisit(laMapperNode* n, laNodeVisitInfo* vi){
  519. LA_GUARD_THIS_NODE(n,vi);
  520. if(LA_SRC_AND_PARENT(n->In)){ laBaseNode* bn=n->In->Source->Parent; LA_VISIT_NODE(bn,vi); }
  521. if(LA_SRC_AND_PARENT(n->InMin)){ laBaseNode* bn=n->InMin->Source->Parent; LA_VISIT_NODE(bn,vi); }
  522. if(LA_SRC_AND_PARENT(n->InMax)){ laBaseNode* bn=n->InMax->Source->Parent; LA_VISIT_NODE(bn,vi); }
  523. if(LA_SRC_AND_PARENT(n->OutMin)){ laBaseNode* bn=n->OutMin->Source->Parent; LA_VISIT_NODE(bn,vi); }
  524. if(LA_SRC_AND_PARENT(n->OutMax)){ laBaseNode* bn=n->OutMax->Source->Parent; LA_VISIT_NODE(bn,vi); }
  525. LA_ADD_THIS_NODE(n,vi);
  526. return LA_DAG_FLAG_PERM;
  527. }
  528. int IDN_MapperEval(laMapperNode* n){
  529. real in=0; real* InMin=0,*InMax=0,*OutMin=0,*OutMax=0;
  530. if(LA_SRC_AND_PARENT(n->In) && (n->In->Source->DataType&LA_PROP_FLOAT)){ in=*((real*)n->In->Source->Data); }
  531. if(LA_SRC_AND_PARENT(n->InMin) && (n->InMin->Source->DataType&LA_PROP_FLOAT)){ InMin=n->InMin->Source->Data; }
  532. if(LA_SRC_AND_PARENT(n->InMax) && (n->InMax->Source->DataType&LA_PROP_FLOAT)){ InMax=n->InMax->Source->Data; }
  533. if(LA_SRC_AND_PARENT(n->OutMin) && (n->OutMin->Source->DataType&LA_PROP_FLOAT)){ OutMin=n->OutMin->Source->Data; }
  534. if(LA_SRC_AND_PARENT(n->OutMax) && (n->OutMax->Source->DataType&LA_PROP_FLOAT)){ OutMax=n->OutMax->Source->Data; }
  535. real result=laValueMapperEvaluate(n->Mapper,in,InMin,InMax,OutMin,OutMax,n->ClampInput,n->ClampOutput);
  536. n->rOut=result;
  537. return 1;
  538. }
  539. void laui_MapperNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){
  540. laColumn* c=laFirstColumn(uil); laMapperNode*n=This->EndInstance;
  541. laColumn* cl,*cr; laSplitColumn(uil,c,0.4); cl=laLeftColumn(c,3); cr=laRightColumn(c,0);
  542. laUiItem*b,*b2;
  543. LA_BASE_NODE_HEADER(uil,c,This);
  544. b=laBeginRow(uil,c,0,0);
  545. laShowNodeSocket(uil,c,This,"in",0)->Flags|=LA_UI_SOCKET_LABEL_E; laShowItemFull(uil,c,This,"clamp_input",0,"text=C",0,0); laShowNodeSocket(uil,c,This,"in_min",0);
  546. laShowItem(uil,c,This,"mapper.in_range")->Expand=1; laShowNodeSocket(uil,c,This,"in_max",0);
  547. laEndRow(uil,b);
  548. laShowItem(uil,c,This,"mapper");
  549. b=laBeginRow(uil,c,0,0);
  550. laShowNodeSocket(uil,c,This,"out_min",0); laShowItem(uil,c,This,"mapper.out_range")->Expand=1;
  551. laShowNodeSocket(uil,c,This,"out_max",0); laShowItemFull(uil,c,This,"clamp_output",0,"text=C",0,0); laShowNodeSocket(uil,c,This,"out",0)->Flags|=LA_UI_SOCKET_LABEL_W;
  552. laEndRow(uil,b);
  553. }
  554. void IDN_RandomInit(laRandomNode* n, int NoCreate){
  555. if(!NoCreate){
  556. strSafeSet(&n->Base.Name,"Random"); n->Out=laCreateOutSocket(n,"RAND",LA_PROP_FLOAT); n->Min=0; n->Max=1;
  557. }
  558. if(!n->InMin) n->InMin=laCreateInSocket("[IN",LA_PROP_FLOAT); if(!n->InMax) n->InMax=laCreateInSocket("IN]",LA_PROP_FLOAT);
  559. n->Out->Data=&n->rOut;
  560. }
  561. void IDN_RandomDestroy(laRandomNode* n){
  562. strSafeDestroy(&n->Base.Name); laDestroyOutSocket(n->Out); laDestroyInSocket(n->InMin); laDestroyInSocket(n->InMax);
  563. }
  564. int IDN_RandomVisit(laRandomNode* n, laNodeVisitInfo* vi){
  565. LA_GUARD_THIS_NODE(n,vi);
  566. if(LA_SRC_AND_PARENT(n->InMin)){ laBaseNode* bn=n->InMin->Source->Parent; LA_VISIT_NODE(bn,vi); }
  567. if(LA_SRC_AND_PARENT(n->InMax)){ laBaseNode* bn=n->InMax->Source->Parent; LA_VISIT_NODE(bn,vi); }
  568. LA_ADD_THIS_NODE(n,vi);
  569. return LA_DAG_FLAG_PERM;
  570. }
  571. int IDN_RandomEval(laRandomNode* n){
  572. real Min=n->Min,Max=n->Max;
  573. if(LA_SRC_AND_PARENT(n->InMin) && (n->InMin->Source->DataType&LA_PROP_FLOAT)){ Min=*((real*)n->InMin->Source->Data); }
  574. if(LA_SRC_AND_PARENT(n->InMax) && (n->InMax->Source->DataType&LA_PROP_FLOAT)){ Max=*((real*)n->InMax->Source->Data); }
  575. n->rOut=Min+(real)rand()/(real)(RAND_MAX/(Max-Min));
  576. return 1;
  577. }
  578. void laui_RandomNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){
  579. laColumn* c=laFirstColumn(uil); laRandomNode*n=This->EndInstance;
  580. laColumn* cl,*cr; laSplitColumn(uil,c,0.4); cl=laLeftColumn(c,3); cr=laRightColumn(c,0);
  581. laUiItem*b,*b2;
  582. LA_BASE_NODE_HEADER(uil,c,This);
  583. b=laBeginRow(uil,c,0,0);
  584. laShowNodeSocket(uil,c,This,"min",0); laShowItem(uil,c,This,"range")->Expand=1; laShowNodeSocket(uil,c,This,"max",0);
  585. laShowNodeSocket(uil,c,This,"out",0)->Flags|=LA_UI_SOCKET_LABEL_W;
  586. laEndRow(uil,b);
  587. }
  588. void IDN_VectorMathInit(laVectorMathNode* n, int NoCreate){
  589. if(!NoCreate){
  590. strSafeSet(&n->Base.Name,"Math");
  591. n->InL=laCreateInSocket("l",0); n->InR=laCreateInSocket("r",0);
  592. n->Out=laCreateOutSocket(n,"OUT",LA_PROP_FLOAT);
  593. }
  594. n->Out->Data=n->rOut;
  595. }
  596. void IDN_VectorMathDestroy(laVectorMathNode* n){
  597. strSafeDestroy(&n->Base.Name); laDestroyInSocket(n->InL); laDestroyInSocket(n->InR); laDestroyOutSocket(n->Out);
  598. }
  599. int IDN_VectorMathVisit(laVectorMathNode* n, laNodeVisitInfo* vi){
  600. LA_GUARD_THIS_NODE(n,vi);
  601. if(LA_SRC_AND_PARENT(n->InL)){ laBaseNode* bn=n->InL->Source->Parent; LA_VISIT_NODE(bn,vi); }
  602. if(LA_SRC_AND_PARENT(n->InR)){ laBaseNode* bn=n->InR->Source->Parent; LA_VISIT_NODE(bn,vi); }
  603. LA_ADD_THIS_NODE(n,vi);
  604. return LA_DAG_FLAG_PERM;
  605. }
  606. #define LA_GET_SRC_AS_FLOAT_THINGS(var, socket, maxlen) \
  607. {if(socket->Source->DataType&LA_PROP_FLOAT){ real*adr=socket->Source->Data; maxlen=TNS_MIN2(TNS_MAX2(1,socket->Source->ArrLen),maxlen); for(int i=0;i<maxlen;i++){ var[i]=adr[i]; } }\
  608. if(socket->Source->DataType&(LA_PROP_INT|LA_PROP_ENUM)){ int*adr=socket->Source->Data; maxlen=TNS_MIN2(TNS_MAX2(1,socket->Source->ArrLen),maxlen); for(int i=0;i<maxlen;i++){ var[i]=adr[i]; } }\
  609. }
  610. int IDN_VectorMathEval(laVectorMathNode* n){
  611. real vl[4]={0,0,0,1};real vr[4]={0,0,0,1}; int maxlen1=4,maxlen2=4,maxlen;
  612. int hasl=LA_SRC_AND_PARENT(n->InL),hasr=LA_SRC_AND_PARENT(n->InR);
  613. if(hasl){ LA_GET_SRC_AS_FLOAT_THINGS(vl,n->InL,maxlen1) } if(hasr){ LA_GET_SRC_AS_FLOAT_THINGS(vr,n->InR,maxlen2) }
  614. if(maxlen1>1 && maxlen2<maxlen1){ for(int i=maxlen2;i<maxlen1;i++){ vr[i]=vr[maxlen2-1]; } maxlen=maxlen1; }
  615. else{ maxlen=TNS_MIN2(maxlen1,maxlen2); }
  616. switch(n->Operation){
  617. case LA_VECTOR_MATH_OP_ADD: default:n->Out->ArrLen=maxlen; for(int i=0;i<maxlen;i++)n->rOut[i]=vl[i]+vr[i]; break;
  618. case LA_VECTOR_MATH_OP_SUB:n->Out->ArrLen=maxlen; for(int i=0;i<maxlen;i++)n->rOut[i]=vl[i]-vr[i]; break;
  619. case LA_VECTOR_MATH_OP_MUL:n->Out->ArrLen=maxlen; for(int i=0;i<maxlen;i++)n->rOut[i]=vl[i]*vr[i]; break;
  620. case LA_VECTOR_MATH_OP_DIV:n->Out->ArrLen=maxlen; for(int i=0;i<maxlen;i++)n->rOut[i]=vl[i]/vr[i]; break;
  621. case LA_VECTOR_MATH_OP_POW:n->Out->ArrLen=maxlen; for(int i=0;i<maxlen;i++)n->rOut[i]=pow(vl[i],vr[i]); break;
  622. case LA_VECTOR_MATH_OP_LOG:n->Out->ArrLen=maxlen; for(int i=0;i<maxlen;i++)n->rOut[i]=log2(vl[i])/log2(vr[i]); break;
  623. case LA_VECTOR_MATH_OP_CROSS: if(maxlen<3) return 0; n->Out->ArrLen=3; tnsVectorCross3d(n->rOut,vl,vr); break;
  624. case LA_VECTOR_MATH_OP_DOT: if(maxlen<2) return 0; n->Out->ArrLen=1; if(maxlen==2) n->rOut[0]=tnsDot2d(vl,vr,0); else n->rOut[0]=tnsDot3d(vl,vr,0); break;
  625. case LA_VECTOR_MATH_OP_LEN: if(maxlen<2) return 0; n->Out->ArrLen=1;
  626. if(maxlen==2){ tnsVector2d d; tnsVectorMinus2d(d,vr,vl); n->rOut[0]=tnsLength2d(d); }
  627. else { tnsVector3d d; tnsVectorMinus2d(d,vr,vl); n->rOut[0]=tnsLength3d(d); } break;
  628. case LA_VECTOR_MATH_OP_NORMALIZE: if(maxlen<2) return 0; n->Out->ArrLen=maxlen; if(maxlen==2) tnsNormalize2d(n->rOut, vl); else tnsNormalize3d(n->rOut, vl); break;
  629. }
  630. return 1;
  631. }
  632. void laui_VectorMathNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){
  633. laColumn* c=laFirstColumn(uil); laVectorMathNode*n=This->EndInstance;
  634. laColumn* cl,*cr; laSplitColumn(uil,c,0.4); cl=laLeftColumn(c,3); cr=laRightColumn(c,0);
  635. laUiItem*b,*b2;
  636. LA_BASE_NODE_HEADER(uil,c,This);
  637. b=laBeginRow(uil,c,0,0);
  638. laShowNodeSocket(uil,c,This,"in_l",0); laShowNodeSocket(uil,c,This,"in_r",0);
  639. laShowSeparator(uil,c)->Expand=1;
  640. laShowItem(uil,c,This,"operation");
  641. laShowNodeSocket(uil,c,This,"out",0)->Flags|=LA_UI_SOCKET_LABEL_W;
  642. laEndRow(uil,b);
  643. }
  644. void IDN_CommentInit(laCommentNode* n, int NoCreate){
  645. if(NoCreate){return;}
  646. strSafeSet(&n->Base.Name,"Math"); strSafeSet(&n->Content,"");
  647. }
  648. void IDN_CommentDestroy(laCommentNode* n){
  649. strSafeDestroy(&n->Base.Name); strSafeDestroy(&n->Content);
  650. }
  651. int IDN_CommentVisit(laCommentNode* n, laNodeVisitInfo* vi){
  652. //LA_GUARD_THIS_NODE(n,vi);
  653. //LA_ADD_THIS_NODE(n,vi);
  654. // No need to evaluate comments I guess?
  655. return LA_DAG_FLAG_PERM;
  656. }
  657. int IDN_CommentEval(laCommentNode* n){ return 1; }
  658. void laui_CommentNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){
  659. laColumn* c=laFirstColumn(uil); laCommentNode*n=This->EndInstance;
  660. LA_BASE_NODE_HEADER(uil,c,This);
  661. laColumn* cl,*cr; laSplitColumn(uil,c,0.7); cl=laLeftColumn(c,0);cr=laRightColumn(c,1);
  662. laUiItem* b=laOnConditionToggle(uil,cr,0,0,0,0,0);{
  663. laShowItemFull(uil,cl,This,"content",LA_WIDGET_STRING_MULTI,0,0,0)->Flags|=LA_UI_FLAGS_NO_SCROLL_INACTIVE;
  664. }laElse(uil,b);{
  665. laShowItemFull(uil,cl,This,"content",LA_WIDGET_STRING_PLAIN,0,0,0)->Flags|=LA_TEXT_LINE_WRAP;
  666. }laEndCondition(uil,b);}
  667. void IDN_RGB2OKHSLInit(laRGB2OKHSLNode* n, int NoCreate){
  668. if(!NoCreate){
  669. strSafeSet(&n->Base.Name,"RGB to OKHL"); n->In=laCreateInSocket("IN",LA_PROP_FLOAT);
  670. n->OutH=laCreateOutSocket(n,"H",LA_PROP_FLOAT);
  671. n->OutS=laCreateOutSocket(n,"S",LA_PROP_FLOAT);
  672. n->OutL=laCreateOutSocket(n,"L",LA_PROP_FLOAT);
  673. tnsVectorSet3(n->RGB,0.2,0.2,0.2);
  674. }
  675. n->OutH->Data=&n->rOut[0]; n->OutS->Data=&n->rOut[1]; n->OutL->Data=&n->rOut[2];
  676. }
  677. void IDN_RGB2OKHSLDestroy(laRGB2OKHSLNode* n){
  678. strSafeDestroy(&n->Base.Name);
  679. laDestroyInSocket(n->In); laDestroyOutSocket(n->OutH); laDestroyOutSocket(n->OutS); laDestroyOutSocket(n->OutL);
  680. }
  681. int IDN_RGB2OKHSLVisit(laRGB2OKHSLNode* n, laNodeVisitInfo* vi){
  682. LA_GUARD_THIS_NODE(n,vi);
  683. if(LA_SRC_AND_PARENT(n->In)){ laBaseNode* bn=n->In->Source->Parent; LA_VISIT_NODE(bn,vi); }
  684. LA_ADD_THIS_NODE(n,vi);
  685. return LA_DAG_FLAG_PERM;
  686. }
  687. int IDN_RGB2OKHSLEval(laRGB2OKHSLNode* n){
  688. real* in=n->RGB;
  689. if(LA_SRC_AND_PARENT(n->In) && (n->In->Source->DataType==(LA_PROP_FLOAT|LA_PROP_ARRAY) && n->In->Source->ArrLen>=3)){ in=n->In->Source->Data; }
  690. tnsRGB2HCYLinear(in, n->rOut);
  691. return 1;
  692. }
  693. void laui_RGB2OKHSLNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){
  694. laColumn* c=laFirstColumn(uil); laRGB2OKHSLNode*n=This->EndInstance;
  695. laUiItem*b,*b2;
  696. LA_BASE_NODE_HEADER(uil,c,This);
  697. b=laBeginRow(uil,c,0,0);
  698. laShowNodeSocket(uil,c,This,"in",0);
  699. b2=laOnConditionThat(uil,c,laNot(laPropExpression(This,"in.source")));{
  700. laShowItem(uil,c,This,"color");
  701. }laEndCondition(uil,b2);
  702. laShowSeparator(uil,c)->Expand=1;
  703. laShowLabel(uil,c,"OKHSL",0,0);
  704. laShowItem(uil,c,This,"out_h");
  705. laShowItem(uil,c,This,"out_s");
  706. laShowItem(uil,c,This,"out_l");
  707. laEndRow(uil,b);
  708. }
  709. void IDN_OKHSL2RGBInit(laOKHSL2RGBNode* n, int NoCreate){
  710. if(!NoCreate){
  711. strSafeSet(&n->Base.Name,"OKHL to RGB"); n->Out=laCreateOutSocket(n,"RGB",LA_PROP_FLOAT|LA_PROP_ARRAY);
  712. n->InH=laCreateInSocket("H",LA_PROP_FLOAT);
  713. n->InS=laCreateInSocket("S",LA_PROP_FLOAT);
  714. n->InL=laCreateInSocket("L",LA_PROP_FLOAT);
  715. }
  716. n->Out->ArrLen=3; n->Out->Data=n->rOut;
  717. }
  718. void IDN_OKHSL2RGBDestroy(laOKHSL2RGBNode* n){
  719. strSafeDestroy(&n->Base.Name);
  720. laDestroyInSocket(n->InH); laDestroyInSocket(n->InS); laDestroyInSocket(n->InL); laDestroyOutSocket(n->Out);
  721. }
  722. int IDN_OKHSL2RGBVisit(laOKHSL2RGBNode* n, laNodeVisitInfo* vi){
  723. LA_GUARD_THIS_NODE(n,vi);
  724. if(LA_SRC_AND_PARENT(n->InH)){ laBaseNode* bn=n->InH->Source->Parent; LA_VISIT_NODE(bn,vi); }
  725. if(LA_SRC_AND_PARENT(n->InS)){ laBaseNode* bn=n->InS->Source->Parent; LA_VISIT_NODE(bn,vi); }
  726. if(LA_SRC_AND_PARENT(n->InL)){ laBaseNode* bn=n->InL->Source->Parent; LA_VISIT_NODE(bn,vi); }
  727. LA_ADD_THIS_NODE(n,vi);
  728. return LA_DAG_FLAG_PERM;
  729. }
  730. int IDN_OKHSL2RGBEval(laOKHSL2RGBNode* n){
  731. real in[3]={0,0,0};
  732. if(LA_SRC_AND_PARENT(n->InH) && (n->InH->Source->DataType&LA_PROP_FLOAT)){ in[0]=*((real*)n->InH->Source->Data); }
  733. if(LA_SRC_AND_PARENT(n->InS) && (n->InS->Source->DataType&LA_PROP_FLOAT)){ in[1]=*((real*)n->InS->Source->Data); }
  734. if(LA_SRC_AND_PARENT(n->InL) && (n->InL->Source->DataType&LA_PROP_FLOAT)){ in[2]=*((real*)n->InL->Source->Data); }
  735. tnsHCY2RGBLinear(in, n->rOut);
  736. return 1;
  737. }
  738. void laui_OKHSL2RGBNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){
  739. laColumn* c=laFirstColumn(uil); laOKHSL2RGBNode*n=This->EndInstance;
  740. laUiItem*b,*b2;
  741. LA_BASE_NODE_HEADER(uil,c,This);
  742. b=laBeginRow(uil,c,0,0);
  743. laShowItem(uil,c,This,"in_h");
  744. laShowItem(uil,c,This,"in_s");
  745. laShowItem(uil,c,This,"in_l");
  746. laShowLabel(uil,c,"OKHSL",0,0);
  747. laShowSeparator(uil,c)->Expand=1; laShowNodeSocket(uil,c,This,"out",0)->Flags|=LA_UI_SOCKET_LABEL_W;
  748. laEndRow(uil,b);
  749. }
  750. int OPINV_AddInputMapperPage(laOperator* a, laEvent *e){
  751. laRackPage* dp=memAcquireHyper(sizeof(laRackPage));
  752. strSafeSet(&dp->Name,"New Page");
  753. lstAppendItem(&MAIN.InputMapping->Pages, dp); MAIN.InputMapping->CurrentPage=dp; dp->RackType=LA_RACK_TYPE_INPUT;
  754. laNotifyUsers("la.input_mapping"); laRecordAndPush(0,"la.input_mapping","Add Page", 0);
  755. return LA_FINISHED;
  756. }
  757. int OPINV_AddNodesRack(laOperator* a, laEvent *e){
  758. laRackPage* dp=a->This?a->This->EndInstance:0; if(!dp) return LA_FINISHED;
  759. laNodeRack* ir=memAcquire(sizeof(laNodeRack));
  760. strSafeSet(&ir->Name,"New Rack");
  761. lstAppendItem(&dp->Racks, ir); ir->ParentPage=dp;
  762. ir->RackType=dp->RackType;
  763. laNotifyInstanceUsers(dp); laRecordInstanceDifferences(dp,"la_node_rack"); laPushDifferences("Add Rack", 0);
  764. return LA_FINISHED;
  765. }
  766. int OPINV_RebuildInputMapping(laOperator* a, laEvent *e){
  767. laMappingRequestRebuild();
  768. return LA_FINISHED;
  769. }
  770. laBaseNode* la_CreateNode(laNodeRack* ir, laBaseNodeType* NodeType){
  771. laBaseNode* bn=memAcquire(NodeType->NodeSize);
  772. bn->Type=NodeType; NodeType->Init(bn, 0); bn->InitDone=1; lstAppendItem(&ir->Nodes, bn); bn->InRack=ir;
  773. laNotifyInstanceUsers(ir); laRecordInstanceDifferences(ir,"la_node_rack"); laPushDifferences("Add Node", 0);
  774. return bn;
  775. }
  776. void la_DestroyInputMapperNode(laBaseNode* bn){
  777. lstRemoveItem(bn->InRack, bn); bn->Type->Destroy(bn);
  778. laNotifyUsers("la.input_racks"); laRecordAndPush(0,"la.input_mapping","Delete node", 0);
  779. memLeave(bn);
  780. }
  781. int OPINV_AddNode(laOperator* a, laEvent *e){
  782. laNodeRack* ir=a->This?a->This->EndInstance:0; if(!ir) return LA_CANCELED;
  783. laBaseNodeType* bnt=0;
  784. if(!MAIN.CurrentNodeCategory) MAIN.CurrentNodeCategory=MAIN.NodeCategories.pFirst;
  785. char* target=strGetArgumentString(a->ExtraInstructionsP,"target");
  786. if(!target || strSame(target,"INPUT")){ MAIN.FilterNodeCategory=LA_RACK_TYPE_INPUT;
  787. if(!(MAIN.CurrentNodeCategory->For&LA_RACK_TYPE_INPUT)) MAIN.CurrentNodeCategory=LA_NODE_CATEGORY_INPUT; }
  788. else{ MAIN.FilterNodeCategory=LA_RACK_TYPE_DRIVER;
  789. if(!(MAIN.CurrentNodeCategory->For&LA_RACK_TYPE_DRIVER)) MAIN.CurrentNodeCategory=LA_NODE_CATEGORY_DRIVER; }
  790. char* type=strGetArgumentString(a->ExtraInstructionsP,"type");
  791. if(!type){ laEnableOperatorPanel(a,a->This,e->x-LA_RH*4,e->y-LA_RH,200,200,0,0,LA_RH*15,0,0,0,0,0,e); return LA_RUNNING; }
  792. else{
  793. for(int i=0;i<MAIN.NodeTypeNext;i++){
  794. if(strSame(MAIN.NodeTypes[i]->TypeName,type)){ la_CreateNode(ir, MAIN.NodeTypes[i]); }
  795. }
  796. }
  797. return LA_FINISHED;
  798. }
  799. int OPMOD_AddNode(laOperator* a, laEvent *e){
  800. laNodeRack* r=a->This->EndInstance;
  801. if(a->ConfirmData){
  802. if(a->ConfirmData->StrData){
  803. for(int i=0;i<MAIN.NodeTypeNext;i++){
  804. if(strSame(MAIN.NodeTypes[i]->TypeName,a->ConfirmData->StrData)){ la_CreateNode(r, MAIN.NodeTypes[i]); break; }
  805. }
  806. }
  807. return LA_FINISHED;
  808. }
  809. return LA_RUNNING;
  810. }
  811. void laui_AddNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){
  812. laColumn* c=laFirstColumn(uil),*cl,*cr; laSplitColumn(uil,c,0.4); cl=laLeftColumn(c,4); cr=laRightColumn(c,0);
  813. laShowItemFull(uil,cl,0,"la.node_categories",LA_WIDGET_COLLECTION,"feedback=NONE;",0,0);
  814. laUiItem* g=laMakeEmptyGroup(uil,cr,"Nodes",0); laUiList* gu=g->Page; laColumn* gc=laFirstColumn(gu); g->Flags|=LA_UI_FLAGS_NO_DECAL|LA_UI_FLAGS_NO_GAP;
  815. laShowItemFull(gu,gc,0,"la.node_categories",LA_WIDGET_COLLECTION_SINGLE,0,laui_NodeCategory,0)->Flags|=LA_UI_FLAGS_NO_DECAL;
  816. }
  817. int OPINV_MoveNodeToRack(laOperator* a, laEvent *e){
  818. laBaseNode* n=a->This?a->This->EndInstance:0; if(!n||!n->InRack) return LA_CANCELED;
  819. laBaseNodeType* bnt=0; laNodeRack* target;
  820. char* direction=strGetArgumentString(a->ExtraInstructionsP,"direction");
  821. if(strSame(direction,"left")) target=n->InRack->Item.pPrev; else target=n->InRack->Item.pNext;
  822. if(!target) return LA_CANCELED;
  823. lstRemoveItem(&n->InRack->Nodes, n); lstAppendItem(&target->Nodes,n); n->InRack=target;
  824. laNotifyInstanceUsers(n->InRack->ParentPage); laRecordInstanceDifferences(n->InRack->ParentPage,"la_node_page"); laPushDifferences("Move Node", 0);
  825. return LA_FINISHED;
  826. }
  827. int OPINV_DeleteNode(laOperator* a, laEvent *e){
  828. laBaseNode* n=a->This?a->This->EndInstance:0; if(!n||!n->InRack) return LA_CANCELED;
  829. laBaseNodeType* bnt=0; laNodeRack* target;
  830. laNodeRack* parent=n->InRack;
  831. lstRemoveItem(&n->InRack->Nodes, n); n->Type->Destroy(n); memLeave(n);
  832. laMappingRequestRebuild(); laDriverRequestRebuild();
  833. laNotifyInstanceUsers(parent); laRecordInstanceDifferences(parent,"la_node_rack"); laPushDifferences("Delete Node", 0);
  834. return LA_FINISHED;
  835. }
  836. int OPINV_MoveRack(laOperator* a, laEvent *e){
  837. laNodeRack* r=a->This?a->This->EndInstance:0; if(!r) return LA_CANCELED;
  838. char* direction=strGetArgumentString(a->ExtraInstructionsP,"direction");
  839. if(strSame(direction,"left")) lstMoveUp(&r->ParentPage->Racks,r); else lstMoveDown(&r->ParentPage->Racks,r);
  840. laNotifyInstanceUsers(r->ParentPage); laRecordInstanceDifferences(r->ParentPage,"la_rack_page"); laPushDifferences("Move Rack", 0);
  841. return LA_FINISHED;
  842. }
  843. int OPINV_InsertRack(laOperator* a, laEvent *e){
  844. laNodeRack* rr=a->This?a->This->EndInstance:0; if(!rr) return LA_CANCELED;
  845. laNodeRack* r=memAcquire(sizeof(laNodeRack));
  846. strSafeSet(&r->Name,"New Rack");
  847. lstInsertItemAfter(&rr->ParentPage->Racks,r,rr); r->ParentPage=rr->ParentPage; r->RackType=rr->RackType;
  848. laNotifyInstanceUsers(r->ParentPage); laRecordInstanceDifferences(r->ParentPage,"la_rack_page"); laPushDifferences("Insert Rack", 0);
  849. return LA_FINISHED;
  850. }
  851. int OPINV_DeleteRack(laOperator* a, laEvent *e){
  852. laNodeRack* rr=a->This?a->This->EndInstance:0; if(!rr) return LA_CANCELED;
  853. if(strSame(strGetArgumentString(a->ExtraInstructionsP,"confirm"),"true")){
  854. laBaseNode* n; while(n=lstPopItem(&rr->Nodes)){ n->Type->Destroy(n); memLeave(n); }
  855. laRackPage* page=rr->ParentPage;
  856. strSafeDestroy(&rr->Name); lstRemoveItem(&rr->ParentPage->Racks, rr); memLeave(rr);
  857. laNotifyInstanceUsers(page); laRecordInstanceDifferences(page,"la_rack_page"); laPushDifferences("Delete Rack", 0);
  858. return LA_FINISHED;
  859. }
  860. laEnableOperatorPanel(a,a->This,e->x,e->y,200,200,0,0,0,0,0,0,0,0,e);
  861. return LA_RUNNING;
  862. }
  863. void laui_DeleteRack(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){
  864. laColumn* c=laFirstColumn(uil);
  865. laShowItemFull(uil,c,This,"delete",0,"confirm=true;",0,0);
  866. }
  867. laPropContainer* laget_BaseNodeType(laBaseNode* bn){
  868. for(int i=0;i<MAIN.NodeTypeNext;i++){ if(bn->Type==MAIN.NodeTypes[i]) return MAIN.NodeTypes[i]->pc; }
  869. return LA_PC_IDN_GENERIC;
  870. }
  871. int laget_BaseNodeGap(laNodeRack* rack_unused, laBaseNode* n){
  872. return n->Gap;
  873. }
  874. void laread_BaseNodeGap(laBaseNode* n, int gap){
  875. n->Gap=gap;
  876. }
  877. void laset_BaseNodeGap(laBaseNode* n, int gap){
  878. laBaseNode* nn;
  879. if(gap==-1){
  880. int done=0; nn=n; while(nn){ if(nn->Gap>0){ nn->Gap--; done=1; break; } nn=nn->Item.pPrev; }
  881. if(done){ nn=n->Item.pNext; while(nn){ if(nn->Gap>0){ nn->Gap++; break; } nn=nn->Item.pNext; } }
  882. }elif(gap==1){
  883. n->Gap+=gap; nn=n->Item.pNext; while(nn){ if(nn->Gap>0){ nn->Gap--; break; } nn=nn->Item.pNext; }
  884. }elif(gap==-2){
  885. if(n->Gap){ n->Gap--; if(nn=n->Item.pNext){ nn->Gap++; } }
  886. elif(nn=n->Item.pPrev){ n->Gap=nn->Gap; nn->Gap=0; lstRemoveItem(&n->InRack->Nodes,n); lstInsertItemBefore(&n->InRack->Nodes,n,nn); }
  887. }elif(gap==2){
  888. if(nn=n->Item.pNext){ if(!nn->Gap){ nn->Gap=n->Gap; n->Gap=0; lstRemoveItem(&n->InRack->Nodes,n); lstInsertItemAfter(&n->InRack->Nodes,n,nn); }else{ nn->Gap--; n->Gap++; } }
  889. else n->Gap++;
  890. }
  891. }
  892. void laset_InputNodeUserID(laInputControllerNode* n, int i){
  893. laNotifyUsers("la.input_racks");
  894. }
  895. void laset_InputControllerNodeSocketWhich(laInputControllerNodeSocket* s, char* str){
  896. strSafeSet(&s->Which, str);
  897. laNotifyUsers("la.input_racks"); laMappingRequestRebuild();
  898. }
  899. int laget_SocketEnumArrayLength(laInputControllerNodeSocket* s){
  900. return s->Out->ArrLen?s->Out->ArrLen:1;
  901. }
  902. int laget_VisualizerArrayLength(laInputVisualizerNode* s){
  903. return s->In->ArrLen?s->In->ArrLen:1;
  904. }
  905. laBoxedTheme* laget_NodeGetTheme(laNodeRack* rack_unused, laBaseNode* n){
  906. return 0;
  907. }
  908. void laRegisterNode(laBaseNodeType* type, laPropContainer* pc,
  909. laBaseNodeInitF init, laBaseNodeDestroyF destroy, laBaseNodeVisitF visit, laBaseNodeEvalF eval,
  910. int nodesize, char* udf_string, char* type_string, char* UiText, int icon){
  911. arrEnsureLength(&MAIN.NodeTypes, MAIN.NodeTypeNext, &MAIN.NodeTypeMax, sizeof(laBaseNode*));
  912. type->Init = init; type->Destroy = destroy; type->Visit=visit; type->Eval=eval; type->NodeSize=nodesize; type->pc=pc;
  913. type->TypeName=type_string;type->Name=UiText;type->Icon=icon;
  914. MAIN.NodeTypes[MAIN.NodeTypeNext]=type; MAIN.NodeTypeNext++;
  915. la_UDFAppendSharedTypePointer(udf_string, type);
  916. }
  917. void lapost_Node(laBaseNode *bn){
  918. if(!bn->InitDone){
  919. bn->Type->Init(bn,1);
  920. bn->InitDone=1;
  921. }
  922. }
  923. void la_AddValuesNodeEnum(laProp* p){
  924. laAddEnumItemAs(p,"FLOAT","Float","Float value",LA_VALUES_NODE_FLOAT,0);
  925. laAddEnumItemAs(p,"INT","Int","Int value",LA_VALUES_NODE_INT,0);
  926. laAddEnumItemAs(p,"ENUM","Switch","Swich value",LA_VALUES_NODE_ENUM,0);
  927. }
  928. void la_AddValuesNodeEnumValue(laProp* p){
  929. laAddEnumItemAs(p,"IDLE","Idle","Idle",0,0);
  930. laAddEnumItemAs(p,"ACTIVE","Active","Active",1,0);
  931. }
  932. void la_RegisterInputMapperOperators(){
  933. laPropContainer *pc; laProp *p;
  934. laOperatorType *at;
  935. laEnumProp *ep;
  936. laCreateOperatorType("LA_add_input_mapping_page", "Add Page", "Add a page for inpur mapping", 0,0,0,OPINV_AddInputMapperPage,0,'+',0);
  937. laCreateOperatorType("LA_add_rack", "Add Rack", "Add a rack for nodes", 0,0,0,OPINV_AddNodesRack,0,'+',0);
  938. at=laCreateOperatorType("OPINV_AddNode", "Add Node", "Add a node to the rack",0,0,0,OPINV_AddNode,OPMOD_AddNode,'+',0);
  939. at->UiDefine=laui_AddNode;
  940. laCreateOperatorType("LA_input_mapping_rebuild", "Rebuild Input Mapping", "Rebuild input mapping for evaluation",0,0,0,OPINV_RebuildInputMapping,0,U'⭮',0);
  941. laCreateOperatorType("LA_move_node_to_rack", "Move Node", "Move node to another rack",0,0,0,OPINV_MoveNodeToRack,0,0,0);
  942. laCreateOperatorType("LA_delete_node", "Delete Node", "Delete this node",0,0,0,OPINV_DeleteNode,0,0,0);
  943. laCreateOperatorType("LA_move_rack", "Move Rack", "Move this rack",0,0,0,OPINV_MoveRack,0,0,0);
  944. laCreateOperatorType("LA_insert_rack", "Insert Rack", "Insert a new rack",0,0,0,OPINV_InsertRack,0,0,0);
  945. at=laCreateOperatorType("LA_delete_rack", "Delete Rack", "Delete a rack",0,0,0,OPINV_DeleteRack,OPMOD_FinishOnData,U'❌',0);
  946. at->UiDefine=laui_DeleteRack;
  947. pc=laAddPropertyContainer("la_node_rack", "Input Rack", "Input rack for putting input mapping nodes",0,0,sizeof(laNodeRack),0,0,1);
  948. laAddStringProperty(pc,"name","Name","Name of this rack",0,0,0,0,1,offsetof(laNodeRack,Name),0,0,0,0,LA_AS_IDENTIFIER);
  949. p=laAddSubGroup(pc,"nodes","Nodes","Nodes under this rack","la_base_node",laget_BaseNodeType,0,0,-1,0,0,0,0,0,0,offsetof(laNodeRack,Nodes),0);
  950. laSubGroupExtraFunctions(p,0,laget_NodeGetTheme,laget_BaseNodeGap,0);
  951. laAddSubGroup(pc,"parent_page","Parent Page","Parent page of this rack","la_rack_page",0,0,0,offsetof(laNodeRack,ParentPage),0,0,0,0,0,0,0,LA_UDF_REFER);
  952. laAddIntProperty(pc,"type", "Type", "Type of the rack", 0,0,0,0,0,0,0,0,offsetof(laNodeRack,RackType),0,0,0,0,0,0,0,0,0,0,LA_READ_ONLY);
  953. laAddOperatorProperty(pc,"add_node","Add Node","Add a node into this rack","OPINV_AddNode",'+',0);
  954. laAddOperatorProperty(pc,"insert_rack","Insert Rack","Insert a rack","LA_insert_rack",'+',0);
  955. laAddOperatorProperty(pc,"move","Move Rack","Move this rack","LA_move_rack",0,0);
  956. laAddOperatorProperty(pc,"delete","Delete Rack","Delete this rack","LA_delete_rack",0,0);
  957. pc=laAddPropertyContainer("la_base_node", "Input Node", "Input logic node",0,0,sizeof(laBaseNode),0,0,1);
  958. LA_PC_IDN_GENERIC=pc;
  959. laAddStringProperty(pc,"name","Name","Name of this input node",0,0,0,0,1,offsetof(laBaseNode,Name),0,0,0,0,LA_AS_IDENTIFIER);
  960. laAddIntProperty(pc,"__gap", "Gap", "Gap of the node", 0,0,0,0,0,0,0,0,offsetof(laBaseNode,Gap),0,laset_BaseNodeGap,0,0,0,0,0,0,laread_BaseNodeGap,0,0);
  961. laAddSubGroup(pc,"internal_type","Internal Type","Internal node type","any_pointer",0,0,0,offsetof(laBaseNode,Type),0,0,0,0,0,0,0,LA_READ_ONLY|LA_UDF_REFER);
  962. laAddOperatorProperty(pc,"move","Move","Move node across racks","LA_move_node_to_rack",0,0);
  963. laAddOperatorProperty(pc,"delete","Delete","Delete node","LA_delete_node",0,0);
  964. laAddSubGroup(pc,"in_rack","In Rack","The rack this node is in","la_node_rack",0,0,0,offsetof(laBaseNode,InRack),0,0,0,0,0,0,0,LA_UDF_REFER);
  965. pc=laAddPropertyContainer("la_input_controller_node", "Controller output", "Output controller values",0,laui_ControllerNode,sizeof(laInputControllerNode),lapost_Node,0,1);
  966. LA_PC_IDN_CONTROLLER=pc; laPropContainerExtraFunctions(pc,0,0,0,0,laui_DefaultNodeOperationsPropUiDefine);
  967. laAddSubGroup(pc,"base","Base","Base node","la_base_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
  968. laAddIntProperty(pc,"user_id", "User ID", "Which controller should the data come from", 0,0,0,0,0,0,0,0,offsetof(laInputControllerNode,UserID),0,0,0,0,0,0,0,0,0,0,0);
  969. laAddSubGroup(pc,"out0","Out 0","Output 0","la_input_controller_node_socket",0,0,0,offsetof(laInputControllerNode, Sockets[0]),0,0,0,0,0,0,0,LA_UDF_LOCAL);
  970. laAddSubGroup(pc,"out1","Out 1","Output 1","la_input_controller_node_socket",0,0,0,offsetof(laInputControllerNode, Sockets[1]),0,0,0,0,0,0,0,LA_UDF_LOCAL);
  971. laAddSubGroup(pc,"out2","Out 2","Output 2","la_input_controller_node_socket",0,0,0,offsetof(laInputControllerNode, Sockets[2]),0,0,0,0,0,0,0,LA_UDF_LOCAL);
  972. laAddSubGroup(pc,"out3","Out 3","Output 3","la_input_controller_node_socket",0,0,0,offsetof(laInputControllerNode, Sockets[3]),0,0,0,0,0,0,0,LA_UDF_LOCAL);
  973. laAddSubGroup(pc,"out4","Out 4","Output 4","la_input_controller_node_socket",0,0,0,offsetof(laInputControllerNode, Sockets[4]),0,0,0,0,0,0,0,LA_UDF_LOCAL);
  974. laAddSubGroup(pc,"out5","Out 5","Output 5","la_input_controller_node_socket",0,0,0,offsetof(laInputControllerNode, Sockets[5]),0,0,0,0,0,0,0,LA_UDF_LOCAL);
  975. laAddSubGroup(pc,"out6","Out 6","Output 6","la_input_controller_node_socket",0,0,0,offsetof(laInputControllerNode, Sockets[6]),0,0,0,0,0,0,0,LA_UDF_LOCAL);
  976. laAddSubGroup(pc,"out7","Out 7","Output 7","la_input_controller_node_socket",0,0,0,offsetof(laInputControllerNode, Sockets[7]),0,0,0,0,0,0,0,LA_UDF_LOCAL);
  977. pc=laAddPropertyContainer("la_input_controller_node_socket", "Controller Socket", "One value from a controller output",0,0,sizeof(laInputControllerNodeSocket),0,0,1|LA_PROP_OTHER_ALLOC);
  978. laAddStringProperty(pc,"which","Which","Select which output from the controller",0,0,0,0,1,offsetof(laInputControllerNodeSocket,Which),0,0,laset_InputControllerNodeSocketWhich,0,LA_AS_IDENTIFIER);
  979. laAddFloatProperty(pc,"axis", "🡘", "Axis value", LA_WIDGET_VALUE_METER,0,0,1,-1,0,0,0,offsetof(laInputControllerNodeSocket,RealVal),0,0,0,0,0,0,0,0,0,0,LA_READ_ONLY|LA_UDF_IGNORE);
  980. laAddFloatProperty(pc,"axis2d", "2D Axis", "2D Axis value", LA_WIDGET_VALUE_METER,0,0,1,-1,0,0,0,offsetof(laInputControllerNodeSocket,RealVal),0,0,2,0,0,0,0,0,0,0,LA_READ_ONLY|LA_UDF_IGNORE);
  981. p=laAddEnumProperty(pc,"switch", "SW", "Switch value", LA_WIDGET_ENUM_HIGHLIGHT,0,0,0,0,offsetof(laInputControllerNodeSocket,IntVal),0,0,0,laget_SocketEnumArrayLength,0,0,0,0,0,LA_READ_ONLY|LA_UDF_IGNORE);
  982. laAddEnumItemAs(p,"IDLE", "Idle", "Button is not pressed", 0, 0);
  983. laAddEnumItemAs(p,"ACTIVE", "Active", "Button is pressed", 1, 0);
  984. laAddSubGroup(pc, "out", "Out","Output value","la_out_socket",0,0,0,offsetof(laInputControllerNodeSocket,Out),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  985. pc=laAddPropertyContainer("la_input_visualizer_node", "Visualizer", "Visualizer node",0,laui_InputVisualizeNode,sizeof(laInputVisualizerNode),lapost_Node,0,1);
  986. LA_PC_IDN_VISUALIZER=pc; laPropContainerExtraFunctions(pc,0,0,0,0,laui_DefaultNodeOperationsPropUiDefine);
  987. laAddSubGroup(pc,"base","Base","Base node","la_base_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
  988. laAddSubGroup(pc, "in", "In","Input value","la_in_socket",0,0,0,offsetof(laInputVisualizerNode,In),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  989. laAddFloatProperty(pc,"axis", "🡘", "Axis value", LA_WIDGET_VALUE_METER,0,0,1,-1,0,0,0,offsetof(laInputVisualizerNode,RealVal),0,0,0,0,0,0,0,0,0,0,LA_READ_ONLY|LA_UDF_IGNORE);
  990. laAddFloatProperty(pc,"axis2d", "2D Axis", "2D Axis value", LA_WIDGET_VALUE_METER_2D,0,0,1,-1,0,0,0,offsetof(laInputVisualizerNode,RealVal),0,0,2,0,0,0,0,0,0,0,LA_READ_ONLY|LA_UDF_IGNORE);
  991. p=laAddEnumProperty(pc,"switch", "SW", "Switch value", LA_WIDGET_ENUM_HIGHLIGHT,0,0,0,0,offsetof(laInputVisualizerNode,IntVal),0,0,0,laget_VisualizerArrayLength,0,0,0,0,0,LA_READ_ONLY|LA_UDF_IGNORE);
  992. laAddEnumItemAs(p,"IDLE", "Idle", "Button is not pressed", 0, 0);
  993. laAddEnumItemAs(p,"ACTIVE", "Active", "Button is pressed", 1, 0);
  994. pc=laAddPropertyContainer("la_split_node", "Split", "Split node",0,laui_SplitNode,sizeof(laSplitNode),0,0,1);
  995. LA_PC_IDN_SPLIT=pc; laPropContainerExtraFunctions(pc,0,0,0,0,laui_DefaultNodeOperationsPropUiDefine);
  996. laAddSubGroup(pc,"base","Base","Base node","la_base_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
  997. laAddSubGroup(pc,"in", "In","Input value","la_in_socket",0,0,0,offsetof(laSplitNode,In),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  998. laAddSubGroup(pc,"out0","Out 0","Output 0","la_split_node_out_socket",0,0,0,offsetof(laSplitNode, Out[0]),0,0,0,0,0,0,0,LA_UDF_LOCAL);
  999. laAddSubGroup(pc,"out1","Out 1","Output 1","la_split_node_out_socket",0,0,0,offsetof(laSplitNode, Out[1]),0,0,0,0,0,0,0,LA_UDF_LOCAL);
  1000. laAddSubGroup(pc,"out2","Out 2","Output 2","la_split_node_out_socket",0,0,0,offsetof(laSplitNode, Out[2]),0,0,0,0,0,0,0,LA_UDF_LOCAL);
  1001. laAddSubGroup(pc,"out3","Out 3","Output 3","la_split_node_out_socket",0,0,0,offsetof(laSplitNode, Out[3]),0,0,0,0,0,0,0,LA_UDF_LOCAL);
  1002. laAddSubGroup(pc,"out4","Out 4","Output 4","la_split_node_out_socket",0,0,0,offsetof(laSplitNode, Out[4]),0,0,0,0,0,0,0,LA_UDF_LOCAL);
  1003. laAddSubGroup(pc,"out5","Out 5","Output 5","la_split_node_out_socket",0,0,0,offsetof(laSplitNode, Out[5]),0,0,0,0,0,0,0,LA_UDF_LOCAL);
  1004. laAddSubGroup(pc,"out6","Out 6","Output 6","la_split_node_out_socket",0,0,0,offsetof(laSplitNode, Out[6]),0,0,0,0,0,0,0,LA_UDF_LOCAL);
  1005. laAddSubGroup(pc,"out7","Out 7","Output 7","la_split_node_out_socket",0,0,0,offsetof(laSplitNode, Out[7]),0,0,0,0,0,0,0,LA_UDF_LOCAL);
  1006. laAddIntProperty(pc, "array_length", "Array Length", "Array length of data", 0, 0, 0, 0, 0, 0, 0, 0, offsetof(laSplitNode, ArrLen), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,LA_READ_ONLY);
  1007. pc=laAddPropertyContainer("la_split_node_out_socket", "Split Out", "One value from an array input",0,0,sizeof(laSplitNodeOutSocket),0,0,1|LA_PROP_OTHER_ALLOC);
  1008. laAddSubGroup(pc, "out", "Out","Output value","la_out_socket",0,0,0,offsetof(laSplitNodeOutSocket,Out),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  1009. pc=laAddPropertyContainer("la_switch_node", "Switch", "Switch node",0,laui_SwitchNode,sizeof(laSwitchNode),0,0,1);
  1010. LA_PC_IDN_SWITCH=pc; laPropContainerExtraFunctions(pc,0,0,0,0,laui_DefaultNodeOperationsPropUiDefine);
  1011. laAddSubGroup(pc,"base","Base","Base node","la_base_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
  1012. laAddSubGroup(pc,"out", "Out","Output value","la_out_socket",0,0,0,offsetof(laSwitchNode, Out),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  1013. laAddSubGroup(pc,"in0","In 0","Input 0","la_switch_node_in_socket",0,0,0,offsetof(laSwitchNode, In[0]),0,0,0,0,0,0,0,LA_UDF_LOCAL);
  1014. laAddSubGroup(pc,"in1","In 1","Input 1","la_switch_node_in_socket",0,0,0,offsetof(laSwitchNode, In[1]),0,0,0,0,0,0,0,LA_UDF_LOCAL);
  1015. laAddSubGroup(pc,"in2","In 2","Input 2","la_switch_node_in_socket",0,0,0,offsetof(laSwitchNode, In[2]),0,0,0,0,0,0,0,LA_UDF_LOCAL);
  1016. laAddSubGroup(pc,"in3","In 3","Input 3","la_switch_node_in_socket",0,0,0,offsetof(laSwitchNode, In[3]),0,0,0,0,0,0,0,LA_UDF_LOCAL);
  1017. laAddSubGroup(pc,"in4","In 4","Input 4","la_switch_node_in_socket",0,0,0,offsetof(laSwitchNode, In[4]),0,0,0,0,0,0,0,LA_UDF_LOCAL);
  1018. laAddSubGroup(pc,"in5","In 5","Input 5","la_switch_node_in_socket",0,0,0,offsetof(laSwitchNode, In[5]),0,0,0,0,0,0,0,LA_UDF_LOCAL);
  1019. laAddSubGroup(pc,"in6","In 6","Input 6","la_switch_node_in_socket",0,0,0,offsetof(laSwitchNode, In[6]),0,0,0,0,0,0,0,LA_UDF_LOCAL);
  1020. laAddSubGroup(pc,"in7","In 7","Input 7","la_switch_node_in_socket",0,0,0,offsetof(laSwitchNode, In[7]),0,0,0,0,0,0,0,LA_UDF_LOCAL);
  1021. laAddIntProperty(pc, "switch", "Switch", "Switch which input to use", 0, 0, 0, 0, 0, 0, 0, 0, offsetof(laSwitchNode, Switch), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
  1022. laAddSubGroup(pc,"switch_in", "Switch In","Switch control","la_in_socket",0,0,0,offsetof(laSwitchNode,SwitchIn),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  1023. pc=laAddPropertyContainer("la_switch_node_in_socket", "Switch In", "Input of many values",0,0,sizeof(laSwitchNodeInSocket),0,0,1|LA_PROP_OTHER_ALLOC);
  1024. laAddSubGroup(pc, "in", "In","Input value","la_in_socket",0,0,0,offsetof(laSwitchNodeInSocket,In),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  1025. pc=laAddPropertyContainer("la_combine_node", "Combine", "Combine node",0,laui_CombineNode,sizeof(laCombineNode),0,0,1);
  1026. LA_PC_IDN_COMBINE=pc; laPropContainerExtraFunctions(pc,0,0,0,0,laui_DefaultNodeOperationsPropUiDefine);
  1027. laAddSubGroup(pc,"base","Base","Base node","la_base_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
  1028. laAddSubGroup(pc,"out", "Out","Output value","la_out_socket",0,0,0,offsetof(laCombineNode, Out),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  1029. laAddSubGroup(pc,"out_int", "Out Int","Output value in int format","la_out_socket",0,0,0,offsetof(laCombineNode, OutInt),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  1030. laAddSubGroup(pc,"out_enum", "Out Enum","Output value in Enum format","la_out_socket",0,0,0,offsetof(laCombineNode, OutEnum),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  1031. laAddSubGroup(pc,"in0","In 0","Input 0","la_switch_node_in_socket",0,0,0,offsetof(laCombineNode, In[0]),0,0,0,0,0,0,0,LA_UDF_LOCAL);
  1032. laAddSubGroup(pc,"in1","In 1","Input 1","la_switch_node_in_socket",0,0,0,offsetof(laCombineNode, In[1]),0,0,0,0,0,0,0,LA_UDF_LOCAL);
  1033. laAddSubGroup(pc,"in2","In 2","Input 2","la_switch_node_in_socket",0,0,0,offsetof(laCombineNode, In[2]),0,0,0,0,0,0,0,LA_UDF_LOCAL);
  1034. laAddSubGroup(pc,"in3","In 3","Input 3","la_switch_node_in_socket",0,0,0,offsetof(laCombineNode, In[3]),0,0,0,0,0,0,0,LA_UDF_LOCAL);
  1035. laAddSubGroup(pc,"in4","In 4","Input 4","la_switch_node_in_socket",0,0,0,offsetof(laCombineNode, In[4]),0,0,0,0,0,0,0,LA_UDF_LOCAL);
  1036. laAddSubGroup(pc,"in5","In 5","Input 5","la_switch_node_in_socket",0,0,0,offsetof(laCombineNode, In[5]),0,0,0,0,0,0,0,LA_UDF_LOCAL);
  1037. laAddSubGroup(pc,"in6","In 6","Input 6","la_switch_node_in_socket",0,0,0,offsetof(laCombineNode, In[6]),0,0,0,0,0,0,0,LA_UDF_LOCAL);
  1038. laAddSubGroup(pc,"in7","In 7","Input 7","la_switch_node_in_socket",0,0,0,offsetof(laCombineNode, In[7]),0,0,0,0,0,0,0,LA_UDF_LOCAL);
  1039. pc=laAddPropertyContainer("la_values_node", "Values", "Values node",0,laui_ValuesNode,sizeof(laValuesNode),lapost_Node,0,1);
  1040. LA_PC_IDN_VALUES=pc; laPropContainerExtraFunctions(pc,0,0,0,0,laui_DefaultNodeOperationsPropUiDefine);
  1041. laAddSubGroup(pc,"base","Base","Base node","la_base_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
  1042. laAddSubGroup(pc,"out0","Out 0","Output 0","la_split_node_out_socket",0,0,0,offsetof(laValuesNode, Out[0]),0,0,0,0,0,0,0,LA_UDF_LOCAL);
  1043. laAddSubGroup(pc,"out1","Out 1","Output 1","la_split_node_out_socket",0,0,0,offsetof(laValuesNode, Out[1]),0,0,0,0,0,0,0,LA_UDF_LOCAL);
  1044. laAddSubGroup(pc,"out2","Out 2","Output 2","la_split_node_out_socket",0,0,0,offsetof(laValuesNode, Out[2]),0,0,0,0,0,0,0,LA_UDF_LOCAL);
  1045. laAddSubGroup(pc,"out3","Out 3","Output 3","la_split_node_out_socket",0,0,0,offsetof(laValuesNode, Out[3]),0,0,0,0,0,0,0,LA_UDF_LOCAL);
  1046. laAddSubGroup(pc,"out4","Out 4","Output 4","la_split_node_out_socket",0,0,0,offsetof(laValuesNode, Out[4]),0,0,0,0,0,0,0,LA_UDF_LOCAL);
  1047. laAddSubGroup(pc,"out5","Out 5","Output 5","la_split_node_out_socket",0,0,0,offsetof(laValuesNode, Out[5]),0,0,0,0,0,0,0,LA_UDF_LOCAL);
  1048. laAddSubGroup(pc,"out6","Out 6","Output 6","la_split_node_out_socket",0,0,0,offsetof(laValuesNode, Out[6]),0,0,0,0,0,0,0,LA_UDF_LOCAL);
  1049. laAddSubGroup(pc,"out7","Out 7","Output 7","la_split_node_out_socket",0,0,0,offsetof(laValuesNode, Out[7]),0,0,0,0,0,0,0,LA_UDF_LOCAL);
  1050. p=laAddEnumProperty(pc,"mode0","Mode 0","Mode 0",LA_WIDGET_ENUM_CYCLE,0,0,0,0,offsetof(laValuesNode, Modes[0]),0,0,0,0,0,0,0,0,0,0); la_AddValuesNodeEnum(p);
  1051. p=laAddEnumProperty(pc,"mode1","Mode 1","Mode 1",LA_WIDGET_ENUM_CYCLE,0,0,0,0,offsetof(laValuesNode, Modes[1]),0,0,0,0,0,0,0,0,0,0); la_AddValuesNodeEnum(p);
  1052. p=laAddEnumProperty(pc,"mode2","Mode 2","Mode 2",LA_WIDGET_ENUM_CYCLE,0,0,0,0,offsetof(laValuesNode, Modes[2]),0,0,0,0,0,0,0,0,0,0); la_AddValuesNodeEnum(p);
  1053. p=laAddEnumProperty(pc,"mode3","Mode 3","Mode 3",LA_WIDGET_ENUM_CYCLE,0,0,0,0,offsetof(laValuesNode, Modes[3]),0,0,0,0,0,0,0,0,0,0); la_AddValuesNodeEnum(p);
  1054. p=laAddEnumProperty(pc,"mode4","Mode 4","Mode 4",LA_WIDGET_ENUM_CYCLE,0,0,0,0,offsetof(laValuesNode, Modes[4]),0,0,0,0,0,0,0,0,0,0); la_AddValuesNodeEnum(p);
  1055. p=laAddEnumProperty(pc,"mode5","Mode 5","Mode 5",LA_WIDGET_ENUM_CYCLE,0,0,0,0,offsetof(laValuesNode, Modes[5]),0,0,0,0,0,0,0,0,0,0); la_AddValuesNodeEnum(p);
  1056. p=laAddEnumProperty(pc,"mode6","Mode 6","Mode 6",LA_WIDGET_ENUM_CYCLE,0,0,0,0,offsetof(laValuesNode, Modes[6]),0,0,0,0,0,0,0,0,0,0); la_AddValuesNodeEnum(p);
  1057. p=laAddEnumProperty(pc,"mode7","Mode 7","Mode 7",LA_WIDGET_ENUM_CYCLE,0,0,0,0,offsetof(laValuesNode, Modes[7]),0,0,0,0,0,0,0,0,0,0); la_AddValuesNodeEnum(p);
  1058. laAddIntProperty(pc, "valuei0", "Value", "Int value 0", 0,0,0,0,0,0,0,0,offsetof(laValuesNode, ValuesI[0]),0,0,0,0,0,0,0,0,0,0,0);
  1059. laAddIntProperty(pc, "valuei1", "Value", "Int value 1", 0,0,0,0,0,0,0,0,offsetof(laValuesNode, ValuesI[1]),0,0,0,0,0,0,0,0,0,0,0);
  1060. laAddIntProperty(pc, "valuei2", "Value", "Int value 2", 0,0,0,0,0,0,0,0,offsetof(laValuesNode, ValuesI[2]),0,0,0,0,0,0,0,0,0,0,0);
  1061. laAddIntProperty(pc, "valuei3", "Value", "Int value 3", 0,0,0,0,0,0,0,0,offsetof(laValuesNode, ValuesI[3]),0,0,0,0,0,0,0,0,0,0,0);
  1062. laAddIntProperty(pc, "valuei4", "Value", "Int value 4", 0,0,0,0,0,0,0,0,offsetof(laValuesNode, ValuesI[4]),0,0,0,0,0,0,0,0,0,0,0);
  1063. laAddIntProperty(pc, "valuei5", "Value", "Int value 5", 0,0,0,0,0,0,0,0,offsetof(laValuesNode, ValuesI[5]),0,0,0,0,0,0,0,0,0,0,0);
  1064. laAddIntProperty(pc, "valuei6", "Value", "Int value 6", 0,0,0,0,0,0,0,0,offsetof(laValuesNode, ValuesI[6]),0,0,0,0,0,0,0,0,0,0,0);
  1065. laAddIntProperty(pc, "valuei7", "Value", "Int value 7", 0,0,0,0,0,0,0,0,offsetof(laValuesNode, ValuesI[7]),0,0,0,0,0,0,0,0,0,0,0);
  1066. laAddFloatProperty(pc, "value0", "Value", "Float value 0", 0,0,0,0,0,0,0,0,offsetof(laValuesNode, Values[0]),0,0,0,0,0,0,0,0,0,0,0);
  1067. laAddFloatProperty(pc, "value1", "Value", "Float value 1", 0,0,0,0,0,0,0,0,offsetof(laValuesNode, Values[1]),0,0,0,0,0,0,0,0,0,0,0);
  1068. laAddFloatProperty(pc, "value2", "Value", "Float value 2", 0,0,0,0,0,0,0,0,offsetof(laValuesNode, Values[2]),0,0,0,0,0,0,0,0,0,0,0);
  1069. laAddFloatProperty(pc, "value3", "Value", "Float value 3", 0,0,0,0,0,0,0,0,offsetof(laValuesNode, Values[3]),0,0,0,0,0,0,0,0,0,0,0);
  1070. laAddFloatProperty(pc, "value4", "Value", "Float value 4", 0,0,0,0,0,0,0,0,offsetof(laValuesNode, Values[4]),0,0,0,0,0,0,0,0,0,0,0);
  1071. laAddFloatProperty(pc, "value5", "Value", "Float value 5", 0,0,0,0,0,0,0,0,offsetof(laValuesNode, Values[5]),0,0,0,0,0,0,0,0,0,0,0);
  1072. laAddFloatProperty(pc, "value6", "Value", "Float value 6", 0,0,0,0,0,0,0,0,offsetof(laValuesNode, Values[6]),0,0,0,0,0,0,0,0,0,0,0);
  1073. laAddFloatProperty(pc, "value7", "Value", "Float value 7", 0,0,0,0,0,0,0,0,offsetof(laValuesNode, Values[7]),0,0,0,0,0,0,0,0,0,0,0);
  1074. p=laAddEnumProperty(pc,"valuee0","SW","Enum Value 0",LA_WIDGET_ENUM_CYCLE,0,0,0,0,offsetof(laValuesNode, ValuesE[0]),0,0,0,0,0,0,0,0,0,0);la_AddValuesNodeEnumValue(p);
  1075. p=laAddEnumProperty(pc,"valuee1","SW","Enum Value 1",LA_WIDGET_ENUM_CYCLE,0,0,0,0,offsetof(laValuesNode, ValuesE[1]),0,0,0,0,0,0,0,0,0,0);la_AddValuesNodeEnumValue(p);
  1076. p=laAddEnumProperty(pc,"valuee2","SW","Enum Value 2",LA_WIDGET_ENUM_CYCLE,0,0,0,0,offsetof(laValuesNode, ValuesE[2]),0,0,0,0,0,0,0,0,0,0);la_AddValuesNodeEnumValue(p);
  1077. p=laAddEnumProperty(pc,"valuee3","SW","Enum Value 3",LA_WIDGET_ENUM_CYCLE,0,0,0,0,offsetof(laValuesNode, ValuesE[3]),0,0,0,0,0,0,0,0,0,0);la_AddValuesNodeEnumValue(p);
  1078. p=laAddEnumProperty(pc,"valuee4","SW","Enum Value 4",LA_WIDGET_ENUM_CYCLE,0,0,0,0,offsetof(laValuesNode, ValuesE[4]),0,0,0,0,0,0,0,0,0,0);la_AddValuesNodeEnumValue(p);
  1079. p=laAddEnumProperty(pc,"valuee5","SW","Enum Value 5",LA_WIDGET_ENUM_CYCLE,0,0,0,0,offsetof(laValuesNode, ValuesE[5]),0,0,0,0,0,0,0,0,0,0);la_AddValuesNodeEnumValue(p);
  1080. p=laAddEnumProperty(pc,"valuee6","SW","Enum Value 6",LA_WIDGET_ENUM_CYCLE,0,0,0,0,offsetof(laValuesNode, ValuesE[6]),0,0,0,0,0,0,0,0,0,0);la_AddValuesNodeEnumValue(p);
  1081. p=laAddEnumProperty(pc,"valuee7","SW","Enum Value 7",LA_WIDGET_ENUM_CYCLE,0,0,0,0,offsetof(laValuesNode, ValuesE[7]),0,0,0,0,0,0,0,0,0,0);la_AddValuesNodeEnumValue(p);
  1082. pc=laAddPropertyContainer("la_matrix_node", "Matrix", "Matrix node",0,laui_MatrixNode,sizeof(laMatrixNode),lapost_Node,0,1);
  1083. LA_PC_IDN_MATRIX=pc; laPropContainerExtraFunctions(pc,0,0,0,0,laui_DefaultNodeOperationsPropUiDefine);
  1084. laAddSubGroup(pc,"base","Base","Base node","la_base_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
  1085. laAddSubGroup(pc,"in_l", "L","Left input","la_in_socket",0,0,0,offsetof(laMatrixNode, InL),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  1086. laAddSubGroup(pc,"in_r", "R","Right input","la_in_socket",0,0,0,offsetof(laMatrixNode, InR),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  1087. laAddSubGroup(pc,"out", "Out","Output value","la_out_socket",0,0,0,offsetof(laMatrixNode, Out),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  1088. p=laAddEnumProperty(pc,"operation", "Operation", "Operation", 0,0,0,0,0,offsetof(laMatrixNode,Operation),0,0,0,0,0,0,0,0,0,0);
  1089. laAddEnumItemAs(p,"MUL", "Multiply", "L x R", LA_MATRIX_NODE_OP_MUL, 0);
  1090. laAddEnumItemAs(p,"INV", "Invert", "Invert L or R", LA_MATRIX_NODE_OP_INV, 0);
  1091. #define REGISTER_MATH_NODE \
  1092. laPropContainerExtraFunctions(pc,0,0,0,0,laui_DefaultNodeOperationsPropUiDefine); \
  1093. laAddSubGroup(pc,"base","Base","Base node","la_base_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);\
  1094. laAddFloatProperty(pc, "vl", "L", "Left value", 0,0,0,0,0,0,0,0,offsetof(laMathNode, ValueL),0,0,0,0,0,0,0,0,0,0,0);\
  1095. laAddFloatProperty(pc, "vr", "R", "Right value", 0,0,0,0,0,0,0,0,offsetof(laMathNode, ValueR),0,0,0,0,0,0,0,0,0,0,0);\
  1096. laAddSubGroup(pc,"in_l", "L","Left input","la_in_socket",0,0,0,offsetof(laMathNode, InL),0,0,0,0,0,0,0,LA_UDF_SINGLE);\
  1097. laAddSubGroup(pc,"in_r", "R","Right input","la_in_socket",0,0,0,offsetof(laMathNode, InR),0,0,0,0,0,0,0,LA_UDF_SINGLE);\
  1098. laAddSubGroup(pc,"out", "Out","Output value","la_out_socket",0,0,0,offsetof(laMathNode, Out),0,0,0,0,0,0,0,LA_UDF_SINGLE);\
  1099. laAddSubGroup(pc,"out_int", "Out Int","Output value in Integer","la_out_socket",0,0,0,offsetof(laMathNode, OutInt),0,0,0,0,0,0,0,LA_UDF_SINGLE);\
  1100. p=laAddEnumProperty(pc,"operation", "Operation", "Operation", 0,0,0,0,0,offsetof(laMathNode, Operation),0,0,0,0,0,0,0,0,0,0);\
  1101. laAddEnumItemAs(p,"ADD", "Add", "L + R", LA_MATH_NODE_OP_ADD, 0);\
  1102. laAddEnumItemAs(p,"SUB", "Subtract", "L - R", LA_MATH_NODE_OP_SUB, 0);\
  1103. laAddEnumItemAs(p,"MUL", "Multiply", "L x R", LA_MATH_NODE_OP_MUL, 0);\
  1104. laAddEnumItemAs(p,"DIV", "Divide", "L / R", LA_MATH_NODE_OP_DIV, 0);\
  1105. laAddEnumItemAs(p,"POW", "Power", "pow(L,R)", LA_MATH_NODE_OP_POW, 0);\
  1106. laAddEnumItemAs(p,"LOG", "Log", "log(L)base(R)", LA_MATH_NODE_OP_LOG, 0);\
  1107. laAddEnumItemAs(p,"SIN", "Sine", "sin(L)", LA_MATH_NODE_OP_SIN, 0);\
  1108. laAddEnumItemAs(p,"COS", "Cosine", "cos(L)", LA_MATH_NODE_OP_COS, 0);\
  1109. laAddEnumItemAs(p,"TAN", "Tangent", "tan(L)", LA_MATH_NODE_OP_TAN, 0);\
  1110. laAddEnumItemAs(p,"ASIN", "Arcsin", "asin(L)", LA_MATH_NODE_OP_ASIN, 0);\
  1111. laAddEnumItemAs(p,"ACOS", "Arccosine", "acos(L)", LA_MATH_NODE_OP_ACOS, 0);\
  1112. laAddEnumItemAs(p,"ATAN", "Arctangent", "atan(L)", LA_MATH_NODE_OP_ATAN, 0);\
  1113. laAddEnumItemAs(p,"ATAN2", "Atan2", "atan2(L,R) where L or R can be zero", LA_MATH_NODE_OP_ATAN2, 0);\
  1114. laAddEnumItemAs(p,"MOD", "Mod", "L \% R", LA_MATH_NODE_OP_MOD, 0);
  1115. pc=laAddPropertyContainer("la_math_node", "Math", "Math node",0,laui_MathNode,sizeof(laMathNode),lapost_Node,0,1); LA_PC_IDN_MATH=pc; REGISTER_MATH_NODE
  1116. pc=laAddPropertyContainer("la_small_math_node", "Small Math", "Small Math node",0,laui_SmallMathNode,sizeof(laMathNode),lapost_Node,0,1); LA_PC_IDN_SMALL_MATH=pc; REGISTER_MATH_NODE
  1117. pc=laAddPropertyContainer("la_mapper_node", "Mapper", "Mapper node",0,laui_MapperNode,sizeof(laMapperNode),lapost_Node,0,1);
  1118. LA_PC_IDN_MAPPER=pc; laPropContainerExtraFunctions(pc,0,0,0,0,laui_DefaultNodeOperationsPropUiDefine);
  1119. laAddSubGroup(pc,"base","Base","Base node","la_base_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
  1120. laAddSubGroup(pc,"in", "In","Input value","la_in_socket",0,0,0,offsetof(laMapperNode, In),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  1121. laAddSubGroup(pc,"in_min", "In Min","Minimum input value","la_in_socket",0,0,0,offsetof(laMapperNode, InMin),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  1122. laAddSubGroup(pc,"in_max", "In Max","Maximum input value","la_in_socket",0,0,0,offsetof(laMapperNode, InMax),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  1123. laAddSubGroup(pc,"out_min", "Out Min","Minimum output value","la_in_socket",0,0,0,offsetof(laMapperNode, OutMin),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  1124. laAddSubGroup(pc,"out_max", "Out Max","Maximum output value","la_in_socket",0,0,0,offsetof(laMapperNode, OutMax),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  1125. laAddSubGroup(pc,"out", "Out","Output value","la_out_socket",0,0,0,offsetof(laMapperNode, Out),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  1126. laAddSubGroup(pc,"mapper", "Mapper","Value mapper","la_value_mapper",0,LA_WIDGET_MAPPER,0,offsetof(laMapperNode, Mapper),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  1127. p=laAddEnumProperty(pc,"clamp_input", "Clamp Input", "Clamp input", LA_WIDGET_ENUM_HIGHLIGHT,0,0,0,0,offsetof(laMapperNode,ClampInput),0,0,0,0,0,0,0,0,0,0);
  1128. laAddEnumItemAs(p,"NONE", "None", "Don't clamp", 0, 0); laAddEnumItemAs(p,"CLAMP", "Clamp", "Clamp to specified range", 1, 0);
  1129. p=laAddEnumProperty(pc,"clamp_output", "Clamp Output", "Clamp output", LA_WIDGET_ENUM_HIGHLIGHT,0,0,0,0,offsetof(laMapperNode,ClampOutput),0,0,0,0,0,0,0,0,0,0);
  1130. laAddEnumItemAs(p,"NONE", "None", "Don't clamp", 0, 0); laAddEnumItemAs(p,"CLAMP", "Clamp", "Clamp to specified range", 1, 0);
  1131. pc=laAddPropertyContainer("la_random_node", "Random", "Random node",0,laui_RandomNode,sizeof(laRandomNode),lapost_Node,0,1);
  1132. LA_PC_IDN_RANDOM=pc; laPropContainerExtraFunctions(pc,0,0,0,0,laui_DefaultNodeOperationsPropUiDefine);
  1133. laAddSubGroup(pc,"base","Base","Base node","la_base_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
  1134. laAddSubGroup(pc,"out", "Out","Output value","la_out_socket",0,0,0,offsetof(laRandomNode, Out),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  1135. laAddSubGroup(pc,"min", "Min","Minimum output value","la_in_socket",0,0,0,offsetof(laRandomNode, InMin),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  1136. laAddSubGroup(pc,"max", "Max","Maximum output value","la_in_socket",0,0,0,offsetof(laRandomNode, InMax),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  1137. laAddFloatProperty(pc, "range", "Range", "Range of the random values", 0,0,0,0,0,0,0,0,offsetof(laRandomNode, Min),0,0,2,0,0,0,0,0,0,0,0);
  1138. pc=laAddPropertyContainer("la_vector_math_node", "Vector Math", "Math node",0,laui_VectorMathNode,sizeof(laVectorMathNode),lapost_Node,0,1);
  1139. LA_PC_IDN_VECTOR_MATH=pc; laPropContainerExtraFunctions(pc,0,0,0,0,laui_DefaultNodeOperationsPropUiDefine);
  1140. laAddSubGroup(pc,"base","Base","Base node","la_base_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
  1141. laAddSubGroup(pc,"in_l", "L","Left input","la_in_socket",0,0,0,offsetof(laVectorMathNode, InL),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  1142. laAddSubGroup(pc,"in_r", "R","Right input","la_in_socket",0,0,0,offsetof(laVectorMathNode, InR),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  1143. laAddSubGroup(pc,"out", "Out","Output value","la_out_socket",0,0,0,offsetof(laVectorMathNode, Out),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  1144. p=laAddEnumProperty(pc,"operation", "Operation", "Operation", 0,0,0,0,0,offsetof(laVectorMathNode, Operation),0,0,0,0,0,0,0,0,0,0);
  1145. laAddEnumItemAs(p,"ADD", "Add", "L + R", LA_VECTOR_MATH_OP_ADD, 0);
  1146. laAddEnumItemAs(p,"SUB", "Subtract", "L - R", LA_VECTOR_MATH_OP_SUB, 0);
  1147. laAddEnumItemAs(p,"MUL", "Multiply (component)", "L x R (component)", LA_VECTOR_MATH_OP_MUL, 0);
  1148. laAddEnumItemAs(p,"DIV", "Divide (component)", "L / R (component)", LA_VECTOR_MATH_OP_DIV, 0);
  1149. laAddEnumItemAs(p,"CROSS", "Cross", "L x R", LA_VECTOR_MATH_OP_CROSS, 0);
  1150. laAddEnumItemAs(p,"DOT", "Dot", "L . R", LA_VECTOR_MATH_OP_DOT, 0);
  1151. laAddEnumItemAs(p,"POW", "Power", "pow(L,R)", LA_VECTOR_MATH_OP_POW, 0);
  1152. laAddEnumItemAs(p,"LOG", "Log", "log(L)base(R)", LA_VECTOR_MATH_OP_LOG, 0);
  1153. laAddEnumItemAs(p,"LEN", "Length", "Length(L)", LA_VECTOR_MATH_OP_LEN, 0);
  1154. laAddEnumItemAs(p,"NORM", "Normalize", "Normalize(L)", LA_VECTOR_MATH_OP_NORMALIZE, 0);
  1155. pc=laAddPropertyContainer("la_comment_node", "Comment", "Comment",0,laui_CommentNode,sizeof(laCommentNode),lapost_Node,0,1);
  1156. LA_PC_IDN_COMMENT=pc; laPropContainerExtraFunctions(pc,0,0,0,0,laui_DefaultNodeOperationsPropUiDefine);
  1157. laAddSubGroup(pc,"base","Base","Base node","la_base_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
  1158. laAddStringProperty(pc,"content","Content","Content of the comment",LA_WIDGET_STRING_MULTI,0,0,0,1,offsetof(laCommentNode,Content),0,0,0,0,0);
  1159. pc=laAddPropertyContainer("la_rgb_to_okhsl_node", "RGB 2 OKHSL", "RGB color to OKHSL values",0,laui_RGB2OKHSLNode,sizeof(laRGB2OKHSLNode),lapost_Node,0,1);
  1160. LA_PC_IDN_RGB2OKHSL=pc; laPropContainerExtraFunctions(pc,0,0,0,0,laui_DefaultNodeOperationsPropUiDefine);
  1161. laAddSubGroup(pc,"base","Base","Base node","la_base_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
  1162. laAddSubGroup(pc,"in", "In","Input color","la_in_socket",0,0,0,offsetof(laRGB2OKHSLNode, In),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  1163. laAddSubGroup(pc,"out_h", "H","Hue","la_out_socket",0,0,0,offsetof(laRGB2OKHSLNode, OutH),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  1164. laAddSubGroup(pc,"out_s", "S","Chroma","la_out_socket",0,0,0,offsetof(laRGB2OKHSLNode, OutS),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  1165. laAddSubGroup(pc,"out_l", "L","Brightness","la_out_socket",0,0,0,offsetof(laRGB2OKHSLNode, OutL),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  1166. laAddFloatProperty(pc, "color", "Color", "Default color", LA_WIDGET_FLOAT_COLOR,0,0,0,0,0,0,0,offsetof(laRGB2OKHSLNode, RGB),0,0,3,0,0,0,0,0,0,0,0);
  1167. pc=laAddPropertyContainer("la_okhsl_to_rgb_node", "OKHSL 2 RGB", "OKHSL values to RGB color",0,laui_OKHSL2RGBNode,sizeof(laOKHSL2RGBNode),lapost_Node,0,1);
  1168. LA_PC_IDN_OKHSL2RGB=pc; laPropContainerExtraFunctions(pc,0,0,0,0,laui_DefaultNodeOperationsPropUiDefine);
  1169. laAddSubGroup(pc,"base","Base","Base node","la_base_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
  1170. laAddSubGroup(pc,"out", "Out","Output color","la_out_socket",0,0,0,offsetof(laOKHSL2RGBNode, Out),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  1171. laAddSubGroup(pc,"in_h", "H","Hue","la_in_socket",0,0,0,offsetof(laOKHSL2RGBNode, InH),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  1172. laAddSubGroup(pc,"in_s", "S","Chroma","la_in_socket",0,0,0,offsetof(laOKHSL2RGBNode, InS),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  1173. laAddSubGroup(pc,"in_l", "L","Brightness","la_in_socket",0,0,0,offsetof(laOKHSL2RGBNode, InL),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  1174. typedef laMathNode laSmallMathNode;
  1175. LA_IDN_REGISTER("Controller",U'🕹',LA_IDN_CONTROLLER,LA_PC_IDN_CONTROLLER, IDN_ControllerInit, IDN_ControllerDestroy, IDN_ControllerVisit, IDN_ControllerEval, laInputControllerNode);
  1176. LA_IDN_REGISTER("Visualizer",U'🔍',LA_IDN_VISUALIZER,LA_PC_IDN_VISUALIZER, IDN_InputVisualizeInit, IDN_InputVisualizeDestroy, IDN_InputVisualizeVisit, IDN_InputVisualizerEval, laInputVisualizerNode);
  1177. LA_IDN_REGISTER("Split",U'⚟',LA_IDN_SPLIT,LA_PC_IDN_SPLIT, IDN_SplitInit, IDN_SplitDestroy, IDN_SplitVisit, IDN_SplitEval, laSplitNode);
  1178. LA_IDN_REGISTER("Switch",U'🚦',LA_IDN_SWITCH,LA_PC_IDN_SWITCH, IDN_SwitchInit, IDN_SwitchDestroy, IDN_SwitchVisit, IDN_SwitchEval, laSwitchNode);
  1179. LA_IDN_REGISTER("Combine",U'⚞',LA_IDN_COMBINE,LA_PC_IDN_COMBINE, IDN_CombineInit, IDN_CombineDestroy, IDN_CombineVisit, IDN_CombineEval, laCombineNode);
  1180. LA_IDN_REGISTER("Values",0,LA_IDN_VALUES,LA_PC_IDN_VALUES, IDN_ValuesInit, IDN_ValuesDestroy, IDN_ValuesVisit, IDN_ValuesEval, laValuesNode);
  1181. LA_IDN_REGISTER("Matrix",0,LA_IDN_MATRIX,LA_PC_IDN_MATRIX, IDN_MatrixInit, IDN_MatrixDestroy, IDN_MatrixVisit, IDN_MatrixEval, laMatrixNode);
  1182. LA_IDN_REGISTER("Math",0,LA_IDN_MATH,LA_PC_IDN_MATH, IDN_MathInit, IDN_MathDestroy, IDN_MathVisit, IDN_MathEval, laMathNode);
  1183. LA_IDN_REGISTER("Small Math",0,LA_IDN_SMALL_MATH,LA_PC_IDN_SMALL_MATH, IDN_MathInit, IDN_MathDestroy, IDN_MathVisit, IDN_MathEval, laSmallMathNode);
  1184. LA_IDN_REGISTER("Mapper",0,LA_IDN_MAPPER,LA_PC_IDN_MAPPER, IDN_MapperInit, IDN_MapperDestroy, IDN_MapperVisit, IDN_MapperEval, laMapperNode);
  1185. LA_IDN_REGISTER("Random",0,LA_IDN_RANDOM,LA_PC_IDN_RANDOM, IDN_RandomInit, IDN_RandomDestroy, IDN_RandomVisit, IDN_RandomEval, laRandomNode);
  1186. LA_IDN_REGISTER("Vector Math",0,LA_IDN_VECTOR_MATH,LA_PC_IDN_VECTOR_MATH, IDN_VectorMathInit, IDN_VectorMathDestroy, IDN_VectorMathVisit, IDN_VectorMathEval, laVectorMathNode);
  1187. LA_IDN_REGISTER("Comment",0,LA_IDN_COMMENT,LA_PC_IDN_COMMENT, IDN_CommentInit, IDN_CommentDestroy, IDN_CommentVisit, IDN_CommentEval, laCommentNode);
  1188. LA_IDN_REGISTER("RGB to OKHSL",0,LA_IDN_RGB2OKHSL,LA_PC_IDN_RGB2OKHSL, IDN_RGB2OKHSLInit, IDN_RGB2OKHSLDestroy, IDN_RGB2OKHSLVisit, IDN_RGB2OKHSLEval, laRGB2OKHSLNode);
  1189. LA_IDN_REGISTER("OKHSL to RGB",0,LA_IDN_OKHSL2RGB,LA_PC_IDN_OKHSL2RGB, IDN_OKHSL2RGBInit, IDN_OKHSL2RGBDestroy, IDN_OKHSL2RGBVisit, IDN_OKHSL2RGBEval, laOKHSL2RGBNode);
  1190. LA_NODE_CATEGORY_INPUT=laAddNodeCategory("Input",0,LA_RACK_TYPE_INPUT);
  1191. LA_NODE_CATEGORY_MATH=laAddNodeCategory("Math",0,LA_RACK_TYPE_ALL);
  1192. LA_NODE_CATEGORY_COLOR=laAddNodeCategory("Color",0,LA_RACK_TYPE_ALL);
  1193. LA_NODE_CATEGORY_ROUTE=laAddNodeCategory("Route",0,LA_RACK_TYPE_ALL);
  1194. LA_NODE_CATEGORY_AUX=laAddNodeCategory("Auxiliary",0,LA_RACK_TYPE_ALL);
  1195. laNodeCategoryAddNodeTypes(LA_NODE_CATEGORY_INPUT, &LA_IDN_CONTROLLER,0);
  1196. laNodeCategoryAddNodeTypes(LA_NODE_CATEGORY_MATH, &LA_IDN_MATH, &LA_IDN_SMALL_MATH,&LA_IDN_VECTOR_MATH,&LA_IDN_MAPPER,&LA_IDN_RANDOM,&LA_IDN_MATRIX, &LA_IDN_VALUES,0);
  1197. laNodeCategoryAddNodeTypes(LA_NODE_CATEGORY_ROUTE, &LA_IDN_SPLIT, &LA_IDN_SWITCH, &LA_IDN_COMBINE,0);
  1198. laNodeCategoryAddNodeTypes(LA_NODE_CATEGORY_AUX, &LA_IDN_COMMENT, &LA_IDN_VISUALIZER,0);
  1199. laNodeCategoryAddNodeTypes(LA_NODE_CATEGORY_COLOR, &LA_IDN_RGB2OKHSL, &LA_IDN_OKHSL2RGB,0);
  1200. MAIN.tNodeIn=laCreateInSocket("TIN",0);
  1201. MAIN.tNodeOut=laCreateOutSocket(0,"TOUT",0);
  1202. }
  1203. void laMappingRequestRebuild(){ MAIN.InputMapping->NeedRebuild=1; }
  1204. void laMappingRequestEval(){ MAIN.InputMapping->NeedEval=1; }
  1205. int __DEBUG_PAGE_EVAL__=1;
  1206. int laRebuildPageEval(laRackPage* rp){
  1207. if(!rp)return LA_DAG_FLAG_PERM;
  1208. while(lstPopPointer(&rp->Eval)); while(lstPopPointer(&rp->AlwaysBranchers));
  1209. laListHandle pending={0};
  1210. for(laNodeRack* ir=rp->Racks.pFirst;ir;ir=ir->Item.pNext){
  1211. for(laBaseNode*bn=ir->Nodes.pFirst;bn;bn=bn->Item.pNext){ if(!bn->InitDone){ bn->Type->Init(bn,1); bn->InitDone=1; }
  1212. lstAppendPointer(&pending,bn); bn->Branch=0; bn->BranchTemp=0;
  1213. }
  1214. }
  1215. laBaseNode*n; int result=LA_DAG_FLAG_PERM; laListItemPointer*NextLip;
  1216. laNodeVisitInfo vi;
  1217. vi.Branch=1; vi.NextBranch=2; vi.l=&rp->Eval; vi.br=&rp->AlwaysBranchers; vi.Page=rp;
  1218. for(laListItemPointer*lip=pending.pFirst;lip;lip=NextLip){ n=lip->p; NextLip=lip->pNext;
  1219. if(n->Branch & 1) continue;
  1220. result=n->Type->Visit(n,&vi); if(result==LA_DAG_FLAG_ERR){ while(lstPopPointer(&pending)); break; }
  1221. }
  1222. if(result==LA_DAG_FLAG_ERR){ while(lstPopPointer(&rp->Eval)); while(lstPopPointer(&rp->AlwaysBranchers)); return LA_DAG_FLAG_ERR; }
  1223. return LA_DAG_FLAG_PERM;
  1224. }
  1225. int laRunPage(laRackPage* rp, uint64_t mask){
  1226. static uint64_t magic=3;
  1227. if(!rp || (!rp->Eval.pFirst && !rp->AlwaysBranchers.pFirst)) return 0;
  1228. if(__DEBUG_PAGE_EVAL__ && mask==1){ printf("Page eval %s\n",(rp->Name&&rp->Name->Ptr)?rp->Name->Ptr:""); }
  1229. if(mask==1){
  1230. for(laListItemPointer*lip=rp->AlwaysBranchers.pFirst;lip;lip=lip->pNext){
  1231. laBaseNode* n=lip->p; if(!n->InitDone){ n->Type->Init(n,1); n->InitDone=1; }
  1232. if(n->EvalMagic==magic) continue; if(__DEBUG_PAGE_EVAL__){ printf(" BR %.6x\n",n); }
  1233. n->EvalMagic=magic; n->Type->Eval(n);
  1234. }
  1235. }
  1236. for(laListItemPointer*lip=rp->Eval.pFirst;lip;lip=lip->pNext){
  1237. laBaseNode* n=lip->p; if(!n->InitDone){ n->Type->Init(n,1); n->InitDone=1; }
  1238. if((!(n->Branch&mask)) || (mask==1&&n->Branch!=1) || n->EvalMagic==magic) continue;
  1239. if(__DEBUG_PAGE_EVAL__){ printf(" -- %d %s %.6x\n",mask,n->Type->Name,n); }
  1240. n->EvalMagic=magic; n->Type->Eval(n);
  1241. }
  1242. if(__DEBUG_PAGE_EVAL__ && mask==1){ printf("End\n"); }
  1243. if(mask==1){ magic++; }
  1244. return 1;
  1245. }
  1246. int la_RunInputMapping(){
  1247. MAIN.InputMapping->NeedEval = 0;
  1248. return laRunPage(MAIN.InputMapping->CurrentPage, 1);
  1249. }
  1250. int la_RebuildInputMapping(){
  1251. MAIN.InputMapping->NeedRebuild = 0;
  1252. return laRebuildPageEval(MAIN.InputMapping->CurrentPage);
  1253. }
  1254. //==================================================================================================
  1255. laNodeOutSocket* laCreateOutSocket(void* NodeParentOptional, char* label, int DataType){
  1256. laNodeOutSocket* os=memAcquire(sizeof(laNodeOutSocket));
  1257. strSafeSet(&os->Label, label); os->DataType = DataType; os->Parent=NodeParentOptional;
  1258. return os;
  1259. }
  1260. laNodeInSocket* laCreateInSocket(char* label, int DataType){
  1261. laNodeInSocket* is=memAcquire(sizeof(laNodeInSocket));
  1262. strSafeSet(&is->Label, label); is->DataType = DataType;
  1263. return is;
  1264. }
  1265. void laDestroyInSocket(laNodeInSocket* s){ strSafeDestroy(&s->Label); memLeave(s); }
  1266. void laDestroyOutSocket(laNodeOutSocket* s){ strSafeDestroy(&s->Label); memLeave(s); }
  1267. laNodeCategory* laAddNodeCategory(char* Name,laUiDefineFunc* Ui,int ForRackTypes){
  1268. laNodeCategory* nc=memAcquire(sizeof(laNodeCategory));
  1269. lstAppendItem(&MAIN.NodeCategories,nc);
  1270. strSafeSet(&nc->Name, Name); nc->Ui=Ui; nc->For=ForRackTypes;
  1271. return nc;
  1272. }
  1273. void laNodeCategoryAddNodeTypes(laNodeCategory* nc, ...){
  1274. va_list list; va_start(list,nc);
  1275. laBaseNodeType* nt;
  1276. while(nt=va_arg(list,laBaseNodeType*)){
  1277. lstAppendPointer(&nc->NodeTypes, nt);
  1278. }
  1279. va_end(list);
  1280. }