*/}}

ournodes.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. #include "ourpaint.h"
  2. extern LA MAIN;
  3. extern tnsMain* T;
  4. extern OurPaint *Our;
  5. laBaseNodeType OUR_IDN_BRUSH_SETTINGS;
  6. laBaseNodeType OUR_IDN_BRUSH_OUTPUTS;
  7. laBaseNodeType OUR_IDN_BRUSH_DEVICE;
  8. laPropContainer* OUR_PC_IDN_BRUSH_SETTINGS;
  9. laPropContainer* OUR_PC_IDN_BRUSH_OUTPUTS;
  10. laPropContainer* OUR_PC_IDN_BRUSH_DEVICE;
  11. void IDN_BrushSettingsInit(OurBrushSettingsNode* n){
  12. n->CanvasScale=laCreateOutSocket(n,"Canvas Scale",LA_PROP_FLOAT); n->CanvasScale->Data=&n->rCanvasScale;
  13. n->Size=laCreateOutSocket(n,"Size",LA_PROP_FLOAT); n->Size->Data=&n->rSize;
  14. n->Transparency=laCreateOutSocket(n,"Transparency",LA_PROP_FLOAT); n->Transparency->Data=&n->rTransparency;
  15. n->Hardness=laCreateOutSocket(n,"Hardness",LA_PROP_FLOAT); n->Hardness->Data=&n->rHardness;
  16. n->Smudge=laCreateOutSocket(n,"Smudge",LA_PROP_FLOAT); n->Smudge->Data=&n->rSmudge;
  17. n->SmudgeLength=laCreateOutSocket(n,"Smudge Length",LA_PROP_FLOAT); n->SmudgeLength->Data=&n->rSmudgeLength;
  18. n->DabsPerSize=laCreateOutSocket(n,"Dabs Per Size",LA_PROP_FLOAT); n->DabsPerSize->Data=&n->rDabsPerSize;
  19. n->Slender=laCreateOutSocket(n,"Slender",LA_PROP_FLOAT); n->Slender->Data=&n->rSlender;
  20. n->Angle=laCreateOutSocket(n,"Angle",LA_PROP_FLOAT); n->Angle->Data=&n->rAngle;
  21. strSafeSet(&n->Base.Name, "Brush Settings");
  22. }
  23. void IDN_BrushSettingsDestroy(OurBrushSettingsNode* n){
  24. laDestroyOutSocket(n->Size); laDestroyOutSocket(n->Transparency); laDestroyOutSocket(n->Hardness); laDestroyOutSocket(n->Smudge);
  25. laDestroyOutSocket(n->SmudgeLength); laDestroyOutSocket(n->DabsPerSize); laDestroyOutSocket(n->Slender); laDestroyOutSocket(n->Angle);
  26. laDestroyOutSocket(n->CanvasScale); strSafeDestroy(&n->Base.Name);
  27. }
  28. int IDN_BrushSettingsVisit(OurBrushSettingsNode* n, laListHandle* l){
  29. LA_GUARD_THIS_NODE(n); n->Base.Eval=LA_DAG_FLAG_PERM; lstAppendPointer(l, n);
  30. return LA_DAG_FLAG_PERM;
  31. }
  32. int IDN_BrushSettingsEval(OurBrushSettingsNode* n){
  33. if(!Our->CurrentBrush){ return 0; } // unlikely;
  34. n->rCanvasScale = Our->CurrentScale;
  35. n->rSize = Our->CurrentBrush->Size;
  36. n->rTransparency = Our->CurrentBrush->Transparency;
  37. n->rHardness = Our->CurrentBrush->Hardness;
  38. n->rSmudge = Our->CurrentBrush->Smudge;
  39. n->rSmudgeLength = Our->CurrentBrush->SmudgeResampleLength;
  40. n->rDabsPerSize = Our->CurrentBrush->DabsPerSize;
  41. n->rSlender = Our->CurrentBrush->Slender;
  42. n->rAngle = Our->CurrentBrush->Angle;
  43. return 1;
  44. }
  45. void ui_BrushSettingsNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){
  46. laColumn* c=laFirstColumn(uil); OurBrushSettingsNode*n=This->EndInstance;
  47. laUiItem* b,*u;
  48. LA_BASE_NODE_HEADER(uil,c,This);
  49. b=laBeginRow(uil,c,0,0); u=laShowLabel(uil,c,"Canvas Scale",0,0);u->Flags|=LA_TEXT_ALIGN_RIGHT; u->Expand=1; laShowNodeSocket(uil,c,This,"canvas_scale",0); laEndRow(uil,b);
  50. b=laBeginRow(uil,c,0,0); u=laShowLabel(uil,c,"Size",0,0);u->Flags|=LA_TEXT_ALIGN_RIGHT; u->Expand=1; laShowNodeSocket(uil,c,This,"size",0); laEndRow(uil,b);
  51. b=laBeginRow(uil,c,0,0); u=laShowLabel(uil,c,"Transparency",0,0);u->Flags|=LA_TEXT_ALIGN_RIGHT; u->Expand=1; laShowNodeSocket(uil,c,This,"transparency",0); laEndRow(uil,b);
  52. b=laBeginRow(uil,c,0,0); u=laShowLabel(uil,c,"Hardness",0,0);u->Flags|=LA_TEXT_ALIGN_RIGHT; u->Expand=1; laShowNodeSocket(uil,c,This,"hardness",0); laEndRow(uil,b);
  53. b=laBeginRow(uil,c,0,0); u=laShowLabel(uil,c,"Smudge",0,0);u->Flags|=LA_TEXT_ALIGN_RIGHT; u->Expand=1; laShowNodeSocket(uil,c,This,"smudge",0); laEndRow(uil,b);
  54. b=laBeginRow(uil,c,0,0); u=laShowLabel(uil,c,"Smudge Length",0,0);u->Flags|=LA_TEXT_ALIGN_RIGHT; u->Expand=1; laShowNodeSocket(uil,c,This,"smudge_length",0); laEndRow(uil,b);
  55. b=laBeginRow(uil,c,0,0); u=laShowLabel(uil,c,"Dabs Per Size",0,0);u->Flags|=LA_TEXT_ALIGN_RIGHT; u->Expand=1; laShowNodeSocket(uil,c,This,"dabs_per_size",0); laEndRow(uil,b);
  56. b=laBeginRow(uil,c,0,0); u=laShowLabel(uil,c,"Slender",0,0);u->Flags|=LA_TEXT_ALIGN_RIGHT; u->Expand=1; laShowNodeSocket(uil,c,This,"slender",0); laEndRow(uil,b);
  57. b=laBeginRow(uil,c,0,0); u=laShowLabel(uil,c,"Angle",0,0);u->Flags|=LA_TEXT_ALIGN_RIGHT; u->Expand=1; laShowNodeSocket(uil,c,This,"angle",0); laEndRow(uil,b);
  58. }
  59. void IDN_BrushOutputsInit(OurBrushOutputsNode* n){
  60. n->Position=laCreateInSocket("Position",LA_PROP_FLOAT);
  61. n->Size=laCreateInSocket("Size",LA_PROP_FLOAT);
  62. n->Transparency=laCreateInSocket("Transparency",LA_PROP_FLOAT);
  63. n->Hardness=laCreateInSocket("Hardness",LA_PROP_FLOAT);
  64. n->Smudge=laCreateInSocket("Smudge",LA_PROP_FLOAT);
  65. n->SmudgeLength=laCreateInSocket("Smudge Length",LA_PROP_FLOAT);
  66. n->DabsPerSize=laCreateInSocket("Dabs Per Size",LA_PROP_FLOAT);
  67. n->Slender=laCreateInSocket("Slender",LA_PROP_FLOAT);
  68. n->Angle=laCreateInSocket("Angle",LA_PROP_FLOAT);
  69. strSafeSet(&n->Base.Name, "Brush Outputs");
  70. }
  71. void IDN_BrushOutputsDestroy(OurBrushOutputsNode* n){
  72. laDestroyInSocket(n->Position);
  73. laDestroyInSocket(n->Size); laDestroyInSocket(n->Transparency); laDestroyInSocket(n->Hardness); laDestroyInSocket(n->Smudge);
  74. laDestroyInSocket(n->SmudgeLength); laDestroyInSocket(n->DabsPerSize); laDestroyInSocket(n->Slender); laDestroyInSocket(n->Angle);
  75. strSafeDestroy(&n->Base.Name);
  76. }
  77. int IDN_BrushOutputsVisit(OurBrushOutputsNode* n, laListHandle* l){
  78. LA_GUARD_THIS_NODE(n);
  79. #define BRUSH_OUT_VISIT(a)\
  80. if(LA_SRC_AND_PARENT(n->a)){ laBaseNode*bn=n->a->Source->Parent; LA_VISIT_NODE(bn); }
  81. BRUSH_OUT_VISIT(Position)
  82. BRUSH_OUT_VISIT(Size)
  83. BRUSH_OUT_VISIT(Transparency)
  84. BRUSH_OUT_VISIT(Hardness)
  85. BRUSH_OUT_VISIT(Smudge)
  86. BRUSH_OUT_VISIT(SmudgeLength)
  87. BRUSH_OUT_VISIT(DabsPerSize)
  88. BRUSH_OUT_VISIT(Slender)
  89. BRUSH_OUT_VISIT(Angle)
  90. #undef BRUSH_OUT_VISIT
  91. n->Base.Eval=LA_DAG_FLAG_PERM; lstAppendPointer(l, n);
  92. return LA_DAG_FLAG_PERM;
  93. }
  94. int IDN_BrushOutputsEval(OurBrushOutputsNode* n){
  95. if(!Our->CurrentBrush) return 0;
  96. #define BRUSH_OUT_EVAL(a)\
  97. if(LA_SRC_AND_PARENT(n->a) && (n->a->Source->DataType&LA_PROP_FLOAT)){ Our->CurrentBrush->Eval##a=*((real*)n->a->Source->Data); }
  98. if(LA_SRC_AND_PARENT(n->Position) && (n->Position->Source->DataType&LA_PROP_FLOAT|LA_PROP_ARRAY) && n->Position->Source->ArrLen>=2){
  99. Our->CurrentBrush->EvalPositionOut[0]=((real*)n->Position->Source->Data)[0];
  100. Our->CurrentBrush->EvalPositionOut[1]=((real*)n->Position->Source->Data)[1];
  101. }
  102. BRUSH_OUT_EVAL(Size)
  103. BRUSH_OUT_EVAL(Transparency)
  104. BRUSH_OUT_EVAL(Hardness)
  105. BRUSH_OUT_EVAL(Smudge)
  106. BRUSH_OUT_EVAL(SmudgeLength)
  107. BRUSH_OUT_EVAL(DabsPerSize)
  108. BRUSH_OUT_EVAL(Slender)
  109. BRUSH_OUT_EVAL(Angle)
  110. #undef BRUSH_OUT_EVAL
  111. return 1;
  112. }
  113. void ui_BrushOutputsNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){
  114. laColumn* c=laFirstColumn(uil); OurBrushOutputsNode*n=This->EndInstance;
  115. laUiItem* b,*u;
  116. LA_BASE_NODE_HEADER(uil,c,This);
  117. b=laBeginRow(uil,c,0,0); laShowNodeSocket(uil,c,This,"position",0); laShowLabel(uil,c,"Position",0,0); laEndRow(uil,b);
  118. b=laBeginRow(uil,c,0,0); laShowNodeSocket(uil,c,This,"size",0); laShowLabel(uil,c,"Size",0,0); laEndRow(uil,b);
  119. b=laBeginRow(uil,c,0,0); laShowNodeSocket(uil,c,This,"transparency",0); laShowLabel(uil,c,"Transparency",0,0); laEndRow(uil,b);
  120. b=laBeginRow(uil,c,0,0); laShowNodeSocket(uil,c,This,"hardness",0); laShowLabel(uil,c,"Hardness",0,0); laEndRow(uil,b);
  121. b=laBeginRow(uil,c,0,0); laShowNodeSocket(uil,c,This,"smudge",0); laShowLabel(uil,c,"Smudge",0,0); laEndRow(uil,b);
  122. b=laBeginRow(uil,c,0,0); laShowNodeSocket(uil,c,This,"smudge_length",0); laShowLabel(uil,c,"Smudge Length",0,0); laEndRow(uil,b);
  123. b=laBeginRow(uil,c,0,0); laShowNodeSocket(uil,c,This,"dabs_per_size",0); laShowLabel(uil,c,"Dabs Per Size",0,0); laEndRow(uil,b);
  124. b=laBeginRow(uil,c,0,0); laShowNodeSocket(uil,c,This,"slender",0); laShowLabel(uil,c,"Slender",0,0); laEndRow(uil,b);
  125. b=laBeginRow(uil,c,0,0); laShowNodeSocket(uil,c,This,"angle",0); laShowLabel(uil,c,"Angle",0,0); laEndRow(uil,b);
  126. }
  127. void IDN_BrushDeviceInit(OurBrushDeviceNode* n){
  128. n->Pressure=laCreateOutSocket(n,"Pressure",LA_PROP_FLOAT); n->Pressure->Data=&n->rPressure;
  129. n->Position=laCreateOutSocket(n,"Position",LA_PROP_FLOAT|LA_PROP_ARRAY); n->Position->Data=n->rPosition; n->Position->ArrLen=2;
  130. n->Tilt=laCreateOutSocket(n,"Tilt",LA_PROP_FLOAT|LA_PROP_ARRAY); n->Tilt->Data=n->rTilt; n->Tilt->ArrLen=2;
  131. n->IsEraser=laCreateOutSocket(n,"Is Eraser",LA_PROP_INT); n->IsEraser->Data=&n->rIsEraser;
  132. n->LastPosition=laCreateOutSocket(n,"Last Position",LA_PROP_FLOAT|LA_PROP_ARRAY); n->LastPosition->Data=n->rLastPosition; n->LastPosition->ArrLen=2;
  133. strSafeSet(&n->Base.Name, "Brush Device");
  134. }
  135. void IDN_BrushDeviceDestroy(OurBrushDeviceNode* n){
  136. laDestroyOutSocket(n->Pressure); laDestroyOutSocket(n->Tilt); laDestroyOutSocket(n->Position); laDestroyOutSocket(n->IsEraser); laDestroyOutSocket(n->LastPosition);
  137. strSafeDestroy(&n->Base.Name);
  138. }
  139. int IDN_BrushDeviceVisit(OurBrushDeviceNode* n, laListHandle* l){
  140. LA_GUARD_THIS_NODE(n); n->Base.Eval=LA_DAG_FLAG_PERM; lstAppendPointer(l, n);
  141. return LA_DAG_FLAG_PERM;
  142. }
  143. int IDN_BrushDeviceEval(OurBrushDeviceNode* n){
  144. if(!Our->CurrentBrush){ return 0; } // unlikely;
  145. tnsVectorSet2v(n->rPosition, Our->CurrentBrush->EvalPosition);
  146. tnsVectorSet2(n->rLastPosition, Our->CurrentBrush->LastX, Our->CurrentBrush->LastY); printf("%lf %lf\n",Our->CurrentBrush->LastX, Our->CurrentBrush->LastY);
  147. tnsVectorSet2v(n->rTilt, Our->CurrentBrush->EvalTilt);
  148. n->rIsEraser = Our->CurrentBrush->EvalIsEraser;
  149. n->rPressure = Our->CurrentBrush->EvalPressure;
  150. return 1;
  151. }
  152. void ui_BrushDeviceNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){
  153. laColumn* c=laFirstColumn(uil); OurBrushDeviceNode*n=This->EndInstance;
  154. laUiItem* b,*u;
  155. LA_BASE_NODE_HEADER(uil,c,This);
  156. b=laBeginRow(uil,c,0,0); u=laShowLabel(uil,c,"Position",0,0);u->Flags|=LA_TEXT_ALIGN_RIGHT; u->Expand=1; laShowNodeSocket(uil,c,This,"position",0); laEndRow(uil,b);
  157. b=laBeginRow(uil,c,0,0); u=laShowLabel(uil,c,"Last Position",0,0);u->Flags|=LA_TEXT_ALIGN_RIGHT; u->Expand=1; laShowNodeSocket(uil,c,This,"last_position",0); laEndRow(uil,b);
  158. b=laBeginRow(uil,c,0,0); u=laShowLabel(uil,c,"Pressure",0,0);u->Flags|=LA_TEXT_ALIGN_RIGHT; u->Expand=1; laShowNodeSocket(uil,c,This,"pressure",0); laEndRow(uil,b);
  159. b=laBeginRow(uil,c,0,0); u=laShowLabel(uil,c,"Tilt",0,0);u->Flags|=LA_TEXT_ALIGN_RIGHT; u->Expand=1; laShowNodeSocket(uil,c,This,"tilt",0); laEndRow(uil,b);
  160. b=laBeginRow(uil,c,0,0); u=laShowLabel(uil,c,"Is Eraser",0,0);u->Flags|=LA_TEXT_ALIGN_RIGHT; u->Expand=1;laShowNodeSocket(uil,c,This,"is_eraser",0); laEndRow(uil,b);
  161. }
  162. int ourEvalBrush(){
  163. for(laListItemPointer*lip=Our->BrushEval.pFirst;lip;lip=lip->pNext){ laBaseNode* n=lip->p; n->Type->Eval(n); }
  164. return 1;
  165. }
  166. int ourRebuildBrushEval(){
  167. while(lstPopPointer(&Our->BrushEval));
  168. if(!Our->CurrentBrush || !Our->CurrentBrush->Rack) return LA_DAG_FLAG_PERM;
  169. laListHandle pending={0}; laRackPage* rp=Our->CurrentBrush->Rack; if(!rp)return LA_DAG_FLAG_PERM;
  170. for(laNodeRack* ir=rp->Racks.pFirst;ir;ir=ir->Item.pNext){
  171. for(laBaseNode*bn=ir->Nodes.pFirst;bn;bn=bn->Item.pNext){ lstAppendPointer(&pending,bn); bn->Eval=0; }
  172. }
  173. laBaseNode*n;int result=LA_DAG_FLAG_PERM; laListItemPointer*NextLip;
  174. for(laListItemPointer*lip=pending.pFirst;lip;lip=NextLip){ n=lip->p; NextLip=lip->pNext;
  175. if(n->Eval&LA_DAG_FLAG_PERM) continue;
  176. result=n->Type->Visit(n,&Our->BrushEval); if(result==LA_DAG_FLAG_ERR){ while(lstPopPointer(&pending)); break; }
  177. }
  178. if(result==LA_DAG_FLAG_ERR){ while(lstPopPointer(&MAIN.InputMapping->Eval)); return LA_DAG_FLAG_ERR; }
  179. return LA_DAG_FLAG_PERM;
  180. }
  181. void ourRegisterNodes(){
  182. laPropContainer *pc; laProp *p;
  183. laOperatorType *at;
  184. laEnumProp *ep;
  185. pc=laAddPropertyContainer("our_node_brush_settings", "Brush Settings", "Brush settings node to read from",0,ui_BrushSettingsNode,sizeof(OurBrushSettingsNode),0,0,1);
  186. OUR_PC_IDN_BRUSH_SETTINGS=pc; laPropContainerExtraFunctions(pc,0,0,0,0,laui_DefaultNodeOperationsPropUiDefine);
  187. laAddSubGroup(pc,"base","Base","Base node","la_base_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
  188. laAddSubGroup(pc,"canvas_scale", "Canvas scale","Canvas scale","la_out_socket",0,0,0,offsetof(OurBrushSettingsNode,CanvasScale),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  189. laAddSubGroup(pc,"size", "Size","Size","la_out_socket",0,0,0,offsetof(OurBrushSettingsNode,Size),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  190. laAddSubGroup(pc,"transparency", "Transparency","Transparency","la_out_socket",0,0,0,offsetof(OurBrushSettingsNode,Transparency),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  191. laAddSubGroup(pc,"hardness", "Hardness","Hardness","la_out_socket",0,0,0,offsetof(OurBrushSettingsNode,Hardness),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  192. laAddSubGroup(pc,"smudge", "Smudge","Smudge","la_out_socket",0,0,0,offsetof(OurBrushSettingsNode,Smudge),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  193. laAddSubGroup(pc,"smudge_length", "Smudge Length","Smudge length","la_out_socket",0,0,0,offsetof(OurBrushSettingsNode,SmudgeLength),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  194. laAddSubGroup(pc,"dabs_per_size", "Dabs Per Size","Dabs per size","la_out_socket",0,0,0,offsetof(OurBrushSettingsNode,DabsPerSize),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  195. laAddSubGroup(pc,"slender", "Slender","Slender","la_out_socket",0,0,0,offsetof(OurBrushSettingsNode,Slender),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  196. laAddSubGroup(pc,"angle", "Angle","Angle","la_out_socket",0,0,0,offsetof(OurBrushSettingsNode,Angle),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  197. pc=laAddPropertyContainer("our_node_brush_outputs", "Brush Outputs", "Brush outputs to draw actual dabs",0,ui_BrushOutputsNode,sizeof(OurBrushOutputsNode),0,0,1);
  198. OUR_PC_IDN_BRUSH_OUTPUTS=pc; laPropContainerExtraFunctions(pc,0,0,0,0,laui_DefaultNodeOperationsPropUiDefine);
  199. laAddSubGroup(pc,"base","Base","Base node","la_base_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
  200. laAddSubGroup(pc,"position", "Position","Position","la_in_socket",0,0,0,offsetof(OurBrushOutputsNode,Position),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  201. laAddSubGroup(pc,"size", "Size","Size","la_in_socket",0,0,0,offsetof(OurBrushOutputsNode,Size),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  202. laAddSubGroup(pc,"transparency", "Transparency","Transparency","la_in_socket",0,0,0,offsetof(OurBrushOutputsNode,Transparency),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  203. laAddSubGroup(pc,"hardness", "Hardness","Hardness","la_in_socket",0,0,0,offsetof(OurBrushOutputsNode,Hardness),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  204. laAddSubGroup(pc,"smudge", "Smudge","Smudge","la_in_socket",0,0,0,offsetof(OurBrushOutputsNode,Smudge),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  205. laAddSubGroup(pc,"smudge_length", "Smudge Length","Smudge length","la_in_socket",0,0,0,offsetof(OurBrushOutputsNode,SmudgeLength),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  206. laAddSubGroup(pc,"dabs_per_size", "Dabs Per Size","Dabs per size","la_in_socket",0,0,0,offsetof(OurBrushOutputsNode,DabsPerSize),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  207. laAddSubGroup(pc,"slender", "Slender","Slender","la_in_socket",0,0,0,offsetof(OurBrushOutputsNode,Slender),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  208. laAddSubGroup(pc,"angle", "Angle","Angle","la_in_socket",0,0,0,offsetof(OurBrushOutputsNode,Angle),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  209. pc=laAddPropertyContainer("our_node_brush_device", "Brush Device", "Brush device input",0,ui_BrushDeviceNode,sizeof(OurBrushDeviceNode),0,0,1);
  210. OUR_PC_IDN_BRUSH_DEVICE =pc; laPropContainerExtraFunctions(pc,0,0,0,0,laui_DefaultNodeOperationsPropUiDefine);
  211. laAddSubGroup(pc,"base","Base","Base node","la_base_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
  212. laAddSubGroup(pc,"pressure","Pressure","Pressure of the input","la_out_socket",0,0,0,offsetof(OurBrushDeviceNode,Pressure),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  213. laAddSubGroup(pc,"tilt", "Tilt","Pen tilt vector","la_out_socket",0,0,0,offsetof(OurBrushDeviceNode,Tilt),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  214. laAddSubGroup(pc,"position", "Dab position","Interpolated dab position","la_out_socket",0,0,0,offsetof(OurBrushDeviceNode,Position),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  215. laAddSubGroup(pc,"last_position", "Last position","Position of the previous dab","la_out_socket",0,0,0,offsetof(OurBrushDeviceNode,LastPosition),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  216. laAddSubGroup(pc,"is_eraser", "Is Eraser","Input event is from an eraser","la_out_socket",0,0,0,offsetof(OurBrushDeviceNode,IsEraser),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  217. LA_IDN_REGISTER("Brush Settings",L'🖌',OUR_IDN_BRUSH_SETTINGS,OUR_PC_IDN_BRUSH_SETTINGS, IDN_BrushSettingsInit, IDN_BrushSettingsDestroy, IDN_BrushSettingsVisit, IDN_BrushSettingsEval, OurBrushSettingsNode);
  218. LA_IDN_REGISTER("Brush Outputs",L'🖌',OUR_IDN_BRUSH_OUTPUTS,OUR_PC_IDN_BRUSH_OUTPUTS, IDN_BrushOutputsInit, IDN_BrushOutputsDestroy, IDN_BrushOutputsVisit, IDN_BrushOutputsEval, OurBrushOutputsNode);
  219. LA_IDN_REGISTER("Brush Device",L'🖳',OUR_IDN_BRUSH_DEVICE,OUR_PC_IDN_BRUSH_DEVICE, IDN_BrushDeviceInit, IDN_BrushDeviceDestroy, IDN_BrushDeviceVisit, IDN_BrushDeviceEval, OurBrushDeviceNode);
  220. laNodeCategory* nc=laAddNodeCategory("Our Paint",0,LA_RACK_TYPE_DRIVER);
  221. laNodeCategoryAddNodeTypes(LA_NODE_CATEGORY_DRIVER, &OUR_IDN_BRUSH_OUTPUTS,0);
  222. laNodeCategoryAddNodeTypes(nc, &OUR_IDN_BRUSH_DEVICE, 0);
  223. laNodeCategoryAddNodeTypes(nc, &OUR_IDN_BRUSH_SETTINGS, 0);
  224. }