/* * LaGUI: A graphical application framework. * Copyright (C) 2022-2023 Wu Yiming * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "../la_5.h" extern LA MAIN; extern struct _tnsMain *T; laBaseNodeType LA_IDN_KEYBOARD; laBaseNodeType LA_IDN_MOUSE; laBaseNodeType LA_IDN_CONTROLLER; laBaseNodeType LA_IDN_VISUALIZER; laBaseNodeType LA_IDN_SPLIT; laBaseNodeType LA_IDN_SWITCH; laBaseNodeType LA_IDN_COMBINE; laBaseNodeType LA_IDN_VALUES; laBaseNodeType LA_IDN_MATRIX; laBaseNodeType LA_IDN_MATH; laBaseNodeType LA_IDN_SMALL_MATH; laBaseNodeType LA_IDN_MAPPER; laBaseNodeType LA_IDN_RANDOM; laBaseNodeType LA_IDN_VECTOR_MATH; laBaseNodeType LA_IDN_COMMENT; laBaseNodeType LA_IDN_RGB2OKHSL; laBaseNodeType LA_IDN_OKHSL2RGB; laBaseNodeType LA_IDN_LOOP; laBaseNodeType LA_IDN_LOOP_INDEX; laPropContainer* LA_PC_IDN_GENERIC; laPropContainer* LA_PC_IDN_KEYBOARD; laPropContainer* LA_PC_IDN_MOUSE; laPropContainer* LA_PC_IDN_CONTROLLER; laPropContainer* LA_PC_IDN_VISUALIZER; laPropContainer* LA_PC_IDN_SPLIT; laPropContainer* LA_PC_IDN_SWITCH; laPropContainer* LA_PC_IDN_COMBINE; laPropContainer* LA_PC_IDN_VALUES; laPropContainer* LA_PC_IDN_MATRIX; laPropContainer* LA_PC_IDN_MATH; laPropContainer* LA_PC_IDN_SMALL_MATH; laPropContainer* LA_PC_IDN_MAPPER; laPropContainer* LA_PC_IDN_RANDOM; laPropContainer* LA_PC_IDN_VECTOR_MATH; laPropContainer* LA_PC_IDN_COMMENT; laPropContainer* LA_PC_IDN_RGB2OKHSL; laPropContainer* LA_PC_IDN_OKHSL2RGB; laPropContainer* LA_PC_IDN_LOOP; laPropContainer* LA_PC_IDN_LOOP_INDEX; laNodeCategory* LA_NODE_CATEGORY_INPUT; laNodeCategory* LA_NODE_CATEGORY_MATH; laNodeCategory* LA_NODE_CATEGORY_ROUTE; laNodeCategory* LA_NODE_CATEGORY_AUX; laNodeCategory* LA_NODE_CATEGORY_DRIVER; laNodeCategory* LA_NODE_CATEGORY_COLOR; void la_PageClearBranch(laRackPage* rp, int mask); #define LA_IDN_CONTROLLER_RESET_SOCKET(ns) \ {ns->IntVal[0]=0; ns->Out->DataType=LA_PROP_INT; ns->Offset=0; ns->Out->Data=&ns->IntVal;} void IDN_ControllerInit(laInputControllerNode* n, int NoCreate){ if(NoCreate){return;} for(int i=0;i<8;i++){ n->Sockets[i].Out=laCreateOutSocket(n, "out", 0); n->Sockets[i].Parent=n; } strSafeSet(&n->Base.Name,"Controller Output"); } void IDN_ControllerDestroy(laInputControllerNode* n){ for(int i=0;i<8;i++){ laDestroyOutSocket(n->Sockets[i].Out); } strSafeDestroy(&n->Base.Name); } int IDN_ControllerVisit(laInputControllerNode* n, laNodeVisitInfo* vi){ laController* c=la_FindControllerWithID(n->UserID); 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; } else{ for(int i=0;i<8;i++){ laInputControllerNodeSocket* ns=&n->Sockets[i]; if(!ns->Which || !ns->Which->Ptr){ LA_IDN_CONTROLLER_RESET_SOCKET(ns); continue; } laPropContainer*pc=la_EnsureSubTarget(LA_PROP_CONTROLLER, c); laProp* p=la_PropLookup(&pc->Props, n->Sockets[i].Which->Ptr); if((!p)||(!p->Offset)|| ((p->PropertyType!=LA_PROP_INT)&&(p->PropertyType!=LA_PROP_ENUM)&& (p->PropertyType!=(LA_PROP_INT|LA_PROP_ARRAY))&&(p->PropertyType!=(LA_PROP_ENUM|LA_PROP_ARRAY)))){ LA_IDN_CONTROLLER_RESET_SOCKET(ns); continue; } if(p->PropertyType==LA_PROP_INT){ ns->Out->DataType=LA_PROP_FLOAT; ns->Out->Data=&ns->RealVal; ns->Out->ArrLen=1; } 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; } elif(p->PropertyType==LA_PROP_ENUM){ ns->Out->DataType=LA_PROP_ENUM; ns->Out->Data=&ns->IntVal; ns->Out->ArrLen=1; } 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; } ns->Offset=p->Offset; } } LA_ADD_THIS_NODE(n,vi); return LA_DAG_FLAG_PERM; } int IDN_ControllerEval(laInputControllerNode* n){ laNotifyInstanceUsers(n); laController* c=la_FindControllerWithID(n->UserID); if(!c){ for(int i=0;i<8;i++){ laInputControllerNodeSocket* ns=&n->Sockets[i]; LA_IDN_CONTROLLER_RESET_SOCKET(ns); } return 1; } for(int i=0;i<8;i++){ laInputControllerNodeSocket* ns=&n->Sockets[i]; int *addr=((char*)c)+ns->Offset; char* addc=addr; if(ns->Out->DataType==LA_PROP_FLOAT){ ns->RealVal[0]=(real)(*addr)/32767.0; } if(ns->Out->DataType==(LA_PROP_FLOAT|LA_PROP_ARRAY)){ for(int a=0;aOut->ArrLen;a++) ns->RealVal[a]=((real)addr[a])/32767.0; } elif(ns->Out->DataType==LA_PROP_ENUM){ ns->IntVal[0]=(*addc); } elif(ns->Out->DataType==(LA_PROP_ENUM|LA_PROP_ARRAY)){ for(int a=0;aOut->ArrLen;a++) ns->IntVal[a]=addc[a]; } } return 1; } void IDN_ControllerCopy(laInputControllerNode* new, laInputControllerNode* old, int DoRematch){ if(DoRematch) return; for(int i=0;i<8;i++){ old->Sockets[i].Out->Duplicated=new->Sockets[i].Out; strSafeSet(&new->Sockets[i].Which,old->Sockets[i].Which?old->Sockets[i].Which->Ptr:0); } new->Mode=old->Mode;new->UserID=old->UserID; } void laui_ControllerNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){ laColumn* c=laFirstColumn(uil); laInputControllerNode*n=This->EndInstance; laColumn* cl,*cr; LA_BASE_NODE_HEADER(uil,c,This); laSplitColumn(uil,c,0.3); cl=laLeftColumn(c,0); cr=laRightColumn(c,0); laUiItem* b=laBeginRow(uil,c,0,0); laShowItem(uil,c,This,"base.name")->Expand=1; laShowItem(uil,c,This,"user_id"); laEndRow(uil,b); char* buf[128],buf2[128]; for(int i=0;i<8;i++){ sprintf(buf,"out%d.which",i); laShowItem(uil,cl,This,buf); laUiItem* b=laBeginRow(uil,cr,0,0); sprintf(buf2,"out%d.out.data_type",i); laUiItem* b2=laOnConditionThat(uil,cr,laEqual(laPropExpression(This,buf2),laIntExpression(LA_PROP_FLOAT)));{ sprintf(buf,"out%d.axis",i); laShowItem(uil,cr,This,buf)->Expand=1; }laElse(uil,b2);{ laUiItem* b3=laOnConditionThat(uil,cr,laEqual(laPropExpression(This,buf2),laIntExpression(LA_PROP_FLOAT|LA_PROP_ARRAY)));{ 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; }laElse(uil,b3);{ sprintf(buf,"out%d.switch",i); laUiItem* sui=laShowItem(uil,cr,This,buf);sui->Expand=1;sui->Flags|=LA_UI_FLAGS_TRANSPOSE; }laEndCondition(uil,b3); }laEndCondition(uil,b2); sprintf(buf,"out%d.out",i); laShowNodeSocket(uil,cr,This,buf,0); laEndRow(uil,b); } } void IDN_InputVisualizerInit(laInputVisualizerNode* n, int NoCreate){ if(NoCreate){return;} n->In=laCreateInSocket("IN", 0); strSafeSet(&n->Base.Name,"Input Visualizer"); } void IDN_InputVisualizerDestroy(laInputVisualizerNode* n){ laDestroyInSocket(n->In); strSafeDestroy(&n->Base.Name); } int IDN_InputVisualizerVisit(laInputVisualizerNode* n, laNodeVisitInfo* vi){ LA_GUARD_THIS_NODE(n,vi); if(LA_SRC_AND_PARENT(n->In)){ laBaseNode* sn=n->In->Source->Parent;LA_VISIT_NODE(sn,vi); } LA_ADD_THIS_NODE(n,vi); return LA_DAG_FLAG_PERM; } int IDN_InputVisualizerEval(laInputVisualizerNode* n){ if(!n->In->Source) return 0; laNodeOutSocket* os=n->In->Source; int arrlen=1; switch(os->DataType){ case LA_PROP_FLOAT|LA_PROP_ARRAY: case LA_PROP_FLOAT: if(os->ArrLen)arrlen=os->ArrLen; memcpy(n->RealVal,os->Data,sizeof(real)*arrlen); n->In->ArrLen=arrlen; break; case LA_PROP_ENUM|LA_PROP_ARRAY: case LA_PROP_ENUM: if(os->ArrLen)arrlen=os->ArrLen; memcpy(n->IntVal,os->Data,sizeof(int)*arrlen); n->In->ArrLen=arrlen; break; default: n->IntVal[0]=0; n->In->ArrLen=1; break; } n->In->DataType=os->DataType; laNotifyInstanceUsers(n); return 1; } void IDN_InputVisualizerCopy(laInputVisualizerNode* new, laInputVisualizerNode* old, int DoRematch){ if(DoRematch){ LA_IDN_NEW_LINK(In) return; } } void laui_InputVisualizeNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){ laColumn* c=laFirstColumn(uil); laInputVisualizerNode*n=This->EndInstance; LA_BASE_NODE_HEADER(uil,c,This); laColumn* cl,*cr; laSplitColumn(uil,c,0.4); cl=laLeftColumn(c,1); cr=laRightColumn(c,0); laShowNodeSocket(uil,cl,This,"in",0); laUiItem* b2=laOnConditionThat(uil,cr,laEqual(laPropExpression(This,"in.data_type"),laIntExpression(LA_PROP_FLOAT)));{ laShowItem(uil,cr,This,"axis"); }laElse(uil,b2);{ laUiItem* b3=laOnConditionThat(uil,cr,laEqual(laPropExpression(This,"in.data_type"),laIntExpression(LA_PROP_FLOAT|LA_PROP_ARRAY)));{ laUiItem* aui=laShowItem(uil,cr,This,"axis2d"); }laElse(uil,b3);{ laUiItem* sui=laShowItem(uil,cr,This,"switch"); }laEndCondition(uil,b3); }laEndCondition(uil,b2); } void IDN_SplitInit(laSplitNode* n, int NoCreate){ if(NoCreate){return;} n->In=laCreateInSocket("in", 0); strSafeSet(&n->Base.Name,"Split"); for(int i=0;i<8;i++){ char str[4]; sprintf(str,"%d",i); n->Out[i].Out=laCreateOutSocket(n,str,0); } } void IDN_SplitDestroy(laSplitNode* n){ laDestroyInSocket(n->In); strSafeDestroy(&n->Base.Name); for(int i=0;i<8;i++){ laDestroyOutSocket(n->Out[i].Out); } } int IDN_SplitVisit(laSplitNode* n, laNodeVisitInfo* vi){ LA_GUARD_THIS_NODE(n,vi); if(LA_SRC_AND_PARENT(n->In)){ laBaseNode* sn=n->In->Source->Parent; LA_VISIT_NODE(sn,vi); } LA_ADD_THIS_NODE(n,vi); return LA_DAG_FLAG_PERM; } int IDN_SplitEval(laSplitNode* n){ if(!n->In->Source) return 0; laNodeOutSocket* os=n->In->Source; int arrlen=1; switch(os->DataType){ case LA_PROP_FLOAT|LA_PROP_ARRAY: case LA_PROP_FLOAT: if(os->ArrLen) n->ArrLen=os->ArrLen; for(int i=0;iArrLen,8);i++){ n->Out[i].Out->DataType=LA_PROP_FLOAT; n->Out[i].Out->Data=&n->RealVal[i]; } memcpy(n->RealVal,os->Data,sizeof(real)*n->ArrLen); n->In->ArrLen=arrlen; break; case LA_PROP_ENUM|LA_PROP_ARRAY: case LA_PROP_ENUM: if(os->ArrLen) n->ArrLen=os->ArrLen; for(int i=0;iArrLen,8);i++){ n->Out[i].Out->DataType=LA_PROP_ENUM; n->Out[i].Out->Data=&n->IntVal[i]; } memcpy(n->IntVal,os->Data,sizeof(int)*n->ArrLen); n->In->ArrLen=arrlen; break; default: for(int i=0;iArrLen,8);i++){ n->Out[i].Out->DataType=LA_PROP_ENUM; n->Out[i].Out->Data=&n->IntVal[i]; } n->IntVal[0]=0; n->In->ArrLen=1; break; } n->In->DataType=os->DataType; return 1; } void IDN_SplitCopy(laSplitNode* new, laSplitNode* old, int DoRematch){ if(DoRematch){ LA_IDN_NEW_LINK(In) return; } for(int i=0;i<8;i++){ old->Out[i].Out->Duplicated=new->Out[i].Out; } } void laui_SplitNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){ laColumn* c=laFirstColumn(uil); laSplitNode*n=This->EndInstance; laColumn* cl,*cr; laSplitColumn(uil,c,0.4); cl=laLeftColumn(c,1); cr=laRightColumn(c,0); LA_BASE_NODE_HEADER(uil,c,This); laUiItem* b=laBeginRow(uil,c,0,0); laShowNodeSocket(uil,c,This,"in",0); laShowItemFull(uil,c,This,"array_length",LA_WIDGET_INT_PLAIN,0,0,0); laShowLabel(uil,c,"🡲",0,0)->Expand=1; for(int i=0;i<8;i++){ char* buf[128]; sprintf(buf,"out%d.out",i); laShowNodeSocket(uil,cr,This,buf,0); } laEndRow(uil,b); } void IDN_SwitchInit(laSwitchNode* n, int NoCreate){ if(NoCreate){return;} n->SwitchIn=laCreateInSocket("sw in",0); n->Out=laCreateOutSocket(n,"out",0); strSafeSet(&n->Base.Name,"Switch"); for(int i=0;i<8;i++){ char str[4]; sprintf(str,"%d",i); n->In[i].In=laCreateInSocket(n,str); } } void IDN_SwitchDestroy(laSwitchNode* n){ laDestroyInSocket(n->SwitchIn); laDestroyOutSocket(n->Out); strSafeDestroy(&n->Base.Name); for(int i=0;i<8;i++){ laDestroyInSocket(n->In[i].In); } } int IDN_SwitchVisit(laSwitchNode* n, laNodeVisitInfo* vi){ LA_GUARD_THIS_NODE(n,vi); n->MaxUsed=0; n->Page=vi->Page; for(int i=0;i<8;i++){ if(n->In[i].In->Source){ n->MaxUsed=i+2; } } uint64_t OrigBranch=vi->Branch; int NextBranch=vi->NextBranch; vi->NextBranch+=n->MaxUsed; n->BranchSW=(1<<(NextBranch-1)); if(OrigBranch==1){ lstAppendPointer(vi->br,n); } for(int i=0;i<8;i++){ if(n->In[i].In->Source){ vi->Branch=OrigBranch|(1<<(NextBranch+i)); laBaseNode* sn=n->In[i].In->Source->Parent; LA_VISIT_NODE(sn,vi); } } vi->Branch=OrigBranch|n->BranchSW; laBaseNode* sw=n->SwitchIn->Source?n->SwitchIn->Source->Parent:0; if(sw){ LA_VISIT_NODE(sw,vi); } vi->Branch=OrigBranch; LA_ADD_THIS_NODE(n,vi); return LA_DAG_FLAG_PERM; } int IDN_SwitchEval(laSwitchNode* n){ int sw=n->Switch; if(n->SwitchIn->Source){ laRunPage(n->Page,n->BranchSW); laNodeOutSocket* os=n->SwitchIn->Source; int* id; real* fd; switch(os->DataType){ case LA_PROP_ARRAY|LA_PROP_ENUM: id=os->Data; for(int i=0;iArrLen;i++){ if(id[i]){sw=i; break;} } break; case LA_PROP_ENUM: case LA_PROP_INT: case LA_PROP_INT|LA_PROP_ARRAY: id=os->Data; sw=*id; break; case LA_PROP_FLOAT: case LA_PROP_FLOAT|LA_PROP_ARRAY: fd=os->Data; sw=(int)(*fd); break; default: sw=0; break; } } laRunPage(n->Page,(n->BranchSW<<(sw+1))); TNS_CLAMP(sw,0,7); laSwitchNodeInSocket *is=&n->In[sw]; 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; } else{ n->Out->Data=&n->TempVal; n->Out->DataType=LA_PROP_FLOAT; n->Out->ArrLen=1; } return 1; } void IDN_SwitchCopy(laSwitchNode* new, laSwitchNode* old, int DoRematch){ if(DoRematch){ for(int i=0;i<8;i++){ LA_IDN_NEW_LINK(In[i].In) } LA_IDN_NEW_LINK(SwitchIn) return; } old->Out->Duplicated=new->Out; new->Switch=old->Switch; } void laui_SwitchNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){ laColumn* c=laFirstColumn(uil); laSwitchNode*n=This->EndInstance; laColumn* cl,*cr; laSplitColumn(uil,c,0.4); cl=laLeftColumn(c,1); cr=laRightColumn(c,0); LA_BASE_NODE_HEADER(uil,c,This); laUiItem* b=laBeginRow(uil,c,0,0); for(int i=0;i<8;i++){ char* buf[128]; sprintf(buf,"in%d.in",i); laShowNodeSocket(uil,cr,This,buf,0); } laShowSeparator(uil,c)->Expand=1; laEndRow(uil,b); b=laBeginRow(uil,c,0,0); laShowItem(uil,c,This,"switch_in"); laUiItem* b2=laOnConditionThat(uil,c,laNot(laPropExpression(This,"switch_in.source")));{ laShowItem(uil,c,This,"switch"); };laEndCondition(uil,b2); laShowSeparator(uil,c)->Expand=1; laShowNodeSocket(uil,c,This,"out",0); laEndRow(uil,b); } void IDN_CombineInit(laCombineNode* n, int NoCreate){ if(!NoCreate){ n->Out=laCreateOutSocket(n,"F",0);n->OutInt=laCreateOutSocket(n,"I",0);n->OutEnum=laCreateOutSocket(n,"E",0); strSafeSet(&n->Base.Name,"Combine"); for(int i=0;i<8;i++){ char str[4]; sprintf(str,"%d",i); n->In[i].In=laCreateInSocket(n,str); } } n->Out->Data=n->Values; n->OutInt->Data=n->ValuesI; n->OutEnum->Data=n->ValuesI; 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; } void IDN_CombineDestroy(laCombineNode* n){ laDestroyOutSocket(n->Out);laDestroyOutSocket(n->OutInt);laDestroyOutSocket(n->OutEnum); strSafeDestroy(&n->Base.Name); for(int i=0;i<8;i++){ laDestroyInSocket(n->In[i].In); } } int IDN_CombineVisit(laCombineNode* n, laNodeVisitInfo* vi){ LA_GUARD_THIS_NODE(n,vi); 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); } } LA_ADD_THIS_NODE(n,vi); return LA_DAG_FLAG_PERM; } int IDN_CombineEval(laCombineNode* n){ int maxlen=0; for(int i=0;i<8;i++){ laNodeInSocket *is=n->In[i].In; if(LA_SRC_AND_PARENT(is)){ if((is->Source->DataType&LA_PROP_FLOAT) && is->Source->Data){ n->Values[i]=*((real*)is->Source->Data); } elif((is->Source->DataType&LA_PROP_INT) && is->Source->Data){ n->Values[i]=*((int*)is->Source->Data); } elif((is->Source->DataType&LA_PROP_ENUM) && is->Source->Data){ n->Values[i]=*((int*)is->Source->Data); } else n->Values[i]=0; maxlen=i+1; } else n->Values[i]=0; n->ValuesI[i]=n->Values[i]; } n->Out->ArrLen=n->OutInt->ArrLen=n->OutEnum->ArrLen=maxlen; return 1; } void IDN_CombineCopy(laCombineNode* new, laCombineNode* old, int DoRematch){ if(DoRematch){ for(int i=0;i<8;i++){ LA_IDN_NEW_LINK(In[i].In) } return; } old->Out->Duplicated=new->Out; old->OutInt->Duplicated=new->OutInt; old->OutEnum->Duplicated=new->OutEnum; } void laui_CombineNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){ laColumn* c=laFirstColumn(uil); laCombineNode*n=This->EndInstance; laColumn* cl,*cr; laSplitColumn(uil,c,0.4); cl=laLeftColumn(c,1); cr=laRightColumn(c,0); LA_BASE_NODE_HEADER(uil,c,This); laUiItem* b=laBeginRow(uil,c,0,0); for(int i=0;i<8;i++){ char* buf[128]; sprintf(buf,"in%d.in",i); laShowNodeSocket(uil,cr,This,buf,0); } laShowSeparator(uil,c)->Expand=1; laEndRow(uil,b); b=laBeginRow(uil,c,0,0); laUiItem* lu=laShowLabel(uil,c,"Combine 🡲",0,0); lu->Expand=1; lu->Flags|=LA_TEXT_ALIGN_RIGHT; laShowNodeSocket(uil,c,This,"out_enum",0)->Flags|=LA_UI_SOCKET_LABEL_W; laShowNodeSocket(uil,c,This,"out_int",0)->Flags|=LA_UI_SOCKET_LABEL_W; laShowNodeSocket(uil,c,This,"out",0)->Flags|=LA_UI_SOCKET_LABEL_W; laEndRow(uil,b); } void IDN_ValuesInit(laValuesNode* n, int NoCreate){ if(NoCreate){return;} strSafeSet(&n->Base.Name,"Values"); for(int i=0;i<8;i++){ char str[4]; sprintf(str,"%d",i); n->Out[i].Out=laCreateOutSocket(n,str,0); } } void IDN_ValuesDestroy(laValuesNode* n){ strSafeDestroy(&n->Base.Name); for(int i=0;i<8;i++){ laDestroyOutSocket(n->Out[i].Out); } } int IDN_ValuesVisit(laValuesNode* n, laNodeVisitInfo* vi){ LA_GUARD_THIS_NODE(n,vi); LA_ADD_THIS_NODE(n,vi); return LA_DAG_FLAG_PERM; } int IDN_ValuesEval(laValuesNode* n){ for(int i=0;i<8;i++){ laNodeOutSocket *is=n->Out[i].Out; if(n->Modes[i]==LA_VALUES_NODE_FLOAT){ is->Data=&n->Values[i]; is->DataType=LA_PROP_FLOAT; } if(n->Modes[i]==LA_VALUES_NODE_INT){ is->Data=&n->ValuesI[i]; is->DataType=LA_PROP_INT; } if(n->Modes[i]==LA_VALUES_NODE_ENUM){ is->Data=&n->ValuesE[i]; is->DataType=LA_PROP_ENUM; } } return 1; } void IDN_ValuesCopy(laValuesNode* new, laValuesNode* old, int DoRematch){ if(DoRematch){ return; } for(int i=0;i<8;i++){ old->Out[i].Out->Duplicated=new->Out[i].Out; new->Modes[i]=old->Modes[i]; new->Values[i]=old->Values[i]; new->ValuesE[i]=old->ValuesE[i]; new->ValuesI[i]=old->ValuesI[i]; } } void laui_ValuesNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){ laColumn* c=laFirstColumn(uil); laValuesNode*n=This->EndInstance; laUiItem*b,*b2; LA_BASE_NODE_HEADER(uil,c,This); laColumn* cl,*cr; laSplitColumn(uil,c,0.4); cl=laLeftColumn(c,3); cr=laRightColumn(c,0); for(int i=0;i<8;i++){ char* bufm[32]; sprintf(bufm,"mode%d",i); laShowItem(uil,cl,This,bufm); b=laBeginRow(uil,cr,0,0); b2=laOnConditionThat(uil,cr,laEqual(laPropExpression(This,bufm),laIntExpression(LA_VALUES_NODE_FLOAT)));{ char* buf[32]; sprintf(buf,"value%d",i); laShowItem(uil,cr,This,buf)->Expand=1; }laEndCondition(uil,b2); b2=laOnConditionThat(uil,cr,laEqual(laPropExpression(This,bufm),laIntExpression(LA_VALUES_NODE_INT)));{ char* buf[32]; sprintf(buf,"valuei%d",i); laShowItem(uil,cr,This,buf)->Expand=1; }laEndCondition(uil,b2); b2=laOnConditionThat(uil,cr,laEqual(laPropExpression(This,bufm),laIntExpression(LA_VALUES_NODE_ENUM)));{ char* buf[32]; sprintf(buf,"valuee%d",i); laUiItem* eui=laShowItem(uil,cr,This,buf); eui->Expand=1; eui->Flags|=LA_UI_FLAGS_HIGHLIGHT; }laEndCondition(uil,b2); sprintf(bufm,"out%d.out",i); laShowNodeSocket(uil,cr,This,bufm,0); laEndRow(uil,b); } } void IDN_MatrixInit(laMatrixNode* n, int NoCreate){ if(!NoCreate){ strSafeSet(&n->Base.Name,"Matrix"); n->InL=laCreateInSocket("l",0); n->InR=laCreateInSocket("r",0); n->Out=laCreateOutSocket(n,"MAT",LA_PROP_FLOAT|LA_PROP_ARRAY); } n->Out->ArrLen=16; n->Out->Data=n->Mat; } void IDN_MatrixDestroy(laMatrixNode* n){ strSafeDestroy(&n->Base.Name); laDestroyInSocket(n->InL); laDestroyInSocket(n->InR); laDestroyOutSocket(n->Out); } int IDN_MatrixVisit(laMatrixNode* n, laNodeVisitInfo* vi){ LA_GUARD_THIS_NODE(n,vi); if(LA_SRC_AND_PARENT(n->InL)){ laBaseNode* bn=n->InL->Source->Parent; LA_VISIT_NODE(bn,vi); } if(LA_SRC_AND_PARENT(n->InR)){ laBaseNode* bn=n->InR->Source->Parent; LA_VISIT_NODE(bn,vi); } LA_ADD_THIS_NODE(n,vi); return LA_DAG_FLAG_PERM; } int IDN_MatrixEval(laMatrixNode* n){ int hasl=LA_SRC_AND_PARENT(n->InL),hasr=LA_SRC_AND_PARENT(n->InR); if((!hasl) && (!hasr)){ tnsLoadIdentity44d(n->Mat); return 0; } if(hasl&&((n->InL->Source->DataType!=(LA_PROP_FLOAT|LA_PROP_ARRAY))||n->InL->Source->ArrLen!=16)){tnsLoadIdentity44d(n->Mat); return 0;} if(hasr&&((n->InR->Source->DataType!=(LA_PROP_FLOAT|LA_PROP_ARRAY))||n->InR->Source->ArrLen!=16)){tnsLoadIdentity44d(n->Mat); return 0;} if(n->Operation==LA_MATRIX_NODE_OP_INV){ real* mat; if(hasl)mat=n->InL->Source->Data;else mat=n->InR->Source->Data; tnsInverse44d(n->Mat, mat); }else{ if(!hasl) { memcpy(n->Mat,n->InR->Source->Data,sizeof(tnsMatrix44d)); } elif(!hasr) { memcpy(n->Mat,n->InL->Source->Data,sizeof(tnsMatrix44d)); } else{ tnsMultiply44d(n->Mat,n->InL->Source->Data,n->InR->Source->Data); } } return 1; } void IDN_MatrixCopy(laMatrixNode* new, laMatrixNode* old, int DoRematch){ if(DoRematch){ LA_IDN_NEW_LINK(InL) LA_IDN_NEW_LINK(InR) return; } old->Out->Duplicated=new->Out; new->Operation=old->Operation; } void laui_MatrixNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){ laColumn* c=laFirstColumn(uil); laMatrixNode*n=This->EndInstance; laColumn* cl,*cr; laSplitColumn(uil,c,0.4); cl=laLeftColumn(c,3); cr=laRightColumn(c,0); laUiItem*b,*b2; LA_BASE_NODE_HEADER(uil,c,This); b=laBeginRow(uil,c,0,0); laShowNodeSocket(uil,c,This,"in_l",0); laShowNodeSocket(uil,c,This,"in_r",0); laShowItem(uil,c,This,"operation"); laShowSeparator(uil,c)->Expand=1; laShowNodeSocket(uil,c,This,"out",0)->Flags|=LA_UI_SOCKET_LABEL_W; laEndRow(uil,b); } void IDN_MathInit(laMathNode* n, int NoCreate){ if(!NoCreate){ strSafeSet(&n->Base.Name,"Math"); n->InL=laCreateInSocket("l",0); n->InR=laCreateInSocket("r",0); n->Out=laCreateOutSocket(n,"F",LA_PROP_FLOAT); n->OutInt=laCreateOutSocket(n,"I",LA_PROP_INT); } n->Out->Data=&n->Value; n->OutInt->Data=&n->ValueI; } void IDN_MathDestroy(laMathNode* n){ strSafeDestroy(&n->Base.Name); laDestroyInSocket(n->InL); laDestroyInSocket(n->InR); laDestroyOutSocket(n->Out); laDestroyOutSocket(n->OutInt); } int IDN_MathVisit(laMathNode* n, laNodeVisitInfo* vi){ LA_GUARD_THIS_NODE(n,vi); if(LA_SRC_AND_PARENT(n->InL)){ laBaseNode* bn=n->InL->Source->Parent; LA_VISIT_NODE(bn,vi); } if(LA_SRC_AND_PARENT(n->InR)){ laBaseNode* bn=n->InR->Source->Parent; LA_VISIT_NODE(bn,vi); } LA_ADD_THIS_NODE(n,vi); return LA_DAG_FLAG_PERM; } #define LA_GET_SRC_AS_FLOAT(var, socket) \ {if(socket->Source->DataType&LA_PROP_FLOAT) var=*((real*)socket->Source->Data);\ if(socket->Source->DataType&(LA_PROP_INT|LA_PROP_ENUM)) var=*((int*)socket->Source->Data);} int IDN_MathEval(laMathNode* n){ real vl=n->ValueL;real vr=n->ValueR; int hasl=LA_SRC_AND_PARENT(n->InL),hasr=LA_SRC_AND_PARENT(n->InR); if(hasl){ LA_GET_SRC_AS_FLOAT(vl,n->InL) } if(hasr){ LA_GET_SRC_AS_FLOAT(vr,n->InR) } switch(n->Operation){ case LA_MATH_NODE_OP_ADD: default: n->Value=vl+vr; break; case LA_MATH_NODE_OP_SUB: n->Value=vl-vr; break; case LA_MATH_NODE_OP_MUL: n->Value=vl*vr; break; case LA_MATH_NODE_OP_DIV: if(vr)n->Value=vl/vr;else n->Value=0; break; case LA_MATH_NODE_OP_POW: n->Value=pow(vl,vr); break; case LA_MATH_NODE_OP_LOG: n->Value=log2(vl)/log2(vr); break; case LA_MATH_NODE_OP_SIN: n->Value=sin(vl); break; case LA_MATH_NODE_OP_COS: n->Value=cos(vl); break; case LA_MATH_NODE_OP_TAN: n->Value=tan(vl); break; case LA_MATH_NODE_OP_ASIN: n->Value=asin(vl); break; case LA_MATH_NODE_OP_ACOS: n->Value=acos(vl); break; case LA_MATH_NODE_OP_ATAN: n->Value=atan(vl); break; case LA_MATH_NODE_OP_ATAN2: n->Value=atan2(vl,vr); break; case LA_MATH_NODE_OP_MOD: n->Value=fmod(vl,vr); break; } n->ValueI=(int)n->Value; return 1; } void IDN_MathCopy(laMathNode* new, laMathNode* old, int DoRematch){ if(DoRematch){ LA_IDN_NEW_LINK(InL) LA_IDN_NEW_LINK(InR) return; } old->Out->Duplicated=new->Out; old->OutInt->Duplicated=new->OutInt; new->Operation=old->Operation; new->ValueL=old->ValueL; new->ValueR=old->ValueR; } void laui_MathNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){ laColumn* c=laFirstColumn(uil); laMathNode*n=This->EndInstance; laColumn* cl,*cr; laSplitColumn(uil,c,0.4); cl=laLeftColumn(c,3); cr=laRightColumn(c,0); laUiItem*b,*b2; LA_BASE_NODE_HEADER(uil,c,This); b=laBeginRow(uil,c,0,0); 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); laShowSeparator(uil,c)->Expand=1; laShowItem(uil,c,This,"operation"); laEndRow(uil,b); b=laBeginRow(uil,c,0,0); 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); laShowSeparator(uil,c)->Expand=1; laShowNodeSocket(uil,c,This,"out_int",0)->Flags|=LA_UI_SOCKET_LABEL_W; laShowNodeSocket(uil,c,This,"out",0)->Flags|=LA_UI_SOCKET_LABEL_W; laEndRow(uil,b); } void laui_SmallMathNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){ laColumn* c=laFirstColumn(uil); laMathNode*n=This->EndInstance; laColumn* cl,*cr; laSplitColumn(uil,c,0.4); cl=laLeftColumn(c,3); cr=laRightColumn(c,0); laUiItem*b,*b2; LA_BASE_NODE_HEADER(uil,c,This); b=laBeginRow(uil,c,0,0); laShowNodeSocket(uil,c,This,"in_l",0);laShowNodeSocket(uil,c,This,"in_r",0); laShowSeparator(uil,c)->Expand=1;laShowItem(uil,c,This,"operation"); laShowNodeSocket(uil,c,This,"out",0)->Flags|=LA_UI_SOCKET_LABEL_W; laEndRow(uil,b); } void IDN_MapperInit(laMapperNode* n, int NoCreate){ if(!NoCreate){ strSafeSet(&n->Base.Name,"Mapper"); n->Mapper=laValueMapperInit(); } if(!n->In) n->In=laCreateInSocket("IN",LA_PROP_FLOAT); if(!n->Out) n->Out=laCreateOutSocket(n,"OUT",LA_PROP_FLOAT); if(!n->InMin) n->InMin=laCreateInSocket("[IN",LA_PROP_FLOAT); if(!n->InMax) n->InMax=laCreateInSocket("IN]",LA_PROP_FLOAT); if(!n->OutMin) n->OutMin=laCreateInSocket("[OUT",LA_PROP_FLOAT); if(!n->OutMax) n->OutMax=laCreateInSocket("OUT]",LA_PROP_FLOAT); n->Out->Data=&n->rOut; } void IDN_MapperDestroy(laMapperNode* n){ strSafeDestroy(&n->Base.Name); laDestroyInSocket(n->In); laDestroyOutSocket(n->Out); laDestroyInSocket(n->InMin); laDestroyInSocket(n->InMax); laDestroyInSocket(n->OutMin); laDestroyInSocket(n->OutMax); laValueMapperDestroy(n->Mapper); } int IDN_MapperVisit(laMapperNode* n, laNodeVisitInfo* vi){ LA_GUARD_THIS_NODE(n,vi); if(LA_SRC_AND_PARENT(n->In)){ laBaseNode* bn=n->In->Source->Parent; LA_VISIT_NODE(bn,vi); } if(LA_SRC_AND_PARENT(n->InMin)){ laBaseNode* bn=n->InMin->Source->Parent; LA_VISIT_NODE(bn,vi); } if(LA_SRC_AND_PARENT(n->InMax)){ laBaseNode* bn=n->InMax->Source->Parent; LA_VISIT_NODE(bn,vi); } if(LA_SRC_AND_PARENT(n->OutMin)){ laBaseNode* bn=n->OutMin->Source->Parent; LA_VISIT_NODE(bn,vi); } if(LA_SRC_AND_PARENT(n->OutMax)){ laBaseNode* bn=n->OutMax->Source->Parent; LA_VISIT_NODE(bn,vi); } LA_ADD_THIS_NODE(n,vi); return LA_DAG_FLAG_PERM; } int IDN_MapperEval(laMapperNode* n){ real in=0; real* InMin=0,*InMax=0,*OutMin=0,*OutMax=0; if(LA_SRC_AND_PARENT(n->In) && (n->In->Source->DataType&LA_PROP_FLOAT)){ in=*((real*)n->In->Source->Data); } if(LA_SRC_AND_PARENT(n->InMin) && (n->InMin->Source->DataType&LA_PROP_FLOAT)){ InMin=n->InMin->Source->Data; } if(LA_SRC_AND_PARENT(n->InMax) && (n->InMax->Source->DataType&LA_PROP_FLOAT)){ InMax=n->InMax->Source->Data; } if(LA_SRC_AND_PARENT(n->OutMin) && (n->OutMin->Source->DataType&LA_PROP_FLOAT)){ OutMin=n->OutMin->Source->Data; } if(LA_SRC_AND_PARENT(n->OutMax) && (n->OutMax->Source->DataType&LA_PROP_FLOAT)){ OutMax=n->OutMax->Source->Data; } real result=laValueMapperEvaluate(n->Mapper,in,InMin,InMax,OutMin,OutMax,n->ClampInput,n->ClampOutput); n->rOut=result; return 1; } void IDN_MapperCopy(laMapperNode* new, laMapperNode* old, int DoRematch){ if(DoRematch){ LA_IDN_NEW_LINK(In) LA_IDN_NEW_LINK(InMax) LA_IDN_NEW_LINK(InMin) LA_IDN_NEW_LINK(OutMax) LA_IDN_NEW_LINK(OutMin) return; } old->Out->Duplicated=new->Out; new->ClampInput=old->ClampInput; new->ClampOutput=old->ClampOutput; laValueMapperCopy(new->Mapper,old->Mapper); } void laui_MapperNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){ laColumn* c=laFirstColumn(uil); laMapperNode*n=This->EndInstance; laColumn* cl,*cr; laSplitColumn(uil,c,0.4); cl=laLeftColumn(c,3); cr=laRightColumn(c,0); laUiItem*b,*b2; LA_BASE_NODE_HEADER(uil,c,This); b=laBeginRow(uil,c,0,0); 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); laShowItem(uil,c,This,"mapper.in_range")->Expand=1; laShowNodeSocket(uil,c,This,"in_max",0); laEndRow(uil,b); laShowItem(uil,c,This,"mapper"); b=laBeginRow(uil,c,0,0); laShowNodeSocket(uil,c,This,"out_min",0); laShowItem(uil,c,This,"mapper.out_range")->Expand=1; 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; laEndRow(uil,b); } void IDN_RandomInit(laRandomNode* n, int NoCreate){ if(!NoCreate){ strSafeSet(&n->Base.Name,"Random"); n->Out=laCreateOutSocket(n,"RAND",LA_PROP_FLOAT); n->Min=0; n->Max=1; } if(!n->InMin) n->InMin=laCreateInSocket("[IN",LA_PROP_FLOAT); if(!n->InMax) n->InMax=laCreateInSocket("IN]",LA_PROP_FLOAT); n->Out->Data=&n->rOut; } void IDN_RandomDestroy(laRandomNode* n){ strSafeDestroy(&n->Base.Name); laDestroyOutSocket(n->Out); laDestroyInSocket(n->InMin); laDestroyInSocket(n->InMax); } int IDN_RandomVisit(laRandomNode* n, laNodeVisitInfo* vi){ LA_GUARD_THIS_NODE(n,vi); if(LA_SRC_AND_PARENT(n->InMin)){ laBaseNode* bn=n->InMin->Source->Parent; LA_VISIT_NODE(bn,vi); } if(LA_SRC_AND_PARENT(n->InMax)){ laBaseNode* bn=n->InMax->Source->Parent; LA_VISIT_NODE(bn,vi); } LA_ADD_THIS_NODE(n,vi); return LA_DAG_FLAG_PERM; } int IDN_RandomEval(laRandomNode* n){ real Min=n->Min,Max=n->Max; if(LA_SRC_AND_PARENT(n->InMin) && (n->InMin->Source->DataType&LA_PROP_FLOAT)){ Min=*((real*)n->InMin->Source->Data); } if(LA_SRC_AND_PARENT(n->InMax) && (n->InMax->Source->DataType&LA_PROP_FLOAT)){ Max=*((real*)n->InMax->Source->Data); } n->rOut=Min+(real)rand()/(real)(RAND_MAX/(Max-Min)); return 1; } void IDN_RandomCopy(laRandomNode* new, laRandomNode* old, int DoRematch){ if(DoRematch){ LA_IDN_NEW_LINK(InMax) LA_IDN_NEW_LINK(InMin) return; } old->Out->Duplicated=new->Out; new->Max=old->Max; new->Min=old->Min; } void laui_RandomNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){ laColumn* c=laFirstColumn(uil); laRandomNode*n=This->EndInstance; laColumn* cl,*cr; laSplitColumn(uil,c,0.4); cl=laLeftColumn(c,3); cr=laRightColumn(c,0); laUiItem*b,*b2; LA_BASE_NODE_HEADER(uil,c,This); b=laBeginRow(uil,c,0,0); laShowNodeSocket(uil,c,This,"min",0); laShowItem(uil,c,This,"range")->Expand=1; laShowNodeSocket(uil,c,This,"max",0); laShowNodeSocket(uil,c,This,"out",0)->Flags|=LA_UI_SOCKET_LABEL_W; laEndRow(uil,b); } void IDN_VectorMathInit(laVectorMathNode* n, int NoCreate){ if(!NoCreate){ strSafeSet(&n->Base.Name,"Math"); n->InL=laCreateInSocket("l",0); n->InR=laCreateInSocket("r",0); n->Out=laCreateOutSocket(n,"OUT",LA_PROP_FLOAT); } n->Out->Data=n->rOut; } void IDN_VectorMathDestroy(laVectorMathNode* n){ strSafeDestroy(&n->Base.Name); laDestroyInSocket(n->InL); laDestroyInSocket(n->InR); laDestroyOutSocket(n->Out); } int IDN_VectorMathVisit(laVectorMathNode* n, laNodeVisitInfo* vi){ LA_GUARD_THIS_NODE(n,vi); if(LA_SRC_AND_PARENT(n->InL)){ laBaseNode* bn=n->InL->Source->Parent; LA_VISIT_NODE(bn,vi); } if(LA_SRC_AND_PARENT(n->InR)){ laBaseNode* bn=n->InR->Source->Parent; LA_VISIT_NODE(bn,vi); } LA_ADD_THIS_NODE(n,vi); return LA_DAG_FLAG_PERM; } #define LA_GET_SRC_AS_FLOAT_THINGS(var, socket, maxlen) \ {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;iSource->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;iInL),hasr=LA_SRC_AND_PARENT(n->InR); if(hasl){ LA_GET_SRC_AS_FLOAT_THINGS(vl,n->InL,maxlen1) } if(hasr){ LA_GET_SRC_AS_FLOAT_THINGS(vr,n->InR,maxlen2) } if(maxlen1>1 && maxlen2Operation){ case LA_VECTOR_MATH_OP_ADD: default:n->Out->ArrLen=maxlen; for(int i=0;irOut[i]=vl[i]+vr[i]; break; case LA_VECTOR_MATH_OP_SUB:n->Out->ArrLen=maxlen; for(int i=0;irOut[i]=vl[i]-vr[i]; break; case LA_VECTOR_MATH_OP_MUL:n->Out->ArrLen=maxlen; for(int i=0;irOut[i]=vl[i]*vr[i]; break; case LA_VECTOR_MATH_OP_DIV:n->Out->ArrLen=maxlen; for(int i=0;irOut[i]=vl[i]/vr[i]; break; case LA_VECTOR_MATH_OP_POW:n->Out->ArrLen=maxlen; for(int i=0;irOut[i]=pow(vl[i],vr[i]); break; case LA_VECTOR_MATH_OP_LOG:n->Out->ArrLen=maxlen; for(int i=0;irOut[i]=log2(vl[i])/log2(vr[i]); break; case LA_VECTOR_MATH_OP_CROSS: if(maxlen<3) return 0; n->Out->ArrLen=3; tnsVectorCross3d(n->rOut,vl,vr); break; 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; case LA_VECTOR_MATH_OP_LEN: if(maxlen<2) return 0; n->Out->ArrLen=1; if(maxlen==2){ tnsVector2d d; tnsVectorMinus2d(d,vr,vl); n->rOut[0]=tnsLength2d(d); } else { tnsVector3d d; tnsVectorMinus2d(d,vr,vl); n->rOut[0]=tnsLength3d(d); } break; 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; } return 1; } void IDN_VectorMathCopy(laVectorMathNode* new, laVectorMathNode* old, int DoRematch){ if(DoRematch){ LA_IDN_NEW_LINK(InL) LA_IDN_NEW_LINK(InR) return; } old->Out->Duplicated=new->Out; new->Operation=old->Operation; } void laui_VectorMathNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){ laColumn* c=laFirstColumn(uil); laVectorMathNode*n=This->EndInstance; laColumn* cl,*cr; laSplitColumn(uil,c,0.4); cl=laLeftColumn(c,3); cr=laRightColumn(c,0); laUiItem*b,*b2; LA_BASE_NODE_HEADER(uil,c,This); b=laBeginRow(uil,c,0,0); laShowNodeSocket(uil,c,This,"in_l",0); laShowNodeSocket(uil,c,This,"in_r",0); laShowSeparator(uil,c)->Expand=1; laShowItem(uil,c,This,"operation"); laShowNodeSocket(uil,c,This,"out",0)->Flags|=LA_UI_SOCKET_LABEL_W; laEndRow(uil,b); } void IDN_CommentInit(laCommentNode* n, int NoCreate){ if(NoCreate){return;} strSafeSet(&n->Base.Name,"Math"); strSafeSet(&n->Content,""); } void IDN_CommentDestroy(laCommentNode* n){ strSafeDestroy(&n->Base.Name); strSafeDestroy(&n->Content); } int IDN_CommentVisit(laCommentNode* n, laNodeVisitInfo* vi){ //LA_GUARD_THIS_NODE(n,vi); //LA_ADD_THIS_NODE(n,vi); // No need to evaluate comments I guess? return LA_DAG_FLAG_PERM; } int IDN_CommentEval(laCommentNode* n){ return 1; } void IDN_CommentCopy(laCommentNode* new, laCommentNode* old, int DoRematch){ if(DoRematch){ return; } strSafeSet(new->Content,old->Content?old->Content->Ptr:0); } void laui_CommentNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){ laColumn* c=laFirstColumn(uil); laCommentNode*n=This->EndInstance; LA_BASE_NODE_HEADER(uil,c,This); laColumn* cl,*cr; laSplitColumn(uil,c,0.7); cl=laLeftColumn(c,0);cr=laRightColumn(c,1); laUiItem* b=laOnConditionToggle(uil,cr,0,0,0,0,0);{ laShowItemFull(uil,cl,This,"content",LA_WIDGET_STRING_MULTI,0,0,0)->Flags|=LA_UI_FLAGS_NO_SCROLL_INACTIVE; }laElse(uil,b);{ laShowItemFull(uil,cl,This,"content",LA_WIDGET_STRING_PLAIN,0,0,0)->Flags|=LA_TEXT_LINE_WRAP; }laEndCondition(uil,b);} void IDN_RGB2OKHSLInit(laRGB2OKHSLNode* n, int NoCreate){ if(!NoCreate){ strSafeSet(&n->Base.Name,"RGB to OKHL"); n->In=laCreateInSocket("IN",LA_PROP_FLOAT); n->OutH=laCreateOutSocket(n,"H",LA_PROP_FLOAT); n->OutS=laCreateOutSocket(n,"S",LA_PROP_FLOAT); n->OutL=laCreateOutSocket(n,"L",LA_PROP_FLOAT); tnsVectorSet3(n->RGB,0.2,0.2,0.2); } n->OutH->Data=&n->rOut[0]; n->OutS->Data=&n->rOut[1]; n->OutL->Data=&n->rOut[2]; } void IDN_RGB2OKHSLDestroy(laRGB2OKHSLNode* n){ strSafeDestroy(&n->Base.Name); laDestroyInSocket(n->In); laDestroyOutSocket(n->OutH); laDestroyOutSocket(n->OutS); laDestroyOutSocket(n->OutL); } int IDN_RGB2OKHSLVisit(laRGB2OKHSLNode* n, laNodeVisitInfo* vi){ LA_GUARD_THIS_NODE(n,vi); if(LA_SRC_AND_PARENT(n->In)){ laBaseNode* bn=n->In->Source->Parent; LA_VISIT_NODE(bn,vi); } LA_ADD_THIS_NODE(n,vi); return LA_DAG_FLAG_PERM; } int IDN_RGB2OKHSLEval(laRGB2OKHSLNode* n){ real* in=n->RGB; 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; } tnsRGB2HCYLinear(in, n->rOut); return 1; } void IDN_RGB2OKHSLCopy(laRGB2OKHSLNode* new, laRGB2OKHSLNode* old, int DoRematch){ if(DoRematch){ LA_IDN_NEW_LINK(In) return; } old->OutH->Duplicated=new->OutH;old->OutS->Duplicated=new->OutS;old->OutL->Duplicated=new->OutL; } void laui_RGB2OKHSLNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){ laColumn* c=laFirstColumn(uil); laRGB2OKHSLNode*n=This->EndInstance; laUiItem*b,*b2; LA_BASE_NODE_HEADER(uil,c,This); b=laBeginRow(uil,c,0,0); laShowNodeSocket(uil,c,This,"in",0); b2=laOnConditionThat(uil,c,laNot(laPropExpression(This,"in.source")));{ laShowItem(uil,c,This,"color"); }laEndCondition(uil,b2); laShowSeparator(uil,c)->Expand=1; laShowLabel(uil,c,"OKHSL",0,0); laShowItem(uil,c,This,"out_h"); laShowItem(uil,c,This,"out_s"); laShowItem(uil,c,This,"out_l"); laEndRow(uil,b); } void IDN_OKHSL2RGBInit(laOKHSL2RGBNode* n, int NoCreate){ if(!NoCreate){ strSafeSet(&n->Base.Name,"OKHL to RGB"); n->Out=laCreateOutSocket(n,"RGB",LA_PROP_FLOAT|LA_PROP_ARRAY); n->InH=laCreateInSocket("H",LA_PROP_FLOAT); n->InS=laCreateInSocket("S",LA_PROP_FLOAT); n->InL=laCreateInSocket("L",LA_PROP_FLOAT); } n->Out->ArrLen=3; n->Out->Data=n->rOut; } void IDN_OKHSL2RGBDestroy(laOKHSL2RGBNode* n){ strSafeDestroy(&n->Base.Name); laDestroyInSocket(n->InH); laDestroyInSocket(n->InS); laDestroyInSocket(n->InL); laDestroyOutSocket(n->Out); } int IDN_OKHSL2RGBVisit(laOKHSL2RGBNode* n, laNodeVisitInfo* vi){ LA_GUARD_THIS_NODE(n,vi); if(LA_SRC_AND_PARENT(n->InH)){ laBaseNode* bn=n->InH->Source->Parent; LA_VISIT_NODE(bn,vi); } if(LA_SRC_AND_PARENT(n->InS)){ laBaseNode* bn=n->InS->Source->Parent; LA_VISIT_NODE(bn,vi); } if(LA_SRC_AND_PARENT(n->InL)){ laBaseNode* bn=n->InL->Source->Parent; LA_VISIT_NODE(bn,vi); } LA_ADD_THIS_NODE(n,vi); return LA_DAG_FLAG_PERM; } int IDN_OKHSL2RGBEval(laOKHSL2RGBNode* n){ real in[3]={0,0,0}; if(LA_SRC_AND_PARENT(n->InH) && (n->InH->Source->DataType&LA_PROP_FLOAT)){ in[0]=*((real*)n->InH->Source->Data); } if(LA_SRC_AND_PARENT(n->InS) && (n->InS->Source->DataType&LA_PROP_FLOAT)){ in[1]=*((real*)n->InS->Source->Data); } if(LA_SRC_AND_PARENT(n->InL) && (n->InL->Source->DataType&LA_PROP_FLOAT)){ in[2]=*((real*)n->InL->Source->Data); } tnsHCY2RGBLinear(in, n->rOut); return 1; } void IDN_OKHSL2RGBCopy(laOKHSL2RGBNode* new, laOKHSL2RGBNode* old, int DoRematch){ if(DoRematch){ LA_IDN_NEW_LINK(InH) LA_IDN_NEW_LINK(InS) LA_IDN_NEW_LINK(InL) return; } old->Out->Duplicated=new->Out; } void laui_OKHSL2RGBNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){ laColumn* c=laFirstColumn(uil); laOKHSL2RGBNode*n=This->EndInstance; laUiItem*b,*b2; LA_BASE_NODE_HEADER(uil,c,This); b=laBeginRow(uil,c,0,0); laShowItem(uil,c,This,"in_h"); laShowItem(uil,c,This,"in_s"); laShowItem(uil,c,This,"in_l"); laShowLabel(uil,c,"OKHSL",0,0); laShowSeparator(uil,c)->Expand=1; laShowNodeSocket(uil,c,This,"out",0)->Flags|=LA_UI_SOCKET_LABEL_W; laEndRow(uil,b); } void IDN_LoopInit(laLoopNode* n, int NoCreate){ if(!NoCreate){ strSafeSet(&n->Base.Name,"Loop"); n->Branch=laCreateInSocket("CTRL",LA_PROP_FLOAT); n->InIndex=laCreateInSocket("IDX",LA_PROP_FLOAT); n->InIterations=laCreateInSocket("NUM",LA_PROP_FLOAT); n->Prev=laCreateInSocket("PREV",LA_PROP_FLOAT); n->Next=laCreateOutSocket(n,"NEXT",LA_PROP_INT); } n->Next->Data=&n->Iterations; } void IDN_LoopDestroy(laLoopNode* n){ strSafeDestroy(&n->Base.Name); laDestroyInSocket(n->Prev); laDestroyInSocket(n->InIterations); laDestroyInSocket(n->InIndex); laDestroyInSocket(n->Branch); laDestroyOutSocket(n->Next); } int IDN_LoopVisit(laLoopNode* n, laNodeVisitInfo* vi){ LA_GUARD_THIS_NODE(n,vi);if(!LA_SRC_AND_PARENT(n->Branch)){ return LA_DAG_FLAG_PERM; } if(LA_SRC_AND_PARENT(n->Prev)){ laBaseNode* bn=n->Prev->Source->Parent; LA_VISIT_NODE(bn,vi); } if(LA_SRC_AND_PARENT(n->InIterations)){ laBaseNode* bn=n->InIterations->Source->Parent; LA_VISIT_NODE(bn,vi); } if(LA_SRC_AND_PARENT(n->InIndex)){ laBaseNode* bn=n->InIndex->Source->Parent; LA_VISIT_NODE(bn,vi); } uint64_t OrigBranch=vi->Branch; int NextBranch=vi->NextBranch; n->Page=vi->Page; vi->NextBranch+=1; n->BranchControl=(1<<(NextBranch-1)); if(OrigBranch==1){ lstAppendPointer(vi->br,n); } vi->Branch=OrigBranch|n->BranchControl; laBaseNode* sw=n->Branch->Source->Parent; LA_VISIT_NODE(sw,vi); vi->Branch=OrigBranch; LA_ADD_THIS_NODE(n,vi); return LA_DAG_FLAG_PERM; } int IDN_LoopEval(laLoopNode* n){ laLoopIndexNode* lin=LA_SRC_AND_PARENT(n->InIndex)?n->InIndex->Source->Parent:0; if(lin->Base.Type!=&LA_IDN_LOOP_INDEX){lin=0;} int Iterations=n->Iterations; if(LA_SRC_AND_PARENT(n->InIterations)){ LA_GET_SRC_AS_VALUE(Iterations, n->InIterations); } for(int i=0; iIteration=i; } la_PageClearBranch(n->Page,n->BranchControl); laRunPage(n->Page,n->BranchControl); } return 1; } void IDN_LoopCopy(laLoopNode* new, laLoopNode* old, int DoRematch){ if(DoRematch){ LA_IDN_NEW_LINK(Branch) LA_IDN_NEW_LINK(InIndex) LA_IDN_NEW_LINK(InIterations) LA_IDN_NEW_LINK(Prev) return; } old->Next->Duplicated=new->Next; } void laui_LoopNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){ laColumn* c=laFirstColumn(uil), *cl,*cr; laLoopNode*n=This->EndInstance; laUiItem*b,*b2; LA_BASE_NODE_HEADER(uil,c,This); laSplitColumn(uil,c,0.6); cl=laLeftColumn(c,0); cr=laRightColumn(c,5); b=laBeginRow(uil,cl,0,0); laShowItem(uil,cl,This,"branch")->Flags|=LA_UI_SOCKET_LABEL_E; laShowItem(uil,cl,This,"in_iterations")->Flags|=LA_UI_SOCKET_LABEL_E; laShowSeparator(uil,cl)->Expand=1; laEndRow(uil,b); b=laBeginRow(uil,cl,1,0); laShowItem(uil,cl,This,"index")->Flags|=LA_UI_SOCKET_LABEL_E; laShowItem(uil,cl,This,"iterations"); laShowSeparator(uil,cl)->Expand=1; laEndRow(uil,b); b=laBeginRow(uil,cr,1,0); laShowItem(uil,cr,This,"prev")->Flags|=LA_UI_SOCKET_LABEL_S; laShowItem(uil,cr,This,"next")->Flags|=LA_UI_SOCKET_LABEL_N; laEndRow(uil,b); } void IDN_LoopIndexInit(laLoopIndexNode* n, int NoCreate){ if(!NoCreate){ strSafeSet(&n->Base.Name,"Loop Index"); n->Out=laCreateOutSocket(n,"IDX",LA_PROP_INT); } n->Out->Data=&n->Iteration; n->Out->DataType=LA_PROP_INT; } void IDN_LoopIndexDestroy(laLoopIndexNode* n){ strSafeDestroy(&n->Base.Name); laDestroyOutSocket(n->Out); } int IDN_LoopIndexVisit(laLoopIndexNode* n, laNodeVisitInfo* vi){ LA_GUARD_THIS_NODE(n,vi); LA_ADD_THIS_NODE(n,vi); return LA_DAG_FLAG_PERM; } int IDN_LoopIndexEval(laLoopIndexNode* n){ return 1; } void IDN_LoopIndexCopy(laLoopIndexNode* new, laLoopIndexNode* old, int DoRematch){ if(DoRematch){ return; } old->Out->Duplicated=new->Out; } void laui_LoopIndexNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){ laColumn* c=laFirstColumn(uil); laLoopIndexNode*n=This->EndInstance; laUiItem*b,*b2; LA_BASE_NODE_HEADER(uil,c,This); b=laBeginRow(uil,c,0,0); laShowSeparator(uil,c)->Expand=1; laShowItem(uil,c,This,"index")->Flags|=LA_UI_SOCKET_LABEL_W; laEndRow(uil,b); } int OPINV_AddInputMapperPage(laOperator* a, laEvent *e){ laRackPage* dp=memAcquire(sizeof(laRackPage)); strSafeSet(&dp->Name,"New Page"); lstAppendItem(&MAIN.InputMapping->Pages, dp); memAssignRef(MAIN.InputMapping,&MAIN.InputMapping->CurrentPage,dp); dp->RackType=LA_RACK_TYPE_INPUT; laNotifyUsers("la.input_mapping"); laRecordAndPush(0,"la.input_mapping","Add Page", 0); return LA_FINISHED; } int OPINV_AddNodesRack(laOperator* a, laEvent *e){ laRackPage* dp=a->This?a->This->EndInstance:0; if(!dp) return LA_FINISHED; laNodeRack* ir=memAcquire(sizeof(laNodeRack)); strSafeSet(&ir->Name,"New Rack"); lstAppendItem(&dp->Racks, ir); ir->ParentPage=dp; ir->RackType=dp->RackType; laNotifyInstanceUsers(dp); laRecordInstanceDifferences(dp,"la_rack_page"); laPushDifferences("Add Rack", 0); return LA_FINISHED; } int OPINV_RebuildInputMapping(laOperator* a, laEvent *e){ laGraphRequestRebuild(); return LA_FINISHED; } int OPCHK_RemoveInputMappingPage(laPropPack *This, laStringSplitor *ss){ if ((!This) || (la_EnsureSubTarget(This->LastPs->p,0) != LA_PC_RACK_PAGE)) return 0; laRackPage* dp=This->EndInstance; if(dp->ParentObject) return 0; return 1; } int OPINV_RemoveInputMappingPage(laOperator* a, laEvent *e){ laRackPage* dp=a->This?a->This->EndInstance:0; if((!dp) || dp->ParentObject) return LA_CANCELED; if(strSame(strGetArgumentString(a->ExtraInstructionsP,"confirm"),"true")){ strSafeDestroy(&dp->Name); while(dp->Racks.pFirst){ laDestroyRack(dp->Racks.pFirst); } while(lstPopPointer(&dp->Eval)); while(lstPopPointer(&dp->AlwaysBranchers)); if(MAIN.InputMapping->CurrentPage==dp){ laRackPage* adp=dp->Item.pNext?dp->Item.pNext:dp->Item.pPrev; memAssignRef(MAIN.InputMapping,&MAIN.InputMapping->CurrentPage,adp); }laNotifyInstanceUsers(dp); lstRemoveItem(&MAIN.InputMapping->Pages, dp); memLeave(dp); laNotifyInstanceUsers(MAIN.InputMapping); laRecordAndPush(a->This,"","Remove input mapping page", 0); return LA_FINISHED; } laEnableOperatorPanel(a,a->This,e->x,e->y,200,200,0,0,0,0,0,0,0,0,e); return LA_RUNNING; } void laui_RemoveInputMappingPage(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){ laColumn* c=laFirstColumn(uil); laShowItemFull(uil,c,This,"remove_input_mapping_page",0,"confirm=true;text=Confirm",0,0); } laBaseNode* la_CreateNode(laNodeRack* ir, laBaseNodeType* NodeType){ laBaseNode* bn=memAcquire(NodeType->NodeSize); bn->Type=NodeType; NodeType->Init(bn, 0); bn->InitDone=1; lstAppendItem(&ir->Nodes, bn); bn->InRack=ir; laNotifyInstanceUsers(ir); laRecordInstanceDifferences(ir,"la_node_rack"); laPushDifferences("Add Node", 0); return bn; } int OPINV_AddNode(laOperator* a, laEvent *e){ laNodeRack* ir=a->This?a->This->EndInstance:0; if(!ir) return LA_CANCELED; laBaseNodeType* bnt=0; if(!MAIN.CurrentNodeCategory) MAIN.CurrentNodeCategory=MAIN.NodeCategories.pFirst; char* target=strGetArgumentString(a->ExtraInstructionsP,"target"); int ti=0; if(target) sscanf(target,"%d",&ti); if((!target) || ti==0){ MAIN.FilterNodeCategory=LA_RACK_TYPE_INPUT; } else{ MAIN.FilterNodeCategory=ti; } char* type=strGetArgumentString(a->ExtraInstructionsP,"type"); 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; } else{ for(int i=0;iTypeName,type)){ la_CreateNode(ir, MAIN.NodeTypes[i]); } } } return LA_FINISHED; } int OPMOD_AddNode(laOperator* a, laEvent *e){ laNodeRack* r=a->This->EndInstance; if(a->ConfirmData){ if(a->ConfirmData->StrData){ for(int i=0;iTypeName,a->ConfirmData->StrData)){ la_CreateNode(r, MAIN.NodeTypes[i]); break; } } } return LA_FINISHED; } return LA_RUNNING; } void laui_AddNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){ laColumn* c=laFirstColumn(uil),*cl,*cr; laSplitColumn(uil,c,0.4); cl=laLeftColumn(c,4); cr=laRightColumn(c,0); laShowItemFull(uil,cl,0,"la.node_categories",LA_WIDGET_COLLECTION,"feedback=NONE;",0,0); 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; laShowItemFull(gu,gc,0,"la.node_categories",LA_WIDGET_COLLECTION_SINGLE,0,laui_NodeCategory,0)->Flags|=LA_UI_FLAGS_NO_DECAL; } int OPINV_MoveNodeToRack(laOperator* a, laEvent *e){ laBaseNode* n=a->This?a->This->EndInstance:0; if(!n||!n->InRack) return LA_CANCELED; laBaseNodeType* bnt=0; laNodeRack* target; char* direction=strGetArgumentString(a->ExtraInstructionsP,"direction"); if(strSame(direction,"left")) target=n->InRack->Item.pPrev; else target=n->InRack->Item.pNext; if(!target) return LA_CANCELED; lstRemoveItem(&n->InRack->Nodes, n); lstAppendItem(&target->Nodes,n); n->InRack=target; laNotifyInstanceUsers(n->InRack->ParentPage); laRecordInstanceDifferences(n->InRack->ParentPage,"la_node_page"); laPushDifferences("Move Node", 0); return LA_FINISHED; } int OPINV_DeleteNode(laOperator* a, laEvent *e){ laBaseNode* n=a->This?a->This->EndInstance:0; if(!n||!n->InRack) return LA_CANCELED; laBaseNodeType* bnt=0; laNodeRack* target; laNodeRack* parent=n->InRack; lstRemoveItem(&n->InRack->Nodes, n); n->Type->Destroy(n); memLeave(n); laGraphRequestRebuild(); laNotifyInstanceUsers(parent); laRecordInstanceDifferences(parent,"la_node_rack"); laPushDifferences("Delete Node", 0); return LA_FINISHED; } int OPINV_MoveRack(laOperator* a, laEvent *e){ laNodeRack* r=a->This?a->This->EndInstance:0; if(!r) return LA_CANCELED; char* direction=strGetArgumentString(a->ExtraInstructionsP,"direction"); if(strSame(direction,"left")) lstMoveUp(&r->ParentPage->Racks,r); else lstMoveDown(&r->ParentPage->Racks,r); laNotifyInstanceUsers(r->ParentPage); laRecordInstanceDifferences(r->ParentPage,"la_rack_page"); laPushDifferences("Move Rack", 0); return LA_FINISHED; } int OPINV_InsertRack(laOperator* a, laEvent *e){ laNodeRack* rr=a->This?a->This->EndInstance:0; if(!rr) return LA_CANCELED; laNodeRack* r=memAcquire(sizeof(laNodeRack)); strSafeSet(&r->Name,"New Rack"); lstInsertItemAfter(&rr->ParentPage->Racks,r,rr); r->ParentPage=rr->ParentPage; r->RackType=rr->RackType; laNotifyInstanceUsers(r->ParentPage); laRecordInstanceDifferences(r->ParentPage,"la_rack_page"); laPushDifferences("Insert Rack", 0); return LA_FINISHED; } int OPINV_DeleteRack(laOperator* a, laEvent *e){ laNodeRack* rr=a->This?a->This->EndInstance:0; if(!rr) return LA_CANCELED; if(strSame(strGetArgumentString(a->ExtraInstructionsP,"confirm"),"true")){ laRackPage* page=rr->ParentPage; laDestroyRack(rr); laNotifyInstanceUsers(page); laRecordInstanceDifferences(page,"la_rack_page"); laPushDifferences("Delete Rack", 0); return LA_FINISHED; } laEnableOperatorPanel(a,a->This,e->x,e->y,200,200,0,0,0,0,0,0,0,0,e); return LA_RUNNING; } void laui_DeleteRack(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){ laColumn* c=laFirstColumn(uil); laShowItemFull(uil,c,This,"delete",0,"confirm=true;",0,0); } laPropContainer* laget_BaseNodeType(laBaseNode* bn){ for(int i=0;iType==MAIN.NodeTypes[i]) return MAIN.NodeTypes[i]->pc; } return LA_PC_IDN_GENERIC; } int laget_BaseNodeGap(laNodeRack* rack_unused, laBaseNode* n){ return n->Gap; } void laread_BaseNodeGap(laBaseNode* n, int gap){ n->Gap=gap; } void laset_BaseNodeGap(laBaseNode* n, int gap){ laBaseNode* nn; if(gap==-1){ int done=0; nn=n; while(nn){ if(nn->Gap>0){ nn->Gap--; done=1; break; } nn=nn->Item.pPrev; } if(done){ nn=n->Item.pNext; while(nn){ if(nn->Gap>0){ nn->Gap++; break; } nn=nn->Item.pNext; } } }elif(gap==1){ n->Gap+=gap; nn=n->Item.pNext; while(nn){ if(nn->Gap>0){ nn->Gap--; break; } nn=nn->Item.pNext; } }elif(gap==-2){ if(n->Gap){ n->Gap--; if(nn=n->Item.pNext){ nn->Gap++; } } elif(nn=n->Item.pPrev){ n->Gap=nn->Gap; nn->Gap=0; lstRemoveItem(&n->InRack->Nodes,n); lstInsertItemBefore(&n->InRack->Nodes,n,nn); } }elif(gap==2){ 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++; } } else n->Gap++; } } void laset_InputNodeUserID(laInputControllerNode* n, int i){ laNotifyUsers("la.input_racks"); } void laset_InputControllerNodeSocketWhich(laInputControllerNodeSocket* s, char* str){ strSafeSet(&s->Which, str); laNotifyUsers("la.input_racks"); laGraphRequestRebuild(); } int laget_SocketEnumArrayLength(laInputControllerNodeSocket* s){ return s->Out->ArrLen?s->Out->ArrLen:1; } int laget_VisualizerArrayLength(laInputVisualizerNode* s){ return s->In->ArrLen?s->In->ArrLen:1; } laBoxedTheme* laget_NodeGetTheme(laNodeRack* rack_unused, laBaseNode* n){ return 0; } void laRegisterNode(laBaseNodeType* type, laPropContainer* pc, laBaseNodeInitF init, laBaseNodeDestroyF destroy, laBaseNodeVisitF visit, laBaseNodeEvalF eval, laBaseNodeCopyF copy, int nodesize, char* udf_string, char* type_string, char* UiText, int icon){ arrEnsureLength(&MAIN.NodeTypes, MAIN.NodeTypeNext, &MAIN.NodeTypeMax, sizeof(laBaseNode*)); type->Init = init; type->Destroy = destroy; type->Visit=visit; type->Eval=eval; type->NodeSize=nodesize; type->Copy=copy; type->pc=pc; type->TypeName=type_string;type->Name=UiText;type->Icon=icon; MAIN.NodeTypes[MAIN.NodeTypeNext]=type; MAIN.NodeTypeNext++; la_UDFAppendSharedTypePointer(udf_string, type); } void lapost_Node(laBaseNode *bn){ if(!bn->InitDone){ bn->Type->Init(bn,1); bn->InitDone=1; } } extern laRackPage* DEBUG_READ_RACK_PAGE; void lapost_NodeRack(laNodeRack *rr){ if(!rr->ParentPage){ memAssignRef(rr,&rr->ParentPage,DEBUG_READ_RACK_PAGE); } } void la_AddValuesNodeEnum(laProp* p){ laAddEnumItemAs(p,"FLOAT","Float","Float value",LA_VALUES_NODE_FLOAT,0); laAddEnumItemAs(p,"INT","Int","Int value",LA_VALUES_NODE_INT,0); laAddEnumItemAs(p,"ENUM","Switch","Swich value",LA_VALUES_NODE_ENUM,0); } void la_AddValuesNodeEnumValue(laProp* p){ laAddEnumItemAs(p,"IDLE","Idle","Idle",0,0); laAddEnumItemAs(p,"ACTIVE","Active","Active",1,0); } void la_RegisterInputMapperOperators(){ laPropContainer *pc; laProp *p; laOperatorType *at; laEnumProp *ep; laCreateOperatorType("LA_add_input_mapping_page", "Add Page", "Add a page for inpur mapping", 0,0,0,OPINV_AddInputMapperPage,0,'+',0); laCreateOperatorType("LA_add_rack", "Add Rack", "Add a rack for nodes", 0,0,0,OPINV_AddNodesRack,0,'+',0); at=laCreateOperatorType("OPINV_AddNode", "Add Node", "Add a node to the rack",0,0,0,OPINV_AddNode,OPMOD_AddNode,'+',0); at->UiDefine=laui_AddNode; laCreateOperatorType("LA_input_mapping_rebuild", "Rebuild Input Mapping", "Rebuild input mapping for evaluation",0,0,0,OPINV_RebuildInputMapping,0,U'⭮',0); laCreateOperatorType("LA_move_node_to_rack", "Move Node", "Move node to another rack",0,0,0,OPINV_MoveNodeToRack,0,0,0); laCreateOperatorType("LA_delete_node", "Delete Node", "Delete this node",0,0,0,OPINV_DeleteNode,0,0,0); laCreateOperatorType("LA_move_rack", "Move Rack", "Move this rack",0,0,0,OPINV_MoveRack,0,0,0); laCreateOperatorType("LA_insert_rack", "Insert Rack", "Insert a new rack",0,0,0,OPINV_InsertRack,0,0,0); at=laCreateOperatorType("LA_delete_rack", "Delete Rack", "Delete a rack",0,0,0,OPINV_DeleteRack,OPMOD_FinishOnData,U'❌',0); at->UiDefine=laui_DeleteRack; laCreateOperatorType("LA_remove_input_mapping_page", "Remove Page", "Remove a input mapper page",OPCHK_RemoveInputMappingPage,0,0,OPINV_RemoveInputMappingPage,OPMOD_FinishOnData,L'🗴',0) ->UiDefine=laui_RemoveInputMappingPage; pc=laAddPropertyContainer("la_node_rack", "Input Rack", "Input rack for putting input mapping nodes",0,0,sizeof(laNodeRack),lapost_NodeRack,0,1); laAddStringProperty(pc,"name","Name","Name of this rack",0,0,0,0,1,offsetof(laNodeRack,Name),0,0,0,0,LA_AS_IDENTIFIER); 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); laSubGroupExtraFunctions(p,0,0,laget_NodeGetTheme,laget_BaseNodeGap,0); 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); 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); laAddOperatorProperty(pc,"add_node","Add Node","Add a node into this rack","OPINV_AddNode",'+',0); laAddOperatorProperty(pc,"insert_rack","Insert Rack","Insert a rack","LA_insert_rack",'+',0); laAddOperatorProperty(pc,"move","Move Rack","Move this rack","LA_move_rack",0,0); laAddOperatorProperty(pc,"delete","Delete Rack","Delete this rack","LA_delete_rack",0,0); pc=laAddPropertyContainer("la_base_node", "Input Node", "Input logic node",0,0,sizeof(laBaseNode),0,0,1); LA_PC_IDN_GENERIC=pc; laAddStringProperty(pc,"name","Name","Name of this input node",0,0,0,0,1,offsetof(laBaseNode,Name),0,0,0,0,LA_AS_IDENTIFIER); 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); 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); laAddOperatorProperty(pc,"move","Move","Move node across racks","LA_move_node_to_rack",0,0); laAddOperatorProperty(pc,"delete","Delete","Delete node","LA_delete_node",0,0); 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); pc=laAddPropertyContainer("la_input_controller_node", "Controller output", "Output controller values",0,laui_ControllerNode,sizeof(laInputControllerNode),lapost_Node,0,1); LA_PC_IDN_CONTROLLER=pc; laPropContainerExtraFunctions(pc,0,0,0,0,laui_DefaultNodeOperationsPropUiDefine); laAddSubGroup(pc,"base","Base","Base node","la_base_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); laAddFloatProperty(pc,"axis", "🡘", "Axis value", LA_WIDGET_VALUE_METER,0,0,1,-1,0,0,0,offsetof(laInputControllerNodeSocket,RealVal),0,0,0,0,0,0,0,0,0,0,LA_READ_ONLY|LA_UDF_IGNORE); laAddFloatProperty(pc,"axis2d", "2D Axis", "2D Axis value", LA_WIDGET_VALUE_METER,0,0,1,-1,0,0,0,offsetof(laInputControllerNodeSocket,RealVal),0,0,2,0,0,0,0,0,0,0,LA_READ_ONLY|LA_UDF_IGNORE); 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); laAddEnumItemAs(p,"IDLE", "Idle", "Button is not pressed", 0, 0); laAddEnumItemAs(p,"ACTIVE", "Active", "Button is pressed", 1, 0); 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); pc=laAddPropertyContainer("la_input_visualizer_node", "Visualizer", "Visualizer node",0,laui_InputVisualizeNode,sizeof(laInputVisualizerNode),lapost_Node,0,1); LA_PC_IDN_VISUALIZER=pc; laPropContainerExtraFunctions(pc,0,0,0,0,laui_DefaultNodeOperationsPropUiDefine); laAddSubGroup(pc,"base","Base","Base node","la_base_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL); 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); laAddFloatProperty(pc,"axis", "🡘", "Axis value", LA_WIDGET_VALUE_METER,0,0,1,-1,0,0,0,offsetof(laInputVisualizerNode,RealVal),0,0,0,0,0,0,0,0,0,0,LA_READ_ONLY|LA_UDF_IGNORE); 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); 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); laAddEnumItemAs(p,"IDLE", "Idle", "Button is not pressed", 0, 0); laAddEnumItemAs(p,"ACTIVE", "Active", "Button is pressed", 1, 0); pc=laAddPropertyContainer("la_split_node", "Split", "Split node",0,laui_SplitNode,sizeof(laSplitNode),0,0,1); LA_PC_IDN_SPLIT=pc; laPropContainerExtraFunctions(pc,0,0,0,0,laui_DefaultNodeOperationsPropUiDefine); laAddSubGroup(pc,"base","Base","Base node","la_base_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); pc=laAddPropertyContainer("la_switch_node", "Switch", "Switch node",0,laui_SwitchNode,sizeof(laSwitchNode),0,0,1); LA_PC_IDN_SWITCH=pc; laPropContainerExtraFunctions(pc,0,0,0,0,laui_DefaultNodeOperationsPropUiDefine); laAddSubGroup(pc,"base","Base","Base node","la_base_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); pc=laAddPropertyContainer("la_switch_node_in_socket", "Switch In", "Input of many values",0,0,sizeof(laSwitchNodeInSocket),0,0,1|LA_PROP_OTHER_ALLOC); 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); pc=laAddPropertyContainer("la_combine_node", "Combine", "Combine node",0,laui_CombineNode,sizeof(laCombineNode),0,0,1); LA_PC_IDN_COMBINE=pc; laPropContainerExtraFunctions(pc,0,0,0,0,laui_DefaultNodeOperationsPropUiDefine); laAddSubGroup(pc,"base","Base","Base node","la_base_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); pc=laAddPropertyContainer("la_values_node", "Values", "Values node",0,laui_ValuesNode,sizeof(laValuesNode),lapost_Node,0,1); LA_PC_IDN_VALUES=pc; laPropContainerExtraFunctions(pc,0,0,0,0,laui_DefaultNodeOperationsPropUiDefine); laAddSubGroup(pc,"base","Base","Base node","la_base_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); pc=laAddPropertyContainer("la_matrix_node", "Matrix", "Matrix node",0,laui_MatrixNode,sizeof(laMatrixNode),lapost_Node,0,1); LA_PC_IDN_MATRIX=pc; laPropContainerExtraFunctions(pc,0,0,0,0,laui_DefaultNodeOperationsPropUiDefine); laAddSubGroup(pc,"base","Base","Base node","la_base_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL); 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); 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); 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); p=laAddEnumProperty(pc,"operation", "Operation", "Operation", 0,0,0,0,0,offsetof(laMatrixNode,Operation),0,0,0,0,0,0,0,0,0,0); laAddEnumItemAs(p,"MUL", "Multiply", "L x R", LA_MATRIX_NODE_OP_MUL, 0); laAddEnumItemAs(p,"INV", "Invert", "Invert L or R", LA_MATRIX_NODE_OP_INV, 0); #define REGISTER_MATH_NODE \ laPropContainerExtraFunctions(pc,0,0,0,0,laui_DefaultNodeOperationsPropUiDefine); \ laAddSubGroup(pc,"base","Base","Base node","la_base_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);\ 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);\ 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);\ 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);\ 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);\ 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);\ 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);\ p=laAddEnumProperty(pc,"operation", "Operation", "Operation", 0,0,0,0,0,offsetof(laMathNode, Operation),0,0,0,0,0,0,0,0,0,0);\ laAddEnumItemAs(p,"ADD", "Add", "L + R", LA_MATH_NODE_OP_ADD, 0);\ laAddEnumItemAs(p,"SUB", "Subtract", "L - R", LA_MATH_NODE_OP_SUB, 0);\ laAddEnumItemAs(p,"MUL", "Multiply", "L x R", LA_MATH_NODE_OP_MUL, 0);\ laAddEnumItemAs(p,"DIV", "Divide", "L / R", LA_MATH_NODE_OP_DIV, 0);\ laAddEnumItemAs(p,"POW", "Power", "pow(L,R)", LA_MATH_NODE_OP_POW, 0);\ laAddEnumItemAs(p,"LOG", "Log", "log(L)base(R)", LA_MATH_NODE_OP_LOG, 0);\ laAddEnumItemAs(p,"SIN", "Sine", "sin(L)", LA_MATH_NODE_OP_SIN, 0);\ laAddEnumItemAs(p,"COS", "Cosine", "cos(L)", LA_MATH_NODE_OP_COS, 0);\ laAddEnumItemAs(p,"TAN", "Tangent", "tan(L)", LA_MATH_NODE_OP_TAN, 0);\ laAddEnumItemAs(p,"ASIN", "Arcsin", "asin(L)", LA_MATH_NODE_OP_ASIN, 0);\ laAddEnumItemAs(p,"ACOS", "Arccosine", "acos(L)", LA_MATH_NODE_OP_ACOS, 0);\ laAddEnumItemAs(p,"ATAN", "Arctangent", "atan(L)", LA_MATH_NODE_OP_ATAN, 0);\ laAddEnumItemAs(p,"ATAN2", "Atan2", "atan2(L,R) where L or R can be zero", LA_MATH_NODE_OP_ATAN2, 0);\ laAddEnumItemAs(p,"MOD", "Mod", "L \% R", LA_MATH_NODE_OP_MOD, 0); 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 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 pc=laAddPropertyContainer("la_mapper_node", "Mapper", "Mapper node",0,laui_MapperNode,sizeof(laMapperNode),lapost_Node,0,1); LA_PC_IDN_MAPPER=pc; laPropContainerExtraFunctions(pc,0,0,0,0,laui_DefaultNodeOperationsPropUiDefine); laAddSubGroup(pc,"base","Base","Base node","la_base_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL); 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); 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); 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); 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); 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); 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); 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); 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); laAddEnumItemAs(p,"NONE", "None", "Don't clamp", 0, 0); laAddEnumItemAs(p,"CLAMP", "Clamp", "Clamp to specified range", 1, 0); 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); laAddEnumItemAs(p,"NONE", "None", "Don't clamp", 0, 0); laAddEnumItemAs(p,"CLAMP", "Clamp", "Clamp to specified range", 1, 0); pc=laAddPropertyContainer("la_random_node", "Random", "Random node",0,laui_RandomNode,sizeof(laRandomNode),lapost_Node,0,1); LA_PC_IDN_RANDOM=pc; laPropContainerExtraFunctions(pc,0,0,0,0,laui_DefaultNodeOperationsPropUiDefine); laAddSubGroup(pc,"base","Base","Base node","la_base_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL); 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); 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); 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); 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); pc=laAddPropertyContainer("la_vector_math_node", "Vector Math", "Math node",0,laui_VectorMathNode,sizeof(laVectorMathNode),lapost_Node,0,1); LA_PC_IDN_VECTOR_MATH=pc; laPropContainerExtraFunctions(pc,0,0,0,0,laui_DefaultNodeOperationsPropUiDefine); laAddSubGroup(pc,"base","Base","Base node","la_base_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL); 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); 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); 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); p=laAddEnumProperty(pc,"operation", "Operation", "Operation", 0,0,0,0,0,offsetof(laVectorMathNode, Operation),0,0,0,0,0,0,0,0,0,0); laAddEnumItemAs(p,"ADD", "Add", "L + R", LA_VECTOR_MATH_OP_ADD, 0); laAddEnumItemAs(p,"SUB", "Subtract", "L - R", LA_VECTOR_MATH_OP_SUB, 0); laAddEnumItemAs(p,"MUL", "Multiply (component)", "L x R (component)", LA_VECTOR_MATH_OP_MUL, 0); laAddEnumItemAs(p,"DIV", "Divide (component)", "L / R (component)", LA_VECTOR_MATH_OP_DIV, 0); laAddEnumItemAs(p,"CROSS", "Cross", "L x R", LA_VECTOR_MATH_OP_CROSS, 0); laAddEnumItemAs(p,"DOT", "Dot", "L . R", LA_VECTOR_MATH_OP_DOT, 0); laAddEnumItemAs(p,"POW", "Power", "pow(L,R)", LA_VECTOR_MATH_OP_POW, 0); laAddEnumItemAs(p,"LOG", "Log", "log(L)base(R)", LA_VECTOR_MATH_OP_LOG, 0); laAddEnumItemAs(p,"LEN", "Length", "Length(L)", LA_VECTOR_MATH_OP_LEN, 0); laAddEnumItemAs(p,"NORM", "Normalize", "Normalize(L)", LA_VECTOR_MATH_OP_NORMALIZE, 0); pc=laAddPropertyContainer("la_comment_node", "Comment", "Comment",0,laui_CommentNode,sizeof(laCommentNode),lapost_Node,0,1); LA_PC_IDN_COMMENT=pc; laPropContainerExtraFunctions(pc,0,0,0,0,laui_DefaultNodeOperationsPropUiDefine); laAddSubGroup(pc,"base","Base","Base node","la_base_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL); laAddStringProperty(pc,"content","Content","Content of the comment",LA_WIDGET_STRING_MULTI,0,0,0,1,offsetof(laCommentNode,Content),0,0,0,0,0); pc=laAddPropertyContainer("la_rgb_to_okhsl_node", "RGB 2 OKHSL", "RGB color to OKHSL values",0,laui_RGB2OKHSLNode,sizeof(laRGB2OKHSLNode),lapost_Node,0,1); LA_PC_IDN_RGB2OKHSL=pc; laPropContainerExtraFunctions(pc,0,0,0,0,laui_DefaultNodeOperationsPropUiDefine); laAddSubGroup(pc,"base","Base","Base node","la_base_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL); 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); 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); 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); 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); 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); pc=laAddPropertyContainer("la_okhsl_to_rgb_node", "OKHSL 2 RGB", "OKHSL values to RGB color",0,laui_OKHSL2RGBNode,sizeof(laOKHSL2RGBNode),lapost_Node,0,1); LA_PC_IDN_OKHSL2RGB=pc; laPropContainerExtraFunctions(pc,0,0,0,0,laui_DefaultNodeOperationsPropUiDefine); laAddSubGroup(pc,"base","Base","Base node","la_base_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL); 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); 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); 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); 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); pc=laAddPropertyContainer("la_loop_node", "Loop", "Repeat a series of operations for a few times",0,laui_LoopNode,sizeof(laLoopNode),lapost_Node,0,1); LA_PC_IDN_LOOP=pc; laPropContainerExtraFunctions(pc,0,0,0,0,laui_DefaultNodeOperationsPropUiDefine); laAddSubGroup(pc,"base","Base","Base node","la_base_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL); 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); 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); 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); 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); 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); 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); pc=laAddPropertyContainer("la_loop_index_node", "Loop Index", "Index reference of the loop node",0,laui_LoopIndexNode,sizeof(laLoopIndexNode),lapost_Node,0,1); LA_PC_IDN_LOOP_INDEX=pc; laPropContainerExtraFunctions(pc,0,0,0,0,laui_DefaultNodeOperationsPropUiDefine); laAddSubGroup(pc,"base","Base","Base node","la_base_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL); 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); typedef laMathNode laSmallMathNode; LA_IDN_REGISTER("Controller",U'🕹',LA_IDN_CONTROLLER,LA_PC_IDN_CONTROLLER, IDN_Controller, laInputControllerNode); LA_IDN_REGISTER("Visualizer",U'🔍',LA_IDN_VISUALIZER,LA_PC_IDN_VISUALIZER, IDN_InputVisualizer, laInputVisualizerNode); LA_IDN_REGISTER("Split",U'⚟',LA_IDN_SPLIT,LA_PC_IDN_SPLIT, IDN_Split, laSplitNode); LA_IDN_REGISTER("Switch",U'🚦',LA_IDN_SWITCH,LA_PC_IDN_SWITCH, IDN_Switch, laSwitchNode); LA_IDN_REGISTER("Combine",U'⚞',LA_IDN_COMBINE,LA_PC_IDN_COMBINE, IDN_Combine, laCombineNode); LA_IDN_REGISTER("Values",0,LA_IDN_VALUES,LA_PC_IDN_VALUES, IDN_Values, laValuesNode); LA_IDN_REGISTER("Matrix",0,LA_IDN_MATRIX,LA_PC_IDN_MATRIX, IDN_Matrix, laMatrixNode); LA_IDN_REGISTER("Math",0,LA_IDN_MATH,LA_PC_IDN_MATH, IDN_Math, laMathNode); LA_IDN_REGISTER("Small Math",0,LA_IDN_SMALL_MATH,LA_PC_IDN_SMALL_MATH, IDN_Math, laSmallMathNode); LA_IDN_REGISTER("Mapper",0,LA_IDN_MAPPER,LA_PC_IDN_MAPPER, IDN_Mapper, laMapperNode); LA_IDN_REGISTER("Random",0,LA_IDN_RANDOM,LA_PC_IDN_RANDOM, IDN_Random, laRandomNode); LA_IDN_REGISTER("Vector Math",0,LA_IDN_VECTOR_MATH,LA_PC_IDN_VECTOR_MATH, IDN_VectorMath, laVectorMathNode); LA_IDN_REGISTER("Comment",0,LA_IDN_COMMENT,LA_PC_IDN_COMMENT, IDN_Comment, laCommentNode); LA_IDN_REGISTER("RGB to OKHSL",0,LA_IDN_RGB2OKHSL,LA_PC_IDN_RGB2OKHSL, IDN_RGB2OKHSL, laRGB2OKHSLNode); LA_IDN_REGISTER("OKHSL to RGB",0,LA_IDN_OKHSL2RGB,LA_PC_IDN_OKHSL2RGB, IDN_OKHSL2RGB, laOKHSL2RGBNode); LA_IDN_REGISTER("Loop",0,LA_IDN_LOOP,LA_PC_IDN_LOOP, IDN_Loop, laLoopNode); LA_IDN_REGISTER("Loop Index",0,LA_IDN_LOOP_INDEX,LA_PC_IDN_LOOP_INDEX, IDN_LoopIndex, laLoopIndexNode); LA_NODE_CATEGORY_INPUT=laAddNodeCategory("Input",0,LA_RACK_TYPE_INPUT); LA_NODE_CATEGORY_MATH=laAddNodeCategory("Math",0,LA_RACK_TYPE_ALL); LA_NODE_CATEGORY_COLOR=laAddNodeCategory("Color",0,LA_RACK_TYPE_ALL); LA_NODE_CATEGORY_ROUTE=laAddNodeCategory("Route",0,LA_RACK_TYPE_ALL); LA_NODE_CATEGORY_AUX=laAddNodeCategory("Auxiliary",0,LA_RACK_TYPE_ALL); laNodeCategoryAddNodeTypes(LA_NODE_CATEGORY_INPUT, &LA_IDN_CONTROLLER,0); 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); laNodeCategoryAddNodeTypes(LA_NODE_CATEGORY_ROUTE, &LA_IDN_SPLIT, &LA_IDN_SWITCH, &LA_IDN_COMBINE, &LA_IDN_LOOP, &LA_IDN_LOOP_INDEX,0); laNodeCategoryAddNodeTypes(LA_NODE_CATEGORY_AUX, &LA_IDN_COMMENT, &LA_IDN_VISUALIZER,0); laNodeCategoryAddNodeTypes(LA_NODE_CATEGORY_COLOR, &LA_IDN_RGB2OKHSL, &LA_IDN_OKHSL2RGB,0); MAIN.tNodeIn=laCreateInSocket("TIN",0); MAIN.tNodeOut=laCreateOutSocket(0,"TOUT",0); } void laGraphRequestRebuild(){ MAIN.GraphNeedsRebuild=1; } void laMappingRequestEval(){ MAIN.InputNeedsEval=1; } int __DEBUG_PAGE_EVAL__=0; void la_PageClearBranch(laRackPage* rp, int mask){ for(laListItemPointer*lip=rp->Eval.pFirst;lip;lip=lip->pNext){ laBaseNode* n=lip->p; if(!n->InitDone){ n->Type->Init(n,1); n->InitDone=1; } if(n->Branch&mask){ n->EvalMagic=0; } } } int laRebuildPageEval(laRackPage* rp){ if(!rp)return LA_DAG_FLAG_PERM; while(lstPopPointer(&rp->Eval)); while(lstPopPointer(&rp->AlwaysBranchers)); laListHandle pending={0}; for(laNodeRack* ir=rp->Racks.pFirst;ir;ir=ir->Item.pNext){ for(laBaseNode*bn=ir->Nodes.pFirst;bn;bn=bn->Item.pNext){ if(!bn->InitDone){ bn->Type->Init(bn,1); bn->InitDone=1; } lstAppendPointer(&pending,bn); bn->Branch=0; bn->BranchTemp=0; } } laBaseNode*n; int result=LA_DAG_FLAG_PERM; laListItemPointer*NextLip; laNodeVisitInfo vi; vi.Branch=1; vi.NextBranch=2; vi.l=&rp->Eval; vi.br=&rp->AlwaysBranchers; vi.Page=rp; for(laListItemPointer*lip=pending.pFirst;lip;lip=NextLip){ n=lip->p; NextLip=lip->pNext; if(n->Branch & 1) continue; result=n->Type->Visit(n,&vi); if(result==LA_DAG_FLAG_ERR){ while(lstPopPointer(&pending)); break; } } if(result==LA_DAG_FLAG_ERR){ while(lstPopPointer(&rp->Eval)); while(lstPopPointer(&rp->AlwaysBranchers)); return LA_DAG_FLAG_ERR; } return LA_DAG_FLAG_PERM; } int laRunPage(laRackPage* rp, uint64_t mask){ static uint64_t magic=3; if(!magic){ magic=3; } if(!rp || (!rp->Eval.pFirst && !rp->AlwaysBranchers.pFirst)) return 0; if(__DEBUG_PAGE_EVAL__ && mask==1){ printf("Page eval %s\n",(rp->Name&&rp->Name->Ptr)?rp->Name->Ptr:""); } if(mask==1){ for(laListItemPointer*lip=rp->AlwaysBranchers.pFirst;lip;lip=lip->pNext){ laBaseNode* n=lip->p; if(!n->InitDone){ n->Type->Init(n,1); n->InitDone=1; } if(n->EvalMagic==magic) continue; if(__DEBUG_PAGE_EVAL__){ printf(" BR %.6x\n",n); } n->EvalMagic=magic; n->Type->Eval(n); } } for(laListItemPointer*lip=rp->Eval.pFirst;lip;lip=lip->pNext){ laBaseNode* n=lip->p; if(!n->InitDone){ n->Type->Init(n,1); n->InitDone=1; } if((!(n->Branch&mask)) || (mask==1&&n->Branch!=1) || n->EvalMagic==magic) continue; if(__DEBUG_PAGE_EVAL__){ printf(" -- %d %s %.6x\n",mask,n->Type->Name,n); } n->EvalMagic=magic; n->Type->Eval(n); } if(__DEBUG_PAGE_EVAL__ && mask==1){ printf("End\n"); } if(mask==1){ magic++; } return 1; } int la_RunInputMapping(){ MAIN.InputNeedsEval = 0; return laRunPage(MAIN.InputMapping->CurrentPage, 1); } int la_RebuildInputMapping(){ return laRebuildPageEval(MAIN.InputMapping->CurrentPage); } //================================================================================================== laNodeOutSocket* laCreateOutSocket(void* NodeParentOptional, char* label, int DataType){ laNodeOutSocket* os=memAcquire(sizeof(laNodeOutSocket)); strSafeSet(&os->Label, label); os->DataType = DataType; os->Parent=NodeParentOptional; return os; } laNodeInSocket* laCreateInSocket(char* label, int DataType){ laNodeInSocket* is=memAcquire(sizeof(laNodeInSocket)); strSafeSet(&is->Label, label); is->DataType = DataType; return is; } void laDestroyInSocket(laNodeInSocket* s){ strSafeDestroy(&s->Label); memLeave(s); } void laDestroyOutSocket(laNodeOutSocket* s){ strSafeDestroy(&s->Label); memLeave(s); } laNodeCategory* laAddNodeCategory(char* Name,laUiDefineFunc* Ui,int ForRackTypes){ laNodeCategory* nc=memAcquire(sizeof(laNodeCategory)); lstAppendItem(&MAIN.NodeCategories,nc); strSafeSet(&nc->Name, Name); nc->Ui=Ui; nc->For=ForRackTypes; return nc; } void laNodeCategoryAddNodeTypes(laNodeCategory* nc, ...){ va_list list; va_start(list,nc); laBaseNodeType* nt; while(nt=va_arg(list,laBaseNodeType*)){ lstAppendPointer(&nc->NodeTypes, nt); } va_end(list); } void laDestroyRack(laNodeRack* rr){ laBaseNode* n; while(n=lstPopItem(&rr->Nodes)){ n->Type->Destroy(n); memLeave(n); } laRackPage* page=rr->ParentPage; strSafeDestroy(&rr->Name); lstRemoveItem(&rr->ParentPage->Racks, rr); memLeave(rr); } laRackPage* laDuplicateRackPage(laRackPage* new_optional, laRackPage* from){ laRackPage* nr=new_optional?new_optional:memAcquire(sizeof(laRackPage)); strSafeSet(&nr->Name,from->Name?from->Name->Ptr:0); strSafeSet(&nr->Script,nr->Script?from->Script->Ptr:0); nr->TriggerMode=from->TriggerMode; nr->UseScript=from->UseScript; nr->RackType=from->RackType; for(laNodeRack* r=from->Racks.pFirst;r;r=r->Item.pNext){ laNodeRack* nnr=memAcquire(sizeof(laNodeRack)); r->Duplicated=nnr; lstAppendItem(&nr->Racks, nnr); strSafeSet(&nnr->Name,r->Name?r->Name->Ptr:0); nnr->ParentPage=nr; nnr->RackType=r->RackType; for(laBaseNode* n=r->Nodes.pFirst;n;n=n->Item.pNext){ laBaseNode* nn=memAcquire(n->Type->NodeSize); nn->Type=n->Type; nn->InitDone=1; lstAppendItem(&nnr->Nodes, nn); nn->InRack=nnr; n->Duplicated=nn; nn->Type->Init(nn, 0); nn->Type->Copy(nn,n,0); } } for(laNodeRack* r=from->Racks.pFirst;r;r=r->Item.pNext){ for(laBaseNode* n=r->Nodes.pFirst;n;n=n->Item.pNext){ n->Type->Copy(n->Duplicated,n,1); } } return nr; }