*/}}

la_nodes_basic.c 97 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637
  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. laBaseNodeType LA_IDN_LOOP;
  39. laBaseNodeType LA_IDN_LOOP_INDEX;
  40. laPropContainer* LA_PC_IDN_GENERIC;
  41. laPropContainer* LA_PC_IDN_KEYBOARD;
  42. laPropContainer* LA_PC_IDN_MOUSE;
  43. laPropContainer* LA_PC_IDN_CONTROLLER;
  44. laPropContainer* LA_PC_IDN_VISUALIZER;
  45. laPropContainer* LA_PC_IDN_SPLIT;
  46. laPropContainer* LA_PC_IDN_SWITCH;
  47. laPropContainer* LA_PC_IDN_COMBINE;
  48. laPropContainer* LA_PC_IDN_VALUES;
  49. laPropContainer* LA_PC_IDN_MATRIX;
  50. laPropContainer* LA_PC_IDN_MATH;
  51. laPropContainer* LA_PC_IDN_SMALL_MATH;
  52. laPropContainer* LA_PC_IDN_MAPPER;
  53. laPropContainer* LA_PC_IDN_RANDOM;
  54. laPropContainer* LA_PC_IDN_VECTOR_MATH;
  55. laPropContainer* LA_PC_IDN_COMMENT;
  56. laPropContainer* LA_PC_IDN_RGB2OKHSL;
  57. laPropContainer* LA_PC_IDN_OKHSL2RGB;
  58. laPropContainer* LA_PC_IDN_LOOP;
  59. laPropContainer* LA_PC_IDN_LOOP_INDEX;
  60. laNodeCategory* LA_NODE_CATEGORY_INPUT;
  61. laNodeCategory* LA_NODE_CATEGORY_MATH;
  62. laNodeCategory* LA_NODE_CATEGORY_ROUTE;
  63. laNodeCategory* LA_NODE_CATEGORY_AUX;
  64. laNodeCategory* LA_NODE_CATEGORY_DRIVER;
  65. laNodeCategory* LA_NODE_CATEGORY_COLOR;
  66. void la_PageClearBranch(laRackPage* rp, int mask);
  67. #define LA_IDN_CONTROLLER_RESET_SOCKET(ns) \
  68. {ns->IntVal[0]=0; ns->Out->DataType=LA_PROP_INT; ns->Offset=0; ns->Out->Data=&ns->IntVal;}
  69. void IDN_KeyboardInit(laKeyboardNode* n, int NoCreate){
  70. if(NoCreate){return;}
  71. n->KeyDown=laCreateOutSocket(n,"DOWN",LA_PROP_INT); n->Key=laCreateOutSocket(n,"KEY",LA_PROP_INT);
  72. n->IsKey=laCreateOutSocket(n,"IS",LA_PROP_INT);
  73. strSafeSet(&n->Base.Name,"Keyboard");
  74. }
  75. void IDN_KeyboardDestroy(laKeyboardNode* n){
  76. laDestroyOutSocket(n->KeyDown); laDestroyOutSocket(n->Key); laDestroyOutSocket(n->IsKey); strSafeDestroy(&n->Base.Name);
  77. }
  78. int IDN_KeyboardVisit(laKeyboardNode* n, laNodeVisitInfo* vi){
  79. LA_GUARD_THIS_NODE(n,vi); LA_ADD_THIS_NODE(n,vi);
  80. n->Key->Data = &n->iKey; n->KeyDown->Data = &n->iKeyDown; n->IsKey->Data=&n->iIsKey;
  81. return LA_DAG_FLAG_PERM;
  82. }
  83. int IDN_KeyboardEval(laKeyboardNode* n){
  84. laEvent* e=MAIN.CurrentInputEvent;
  85. if(!e || !(e->type&LA_KEYBOARD_EVENT)){ n->iKey=0; n->iKeyDown=0; n->iIsKey=0; return 1; }
  86. if(e->type&LA_STATE_DOWN){ n->iKeyDown=1; }else{ n->iKeyDown=0; }
  87. n->iKey = e->key; n->iIsKey=1;
  88. return 1;
  89. }
  90. void IDN_KeyboardCopy(laKeyboardNode* new, laKeyboardNode* old, int DoRematch){
  91. if(DoRematch){ return; }
  92. LA_IDN_OLD_DUPL(Key); LA_IDN_OLD_DUPL(KeyDown); LA_IDN_OLD_DUPL(IsKey);
  93. }
  94. void laui_KeyboardNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){
  95. laColumn* c=laFirstColumn(uil); laKeyboardNode*n=This->EndInstance;
  96. LA_BASE_NODE_HEADER(uil,c,This);
  97. laUiItem* b=laBeginRow(uil,c,0,0);
  98. laShowNodeSocket(uil,c,This,"is_key",0)->Flags|=LA_UI_SOCKET_LABEL_E;
  99. laShowLabel(uil,c,"Key",0,0)->Expand=1;
  100. laShowNodeSocket(uil,c,This,"key",0)->Flags|=LA_UI_SOCKET_LABEL_W;
  101. laShowNodeSocket(uil,c,This,"key_down",0)->Flags|=LA_UI_SOCKET_LABEL_W;
  102. laEndRow(uil,b);
  103. }
  104. void IDN_ControllerInit(laInputControllerNode* n, int NoCreate){
  105. if(NoCreate){return;}
  106. for(int i=0;i<8;i++){ n->Sockets[i].Out=laCreateOutSocket(n, "out", 0); n->Sockets[i].Parent=n; }
  107. strSafeSet(&n->Base.Name,"Controller Output");
  108. }
  109. void IDN_ControllerDestroy(laInputControllerNode* n){
  110. for(int i=0;i<8;i++){ laDestroyOutSocket(n->Sockets[i].Out); }
  111. strSafeDestroy(&n->Base.Name);
  112. }
  113. int IDN_ControllerVisit(laInputControllerNode* n, laNodeVisitInfo* vi){
  114. laController* c=la_FindControllerWithID(n->UserID);
  115. 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; }
  116. else{
  117. for(int i=0;i<8;i++){ laInputControllerNodeSocket* ns=&n->Sockets[i];
  118. if(!ns->Which || !ns->Which->Ptr){ LA_IDN_CONTROLLER_RESET_SOCKET(ns); continue; }
  119. laPropContainer*pc=la_EnsureSubTarget(LA_PROP_CONTROLLER, c);
  120. laProp* p=la_PropLookup(&pc->Props, n->Sockets[i].Which->Ptr);
  121. if((!p)||(!p->Offset)||
  122. ((p->PropertyType!=LA_PROP_INT)&&(p->PropertyType!=LA_PROP_ENUM)&&
  123. (p->PropertyType!=(LA_PROP_INT|LA_PROP_ARRAY))&&(p->PropertyType!=(LA_PROP_ENUM|LA_PROP_ARRAY)))){ LA_IDN_CONTROLLER_RESET_SOCKET(ns); continue; }
  124. if(p->PropertyType==LA_PROP_INT){ ns->Out->DataType=LA_PROP_FLOAT; ns->Out->Data=&ns->RealVal; ns->Out->ArrLen=1; }
  125. 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; }
  126. elif(p->PropertyType==LA_PROP_ENUM){ ns->Out->DataType=LA_PROP_ENUM; ns->Out->Data=&ns->IntVal; ns->Out->ArrLen=1; }
  127. 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; }
  128. ns->Offset=p->Offset;
  129. }
  130. }
  131. LA_ADD_THIS_NODE(n,vi);
  132. return LA_DAG_FLAG_PERM;
  133. }
  134. int IDN_ControllerEval(laInputControllerNode* n){
  135. laNotifyInstanceUsers(n);
  136. laController* c=la_FindControllerWithID(n->UserID); if(!c){
  137. for(int i=0;i<8;i++){ laInputControllerNodeSocket* ns=&n->Sockets[i]; LA_IDN_CONTROLLER_RESET_SOCKET(ns); } return 1;
  138. }
  139. for(int i=0;i<8;i++){ laInputControllerNodeSocket* ns=&n->Sockets[i];
  140. int *addr=((char*)c)+ns->Offset; char* addc=addr;
  141. if(ns->Out->DataType==LA_PROP_FLOAT){ ns->RealVal[0]=(real)(*addr)/32767.0; }
  142. 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; }
  143. elif(ns->Out->DataType==LA_PROP_ENUM){ ns->IntVal[0]=(*addc); }
  144. elif(ns->Out->DataType==(LA_PROP_ENUM|LA_PROP_ARRAY)){ for(int a=0;a<ns->Out->ArrLen;a++) ns->IntVal[a]=addc[a]; }
  145. }
  146. return 1;
  147. }
  148. void IDN_ControllerCopy(laInputControllerNode* new, laInputControllerNode* old, int DoRematch){
  149. if(DoRematch) return;
  150. for(int i=0;i<8;i++){ old->Sockets[i].Out->Duplicated=new->Sockets[i].Out;
  151. strSafeSet(&new->Sockets[i].Which,old->Sockets[i].Which?old->Sockets[i].Which->Ptr:0);
  152. }
  153. new->Mode=old->Mode;new->UserID=old->UserID;
  154. }
  155. void laui_ControllerNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){
  156. laColumn* c=laFirstColumn(uil); laInputControllerNode*n=This->EndInstance;
  157. laColumn* cl,*cr;
  158. LA_BASE_NODE_HEADER(uil,c,This);
  159. laSplitColumn(uil,c,0.3); cl=laLeftColumn(c,0); cr=laRightColumn(c,0);
  160. laUiItem* b=laBeginRow(uil,c,0,0);
  161. laShowItem(uil,c,This,"base.name")->Expand=1;
  162. laShowItem(uil,c,This,"user_id");
  163. laEndRow(uil,b);
  164. char* buf[128],buf2[128];
  165. for(int i=0;i<8;i++){
  166. sprintf(buf,"out%d.which",i); laShowItem(uil,cl,This,buf);
  167. laUiItem* b=laBeginRow(uil,cr,0,0);
  168. sprintf(buf2,"out%d.out.data_type",i);
  169. laUiItem* b2=laOnConditionThat(uil,cr,laEqual(laPropExpression(This,buf2),laIntExpression(LA_PROP_FLOAT)));{
  170. sprintf(buf,"out%d.axis",i); laShowItem(uil,cr,This,buf)->Expand=1;
  171. }laElse(uil,b2);{
  172. laUiItem* b3=laOnConditionThat(uil,cr,laEqual(laPropExpression(This,buf2),laIntExpression(LA_PROP_FLOAT|LA_PROP_ARRAY)));{
  173. 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;
  174. }laElse(uil,b3);{
  175. sprintf(buf,"out%d.switch",i); laUiItem* sui=laShowItem(uil,cr,This,buf);sui->Expand=1;sui->Flags|=LA_UI_FLAGS_TRANSPOSE;
  176. }laEndCondition(uil,b3);
  177. }laEndCondition(uil,b2);
  178. sprintf(buf,"out%d.out",i); laShowNodeSocket(uil,cr,This,buf,0);
  179. laEndRow(uil,b);
  180. }
  181. }
  182. void IDN_InputVisualizerInit(laInputVisualizerNode* n, int NoCreate){
  183. if(NoCreate){return;}
  184. n->In=laCreateInSocket("IN", 0);
  185. strSafeSet(&n->Base.Name,"Input Visualizer");
  186. }
  187. void IDN_InputVisualizerDestroy(laInputVisualizerNode* n){
  188. laDestroyInSocket(n->In);
  189. strSafeDestroy(&n->Base.Name);
  190. }
  191. int IDN_InputVisualizerVisit(laInputVisualizerNode* n, laNodeVisitInfo* vi){
  192. LA_GUARD_THIS_NODE(n,vi);
  193. if(LA_SRC_AND_PARENT(n->In)){ laBaseNode* sn=n->In->Source->Parent;LA_VISIT_NODE(sn,vi); }
  194. LA_ADD_THIS_NODE(n,vi);
  195. return LA_DAG_FLAG_PERM;
  196. }
  197. int IDN_InputVisualizerEval(laInputVisualizerNode* n){
  198. if(!n->In->Source) return 0;
  199. laNodeOutSocket* os=n->In->Source; int arrlen=1;
  200. switch(os->DataType){
  201. case LA_PROP_FLOAT|LA_PROP_ARRAY:
  202. case LA_PROP_FLOAT: if(os->ArrLen)arrlen=os->ArrLen; memcpy(n->RealVal,os->Data,sizeof(real)*arrlen); n->In->ArrLen=arrlen; break;
  203. case LA_PROP_ENUM|LA_PROP_ARRAY:
  204. case LA_PROP_ENUM: if(os->ArrLen)arrlen=os->ArrLen; memcpy(n->IntVal,os->Data,sizeof(int)*arrlen); n->In->ArrLen=arrlen; break;
  205. default: n->IntVal[0]=0; n->In->ArrLen=1; break;
  206. }
  207. n->In->DataType=os->DataType;
  208. laNotifyInstanceUsers(n);
  209. return 1;
  210. }
  211. void IDN_InputVisualizerCopy(laInputVisualizerNode* new, laInputVisualizerNode* old, int DoRematch){
  212. if(DoRematch){ LA_IDN_NEW_LINK(In) return; }
  213. }
  214. void laui_InputVisualizeNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){
  215. laColumn* c=laFirstColumn(uil); laInputVisualizerNode*n=This->EndInstance;
  216. LA_BASE_NODE_HEADER(uil,c,This);
  217. laColumn* cl,*cr; laSplitColumn(uil,c,0.4); cl=laLeftColumn(c,1); cr=laRightColumn(c,0);
  218. laShowNodeSocket(uil,cl,This,"in",0);
  219. laUiItem* b2=laOnConditionThat(uil,cr,laEqual(laPropExpression(This,"in.data_type"),laIntExpression(LA_PROP_FLOAT)));{
  220. laShowItem(uil,cr,This,"axis");
  221. }laElse(uil,b2);{
  222. laUiItem* b3=laOnConditionThat(uil,cr,laEqual(laPropExpression(This,"in.data_type"),laIntExpression(LA_PROP_FLOAT|LA_PROP_ARRAY)));{
  223. laUiItem* aui=laShowItem(uil,cr,This,"axis2d");
  224. }laElse(uil,b3);{
  225. laUiItem* sui=laShowItem(uil,cr,This,"switch");
  226. }laEndCondition(uil,b3);
  227. }laEndCondition(uil,b2);
  228. }
  229. void IDN_SplitInit(laSplitNode* n, int NoCreate){
  230. if(NoCreate){return;}
  231. n->In=laCreateInSocket("in", 0); strSafeSet(&n->Base.Name,"Split");
  232. for(int i=0;i<8;i++){ char str[4]; sprintf(str,"%d",i); n->Out[i].Out=laCreateOutSocket(n,str,0); }
  233. }
  234. void IDN_SplitDestroy(laSplitNode* n){
  235. laDestroyInSocket(n->In); strSafeDestroy(&n->Base.Name);
  236. for(int i=0;i<8;i++){ laDestroyOutSocket(n->Out[i].Out); }
  237. }
  238. int IDN_SplitVisit(laSplitNode* n, laNodeVisitInfo* vi){
  239. LA_GUARD_THIS_NODE(n,vi);
  240. if(LA_SRC_AND_PARENT(n->In)){ laBaseNode* sn=n->In->Source->Parent; LA_VISIT_NODE(sn,vi); }
  241. LA_ADD_THIS_NODE(n,vi);
  242. return LA_DAG_FLAG_PERM;
  243. }
  244. int IDN_SplitEval(laSplitNode* n){
  245. if(!n->In->Source) return 0;
  246. laNodeOutSocket* os=n->In->Source; int arrlen=1;
  247. switch(os->DataType){
  248. case LA_PROP_FLOAT|LA_PROP_ARRAY:
  249. case LA_PROP_FLOAT: if(os->ArrLen) n->ArrLen=os->ArrLen;
  250. 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]; }
  251. memcpy(n->RealVal,os->Data,sizeof(real)*n->ArrLen); n->In->ArrLen=arrlen; break;
  252. case LA_PROP_ENUM|LA_PROP_ARRAY:
  253. case LA_PROP_ENUM: if(os->ArrLen) n->ArrLen=os->ArrLen;
  254. 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]; }
  255. memcpy(n->IntVal,os->Data,sizeof(int)*n->ArrLen); n->In->ArrLen=arrlen; break;
  256. default:
  257. 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]; }
  258. n->IntVal[0]=0; n->In->ArrLen=1; break;
  259. }
  260. n->In->DataType=os->DataType;
  261. return 1;
  262. }
  263. void IDN_SplitCopy(laSplitNode* new, laSplitNode* old, int DoRematch){
  264. if(DoRematch){ LA_IDN_NEW_LINK(In) return; }
  265. for(int i=0;i<8;i++){ old->Out[i].Out->Duplicated=new->Out[i].Out; }
  266. }
  267. void laui_SplitNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){
  268. laColumn* c=laFirstColumn(uil); laSplitNode*n=This->EndInstance;
  269. laColumn* cl,*cr; laSplitColumn(uil,c,0.4); cl=laLeftColumn(c,1); cr=laRightColumn(c,0);
  270. LA_BASE_NODE_HEADER(uil,c,This);
  271. laUiItem* b=laBeginRow(uil,c,0,0);
  272. laShowNodeSocket(uil,c,This,"in",0);
  273. laShowItemFull(uil,c,This,"array_length",LA_WIDGET_INT_PLAIN,0,0,0);
  274. laShowLabel(uil,c,"🡲",0,0)->Expand=1;
  275. for(int i=0;i<8;i++){
  276. char* buf[128]; sprintf(buf,"out%d.out",i); laShowNodeSocket(uil,cr,This,buf,0);
  277. }
  278. laEndRow(uil,b);
  279. }
  280. void IDN_SwitchInit(laSwitchNode* n, int NoCreate){
  281. if(NoCreate){return;}
  282. n->SwitchIn=laCreateInSocket("sw in",0); n->Out=laCreateOutSocket(n,"out",0); strSafeSet(&n->Base.Name,"Switch");
  283. for(int i=0;i<8;i++){ char str[4]; sprintf(str,"%d",i); n->In[i].In=laCreateInSocket(n,str); }
  284. }
  285. void IDN_SwitchDestroy(laSwitchNode* n){
  286. laDestroyInSocket(n->SwitchIn); laDestroyOutSocket(n->Out); strSafeDestroy(&n->Base.Name);
  287. for(int i=0;i<8;i++){ laDestroyInSocket(n->In[i].In); }
  288. }
  289. int IDN_SwitchVisit(laSwitchNode* n, laNodeVisitInfo* vi){
  290. LA_GUARD_THIS_NODE(n,vi); n->MaxUsed=0; n->Page=vi->Page;
  291. for(int i=0;i<8;i++){ if(n->In[i].In->Source){ n->MaxUsed=i+2; } }
  292. uint64_t OrigBranch=vi->Branch; int NextBranch=vi->NextBranch;
  293. vi->NextBranch+=n->MaxUsed; n->BranchSW=(1<<(NextBranch-1));
  294. if(OrigBranch==1){ lstAppendPointer(vi->br,n); }
  295. for(int i=0;i<8;i++){
  296. if(n->In[i].In->Source){
  297. vi->Branch=OrigBranch|(1<<(NextBranch+i));
  298. laBaseNode* sn=n->In[i].In->Source->Parent; LA_VISIT_NODE(sn,vi);
  299. }
  300. }
  301. vi->Branch=OrigBranch|n->BranchSW;
  302. laBaseNode* sw=n->SwitchIn->Source?n->SwitchIn->Source->Parent:0; if(sw){ LA_VISIT_NODE(sw,vi); }
  303. vi->Branch=OrigBranch;
  304. LA_ADD_THIS_NODE(n,vi);
  305. return LA_DAG_FLAG_PERM;
  306. }
  307. int IDN_SwitchEval(laSwitchNode* n){
  308. int sw=n->Switch;
  309. if(n->SwitchIn->Source){
  310. laRunPage(n->Page,n->BranchSW);
  311. laNodeOutSocket* os=n->SwitchIn->Source; int* id; real* fd;
  312. switch(os->DataType){
  313. case LA_PROP_ARRAY|LA_PROP_ENUM:
  314. id=os->Data; for(int i=0;i<os->ArrLen;i++){ if(id[i]){sw=i; break;} } break;
  315. case LA_PROP_ENUM: case LA_PROP_INT: case LA_PROP_INT|LA_PROP_ARRAY:
  316. id=os->Data; sw=*id; break;
  317. case LA_PROP_FLOAT: case LA_PROP_FLOAT|LA_PROP_ARRAY:
  318. fd=os->Data; sw=(int)(*fd); break;
  319. default: sw=0; break;
  320. }
  321. }
  322. laRunPage(n->Page,(n->BranchSW<<(sw+1)));
  323. TNS_CLAMP(sw,0,7);
  324. laSwitchNodeInSocket *is=&n->In[sw];
  325. 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; }
  326. else{ n->Out->Data=&n->TempVal; n->Out->DataType=LA_PROP_FLOAT; n->Out->ArrLen=1; }
  327. return 1;
  328. }
  329. void IDN_SwitchCopy(laSwitchNode* new, laSwitchNode* old, int DoRematch){
  330. if(DoRematch){ for(int i=0;i<8;i++){ LA_IDN_NEW_LINK(In[i].In) } LA_IDN_NEW_LINK(SwitchIn) return; }
  331. old->Out->Duplicated=new->Out; new->Switch=old->Switch;
  332. }
  333. void laui_SwitchNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){
  334. laColumn* c=laFirstColumn(uil); laSwitchNode*n=This->EndInstance;
  335. laColumn* cl,*cr; laSplitColumn(uil,c,0.4); cl=laLeftColumn(c,1); cr=laRightColumn(c,0);
  336. LA_BASE_NODE_HEADER(uil,c,This);
  337. laUiItem* b=laBeginRow(uil,c,0,0);
  338. for(int i=0;i<8;i++){
  339. char* buf[128]; sprintf(buf,"in%d.in",i); laShowNodeSocket(uil,cr,This,buf,0);
  340. } laShowSeparator(uil,c)->Expand=1;
  341. laEndRow(uil,b);
  342. b=laBeginRow(uil,c,0,0);
  343. laShowItem(uil,c,This,"switch_in");
  344. laUiItem* b2=laOnConditionThat(uil,c,laNot(laPropExpression(This,"switch_in.source")));{
  345. laShowItem(uil,c,This,"switch");
  346. };laEndCondition(uil,b2);
  347. laShowSeparator(uil,c)->Expand=1;
  348. laShowNodeSocket(uil,c,This,"out",0);
  349. laEndRow(uil,b);
  350. }
  351. void IDN_CombineInit(laCombineNode* n, int NoCreate){
  352. if(!NoCreate){
  353. n->Out=laCreateOutSocket(n,"F",0);n->OutInt=laCreateOutSocket(n,"I",0);n->OutEnum=laCreateOutSocket(n,"E",0); strSafeSet(&n->Base.Name,"Combine");
  354. for(int i=0;i<8;i++){ char str[4]; sprintf(str,"%d",i); n->In[i].In=laCreateInSocket(n,str); }
  355. }
  356. n->Out->Data=n->Values; n->OutInt->Data=n->ValuesI; n->OutEnum->Data=n->ValuesI;
  357. 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;
  358. }
  359. void IDN_CombineDestroy(laCombineNode* n){
  360. laDestroyOutSocket(n->Out);laDestroyOutSocket(n->OutInt);laDestroyOutSocket(n->OutEnum); strSafeDestroy(&n->Base.Name);
  361. for(int i=0;i<8;i++){ laDestroyInSocket(n->In[i].In); }
  362. }
  363. int IDN_CombineVisit(laCombineNode* n, laNodeVisitInfo* vi){
  364. LA_GUARD_THIS_NODE(n,vi);
  365. 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); } }
  366. LA_ADD_THIS_NODE(n,vi);
  367. return LA_DAG_FLAG_PERM;
  368. }
  369. int IDN_CombineEval(laCombineNode* n){
  370. int maxlen=0;
  371. for(int i=0;i<8;i++){ laNodeInSocket *is=n->In[i].In;
  372. if(LA_SRC_AND_PARENT(is)){
  373. if((is->Source->DataType&LA_PROP_FLOAT) && is->Source->Data){ n->Values[i]=*((real*)is->Source->Data); }
  374. elif((is->Source->DataType&LA_PROP_INT) && is->Source->Data){ n->Values[i]=*((int*)is->Source->Data); }
  375. elif((is->Source->DataType&LA_PROP_ENUM) && is->Source->Data){ n->Values[i]=*((int*)is->Source->Data); }
  376. else n->Values[i]=0;
  377. maxlen=i+1;
  378. }
  379. else n->Values[i]=0;
  380. n->ValuesI[i]=n->Values[i];
  381. }
  382. n->Out->ArrLen=n->OutInt->ArrLen=n->OutEnum->ArrLen=maxlen;
  383. return 1;
  384. }
  385. void IDN_CombineCopy(laCombineNode* new, laCombineNode* old, int DoRematch){
  386. if(DoRematch){
  387. for(int i=0;i<8;i++){ LA_IDN_NEW_LINK(In[i].In) }
  388. return;
  389. }
  390. old->Out->Duplicated=new->Out; old->OutInt->Duplicated=new->OutInt; old->OutEnum->Duplicated=new->OutEnum;
  391. }
  392. void laui_CombineNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){
  393. laColumn* c=laFirstColumn(uil); laCombineNode*n=This->EndInstance;
  394. laColumn* cl,*cr; laSplitColumn(uil,c,0.4); cl=laLeftColumn(c,1); cr=laRightColumn(c,0);
  395. LA_BASE_NODE_HEADER(uil,c,This);
  396. laUiItem* b=laBeginRow(uil,c,0,0);
  397. for(int i=0;i<8;i++){
  398. char* buf[128]; sprintf(buf,"in%d.in",i); laShowNodeSocket(uil,cr,This,buf,0);
  399. } laShowSeparator(uil,c)->Expand=1;
  400. laEndRow(uil,b);
  401. b=laBeginRow(uil,c,0,0);
  402. laUiItem* lu=laShowLabel(uil,c,"Combine 🡲",0,0); lu->Expand=1; lu->Flags|=LA_TEXT_ALIGN_RIGHT;
  403. laShowNodeSocket(uil,c,This,"out_enum",0)->Flags|=LA_UI_SOCKET_LABEL_W;
  404. laShowNodeSocket(uil,c,This,"out_int",0)->Flags|=LA_UI_SOCKET_LABEL_W;
  405. laShowNodeSocket(uil,c,This,"out",0)->Flags|=LA_UI_SOCKET_LABEL_W;
  406. laEndRow(uil,b);
  407. }
  408. void IDN_ValuesInit(laValuesNode* n, int NoCreate){
  409. if(NoCreate){return;}
  410. strSafeSet(&n->Base.Name,"Values");
  411. for(int i=0;i<8;i++){ char str[4]; sprintf(str,"%d",i); n->Out[i].Out=laCreateOutSocket(n,str,0); }
  412. }
  413. void IDN_ValuesDestroy(laValuesNode* n){
  414. strSafeDestroy(&n->Base.Name);
  415. for(int i=0;i<8;i++){ laDestroyOutSocket(n->Out[i].Out); }
  416. }
  417. int IDN_ValuesVisit(laValuesNode* n, laNodeVisitInfo* vi){
  418. LA_GUARD_THIS_NODE(n,vi);
  419. LA_ADD_THIS_NODE(n,vi);
  420. return LA_DAG_FLAG_PERM;
  421. }
  422. int IDN_ValuesEval(laValuesNode* n){
  423. for(int i=0;i<8;i++){ laNodeOutSocket *is=n->Out[i].Out;
  424. if(n->Modes[i]==LA_VALUES_NODE_FLOAT){ is->Data=&n->Values[i]; is->DataType=LA_PROP_FLOAT; }
  425. if(n->Modes[i]==LA_VALUES_NODE_INT){ is->Data=&n->ValuesI[i]; is->DataType=LA_PROP_INT; }
  426. if(n->Modes[i]==LA_VALUES_NODE_ENUM){ is->Data=&n->ValuesE[i]; is->DataType=LA_PROP_ENUM; }
  427. }
  428. return 1;
  429. }
  430. void IDN_ValuesCopy(laValuesNode* new, laValuesNode* old, int DoRematch){
  431. if(DoRematch){ return; }
  432. for(int i=0;i<8;i++){
  433. old->Out[i].Out->Duplicated=new->Out[i].Out; new->Modes[i]=old->Modes[i];
  434. new->Values[i]=old->Values[i]; new->ValuesE[i]=old->ValuesE[i]; new->ValuesI[i]=old->ValuesI[i];
  435. }
  436. }
  437. void laui_ValuesNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){
  438. laColumn* c=laFirstColumn(uil); laValuesNode*n=This->EndInstance;
  439. laUiItem*b,*b2;
  440. LA_BASE_NODE_HEADER(uil,c,This);
  441. laColumn* cl,*cr; laSplitColumn(uil,c,0.4); cl=laLeftColumn(c,3); cr=laRightColumn(c,0);
  442. for(int i=0;i<8;i++){
  443. char* bufm[32]; sprintf(bufm,"mode%d",i); laShowItem(uil,cl,This,bufm);
  444. b=laBeginRow(uil,cr,0,0);
  445. b2=laOnConditionThat(uil,cr,laEqual(laPropExpression(This,bufm),laIntExpression(LA_VALUES_NODE_FLOAT)));{
  446. char* buf[32]; sprintf(buf,"value%d",i); laShowItem(uil,cr,This,buf)->Expand=1;
  447. }laEndCondition(uil,b2);
  448. b2=laOnConditionThat(uil,cr,laEqual(laPropExpression(This,bufm),laIntExpression(LA_VALUES_NODE_INT)));{
  449. char* buf[32]; sprintf(buf,"valuei%d",i); laShowItem(uil,cr,This,buf)->Expand=1;
  450. }laEndCondition(uil,b2);
  451. b2=laOnConditionThat(uil,cr,laEqual(laPropExpression(This,bufm),laIntExpression(LA_VALUES_NODE_ENUM)));{
  452. char* buf[32]; sprintf(buf,"valuee%d",i); laUiItem* eui=laShowItem(uil,cr,This,buf); eui->Expand=1; eui->Flags|=LA_UI_FLAGS_HIGHLIGHT;
  453. }laEndCondition(uil,b2);
  454. sprintf(bufm,"out%d.out",i); laShowNodeSocket(uil,cr,This,bufm,0);
  455. laEndRow(uil,b);
  456. }
  457. }
  458. void IDN_MatrixInit(laMatrixNode* n, int NoCreate){
  459. if(!NoCreate){
  460. strSafeSet(&n->Base.Name,"Matrix");
  461. n->InL=laCreateInSocket("l",0); n->InR=laCreateInSocket("r",0); n->Out=laCreateOutSocket(n,"MAT",LA_PROP_FLOAT|LA_PROP_ARRAY);
  462. }
  463. n->Out->ArrLen=16; n->Out->Data=n->Mat;
  464. }
  465. void IDN_MatrixDestroy(laMatrixNode* n){
  466. strSafeDestroy(&n->Base.Name);
  467. laDestroyInSocket(n->InL); laDestroyInSocket(n->InR); laDestroyOutSocket(n->Out);
  468. }
  469. int IDN_MatrixVisit(laMatrixNode* n, laNodeVisitInfo* vi){
  470. LA_GUARD_THIS_NODE(n,vi);
  471. if(LA_SRC_AND_PARENT(n->InL)){ laBaseNode* bn=n->InL->Source->Parent; LA_VISIT_NODE(bn,vi); }
  472. if(LA_SRC_AND_PARENT(n->InR)){ laBaseNode* bn=n->InR->Source->Parent; LA_VISIT_NODE(bn,vi); }
  473. LA_ADD_THIS_NODE(n,vi);
  474. return LA_DAG_FLAG_PERM;
  475. }
  476. int IDN_MatrixEval(laMatrixNode* n){
  477. int hasl=LA_SRC_AND_PARENT(n->InL),hasr=LA_SRC_AND_PARENT(n->InR);
  478. if((!hasl) && (!hasr)){ tnsLoadIdentity44d(n->Mat); return 0; }
  479. if(hasl&&((n->InL->Source->DataType!=(LA_PROP_FLOAT|LA_PROP_ARRAY))||n->InL->Source->ArrLen!=16)){tnsLoadIdentity44d(n->Mat); return 0;}
  480. if(hasr&&((n->InR->Source->DataType!=(LA_PROP_FLOAT|LA_PROP_ARRAY))||n->InR->Source->ArrLen!=16)){tnsLoadIdentity44d(n->Mat); return 0;}
  481. if(n->Operation==LA_MATRIX_NODE_OP_INV){
  482. real* mat; if(hasl)mat=n->InL->Source->Data;else mat=n->InR->Source->Data;
  483. tnsInverse44d(n->Mat, mat);
  484. }else{
  485. if(!hasl) { memcpy(n->Mat,n->InR->Source->Data,sizeof(tnsMatrix44d)); }
  486. elif(!hasr) { memcpy(n->Mat,n->InL->Source->Data,sizeof(tnsMatrix44d)); }
  487. else{
  488. tnsMultiply44d(n->Mat,n->InL->Source->Data,n->InR->Source->Data);
  489. }
  490. }
  491. return 1;
  492. }
  493. void IDN_MatrixCopy(laMatrixNode* new, laMatrixNode* old, int DoRematch){
  494. if(DoRematch){ LA_IDN_NEW_LINK(InL) LA_IDN_NEW_LINK(InR) return; }
  495. old->Out->Duplicated=new->Out; new->Operation=old->Operation;
  496. }
  497. void laui_MatrixNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){
  498. laColumn* c=laFirstColumn(uil); laMatrixNode*n=This->EndInstance;
  499. laColumn* cl,*cr; laSplitColumn(uil,c,0.4); cl=laLeftColumn(c,3); cr=laRightColumn(c,0);
  500. laUiItem*b,*b2;
  501. LA_BASE_NODE_HEADER(uil,c,This);
  502. b=laBeginRow(uil,c,0,0);
  503. laShowNodeSocket(uil,c,This,"in_l",0); laShowNodeSocket(uil,c,This,"in_r",0); laShowItem(uil,c,This,"operation");
  504. laShowSeparator(uil,c)->Expand=1; laShowNodeSocket(uil,c,This,"out",0)->Flags|=LA_UI_SOCKET_LABEL_W;
  505. laEndRow(uil,b);
  506. }
  507. void IDN_MathInit(laMathNode* n, int NoCreate){
  508. if(!NoCreate){
  509. strSafeSet(&n->Base.Name,"Math");
  510. n->InL=laCreateInSocket("l",0); n->InR=laCreateInSocket("r",0);
  511. n->Out=laCreateOutSocket(n,"F",LA_PROP_FLOAT); n->OutInt=laCreateOutSocket(n,"I",LA_PROP_INT);
  512. }
  513. n->Out->Data=&n->Value; n->OutInt->Data=&n->ValueI;
  514. }
  515. void IDN_MathDestroy(laMathNode* n){
  516. strSafeDestroy(&n->Base.Name); laDestroyInSocket(n->InL); laDestroyInSocket(n->InR); laDestroyOutSocket(n->Out); laDestroyOutSocket(n->OutInt);
  517. }
  518. int IDN_MathVisit(laMathNode* n, laNodeVisitInfo* vi){
  519. LA_GUARD_THIS_NODE(n,vi);
  520. if(LA_SRC_AND_PARENT(n->InL)){ laBaseNode* bn=n->InL->Source->Parent; LA_VISIT_NODE(bn,vi); }
  521. if(LA_SRC_AND_PARENT(n->InR)){ laBaseNode* bn=n->InR->Source->Parent; LA_VISIT_NODE(bn,vi); }
  522. LA_ADD_THIS_NODE(n,vi);
  523. return LA_DAG_FLAG_PERM;
  524. }
  525. #define LA_GET_SRC_AS_FLOAT(var, socket) \
  526. {if(socket->Source->DataType&LA_PROP_FLOAT) var=*((real*)socket->Source->Data);\
  527. if(socket->Source->DataType&(LA_PROP_INT|LA_PROP_ENUM)) var=*((int*)socket->Source->Data);}
  528. int IDN_MathEval(laMathNode* n){
  529. real vl=n->ValueL;real vr=n->ValueR;
  530. int hasl=LA_SRC_AND_PARENT(n->InL),hasr=LA_SRC_AND_PARENT(n->InR);
  531. if(hasl){ LA_GET_SRC_AS_FLOAT(vl,n->InL) } if(hasr){ LA_GET_SRC_AS_FLOAT(vr,n->InR) }
  532. switch(n->Operation){
  533. case LA_MATH_NODE_OP_ADD: default: n->Value=vl+vr; break;
  534. case LA_MATH_NODE_OP_SUB: n->Value=vl-vr; break;
  535. case LA_MATH_NODE_OP_MUL: n->Value=vl*vr; break;
  536. case LA_MATH_NODE_OP_DIV: if(vr)n->Value=vl/vr;else n->Value=0; break;
  537. case LA_MATH_NODE_OP_POW: n->Value=pow(vl,vr); break;
  538. case LA_MATH_NODE_OP_LOG: n->Value=log2(vl)/log2(vr); break;
  539. case LA_MATH_NODE_OP_SIN: n->Value=sin(vl); break;
  540. case LA_MATH_NODE_OP_COS: n->Value=cos(vl); break;
  541. case LA_MATH_NODE_OP_TAN: n->Value=tan(vl); break;
  542. case LA_MATH_NODE_OP_ASIN: n->Value=asin(vl); break;
  543. case LA_MATH_NODE_OP_ACOS: n->Value=acos(vl); break;
  544. case LA_MATH_NODE_OP_ATAN: n->Value=atan(vl); break;
  545. case LA_MATH_NODE_OP_ATAN2: n->Value=atan2(vl,vr); break;
  546. case LA_MATH_NODE_OP_MOD: n->Value=fmod(vl,vr); break;
  547. }
  548. n->ValueI=(int)n->Value;
  549. return 1;
  550. }
  551. void IDN_MathCopy(laMathNode* new, laMathNode* old, int DoRematch){
  552. if(DoRematch){ LA_IDN_NEW_LINK(InL) LA_IDN_NEW_LINK(InR) return; }
  553. old->Out->Duplicated=new->Out; old->OutInt->Duplicated=new->OutInt; new->Operation=old->Operation;
  554. new->ValueL=old->ValueL; new->ValueR=old->ValueR;
  555. }
  556. void laui_MathNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){
  557. laColumn* c=laFirstColumn(uil); laMathNode*n=This->EndInstance;
  558. laColumn* cl,*cr; laSplitColumn(uil,c,0.4); cl=laLeftColumn(c,3); cr=laRightColumn(c,0);
  559. laUiItem*b,*b2;
  560. LA_BASE_NODE_HEADER(uil,c,This);
  561. b=laBeginRow(uil,c,0,0);
  562. 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);
  563. laShowSeparator(uil,c)->Expand=1; laShowItem(uil,c,This,"operation");
  564. laEndRow(uil,b);
  565. b=laBeginRow(uil,c,0,0);
  566. 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);
  567. laShowSeparator(uil,c)->Expand=1;
  568. laShowNodeSocket(uil,c,This,"out_int",0)->Flags|=LA_UI_SOCKET_LABEL_W;
  569. laShowNodeSocket(uil,c,This,"out",0)->Flags|=LA_UI_SOCKET_LABEL_W;
  570. laEndRow(uil,b);
  571. }
  572. void laui_SmallMathNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){
  573. laColumn* c=laFirstColumn(uil); laMathNode*n=This->EndInstance;
  574. laColumn* cl,*cr; laSplitColumn(uil,c,0.4); cl=laLeftColumn(c,3); cr=laRightColumn(c,0);
  575. laUiItem*b,*b2;
  576. LA_BASE_NODE_HEADER(uil,c,This);
  577. b=laBeginRow(uil,c,0,0);
  578. laShowNodeSocket(uil,c,This,"in_l",0);laShowNodeSocket(uil,c,This,"in_r",0);
  579. laShowSeparator(uil,c)->Expand=1;laShowItem(uil,c,This,"operation");
  580. laShowNodeSocket(uil,c,This,"out",0)->Flags|=LA_UI_SOCKET_LABEL_W;
  581. laEndRow(uil,b);
  582. }
  583. void IDN_MapperInit(laMapperNode* n, int NoCreate){
  584. if(!NoCreate){
  585. strSafeSet(&n->Base.Name,"Mapper");
  586. n->Mapper=laValueMapperInit();
  587. }
  588. if(!n->In) n->In=laCreateInSocket("IN",LA_PROP_FLOAT); if(!n->Out) n->Out=laCreateOutSocket(n,"OUT",LA_PROP_FLOAT);
  589. if(!n->InMin) n->InMin=laCreateInSocket("[IN",LA_PROP_FLOAT); if(!n->InMax) n->InMax=laCreateInSocket("IN]",LA_PROP_FLOAT);
  590. if(!n->OutMin) n->OutMin=laCreateInSocket("[OUT",LA_PROP_FLOAT); if(!n->OutMax) n->OutMax=laCreateInSocket("OUT]",LA_PROP_FLOAT);
  591. n->Out->Data=&n->rOut;
  592. }
  593. void IDN_MapperDestroy(laMapperNode* n){
  594. strSafeDestroy(&n->Base.Name);
  595. laDestroyInSocket(n->In); laDestroyOutSocket(n->Out);
  596. laDestroyInSocket(n->InMin); laDestroyInSocket(n->InMax); laDestroyInSocket(n->OutMin); laDestroyInSocket(n->OutMax);
  597. laValueMapperDestroy(n->Mapper);
  598. }
  599. int IDN_MapperVisit(laMapperNode* n, laNodeVisitInfo* vi){
  600. LA_GUARD_THIS_NODE(n,vi);
  601. if(LA_SRC_AND_PARENT(n->In)){ laBaseNode* bn=n->In->Source->Parent; LA_VISIT_NODE(bn,vi); }
  602. if(LA_SRC_AND_PARENT(n->InMin)){ laBaseNode* bn=n->InMin->Source->Parent; LA_VISIT_NODE(bn,vi); }
  603. if(LA_SRC_AND_PARENT(n->InMax)){ laBaseNode* bn=n->InMax->Source->Parent; LA_VISIT_NODE(bn,vi); }
  604. if(LA_SRC_AND_PARENT(n->OutMin)){ laBaseNode* bn=n->OutMin->Source->Parent; LA_VISIT_NODE(bn,vi); }
  605. if(LA_SRC_AND_PARENT(n->OutMax)){ laBaseNode* bn=n->OutMax->Source->Parent; LA_VISIT_NODE(bn,vi); }
  606. LA_ADD_THIS_NODE(n,vi);
  607. return LA_DAG_FLAG_PERM;
  608. }
  609. int IDN_MapperEval(laMapperNode* n){
  610. real in=0; real* InMin=0,*InMax=0,*OutMin=0,*OutMax=0;
  611. if(LA_SRC_AND_PARENT(n->In) && (n->In->Source->DataType&LA_PROP_FLOAT)){ in=*((real*)n->In->Source->Data); }
  612. if(LA_SRC_AND_PARENT(n->InMin) && (n->InMin->Source->DataType&LA_PROP_FLOAT)){ InMin=n->InMin->Source->Data; }
  613. if(LA_SRC_AND_PARENT(n->InMax) && (n->InMax->Source->DataType&LA_PROP_FLOAT)){ InMax=n->InMax->Source->Data; }
  614. if(LA_SRC_AND_PARENT(n->OutMin) && (n->OutMin->Source->DataType&LA_PROP_FLOAT)){ OutMin=n->OutMin->Source->Data; }
  615. if(LA_SRC_AND_PARENT(n->OutMax) && (n->OutMax->Source->DataType&LA_PROP_FLOAT)){ OutMax=n->OutMax->Source->Data; }
  616. real result=laValueMapperEvaluate(n->Mapper,in,InMin,InMax,OutMin,OutMax,n->ClampInput,n->ClampOutput);
  617. n->rOut=result;
  618. return 1;
  619. }
  620. void IDN_MapperCopy(laMapperNode* new, laMapperNode* old, int DoRematch){
  621. if(DoRematch){ LA_IDN_NEW_LINK(In) LA_IDN_NEW_LINK(InMax)
  622. LA_IDN_NEW_LINK(InMin) LA_IDN_NEW_LINK(OutMax) LA_IDN_NEW_LINK(OutMin) return;
  623. }
  624. old->Out->Duplicated=new->Out; new->ClampInput=old->ClampInput; new->ClampOutput=old->ClampOutput;
  625. laValueMapperCopy(new->Mapper,old->Mapper);
  626. }
  627. void laui_MapperNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){
  628. laColumn* c=laFirstColumn(uil); laMapperNode*n=This->EndInstance;
  629. laColumn* cl,*cr; laSplitColumn(uil,c,0.4); cl=laLeftColumn(c,3); cr=laRightColumn(c,0);
  630. laUiItem*b,*b2;
  631. LA_BASE_NODE_HEADER(uil,c,This);
  632. b=laBeginRow(uil,c,0,0);
  633. 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);
  634. laShowItem(uil,c,This,"mapper.in_range")->Expand=1; laShowNodeSocket(uil,c,This,"in_max",0);
  635. laEndRow(uil,b);
  636. laShowItem(uil,c,This,"mapper");
  637. b=laBeginRow(uil,c,0,0);
  638. laShowNodeSocket(uil,c,This,"out_min",0); laShowItem(uil,c,This,"mapper.out_range")->Expand=1;
  639. 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;
  640. laEndRow(uil,b);
  641. }
  642. void IDN_RandomInit(laRandomNode* n, int NoCreate){
  643. if(!NoCreate){
  644. strSafeSet(&n->Base.Name,"Random"); n->Out=laCreateOutSocket(n,"RAND",LA_PROP_FLOAT); n->Min=0; n->Max=1;
  645. }
  646. if(!n->InMin) n->InMin=laCreateInSocket("[IN",LA_PROP_FLOAT); if(!n->InMax) n->InMax=laCreateInSocket("IN]",LA_PROP_FLOAT);
  647. n->Out->Data=&n->rOut;
  648. }
  649. void IDN_RandomDestroy(laRandomNode* n){
  650. strSafeDestroy(&n->Base.Name); laDestroyOutSocket(n->Out); laDestroyInSocket(n->InMin); laDestroyInSocket(n->InMax);
  651. }
  652. int IDN_RandomVisit(laRandomNode* n, laNodeVisitInfo* vi){
  653. LA_GUARD_THIS_NODE(n,vi);
  654. if(LA_SRC_AND_PARENT(n->InMin)){ laBaseNode* bn=n->InMin->Source->Parent; LA_VISIT_NODE(bn,vi); }
  655. if(LA_SRC_AND_PARENT(n->InMax)){ laBaseNode* bn=n->InMax->Source->Parent; LA_VISIT_NODE(bn,vi); }
  656. LA_ADD_THIS_NODE(n,vi);
  657. return LA_DAG_FLAG_PERM;
  658. }
  659. int IDN_RandomEval(laRandomNode* n){
  660. real Min=n->Min,Max=n->Max;
  661. if(LA_SRC_AND_PARENT(n->InMin) && (n->InMin->Source->DataType&LA_PROP_FLOAT)){ Min=*((real*)n->InMin->Source->Data); }
  662. if(LA_SRC_AND_PARENT(n->InMax) && (n->InMax->Source->DataType&LA_PROP_FLOAT)){ Max=*((real*)n->InMax->Source->Data); }
  663. n->rOut=Min+(real)rand()/(real)(RAND_MAX/(Max-Min));
  664. return 1;
  665. }
  666. void IDN_RandomCopy(laRandomNode* new, laRandomNode* old, int DoRematch){
  667. if(DoRematch){ LA_IDN_NEW_LINK(InMax) LA_IDN_NEW_LINK(InMin) return; }
  668. old->Out->Duplicated=new->Out; new->Max=old->Max; new->Min=old->Min;
  669. }
  670. void laui_RandomNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){
  671. laColumn* c=laFirstColumn(uil); laRandomNode*n=This->EndInstance;
  672. laColumn* cl,*cr; laSplitColumn(uil,c,0.4); cl=laLeftColumn(c,3); cr=laRightColumn(c,0);
  673. laUiItem*b,*b2;
  674. LA_BASE_NODE_HEADER(uil,c,This);
  675. b=laBeginRow(uil,c,0,0);
  676. laShowNodeSocket(uil,c,This,"min",0); laShowItem(uil,c,This,"range")->Expand=1; laShowNodeSocket(uil,c,This,"max",0);
  677. laShowNodeSocket(uil,c,This,"out",0)->Flags|=LA_UI_SOCKET_LABEL_W;
  678. laEndRow(uil,b);
  679. }
  680. void IDN_VectorMathInit(laVectorMathNode* n, int NoCreate){
  681. if(!NoCreate){
  682. strSafeSet(&n->Base.Name,"Math");
  683. n->InL=laCreateInSocket("l",0); n->InR=laCreateInSocket("r",0);
  684. n->Out=laCreateOutSocket(n,"OUT",LA_PROP_FLOAT);
  685. }
  686. n->Out->Data=n->rOut;
  687. }
  688. void IDN_VectorMathDestroy(laVectorMathNode* n){
  689. strSafeDestroy(&n->Base.Name); laDestroyInSocket(n->InL); laDestroyInSocket(n->InR); laDestroyOutSocket(n->Out);
  690. }
  691. int IDN_VectorMathVisit(laVectorMathNode* n, laNodeVisitInfo* vi){
  692. LA_GUARD_THIS_NODE(n,vi);
  693. if(LA_SRC_AND_PARENT(n->InL)){ laBaseNode* bn=n->InL->Source->Parent; LA_VISIT_NODE(bn,vi); }
  694. if(LA_SRC_AND_PARENT(n->InR)){ laBaseNode* bn=n->InR->Source->Parent; LA_VISIT_NODE(bn,vi); }
  695. LA_ADD_THIS_NODE(n,vi);
  696. return LA_DAG_FLAG_PERM;
  697. }
  698. #define LA_GET_SRC_AS_FLOAT_THINGS(var, socket, maxlen) \
  699. {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]; } }\
  700. 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]; } }\
  701. }
  702. int IDN_VectorMathEval(laVectorMathNode* n){
  703. real vl[4]={0,0,0,1};real vr[4]={0,0,0,1}; int maxlen1=4,maxlen2=4,maxlen;
  704. int hasl=LA_SRC_AND_PARENT(n->InL),hasr=LA_SRC_AND_PARENT(n->InR);
  705. if(hasl){ LA_GET_SRC_AS_FLOAT_THINGS(vl,n->InL,maxlen1) } if(hasr){ LA_GET_SRC_AS_FLOAT_THINGS(vr,n->InR,maxlen2) }
  706. if(maxlen1>1 && maxlen2<maxlen1){ for(int i=maxlen2;i<maxlen1;i++){ vr[i]=vr[maxlen2-1]; } maxlen=maxlen1; }
  707. else{ maxlen=TNS_MIN2(maxlen1,maxlen2); }
  708. switch(n->Operation){
  709. 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;
  710. 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;
  711. 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;
  712. 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;
  713. 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;
  714. 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;
  715. case LA_VECTOR_MATH_OP_CROSS: if(maxlen<3) return 0; n->Out->ArrLen=3; tnsVectorCross3d(n->rOut,vl,vr); break;
  716. 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;
  717. case LA_VECTOR_MATH_OP_LEN: if(maxlen<2) return 0; n->Out->ArrLen=1;
  718. if(maxlen==2){ tnsVector2d d; tnsVectorMinus2d(d,vr,vl); n->rOut[0]=tnsLength2d(d); }
  719. else { tnsVector3d d; tnsVectorMinus2d(d,vr,vl); n->rOut[0]=tnsLength3d(d); } break;
  720. 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;
  721. }
  722. return 1;
  723. }
  724. void IDN_VectorMathCopy(laVectorMathNode* new, laVectorMathNode* old, int DoRematch){
  725. if(DoRematch){ LA_IDN_NEW_LINK(InL) LA_IDN_NEW_LINK(InR) return; }
  726. old->Out->Duplicated=new->Out; new->Operation=old->Operation;
  727. }
  728. void laui_VectorMathNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){
  729. laColumn* c=laFirstColumn(uil); laVectorMathNode*n=This->EndInstance;
  730. laColumn* cl,*cr; laSplitColumn(uil,c,0.4); cl=laLeftColumn(c,3); cr=laRightColumn(c,0);
  731. laUiItem*b,*b2;
  732. LA_BASE_NODE_HEADER(uil,c,This);
  733. b=laBeginRow(uil,c,0,0);
  734. laShowNodeSocket(uil,c,This,"in_l",0); laShowNodeSocket(uil,c,This,"in_r",0);
  735. laShowSeparator(uil,c)->Expand=1;
  736. laShowItem(uil,c,This,"operation");
  737. laShowNodeSocket(uil,c,This,"out",0)->Flags|=LA_UI_SOCKET_LABEL_W;
  738. laEndRow(uil,b);
  739. }
  740. void IDN_CommentInit(laCommentNode* n, int NoCreate){
  741. if(NoCreate){return;}
  742. strSafeSet(&n->Base.Name,"Math"); strSafeSet(&n->Content,"");
  743. }
  744. void IDN_CommentDestroy(laCommentNode* n){
  745. strSafeDestroy(&n->Base.Name); strSafeDestroy(&n->Content);
  746. }
  747. int IDN_CommentVisit(laCommentNode* n, laNodeVisitInfo* vi){
  748. //LA_GUARD_THIS_NODE(n,vi);
  749. //LA_ADD_THIS_NODE(n,vi);
  750. // No need to evaluate comments I guess?
  751. return LA_DAG_FLAG_PERM;
  752. }
  753. int IDN_CommentEval(laCommentNode* n){ return 1; }
  754. void IDN_CommentCopy(laCommentNode* new, laCommentNode* old, int DoRematch){
  755. if(DoRematch){ return; }
  756. strSafeSet(&new->Content,old->Content?old->Content->Ptr:0);
  757. }
  758. void laui_CommentNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){
  759. laColumn* c=laFirstColumn(uil); laCommentNode*n=This->EndInstance;
  760. LA_BASE_NODE_HEADER(uil,c,This);
  761. laColumn* cl,*cr; laSplitColumn(uil,c,0.7); cl=laLeftColumn(c,0);cr=laRightColumn(c,1);
  762. laUiItem* b=laOnConditionToggle(uil,cr,0,0,0,0,0);{
  763. laShowItemFull(uil,cl,This,"content",LA_WIDGET_STRING_MULTI,0,0,0)->Flags|=LA_UI_FLAGS_NO_SCROLL_INACTIVE;
  764. }laElse(uil,b);{
  765. laShowItemFull(uil,cl,This,"content",LA_WIDGET_STRING_PLAIN,0,0,0)->Flags|=LA_TEXT_LINE_WRAP;
  766. }laEndCondition(uil,b);}
  767. void IDN_RGB2OKHSLInit(laRGB2OKHSLNode* n, int NoCreate){
  768. if(!NoCreate){
  769. strSafeSet(&n->Base.Name,"RGB to OKHL"); n->In=laCreateInSocket("IN",LA_PROP_FLOAT);
  770. n->OutH=laCreateOutSocket(n,"H",LA_PROP_FLOAT);
  771. n->OutS=laCreateOutSocket(n,"S",LA_PROP_FLOAT);
  772. n->OutL=laCreateOutSocket(n,"L",LA_PROP_FLOAT);
  773. tnsVectorSet3(n->RGB,0.2,0.2,0.2);
  774. }
  775. n->OutH->Data=&n->rOut[0]; n->OutS->Data=&n->rOut[1]; n->OutL->Data=&n->rOut[2];
  776. }
  777. void IDN_RGB2OKHSLDestroy(laRGB2OKHSLNode* n){
  778. strSafeDestroy(&n->Base.Name);
  779. laDestroyInSocket(n->In); laDestroyOutSocket(n->OutH); laDestroyOutSocket(n->OutS); laDestroyOutSocket(n->OutL);
  780. }
  781. int IDN_RGB2OKHSLVisit(laRGB2OKHSLNode* n, laNodeVisitInfo* vi){
  782. LA_GUARD_THIS_NODE(n,vi);
  783. if(LA_SRC_AND_PARENT(n->In)){ laBaseNode* bn=n->In->Source->Parent; LA_VISIT_NODE(bn,vi); }
  784. LA_ADD_THIS_NODE(n,vi);
  785. return LA_DAG_FLAG_PERM;
  786. }
  787. int IDN_RGB2OKHSLEval(laRGB2OKHSLNode* n){
  788. real* in=n->RGB;
  789. 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; }
  790. tnsRGB2HCYLinear(in, n->rOut);
  791. return 1;
  792. }
  793. void IDN_RGB2OKHSLCopy(laRGB2OKHSLNode* new, laRGB2OKHSLNode* old, int DoRematch){
  794. if(DoRematch){ LA_IDN_NEW_LINK(In) return; }
  795. old->OutH->Duplicated=new->OutH;old->OutS->Duplicated=new->OutS;old->OutL->Duplicated=new->OutL;
  796. }
  797. void laui_RGB2OKHSLNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){
  798. laColumn* c=laFirstColumn(uil); laRGB2OKHSLNode*n=This->EndInstance;
  799. laUiItem*b,*b2;
  800. LA_BASE_NODE_HEADER(uil,c,This);
  801. b=laBeginRow(uil,c,0,0);
  802. laShowNodeSocket(uil,c,This,"in",0);
  803. b2=laOnConditionThat(uil,c,laNot(laPropExpression(This,"in.source")));{
  804. laShowItem(uil,c,This,"color");
  805. }laEndCondition(uil,b2);
  806. laShowSeparator(uil,c)->Expand=1;
  807. laShowLabel(uil,c,"OKHSL",0,0);
  808. laShowItem(uil,c,This,"out_h");
  809. laShowItem(uil,c,This,"out_s");
  810. laShowItem(uil,c,This,"out_l");
  811. laEndRow(uil,b);
  812. }
  813. void IDN_OKHSL2RGBInit(laOKHSL2RGBNode* n, int NoCreate){
  814. if(!NoCreate){
  815. strSafeSet(&n->Base.Name,"OKHL to RGB"); n->Out=laCreateOutSocket(n,"RGB",LA_PROP_FLOAT|LA_PROP_ARRAY);
  816. n->InH=laCreateInSocket("H",LA_PROP_FLOAT);
  817. n->InS=laCreateInSocket("S",LA_PROP_FLOAT);
  818. n->InL=laCreateInSocket("L",LA_PROP_FLOAT);
  819. }
  820. n->Out->ArrLen=3; n->Out->Data=n->rOut;
  821. }
  822. void IDN_OKHSL2RGBDestroy(laOKHSL2RGBNode* n){
  823. strSafeDestroy(&n->Base.Name);
  824. laDestroyInSocket(n->InH); laDestroyInSocket(n->InS); laDestroyInSocket(n->InL); laDestroyOutSocket(n->Out);
  825. }
  826. int IDN_OKHSL2RGBVisit(laOKHSL2RGBNode* n, laNodeVisitInfo* vi){
  827. LA_GUARD_THIS_NODE(n,vi);
  828. if(LA_SRC_AND_PARENT(n->InH)){ laBaseNode* bn=n->InH->Source->Parent; LA_VISIT_NODE(bn,vi); }
  829. if(LA_SRC_AND_PARENT(n->InS)){ laBaseNode* bn=n->InS->Source->Parent; LA_VISIT_NODE(bn,vi); }
  830. if(LA_SRC_AND_PARENT(n->InL)){ laBaseNode* bn=n->InL->Source->Parent; LA_VISIT_NODE(bn,vi); }
  831. LA_ADD_THIS_NODE(n,vi);
  832. return LA_DAG_FLAG_PERM;
  833. }
  834. int IDN_OKHSL2RGBEval(laOKHSL2RGBNode* n){
  835. real in[3]={0,0,0};
  836. if(LA_SRC_AND_PARENT(n->InH) && (n->InH->Source->DataType&LA_PROP_FLOAT)){ in[0]=*((real*)n->InH->Source->Data); }
  837. if(LA_SRC_AND_PARENT(n->InS) && (n->InS->Source->DataType&LA_PROP_FLOAT)){ in[1]=*((real*)n->InS->Source->Data); }
  838. if(LA_SRC_AND_PARENT(n->InL) && (n->InL->Source->DataType&LA_PROP_FLOAT)){ in[2]=*((real*)n->InL->Source->Data); }
  839. tnsHCY2RGBLinear(in, n->rOut);
  840. return 1;
  841. }
  842. void IDN_OKHSL2RGBCopy(laOKHSL2RGBNode* new, laOKHSL2RGBNode* old, int DoRematch){
  843. if(DoRematch){ LA_IDN_NEW_LINK(InH) LA_IDN_NEW_LINK(InS) LA_IDN_NEW_LINK(InL) return; }
  844. old->Out->Duplicated=new->Out;
  845. }
  846. void laui_OKHSL2RGBNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){
  847. laColumn* c=laFirstColumn(uil); laOKHSL2RGBNode*n=This->EndInstance;
  848. laUiItem*b,*b2;
  849. LA_BASE_NODE_HEADER(uil,c,This);
  850. b=laBeginRow(uil,c,0,0);
  851. laShowItem(uil,c,This,"in_h");
  852. laShowItem(uil,c,This,"in_s");
  853. laShowItem(uil,c,This,"in_l");
  854. laShowLabel(uil,c,"OKHSL",0,0);
  855. laShowSeparator(uil,c)->Expand=1; laShowNodeSocket(uil,c,This,"out",0)->Flags|=LA_UI_SOCKET_LABEL_W;
  856. laEndRow(uil,b);
  857. }
  858. void IDN_LoopInit(laLoopNode* n, int NoCreate){
  859. if(!NoCreate){
  860. strSafeSet(&n->Base.Name,"Loop");
  861. n->Branch=laCreateInSocket("CTRL",LA_PROP_FLOAT);
  862. n->InIndex=laCreateInSocket("IDX",LA_PROP_FLOAT);
  863. n->InIterations=laCreateInSocket("NUM",LA_PROP_FLOAT);
  864. n->Prev=laCreateInSocket("PREV",LA_PROP_FLOAT); n->Next=laCreateOutSocket(n,"NEXT",LA_PROP_INT);
  865. }
  866. n->Next->Data=&n->Iterations;
  867. }
  868. void IDN_LoopDestroy(laLoopNode* n){
  869. strSafeDestroy(&n->Base.Name);
  870. laDestroyInSocket(n->Prev); laDestroyInSocket(n->InIterations); laDestroyInSocket(n->InIndex);
  871. laDestroyInSocket(n->Branch); laDestroyOutSocket(n->Next);
  872. }
  873. int IDN_LoopVisit(laLoopNode* n, laNodeVisitInfo* vi){
  874. LA_GUARD_THIS_NODE(n,vi);if(!LA_SRC_AND_PARENT(n->Branch)){ return LA_DAG_FLAG_PERM; }
  875. if(LA_SRC_AND_PARENT(n->Prev)){ laBaseNode* bn=n->Prev->Source->Parent; LA_VISIT_NODE(bn,vi); }
  876. if(LA_SRC_AND_PARENT(n->InIterations)){ laBaseNode* bn=n->InIterations->Source->Parent; LA_VISIT_NODE(bn,vi); }
  877. if(LA_SRC_AND_PARENT(n->InIndex)){ laBaseNode* bn=n->InIndex->Source->Parent; LA_VISIT_NODE(bn,vi); }
  878. uint64_t OrigBranch=vi->Branch; int NextBranch=vi->NextBranch; n->Page=vi->Page;
  879. vi->NextBranch+=1; n->BranchControl=(1<<(NextBranch-1));
  880. if(OrigBranch==1){ lstAppendPointer(vi->br,n); }
  881. vi->Branch=OrigBranch|n->BranchControl;
  882. laBaseNode* sw=n->Branch->Source->Parent; LA_VISIT_NODE(sw,vi);
  883. vi->Branch=OrigBranch;
  884. LA_ADD_THIS_NODE(n,vi);
  885. return LA_DAG_FLAG_PERM;
  886. }
  887. int IDN_LoopEval(laLoopNode* n){
  888. laLoopIndexNode* lin=LA_SRC_AND_PARENT(n->InIndex)?n->InIndex->Source->Parent:0;
  889. if(lin->Base.Type!=&LA_IDN_LOOP_INDEX){lin=0;}
  890. int Iterations=n->Iterations;
  891. if(LA_SRC_AND_PARENT(n->InIterations)){ LA_GET_SRC_AS_VALUE(Iterations, n->InIterations); }
  892. for(int i=0; i<Iterations; i++){
  893. if(lin){ lin->Iteration=i; }
  894. la_PageClearBranch(n->Page,n->BranchControl);
  895. laRunPage(n->Page,n->BranchControl);
  896. }
  897. return 1;
  898. }
  899. void IDN_LoopCopy(laLoopNode* new, laLoopNode* old, int DoRematch){
  900. if(DoRematch){ LA_IDN_NEW_LINK(Branch) LA_IDN_NEW_LINK(InIndex) LA_IDN_NEW_LINK(InIterations) LA_IDN_NEW_LINK(Prev) return; }
  901. old->Next->Duplicated=new->Next;
  902. }
  903. void laui_LoopNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){
  904. laColumn* c=laFirstColumn(uil), *cl,*cr;
  905. laLoopNode*n=This->EndInstance;
  906. laUiItem*b,*b2;
  907. LA_BASE_NODE_HEADER(uil,c,This);
  908. laSplitColumn(uil,c,0.6); cl=laLeftColumn(c,0); cr=laRightColumn(c,5);
  909. b=laBeginRow(uil,cl,0,0);
  910. laShowItem(uil,cl,This,"branch")->Flags|=LA_UI_SOCKET_LABEL_E;
  911. laShowItem(uil,cl,This,"in_iterations")->Flags|=LA_UI_SOCKET_LABEL_E;
  912. laShowSeparator(uil,cl)->Expand=1;
  913. laEndRow(uil,b);
  914. b=laBeginRow(uil,cl,1,0);
  915. laShowItem(uil,cl,This,"index")->Flags|=LA_UI_SOCKET_LABEL_E;
  916. laShowItem(uil,cl,This,"iterations");
  917. laShowSeparator(uil,cl)->Expand=1;
  918. laEndRow(uil,b);
  919. b=laBeginRow(uil,cr,1,0);
  920. laShowItem(uil,cr,This,"prev")->Flags|=LA_UI_SOCKET_LABEL_S;
  921. laShowItem(uil,cr,This,"next")->Flags|=LA_UI_SOCKET_LABEL_N;
  922. laEndRow(uil,b);
  923. }
  924. void IDN_LoopIndexInit(laLoopIndexNode* n, int NoCreate){
  925. if(!NoCreate){
  926. strSafeSet(&n->Base.Name,"Loop Index");
  927. n->Out=laCreateOutSocket(n,"IDX",LA_PROP_INT);
  928. }
  929. n->Out->Data=&n->Iteration; n->Out->DataType=LA_PROP_INT;
  930. }
  931. void IDN_LoopIndexDestroy(laLoopIndexNode* n){
  932. strSafeDestroy(&n->Base.Name);
  933. laDestroyOutSocket(n->Out);
  934. }
  935. int IDN_LoopIndexVisit(laLoopIndexNode* n, laNodeVisitInfo* vi){
  936. LA_GUARD_THIS_NODE(n,vi);
  937. LA_ADD_THIS_NODE(n,vi);
  938. return LA_DAG_FLAG_PERM;
  939. }
  940. int IDN_LoopIndexEval(laLoopIndexNode* n){
  941. return 1;
  942. }
  943. void IDN_LoopIndexCopy(laLoopIndexNode* new, laLoopIndexNode* old, int DoRematch){
  944. if(DoRematch){ return; } old->Out->Duplicated=new->Out;
  945. }
  946. void laui_LoopIndexNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){
  947. laColumn* c=laFirstColumn(uil);
  948. laLoopIndexNode*n=This->EndInstance;
  949. laUiItem*b,*b2;
  950. LA_BASE_NODE_HEADER(uil,c,This);
  951. b=laBeginRow(uil,c,0,0);
  952. laShowSeparator(uil,c)->Expand=1;
  953. laShowItem(uil,c,This,"index")->Flags|=LA_UI_SOCKET_LABEL_W;
  954. laEndRow(uil,b);
  955. }
  956. int OPINV_AddNodesRack(laOperator* a, laEvent *e){
  957. laRackPage* dp=a->This?a->This->EndInstance:0; if(!dp) return LA_FINISHED;
  958. laNodeRack* ir=memAcquire(sizeof(laNodeRack));
  959. strSafeSet(&ir->Name,"New Rack");
  960. lstAppendItem(&dp->Racks, ir); ir->ParentPage=dp;
  961. ir->RackType=dp->RackType;
  962. laNotifyInstanceUsers(dp); laRecordInstanceDifferences(dp,"la_rack_page"); laPushDifferences("Add Rack", 0);
  963. return LA_FINISHED;
  964. }
  965. laBaseNode* la_CreateNode(laNodeRack* ir, laBaseNodeType* NodeType){
  966. laBaseNode* bn=memAcquire(NodeType->NodeSize);
  967. bn->Type=NodeType; NodeType->Init(bn, 0); bn->InitDone=1; lstAppendItem(&ir->Nodes, bn); bn->InRack=ir;
  968. laNotifyInstanceUsers(ir); laRecordInstanceDifferences(ir,"la_node_rack"); laPushDifferences("Add Node", 0);
  969. return bn;
  970. }
  971. int OPINV_AddNode(laOperator* a, laEvent *e){
  972. laNodeRack* ir=a->This?a->This->EndInstance:0; if(!ir) return LA_CANCELED;
  973. laBaseNodeType* bnt=0;
  974. if(!MAIN.CurrentNodeCategory) MAIN.CurrentNodeCategory=MAIN.NodeCategories.pFirst;
  975. char* target=strGetArgumentString(a->ExtraInstructionsP,"target");
  976. int ti=0; if(target) sscanf(target,"%d",&ti);
  977. if((!target) || ti==0){ MAIN.FilterNodeCategory=LA_RACK_TYPE_INPUT; }
  978. else{ MAIN.FilterNodeCategory=ti; }
  979. char* type=strGetArgumentString(a->ExtraInstructionsP,"type");
  980. 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; }
  981. else{
  982. for(int i=0;i<MAIN.NodeTypeNext;i++){
  983. if(strSame(MAIN.NodeTypes[i]->TypeName,type)){ la_CreateNode(ir, MAIN.NodeTypes[i]); }
  984. }
  985. }
  986. return LA_FINISHED;
  987. }
  988. int OPMOD_AddNode(laOperator* a, laEvent *e){
  989. laNodeRack* r=a->This->EndInstance;
  990. if(a->ConfirmData){
  991. if(a->ConfirmData->StrData){
  992. for(int i=0;i<MAIN.NodeTypeNext;i++){
  993. if(strSame(MAIN.NodeTypes[i]->TypeName,a->ConfirmData->StrData)){ la_CreateNode(r, MAIN.NodeTypes[i]); break; }
  994. }
  995. }
  996. return LA_FINISHED;
  997. }
  998. return LA_RUNNING;
  999. }
  1000. void laui_AddNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){
  1001. laColumn* c=laFirstColumn(uil),*cl,*cr; laSplitColumn(uil,c,0.4); cl=laLeftColumn(c,4); cr=laRightColumn(c,0);
  1002. laShowItemFull(uil,cl,0,"la.node_categories",LA_WIDGET_COLLECTION,"feedback=NONE;",0,0);
  1003. 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;
  1004. laShowItemFull(gu,gc,0,"la.node_categories",LA_WIDGET_COLLECTION_SINGLE,0,laui_NodeCategory,0)->Flags|=LA_UI_FLAGS_NO_DECAL;
  1005. }
  1006. laNodeRack* la_NewRackAfter(laRackPage* parent,laNodeRack* rr){
  1007. laNodeRack* r=memAcquire(sizeof(laNodeRack));
  1008. strSafeSet(&r->Name,"New Rack");
  1009. if(rr) lstInsertItemAfter(&parent->Racks,r,rr); else lstPushItem(&parent->Racks, r);
  1010. r->ParentPage=parent; r->RackType=parent->RackType;
  1011. }
  1012. int OPINV_MoveNodeToRack(laOperator* a, laEvent *e){
  1013. laBaseNode* n=a->This?a->This->EndInstance:0; if(!n||!n->InRack) return LA_CANCELED;
  1014. laBaseNodeType* bnt=0; laNodeRack* target;
  1015. char* direction=strGetArgumentString(a->ExtraInstructionsP,"direction");
  1016. if(strSame(direction,"left")){ target=n->InRack->Item.pPrev; if(!target){ target=la_NewRackAfter(n->InRack->ParentPage,0); } }
  1017. else{ target=n->InRack->Item.pNext; if(!target){ target=la_NewRackAfter(n->InRack->ParentPage,n->InRack->ParentPage->Racks.pLast); } }
  1018. if(!target) return LA_CANCELED;
  1019. lstRemoveItem(&n->InRack->Nodes, n); lstAppendItem(&target->Nodes,n); n->InRack=target;
  1020. laNotifyInstanceUsers(n->InRack->ParentPage); laRecordInstanceDifferences(n->InRack->ParentPage,"la_node_page"); laPushDifferences("Move Node", 0);
  1021. return LA_FINISHED;
  1022. }
  1023. int OPINV_DeleteNode(laOperator* a, laEvent *e){
  1024. laBaseNode* n=a->This?a->This->EndInstance:0; if(!n||!n->InRack) return LA_CANCELED;
  1025. laBaseNodeType* bnt=0; laNodeRack* target;
  1026. laNodeRack* parent=n->InRack;
  1027. lstRemoveItem(&n->InRack->Nodes, n); n->Type->Destroy(n); memLeave(n);
  1028. laGraphRequestRebuild();
  1029. laNotifyInstanceUsers(parent); laRecordInstanceDifferences(parent,"la_node_rack"); laPushDifferences("Delete Node", 0);
  1030. return LA_FINISHED;
  1031. }
  1032. int OPINV_MoveRack(laOperator* a, laEvent *e){
  1033. laNodeRack* r=a->This?a->This->EndInstance:0; if(!r) return LA_CANCELED;
  1034. char* direction=strGetArgumentString(a->ExtraInstructionsP,"direction");
  1035. if(strSame(direction,"left")) lstMoveUp(&r->ParentPage->Racks,r); else lstMoveDown(&r->ParentPage->Racks,r);
  1036. laNotifyInstanceUsers(r->ParentPage); laRecordInstanceDifferences(r->ParentPage,"la_rack_page"); laPushDifferences("Move Rack", 0);
  1037. return LA_FINISHED;
  1038. }
  1039. int OPINV_InsertRack(laOperator* a, laEvent *e){
  1040. laNodeRack* rr=a->This?a->This->EndInstance:0; if(!rr) return LA_CANCELED;
  1041. laNodeRack* r = la_NewRackAfter(rr->ParentPage,rr);
  1042. laNotifyInstanceUsers(r->ParentPage); laRecordInstanceDifferences(r->ParentPage,"la_rack_page"); laPushDifferences("Insert Rack", 0);
  1043. return LA_FINISHED;
  1044. }
  1045. int OPINV_DeleteRack(laOperator* a, laEvent *e){
  1046. laNodeRack* rr=a->This?a->This->EndInstance:0; if(!rr) return LA_CANCELED;
  1047. if(strSame(strGetArgumentString(a->ExtraInstructionsP,"confirm"),"true")){
  1048. laRackPage* page=rr->ParentPage; laDestroyRack(rr);
  1049. laNotifyInstanceUsers(page); laRecordInstanceDifferences(page,"la_rack_page"); laPushDifferences("Delete Rack", 0);
  1050. return LA_FINISHED;
  1051. }
  1052. laEnableOperatorPanel(a,a->This,e->x,e->y,200,200,0,0,0,0,0,0,0,0,e);
  1053. return LA_RUNNING;
  1054. }
  1055. void laui_DeleteRack(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){
  1056. laColumn* c=laFirstColumn(uil);
  1057. laShowItemFull(uil,c,This,"delete",0,"confirm=true;",0,0);
  1058. }
  1059. laPropContainer* laget_BaseNodeType(laBaseNode* bn){
  1060. for(int i=0;i<MAIN.NodeTypeNext;i++){ if(bn->Type==MAIN.NodeTypes[i]) return MAIN.NodeTypes[i]->pc; }
  1061. return LA_PC_IDN_GENERIC;
  1062. }
  1063. int laget_BaseNodeGap(laNodeRack* rack_unused, laBaseNode* n){
  1064. return n->Gap;
  1065. }
  1066. void laread_BaseNodeGap(laBaseNode* n, int gap){
  1067. n->Gap=gap;
  1068. }
  1069. void laset_BaseNodeGap(laBaseNode* n, int gap){
  1070. laBaseNode* nn;
  1071. if(gap==-1){
  1072. int done=0; nn=n; while(nn){ if(nn->Gap>0){ nn->Gap--; done=1; break; } nn=nn->Item.pPrev; }
  1073. if(done){ nn=n->Item.pNext; while(nn){ if(nn->Gap>0){ nn->Gap++; break; } nn=nn->Item.pNext; } }
  1074. }elif(gap==1){
  1075. n->Gap+=gap; nn=n->Item.pNext; while(nn){ if(nn->Gap>0){ nn->Gap--; break; } nn=nn->Item.pNext; }
  1076. }elif(gap==-2){
  1077. if(n->Gap){ n->Gap--; if(nn=n->Item.pNext){ nn->Gap++; } }
  1078. elif(nn=n->Item.pPrev){ n->Gap=nn->Gap; nn->Gap=0; lstRemoveItem(&n->InRack->Nodes,n); lstInsertItemBefore(&n->InRack->Nodes,n,nn); }
  1079. }elif(gap==2){
  1080. 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++; } }
  1081. else n->Gap++;
  1082. }
  1083. }
  1084. void laset_InputNodeUserID(laInputControllerNode* n, int i){
  1085. laNotifyUsers("la.input_racks");
  1086. }
  1087. void laset_InputControllerNodeSocketWhich(laInputControllerNodeSocket* s, char* str){
  1088. strSafeSet(&s->Which, str);
  1089. laNotifyUsers("la.input_racks"); laGraphRequestRebuild();
  1090. }
  1091. int laget_SocketEnumArrayLength(laInputControllerNodeSocket* s){
  1092. return s->Out->ArrLen?s->Out->ArrLen:1;
  1093. }
  1094. int laget_VisualizerArrayLength(laInputVisualizerNode* s){
  1095. return s->In->ArrLen?s->In->ArrLen:1;
  1096. }
  1097. laBoxedTheme* laget_NodeGetTheme(laNodeRack* rack_unused, laBaseNode* n){
  1098. return 0;
  1099. }
  1100. void laRegisterNode(laBaseNodeType* type, laPropContainer* pc,
  1101. laBaseNodeInitF init, laBaseNodeDestroyF destroy, laBaseNodeVisitF visit, laBaseNodeEvalF eval, laBaseNodeCopyF copy,
  1102. int nodesize, char* udf_string, char* type_string, char* UiText, int icon){
  1103. arrEnsureLength(&MAIN.NodeTypes, MAIN.NodeTypeNext, &MAIN.NodeTypeMax, sizeof(laBaseNode*));
  1104. type->Init = init; type->Destroy = destroy; type->Visit=visit; type->Eval=eval; type->NodeSize=nodesize; type->Copy=copy;
  1105. type->pc=pc; type->TypeName=type_string;type->Name=UiText;type->Icon=icon;
  1106. MAIN.NodeTypes[MAIN.NodeTypeNext]=type; MAIN.NodeTypeNext++;
  1107. la_UDFAppendSharedTypePointer(udf_string, type);
  1108. }
  1109. void lapost_Node(laBaseNode *bn){
  1110. if(!bn->InitDone){
  1111. bn->Type->Init(bn,1);
  1112. bn->InitDone=1;
  1113. }
  1114. }
  1115. extern laRackPage* DEBUG_READ_RACK_PAGE;
  1116. void lapost_NodeRack(laNodeRack *rr){
  1117. if(!rr->ParentPage){
  1118. memAssignRef(rr,&rr->ParentPage,DEBUG_READ_RACK_PAGE);
  1119. }
  1120. }
  1121. void la_AddValuesNodeEnum(laProp* p){
  1122. laAddEnumItemAs(p,"FLOAT","Float","Float value",LA_VALUES_NODE_FLOAT,0);
  1123. laAddEnumItemAs(p,"INT","Int","Int value",LA_VALUES_NODE_INT,0);
  1124. laAddEnumItemAs(p,"ENUM","Switch","Swich value",LA_VALUES_NODE_ENUM,0);
  1125. }
  1126. void la_AddValuesNodeEnumValue(laProp* p){
  1127. laAddEnumItemAs(p,"IDLE","Idle","Idle",0,0);
  1128. laAddEnumItemAs(p,"ACTIVE","Active","Active",1,0);
  1129. }
  1130. void la_RegisterBasicNodes(){
  1131. laPropContainer *pc; laProp *p;
  1132. laOperatorType *at;
  1133. laEnumProp *ep;
  1134. LA_NODE_CATEGORY_INPUT=laEnsureNodeCategory("Input",0,LA_RACK_TYPE_INPUT|LA_RACK_TYPE_DRIVER);
  1135. LA_NODE_CATEGORY_MATH=laEnsureNodeCategory("Math",0,LA_RACK_TYPE_ALL);
  1136. LA_NODE_CATEGORY_COLOR=laEnsureNodeCategory("Color",0,LA_RACK_TYPE_ALL);
  1137. LA_NODE_CATEGORY_ROUTE=laEnsureNodeCategory("Route",0,LA_RACK_TYPE_ALL);
  1138. LA_NODE_CATEGORY_AUX=laEnsureNodeCategory("Auxiliary",0,LA_RACK_TYPE_ALL);
  1139. LA_NODE_CATEGORY_DRIVER=laEnsureNodeCategory("Driver",0,LA_RACK_TYPE_DRIVER);
  1140. laCreateOperatorType("LA_add_rack", "Add Rack", "Add a rack for nodes", 0,0,0,OPINV_AddNodesRack,0,'+',0);
  1141. at=laCreateOperatorType("OPINV_AddNode", "Add Node", "Add a node to the rack",0,0,0,OPINV_AddNode,OPMOD_AddNode,'+',0);
  1142. at->UiDefine=laui_AddNode;
  1143. laCreateOperatorType("LA_move_node_to_rack", "Move Node", "Move node to another rack",0,0,0,OPINV_MoveNodeToRack,0,0,0);
  1144. laCreateOperatorType("LA_delete_node", "Delete Node", "Delete this node",0,0,0,OPINV_DeleteNode,0,0,0);
  1145. laCreateOperatorType("LA_move_rack", "Move Rack", "Move this rack",0,0,0,OPINV_MoveRack,0,0,0);
  1146. laCreateOperatorType("LA_insert_rack", "Insert Rack", "Insert a new rack",0,0,0,OPINV_InsertRack,0,0,0);
  1147. at=laCreateOperatorType("LA_delete_rack", "Delete Rack", "Delete a rack",0,0,0,OPINV_DeleteRack,OPMOD_FinishOnData,U'🞫',0);
  1148. at->UiDefine=laui_DeleteRack;
  1149. pc=laAddPropertyContainer("la_node_rack", "Input Rack", "Input rack for putting input mapping nodes",0,0,sizeof(laNodeRack),lapost_NodeRack,0,1);
  1150. laAddStringProperty(pc,"name","Name","Name of this rack",0,0,0,0,1,offsetof(laNodeRack,Name),0,0,0,0,LA_AS_IDENTIFIER);
  1151. 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);
  1152. laSubGroupExtraFunctions(p,0,0,laget_NodeGetTheme,laget_BaseNodeGap,0);
  1153. 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);
  1154. 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);
  1155. laAddOperatorProperty(pc,"add_node","Add Node","Add a node into this rack","OPINV_AddNode",'+',0);
  1156. laAddOperatorProperty(pc,"insert_rack","Insert Rack","Insert a rack","LA_insert_rack",'+',0);
  1157. laAddOperatorProperty(pc,"move","Move Rack","Move this rack","LA_move_rack",0,0);
  1158. laAddOperatorProperty(pc,"delete","Delete Rack","Delete this rack","LA_delete_rack",0,0);
  1159. pc=laAddPropertyContainer("la_base_node", "Input Node", "Input logic node",0,0,sizeof(laBaseNode),0,0,1);
  1160. LA_PC_IDN_GENERIC=pc;
  1161. laAddStringProperty(pc,"name","Name","Name of this input node",0,0,0,0,1,offsetof(laBaseNode,Name),0,0,0,0,LA_AS_IDENTIFIER);
  1162. 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);
  1163. 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);
  1164. laAddOperatorProperty(pc,"move","Move","Move node across racks","LA_move_node_to_rack",0,0);
  1165. laAddOperatorProperty(pc,"delete","Delete","Delete node","LA_delete_node",0,0);
  1166. 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);
  1167. pc=laAddPropertyContainer("la_keyboard_node", "Keyboard Node", "Output keyboard events",0,laui_KeyboardNode,sizeof(laKeyboardNode),lapost_Node,0,1);
  1168. LA_PC_IDN_KEYBOARD=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,"is_key","Is Key","Is keyboard event","la_out_socket",0,0,0,offsetof(laKeyboardNode, IsKey),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  1171. laAddSubGroup(pc,"key","Key","Key value","la_out_socket",0,0,0,offsetof(laKeyboardNode, Key),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  1172. laAddSubGroup(pc,"key_down","Key Down","Key is down or not","la_out_socket",0,0,0,offsetof(laKeyboardNode, KeyDown),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  1173. pc=laAddPropertyContainer("la_input_controller_node", "Controller output", "Output controller values",0,laui_ControllerNode,sizeof(laInputControllerNode),lapost_Node,0,1);
  1174. LA_PC_IDN_CONTROLLER=pc; laPropContainerExtraFunctions(pc,0,0,0,0,laui_DefaultNodeOperationsPropUiDefine);
  1175. laAddSubGroup(pc,"base","Base","Base node","la_base_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
  1176. 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);
  1177. 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);
  1178. 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);
  1179. 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);
  1180. 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);
  1181. 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);
  1182. 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);
  1183. 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);
  1184. 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);
  1185. 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);
  1186. 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);
  1187. laAddFloatProperty(pc,"axis", "🡘", "Axis value", LA_WIDGET_METER_TYPE1,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);
  1188. laAddFloatProperty(pc,"axis2d", "2D Axis", "2D Axis value", LA_WIDGET_METER_TYPE1,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);
  1189. 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);
  1190. laAddEnumItemAs(p,"IDLE", "Idle", "Button is not pressed", 0, 0);
  1191. laAddEnumItemAs(p,"ACTIVE", "Active", "Button is pressed", 1, 0);
  1192. 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);
  1193. pc=laAddPropertyContainer("la_input_visualizer_node", "Visualizer", "Visualizer node",0,laui_InputVisualizeNode,sizeof(laInputVisualizerNode),lapost_Node,0,1);
  1194. LA_PC_IDN_VISUALIZER=pc; laPropContainerExtraFunctions(pc,0,0,0,0,laui_DefaultNodeOperationsPropUiDefine);
  1195. laAddSubGroup(pc,"base","Base","Base node","la_base_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
  1196. 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);
  1197. laAddFloatProperty(pc,"axis", "🡘", "Axis value", LA_WIDGET_METER_TYPE1,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);
  1198. 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);
  1199. 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);
  1200. laAddEnumItemAs(p,"IDLE", "Idle", "Button is not pressed", 0, 0);
  1201. laAddEnumItemAs(p,"ACTIVE", "Active", "Button is pressed", 1, 0);
  1202. pc=laAddPropertyContainer("la_split_node", "Split", "Split node",0,laui_SplitNode,sizeof(laSplitNode),0,0,1);
  1203. LA_PC_IDN_SPLIT=pc; laPropContainerExtraFunctions(pc,0,0,0,0,laui_DefaultNodeOperationsPropUiDefine);
  1204. laAddSubGroup(pc,"base","Base","Base node","la_base_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
  1205. 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);
  1206. 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);
  1207. 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);
  1208. 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);
  1209. 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);
  1210. 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);
  1211. 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);
  1212. 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);
  1213. 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);
  1214. 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);
  1215. 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);
  1216. 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);
  1217. pc=laAddPropertyContainer("la_switch_node", "Switch", "Switch node",0,laui_SwitchNode,sizeof(laSwitchNode),0,0,1);
  1218. LA_PC_IDN_SWITCH=pc; laPropContainerExtraFunctions(pc,0,0,0,0,laui_DefaultNodeOperationsPropUiDefine);
  1219. laAddSubGroup(pc,"base","Base","Base node","la_base_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
  1220. 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);
  1221. 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);
  1222. 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);
  1223. 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);
  1224. 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);
  1225. 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);
  1226. 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);
  1227. 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);
  1228. 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);
  1229. 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);
  1230. 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);
  1231. pc=laAddPropertyContainer("la_switch_node_in_socket", "Switch In", "Input of many values",0,0,sizeof(laSwitchNodeInSocket),0,0,1|LA_PROP_OTHER_ALLOC);
  1232. 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);
  1233. pc=laAddPropertyContainer("la_combine_node", "Combine", "Combine node",0,laui_CombineNode,sizeof(laCombineNode),0,0,1);
  1234. LA_PC_IDN_COMBINE=pc; laPropContainerExtraFunctions(pc,0,0,0,0,laui_DefaultNodeOperationsPropUiDefine);
  1235. laAddSubGroup(pc,"base","Base","Base node","la_base_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
  1236. 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);
  1237. 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);
  1238. 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);
  1239. 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);
  1240. 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);
  1241. 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);
  1242. 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);
  1243. 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);
  1244. 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);
  1245. 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);
  1246. 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);
  1247. pc=laAddPropertyContainer("la_values_node", "Values", "Values node",0,laui_ValuesNode,sizeof(laValuesNode),lapost_Node,0,1);
  1248. LA_PC_IDN_VALUES=pc; laPropContainerExtraFunctions(pc,0,0,0,0,laui_DefaultNodeOperationsPropUiDefine);
  1249. laAddSubGroup(pc,"base","Base","Base node","la_base_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
  1250. 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);
  1251. 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);
  1252. 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);
  1253. 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);
  1254. 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);
  1255. 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);
  1256. 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);
  1257. 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);
  1258. 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);
  1259. 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);
  1260. 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);
  1261. 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);
  1262. 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);
  1263. 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);
  1264. 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);
  1265. 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);
  1266. 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);
  1267. 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);
  1268. 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);
  1269. 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);
  1270. 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);
  1271. 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);
  1272. 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);
  1273. 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);
  1274. 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);
  1275. 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);
  1276. 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);
  1277. 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);
  1278. 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);
  1279. 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);
  1280. 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);
  1281. 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);
  1282. 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);
  1283. 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);
  1284. 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);
  1285. 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);
  1286. 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);
  1287. 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);
  1288. 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);
  1289. 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);
  1290. pc=laAddPropertyContainer("la_matrix_node", "Matrix", "Matrix node",0,laui_MatrixNode,sizeof(laMatrixNode),lapost_Node,0,1);
  1291. LA_PC_IDN_MATRIX=pc; laPropContainerExtraFunctions(pc,0,0,0,0,laui_DefaultNodeOperationsPropUiDefine);
  1292. laAddSubGroup(pc,"base","Base","Base node","la_base_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
  1293. 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);
  1294. 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);
  1295. 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);
  1296. p=laAddEnumProperty(pc,"operation", "Operation", "Operation", 0,0,0,0,0,offsetof(laMatrixNode,Operation),0,0,0,0,0,0,0,0,0,0);
  1297. laAddEnumItemAs(p,"MUL", "Multiply", "L x R", LA_MATRIX_NODE_OP_MUL, 0);
  1298. laAddEnumItemAs(p,"INV", "Invert", "Invert L or R", LA_MATRIX_NODE_OP_INV, 0);
  1299. #define REGISTER_MATH_NODE \
  1300. laPropContainerExtraFunctions(pc,0,0,0,0,laui_DefaultNodeOperationsPropUiDefine); \
  1301. laAddSubGroup(pc,"base","Base","Base node","la_base_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);\
  1302. 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);\
  1303. 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);\
  1304. 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);\
  1305. 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);\
  1306. 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);\
  1307. 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);\
  1308. p=laAddEnumProperty(pc,"operation", "Operation", "Operation", 0,0,0,0,0,offsetof(laMathNode, Operation),0,0,0,0,0,0,0,0,0,0);\
  1309. laAddEnumItemAs(p,"ADD", "Add", "L + R", LA_MATH_NODE_OP_ADD, 0);\
  1310. laAddEnumItemAs(p,"SUB", "Subtract", "L - R", LA_MATH_NODE_OP_SUB, 0);\
  1311. laAddEnumItemAs(p,"MUL", "Multiply", "L x R", LA_MATH_NODE_OP_MUL, 0);\
  1312. laAddEnumItemAs(p,"DIV", "Divide", "L / R", LA_MATH_NODE_OP_DIV, 0);\
  1313. laAddEnumItemAs(p,"POW", "Power", "pow(L,R)", LA_MATH_NODE_OP_POW, 0);\
  1314. laAddEnumItemAs(p,"LOG", "Log", "log(L)base(R)", LA_MATH_NODE_OP_LOG, 0);\
  1315. laAddEnumItemAs(p,"SIN", "Sine", "sin(L)", LA_MATH_NODE_OP_SIN, 0);\
  1316. laAddEnumItemAs(p,"COS", "Cosine", "cos(L)", LA_MATH_NODE_OP_COS, 0);\
  1317. laAddEnumItemAs(p,"TAN", "Tangent", "tan(L)", LA_MATH_NODE_OP_TAN, 0);\
  1318. laAddEnumItemAs(p,"ASIN", "Arcsin", "asin(L)", LA_MATH_NODE_OP_ASIN, 0);\
  1319. laAddEnumItemAs(p,"ACOS", "Arccosine", "acos(L)", LA_MATH_NODE_OP_ACOS, 0);\
  1320. laAddEnumItemAs(p,"ATAN", "Arctangent", "atan(L)", LA_MATH_NODE_OP_ATAN, 0);\
  1321. laAddEnumItemAs(p,"ATAN2", "Atan2", "atan2(L,R) where L or R can be zero", LA_MATH_NODE_OP_ATAN2, 0);\
  1322. laAddEnumItemAs(p,"MOD", "Mod", "L \% R", LA_MATH_NODE_OP_MOD, 0);
  1323. 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
  1324. 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
  1325. pc=laAddPropertyContainer("la_mapper_node", "Mapper", "Mapper node",0,laui_MapperNode,sizeof(laMapperNode),lapost_Node,0,1);
  1326. LA_PC_IDN_MAPPER=pc; laPropContainerExtraFunctions(pc,0,0,0,0,laui_DefaultNodeOperationsPropUiDefine);
  1327. laAddSubGroup(pc,"base","Base","Base node","la_base_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
  1328. 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);
  1329. 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);
  1330. 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);
  1331. 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);
  1332. 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);
  1333. 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);
  1334. 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);
  1335. 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);
  1336. laAddEnumItemAs(p,"NONE", "None", "Don't clamp", 0, 0); laAddEnumItemAs(p,"CLAMP", "Clamp", "Clamp to specified range", 1, 0);
  1337. 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);
  1338. laAddEnumItemAs(p,"NONE", "None", "Don't clamp", 0, 0); laAddEnumItemAs(p,"CLAMP", "Clamp", "Clamp to specified range", 1, 0);
  1339. pc=laAddPropertyContainer("la_random_node", "Random", "Random node",0,laui_RandomNode,sizeof(laRandomNode),lapost_Node,0,1);
  1340. LA_PC_IDN_RANDOM=pc; laPropContainerExtraFunctions(pc,0,0,0,0,laui_DefaultNodeOperationsPropUiDefine);
  1341. laAddSubGroup(pc,"base","Base","Base node","la_base_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
  1342. 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);
  1343. 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);
  1344. 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);
  1345. 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);
  1346. pc=laAddPropertyContainer("la_vector_math_node", "Vector Math", "Math node",0,laui_VectorMathNode,sizeof(laVectorMathNode),lapost_Node,0,1);
  1347. LA_PC_IDN_VECTOR_MATH=pc; laPropContainerExtraFunctions(pc,0,0,0,0,laui_DefaultNodeOperationsPropUiDefine);
  1348. laAddSubGroup(pc,"base","Base","Base node","la_base_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
  1349. 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);
  1350. 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);
  1351. 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);
  1352. p=laAddEnumProperty(pc,"operation", "Operation", "Operation", 0,0,0,0,0,offsetof(laVectorMathNode, Operation),0,0,0,0,0,0,0,0,0,0);
  1353. laAddEnumItemAs(p,"ADD", "Add", "L + R", LA_VECTOR_MATH_OP_ADD, 0);
  1354. laAddEnumItemAs(p,"SUB", "Subtract", "L - R", LA_VECTOR_MATH_OP_SUB, 0);
  1355. laAddEnumItemAs(p,"MUL", "Multiply (component)", "L x R (component)", LA_VECTOR_MATH_OP_MUL, 0);
  1356. laAddEnumItemAs(p,"DIV", "Divide (component)", "L / R (component)", LA_VECTOR_MATH_OP_DIV, 0);
  1357. laAddEnumItemAs(p,"CROSS", "Cross", "L x R", LA_VECTOR_MATH_OP_CROSS, 0);
  1358. laAddEnumItemAs(p,"DOT", "Dot", "L . R", LA_VECTOR_MATH_OP_DOT, 0);
  1359. laAddEnumItemAs(p,"POW", "Power", "pow(L,R)", LA_VECTOR_MATH_OP_POW, 0);
  1360. laAddEnumItemAs(p,"LOG", "Log", "log(L)base(R)", LA_VECTOR_MATH_OP_LOG, 0);
  1361. laAddEnumItemAs(p,"LEN", "Length", "Length(L)", LA_VECTOR_MATH_OP_LEN, 0);
  1362. laAddEnumItemAs(p,"NORM", "Normalize", "Normalize(L)", LA_VECTOR_MATH_OP_NORMALIZE, 0);
  1363. pc=laAddPropertyContainer("la_comment_node", "Comment", "Comment",0,laui_CommentNode,sizeof(laCommentNode),lapost_Node,0,1);
  1364. LA_PC_IDN_COMMENT=pc; laPropContainerExtraFunctions(pc,0,0,0,0,laui_DefaultNodeOperationsPropUiDefine);
  1365. laAddSubGroup(pc,"base","Base","Base node","la_base_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
  1366. laAddStringProperty(pc,"content","Content","Content of the comment",LA_WIDGET_STRING_MULTI,0,0,0,1,offsetof(laCommentNode,Content),0,0,0,0,0);
  1367. pc=laAddPropertyContainer("la_rgb_to_okhsl_node", "RGB 2 OKHSL", "RGB color to OKHSL values",0,laui_RGB2OKHSLNode,sizeof(laRGB2OKHSLNode),lapost_Node,0,1);
  1368. LA_PC_IDN_RGB2OKHSL=pc; laPropContainerExtraFunctions(pc,0,0,0,0,laui_DefaultNodeOperationsPropUiDefine);
  1369. laAddSubGroup(pc,"base","Base","Base node","la_base_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
  1370. 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);
  1371. 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);
  1372. 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);
  1373. 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);
  1374. 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);
  1375. pc=laAddPropertyContainer("la_okhsl_to_rgb_node", "OKHSL 2 RGB", "OKHSL values to RGB color",0,laui_OKHSL2RGBNode,sizeof(laOKHSL2RGBNode),lapost_Node,0,1);
  1376. LA_PC_IDN_OKHSL2RGB=pc; laPropContainerExtraFunctions(pc,0,0,0,0,laui_DefaultNodeOperationsPropUiDefine);
  1377. laAddSubGroup(pc,"base","Base","Base node","la_base_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
  1378. 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);
  1379. 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);
  1380. 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);
  1381. 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);
  1382. pc=laAddPropertyContainer("la_loop_node", "Loop", "Repeat a series of operations for a few times",0,laui_LoopNode,sizeof(laLoopNode),lapost_Node,0,1);
  1383. LA_PC_IDN_LOOP=pc; laPropContainerExtraFunctions(pc,0,0,0,0,laui_DefaultNodeOperationsPropUiDefine);
  1384. laAddSubGroup(pc,"base","Base","Base node","la_base_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
  1385. laAddIntProperty(pc, "iterations", "Iterations", "Loop iterations", 0,0,0,0,0,0,0,0,offsetof(laLoopNode, Iterations),0,0,0,0,0,0,0,0,0,0,0);
  1386. laAddSubGroup(pc,"in_iterations", "In Iterations","Hue","la_in_socket",0,0,0,offsetof(laLoopNode, InIterations),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  1387. laAddSubGroup(pc,"branch", "Branch","Control branch","la_in_socket",0,0,0,offsetof(laLoopNode, Branch),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  1388. laAddSubGroup(pc,"index", "Index","Index node","la_in_socket",0,0,0,offsetof(laLoopNode, InIndex),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  1389. laAddSubGroup(pc,"prev", "Next","Next node in sequence","la_in_socket",0,0,0,offsetof(laLoopNode, Prev),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  1390. laAddSubGroup(pc,"next", "Next","Next node in sequence","la_out_socket",0,0,0,offsetof(laLoopNode, Next),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  1391. pc=laAddPropertyContainer("la_loop_index_node", "Loop Index", "Index reference of the loop node",0,laui_LoopIndexNode,sizeof(laLoopIndexNode),lapost_Node,0,1);
  1392. LA_PC_IDN_LOOP_INDEX=pc; laPropContainerExtraFunctions(pc,0,0,0,0,laui_DefaultNodeOperationsPropUiDefine);
  1393. laAddSubGroup(pc,"base","Base","Base node","la_base_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
  1394. laAddSubGroup(pc,"index", "Index","Index output","la_out_socket",0,0,0,offsetof(laLoopIndexNode, Out),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  1395. typedef laMathNode laSmallMathNode;
  1396. LA_IDN_REGISTER("Keyboard",U'K',LA_IDN_KEYBOARD,LA_PC_IDN_KEYBOARD, IDN_Keyboard, laKeyboardNode);
  1397. LA_IDN_REGISTER("Controller",U'🕹',LA_IDN_CONTROLLER,LA_PC_IDN_CONTROLLER, IDN_Controller, laInputControllerNode);
  1398. LA_IDN_REGISTER("Visualizer",U'🔍',LA_IDN_VISUALIZER,LA_PC_IDN_VISUALIZER, IDN_InputVisualizer, laInputVisualizerNode);
  1399. LA_IDN_REGISTER("Split",U'⚟',LA_IDN_SPLIT,LA_PC_IDN_SPLIT, IDN_Split, laSplitNode);
  1400. LA_IDN_REGISTER("Switch",U'🚦',LA_IDN_SWITCH,LA_PC_IDN_SWITCH, IDN_Switch, laSwitchNode);
  1401. LA_IDN_REGISTER("Combine",U'⚞',LA_IDN_COMBINE,LA_PC_IDN_COMBINE, IDN_Combine, laCombineNode);
  1402. LA_IDN_REGISTER("Values",0,LA_IDN_VALUES,LA_PC_IDN_VALUES, IDN_Values, laValuesNode);
  1403. LA_IDN_REGISTER("Matrix",0,LA_IDN_MATRIX,LA_PC_IDN_MATRIX, IDN_Matrix, laMatrixNode);
  1404. LA_IDN_REGISTER("Math",0,LA_IDN_MATH,LA_PC_IDN_MATH, IDN_Math, laMathNode);
  1405. LA_IDN_REGISTER("Small Math",0,LA_IDN_SMALL_MATH,LA_PC_IDN_SMALL_MATH, IDN_Math, laSmallMathNode);
  1406. LA_IDN_REGISTER("Mapper",0,LA_IDN_MAPPER,LA_PC_IDN_MAPPER, IDN_Mapper, laMapperNode);
  1407. LA_IDN_REGISTER("Random",0,LA_IDN_RANDOM,LA_PC_IDN_RANDOM, IDN_Random, laRandomNode);
  1408. LA_IDN_REGISTER("Vector Math",0,LA_IDN_VECTOR_MATH,LA_PC_IDN_VECTOR_MATH, IDN_VectorMath, laVectorMathNode);
  1409. LA_IDN_REGISTER("Comment",0,LA_IDN_COMMENT,LA_PC_IDN_COMMENT, IDN_Comment, laCommentNode);
  1410. LA_IDN_REGISTER("RGB to OKHSL",0,LA_IDN_RGB2OKHSL,LA_PC_IDN_RGB2OKHSL, IDN_RGB2OKHSL, laRGB2OKHSLNode);
  1411. LA_IDN_REGISTER("OKHSL to RGB",0,LA_IDN_OKHSL2RGB,LA_PC_IDN_OKHSL2RGB, IDN_OKHSL2RGB, laOKHSL2RGBNode);
  1412. LA_IDN_REGISTER("Loop",0,LA_IDN_LOOP,LA_PC_IDN_LOOP, IDN_Loop, laLoopNode);
  1413. LA_IDN_REGISTER("Loop Index",0,LA_IDN_LOOP_INDEX,LA_PC_IDN_LOOP_INDEX, IDN_LoopIndex, laLoopIndexNode);
  1414. laNodeCategoryAddNodeTypes(LA_NODE_CATEGORY_INPUT, &LA_IDN_KEYBOARD,&LA_IDN_CONTROLLER,0);
  1415. 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);
  1416. laNodeCategoryAddNodeTypes(LA_NODE_CATEGORY_ROUTE, &LA_IDN_SPLIT, &LA_IDN_SWITCH, &LA_IDN_COMBINE, &LA_IDN_LOOP, &LA_IDN_LOOP_INDEX,0);
  1417. laNodeCategoryAddNodeTypes(LA_NODE_CATEGORY_AUX, &LA_IDN_COMMENT, &LA_IDN_VISUALIZER,0);
  1418. laNodeCategoryAddNodeTypes(LA_NODE_CATEGORY_COLOR, &LA_IDN_RGB2OKHSL, &LA_IDN_OKHSL2RGB,0);
  1419. MAIN.tNodeIn=laCreateInSocket("TIN",0);
  1420. MAIN.tNodeOut=laCreateOutSocket(0,"TOUT",0);
  1421. }
  1422. void laGraphRequestRebuild(){ MAIN.GraphNeedsRebuild=1; }
  1423. void laMappingRequestEval(){ MAIN.InputNeedsEval=1; }
  1424. int __DEBUG_PAGE_EVAL__=0;
  1425. void la_PageClearBranch(laRackPage* rp, int mask){
  1426. for(laListItemPointer*lip=rp->Eval.pFirst;lip;lip=lip->pNext){
  1427. laBaseNode* n=lip->p; if(!n->InitDone){ n->Type->Init(n,1); n->InitDone=1; }
  1428. if(n->Branch&mask){ n->EvalMagic=0; }
  1429. }
  1430. }
  1431. int laRebuildPageEval(laRackPage* rp){
  1432. if(!rp)return LA_DAG_FLAG_PERM;
  1433. while(lstPopPointer(&rp->Eval)); while(lstPopPointer(&rp->AlwaysBranchers));
  1434. laListHandle pending={0};
  1435. for(laNodeRack* ir=rp->Racks.pFirst;ir;ir=ir->Item.pNext){
  1436. for(laBaseNode*bn=ir->Nodes.pFirst;bn;bn=bn->Item.pNext){ if(!bn->InitDone){ bn->Type->Init(bn,1); bn->InitDone=1; }
  1437. lstAppendPointer(&pending,bn); bn->Branch=0; bn->BranchTemp=0;
  1438. }
  1439. }
  1440. laBaseNode*n; int result=LA_DAG_FLAG_PERM; laListItemPointer*NextLip;
  1441. laNodeVisitInfo vi;
  1442. vi.Branch=1; vi.NextBranch=2; vi.l=&rp->Eval; vi.br=&rp->AlwaysBranchers; vi.Page=rp;
  1443. for(laListItemPointer*lip=pending.pFirst;lip;lip=NextLip){ n=lip->p; NextLip=lip->pNext;
  1444. if(n->Branch & 1) continue;
  1445. result=n->Type->Visit(n,&vi); if(result==LA_DAG_FLAG_ERR){ while(lstPopPointer(&pending)); break; }
  1446. }
  1447. if(result==LA_DAG_FLAG_ERR){ while(lstPopPointer(&rp->Eval)); while(lstPopPointer(&rp->AlwaysBranchers)); return LA_DAG_FLAG_ERR; }
  1448. return LA_DAG_FLAG_PERM;
  1449. }
  1450. int laRunPage(laRackPage* rp, uint64_t mask){
  1451. static uint64_t magic=3; if(!magic){ magic=3; }
  1452. if(!rp || (!rp->Eval.pFirst && !rp->AlwaysBranchers.pFirst)) return 0;
  1453. if(__DEBUG_PAGE_EVAL__ && mask==1){ printf("Page eval %s\n",(rp->Name&&rp->Name->Ptr)?rp->Name->Ptr:""); }
  1454. if(mask==1){
  1455. for(laListItemPointer*lip=rp->AlwaysBranchers.pFirst;lip;lip=lip->pNext){
  1456. laBaseNode* n=lip->p; if(!n->InitDone){ n->Type->Init(n,1); n->InitDone=1; }
  1457. if(n->EvalMagic==magic) continue; if(__DEBUG_PAGE_EVAL__){ printf(" BR %.6x\n",n); }
  1458. n->EvalMagic=magic; n->Type->Eval(n);
  1459. }
  1460. }
  1461. for(laListItemPointer*lip=rp->Eval.pFirst;lip;lip=lip->pNext){
  1462. laBaseNode* n=lip->p; if(!n->InitDone){ n->Type->Init(n,1); n->InitDone=1; }
  1463. if((!(n->Branch&mask)) || (mask==1&&n->Branch!=1) || n->EvalMagic==magic) continue;
  1464. if(__DEBUG_PAGE_EVAL__){ printf(" -- %d %s %.6x\n",mask,n->Type->Name,n); }
  1465. n->EvalMagic=magic; n->Type->Eval(n);
  1466. }
  1467. if(__DEBUG_PAGE_EVAL__ && mask==1){ printf("End\n"); }
  1468. if(mask==1){ magic++; }
  1469. return 1;
  1470. }
  1471. //==================================================================================================
  1472. laNodeOutSocket* laCreateOutSocket(void* NodeParentOptional, char* label, int DataType){
  1473. laNodeOutSocket* os=memAcquire(sizeof(laNodeOutSocket));
  1474. strSafeSet(&os->Label, label); os->DataType = DataType; os->Parent=NodeParentOptional;
  1475. return os;
  1476. }
  1477. laNodeInSocket* laCreateInSocket(char* label, int DataType){
  1478. laNodeInSocket* is=memAcquire(sizeof(laNodeInSocket));
  1479. strSafeSet(&is->Label, label); is->DataType = DataType;
  1480. return is;
  1481. }
  1482. void laDestroyInSocket(laNodeInSocket* s){ strSafeDestroy(&s->Label); memLeave(s); }
  1483. void laDestroyOutSocket(laNodeOutSocket* s){ strSafeDestroy(&s->Label); memLeave(s); }
  1484. laNodeCategory* laEnsureNodeCategory(char* Name,laUiDefineFunc* Ui,int ForRackTypes){
  1485. laNodeCategory* nc=0;
  1486. for(laNodeCategory* c=MAIN.NodeCategories.pFirst;c;c=c->Item.pNext){
  1487. if(strSame(SSTR(c->Name),Name)){ nc=c; break; }
  1488. }
  1489. if(!nc){
  1490. nc=memAcquire(sizeof(laNodeCategory));
  1491. lstAppendItem(&MAIN.NodeCategories,nc);
  1492. strSafeSet(&nc->Name, Name); nc->Ui=Ui; nc->For=ForRackTypes;
  1493. }
  1494. return nc;
  1495. }
  1496. void laNodeCategoryAddNodeTypes(laNodeCategory* nc, ...){
  1497. va_list list; va_start(list,nc);
  1498. laBaseNodeType* nt;
  1499. while(nt=va_arg(list,laBaseNodeType*)){
  1500. lstAppendPointer(&nc->NodeTypes, nt);
  1501. }
  1502. va_end(list);
  1503. }
  1504. void laDestroyRack(laNodeRack* rr){
  1505. laBaseNode* n; while(n=lstPopItem(&rr->Nodes)){ n->Type->Destroy(n); memLeave(n); }
  1506. laRackPage* page=rr->ParentPage;
  1507. strSafeDestroy(&rr->Name); lstRemoveItem(&rr->ParentPage->Racks, rr); memLeave(rr);
  1508. }
  1509. laRackPage* laDuplicateRackPage(laRackPage* new_optional, laRackPage* from){
  1510. laRackPage* nr=new_optional?new_optional:memAcquire(sizeof(laRackPage));
  1511. strSafeSet(&nr->Name,from->Name?from->Name->Ptr:0);
  1512. strSafeSet(&nr->Script,nr->Script?from->Script->Ptr:0);
  1513. nr->TriggerMode=from->TriggerMode; nr->UseScript=from->UseScript; nr->RackType=from->RackType;
  1514. for(laNodeRack* r=from->Racks.pFirst;r;r=r->Item.pNext){
  1515. laNodeRack* nnr=memAcquire(sizeof(laNodeRack)); r->Duplicated=nnr; lstAppendItem(&nr->Racks, nnr);
  1516. strSafeSet(&nnr->Name,r->Name?r->Name->Ptr:0);
  1517. nnr->ParentPage=nr; nnr->RackType=r->RackType;
  1518. for(laBaseNode* n=r->Nodes.pFirst;n;n=n->Item.pNext){
  1519. laBaseNode* nn=memAcquire(n->Type->NodeSize);
  1520. nn->Type=n->Type; nn->InitDone=1; lstAppendItem(&nnr->Nodes, nn); nn->InRack=nnr; n->Duplicated=nn;
  1521. nn->Type->Init(nn, 0); nn->Type->Copy(nn,n,0);
  1522. }
  1523. }
  1524. for(laNodeRack* r=from->Racks.pFirst;r;r=r->Item.pNext){
  1525. for(laBaseNode* n=r->Nodes.pFirst;n;n=n->Item.pNext){
  1526. n->Type->Copy(n->Duplicated,n,1);
  1527. }
  1528. }
  1529. return nr;
  1530. }