*/}}

main.c 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691
  1. #include "la_5.h"
  2. extern LA MAIN;
  3. STRUCTURE(Bowl){
  4. laListItem Item;
  5. laSafeString* Name;
  6. laListHandle Fruits;
  7. };
  8. STRUCTURE(Basket){
  9. int pad;
  10. int example;
  11. laSafeString* name;
  12. laListHandle Stuff;
  13. laListHandle Bowls;
  14. };
  15. #define FRUIT_TYPE_APPLE 1
  16. #define FRUIT_TYPE_PEAR 2
  17. STRUCTURE(Fruit){
  18. laListItem Item;
  19. int Type;
  20. Fruit* WhyNot;
  21. laListHandle* Parent;
  22. Bowl* Container;
  23. laListHandle Bundled;
  24. };
  25. STRUCTURE(Apple){
  26. Fruit Base;
  27. real HowSweet;
  28. };
  29. STRUCTURE(Pear){
  30. Fruit Base;
  31. int Really;
  32. };
  33. STRUCTURE(Calculator){
  34. laListHandle Item;
  35. laSafeString* Title;
  36. laSafeString* ResultString;
  37. laListHandle Racks;
  38. };
  39. STRUCTURE(CalculatorCollection){
  40. void* base;
  41. laListHandle Calculators;
  42. Calculator* CurrentCalculator;
  43. };
  44. STRUCTURE(CalcRack){
  45. laListItem Item;
  46. laListHandle Nodes;
  47. };
  48. STRUCTURE(CalcNode){
  49. laListItem Item;
  50. int Type;
  51. int Gap;
  52. laNodeOutSocket* OutA;
  53. };
  54. STRUCTURE(CalcOpNode){
  55. CalcNode Base;
  56. int Operation;
  57. laNodeInSocket* inA; real AVal;
  58. laNodeInSocket* inB; real BVal;
  59. };
  60. STRUCTURE(CalcMixNode){
  61. CalcOpNode Base;
  62. laNodeInSocket* inFactor; real Factor;
  63. };
  64. STRUCTURE(CalcNumberNode){
  65. CalcNode Base;
  66. int Mode; // Integer/Real
  67. int iValue;
  68. real rValue;
  69. };
  70. STRUCTURE(CalcResultNode){
  71. CalcNode Base;
  72. laNodeInSocket* inResult;
  73. };
  74. STRUCTURE(CalcRefNode){
  75. CalcNode Base;
  76. Calculator* Reference;
  77. laNodeInSocket* inResult;
  78. };
  79. #define CALC_NODE_GENERIC 0
  80. #define CALC_NODE_NUMBER 1
  81. #define CALC_NODE_OP 2
  82. #define CALC_NODE_MIX 3
  83. #define CALC_NODE_RESULT 4
  84. #define CALC_NODE_REF 5
  85. #define CALC_OP_ADD 0
  86. #define CALC_OP_SUB 1
  87. #define CALC_OP_MUL 2
  88. #define CALC_OP_DIV 3
  89. Basket B={0};
  90. CalculatorCollection* CC=0;
  91. laPropContainer* pcApple,*pcPear;
  92. laProp* pBasket, *pFruit, *pBowl;
  93. laPropContainer* pcNumber,*pcOp,*pcMix,*pcResult,*pcGeneric,*pcRef;
  94. laTheme* LightTheme, *DarkTheme;
  95. void UiCalcNumberNode(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
  96. laColumn* c=laFirstColumn(uil); laUiItem* b=laBeginRow(uil,c,0,0);
  97. laShowHeightAdjuster(uil,c,This,"base.__gap",0);
  98. laShowItem(uil,c,This,"mode");
  99. laUiItem* b1=laOnConditionThat(uil,c,laEqual(laPropExpression(This,"mode"),laIntExpression(0)));{
  100. laShowItem(uil,c,This,"value_i");
  101. }laElse(uil,b1);{
  102. laShowItem(uil,c,This,"value_r");
  103. }laEndCondition(uil,b1);
  104. laShowSeparator(uil,c)->Expand=1;
  105. laShowNodeSocket(uil,c,This,"base.out_a",0);
  106. laShowLabel(uil,c,"🤙",0,0)->Flags|=LA_TEXT_ALIGN_RIGHT;
  107. laEndRow(uil,b);
  108. }
  109. void UiCalcOpNode(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
  110. laColumn* c=laFirstColumn(uil); laUiItem* b=laBeginRow(uil,c,0,0);
  111. laShowHeightAdjuster(uil,c,This,"base.__gap",0);
  112. laShowNodeSocket(uil,c,This,"in_a",0);
  113. laUiItem* b1=laOnConditionThat(uil,c,laNot(laPropExpression(This,"in_a.source")));{
  114. laShowItem(uil,c,This,"val_a");
  115. }laEndCondition(uil,b1);
  116. laShowNodeSocket(uil,c,This,"in_b",0);
  117. b1=laOnConditionThat(uil,c,laNot(laPropExpression(This,"in_b.source")));{
  118. laShowItem(uil,c,This,"val_b");
  119. }laEndCondition(uil,b1);
  120. laShowItem(uil,c,This,"operation");
  121. laShowSeparator(uil,c)->Expand=1;
  122. laShowNodeSocket(uil,c,This,"base.out_a",0);
  123. laShowLabel(uil,c,"🤔",0,0)->Flags|=LA_TEXT_ALIGN_RIGHT;
  124. laEndRow(uil,b);
  125. }
  126. void UiCalcMixNode(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
  127. laColumn* c=laFirstColumn(uil); laUiItem* b=laBeginRow(uil,c,0,0);
  128. laShowHeightAdjuster(uil,c,This,"base.base.__gap",0);
  129. laShowNodeSocket(uil,c,This,"base.in_a",0);
  130. laUiItem* b1=laOnConditionThat(uil,c,laNot(laPropExpression(This,"base.in_a.source")));{
  131. laShowItem(uil,c,This,"base.val_a");
  132. }laEndCondition(uil,b1);
  133. laShowNodeSocket(uil,c,This,"base.in_b",0);
  134. b1=laOnConditionThat(uil,c,laNot(laPropExpression(This,"base.in_b.source")));{
  135. laShowItem(uil,c,This,"base.val_b");
  136. }laEndCondition(uil,b1);
  137. laShowItem(uil,c,This,"in_factor");
  138. b1=laOnConditionThat(uil,c,laNot(laPropExpression(This,"in_factor.source")));{
  139. laShowItem(uil,c,This,"factor");
  140. }laEndCondition(uil,b1);
  141. laShowSeparator(uil,c)->Expand=1;
  142. laShowNodeSocket(uil,c,This,"base.base.out_a",0);
  143. laShowLabel(uil,c,"🤝",0,0)->Flags|=LA_TEXT_ALIGN_RIGHT;
  144. laEndRow(uil,b);
  145. }
  146. void UiCalcResultNode(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
  147. laColumn* c=laFirstColumn(uil); laUiItem* b=laBeginRow(uil,c,0,0);
  148. laShowHeightAdjuster(uil,c,This,"base.__gap",0);
  149. laShowNodeSocket(uil,c,This,"in_result",0);
  150. laShowSeparator(uil,c)->Expand=1;
  151. laShowLabel(uil,c,"😋",0,0)->Flags|=LA_TEXT_ALIGN_RIGHT;
  152. laEndRow(uil,b);
  153. }
  154. void UiCalcRefNode(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
  155. laColumn* c=laFirstColumn(uil); laUiItem* b=laBeginRow(uil,c,0,0);
  156. laShowHeightAdjuster(uil,c,This,"base.__gap",0);
  157. laShowNodeSocket(uil,c,This,"in_result",0);
  158. laShowSeparator(uil,c)->Expand=1;
  159. laShowLabel(uil,c,"😋",0,0)->Flags|=LA_TEXT_ALIGN_RIGHT;
  160. laEndRow(uil,b);
  161. laShowItemFull(uil,c,This,"ref",LA_WIDGET_COLLECTION_SELECTOR,0,laui_IdentifierOnly,0);
  162. }
  163. void UiRack(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
  164. laColumn* c=laFirstColumn(uil);
  165. laShowItem(uil,c,This,"nodes")->Flags|=LA_UI_FLAGS_NO_DECAL;;
  166. laShowItem(uil,c,This,"add_node");
  167. }
  168. void UiCalculator(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
  169. laColumn* c=laFirstColumn(uil);
  170. laShowItem(uil,c,This,"title");
  171. laUiItem*b=laBeginRow(uil,c,0,0);
  172. laShowItemFull(uil,c,This,"add_rack",0,"position=head;",0,0)->Flags|=LA_UI_FLAGS_ICON;
  173. laUiItem* ui=laShowLabel(uil,c,"Racks",0,0); ui->Flags|=LA_TEXT_ALIGN_CENTER; ui->Expand=1;
  174. laShowItemFull(uil,c,This,"add_rack",0,0,0,0)->Flags|=LA_UI_FLAGS_ICON;
  175. laEndRow(uil,b);
  176. laUiItem* g=laMakeGroup(uil,c,"Racks",0);{ g->Flags|=LA_UI_FLAGS_NO_GAP|LA_UI_FLAGS_NO_DECAL|LA_UI_FLAGS_NODE_CONTAINER;
  177. laUiList* gu=g->Page; laColumn* gc=laFirstColumn(gu); gu->AllowScale=1; gu->HeightCoeff=-3; g->State=LA_UI_ACTIVE;
  178. laUiItem* hui=laShowItem(gu,gc,This,"racks"); hui->Expand=15; hui->Flags|=LA_UI_FLAGS_NO_GAP|LA_UI_FLAGS_NO_DECAL;
  179. }
  180. laShowItem(uil,c,This,"result");
  181. }
  182. void CalcPanel(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
  183. laColumn* c=laFirstColumn(uil); laColumn* cl,*cr; laSplitColumn(uil,c,0.5); cl=laLeftColumn(c,0); cr=laRightColumn(c,0);
  184. laShowItemFull(uil,cl,0,"calc.current",LA_WIDGET_COLLECTION_SELECTOR,0,laui_IdentifierOnly,0);
  185. laShowItem(uil,cr,0,"CALC_add_calculator");
  186. laShowItemFull(uil,c,0,"calc.current",LA_WIDGET_COLLECTION_SINGLE,0,0,0)->Flags|=LA_UI_COLLECTION_NO_HIGHLIGHT;
  187. }
  188. int OPINV_AddCalculator(laOperator* a, laEvent* e){
  189. Calculator* c=memAcquireHyper(sizeof(Calculator));
  190. strSafeSet(&c->Title, "New Calculator");
  191. lstAppendItem(&CC->Calculators,c);
  192. memAssignRef(CC,&CC->CurrentCalculator,c);
  193. laRecordAndPushProp(0, "calc"); laNotifyUsers("calc"); laPrintDBInstInfo();
  194. return LA_FINISHED;
  195. }
  196. int OPINV_AddRack(laOperator* a, laEvent* e){
  197. Calculator* c=a->This?a->This->EndInstance:CC->CurrentCalculator; if(!c) return LA_FINISHED;
  198. CalcRack* cr=memAcquire(sizeof(CalcRack));
  199. if(strSame(strGetArgumentString(a->ExtraInstructionsP,"position"),"head")){ lstPushItem(&c->Racks,cr); }
  200. else lstAppendItem(&c->Racks,cr);
  201. laRecordAndPushProp(0, "calc"); laNotifyUsers("calc"); laPrintDBInstInfo();
  202. return LA_FINISHED;
  203. }
  204. void AddNodesPanel(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
  205. laColumn* c=laFirstColumn(uil);
  206. laShowLabel(uil,c,"Select node type:",0,0);
  207. laShowItemFull(uil,c,0,"LA_confirm",0,"icon=🤙;text=Number;feedback=NUMBER;",0,0);
  208. laShowItemFull(uil,c,0,"LA_confirm",0,"icon=🤔;text=Calculate;feedback=CALC;",0,0);
  209. laShowItemFull(uil,c,0,"LA_confirm",0,"icon=🤝;text=Mix;feedback=MIX;",0,0);
  210. laShowItemFull(uil,c,0,"LA_confirm",0,"icon=😋;text=Result;feedback=RESULT;",0,0);
  211. laShowItemFull(uil,c,0,"LA_confirm",0,"icon=🡬;text=Reference;feedback=REF;",0,0);
  212. }
  213. int OPINV_AddNode_(laOperator* a, laEvent* e){
  214. CalcRack* cr=a->This?a->This->EndInstance:0; if(!cr) return LA_FINISHED;
  215. laEnableOperatorPanel(a, a->This, e->x,e->y,0,0,0,0,0,0,0,0,0,0,e);
  216. return LA_RUNNING;
  217. }
  218. int OPMOD_AddNode_(laOperator* a, laEvent* e){
  219. if(!a->This){ return LA_FINISHED; }
  220. CalcRack* cr=a->This->EndInstance;
  221. if(a->ConfirmData){
  222. char* str; CalcNode* n=0;
  223. if(strSame(a->ConfirmData->StrData, "NUMBER")){
  224. n=memAcquire(sizeof(CalcNumberNode)); CalcNumberNode* cn=n; n->Type=CALC_NODE_NUMBER;
  225. cn->Base.OutA=laCreateOutSocket(cn, "A", 0);
  226. }elif(strSame(a->ConfirmData->StrData, "CALC")){
  227. n=memAcquire(sizeof(CalcOpNode)); CalcOpNode* cn=n; n->Type=CALC_NODE_OP;
  228. cn->Base.OutA=laCreateOutSocket(cn, "Out", 0);
  229. cn->inA=laCreateInSocket("A", 0);
  230. cn->inB=laCreateInSocket("B", 0);
  231. }elif(strSame(a->ConfirmData->StrData, "MIX")){
  232. n=memAcquire(sizeof(CalcMixNode)); CalcMixNode*cn=n; n->Type=CALC_NODE_MIX;
  233. cn->Base.Base.OutA=laCreateOutSocket(cn, "Out", 0);
  234. cn->Base.inA=laCreateInSocket("A", 0);
  235. cn->Base.inB=laCreateInSocket("B", 0);
  236. cn->inFactor=laCreateInSocket("Factor", 0);
  237. }elif(strSame(a->ConfirmData->StrData, "RESULT")){
  238. n=memAcquire(sizeof(CalcResultNode)); CalcResultNode*cn=n; n->Type=CALC_NODE_RESULT;
  239. cn->Base.OutA=laCreateOutSocket(cn, "Out", 0);
  240. cn->inResult=laCreateInSocket("Result", 0);
  241. }elif(strSame(a->ConfirmData->StrData, "REF")){
  242. n=memAcquire(sizeof(CalcRefNode)); CalcRefNode*cn=n; n->Type=CALC_NODE_REF;
  243. cn->Base.OutA=laCreateOutSocket(cn, "Out", 0);
  244. cn->inResult=laCreateInSocket("Result", 0);
  245. }
  246. if(n){
  247. lstAppendItem(&cr->Nodes,n);
  248. laRecordAndPushProp(0, "calc"); laNotifyUsers("calc"); laPrintDBInstInfo();
  249. }
  250. return LA_FINISHED_PASS;
  251. }
  252. return LA_RUNNING;
  253. }
  254. laPropContainer* CalcGetNodeType(CalcNode* n){
  255. switch(n->Type){
  256. case CALC_NODE_NUMBER: return pcNumber;
  257. case CALC_NODE_OP: return pcOp;
  258. case CALC_NODE_MIX: return pcMix;
  259. case CALC_NODE_RESULT: return pcResult;
  260. case CALC_NODE_REF: return pcRef;
  261. default: case CALC_NODE_GENERIC: return pcGeneric;
  262. }
  263. }
  264. void* CalcGetCollection(void* unused,void* unused1){
  265. return CC;
  266. }
  267. void *CalcGetFirstCalculator(void* unusedcc, void* unused){
  268. return CC->Calculators.pFirst;
  269. }
  270. laBoxedTheme* CalcGetTheme(CalcRack* rack_unused, CalcNode* n){
  271. if(n->Type == CALC_NODE_MIX) return (MAIN.CurrentTheme==LightTheme?DarkTheme:LightTheme);
  272. return 0;
  273. }
  274. int CalcGetGap(CalcRack* rack_unused, CalcNode* n){
  275. return n->Gap;
  276. }
  277. void CalcSetGap(CalcNode* n, int gap){
  278. if(gap<0){
  279. int done=0;
  280. CalcNode* nn=n; while(nn){ if(nn->Gap>0){ nn->Gap--; done=1; break; } nn=nn->Item.pPrev; }
  281. if(done){ nn=n->Item.pNext; while(nn){ if(nn->Gap>0){ nn->Gap++; break; } nn=nn->Item.pNext; } }
  282. }
  283. if(gap>0){
  284. n->Gap+=gap;
  285. CalcNode* nn=n->Item.pNext; while(nn){ if(nn->Gap>0){ nn->Gap--; break; } nn=nn->Item.pNext; }
  286. }
  287. }
  288. int RegisterCalculator(){
  289. LightTheme=laGetTheme("Classic Light");
  290. DarkTheme=laGetTheme("Classic Dark");
  291. CC=memAcquire(sizeof(CalculatorCollection));
  292. laRegisterUiTemplate("panel_calc", "Calculator", CalcPanel, 0, 0);
  293. laCreateOperatorType("CALC_add_calculator", "Add Calculator", "Add a calculator", 0,0,0,OPINV_AddCalculator,0,'+',0);
  294. laCreateOperatorType("CALC_add_rack", "Add Rack", "Add a rack into the calculator", 0,0,0,OPINV_AddRack,0,'+',0);
  295. laCreateOperatorType("CALC_add_node", "Add Node", "Add a fruit into the basket or bundle", 0,0,0,OPINV_AddNode_,OPMOD_AddNode_,'+',0)->UiDefine=AddNodesPanel;
  296. laPropContainer* pc=laDefineRoot();
  297. laAddSubGroup(pc, "calc", "Calculator Collections", "The collection of calculators", "calc_collection",0,0,0,-1,CalcGetCollection,0,0,0,0,0,0,LA_UDF_SINGLE|LA_UDF_LOCAL);
  298. laProp*p;
  299. pc=laAddPropertyContainer("calc_collection", "Calculator Collection", "Collection of calculators", 0, CalcPanel, sizeof(CalculatorCollection), 0, 0, 1|LA_UDF_LOCAL|LA_UDF_SINGLE);
  300. laAddSubGroup(pc, "calculators", "Calculators","Calculators","calculator",0,0,0,offsetof(CalculatorCollection, CurrentCalculator),0,0,0,0,0,0,offsetof(CalculatorCollection,Calculators),0);
  301. laAddSubGroup(pc, "current", "Current Calculator","Current calculator","calculator",0,0,0,offsetof(CalculatorCollection,CurrentCalculator),0,0,0,0,0,0,offsetof(CalculatorCollection,Calculators),LA_UDF_REFER);
  302. laAddOperatorProperty(pc,"add_calculator", "Add Calculator", "Add a calculator", "CALC_add_calculator", 0, 0);
  303. pc=laAddPropertyContainer("calculator", "Calculator", "A node-based calculator", 0, UiCalculator, sizeof(Calculator), 0, 0, 2);
  304. laAddStringProperty(pc,"title","Title","Name of the calculator",0,0,0,0,1,offsetof(Calculator,Title),0,0,0,0,LA_AS_IDENTIFIER);
  305. laAddStringProperty(pc,"result","Result","Result produced by the calculator",0,0,0,0,1,offsetof(Calculator,ResultString),0,0,0,0,0);
  306. laAddSubGroup(pc, "racks", "Racks","Node racks of this calculator","calc_rack",0,0,0,-1,0,0,0,0,0,0,offsetof(Calculator,Racks),0);
  307. laAddOperatorProperty(pc,"add_rack", "Add Rack", "Add a rack into the calculator", "CALC_add_rack", 0, 0);
  308. pc=laAddPropertyContainer("calc_rack", "Rack", "A node rack", 0, UiRack, sizeof(CalcRack), 0, 0, 1);
  309. p= laAddSubGroup(pc, "nodes", "Nodes","Nodes on this rack","calc_node",CalcGetNodeType,0,0,-1,0,0,0,0,0,0,offsetof(CalcRack,Nodes),0);
  310. laSubGroupExtraFunctions(p,0,CalcGetTheme,CalcGetGap);
  311. laAddOperatorProperty(pc,"add_node", "Add Node", "Add a node", "CALC_add_node", 0, 0);
  312. pcGeneric=pc=laAddPropertyContainer("calc_node", "Node", "A calculator node", 0, 0, sizeof(CalcNode), 0, 0, 1);
  313. laAddIntProperty(pc,"__gap", "Gap", "Gap of the node", 0,0,0,0,0,0,0,0,offsetof(CalcNode,Gap),0,CalcSetGap,0,0,0,0,0,0,0,0,0);
  314. p=laAddEnumProperty(pc,"type","Type","Type",0,0,0,0,0,offsetof(CalcNode,Type),0,0,0,0,0,0,0,0,0,LA_AS_IDENTIFIER|LA_READ_ONLY);
  315. laAddEnumItemAs(p,"GENERIC","Generic","Generic", CALC_NODE_GENERIC, 0);
  316. laAddEnumItemAs(p,"NUMBER","Number","Number", CALC_NODE_NUMBER, 0);
  317. laAddEnumItemAs(p,"OP","Op","Op", CALC_NODE_OP, 0);
  318. laAddEnumItemAs(p,"MIX","Mix","Mix", CALC_NODE_MIX, 0);
  319. laAddEnumItemAs(p,"RESULT","Result","Result", CALC_NODE_RESULT, 0);
  320. laAddEnumItemAs(p,"REF","Reference","Reference", CALC_NODE_REF, 0);
  321. laAddSubGroup(pc, "out_a", "Out A","Out A","la_out_socket",0,0,0,offsetof(CalcNode,OutA),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  322. pcNumber=pc=laAddPropertyContainer("calc_number_node", "Number Node", "A node that outputs a constant number", 0, UiCalcNumberNode, sizeof(CalcNumberNode), 0, 0, 1);
  323. laAddSubGroup(pc, "base", "Base","Base","calc_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
  324. laAddIntProperty(pc,"value_i", "Int Value", "Integer value", 0,0,0,0,0,0,0,0,offsetof(CalcNumberNode,iValue),0,0,0,0,0,0,0,0,0,0,0);
  325. laAddFloatProperty(pc,"value_r", "Real Value", "Real value", 0,0,0,0,0,0,0,0,offsetof(CalcNumberNode,rValue),0,0,0,0,0,0,0,0,0,0,0);
  326. p=laAddEnumProperty(pc,"mode","Mode","Number mode",0,0,0,0,0,offsetof(CalcNumberNode,Mode),0,0,0,0,0,0,0,0,0,0);
  327. laAddEnumItemAs(p,"INT","Integer","Integer", 0, 0);
  328. laAddEnumItemAs(p,"REAL","Real","Real", 1, 0);
  329. pcOp=pc=laAddPropertyContainer("calc_op_node", "Op Node", "A node that does an operation between two values", 0, UiCalcOpNode, sizeof(CalcOpNode), 0, 0, 1);
  330. laAddSubGroup(pc, "base", "Base","Base","calc_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
  331. p=laAddEnumProperty(pc,"operation","Operation","Operation on two values",0,0,0,0,0,offsetof(CalcOpNode,Operation),0,0,0,0,0,0,0,0,0,0);
  332. laAddEnumItemAs(p,"ADD","Add","A + B", CALC_OP_ADD,0);
  333. laAddEnumItemAs(p,"SUB","Subtract","A - B", CALC_OP_SUB,0);
  334. laAddEnumItemAs(p,"MUL","Multiply","A * B", CALC_OP_MUL,0);
  335. laAddEnumItemAs(p,"DIV","Divide","A / B", CALC_OP_DIV,0);
  336. laAddSubGroup(pc, "in_a", "A","Input value A","la_in_socket",0,0,0,offsetof(CalcOpNode,inA),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  337. laAddSubGroup(pc, "in_b", "B","Input value B","la_in_socket",0,0,0,offsetof(CalcOpNode,inB),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  338. laAddFloatProperty(pc,"val_a", "A", "Internal value A", 0,0,0,0,0,0,0,0,offsetof(CalcOpNode,AVal),0,0,0,0,0,0,0,0,0,0,0);
  339. laAddFloatProperty(pc,"val_b", "B", "Internal value B", 0,0,0,0,0,0,0,0,offsetof(CalcOpNode,BVal),0,0,0,0,0,0,0,0,0,0,0);
  340. pcMix=pc=laAddPropertyContainer("calc_mix_node", "Mix Node", "A node that mixes two values", 0, UiCalcMixNode, sizeof(CalcMixNode), 0, 0, 1);
  341. laAddSubGroup(pc, "base", "Base","Base","calc_op_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
  342. laAddSubGroup(pc, "in_factor", "Factor","Input factor","la_in_socket",0,0,0,offsetof(CalcMixNode,inFactor),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  343. laAddFloatProperty(pc,"factor", "Factor", "Internal factor", 0,0,0,0,0,0,0,0,offsetof(CalcMixNode,Factor),0,0,0,0,0,0,0,0,0,0,0);
  344. pcResult=pc=laAddPropertyContainer("calc_result_node", "Result Node", "A node that records the result", 0, UiCalcResultNode, sizeof(CalcResultNode), 0, 0, 1);
  345. laAddSubGroup(pc, "base", "Base","Base","calc_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
  346. laAddSubGroup(pc, "in_result", "Result","Input result","la_in_socket",0,0,0,offsetof(CalcResultNode,inResult),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  347. pcRef=pc=laAddPropertyContainer("calc_ref_node", "Reference Node", "A node that references other calculators", 0, UiCalcRefNode, sizeof(CalcRefNode), 0, 0, 1);
  348. laAddSubGroup(pc, "base", "Base","Base","calc_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
  349. laAddSubGroup(pc, "ref", "Reference","Referenced calculator","calculator",0,0,0,offsetof(CalcRefNode,Reference),CalcGetFirstCalculator,0,laget_ListNext,0,0,0,0,LA_UDF_REFER);
  350. laAddSubGroup(pc, "in_result", "Result","Input result","la_in_socket",0,0,0,offsetof(CalcRefNode,inResult),0,0,0,0,0,0,0,LA_UDF_SINGLE);
  351. laSaveProp("calc");
  352. }
  353. int OPINV_AddBowl(laOperator* a, laEvent* e){
  354. Bowl* b=memAcquireHyper(sizeof(Bowl));
  355. lstAppendItem(&B.Bowls,b);
  356. laRecordAndPushProp(0, "basket");laNotifyUsers("basket");
  357. laPrintDBInstInfo();
  358. return LA_FINISHED;
  359. }
  360. int OPINV_RemoveBowl(laOperator* a, laEvent* e){
  361. Bowl* b=a->This?a->This->EndInstance:B.Bowls.pLast; if(!b) return LA_FINISHED;
  362. lstRemoveItem(&B.Bowls, b);
  363. memFree(b);
  364. laRecordAndPushProp(0, "basket");laNotifyUsers("basket");
  365. laPrintDBInstInfo();
  366. return LA_FINISHED;
  367. }
  368. int OPINV_AddFruit(laOperator* a, laEvent* e){
  369. laListHandle* into=(a->This&&a->This->LastPs->p==pBowl)?&((Bowl*)a->This->EndInstance)->Fruits:0;
  370. if(!into) into=a->This?&((Fruit*)a->This->EndInstance)->Bundled:0;
  371. char* stype; int size=sizeof(Apple); int type=FRUIT_TYPE_APPLE;
  372. if(stype=strGetArgumentString(a->ExtraInstructionsP,"type")){
  373. if(!strcmp(stype,"pear")) {size=sizeof(Pear);type=FRUIT_TYPE_PEAR;}
  374. }
  375. Fruit* f=memAcquire(size); f->Type=type;
  376. if(into){ lstAppendItem(into, f); f->Parent=into; laNotifyUsers("basket"); /*laNotifyUsersPPPath(a->This,"base.bundled");*/ }
  377. else{ lstAppendItem(&B.Stuff, f); laNotifyUsers("basket");}
  378. laRecordAndPushProp(0, "basket");
  379. laPrintDBInstInfo();
  380. return LA_FINISHED;
  381. }
  382. void DestroyFruit(Fruit* f){
  383. Fruit* NextF;
  384. for(Fruit*fi=f->Bundled.pFirst;fi;fi=NextF){
  385. NextF=fi->Item.pNext;
  386. DestroyFruit(fi);
  387. }
  388. memFree(f);
  389. }
  390. int OPINV_RemoveFruit(laOperator* a, laEvent* e){
  391. Fruit* f=a->This?a->This->EndInstance:0; laListHandle* l;
  392. if(f->Parent){ l=f->Parent;lstRemoveItem(l,f); laNotifyUsers("basket"); }
  393. else{ l=&B.Stuff; lstRemoveItem(l,f);laNotifyUsers("basket"); }
  394. DestroyFruit(f);
  395. laRecordAndPushProp(0, "basket");
  396. return LA_FINISHED;
  397. }
  398. int OPINV_MoveFruit(laOperator* a, laEvent* e){
  399. Fruit* f=a->This?a->This->EndInstance:0; laListHandle* l; int direction=0; char* dir;
  400. if(dir=strGetArgumentString(a->ExtraInstructionsP,"direction")){
  401. if(!strcmp(dir,"up")) {direction=1;}
  402. }
  403. if(f->Parent){ l=f->Parent; laNotifyUsers("basket"); /*laNotifyUsersPPPath(a->This,"base.parent.bundled");*/ }
  404. else{ l=&B.Stuff; laNotifyUsers("basket"); }
  405. if(direction) lstMoveUp(l,f);
  406. else lstMoveDown(l,f);
  407. laRecordAndPushProp(0, "basket");
  408. return LA_FINISHED;
  409. }
  410. int OPINV_PushBasketState(laOperator* a, laEvent* e){
  411. laRecordAndPushProp(0, "basket");
  412. logPrint("Pushed state: \"basket\"\n");
  413. return LA_FINISHED;
  414. }
  415. laPropContainer* FruitGetType(Fruit* f){
  416. if(f->Type==FRUIT_TYPE_APPLE) return pcApple;
  417. if(f->Type==FRUIT_TYPE_PEAR) return pcPear;
  418. return pcApple;
  419. }
  420. void* FruitGetBasket(void* none){
  421. return &B;
  422. }
  423. void* BowlGetFirst(void* none, void *UNUSED){
  424. return B.Bowls.pFirst;
  425. }
  426. void* FruitGetFirst(void* none, void *UNUSED){
  427. return B.Stuff.pFirst;
  428. }
  429. void FruitsPanel(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
  430. laColumn* c=laFirstColumn(uil);
  431. laColumn* cl;
  432. laSplitColumn(uil,c,0.5);
  433. cl=laLeftColumn(c,0);
  434. laShowItem(uil,c,0,"basket");
  435. laUiItem* r=laBeginRow(uil,c,0,0);
  436. strSafeSet(&laShowItem(uil,c,0,"FRUIT_add")->ExtraInstructions,"type=apple;icon=🍏;text=Add Apple;");
  437. strSafeSet(&laShowItem(uil,c,0,"FRUIT_add")->ExtraInstructions,"type=pear;icon=🍐;text=Add Pear;");
  438. laShowItem(uil,c,0,"BOWL_add");
  439. laEndRow(uil,r);
  440. laShowSeparator(uil,c);
  441. laShowItemFull(uil,c,0,"la.example_string", LA_WIDGET_STRING_MULTI, 0 ,0,0);
  442. r=laBeginRow(uil,c,0,0);
  443. laShowItem(uil,c,0,"LA_undo");
  444. laShowItem(uil,c,0,"LA_redo");
  445. laShowItem(uil,c,0,"STATE_push");
  446. laEndRow(uil,r);
  447. }
  448. void UIBowl(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
  449. laColumn* c=laFirstColumn(uil);
  450. laColumn* cl,*cr;
  451. laSplitColumn(uil,c,0.4);
  452. cl=laLeftColumn(c, 1);
  453. cr=laRightColumn(c,0);
  454. laUiItem*u;
  455. laUiItem* r=laBeginRow(uil,cr,1,0);
  456. laShowItem(uil,cr,This,"name")->Expand=1;
  457. laShowItem(uil,cr,This,"remove")->Flags|=LA_UI_FLAGS_ICON;
  458. laEndRow(uil,r);
  459. r=laOnConditionToggle(uil,cl,0,0,0,0,0);{
  460. laShowItem(uil,cr,This,"fruits");
  461. laUiItem* r1=laBeginRow(uil,cr,0,0);
  462. strSafeSet(&laShowItem(uil,cr,This,"add_fruit")->ExtraInstructions,"type=apple;icon=🍏;text=Add Apple;");
  463. strSafeSet(&laShowItem(uil,cr,This,"add_fruit")->ExtraInstructions,"type=pear;icon=🍐;text=Add Pear;");
  464. laEndRow(uil,r1);
  465. }laEndCondition(uil,r);
  466. }
  467. void UIApple(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
  468. laColumn* c=laFirstColumn(uil);
  469. laColumn* cl,*cr;
  470. laSplitColumn(uil,c,0.4);
  471. cl=laLeftColumn(c, 1);
  472. cr=laRightColumn(c,0);
  473. laUiItem*u;
  474. laUiItem* r=laBeginRow(uil,cr,1,0);
  475. laShowLabel(uil,cr,"Apple",0,0)->Expand=1;
  476. laShowItem(uil,cr,This,"how_sweet")->Expand=1;
  477. laShowItem(uil,cr,This,"base.why_not")->Expand=1;
  478. laShowItem(uil,cr,This,"base.container")->Expand=1;
  479. laShowItem(uil,cr,This,"base.remove")->Flags|=LA_UI_FLAGS_ICON;
  480. u=laShowItem(uil,cr,This,"base.move"); strSafeSet(&u->ExtraInstructions,"direction=up;icon=🡹;");u->Flags|=LA_UI_FLAGS_ICON;
  481. u=laShowItem(uil,cr,This,"base.move"); strSafeSet(&u->ExtraInstructions,"direction=down;icon=🡻;");u->Flags|=LA_UI_FLAGS_ICON;
  482. laEndRow(uil,r);
  483. r=laOnConditionToggle(uil,cl,0,0,0,0,0);{
  484. laShowItem(uil,cr,This,"base.bundled");
  485. laUiItem* r1=laBeginRow(uil,cr,0,0);
  486. strSafeSet(&laShowItem(uil,cr,This,"base.add")->ExtraInstructions,"type=apple;icon=🍏;text=Add Apple;");
  487. strSafeSet(&laShowItem(uil,cr,This,"base.add")->ExtraInstructions,"type=pear;icon=🍐;text=Add Pear;");
  488. laEndRow(uil,r1);
  489. }laEndCondition(uil,r);
  490. }
  491. void UIPear(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
  492. laColumn* c=laFirstColumn(uil);
  493. laColumn* cl,*cr;
  494. laSplitColumn(uil,c,0.4);
  495. cl=laLeftColumn(c, 1);
  496. cr=laRightColumn(c,0);
  497. laUiItem*u;
  498. laUiItem* r=laBeginRow(uil,cr,1,0);
  499. laShowLabel(uil,cr,"Pear",0,0)->Expand=1;
  500. laShowItem(uil,cr,This,"really")->Expand=1;
  501. laShowItem(uil,cr,This,"base.why_not")->Expand=1;
  502. laShowItem(uil,cr,This,"base.container")->Expand=1;
  503. laShowItem(uil,cr,This,"base.remove")->Flags|=LA_UI_FLAGS_ICON;
  504. u=laShowItem(uil,cr,This,"base.move"); strSafeSet(&u->ExtraInstructions,"direction=up;icon=🡹;");u->Flags|=LA_UI_FLAGS_ICON;
  505. u=laShowItem(uil,cr,This,"base.move"); strSafeSet(&u->ExtraInstructions,"direction=down;icon=🡻;");u->Flags|=LA_UI_FLAGS_ICON;
  506. laEndRow(uil,r);
  507. r=laOnConditionToggle(uil,cl,0,0,0,0,0);{
  508. laShowItem(uil,cr,This,"base.bundled");
  509. laUiItem* r1=laBeginRow(uil,cr,0,0);
  510. strSafeSet(&laShowItem(uil,cr,This,"base.add")->ExtraInstructions,"type=apple;icon=🍏;text=Add Apple;");
  511. strSafeSet(&laShowItem(uil,cr,This,"base.add")->ExtraInstructions,"type=pear;icon=🍐;text=Add Pear;");
  512. laEndRow(uil,r1);
  513. }laEndCondition(uil,r);
  514. }
  515. void UIBowlSimple(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
  516. laColumn* c=laFirstColumn(uil);
  517. laShowItemFull(uil,c,This,"name",LA_WIDGET_STRING_PLAIN, 0 ,0,0);
  518. }
  519. void UIFruitSimple(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
  520. laColumn* c=laFirstColumn(uil);
  521. laShowItem(uil,c,This,"type");
  522. }
  523. void ScenePanel(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
  524. laColumn* c=laFirstColumn(uil);
  525. laUiItem* ui=laShowCanvas(uil,c,0,"tns.world",0,-1);
  526. laDefault3DViewOverlay(ui);
  527. }
  528. int RegisterEverything(){
  529. laRegisterUiTemplate("panel_fruit", "Fruits", FruitsPanel, 0, 0);
  530. laRegisterUiTemplate("panel_scene", "Scene", ScenePanel, 0, 0);
  531. laCreateOperatorType("BOWL_add", "Add Bowl", "Add a bowl", 0,0,0,OPINV_AddBowl,0,'+',0);
  532. laCreateOperatorType("BOWL_remove", "Remove Bowl", "Remove a bowl", 0,0,0,OPINV_RemoveBowl,0,'-',0);
  533. laCreateOperatorType("FRUIT_add", "Add Fruit", "Add a fruit into the basket or bundle", 0,0,0,OPINV_AddFruit,0,'+',0);
  534. laCreateOperatorType("FRUIT_remove", "Remove Fruit", "Remove a fruit", 0,0,0,OPINV_RemoveFruit,0,'-',0);
  535. laCreateOperatorType("FRUIT_move", "Move Fruit", "Move a fruit", 0,0,0,OPINV_MoveFruit,0,'~',0);
  536. laCreateOperatorType("STATE_push", "Push State", "Push basket state", 0,0,0,OPINV_PushBasketState,0,0,0);
  537. laPropContainer* pc=laDefineRoot();
  538. laAddSubGroup(pc, "basket", "Basket", "The basket", "basket",0,0,0,-1,FruitGetBasket,0,0,0,0,0,0,LA_UDF_SINGLE|LA_UDF_LOCAL);
  539. laProp*p;
  540. pc=laAddPropertyContainer("bowl", "Bowl", "Some sort of a bowl", 0, UIBowl, sizeof(Bowl), 0, 0, 2);
  541. laAddStringProperty(pc,"name","Name","Name of the bowl",0,0,0,0,1,offsetof(Bowl,Name),0,0,0,0,LA_AS_IDENTIFIER);
  542. laAddSubGroup(pc, "fruits", "Fruits","Fruits","fruit",FruitGetType,0,0,-1,0,0,0,0,0,0,offsetof(Bowl,Fruits),0);
  543. laAddOperatorProperty(pc,"remove","Remove","Remove a bowl", "BOWL_remove", '-', 0);
  544. laAddOperatorProperty(pc,"add_fruit","Add","Add a fruit into the bowl", "FRUIT_add", '+', 0);
  545. pc=laAddPropertyContainer("basket", "Basket", "A basket of fruits", 0, 0, sizeof(Basket), 0, 0, 1|LA_UDF_LOCAL|LA_PROP_OTHER_ALLOC|LA_UDF_SINGLE);
  546. laAddIntProperty(pc,"example","Example","Example int",0,0,0,0,0,1,0,0,offsetof(Basket,example),0,0,0,0,0,0,0,0,0,0,0);
  547. laAddStringProperty(pc,"name","Name","Name of the basket",0,0,0,0,1,offsetof(Basket,name),0,0,0,0,LA_UDF_REFER);
  548. laAddSubGroup(pc, "stuff", "Stuff","Stuffs","fruit",FruitGetType,0,0,-1,0,0,0,0,0,0,offsetof(Basket,Stuff),0);
  549. pBowl = laAddSubGroup(pc, "bowls", "Bows","Bows","bowl",0,0,0,-1,0,0,0,0,0,0,offsetof(Basket,Bowls),0);
  550. pc=laAddPropertyContainer("fruit", "Fruit", "A fruit", 0, 0, sizeof(Fruit), 0, 0, 1);
  551. p=laAddEnumProperty(pc,"type","Type","Type",0,0,0,0,0,offsetof(Fruit,Type),0,0,0,0,0,0,0,0,0,LA_AS_IDENTIFIER|LA_READ_ONLY);
  552. laAddEnumItemAs(p,"APPLE","Apple","Apple", FRUIT_TYPE_APPLE, L'🍏');
  553. laAddEnumItemAs(p,"PEAR","Pear","Pear", FRUIT_TYPE_PEAR, L'🍐');
  554. pFruit = laAddSubGroup(pc, "bundled", "Bundled","Bundled","fruit",FruitGetType,0,0,-1,0,0,0,0,0,0,offsetof(Fruit,Bundled),0);
  555. laAddSubGroup(pc, "why_not", "Why Not","Why not try","fruit",0,LA_WIDGET_COLLECTION_SELECTOR,UIFruitSimple,offsetof(Fruit,WhyNot),FruitGetFirst,0,laget_ListNext,0,0,0,0,LA_UDF_REFER);
  556. laAddSubGroup(pc, "parent", "Parent","Parent","any_pointer",0,0,0,offsetof(Fruit,Parent),0,0,0,0,0,0,0,LA_UDF_REFER);
  557. laAddSubGroup(pc, "container", "Container","Container of this fruit","bowl",0,LA_WIDGET_COLLECTION_SELECTOR,UIBowlSimple,offsetof(Fruit, Container),BowlGetFirst,0,laget_ListNext,0,0,0,0,LA_UDF_REFER);
  558. laAddOperatorProperty(pc,"add","Add","Add a fruit into bundled", "FRUIT_add", '+', 0);
  559. laAddOperatorProperty(pc,"remove","Remove","Remove a fruit", "FRUIT_remove", '-', 0);
  560. laAddOperatorProperty(pc,"move","Move","Move a fruit", "FRUIT_move", '~', 0);
  561. pcApple=pc=laAddPropertyContainer("apple", "Apple", "An apple", 0, UIApple, sizeof(Apple), 0, 0, 1);
  562. laAddSubGroup(pc,"base", "Base","Base fruit","fruit",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_SINGLE|LA_UDF_LOCAL);
  563. laAddFloatProperty(pc,"how_sweet","How Sweet","How sweet",0,0,0,100,0,0.1,0,0,offsetof(Apple,HowSweet),0,0,0,0,0,0,0,0,0,0,LA_AS_IDENTIFIER);
  564. pcPear=pc=laAddPropertyContainer("pear", "Pear", "A pear", 0, UIPear, sizeof(Pear), 0, 0, 1);
  565. laAddSubGroup(pc, "base","Base","Base fruit","fruit",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_SINGLE|LA_UDF_LOCAL);
  566. p=laAddEnumProperty(pc,"really","Really","Really a pear?",LA_WIDGET_ENUM_CYCLE,0,0,0,0,offsetof(Pear,Really),0,0,0,0,0,0,0,0,0,LA_AS_IDENTIFIER);
  567. laAddEnumItemAs(p,"NAH","Nah","Nah I don't think so", 0, L'🤔');
  568. laAddEnumItemAs(p,"YEAH","Yeah","It's really a pear", 1, L'😄');
  569. laSaveProp("basket");
  570. tnsObject* s=tnsCreateRootObject("My Root");
  571. tnsObject* o=tnsCreateLight(s,"Sun",100,100,100,1,1);
  572. tnsVector3d target={0,0,0}, up={0,0,1};
  573. tnsLookAt(o,target,up);
  574. }
  575. //void la_DetachedPanel1(laPanel* p){
  576. // la_MakeDetachedProp(p, "tns.texture_list", "tex");
  577. //}
  578. //void la_PanelHeader1(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *cr, int context){
  579. // laColumn* c=cr?cr:laFirstColumn(uil);
  580. // laShowItemFull(uil,c,DetachedProps,"tex", LA_WIDGET_COLLECTION_SELECTOR, 0 ,0,0);
  581. //}
  582. int main(int argc, char *argv[]){
  583. laGetReady();
  584. RegisterEverything();
  585. RegisterCalculator();
  586. laRefreshUDFRegistries();
  587. laEnsureUserPreferences();
  588. laAddRootDBInst("calc");
  589. laAddRootDBInst("basket");
  590. laWindow* w = laDesignWindow(-1,-1,600,600);
  591. laLayout* l = laDesignLayout(w, "Second Layout");
  592. laBlock* b = l->FirstBlock;
  593. laPanel* p=laCreatePanel(b, "LAUI_user_preferences");
  594. l = laDesignLayout(w, "First Layout");
  595. b = l->FirstBlock;
  596. p=laCreatePanel(b, "panel_fruit");
  597. l = laDesignLayout(w, "Scene Layout");
  598. b = l->FirstBlock;
  599. p=laCreatePanel(b, "panel_scene");
  600. l = laDesignLayout(w, "Nodes Layout");
  601. b = l->FirstBlock;
  602. p=laCreatePanel(b, "panel_nodes");
  603. laStartWindow(w);
  604. laMainLoop();
  605. }