|  | @@ -23,9 +23,11 @@ extern struct _tnsMain *T;
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  laBaseNodeType TNS_IDN_TRANSFORM;
 |  |  laBaseNodeType TNS_IDN_TRANSFORM;
 | 
											
												
													
														|  |  laBaseNodeType TNS_IDN_MAKE_TRANSFORM;
 |  |  laBaseNodeType TNS_IDN_MAKE_TRANSFORM;
 | 
											
												
													
														|  | 
 |  | +laBaseNodeType TNS_IDN_ACTION_PLAYER;
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  laPropContainer* TNS_PC_IDN_TRANSFORM;
 |  |  laPropContainer* TNS_PC_IDN_TRANSFORM;
 | 
											
												
													
														|  |  laPropContainer* TNS_PC_IDN_MAKE_TRANSFORM;
 |  |  laPropContainer* TNS_PC_IDN_MAKE_TRANSFORM;
 | 
											
												
													
														|  | 
 |  | +laPropContainer* TNS_PC_IDN_ACTION_PLAYER;
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  void IDN_TransformInit(tnsTransformNode* n, int NoCreate){
 |  |  void IDN_TransformInit(tnsTransformNode* n, int NoCreate){
 | 
											
												
													
														|  |      if(NoCreate){return;}
 |  |      if(NoCreate){return;}
 | 
											
										
											
												
													
														|  | @@ -141,6 +143,74 @@ void tnsui_MakeTransformNode(laUiList *uil, laPropPack *This, laPropPack *Extra,
 | 
											
												
													
														|  |      laEndRow(uil,b);
 |  |      laEndRow(uil,b);
 | 
											
												
													
														|  |  }
 |  |  }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +void IDN_ActionPlayerInit(tnsActionPlayerNode* n, int NoCreate){
 | 
											
												
													
														|  | 
 |  | +    if(NoCreate){ return; }
 | 
											
												
													
														|  | 
 |  | +    strSafeSet(&n->Base.Name,"Make Transform");
 | 
											
												
													
														|  | 
 |  | +    n->Next=laCreateOutSocket(n,"NEXT",0); n->Prev=laCreateInSocket("PREV",0);
 | 
											
												
													
														|  | 
 |  | +    n->Transport=laCreateInSocket("TRANSPORT",0); n->Detached=laCreateInSocket("DETACHED",0); n->Time=laCreateInSocket("TIME",0);
 | 
											
												
													
														|  | 
 |  | +}
 | 
											
												
													
														|  | 
 |  | +void IDN_ActionPlayerDestroy(tnsActionPlayerNode* n){
 | 
											
												
													
														|  | 
 |  | +    laDestroyInSocket(n->Prev); laDestroyOutSocket(n->Next); strSafeDestroy(&n->Base.Name);
 | 
											
												
													
														|  | 
 |  | +    laDestroyInSocket(n->Transport); laDestroyInSocket(n->Time); laDestroyInSocket(n->Detached);
 | 
											
												
													
														|  | 
 |  | +}
 | 
											
												
													
														|  | 
 |  | +int IDN_ActionPlayerVisit(tnsActionPlayerNode* n, laNodeVisitInfo* vi){
 | 
											
												
													
														|  | 
 |  | +    LA_GUARD_THIS_NODE(n,vi);
 | 
											
												
													
														|  | 
 |  | +    if(LA_SRC_AND_PARENT(n->Prev)){ laBaseNode*bn=n->Prev->Source->Parent; LA_VISIT_NODE(bn,vi); }
 | 
											
												
													
														|  | 
 |  | +    LA_ADD_THIS_NODE(n,vi);
 | 
											
												
													
														|  | 
 |  | +    return LA_DAG_FLAG_PERM;
 | 
											
												
													
														|  | 
 |  | +}
 | 
											
												
													
														|  | 
 |  | +int IDN_ActionPlayerEval(tnsActionPlayerNode* n){
 | 
											
												
													
														|  | 
 |  | +    if(!T->Runtime.CurrentEN || !n->Action){ return 1; } tnsEvaluatedNode* en=T->Runtime.CurrentEN;
 | 
											
												
													
														|  | 
 |  | +    int transport = n->iTransport; LA_GET_SRC_AS_VALUE(transport,n->Transport);
 | 
											
												
													
														|  | 
 |  | +    int detached = n->iDetached; LA_GET_SRC_AS_VALUE(detached,n->Detached);
 | 
											
												
													
														|  | 
 |  | +    real time = 0; int has_time=n->Time->Source?1:0; LA_GET_SRC_AS_VALUE(time,n->Time);
 | 
											
												
													
														|  | 
 |  | +    if(en->ActionRetarget){
 | 
											
												
													
														|  | 
 |  | +        laActionRetarget* ar=en->ActionRetarget;
 | 
											
												
													
														|  | 
 |  | +        en->ActionRetarget->DetachedInNode = detached;
 | 
											
												
													
														|  | 
 |  | +        if(!en->ActionRetarget->DetachedInNode){ ar=((tnsRootObject*)en->Target)->ActionRetarget; }
 | 
											
												
													
														|  | 
 |  | +        laRetargetedAction* ra=la_AnimationGetRetargetedAction(ar,n->Action); if(!ra){ return 1; }
 | 
											
												
													
														|  | 
 |  | +        ra->PlayStatus = transport; if(has_time){ ra->PlayHead = time; }
 | 
											
												
													
														|  | 
 |  | +    }else{
 | 
											
												
													
														|  | 
 |  | +        tnsRootObject* o=en->Target; if(o->Base.Type!=TNS_OBJECT_ROOT){ return 1; }
 | 
											
												
													
														|  | 
 |  | +        if(has_time){ n->Action->Offset=0; n->Action->PlayHead=time; }
 | 
											
												
													
														|  | 
 |  | +    }
 | 
											
												
													
														|  | 
 |  | +    return 1;
 | 
											
												
													
														|  | 
 |  | +}
 | 
											
												
													
														|  | 
 |  | +void IDN_ActionPlayerCopy(tnsActionPlayerNode* new, tnsActionPlayerNode* old, int DoRematch){
 | 
											
												
													
														|  | 
 |  | +    if(DoRematch){ LA_IDN_NEW_LINK(Prev) return; }
 | 
											
												
													
														|  | 
 |  | +    old->Next->Duplicated=new->Next; new->Time=old->Time; new->Transport=old->Transport; new->Detached=old->Detached;
 | 
											
												
													
														|  | 
 |  | +    new->iDetached = old->iDetached; new->iTransport = old->iTransport;
 | 
											
												
													
														|  | 
 |  | +}
 | 
											
												
													
														|  | 
 |  | +void tnsui_ActionPlayerNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){
 | 
											
												
													
														|  | 
 |  | +    laColumn* c=laFirstColumn(uil),*cl,*cr,*cll,*clr;
 | 
											
												
													
														|  | 
 |  | +    LA_BASE_NODE_HEADER(uil,c,This);
 | 
											
												
													
														|  | 
 |  | +    laSplitColumn(uil,c,0.6); cl=laLeftColumn(c,0); cr=laRightColumn(c,3);
 | 
											
												
													
														|  | 
 |  | +    laSplitColumn(uil,cl,0.4); cll=laLeftColumn(cl,3); clr=laRightColumn(cl,0);
 | 
											
												
													
														|  | 
 |  | +    tnsActionPlayerNode*n=This->EndInstance;
 | 
											
												
													
														|  | 
 |  | +    laUiItem* b2, *rui;
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    laShowNodeSocket(uil,cr,This,"prev",0)->Flags|=LA_UI_SOCKET_LABEL_W;
 | 
											
												
													
														|  | 
 |  | +    laShowNodeSocket(uil,cr,This,"next",0)->Flags|=LA_UI_SOCKET_LABEL_W;
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    laUiItem* b=laBeginRow(uil,cl,0,0);
 | 
											
												
													
														|  | 
 |  | +    laShowNodeSocket(uil,cl,This,"in_transport",0); b2=laOnConditionThat(uil,c,laNot(laPropExpression(This,"in_transport.source")));{
 | 
											
												
													
														|  | 
 |  | +        laShowItemFull(uil,cl,This,"transport",0,"text=Transport",0,0)->Expand=1;
 | 
											
												
													
														|  | 
 |  | +    }laElse(uil,b2);{
 | 
											
												
													
														|  | 
 |  | +        laShowLabel(uil,cl,"Transport",0,0)->Expand=1;
 | 
											
												
													
														|  | 
 |  | +    }laEndCondition(uil,b2);
 | 
											
												
													
														|  | 
 |  | +    laShowNodeSocket(uil,cl,This,"in_detached",0); b2=laOnConditionThat(uil,c,laNot(laPropExpression(This,"in_detached.source")));{
 | 
											
												
													
														|  | 
 |  | +        laShowItemFull(uil,cl,This,"detached",0,"text=Detached",0,0)->Expand=1;
 | 
											
												
													
														|  | 
 |  | +    }laElse(uil,b2);{
 | 
											
												
													
														|  | 
 |  | +        laShowLabel(uil,cl,"Detached",0,0)->Expand=1;
 | 
											
												
													
														|  | 
 |  | +    }laEndCondition(uil,b2);
 | 
											
												
													
														|  | 
 |  | +    laEndRow(uil,b);
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    laShowNodeSocket(uil,cll,This,"in_time",0)->Flags|=LA_UI_SOCKET_LABEL_E;
 | 
											
												
													
														|  | 
 |  | +    laShowItemFull(uil,clr,This,"action",LA_WIDGET_COLLECTION_SELECTOR,0,laui_IdentifierOnly,0);
 | 
											
												
													
														|  | 
 |  | +}
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |  int OPCHK_AddDriverPage(laPropPack *This, laStringSplitor *ss){
 |  |  int OPCHK_AddDriverPage(laPropPack *This, laStringSplitor *ss){
 | 
											
												
													
														|  |      if (This && la_EnsureSubTarget(This->LastPs->p,0) == TNS_PC_OBJECT_GENERIC) return 1;
 |  |      if (This && la_EnsureSubTarget(This->LastPs->p,0) == TNS_PC_OBJECT_GENERIC) return 1;
 | 
											
												
													
														|  |      return 0;
 |  |      return 0;
 | 
											
										
											
												
													
														|  | @@ -192,6 +262,10 @@ int OPINV_RebuildDrivers(laOperator* a, laEvent *e){
 | 
											
												
													
														|  |  tnsObject* tnsget_FirstObject(void* unused, void* unused2){
 |  |  tnsObject* tnsget_FirstObject(void* unused, void* unused2){
 | 
											
												
													
														|  |      return T->World->AllObjects.pFirst;
 |  |      return T->World->AllObjects.pFirst;
 | 
											
												
													
														|  |  }
 |  |  }
 | 
											
												
													
														|  | 
 |  | +laAction* tnsget_FirstActionFromActionPlayer(tnsActionPlayerNode* apn, void* unused2){
 | 
											
												
													
														|  | 
 |  | +    if(!apn->Base.InRack || !apn->Base.InRack->ParentPage || !apn->Base.InRack->ParentPage->ParentObject) return 0;
 | 
											
												
													
														|  | 
 |  | +    tnsRootObject* ro = apn->Base.InRack->ParentPage->ParentObject; return ro->Actions.pFirst;
 | 
											
												
													
														|  | 
 |  | +}
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  void tns_RegisterNodes(){
 |  |  void tns_RegisterNodes(){
 | 
											
												
													
														|  |      laPropContainer *pc; laProp *p;
 |  |      laPropContainer *pc; laProp *p;
 | 
											
										
											
												
													
														|  | @@ -225,11 +299,28 @@ void tns_RegisterNodes(){
 | 
											
												
													
														|  |      laAddFloatProperty(pc,"use_rot", "Rotation", "Use Rotation",0,"X,Y,Z",0,0,0,0.05,0,0,offsetof(tnsMakeTransformNode, UseRot),0,0,3,0,0,0,0,0,0,0,0);
 |  |      laAddFloatProperty(pc,"use_rot", "Rotation", "Use Rotation",0,"X,Y,Z",0,0,0,0.05,0,0,offsetof(tnsMakeTransformNode, UseRot),0,0,3,0,0,0,0,0,0,0,0);
 | 
											
												
													
														|  |      laAddFloatProperty(pc,"use_sca", "Scale", "Use Scale",0,0,0,0,0,0.05,0,0,offsetof(tnsMakeTransformNode, UseSca),0,0,0,0,0,0,0,0,0,0,0);
 |  |      laAddFloatProperty(pc,"use_sca", "Scale", "Use Scale",0,0,0,0,0,0.05,0,0,offsetof(tnsMakeTransformNode, UseSca),0,0,0,0,0,0,0,0,0,0,0);
 | 
											
												
													
														|  |      laAddFloatProperty(pc,"use_angle", "Angle", "Use Angle",0,0,0,0,0,0.05,0,0,offsetof(tnsMakeTransformNode, UseAngle),0,0,0,0,0,0,0,0,0,0,0);
 |  |      laAddFloatProperty(pc,"use_angle", "Angle", "Use Angle",0,0,0,0,0,0.05,0,0,offsetof(tnsMakeTransformNode, UseAngle),0,0,0,0,0,0,0,0,0,0,0);
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    pc=laAddPropertyContainer("tns_action_player_node", "Action Player", "Action player node",0,tnsui_ActionPlayerNode,sizeof(tnsActionPlayerNode),lapost_Node,0,1);
 | 
											
												
													
														|  | 
 |  | +    TNS_PC_IDN_ACTION_PLAYER=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,"prev", "Previous","Previous node","la_in_socket",0,0,0,offsetof(tnsActionPlayerNode,Prev),0,0,0,0,0,0,0,LA_UDF_SINGLE);
 | 
											
												
													
														|  | 
 |  | +    laAddSubGroup(pc,"next", "Next","Next node","la_out_socket",0,0,0,offsetof(tnsActionPlayerNode,Next),0,0,0,0,0,0,0,LA_UDF_SINGLE);
 | 
											
												
													
														|  | 
 |  | +    laAddSubGroup(pc,"in_transport", "In Transport","Transport input","la_in_socket",0,0,0,offsetof(tnsActionPlayerNode,Transport),0,0,0,0,0,0,0,LA_UDF_SINGLE);
 | 
											
												
													
														|  | 
 |  | +    laAddSubGroup(pc,"in_time", "In Time","Time Input","la_in_socket",0,0,0,offsetof(tnsActionPlayerNode,Time),0,0,0,0,0,0,0,LA_UDF_SINGLE);
 | 
											
												
													
														|  | 
 |  | +    laAddSubGroup(pc,"in_detached", "In Detached","Detached input","la_in_socket",0,0,0,offsetof(tnsActionPlayerNode,Detached),0,0,0,0,0,0,0,LA_UDF_SINGLE);
 | 
											
												
													
														|  | 
 |  | +    ep=laAddEnumProperty(pc,"transport","Transport","Action in transport",LA_WIDGET_ENUM_HIGHLIGHT,0,0,0,0,offsetof(tnsActionPlayerNode,iTransport),0,0,0,0,0,0,0,0,0,0);
 | 
											
												
													
														|  | 
 |  | +    laAddEnumItemAs(ep,"STOPPED","Stopped","Player is stopped",0,0);
 | 
											
												
													
														|  | 
 |  | +    laAddEnumItemAs(ep,"PLAYING","Playing","Player is playing",1,0);
 | 
											
												
													
														|  | 
 |  | +    ep=laAddEnumProperty(pc,"detached","Detached","Action is detached on the instance",LA_WIDGET_ENUM_HIGHLIGHT,0,0,0,0,offsetof(tnsActionPlayerNode,iDetached),0,0,0,0,0,0,0,0,0,0);
 | 
											
												
													
														|  | 
 |  | +    laAddEnumItemAs(ep,"NONE","None","Action is reused from instancer",0,0);
 | 
											
												
													
														|  | 
 |  | +    laAddEnumItemAs(ep,"DETACHED","Detached","Action state is on instance itself",1,0);
 | 
											
												
													
														|  | 
 |  | +    laAddSubGroup(pc,"action","Action","Target action","la_animation_action",0,0,0,offsetof(tnsActionPlayerNode,Action),tnsget_FirstActionFromActionPlayer,0,laget_ListNext,0,0,0,0,LA_UDF_REFER);
 | 
											
												
													
														|  |      
 |  |      
 | 
											
												
													
														|  |      LA_IDN_REGISTER("Transform",0,TNS_IDN_TRANSFORM,TNS_PC_IDN_TRANSFORM, IDN_Transform, tnsTransformNode);
 |  |      LA_IDN_REGISTER("Transform",0,TNS_IDN_TRANSFORM,TNS_PC_IDN_TRANSFORM, IDN_Transform, tnsTransformNode);
 | 
											
												
													
														|  |      LA_IDN_REGISTER("Make Transform",0,TNS_IDN_MAKE_TRANSFORM,TNS_PC_IDN_MAKE_TRANSFORM, IDN_MakeTransform, tnsMakeTransformNode);
 |  |      LA_IDN_REGISTER("Make Transform",0,TNS_IDN_MAKE_TRANSFORM,TNS_PC_IDN_MAKE_TRANSFORM, IDN_MakeTransform, tnsMakeTransformNode);
 | 
											
												
													
														|  | 
 |  | +    LA_IDN_REGISTER("Action Player",0,TNS_IDN_ACTION_PLAYER,TNS_PC_IDN_ACTION_PLAYER, IDN_ActionPlayer, tnsActionPlayerNode);
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |      laNodeCategoryAddNodeTypes(LA_NODE_CATEGORY_MATH, &TNS_IDN_MAKE_TRANSFORM,0);
 |  |      laNodeCategoryAddNodeTypes(LA_NODE_CATEGORY_MATH, &TNS_IDN_MAKE_TRANSFORM,0);
 | 
											
												
													
														|  | -    laNodeCategoryAddNodeTypes(LA_NODE_CATEGORY_DRIVER, &TNS_IDN_TRANSFORM,0);
 |  | 
 | 
											
												
													
														|  | 
 |  | +    laNodeCategoryAddNodeTypes(LA_NODE_CATEGORY_DRIVER, &TNS_IDN_TRANSFORM, &TNS_IDN_ACTION_PLAYER,0);
 | 
											
												
													
														|  |  }
 |  |  }
 | 
											
												
													
														|  |  
 |  |  
 |