|  | @@ -0,0 +1,691 @@
 | 
	
		
			
				|  |  | +#include "la_5.h"
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +extern LA MAIN;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +STRUCTURE(Bowl){
 | 
	
		
			
				|  |  | +    laListItem    Item;
 | 
	
		
			
				|  |  | +    laSafeString* Name;
 | 
	
		
			
				|  |  | +    laListHandle  Fruits;
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +STRUCTURE(Basket){
 | 
	
		
			
				|  |  | +    int pad;
 | 
	
		
			
				|  |  | +    int example;
 | 
	
		
			
				|  |  | +    laSafeString* name;
 | 
	
		
			
				|  |  | +    laListHandle Stuff;
 | 
	
		
			
				|  |  | +    laListHandle Bowls;
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +#define FRUIT_TYPE_APPLE 1
 | 
	
		
			
				|  |  | +#define FRUIT_TYPE_PEAR 2
 | 
	
		
			
				|  |  | +STRUCTURE(Fruit){
 | 
	
		
			
				|  |  | +    laListItem   Item;
 | 
	
		
			
				|  |  | +    int          Type;
 | 
	
		
			
				|  |  | +    Fruit*       WhyNot;
 | 
	
		
			
				|  |  | +    laListHandle*  Parent;
 | 
	
		
			
				|  |  | +    Bowl*        Container;
 | 
	
		
			
				|  |  | +    laListHandle Bundled;
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +STRUCTURE(Apple){
 | 
	
		
			
				|  |  | +    Fruit  Base;
 | 
	
		
			
				|  |  | +    real   HowSweet;
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +STRUCTURE(Pear){
 | 
	
		
			
				|  |  | +    Fruit Base;
 | 
	
		
			
				|  |  | +    int Really;
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +STRUCTURE(Calculator){
 | 
	
		
			
				|  |  | +    laListHandle Item;
 | 
	
		
			
				|  |  | +    laSafeString* Title;
 | 
	
		
			
				|  |  | +    laSafeString* ResultString;
 | 
	
		
			
				|  |  | +    laListHandle Racks;
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +STRUCTURE(CalculatorCollection){
 | 
	
		
			
				|  |  | +    void* base;
 | 
	
		
			
				|  |  | +    laListHandle Calculators;
 | 
	
		
			
				|  |  | +    Calculator* CurrentCalculator;
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +STRUCTURE(CalcRack){
 | 
	
		
			
				|  |  | +    laListItem Item;
 | 
	
		
			
				|  |  | +    laListHandle Nodes;
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +STRUCTURE(CalcNode){
 | 
	
		
			
				|  |  | +    laListItem Item;
 | 
	
		
			
				|  |  | +    int Type;
 | 
	
		
			
				|  |  | +    int Gap;
 | 
	
		
			
				|  |  | +    laNodeOutSocket* OutA;
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +STRUCTURE(CalcOpNode){
 | 
	
		
			
				|  |  | +    CalcNode Base;
 | 
	
		
			
				|  |  | +    int Operation;
 | 
	
		
			
				|  |  | +    laNodeInSocket* inA; real AVal;
 | 
	
		
			
				|  |  | +    laNodeInSocket* inB; real BVal;
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +STRUCTURE(CalcMixNode){
 | 
	
		
			
				|  |  | +    CalcOpNode Base;
 | 
	
		
			
				|  |  | +    laNodeInSocket* inFactor; real Factor;
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +STRUCTURE(CalcNumberNode){
 | 
	
		
			
				|  |  | +    CalcNode Base;
 | 
	
		
			
				|  |  | +    int Mode; // Integer/Real
 | 
	
		
			
				|  |  | +    int iValue;
 | 
	
		
			
				|  |  | +    real rValue;
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +STRUCTURE(CalcResultNode){
 | 
	
		
			
				|  |  | +    CalcNode Base;
 | 
	
		
			
				|  |  | +    laNodeInSocket* inResult;
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +STRUCTURE(CalcRefNode){
 | 
	
		
			
				|  |  | +    CalcNode Base;
 | 
	
		
			
				|  |  | +    Calculator* Reference;
 | 
	
		
			
				|  |  | +    laNodeInSocket* inResult;
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#define CALC_NODE_GENERIC 0
 | 
	
		
			
				|  |  | +#define CALC_NODE_NUMBER 1
 | 
	
		
			
				|  |  | +#define CALC_NODE_OP     2
 | 
	
		
			
				|  |  | +#define CALC_NODE_MIX    3
 | 
	
		
			
				|  |  | +#define CALC_NODE_RESULT 4
 | 
	
		
			
				|  |  | +#define CALC_NODE_REF    5
 | 
	
		
			
				|  |  | +#define CALC_OP_ADD 0
 | 
	
		
			
				|  |  | +#define CALC_OP_SUB 1
 | 
	
		
			
				|  |  | +#define CALC_OP_MUL 2
 | 
	
		
			
				|  |  | +#define CALC_OP_DIV 3
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +Basket B={0};
 | 
	
		
			
				|  |  | +CalculatorCollection* CC=0;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +laPropContainer* pcApple,*pcPear;
 | 
	
		
			
				|  |  | +laProp* pBasket, *pFruit, *pBowl;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +laPropContainer* pcNumber,*pcOp,*pcMix,*pcResult,*pcGeneric,*pcRef;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +laTheme* LightTheme, *DarkTheme;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +void UiCalcNumberNode(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
 | 
	
		
			
				|  |  | +    laColumn* c=laFirstColumn(uil); laUiItem* b=laBeginRow(uil,c,0,0);
 | 
	
		
			
				|  |  | +    laShowHeightAdjuster(uil,c,This,"base.__gap",0);
 | 
	
		
			
				|  |  | +    laShowItem(uil,c,This,"mode");
 | 
	
		
			
				|  |  | +    laUiItem* b1=laOnConditionThat(uil,c,laEqual(laPropExpression(This,"mode"),laIntExpression(0)));{
 | 
	
		
			
				|  |  | +        laShowItem(uil,c,This,"value_i");
 | 
	
		
			
				|  |  | +    }laElse(uil,b1);{
 | 
	
		
			
				|  |  | +        laShowItem(uil,c,This,"value_r");
 | 
	
		
			
				|  |  | +    }laEndCondition(uil,b1);
 | 
	
		
			
				|  |  | +    laShowSeparator(uil,c)->Expand=1;
 | 
	
		
			
				|  |  | +    laShowNodeSocket(uil,c,This,"base.out_a",0);
 | 
	
		
			
				|  |  | +    laShowLabel(uil,c,"🤙",0,0)->Flags|=LA_TEXT_ALIGN_RIGHT;
 | 
	
		
			
				|  |  | +    laEndRow(uil,b);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +void UiCalcOpNode(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
 | 
	
		
			
				|  |  | +    laColumn* c=laFirstColumn(uil); laUiItem* b=laBeginRow(uil,c,0,0);
 | 
	
		
			
				|  |  | +    laShowHeightAdjuster(uil,c,This,"base.__gap",0);
 | 
	
		
			
				|  |  | +    laShowNodeSocket(uil,c,This,"in_a",0);
 | 
	
		
			
				|  |  | +    laUiItem* b1=laOnConditionThat(uil,c,laNot(laPropExpression(This,"in_a.source")));{
 | 
	
		
			
				|  |  | +        laShowItem(uil,c,This,"val_a");
 | 
	
		
			
				|  |  | +    }laEndCondition(uil,b1);
 | 
	
		
			
				|  |  | +    laShowNodeSocket(uil,c,This,"in_b",0);
 | 
	
		
			
				|  |  | +    b1=laOnConditionThat(uil,c,laNot(laPropExpression(This,"in_b.source")));{
 | 
	
		
			
				|  |  | +        laShowItem(uil,c,This,"val_b");
 | 
	
		
			
				|  |  | +    }laEndCondition(uil,b1);
 | 
	
		
			
				|  |  | +    laShowItem(uil,c,This,"operation");
 | 
	
		
			
				|  |  | +    laShowSeparator(uil,c)->Expand=1;
 | 
	
		
			
				|  |  | +    laShowNodeSocket(uil,c,This,"base.out_a",0);
 | 
	
		
			
				|  |  | +    laShowLabel(uil,c,"🤔",0,0)->Flags|=LA_TEXT_ALIGN_RIGHT;
 | 
	
		
			
				|  |  | +    laEndRow(uil,b);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +void UiCalcMixNode(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
 | 
	
		
			
				|  |  | +    laColumn* c=laFirstColumn(uil); laUiItem* b=laBeginRow(uil,c,0,0);
 | 
	
		
			
				|  |  | +    laShowHeightAdjuster(uil,c,This,"base.base.__gap",0);
 | 
	
		
			
				|  |  | +    laShowNodeSocket(uil,c,This,"base.in_a",0);
 | 
	
		
			
				|  |  | +    laUiItem* b1=laOnConditionThat(uil,c,laNot(laPropExpression(This,"base.in_a.source")));{
 | 
	
		
			
				|  |  | +        laShowItem(uil,c,This,"base.val_a");
 | 
	
		
			
				|  |  | +    }laEndCondition(uil,b1);
 | 
	
		
			
				|  |  | +    laShowNodeSocket(uil,c,This,"base.in_b",0);
 | 
	
		
			
				|  |  | +    b1=laOnConditionThat(uil,c,laNot(laPropExpression(This,"base.in_b.source")));{
 | 
	
		
			
				|  |  | +        laShowItem(uil,c,This,"base.val_b");
 | 
	
		
			
				|  |  | +    }laEndCondition(uil,b1);
 | 
	
		
			
				|  |  | +    laShowItem(uil,c,This,"in_factor");
 | 
	
		
			
				|  |  | +    b1=laOnConditionThat(uil,c,laNot(laPropExpression(This,"in_factor.source")));{
 | 
	
		
			
				|  |  | +        laShowItem(uil,c,This,"factor");
 | 
	
		
			
				|  |  | +    }laEndCondition(uil,b1);
 | 
	
		
			
				|  |  | +    laShowSeparator(uil,c)->Expand=1;
 | 
	
		
			
				|  |  | +    laShowNodeSocket(uil,c,This,"base.base.out_a",0);
 | 
	
		
			
				|  |  | +    laShowLabel(uil,c,"🤝",0,0)->Flags|=LA_TEXT_ALIGN_RIGHT;
 | 
	
		
			
				|  |  | +    laEndRow(uil,b);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +void UiCalcResultNode(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
 | 
	
		
			
				|  |  | +    laColumn* c=laFirstColumn(uil); laUiItem* b=laBeginRow(uil,c,0,0);
 | 
	
		
			
				|  |  | +    laShowHeightAdjuster(uil,c,This,"base.__gap",0);
 | 
	
		
			
				|  |  | +    laShowNodeSocket(uil,c,This,"in_result",0);
 | 
	
		
			
				|  |  | +    laShowSeparator(uil,c)->Expand=1;
 | 
	
		
			
				|  |  | +    laShowLabel(uil,c,"😋",0,0)->Flags|=LA_TEXT_ALIGN_RIGHT;
 | 
	
		
			
				|  |  | +    laEndRow(uil,b);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +void UiCalcRefNode(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
 | 
	
		
			
				|  |  | +    laColumn* c=laFirstColumn(uil); laUiItem* b=laBeginRow(uil,c,0,0);
 | 
	
		
			
				|  |  | +    laShowHeightAdjuster(uil,c,This,"base.__gap",0);
 | 
	
		
			
				|  |  | +    laShowNodeSocket(uil,c,This,"in_result",0);
 | 
	
		
			
				|  |  | +    laShowSeparator(uil,c)->Expand=1;
 | 
	
		
			
				|  |  | +    laShowLabel(uil,c,"😋",0,0)->Flags|=LA_TEXT_ALIGN_RIGHT;
 | 
	
		
			
				|  |  | +    laEndRow(uil,b);
 | 
	
		
			
				|  |  | +    laShowItemFull(uil,c,This,"ref",LA_WIDGET_COLLECTION_SELECTOR,0,laui_IdentifierOnly,0);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +void UiRack(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
 | 
	
		
			
				|  |  | +    laColumn* c=laFirstColumn(uil);
 | 
	
		
			
				|  |  | +    laShowItem(uil,c,This,"nodes")->Flags|=LA_UI_FLAGS_NO_DECAL;;
 | 
	
		
			
				|  |  | +    laShowItem(uil,c,This,"add_node");
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +void UiCalculator(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
 | 
	
		
			
				|  |  | +    laColumn* c=laFirstColumn(uil);
 | 
	
		
			
				|  |  | +    laShowItem(uil,c,This,"title");
 | 
	
		
			
				|  |  | +    laUiItem*b=laBeginRow(uil,c,0,0);
 | 
	
		
			
				|  |  | +    laShowItemFull(uil,c,This,"add_rack",0,"position=head;",0,0)->Flags|=LA_UI_FLAGS_ICON;
 | 
	
		
			
				|  |  | +    laUiItem* ui=laShowLabel(uil,c,"Racks",0,0); ui->Flags|=LA_TEXT_ALIGN_CENTER; ui->Expand=1;
 | 
	
		
			
				|  |  | +    laShowItemFull(uil,c,This,"add_rack",0,0,0,0)->Flags|=LA_UI_FLAGS_ICON;
 | 
	
		
			
				|  |  | +    laEndRow(uil,b);
 | 
	
		
			
				|  |  | +    laUiItem* g=laMakeGroup(uil,c,"Racks",0);{ g->Flags|=LA_UI_FLAGS_NO_GAP|LA_UI_FLAGS_NO_DECAL|LA_UI_FLAGS_NODE_CONTAINER;
 | 
	
		
			
				|  |  | +        laUiList* gu=g->Page; laColumn* gc=laFirstColumn(gu); gu->AllowScale=1; gu->HeightCoeff=-3; g->State=LA_UI_ACTIVE;
 | 
	
		
			
				|  |  | +        laUiItem* hui=laShowItem(gu,gc,This,"racks"); hui->Expand=15; hui->Flags|=LA_UI_FLAGS_NO_GAP|LA_UI_FLAGS_NO_DECAL;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    laShowItem(uil,c,This,"result");
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +void CalcPanel(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
 | 
	
		
			
				|  |  | +    laColumn* c=laFirstColumn(uil); laColumn* cl,*cr; laSplitColumn(uil,c,0.5); cl=laLeftColumn(c,0); cr=laRightColumn(c,0);
 | 
	
		
			
				|  |  | +    laShowItemFull(uil,cl,0,"calc.current",LA_WIDGET_COLLECTION_SELECTOR,0,laui_IdentifierOnly,0);
 | 
	
		
			
				|  |  | +    laShowItem(uil,cr,0,"CALC_add_calculator");
 | 
	
		
			
				|  |  | +    laShowItemFull(uil,c,0,"calc.current",LA_WIDGET_COLLECTION_SINGLE,0,0,0)->Flags|=LA_UI_COLLECTION_NO_HIGHLIGHT;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +int OPINV_AddCalculator(laOperator* a, laEvent* e){
 | 
	
		
			
				|  |  | +    Calculator* c=memAcquireHyper(sizeof(Calculator));
 | 
	
		
			
				|  |  | +    strSafeSet(&c->Title, "New Calculator");
 | 
	
		
			
				|  |  | +    lstAppendItem(&CC->Calculators,c);
 | 
	
		
			
				|  |  | +    memAssignRef(CC,&CC->CurrentCalculator,c);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    laRecordAndPushProp(0, "calc"); laNotifyUsers("calc"); laPrintDBInstInfo();
 | 
	
		
			
				|  |  | +    return LA_FINISHED;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +int OPINV_AddRack(laOperator* a, laEvent* e){
 | 
	
		
			
				|  |  | +    Calculator* c=a->This?a->This->EndInstance:CC->CurrentCalculator; if(!c) return LA_FINISHED;
 | 
	
		
			
				|  |  | +    CalcRack* cr=memAcquire(sizeof(CalcRack));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if(strSame(strGetArgumentString(a->ExtraInstructionsP,"position"),"head")){ lstPushItem(&c->Racks,cr); }
 | 
	
		
			
				|  |  | +    else lstAppendItem(&c->Racks,cr);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    laRecordAndPushProp(0, "calc"); laNotifyUsers("calc"); laPrintDBInstInfo();
 | 
	
		
			
				|  |  | +    return LA_FINISHED;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +void AddNodesPanel(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
 | 
	
		
			
				|  |  | +    laColumn* c=laFirstColumn(uil);
 | 
	
		
			
				|  |  | +    laShowLabel(uil,c,"Select node type:",0,0);
 | 
	
		
			
				|  |  | +    laShowItemFull(uil,c,0,"LA_confirm",0,"icon=🤙;text=Number;feedback=NUMBER;",0,0);
 | 
	
		
			
				|  |  | +    laShowItemFull(uil,c,0,"LA_confirm",0,"icon=🤔;text=Calculate;feedback=CALC;",0,0);
 | 
	
		
			
				|  |  | +    laShowItemFull(uil,c,0,"LA_confirm",0,"icon=🤝;text=Mix;feedback=MIX;",0,0);
 | 
	
		
			
				|  |  | +    laShowItemFull(uil,c,0,"LA_confirm",0,"icon=😋;text=Result;feedback=RESULT;",0,0);
 | 
	
		
			
				|  |  | +    laShowItemFull(uil,c,0,"LA_confirm",0,"icon=🡬;text=Reference;feedback=REF;",0,0);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +int OPINV_AddNode_(laOperator* a, laEvent* e){
 | 
	
		
			
				|  |  | +    CalcRack* cr=a->This?a->This->EndInstance:0; if(!cr) return LA_FINISHED;
 | 
	
		
			
				|  |  | +    laEnableOperatorPanel(a, a->This, e->x,e->y,0,0,0,0,0,0,0,0,0,0,e);
 | 
	
		
			
				|  |  | +    return LA_RUNNING;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +int OPMOD_AddNode_(laOperator* a, laEvent* e){
 | 
	
		
			
				|  |  | +    if(!a->This){ return LA_FINISHED; }
 | 
	
		
			
				|  |  | +    CalcRack* cr=a->This->EndInstance;
 | 
	
		
			
				|  |  | +    if(a->ConfirmData){
 | 
	
		
			
				|  |  | +        char* str; CalcNode* n=0;
 | 
	
		
			
				|  |  | +        if(strSame(a->ConfirmData->StrData, "NUMBER")){
 | 
	
		
			
				|  |  | +            n=memAcquire(sizeof(CalcNumberNode)); CalcNumberNode* cn=n; n->Type=CALC_NODE_NUMBER;
 | 
	
		
			
				|  |  | +            cn->Base.OutA=laCreateOutSocket(cn, "A", 0);
 | 
	
		
			
				|  |  | +        }elif(strSame(a->ConfirmData->StrData, "CALC")){
 | 
	
		
			
				|  |  | +            n=memAcquire(sizeof(CalcOpNode)); CalcOpNode* cn=n; n->Type=CALC_NODE_OP;
 | 
	
		
			
				|  |  | +            cn->Base.OutA=laCreateOutSocket(cn, "Out", 0);
 | 
	
		
			
				|  |  | +            cn->inA=laCreateInSocket("A", 0);
 | 
	
		
			
				|  |  | +            cn->inB=laCreateInSocket("B", 0);
 | 
	
		
			
				|  |  | +        }elif(strSame(a->ConfirmData->StrData, "MIX")){
 | 
	
		
			
				|  |  | +            n=memAcquire(sizeof(CalcMixNode)); CalcMixNode*cn=n; n->Type=CALC_NODE_MIX;
 | 
	
		
			
				|  |  | +            cn->Base.Base.OutA=laCreateOutSocket(cn, "Out", 0);
 | 
	
		
			
				|  |  | +            cn->Base.inA=laCreateInSocket("A", 0);
 | 
	
		
			
				|  |  | +            cn->Base.inB=laCreateInSocket("B", 0);
 | 
	
		
			
				|  |  | +            cn->inFactor=laCreateInSocket("Factor", 0);
 | 
	
		
			
				|  |  | +        }elif(strSame(a->ConfirmData->StrData, "RESULT")){
 | 
	
		
			
				|  |  | +            n=memAcquire(sizeof(CalcResultNode)); CalcResultNode*cn=n; n->Type=CALC_NODE_RESULT;
 | 
	
		
			
				|  |  | +            cn->Base.OutA=laCreateOutSocket(cn, "Out", 0);
 | 
	
		
			
				|  |  | +            cn->inResult=laCreateInSocket("Result", 0);
 | 
	
		
			
				|  |  | +        }elif(strSame(a->ConfirmData->StrData, "REF")){
 | 
	
		
			
				|  |  | +            n=memAcquire(sizeof(CalcRefNode)); CalcRefNode*cn=n; n->Type=CALC_NODE_REF;
 | 
	
		
			
				|  |  | +            cn->Base.OutA=laCreateOutSocket(cn, "Out", 0);
 | 
	
		
			
				|  |  | +            cn->inResult=laCreateInSocket("Result", 0);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        if(n){
 | 
	
		
			
				|  |  | +            lstAppendItem(&cr->Nodes,n);
 | 
	
		
			
				|  |  | +            laRecordAndPushProp(0, "calc"); laNotifyUsers("calc"); laPrintDBInstInfo();
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        return LA_FINISHED_PASS;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    return LA_RUNNING;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +laPropContainer* CalcGetNodeType(CalcNode* n){
 | 
	
		
			
				|  |  | +    switch(n->Type){
 | 
	
		
			
				|  |  | +    case CALC_NODE_NUMBER: return pcNumber;
 | 
	
		
			
				|  |  | +    case CALC_NODE_OP: return pcOp;
 | 
	
		
			
				|  |  | +    case CALC_NODE_MIX: return pcMix;
 | 
	
		
			
				|  |  | +    case CALC_NODE_RESULT: return pcResult;
 | 
	
		
			
				|  |  | +    case CALC_NODE_REF: return pcRef;
 | 
	
		
			
				|  |  | +    default: case CALC_NODE_GENERIC: return pcGeneric;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +void* CalcGetCollection(void* unused,void* unused1){
 | 
	
		
			
				|  |  | +    return CC;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +void *CalcGetFirstCalculator(void* unusedcc, void* unused){
 | 
	
		
			
				|  |  | +    return CC->Calculators.pFirst;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +laBoxedTheme* CalcGetTheme(CalcRack* rack_unused, CalcNode* n){
 | 
	
		
			
				|  |  | +    if(n->Type == CALC_NODE_MIX) return (MAIN.CurrentTheme==LightTheme?DarkTheme:LightTheme);
 | 
	
		
			
				|  |  | +    return 0;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +int CalcGetGap(CalcRack* rack_unused, CalcNode* n){
 | 
	
		
			
				|  |  | +    return n->Gap;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +void CalcSetGap(CalcNode* n, int gap){
 | 
	
		
			
				|  |  | +    if(gap<0){
 | 
	
		
			
				|  |  | +        int done=0;
 | 
	
		
			
				|  |  | +        CalcNode* 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; } }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    if(gap>0){
 | 
	
		
			
				|  |  | +        n->Gap+=gap;
 | 
	
		
			
				|  |  | +        CalcNode* nn=n->Item.pNext; while(nn){ if(nn->Gap>0){ nn->Gap--; break; } nn=nn->Item.pNext; }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +int RegisterCalculator(){
 | 
	
		
			
				|  |  | +    LightTheme=laGetTheme("Classic Light");
 | 
	
		
			
				|  |  | +    DarkTheme=laGetTheme("Classic Dark");
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    CC=memAcquire(sizeof(CalculatorCollection));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    laRegisterUiTemplate("panel_calc", "Calculator", CalcPanel, 0, 0);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    laCreateOperatorType("CALC_add_calculator", "Add Calculator", "Add a calculator", 0,0,0,OPINV_AddCalculator,0,'+',0);
 | 
	
		
			
				|  |  | +    laCreateOperatorType("CALC_add_rack", "Add Rack", "Add a rack into the calculator", 0,0,0,OPINV_AddRack,0,'+',0);
 | 
	
		
			
				|  |  | +    laCreateOperatorType("CALC_add_node", "Add Node", "Add a fruit into the basket or bundle", 0,0,0,OPINV_AddNode_,OPMOD_AddNode_,'+',0)->UiDefine=AddNodesPanel;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    laPropContainer* pc=laDefineRoot();
 | 
	
		
			
				|  |  | +    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);
 | 
	
		
			
				|  |  | +    laProp*p;
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +    pc=laAddPropertyContainer("calc_collection", "Calculator Collection", "Collection of calculators", 0, CalcPanel, sizeof(CalculatorCollection), 0, 0, 1|LA_UDF_LOCAL|LA_UDF_SINGLE);
 | 
	
		
			
				|  |  | +    laAddSubGroup(pc, "calculators", "Calculators","Calculators","calculator",0,0,0,offsetof(CalculatorCollection, CurrentCalculator),0,0,0,0,0,0,offsetof(CalculatorCollection,Calculators),0);
 | 
	
		
			
				|  |  | +    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);
 | 
	
		
			
				|  |  | +    laAddOperatorProperty(pc,"add_calculator", "Add Calculator", "Add a calculator", "CALC_add_calculator", 0, 0);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    pc=laAddPropertyContainer("calculator", "Calculator", "A node-based calculator", 0, UiCalculator, sizeof(Calculator), 0, 0, 2);
 | 
	
		
			
				|  |  | +    laAddStringProperty(pc,"title","Title","Name of the calculator",0,0,0,0,1,offsetof(Calculator,Title),0,0,0,0,LA_AS_IDENTIFIER);
 | 
	
		
			
				|  |  | +    laAddStringProperty(pc,"result","Result","Result produced by the calculator",0,0,0,0,1,offsetof(Calculator,ResultString),0,0,0,0,0);
 | 
	
		
			
				|  |  | +    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);
 | 
	
		
			
				|  |  | +    laAddOperatorProperty(pc,"add_rack", "Add Rack", "Add a rack into the calculator", "CALC_add_rack", 0, 0);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    pc=laAddPropertyContainer("calc_rack", "Rack", "A node rack", 0, UiRack, sizeof(CalcRack), 0, 0, 1);
 | 
	
		
			
				|  |  | +    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);
 | 
	
		
			
				|  |  | +    laSubGroupExtraFunctions(p,0,CalcGetTheme,CalcGetGap);
 | 
	
		
			
				|  |  | +    laAddOperatorProperty(pc,"add_node", "Add Node", "Add a node", "CALC_add_node", 0, 0);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    pcGeneric=pc=laAddPropertyContainer("calc_node", "Node", "A calculator node", 0, 0, sizeof(CalcNode), 0, 0, 1);
 | 
	
		
			
				|  |  | +    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);
 | 
	
		
			
				|  |  | +    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);
 | 
	
		
			
				|  |  | +    laAddEnumItemAs(p,"GENERIC","Generic","Generic", CALC_NODE_GENERIC, 0);
 | 
	
		
			
				|  |  | +    laAddEnumItemAs(p,"NUMBER","Number","Number", CALC_NODE_NUMBER, 0);
 | 
	
		
			
				|  |  | +    laAddEnumItemAs(p,"OP","Op","Op", CALC_NODE_OP, 0);
 | 
	
		
			
				|  |  | +    laAddEnumItemAs(p,"MIX","Mix","Mix", CALC_NODE_MIX, 0);
 | 
	
		
			
				|  |  | +    laAddEnumItemAs(p,"RESULT","Result","Result", CALC_NODE_RESULT, 0);
 | 
	
		
			
				|  |  | +    laAddEnumItemAs(p,"REF","Reference","Reference", CALC_NODE_REF, 0);
 | 
	
		
			
				|  |  | +    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);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    pcNumber=pc=laAddPropertyContainer("calc_number_node", "Number Node", "A node that outputs a constant number", 0, UiCalcNumberNode, sizeof(CalcNumberNode), 0, 0, 1);
 | 
	
		
			
				|  |  | +    laAddSubGroup(pc, "base", "Base","Base","calc_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
 | 
	
		
			
				|  |  | +    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);
 | 
	
		
			
				|  |  | +    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);
 | 
	
		
			
				|  |  | +    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);
 | 
	
		
			
				|  |  | +    laAddEnumItemAs(p,"INT","Integer","Integer", 0, 0);
 | 
	
		
			
				|  |  | +    laAddEnumItemAs(p,"REAL","Real","Real", 1, 0);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    pcOp=pc=laAddPropertyContainer("calc_op_node", "Op Node", "A node that does an operation between two values", 0, UiCalcOpNode, sizeof(CalcOpNode), 0, 0, 1);
 | 
	
		
			
				|  |  | +    laAddSubGroup(pc, "base", "Base","Base","calc_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
 | 
	
		
			
				|  |  | +    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);
 | 
	
		
			
				|  |  | +    laAddEnumItemAs(p,"ADD","Add","A + B", CALC_OP_ADD,0);
 | 
	
		
			
				|  |  | +    laAddEnumItemAs(p,"SUB","Subtract","A - B", CALC_OP_SUB,0);
 | 
	
		
			
				|  |  | +    laAddEnumItemAs(p,"MUL","Multiply","A * B", CALC_OP_MUL,0);
 | 
	
		
			
				|  |  | +    laAddEnumItemAs(p,"DIV","Divide","A / B", CALC_OP_DIV,0);
 | 
	
		
			
				|  |  | +    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);
 | 
	
		
			
				|  |  | +    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);
 | 
	
		
			
				|  |  | +    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);
 | 
	
		
			
				|  |  | +    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);
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +    pcMix=pc=laAddPropertyContainer("calc_mix_node", "Mix Node", "A node that mixes two values", 0, UiCalcMixNode, sizeof(CalcMixNode), 0, 0, 1);
 | 
	
		
			
				|  |  | +    laAddSubGroup(pc, "base", "Base","Base","calc_op_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
 | 
	
		
			
				|  |  | +    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);
 | 
	
		
			
				|  |  | +    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);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    pcResult=pc=laAddPropertyContainer("calc_result_node", "Result Node", "A node that records the result", 0, UiCalcResultNode, sizeof(CalcResultNode), 0, 0, 1);
 | 
	
		
			
				|  |  | +    laAddSubGroup(pc, "base", "Base","Base","calc_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
 | 
	
		
			
				|  |  | +    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);
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +    pcRef=pc=laAddPropertyContainer("calc_ref_node", "Reference Node", "A node that references other calculators", 0, UiCalcRefNode, sizeof(CalcRefNode), 0, 0, 1);
 | 
	
		
			
				|  |  | +    laAddSubGroup(pc, "base", "Base","Base","calc_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
 | 
	
		
			
				|  |  | +    laAddSubGroup(pc, "ref", "Reference","Referenced calculator","calculator",0,0,0,offsetof(CalcRefNode,Reference),CalcGetFirstCalculator,0,laget_ListNext,0,0,0,0,LA_UDF_REFER);
 | 
	
		
			
				|  |  | +    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);
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +    laSaveProp("calc");
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +int OPINV_AddBowl(laOperator* a, laEvent* e){
 | 
	
		
			
				|  |  | +    Bowl* b=memAcquireHyper(sizeof(Bowl));
 | 
	
		
			
				|  |  | +    lstAppendItem(&B.Bowls,b);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    laRecordAndPushProp(0, "basket");laNotifyUsers("basket");
 | 
	
		
			
				|  |  | +    laPrintDBInstInfo();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    return LA_FINISHED;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +int OPINV_RemoveBowl(laOperator* a, laEvent* e){
 | 
	
		
			
				|  |  | +    Bowl* b=a->This?a->This->EndInstance:B.Bowls.pLast; if(!b) return LA_FINISHED;
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +    lstRemoveItem(&B.Bowls, b);
 | 
	
		
			
				|  |  | +    memFree(b);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    laRecordAndPushProp(0, "basket");laNotifyUsers("basket");
 | 
	
		
			
				|  |  | +    laPrintDBInstInfo();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    return LA_FINISHED;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +int OPINV_AddFruit(laOperator* a, laEvent* e){
 | 
	
		
			
				|  |  | +    laListHandle* into=(a->This&&a->This->LastPs->p==pBowl)?&((Bowl*)a->This->EndInstance)->Fruits:0;
 | 
	
		
			
				|  |  | +    if(!into) into=a->This?&((Fruit*)a->This->EndInstance)->Bundled:0;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    char* stype; int size=sizeof(Apple); int type=FRUIT_TYPE_APPLE;
 | 
	
		
			
				|  |  | +    if(stype=strGetArgumentString(a->ExtraInstructionsP,"type")){
 | 
	
		
			
				|  |  | +        if(!strcmp(stype,"pear")) {size=sizeof(Pear);type=FRUIT_TYPE_PEAR;}
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    Fruit* f=memAcquire(size); f->Type=type;
 | 
	
		
			
				|  |  | +    if(into){ lstAppendItem(into, f); f->Parent=into; laNotifyUsers("basket"); /*laNotifyUsersPPPath(a->This,"base.bundled");*/ }
 | 
	
		
			
				|  |  | +    else{ lstAppendItem(&B.Stuff, f); laNotifyUsers("basket");}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    laRecordAndPushProp(0, "basket");
 | 
	
		
			
				|  |  | +    laPrintDBInstInfo();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    return LA_FINISHED;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +void DestroyFruit(Fruit* f){
 | 
	
		
			
				|  |  | +    Fruit* NextF;
 | 
	
		
			
				|  |  | +    for(Fruit*fi=f->Bundled.pFirst;fi;fi=NextF){
 | 
	
		
			
				|  |  | +        NextF=fi->Item.pNext;
 | 
	
		
			
				|  |  | +        DestroyFruit(fi);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    memFree(f);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +int OPINV_RemoveFruit(laOperator* a, laEvent* e){
 | 
	
		
			
				|  |  | +    Fruit* f=a->This?a->This->EndInstance:0; laListHandle* l;
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +    if(f->Parent){ l=f->Parent;lstRemoveItem(l,f); laNotifyUsers("basket"); }
 | 
	
		
			
				|  |  | +    else{ l=&B.Stuff; lstRemoveItem(l,f);laNotifyUsers("basket"); }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    DestroyFruit(f);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    laRecordAndPushProp(0, "basket");
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    return LA_FINISHED;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +int OPINV_MoveFruit(laOperator* a, laEvent* e){
 | 
	
		
			
				|  |  | +    Fruit* f=a->This?a->This->EndInstance:0; laListHandle* l; int direction=0; char* dir;
 | 
	
		
			
				|  |  | +    if(dir=strGetArgumentString(a->ExtraInstructionsP,"direction")){
 | 
	
		
			
				|  |  | +        if(!strcmp(dir,"up")) {direction=1;}
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +    if(f->Parent){ l=f->Parent; laNotifyUsers("basket"); /*laNotifyUsersPPPath(a->This,"base.parent.bundled");*/ }
 | 
	
		
			
				|  |  | +    else{ l=&B.Stuff; laNotifyUsers("basket"); }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if(direction) lstMoveUp(l,f); 
 | 
	
		
			
				|  |  | +    else lstMoveDown(l,f); 
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    laRecordAndPushProp(0, "basket");
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    return LA_FINISHED;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +int OPINV_PushBasketState(laOperator* a, laEvent* e){
 | 
	
		
			
				|  |  | +    laRecordAndPushProp(0, "basket");
 | 
	
		
			
				|  |  | +    logPrint("Pushed state: \"basket\"\n");
 | 
	
		
			
				|  |  | +    return LA_FINISHED;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +laPropContainer* FruitGetType(Fruit* f){
 | 
	
		
			
				|  |  | +    if(f->Type==FRUIT_TYPE_APPLE) return pcApple;
 | 
	
		
			
				|  |  | +    if(f->Type==FRUIT_TYPE_PEAR) return pcPear;
 | 
	
		
			
				|  |  | +    return pcApple;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +void* FruitGetBasket(void* none){
 | 
	
		
			
				|  |  | +    return &B;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +void* BowlGetFirst(void* none, void *UNUSED){
 | 
	
		
			
				|  |  | +    return B.Bowls.pFirst;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +void* FruitGetFirst(void* none, void *UNUSED){
 | 
	
		
			
				|  |  | +    return B.Stuff.pFirst;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +void FruitsPanel(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
 | 
	
		
			
				|  |  | +    laColumn* c=laFirstColumn(uil);
 | 
	
		
			
				|  |  | +    laColumn* cl;
 | 
	
		
			
				|  |  | +    laSplitColumn(uil,c,0.5);
 | 
	
		
			
				|  |  | +    cl=laLeftColumn(c,0);
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +    laShowItem(uil,c,0,"basket");
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +    laUiItem* r=laBeginRow(uil,c,0,0);
 | 
	
		
			
				|  |  | +    strSafeSet(&laShowItem(uil,c,0,"FRUIT_add")->ExtraInstructions,"type=apple;icon=🍏;text=Add Apple;");
 | 
	
		
			
				|  |  | +    strSafeSet(&laShowItem(uil,c,0,"FRUIT_add")->ExtraInstructions,"type=pear;icon=🍐;text=Add Pear;");
 | 
	
		
			
				|  |  | +    laShowItem(uil,c,0,"BOWL_add");
 | 
	
		
			
				|  |  | +    laEndRow(uil,r);
 | 
	
		
			
				|  |  | +    laShowSeparator(uil,c);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    laShowItemFull(uil,c,0,"la.example_string", LA_WIDGET_STRING_MULTI, 0 ,0,0);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    r=laBeginRow(uil,c,0,0);
 | 
	
		
			
				|  |  | +    laShowItem(uil,c,0,"LA_undo");
 | 
	
		
			
				|  |  | +    laShowItem(uil,c,0,"LA_redo");
 | 
	
		
			
				|  |  | +    laShowItem(uil,c,0,"STATE_push");
 | 
	
		
			
				|  |  | +    laEndRow(uil,r);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +void UIBowl(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
 | 
	
		
			
				|  |  | +    laColumn* c=laFirstColumn(uil);
 | 
	
		
			
				|  |  | +    laColumn* cl,*cr;
 | 
	
		
			
				|  |  | +    laSplitColumn(uil,c,0.4);
 | 
	
		
			
				|  |  | +    cl=laLeftColumn(c, 1);
 | 
	
		
			
				|  |  | +    cr=laRightColumn(c,0);
 | 
	
		
			
				|  |  | +    laUiItem*u;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    laUiItem* r=laBeginRow(uil,cr,1,0);
 | 
	
		
			
				|  |  | +    laShowItem(uil,cr,This,"name")->Expand=1;
 | 
	
		
			
				|  |  | +    laShowItem(uil,cr,This,"remove")->Flags|=LA_UI_FLAGS_ICON;
 | 
	
		
			
				|  |  | +    laEndRow(uil,r);
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +    r=laOnConditionToggle(uil,cl,0,0,0,0,0);{
 | 
	
		
			
				|  |  | +        laShowItem(uil,cr,This,"fruits");
 | 
	
		
			
				|  |  | +        laUiItem* r1=laBeginRow(uil,cr,0,0);
 | 
	
		
			
				|  |  | +        strSafeSet(&laShowItem(uil,cr,This,"add_fruit")->ExtraInstructions,"type=apple;icon=🍏;text=Add Apple;");
 | 
	
		
			
				|  |  | +        strSafeSet(&laShowItem(uil,cr,This,"add_fruit")->ExtraInstructions,"type=pear;icon=🍐;text=Add Pear;");
 | 
	
		
			
				|  |  | +        laEndRow(uil,r1);
 | 
	
		
			
				|  |  | +    }laEndCondition(uil,r);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +void UIApple(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
 | 
	
		
			
				|  |  | +    laColumn* c=laFirstColumn(uil);
 | 
	
		
			
				|  |  | +    laColumn* cl,*cr;
 | 
	
		
			
				|  |  | +    laSplitColumn(uil,c,0.4);
 | 
	
		
			
				|  |  | +    cl=laLeftColumn(c, 1);
 | 
	
		
			
				|  |  | +    cr=laRightColumn(c,0);
 | 
	
		
			
				|  |  | +    laUiItem*u;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    laUiItem* r=laBeginRow(uil,cr,1,0);
 | 
	
		
			
				|  |  | +    laShowLabel(uil,cr,"Apple",0,0)->Expand=1;
 | 
	
		
			
				|  |  | +    laShowItem(uil,cr,This,"how_sweet")->Expand=1;
 | 
	
		
			
				|  |  | +    laShowItem(uil,cr,This,"base.why_not")->Expand=1;
 | 
	
		
			
				|  |  | +    laShowItem(uil,cr,This,"base.container")->Expand=1;
 | 
	
		
			
				|  |  | +    laShowItem(uil,cr,This,"base.remove")->Flags|=LA_UI_FLAGS_ICON;
 | 
	
		
			
				|  |  | +    u=laShowItem(uil,cr,This,"base.move"); strSafeSet(&u->ExtraInstructions,"direction=up;icon=🡹;");u->Flags|=LA_UI_FLAGS_ICON;
 | 
	
		
			
				|  |  | +    u=laShowItem(uil,cr,This,"base.move"); strSafeSet(&u->ExtraInstructions,"direction=down;icon=🡻;");u->Flags|=LA_UI_FLAGS_ICON;
 | 
	
		
			
				|  |  | +    laEndRow(uil,r);
 | 
	
		
			
				|  |  | +    r=laOnConditionToggle(uil,cl,0,0,0,0,0);{
 | 
	
		
			
				|  |  | +        laShowItem(uil,cr,This,"base.bundled");
 | 
	
		
			
				|  |  | +        laUiItem* r1=laBeginRow(uil,cr,0,0);
 | 
	
		
			
				|  |  | +        strSafeSet(&laShowItem(uil,cr,This,"base.add")->ExtraInstructions,"type=apple;icon=🍏;text=Add Apple;");
 | 
	
		
			
				|  |  | +        strSafeSet(&laShowItem(uil,cr,This,"base.add")->ExtraInstructions,"type=pear;icon=🍐;text=Add Pear;");
 | 
	
		
			
				|  |  | +        laEndRow(uil,r1);
 | 
	
		
			
				|  |  | +    }laEndCondition(uil,r);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +void UIPear(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
 | 
	
		
			
				|  |  | +    laColumn* c=laFirstColumn(uil);
 | 
	
		
			
				|  |  | +    laColumn* cl,*cr;
 | 
	
		
			
				|  |  | +    laSplitColumn(uil,c,0.4);
 | 
	
		
			
				|  |  | +    cl=laLeftColumn(c, 1);
 | 
	
		
			
				|  |  | +    cr=laRightColumn(c,0);
 | 
	
		
			
				|  |  | +    laUiItem*u;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    laUiItem* r=laBeginRow(uil,cr,1,0);
 | 
	
		
			
				|  |  | +    laShowLabel(uil,cr,"Pear",0,0)->Expand=1;
 | 
	
		
			
				|  |  | +    laShowItem(uil,cr,This,"really")->Expand=1;
 | 
	
		
			
				|  |  | +    laShowItem(uil,cr,This,"base.why_not")->Expand=1;
 | 
	
		
			
				|  |  | +    laShowItem(uil,cr,This,"base.container")->Expand=1;
 | 
	
		
			
				|  |  | +    laShowItem(uil,cr,This,"base.remove")->Flags|=LA_UI_FLAGS_ICON;
 | 
	
		
			
				|  |  | +    u=laShowItem(uil,cr,This,"base.move"); strSafeSet(&u->ExtraInstructions,"direction=up;icon=🡹;");u->Flags|=LA_UI_FLAGS_ICON;
 | 
	
		
			
				|  |  | +    u=laShowItem(uil,cr,This,"base.move"); strSafeSet(&u->ExtraInstructions,"direction=down;icon=🡻;");u->Flags|=LA_UI_FLAGS_ICON;
 | 
	
		
			
				|  |  | +    laEndRow(uil,r);
 | 
	
		
			
				|  |  | +    r=laOnConditionToggle(uil,cl,0,0,0,0,0);{
 | 
	
		
			
				|  |  | +        laShowItem(uil,cr,This,"base.bundled");
 | 
	
		
			
				|  |  | +        laUiItem* r1=laBeginRow(uil,cr,0,0);
 | 
	
		
			
				|  |  | +        strSafeSet(&laShowItem(uil,cr,This,"base.add")->ExtraInstructions,"type=apple;icon=🍏;text=Add Apple;");
 | 
	
		
			
				|  |  | +        strSafeSet(&laShowItem(uil,cr,This,"base.add")->ExtraInstructions,"type=pear;icon=🍐;text=Add Pear;");
 | 
	
		
			
				|  |  | +        laEndRow(uil,r1);
 | 
	
		
			
				|  |  | +    }laEndCondition(uil,r);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +void UIBowlSimple(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
 | 
	
		
			
				|  |  | +    laColumn* c=laFirstColumn(uil);
 | 
	
		
			
				|  |  | +    laShowItemFull(uil,c,This,"name",LA_WIDGET_STRING_PLAIN, 0 ,0,0);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +void UIFruitSimple(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
 | 
	
		
			
				|  |  | +    laColumn* c=laFirstColumn(uil);
 | 
	
		
			
				|  |  | +    laShowItem(uil,c,This,"type");
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +void ScenePanel(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
 | 
	
		
			
				|  |  | +    laColumn* c=laFirstColumn(uil);
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +    laUiItem* ui=laShowCanvas(uil,c,0,"tns.world",0,-1);
 | 
	
		
			
				|  |  | +    laDefault3DViewOverlay(ui);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +int RegisterEverything(){
 | 
	
		
			
				|  |  | +    laRegisterUiTemplate("panel_fruit", "Fruits", FruitsPanel, 0, 0);
 | 
	
		
			
				|  |  | +    laRegisterUiTemplate("panel_scene", "Scene", ScenePanel, 0, 0);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    laCreateOperatorType("BOWL_add", "Add Bowl", "Add a bowl", 0,0,0,OPINV_AddBowl,0,'+',0);
 | 
	
		
			
				|  |  | +    laCreateOperatorType("BOWL_remove", "Remove Bowl", "Remove a bowl", 0,0,0,OPINV_RemoveBowl,0,'-',0);
 | 
	
		
			
				|  |  | +    laCreateOperatorType("FRUIT_add", "Add Fruit", "Add a fruit into the basket or bundle", 0,0,0,OPINV_AddFruit,0,'+',0);
 | 
	
		
			
				|  |  | +    laCreateOperatorType("FRUIT_remove", "Remove Fruit", "Remove a fruit", 0,0,0,OPINV_RemoveFruit,0,'-',0);
 | 
	
		
			
				|  |  | +    laCreateOperatorType("FRUIT_move", "Move Fruit", "Move a fruit", 0,0,0,OPINV_MoveFruit,0,'~',0);
 | 
	
		
			
				|  |  | +    laCreateOperatorType("STATE_push", "Push State", "Push basket state", 0,0,0,OPINV_PushBasketState,0,0,0);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    laPropContainer* pc=laDefineRoot();
 | 
	
		
			
				|  |  | +    laAddSubGroup(pc, "basket", "Basket", "The basket", "basket",0,0,0,-1,FruitGetBasket,0,0,0,0,0,0,LA_UDF_SINGLE|LA_UDF_LOCAL);
 | 
	
		
			
				|  |  | +    laProp*p;
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +    pc=laAddPropertyContainer("bowl", "Bowl", "Some sort of a bowl", 0, UIBowl, sizeof(Bowl), 0, 0, 2);
 | 
	
		
			
				|  |  | +    laAddStringProperty(pc,"name","Name","Name of the bowl",0,0,0,0,1,offsetof(Bowl,Name),0,0,0,0,LA_AS_IDENTIFIER);
 | 
	
		
			
				|  |  | +    laAddSubGroup(pc, "fruits", "Fruits","Fruits","fruit",FruitGetType,0,0,-1,0,0,0,0,0,0,offsetof(Bowl,Fruits),0);
 | 
	
		
			
				|  |  | +    laAddOperatorProperty(pc,"remove","Remove","Remove a bowl", "BOWL_remove", '-', 0);
 | 
	
		
			
				|  |  | +    laAddOperatorProperty(pc,"add_fruit","Add","Add a fruit into the bowl", "FRUIT_add", '+', 0);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    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);
 | 
	
		
			
				|  |  | +    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);
 | 
	
		
			
				|  |  | +    laAddStringProperty(pc,"name","Name","Name of the basket",0,0,0,0,1,offsetof(Basket,name),0,0,0,0,LA_UDF_REFER);
 | 
	
		
			
				|  |  | +    laAddSubGroup(pc, "stuff", "Stuff","Stuffs","fruit",FruitGetType,0,0,-1,0,0,0,0,0,0,offsetof(Basket,Stuff),0);
 | 
	
		
			
				|  |  | +    pBowl = laAddSubGroup(pc, "bowls", "Bows","Bows","bowl",0,0,0,-1,0,0,0,0,0,0,offsetof(Basket,Bowls),0);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    pc=laAddPropertyContainer("fruit", "Fruit", "A fruit", 0, 0, sizeof(Fruit), 0, 0, 1);
 | 
	
		
			
				|  |  | +    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);
 | 
	
		
			
				|  |  | +    laAddEnumItemAs(p,"APPLE","Apple","Apple", FRUIT_TYPE_APPLE, L'🍏');
 | 
	
		
			
				|  |  | +    laAddEnumItemAs(p,"PEAR","Pear","Pear", FRUIT_TYPE_PEAR, L'🍐');
 | 
	
		
			
				|  |  | +    pFruit = laAddSubGroup(pc, "bundled", "Bundled","Bundled","fruit",FruitGetType,0,0,-1,0,0,0,0,0,0,offsetof(Fruit,Bundled),0);
 | 
	
		
			
				|  |  | +    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);
 | 
	
		
			
				|  |  | +    laAddSubGroup(pc, "parent", "Parent","Parent","any_pointer",0,0,0,offsetof(Fruit,Parent),0,0,0,0,0,0,0,LA_UDF_REFER);
 | 
	
		
			
				|  |  | +    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);
 | 
	
		
			
				|  |  | +    laAddOperatorProperty(pc,"add","Add","Add a fruit into bundled", "FRUIT_add", '+', 0);
 | 
	
		
			
				|  |  | +    laAddOperatorProperty(pc,"remove","Remove","Remove a fruit", "FRUIT_remove", '-', 0);
 | 
	
		
			
				|  |  | +    laAddOperatorProperty(pc,"move","Move","Move a fruit", "FRUIT_move", '~', 0);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    pcApple=pc=laAddPropertyContainer("apple", "Apple", "An apple", 0, UIApple, sizeof(Apple), 0, 0, 1);
 | 
	
		
			
				|  |  | +    laAddSubGroup(pc,"base", "Base","Base fruit","fruit",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_SINGLE|LA_UDF_LOCAL);
 | 
	
		
			
				|  |  | +    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);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    pcPear=pc=laAddPropertyContainer("pear", "Pear", "A pear", 0, UIPear, sizeof(Pear), 0, 0, 1);
 | 
	
		
			
				|  |  | +    laAddSubGroup(pc, "base","Base","Base fruit","fruit",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_SINGLE|LA_UDF_LOCAL);
 | 
	
		
			
				|  |  | +    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);
 | 
	
		
			
				|  |  | +    laAddEnumItemAs(p,"NAH","Nah","Nah I don't think so", 0, L'🤔');
 | 
	
		
			
				|  |  | +    laAddEnumItemAs(p,"YEAH","Yeah","It's really a pear", 1, L'😄');
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +    laSaveProp("basket");
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    tnsObject* s=tnsCreateRootObject("My Root");
 | 
	
		
			
				|  |  | +    tnsObject* o=tnsCreateLight(s,"Sun",100,100,100,1,1);
 | 
	
		
			
				|  |  | +    tnsVector3d target={0,0,0}, up={0,0,1};
 | 
	
		
			
				|  |  | +    tnsLookAt(o,target,up);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +//void la_DetachedPanel1(laPanel* p){
 | 
	
		
			
				|  |  | +//    la_MakeDetachedProp(p, "tns.texture_list", "tex");
 | 
	
		
			
				|  |  | +//}
 | 
	
		
			
				|  |  | +//void la_PanelHeader1(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *cr, int context){
 | 
	
		
			
				|  |  | +//    laColumn* c=cr?cr:laFirstColumn(uil);
 | 
	
		
			
				|  |  | +//    laShowItemFull(uil,c,DetachedProps,"tex", LA_WIDGET_COLLECTION_SELECTOR, 0 ,0,0);
 | 
	
		
			
				|  |  | +//}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +int main(int argc, char *argv[]){
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    laGetReady();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    RegisterEverything();
 | 
	
		
			
				|  |  | +    RegisterCalculator();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    laRefreshUDFRegistries();
 | 
	
		
			
				|  |  | +    laEnsureUserPreferences();
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +    laAddRootDBInst("calc");
 | 
	
		
			
				|  |  | +    laAddRootDBInst("basket");
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    laWindow* w = laDesignWindow(-1,-1,600,600);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    laLayout* l = laDesignLayout(w, "Second Layout");
 | 
	
		
			
				|  |  | +    laBlock* b = l->FirstBlock;
 | 
	
		
			
				|  |  | +    laPanel* p=laCreatePanel(b, "LAUI_user_preferences");
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    l = laDesignLayout(w, "First Layout");
 | 
	
		
			
				|  |  | +    b = l->FirstBlock;
 | 
	
		
			
				|  |  | +    p=laCreatePanel(b, "panel_fruit");
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    l = laDesignLayout(w, "Scene Layout");
 | 
	
		
			
				|  |  | +    b = l->FirstBlock;
 | 
	
		
			
				|  |  | +    p=laCreatePanel(b, "panel_scene");
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +    l = laDesignLayout(w, "Nodes Layout");
 | 
	
		
			
				|  |  | +    b = l->FirstBlock;
 | 
	
		
			
				|  |  | +    p=laCreatePanel(b, "panel_nodes");
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    laStartWindow(w);
 | 
	
		
			
				|  |  | +    laMainLoop();
 | 
	
		
			
				|  |  | +}
 |