|  | @@ -13,6 +13,7 @@ laBaseNodeType LA_IDN_COMBINE;
 | 
											
												
													
														|  |  laBaseNodeType LA_IDN_VALUES;
 |  |  laBaseNodeType LA_IDN_VALUES;
 | 
											
												
													
														|  |  laBaseNodeType LA_IDN_MATRIX;
 |  |  laBaseNodeType LA_IDN_MATRIX;
 | 
											
												
													
														|  |  laBaseNodeType LA_IDN_MATH;
 |  |  laBaseNodeType LA_IDN_MATH;
 | 
											
												
													
														|  | 
 |  | +laBaseNodeType LA_IDN_MAPPER;
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  laPropContainer* LA_PC_IDN_GENERIC;
 |  |  laPropContainer* LA_PC_IDN_GENERIC;
 | 
											
												
													
														|  |  laPropContainer* LA_PC_IDN_KEYBOARD;
 |  |  laPropContainer* LA_PC_IDN_KEYBOARD;
 | 
											
										
											
												
													
														|  | @@ -25,6 +26,7 @@ laPropContainer* LA_PC_IDN_COMBINE;
 | 
											
												
													
														|  |  laPropContainer* LA_PC_IDN_VALUES;
 |  |  laPropContainer* LA_PC_IDN_VALUES;
 | 
											
												
													
														|  |  laPropContainer* LA_PC_IDN_MATRIX;
 |  |  laPropContainer* LA_PC_IDN_MATRIX;
 | 
											
												
													
														|  |  laPropContainer* LA_PC_IDN_MATH;
 |  |  laPropContainer* LA_PC_IDN_MATH;
 | 
											
												
													
														|  | 
 |  | +laPropContainer* LA_PC_IDN_MAPPER;
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  laNodeCategory* LA_NODE_CATEGORY_INPUT;
 |  |  laNodeCategory* LA_NODE_CATEGORY_INPUT;
 | 
											
												
													
														|  |  laNodeCategory* LA_NODE_CATEGORY_MATH;
 |  |  laNodeCategory* LA_NODE_CATEGORY_MATH;
 | 
											
										
											
												
													
														|  | @@ -467,6 +469,47 @@ void laui_MathNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn
 | 
											
												
													
														|  |      laEndRow(uil,b);
 |  |      laEndRow(uil,b);
 | 
											
												
													
														|  |  }
 |  |  }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | 
 |  | +void IDN_MapperInit(laMapperNode* n){
 | 
											
												
													
														|  | 
 |  | +    strSafeSet(&n->Base.Name,"Mapper");
 | 
											
												
													
														|  | 
 |  | +    n->In=laCreateInSocket("IN",LA_PROP_FLOAT); n->Out=laCreateOutSocket(n,"OUT",LA_PROP_FLOAT);n->Out->Data=&n->rOut;
 | 
											
												
													
														|  | 
 |  | +    n->Mapper=laValueMapperInit();
 | 
											
												
													
														|  | 
 |  | +}
 | 
											
												
													
														|  | 
 |  | +void IDN_MapperDestroy(laMapperNode* n){
 | 
											
												
													
														|  | 
 |  | +    strSafeDestroy(&n->Base.Name);
 | 
											
												
													
														|  | 
 |  | +    laDestroyInSocket(n->In); laDestroyOutSocket(n->Out);
 | 
											
												
													
														|  | 
 |  | +    laValueMapperDestroy(n->Mapper); n->Mapper=0;
 | 
											
												
													
														|  | 
 |  | +}
 | 
											
												
													
														|  | 
 |  | +int IDN_MapperVisit(laMapperNode* n, laListHandle* l){
 | 
											
												
													
														|  | 
 |  | +    LA_GUARD_THIS_NODE(n);
 | 
											
												
													
														|  | 
 |  | +    if(LA_SRC_AND_PARENT(n->In)){ laBaseNode* bn=n->In->Source->Parent; LA_VISIT_NODE(bn); }
 | 
											
												
													
														|  | 
 |  | +    n->Base.Eval=LA_DAG_FLAG_PERM;
 | 
											
												
													
														|  | 
 |  | +    lstAppendPointer(l, n);
 | 
											
												
													
														|  | 
 |  | +    return LA_DAG_FLAG_PERM;
 | 
											
												
													
														|  | 
 |  | +}
 | 
											
												
													
														|  | 
 |  | +int IDN_MapperEval(laMapperNode* n){
 | 
											
												
													
														|  | 
 |  | +    real in=0;
 | 
											
												
													
														|  | 
 |  | +    if(LA_SRC_AND_PARENT(n->In) && (n->In->Source->DataType&LA_PROP_FLOAT)){ in=*((real*)n->In->Source->Data); }
 | 
											
												
													
														|  | 
 |  | +    real result=laValueMapperEvaluate(n->Mapper,in);
 | 
											
												
													
														|  | 
 |  | +    n->rOut=result;
 | 
											
												
													
														|  | 
 |  | +    return 1;
 | 
											
												
													
														|  | 
 |  | +}
 | 
											
												
													
														|  | 
 |  | +void laui_MapperNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){
 | 
											
												
													
														|  | 
 |  | +    laColumn* c=laFirstColumn(uil); laMapperNode*n=This->EndInstance;
 | 
											
												
													
														|  | 
 |  | +    laColumn* cl,*cr; laSplitColumn(uil,c,0.4); cl=laLeftColumn(c,3); cr=laRightColumn(c,0);
 | 
											
												
													
														|  | 
 |  | +    laUiItem*b,*b2;
 | 
											
												
													
														|  | 
 |  | +    LA_BASE_NODE_HEADER(uil,c,This);
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    b=laBeginRow(uil,c,0,0);
 | 
											
												
													
														|  | 
 |  | +    laShowNodeSocket(uil,c,This,"in",0)->Flags|=LA_UI_SOCKET_LABEL_E; laShowItem(uil,c,This,"mapper.in_range")->Expand=1;
 | 
											
												
													
														|  | 
 |  | +    laEndRow(uil,b);
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    laShowItem(uil,c,This,"mapper");
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    b=laBeginRow(uil,c,0,0);
 | 
											
												
													
														|  | 
 |  | +    laShowItem(uil,c,This,"mapper.out_range")->Expand=1;laShowNodeSocket(uil,c,This,"out",0)->Flags|=LA_UI_SOCKET_LABEL_W;
 | 
											
												
													
														|  | 
 |  | +    laEndRow(uil,b);
 | 
											
												
													
														|  | 
 |  | +}
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  int OPINV_AddInputMapperPage(laOperator* a, laEvent *e){
 |  |  int OPINV_AddInputMapperPage(laOperator* a, laEvent *e){
 | 
											
												
													
														|  |      laRackPage* dp=memAcquireHyper(sizeof(laRackPage));
 |  |      laRackPage* dp=memAcquireHyper(sizeof(laRackPage));
 | 
											
										
											
												
													
														|  | @@ -561,6 +604,7 @@ int OPINV_DeleteNode(laOperator* a, laEvent *e){
 | 
											
												
													
														|  |      laNodeRack* parent=n->InRack;
 |  |      laNodeRack* parent=n->InRack;
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |      lstRemoveItem(&n->InRack->Nodes, n); n->Type->Destroy(n); memLeave(n);
 |  |      lstRemoveItem(&n->InRack->Nodes, n); n->Type->Destroy(n); memLeave(n);
 | 
											
												
													
														|  | 
 |  | +    laMappingRequestRebuild(); laDriverRequestRebuild();
 | 
											
												
													
														|  |      laNotifyInstanceUsers(parent); laRecordInstanceDifferences(parent,"la_node_rack"); laPushDifferences("Delete Node", 0);
 |  |      laNotifyInstanceUsers(parent); laRecordInstanceDifferences(parent,"la_node_rack"); laPushDifferences("Delete Node", 0);
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |      return LA_FINISHED;
 |  |      return LA_FINISHED;
 | 
											
										
											
												
													
														|  | @@ -854,6 +898,16 @@ void la_RegisterInputMapperOperators(){
 | 
											
												
													
														|  |      laAddEnumItemAs(p,"ATAN", "Arctangent", "atan(L)", LA_MATH_NODE_OP_ATAN, 0);
 |  |      laAddEnumItemAs(p,"ATAN", "Arctangent", "atan(L)", LA_MATH_NODE_OP_ATAN, 0);
 | 
											
												
													
														|  |      laAddEnumItemAs(p,"ATAN2", "Atan2", "atan2(L,R) where L or R can be zero", LA_MATH_NODE_OP_ATAN2, 0);
 |  |      laAddEnumItemAs(p,"ATAN2", "Atan2", "atan2(L,R) where L or R can be zero", LA_MATH_NODE_OP_ATAN2, 0);
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | 
 |  | +    pc=laAddPropertyContainer("la_mapper_node", "Mapper", "Mapper node",0,laui_MapperNode,sizeof(laMapperNode),0,0,1);
 | 
											
												
													
														|  | 
 |  | +    LA_PC_IDN_MAPPER=pc; laPropContainerExtraFunctions(pc,0,0,0,0,laui_DefaultNodeOperationsPropUiDefine);
 | 
											
												
													
														|  | 
 |  | +    laAddSubGroup(pc,"base","Base","Base node","la_base_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
 | 
											
												
													
														|  | 
 |  | +    laAddSubGroup(pc,"in", "In","Input value","la_in_socket",0,0,0,offsetof(laMapperNode, In),0,0,0,0,0,0,0,LA_UDF_SINGLE);
 | 
											
												
													
														|  | 
 |  | +    laAddSubGroup(pc,"out", "Out","Output value","la_out_socket",0,0,0,offsetof(laMapperNode, Out),0,0,0,0,0,0,0,LA_UDF_SINGLE);
 | 
											
												
													
														|  | 
 |  | +    laAddSubGroup(pc,"mapper", "Mapper","Value mapper","la_value_mapper",0,LA_WIDGET_MAPPER,0,offsetof(laMapperNode, Mapper),0,0,0,0,0,0,0,LA_UDF_SINGLE);
 | 
											
												
													
														|  | 
 |  | +    p=laAddEnumProperty(pc,"clamp", "Clamp", "Clamp output", LA_WIDGET_ENUM_HIGHLIGHT,0,0,0,0,offsetof(laMapperNode,Clamp),0,0,0,0,0,0,0,0,0,0);
 | 
											
												
													
														|  | 
 |  | +    laAddEnumItemAs(p,"NONE", "None", "Don't clamp output", 0, 0);
 | 
											
												
													
														|  | 
 |  | +    laAddEnumItemAs(p,"CLAMP", "Clamp", "Clamp output to specified range", 1, 0);
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |      LA_IDN_REGISTER("Controller",L'🕹',LA_IDN_CONTROLLER,LA_PC_IDN_CONTROLLER, IDN_ControllerInit, IDN_ControllerDestroy, IDN_ControllerVisit, IDN_ControllerEval, laInputControllerNode);
 |  |      LA_IDN_REGISTER("Controller",L'🕹',LA_IDN_CONTROLLER,LA_PC_IDN_CONTROLLER, IDN_ControllerInit, IDN_ControllerDestroy, IDN_ControllerVisit, IDN_ControllerEval, laInputControllerNode);
 | 
											
												
													
														|  |      LA_IDN_REGISTER("Visualizer",L'🔍',LA_IDN_VISUALIZER,LA_PC_IDN_VISUALIZER, IDN_InputVisualizeInit, IDN_InputVisualizeDestroy, IDN_InputVisualizeVisit, IDN_InputVisualizerEval, laInputVisualizerNode);
 |  |      LA_IDN_REGISTER("Visualizer",L'🔍',LA_IDN_VISUALIZER,LA_PC_IDN_VISUALIZER, IDN_InputVisualizeInit, IDN_InputVisualizeDestroy, IDN_InputVisualizeVisit, IDN_InputVisualizerEval, laInputVisualizerNode);
 | 
											
												
													
														|  |      LA_IDN_REGISTER("Split",L'⚟',LA_IDN_SPLIT,LA_PC_IDN_SPLIT, IDN_SplitInit, IDN_SplitDestroy, IDN_SplitVisit, IDN_SplitEval, laSplitNode);
 |  |      LA_IDN_REGISTER("Split",L'⚟',LA_IDN_SPLIT,LA_PC_IDN_SPLIT, IDN_SplitInit, IDN_SplitDestroy, IDN_SplitVisit, IDN_SplitEval, laSplitNode);
 | 
											
										
											
												
													
														|  | @@ -862,13 +916,14 @@ void la_RegisterInputMapperOperators(){
 | 
											
												
													
														|  |      LA_IDN_REGISTER("Values",0,LA_IDN_VALUES,LA_PC_IDN_VALUES, IDN_ValuesInit, IDN_ValuesDestroy, IDN_ValuesVisit, IDN_ValuesEval, laValuesNode);
 |  |      LA_IDN_REGISTER("Values",0,LA_IDN_VALUES,LA_PC_IDN_VALUES, IDN_ValuesInit, IDN_ValuesDestroy, IDN_ValuesVisit, IDN_ValuesEval, laValuesNode);
 | 
											
												
													
														|  |      LA_IDN_REGISTER("Matrix",0,LA_IDN_MATRIX,LA_PC_IDN_MATRIX, IDN_MatrixInit, IDN_MatrixDestroy, IDN_MatrixVisit, IDN_MatrixEval, laMatrixNode);
 |  |      LA_IDN_REGISTER("Matrix",0,LA_IDN_MATRIX,LA_PC_IDN_MATRIX, IDN_MatrixInit, IDN_MatrixDestroy, IDN_MatrixVisit, IDN_MatrixEval, laMatrixNode);
 | 
											
												
													
														|  |      LA_IDN_REGISTER("Math",0,LA_IDN_MATH,LA_PC_IDN_MATH, IDN_MathInit, IDN_MathDestroy, IDN_MathVisit, IDN_MathEval, laMathNode);
 |  |      LA_IDN_REGISTER("Math",0,LA_IDN_MATH,LA_PC_IDN_MATH, IDN_MathInit, IDN_MathDestroy, IDN_MathVisit, IDN_MathEval, laMathNode);
 | 
											
												
													
														|  | 
 |  | +    LA_IDN_REGISTER("Mapper",0,LA_IDN_MAPPER,LA_PC_IDN_MAPPER, IDN_MapperInit, IDN_MapperDestroy, IDN_MapperVisit, IDN_MapperEval, laMapperNode);
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |      LA_NODE_CATEGORY_INPUT=laAddNodeCategory("Input",0,LA_RACK_TYPE_INPUT);
 |  |      LA_NODE_CATEGORY_INPUT=laAddNodeCategory("Input",0,LA_RACK_TYPE_INPUT);
 | 
											
												
													
														|  |      LA_NODE_CATEGORY_MATH=laAddNodeCategory("Math",0,LA_RACK_TYPE_ALL);
 |  |      LA_NODE_CATEGORY_MATH=laAddNodeCategory("Math",0,LA_RACK_TYPE_ALL);
 | 
											
												
													
														|  |      LA_NODE_CATEGORY_ROUTE=laAddNodeCategory("Route",0,LA_RACK_TYPE_ALL);
 |  |      LA_NODE_CATEGORY_ROUTE=laAddNodeCategory("Route",0,LA_RACK_TYPE_ALL);
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |      laNodeCategoryAddNodeTypes(LA_NODE_CATEGORY_INPUT, &LA_IDN_CONTROLLER,0);
 |  |      laNodeCategoryAddNodeTypes(LA_NODE_CATEGORY_INPUT, &LA_IDN_CONTROLLER,0);
 | 
											
												
													
														|  | -    laNodeCategoryAddNodeTypes(LA_NODE_CATEGORY_MATH, &LA_IDN_MATRIX,&LA_IDN_MATH,0);
 |  | 
 | 
											
												
													
														|  | 
 |  | +    laNodeCategoryAddNodeTypes(LA_NODE_CATEGORY_MATH, &LA_IDN_MATRIX,&LA_IDN_MATH,&LA_IDN_MAPPER,0);
 | 
											
												
													
														|  |      laNodeCategoryAddNodeTypes(LA_NODE_CATEGORY_ROUTE, &LA_IDN_SPLIT, &LA_IDN_SWITCH, &LA_IDN_COMBINE, &LA_IDN_VALUES, &LA_IDN_VISUALIZER,0);
 |  |      laNodeCategoryAddNodeTypes(LA_NODE_CATEGORY_ROUTE, &LA_IDN_SPLIT, &LA_IDN_SWITCH, &LA_IDN_COMBINE, &LA_IDN_VALUES, &LA_IDN_VISUALIZER,0);
 | 
											
												
													
														|  |  }
 |  |  }
 | 
											
												
													
														|  |  
 |  |  
 |