1524 lines
46 KiB
C++
1524 lines
46 KiB
C++
//TODO big update
|
||
/*
|
||
add setting bool freeze => stop remapping parameters, and check that target is compatible
|
||
add setting bool execute in real time => does not execute in 1 frame as now (return CKBR_ACTIVATENEXTFRAME)
|
||
|
||
put all these settings in a flag - register flag param hidden
|
||
|
||
put target in input parameter so that user can then change it on the fly
|
||
|
||
reset,wait for completion,stop at exit,no parameter restore,freeze io mapping,real time execute,
|
||
|
||
CHECK TARGET & MAPPED IOS
|
||
*/
|
||
|
||
|
||
/////////////////////////////////////////////////////
|
||
/////////////////////////////////////////////////////
|
||
//
|
||
// CallBehavior
|
||
//
|
||
/////////////////////////////////////////////////////
|
||
/////////////////////////////////////////////////////
|
||
#include "CKALL.h"
|
||
#include "CallBehaviorCallback.h"
|
||
|
||
//#include "Winuser.h"
|
||
//#include "Windows.h"
|
||
|
||
#define CALLBEHAVIOR_NAME "Call Behavior"
|
||
//original guid, remove when integration
|
||
#define CALLBEHAVIOR_GUID CKGUID(0x360a720d,0x7fa42f94)
|
||
//#define CALLBEHAVIOR_GUID CKGUID(0x360a720d,0x7fa42f95)
|
||
#define NARRATIVES_CALLBEHAVIOR_SETTING CKGUID(0x5bc80700,0x24183450)
|
||
|
||
#define EXECUTE_TARGET() \
|
||
CKERROR result = CK_OK; \
|
||
if (flags & eSetting_Hijack_Parameters_Once) \
|
||
result = target->Execute(behcontext.DeltaTime); /*just execute, no more hijack*/\
|
||
else \
|
||
{ \
|
||
BehaviorsParameters behParams; \
|
||
if (flags & eSetting_Parameter_Restore) \
|
||
behParams.SaveBehaviorParameters(target);/*save parameters sources*/ \
|
||
BehaviorsParameters::SetBehaviorParameters(beh,target);/*hijack parameters*/ \
|
||
\
|
||
if (flags & eSetting_SaveInternalStates) \
|
||
{ \
|
||
BehaviorInternalStates locals_currentstate; \
|
||
BehaviorInternalStates locals_relativestate; \
|
||
\
|
||
/*Before execution: >save current state >load state relative to caller*/ \
|
||
locals_currentstate.SaveAllSubBehaviorLocalParameterValues(target); \
|
||
beh->GetLocalParameterValue(ePL_CHUNK_FOR_SUBLOCALS,&locals_relativestate.m_Chunk);\
|
||
locals_relativestate.LoadAllSubBehaviorLocalParameterValues(target); \
|
||
\
|
||
result = target->Execute(behcontext.DeltaTime);/*execute*/ \
|
||
\
|
||
/*After execution: >save state relative to caller >load last current state*/\
|
||
locals_relativestate.SaveAllSubBehaviorLocalParameterValues(target); \
|
||
locals_currentstate.LoadAllSubBehaviorLocalParameterValues(target); \
|
||
} \
|
||
else \
|
||
result = target->Execute(behcontext.DeltaTime);/*execute*/ \
|
||
\
|
||
if (flags & eSetting_Parameter_Restore) \
|
||
behParams.LoadBehaviorParameters(target);/*restore parameters sources*/ \
|
||
} \
|
||
|
||
|
||
|
||
|
||
|
||
CKObjectDeclaration *FillBehaviorCallBehavior2Decl();
|
||
CKERROR CreateCallBehavior2Proto(CKBehaviorPrototype **);
|
||
int CallBehavior2(const CKBehaviorContext& context);
|
||
CKERROR CallBehavior2Callback(const CKBehaviorContext& context);
|
||
|
||
//compatibility with V1 from 4.1.0.37 added....
|
||
int CallBehavior(const CKBehaviorContext& context);
|
||
CKERROR CallBehaviorCallback(const CKBehaviorContext& context);
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
// enums & defines
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
enum SETTINGS
|
||
{
|
||
eSetting_Reset =1, //reset behavior on execute
|
||
eSetting_Wait_for_Completion =2, //wait for completion of behavior instead of just 1st frame links
|
||
eSetting_Stop_at_Exit =4, //do not activate output links of target=>output of targets are deactivated
|
||
eSetting_Parameter_Restore =8, //do restore parameters hijacking of target after execution
|
||
eSetting_Hijack_Parameters_Once =16,//hijack parameter only once at the 1st execution.
|
||
//PRIORITY>eSetting_Parameter_Restore
|
||
eSetting_Freeze_IO_mapping =32,//do not remapped ios on target change
|
||
eSetting_Real_Time_Execution =64,//if target execution last several frames, then execute it in that time and not only the whole in one frame
|
||
//PRIORITY>eSetting_Wait_for_Completion,
|
||
eSetting_Check_Proto_Validity =128,//check prototype validity
|
||
eSetting_SaveInternalStates =256,//save local /not settings or target & sub behavior of target & active states
|
||
|
||
eSetting_PrivateCheckProto =eSetting_Freeze_IO_mapping+eSetting_Check_Proto_Validity,//check in code,private
|
||
|
||
eSetting_InExecution =65536, //currently executed
|
||
};
|
||
|
||
enum INS
|
||
{
|
||
eI_INS, //mapped inputs
|
||
};
|
||
|
||
enum OUTS
|
||
{
|
||
eO_OUTS, //mapped outputs
|
||
};
|
||
|
||
enum PINS
|
||
{
|
||
ePI_TARGET, //target behavior
|
||
ePI_INPUTS, //mapped inputs
|
||
};
|
||
|
||
enum POUTS
|
||
{
|
||
ePO_OUTPUTS, //mapped outputs
|
||
};
|
||
|
||
enum PLOCALS
|
||
{
|
||
ePL_SETTINGS, //settings
|
||
ePL_MAX_RECURSION_DEPTH, //max recursive depth
|
||
ePL_RECURSION_DEPTH, //current recursive depth
|
||
ePL_CHUNK_FOR_SUBLOCALS, //ckstatechunk for locals of subbehaviors
|
||
};
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
// save parameter links
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
struct BehaviorsParameters
|
||
{
|
||
int sourcesCount;
|
||
CK_ID* sources;
|
||
int destinationsCount;
|
||
CK_ID** destinations;
|
||
|
||
BehaviorsParameters() {
|
||
memset(this,0,sizeof(BehaviorsParameters));
|
||
destinations = 0;
|
||
}
|
||
~BehaviorsParameters(){Clear();}
|
||
|
||
void Clear();
|
||
void SaveBehaviorParameters(CKBehavior* beh);
|
||
void LoadBehaviorParameters(CKBehavior* beh);
|
||
|
||
static void ResetBehaviorParameters(CKBehavior* behavior);
|
||
static void NameBehaviorParameters(CKBehavior* callBB,CKBehavior* calledBeh,int iPinOffset=0);
|
||
static void SetBehaviorParameters(CKBehavior* callBB,CKBehavior* calledBeh,int iPinOffset=0);
|
||
};
|
||
|
||
struct BehaviorInternalStates
|
||
{
|
||
//tag to write in chunk
|
||
enum ESubTag
|
||
{
|
||
eST_ActiveStates = -4, //for each beh, save active state (1bit) + outputs active state (31bits)
|
||
eST_OutputParameters = -3, //save all sub beh pout values
|
||
eST_Behavior = -2, //save beh id
|
||
eST_End = -1, //end
|
||
};
|
||
|
||
enum EFlags
|
||
{
|
||
eInternallyCreatedChunk = 1,
|
||
};
|
||
|
||
BehaviorInternalStates() {memset(this,0,sizeof(BehaviorInternalStates));}
|
||
BehaviorInternalStates(CKStateChunk* chunk) {memset(this,0,sizeof(BehaviorInternalStates));m_Chunk=chunk;}
|
||
~BehaviorInternalStates() { if ( (m_Flags & eInternallyCreatedChunk) && m_Chunk) DeleteCKStateChunk(m_Chunk);m_Chunk=0;}
|
||
|
||
DWORD m_Flags;
|
||
|
||
/*
|
||
before execute
|
||
|
||
>save current state
|
||
>load state relative to caller
|
||
------------
|
||
after execute
|
||
|
||
>save state relative to caller
|
||
>load last current state
|
||
*/
|
||
void SaveAllSubBehaviorLocalParameterValues(CKBehavior* iBeh,int iDepth=0);
|
||
void LoadAllSubBehaviorLocalParameterValues(CKBehavior* iBeh,int iDepth=0);
|
||
|
||
static DWORD GetBehaviorActiveStates(CKBehavior* iBeh);
|
||
static void SetBehaviorActiveStates(CKBehavior* iBeh,DWORD iActiveStates);
|
||
|
||
CKStateChunk* m_Chunk;
|
||
};
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
// the behavior
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
CKObjectDeclaration *FillBehaviorCallBehavior2Decl()
|
||
{
|
||
CKObjectDeclaration *od = CreateCKObjectDeclaration(CALLBEHAVIOR_NAME);
|
||
od->SetDescription("Calls immediatly a behavior.");
|
||
/* rem:
|
||
<SPAN CLASS=in>In: </SPAN>triggers the process.<BR>
|
||
<SPAN CLASS=out>Out: </SPAN>is activated when the activated script's process is completed.<BR>
|
||
<BR>
|
||
<SPAN CLASS=pin>Reset?: </SPAN>if TRUE, the script will be reset; if FALSE the script will be resumed from its previous state.<BR>
|
||
<SPAN CLASS=pin>Script: </SPAN>script to be performed.<BR>
|
||
<SPAN CLASS=pin>Wait For Completion?: </SPAN>if TRUE, the script will be executed until completion; if FALSE the script will be executed for one frame.<BR>
|
||
<BR>
|
||
The script called is executed immediatly, stopping the execution of the current script.
|
||
*/
|
||
/* warning:
|
||
The script must not contain a infinite loop if you set Wait For Completion.<BR>
|
||
*/
|
||
od->SetType(CKDLL_BEHAVIORPROTOTYPE);
|
||
od->SetGuid(CALLBEHAVIOR_GUID);
|
||
od->SetAuthorGuid(VIRTOOLS_GUID);
|
||
od->SetAuthorName("Virtools");
|
||
od->SetVersion(0x00020000);
|
||
od->SetCreationFunction(CreateCallBehavior2Proto);
|
||
od->SetCompatibleClassId(CKCID_BEOBJECT);
|
||
od->SetCategory("Narratives/Script Management");
|
||
return od;
|
||
}
|
||
|
||
CKERROR CreateCallBehavior2Proto(CKBehaviorPrototype **pproto)
|
||
{
|
||
CKBehaviorPrototype *proto = CreateCKBehaviorPrototype(CALLBEHAVIOR_NAME);
|
||
if(!proto) return CKERR_OUTOFMEMORY;
|
||
|
||
proto->DeclareInParameter("Target", CKPGUID_BEHAVIOR, 0);
|
||
|
||
proto->DeclareSetting("Settings",NARRATIVES_CALLBEHAVIOR_SETTING,"Wait for Completion,Parameter Restore,Check Proto Validity,Save Internal States");
|
||
proto->DeclareSetting("Max Recursion",CKPGUID_INT,"100");//0 means no protection
|
||
proto->DeclareLocalParameter("",CKPGUID_INT,0);//ePL_RECURSION_DEPTH (-1 means first
|
||
proto->DeclareLocalParameter("",CKPGUID_STATECHUNK,0); //state of locals of sub behaviors
|
||
|
||
proto->SetFlags(CK_BEHAVIORPROTOTYPE_NORMAL);
|
||
proto->SetFunction(CallBehavior2);
|
||
proto->SetBehaviorCallbackFct(CallBehavior2Callback);
|
||
proto->SetBehaviorFlags((CK_BEHAVIOR_FLAGS)(
|
||
CKBEHAVIOR_INTERNALLYCREATEDINPUTS|
|
||
CKBEHAVIOR_INTERNALLYCREATEDOUTPUTS|
|
||
CKBEHAVIOR_INTERNALLYCREATEDINPUTPARAMS|
|
||
CKBEHAVIOR_INTERNALLYCREATEDOUTPUTPARAMS
|
||
));
|
||
|
||
*pproto = proto;
|
||
return CK_OK;
|
||
|
||
}
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
// CALL BEHAVIOR CALLBACK START
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
int CallBehavior2(const CKBehaviorContext& behcontext)
|
||
{
|
||
CKBehavior* beh = behcontext.Behavior;
|
||
|
||
//compatibility with V1 from 4.1.0.37 added....
|
||
if (beh->GetVersion()<0x00020000)
|
||
{
|
||
return CallBehavior(behcontext);
|
||
//not support for older version, please update :)
|
||
//behcontext.Context->OutputToConsole("Error: Please Update CallBehavior BBs");
|
||
//return CKBR_OK;
|
||
}
|
||
|
||
//Get target behavior
|
||
CKBehavior* target = (CKBehavior*) beh->GetInputParameterObject(ePI_TARGET);
|
||
if (!target)
|
||
return CKBR_OK;
|
||
|
||
//get settings
|
||
DWORD flags=0;
|
||
beh->GetLocalParameterValue(ePL_SETTINGS,&flags);
|
||
|
||
//target io mapping check
|
||
if ((flags & eSetting_PrivateCheckProto)==eSetting_PrivateCheckProto)//need the full flag
|
||
{
|
||
int pincount = target->GetInputParameterCount();
|
||
int poutcount = target->GetOutputParameterCount();
|
||
|
||
if (beh->GetInputCount()-eI_INS!=target->GetInputCount() ||
|
||
beh->GetOutputCount()-eO_OUTS!=target->GetOutputCount() ||
|
||
beh->GetInputParameterCount()-ePI_INPUTS!=pincount ||
|
||
beh->GetOutputParameterCount()-ePO_OUTPUTS!=poutcount )
|
||
{
|
||
behcontext.Context->OutputToConsole("CallBehavior: Check Prototype Validity Error");
|
||
return CKBR_OK;
|
||
}
|
||
|
||
for (int i=0;i<pincount;++i)
|
||
{
|
||
CKParameterIn* pin1 = beh->GetInputParameter(i+ePI_INPUTS);
|
||
CKParameterIn* pin2 = target->GetInputParameter(i);
|
||
if (pin1->GetGUID()!=pin2->GetGUID())
|
||
{
|
||
behcontext.Context->OutputToConsole("CallBehavior: Invalid Target Prototype");
|
||
return CKBR_OK;
|
||
}
|
||
}
|
||
for (int i=0;i<poutcount;++i)
|
||
{
|
||
CKParameterOut* pout1 = beh->GetOutputParameter(i+ePO_OUTPUTS);
|
||
CKParameterOut* pout2 = target->GetOutputParameter(i);
|
||
if (pout1->GetGUID()!=pout2->GetGUID())
|
||
{
|
||
behcontext.Context->OutputToConsole("CallBehavior: Invalid Target Prototype");
|
||
return CKBR_OK;
|
||
}
|
||
}
|
||
}
|
||
|
||
//max depth
|
||
int maxDepth = 100;
|
||
beh->GetLocalParameterValue(ePL_MAX_RECURSION_DEPTH,&maxDepth);
|
||
|
||
//current depth - recursion check
|
||
int currentDepth = 0;
|
||
beh->GetLocalParameterValue(ePL_RECURSION_DEPTH,¤tDepth);
|
||
//update current Depth
|
||
currentDepth++;
|
||
beh->SetLocalParameterValue(ePL_RECURSION_DEPTH,¤tDepth);
|
||
//note : 1st execution=> currentdepth here == 0
|
||
if (maxDepth>=0 && currentDepth>maxDepth)
|
||
{
|
||
behcontext.Context->OutputToConsole("CallBehavior: recursion>max recursion depth, BB break");
|
||
flags &= ~eSetting_InExecution;
|
||
beh->SetLocalParameterValue(ePL_SETTINGS,&flags); //save the fact that this beh is in execution
|
||
goto CALLBEHAVIOR_END;
|
||
}
|
||
|
||
//memorize activation state
|
||
BOOL memorizeIsActive = target->IsActive();
|
||
//small note :
|
||
//execute inactive graph, it will activate inner BBs, which then in turn will activate the graph
|
||
//the graph can then return CKBR_ACTIVATENEXTFRAME and still be active
|
||
//execute inactive BB : it will be executed but nothing will change its activate flag
|
||
//it will remain inactive even if it returns CKBR_ACTIVATENEXTFRAME
|
||
//=> we have to activate BBs, and not activate graphes (for graphes, recursion trouble if active too)
|
||
//+++
|
||
//we have to restore active state of a BB
|
||
//ie otherwise, delayer, activate it, execute it, ok let's go on => the delayer is active,
|
||
//now the behavior manager will execute it once again. bad
|
||
//=>restore active state at the end
|
||
|
||
//1st execution INITIALISATION
|
||
int ioCount = target->GetInputCount();
|
||
if ((flags & eSetting_InExecution)==0) //1st execution
|
||
{
|
||
//reset
|
||
if (flags & eSetting_Reset)
|
||
target->Activate(FALSE,TRUE);
|
||
|
||
//Activate Inputs
|
||
//target->ActivateInput(0);
|
||
for (int i=eI_INS;i<eI_INS+ioCount;++i)
|
||
{
|
||
if (beh->IsInputActive(i))
|
||
{
|
||
target->ActivateInput(i-eI_INS);
|
||
//deactivate NOW this input, as it has been checked
|
||
//because in case of recursion, it may cause crashes
|
||
//even if callbehavior was deactivated (see following code)
|
||
//reactivating it again, the input could be not activated
|
||
beh->ActivateInput(i,FALSE);
|
||
}
|
||
}
|
||
//deactivate because in case of recursion, being still active will case unwilling recursion
|
||
if ((target->GetFlags() & CKBEHAVIOR_BUILDINGBLOCK)==0) //IF NOT BUILDING BLOCK
|
||
if ((flags & eSetting_Real_Time_Execution)==0) //no recursion in realtime, so we just check we are not in real time
|
||
beh->Activate(FALSE);
|
||
|
||
if (flags & eSetting_Hijack_Parameters_Once)
|
||
BehaviorsParameters::SetBehaviorParameters(beh,target);
|
||
}
|
||
|
||
//Todo: alors executer un graph non actif, si le graph est actif a la fin, ca veut dire qu'en realtime faut continuer a l'ex
|
||
//mais un bb non actif, un return CKB Activate next frame le rend pas actif
|
||
//du coup chui oblig<69> de l'activer, mais apres je loope infiniment bref a voir pr plus tard
|
||
//en meme temps ca sert a rien un call de BB du coup j'ai desactiv<69> en release
|
||
if (target->GetFlags() & CKBEHAVIOR_BUILDINGBLOCK) //IF BUILDING BLOCK
|
||
target->Activate(TRUE); //force activation
|
||
|
||
//Real time ex
|
||
if (flags & eSetting_Real_Time_Execution)
|
||
{
|
||
if (currentDepth>1)
|
||
{
|
||
behcontext.Context->OutputToConsoleExBeep("Call Behavior: Real Time Execution and recursion is not allowed");
|
||
flags &= ~eSetting_InExecution;
|
||
beh->SetLocalParameterValue(ePL_SETTINGS,&flags); //save the fact that this beh is in execution
|
||
goto CALLBEHAVIOR_END;
|
||
}
|
||
|
||
//have to reactivate script if not active, otherwise we may have some side effect
|
||
/*
|
||
CKBehavior* parent = target;
|
||
while (parent->GetParent())
|
||
parent = target->GetParent();
|
||
if (!parent->IsActive())
|
||
parent->Activate(TRUE,FALSE);
|
||
*/
|
||
|
||
CK_BEHAVIOR_FLAGS behflags = target->GetFlags();
|
||
//if (behflags & CKBEHAVIOR_EXECUTEDLASTFRAME)
|
||
|
||
//1st execution & real time
|
||
if ((flags & eSetting_InExecution)==0)
|
||
{
|
||
flags |= eSetting_InExecution;
|
||
beh->SetLocalParameterValue(ePL_SETTINGS,&flags); //save the fact that this beh is in execution
|
||
}
|
||
|
||
//execution
|
||
EXECUTE_TARGET();
|
||
|
||
//if no more active,
|
||
if(!target->IsActive())
|
||
{
|
||
//remove inExecution flags inexection
|
||
flags &= ~eSetting_InExecution;
|
||
beh->SetLocalParameterValue(ePL_SETTINGS,&flags); //save the fact that this beh is in execution
|
||
}
|
||
}
|
||
|
||
//wait for completion
|
||
else if (flags & eSetting_Wait_for_Completion)
|
||
{
|
||
int loop = 0;
|
||
int maxloop = behcontext.Context->GetBehaviorManager()->GetBehaviorMaxIteration();
|
||
for(;;++loop)
|
||
{
|
||
if (loop > maxloop) //prevent infinite loop
|
||
{
|
||
behcontext.Context->OutputToConsoleExBeep("Call Behavior: Target behavior %s executed too much times",target?target->GetName():"NA");
|
||
target->Activate(FALSE,FALSE);
|
||
break;
|
||
}
|
||
|
||
EXECUTE_TARGET();
|
||
|
||
// The target loop on itself too much times
|
||
if (result == CKBR_INFINITELOOP) {
|
||
target->Activate(FALSE,FALSE);
|
||
break;
|
||
}
|
||
if(!target->IsActive())
|
||
break;
|
||
}
|
||
}
|
||
// we execute only one frame of the target
|
||
else
|
||
{
|
||
EXECUTE_TARGET();
|
||
target->Activate(FALSE,FALSE);
|
||
}
|
||
|
||
//deactivate all inputs (already done at the beginning, put into comment
|
||
//for (int i=eI_INS;i<eI_INS+ioCount;++i)
|
||
// beh->ActivateInput(i,FALSE);
|
||
|
||
//for each target's output activated, activate call behavior output
|
||
ioCount = target->GetOutputCount();
|
||
for (int i=eO_OUTS;i<eO_OUTS+ioCount;++i)
|
||
beh->ActivateOutput(i,target->IsOutputActive(i-eO_OUTS));
|
||
|
||
//if stop at exit, deactivate target outputs
|
||
if (flags & eSetting_Stop_at_Exit)
|
||
{
|
||
for (int i=0;i<ioCount;++i)
|
||
target->ActivateOutput(i,FALSE);
|
||
}
|
||
|
||
//recursive depth update
|
||
CALLBEHAVIOR_END:
|
||
currentDepth--;
|
||
beh->SetLocalParameterValue(ePL_RECURSION_DEPTH,¤tDepth);
|
||
|
||
if (memorizeIsActive==FALSE)
|
||
target->Activate(FALSE,FALSE);
|
||
|
||
//real time execution
|
||
if (flags & eSetting_InExecution)
|
||
return CKBR_ACTIVATENEXTFRAME;
|
||
|
||
return CKBR_OK;
|
||
}
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
// CALL BEHAVIOR CALLBACK END
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
|
||
void RemoveIOxParams2(CKBehavior* beh)
|
||
{
|
||
CKContext* ctx = beh->GetCKContext();
|
||
int count = beh->GetInputParameterCount()-ePI_INPUTS;
|
||
for (int i=0;i<count;++i)
|
||
ctx->DestroyObject(beh->RemoveInputParameter(ePI_INPUTS),CK_DESTROY_NONOTIFY,0);
|
||
|
||
count = beh->GetOutputParameterCount()-ePO_OUTPUTS;
|
||
for (int i=0;i<count;++i)
|
||
ctx->DestroyObject(beh->RemoveOutputParameter(ePO_OUTPUTS),CK_DESTROY_NONOTIFY,0);
|
||
|
||
count = beh->GetInputCount()-eI_INS;
|
||
for (int i=0;i<count;++i)
|
||
beh->DeleteInput(eI_INS);
|
||
|
||
count = beh->GetOutputCount()-eO_OUTS;
|
||
for (int i=0;i<count;++i)
|
||
beh->DeleteOutput(eO_OUTS);
|
||
}
|
||
|
||
CKERROR CallBehavior2Callback(const CKBehaviorContext& behcontext)
|
||
{
|
||
CKBehavior* beh = behcontext.Behavior;
|
||
|
||
if (beh->GetVersion()<0x00020000) //not support for older version, please update :)
|
||
{
|
||
return CallBehaviorCallback(behcontext);
|
||
//not support for older version, please update :)
|
||
//behcontext.Context->OutputToConsole("Error: Please Update CallBehavior BBs");
|
||
//return CKBR_OK;
|
||
}
|
||
|
||
switch( behcontext.CallbackMessage )
|
||
{
|
||
case CKM_BEHAVIORDEACTIVATESCRIPT:
|
||
case CKM_BEHAVIORRESET:
|
||
{
|
||
DWORD flags = 0;
|
||
beh->GetLocalParameterValue(ePL_SETTINGS,&flags); //save the fact that this beh is in execution
|
||
flags &= ~eSetting_InExecution;
|
||
beh->SetLocalParameterValue(ePL_SETTINGS,&flags); //save the fact that this beh is in execution
|
||
}
|
||
break;
|
||
//case CKM_BEHAVIORSETTINGSEDITED: //obsolete in V2
|
||
//create same ios as in target behavior
|
||
case CKM_BEHAVIOREDITED:
|
||
{
|
||
//do not take into account any change if frozen
|
||
DWORD flags=0;
|
||
beh->GetLocalParameterValue(ePL_SETTINGS,&flags);
|
||
if (flags & eSetting_Freeze_IO_mapping)
|
||
break;
|
||
|
||
CKBehavior* target = (CKBehavior*) beh->GetInputParameterObject(ePI_TARGET);
|
||
BOOL bb = FALSE;
|
||
if (target)
|
||
bb = (target->GetFlags() & CKBEHAVIOR_BUILDINGBLOCK)?TRUE:FALSE;
|
||
|
||
#ifdef _DEBUG
|
||
if (target==beh)// || bb) allow bb finally
|
||
{
|
||
//if (bb)
|
||
// behcontext.Context->OutputToConsole("CallBehavior BB cannot target another BB");
|
||
//else
|
||
#else
|
||
if (target==beh || bb) //do not allow bb finally in release lol, active state problems
|
||
{
|
||
if (bb)
|
||
behcontext.Context->OutputToConsole("CallBehavior BB cannot target another BB");
|
||
else
|
||
#endif
|
||
behcontext.Context->OutputToConsole("CallBehavior BB cannot target itself");
|
||
CKParameterIn* pin = beh->GetInputParameter(ePI_TARGET);
|
||
if (pin)
|
||
{
|
||
CKParameter* param = pin->GetDirectSource();
|
||
CK_ID id=0;
|
||
if (param)
|
||
param->SetValue(&id);
|
||
}
|
||
beh->SetName(CALLBEHAVIOR_NAME);
|
||
RemoveIOxParams2(beh);
|
||
|
||
behcontext.Context->SendInterfaceMessage(CKUIM_CALLBEHAVIORBB_CHANGE,(CKDWORD)beh,eCallBehavior_Edit,0);//warn interface
|
||
|
||
return CKBR_PARAMETERERROR;
|
||
}
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
//Fit IOs & Params
|
||
if (CKIsChildClassOf(target,CKCID_BEHAVIOR) && target->GetOwner())
|
||
{
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
//Params
|
||
int inCountTarget = target->GetInputParameterCount();
|
||
int outCountTarget = target->GetOutputParameterCount();
|
||
|
||
int inCountCaller = beh->GetInputParameterCount();
|
||
int outCountCaller = beh->GetOutputParameterCount();
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
//remove params if too much
|
||
for (int i=inCountCaller-1;i>=ePI_INPUTS+inCountTarget;i--)
|
||
behcontext.Context->DestroyObject(beh->RemoveInputParameter(i),CK_DESTROY_NONOTIFY,0);
|
||
for (int i=outCountCaller-1;i>=ePO_OUTPUTS+outCountTarget;i--)
|
||
behcontext.Context->DestroyObject(beh->RemoveOutputParameter(i),CK_DESTROY_NONOTIFY,0);
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
//create params if not enough
|
||
inCountCaller = beh->GetInputParameterCount();
|
||
outCountCaller = beh->GetOutputParameterCount();
|
||
|
||
for (int i=inCountCaller-ePI_INPUTS;i<inCountTarget;i++)
|
||
{
|
||
CKParameterIn* pin = target->GetInputParameter(i);
|
||
beh->CreateInputParameter(pin->GetName(),pin->GetGUID());
|
||
}
|
||
for (int i=outCountCaller-ePO_OUTPUTS;i<outCountTarget;i++)
|
||
{
|
||
CKParameterOut* pout = target->GetOutputParameter(i);
|
||
beh->CreateOutputParameter(pout->GetName(),pout->GetGUID());
|
||
}
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
//IOs
|
||
inCountTarget = target->GetInputCount();
|
||
outCountTarget = target->GetOutputCount();
|
||
|
||
inCountCaller = beh->GetInputCount();
|
||
outCountCaller = beh->GetOutputCount();
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
//remove IOS if too much
|
||
for (int i=inCountCaller-1;i>=eI_INS+inCountTarget;i--)
|
||
beh->DeleteInput(i);
|
||
for (int i=outCountCaller-1;i>=eO_OUTS+outCountTarget;i--)
|
||
beh->DeleteOutput(i);
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
//create IOS if not enough
|
||
inCountCaller = beh->GetInputCount();
|
||
outCountCaller = beh->GetOutputCount();
|
||
|
||
for (int i=inCountCaller-eI_INS;i<inCountTarget;i++)
|
||
{
|
||
CKBehaviorIO* io = target->GetInput(i);
|
||
beh->CreateInput(io->GetName());
|
||
}
|
||
for (int i=outCountCaller-eO_OUTS;i<outCountTarget;i++)
|
||
{
|
||
CKBehaviorIO* io = target->GetOutput(i);
|
||
beh->CreateOutput(io->GetName());
|
||
}
|
||
|
||
//rename
|
||
BehaviorsParameters::NameBehaviorParameters(beh,target);
|
||
if (target && target->GetName())
|
||
{
|
||
XString finalName;
|
||
finalName.Format("%s:%s",CALLBEHAVIOR_NAME,target->GetName());
|
||
beh->SetName(finalName.Str());
|
||
}
|
||
}
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
else //remove all supplementary pins & pouts from BB
|
||
{
|
||
RemoveIOxParams2(beh);
|
||
beh->SetName(CALLBEHAVIOR_NAME);
|
||
}
|
||
|
||
{
|
||
CKBehavior* target = (CKBehavior*) beh->GetInputParameterObject(ePI_TARGET);
|
||
behcontext.Context->SendInterfaceMessage(CKUIM_CALLBEHAVIORBB_CHANGE,(CKDWORD)beh,eCallBehavior_Edit,(CKDWORD)target);//warn interface
|
||
}
|
||
break;
|
||
}
|
||
break;
|
||
case CKM_BEHAVIORDELETE:
|
||
case CKM_BEHAVIORDETACH:
|
||
{
|
||
DWORD flags = 0;
|
||
beh->GetLocalParameterValue(ePL_SETTINGS,&flags); //save the fact that this beh is in execution
|
||
flags &= ~eSetting_InExecution;
|
||
beh->SetLocalParameterValue(ePL_SETTINGS,&flags); //save the fact that this beh is in execution
|
||
|
||
CKBehavior* target = (CKBehavior*) beh->GetInputParameterObject(ePI_TARGET);
|
||
behcontext.Context->SendInterfaceMessage(CKUIM_CALLBEHAVIORBB_CHANGE,(CKDWORD)beh,eCallBehavior_Detach,(CKDWORD)target);//warn interface
|
||
}
|
||
break;
|
||
case CKM_BEHAVIORLOAD:
|
||
case CKM_BEHAVIORATTACH:
|
||
{
|
||
DWORD flags = 0;
|
||
beh->GetLocalParameterValue(ePL_SETTINGS,&flags); //save the fact that this beh is in execution
|
||
flags &= ~eSetting_InExecution;
|
||
beh->SetLocalParameterValue(ePL_SETTINGS,&flags); //save the fact that this beh is in execution
|
||
|
||
CKBehavior* target = (CKBehavior*) beh->GetInputParameterObject(ePI_TARGET);
|
||
behcontext.Context->SendInterfaceMessage(CKUIM_CALLBEHAVIORBB_CHANGE,(CKDWORD)beh,eCallBehavior_Attach,(CKDWORD)target);//warn interface
|
||
if (behcontext.Context->IsInInterfaceMode())
|
||
{
|
||
if (target && target->GetName())
|
||
{
|
||
XString finalName;
|
||
finalName.Format("%s:%s",CALLBEHAVIOR_NAME,target->GetName());
|
||
beh->SetName(finalName.Str());
|
||
}
|
||
}
|
||
|
||
}
|
||
break;
|
||
}
|
||
return CK_OK;
|
||
}
|
||
|
||
//////////////////////////////////////////////////////////////////////////
|
||
// call behavior 1 compatibilit<69> for 4.1.0.37 ...
|
||
//////////////////////////////////////////////////////////////////////////
|
||
enum INS_V1
|
||
{
|
||
eI_INS_V1,
|
||
};
|
||
|
||
enum OUTS_V1
|
||
{
|
||
eO_OUTS_V1,
|
||
};
|
||
|
||
enum PINS_V1
|
||
{
|
||
eRESET_V1,
|
||
eWAITFORCOMPLETION_V1,
|
||
eSTOP_AT_EXIT_V1,
|
||
ePI_INPUTS_V1,
|
||
};
|
||
|
||
enum POUTS_V1
|
||
{
|
||
ePO_OUTPUTS_V1,
|
||
};
|
||
|
||
enum PLOCALS_V1
|
||
{
|
||
ePI_TARGET_BEHAVIOR_V1, //setting
|
||
ePL_MAX_RECURSION_DEPTH_V1, //setting
|
||
eDO_NOT_RESTORE_PARAMETERS_V1, //setting, optimisation
|
||
ePL_RECURSION_DEPTH_V1, //local
|
||
};
|
||
|
||
int CallBehavior(const CKBehaviorContext& behcontext)
|
||
{
|
||
CKBehavior* beh = behcontext.Behavior;
|
||
|
||
//Get target behavior
|
||
CKBehavior* target = (CKBehavior*) beh->GetLocalParameterObject(ePI_TARGET_BEHAVIOR_V1);
|
||
if (!target)
|
||
return CKBR_OK;
|
||
|
||
//reset
|
||
BOOL reset=FALSE;
|
||
beh->GetInputParameterValue(eRESET_V1, &reset);
|
||
if (reset)
|
||
target->Activate(FALSE,TRUE);
|
||
|
||
//Activate Inputs
|
||
//target->ActivateInput(0);
|
||
int ioCount = target->GetInputCount();
|
||
for (int i=eI_INS_V1;i<eI_INS_V1+ioCount;++i)
|
||
{
|
||
if (beh->IsInputActive(i))
|
||
target->ActivateInput(i-eI_INS_V1);
|
||
}
|
||
|
||
// Get waitcomp
|
||
BOOL wc=TRUE;
|
||
beh->GetInputParameterValue(eWAITFORCOMPLETION_V1, &wc);
|
||
|
||
//stop at exit
|
||
BOOL stopAtExit = FALSE;
|
||
beh->GetInputParameterValue(eSTOP_AT_EXIT_V1, &stopAtExit);
|
||
|
||
//max depth
|
||
int maxDepth = 100;
|
||
beh->GetLocalParameterValue(ePL_MAX_RECURSION_DEPTH_V1,&maxDepth);
|
||
|
||
//current depth
|
||
int currentDepth = 0;
|
||
beh->GetLocalParameterValue(ePL_RECURSION_DEPTH_V1,¤tDepth);
|
||
|
||
currentDepth++;
|
||
if (maxDepth>=0 && currentDepth>maxDepth)
|
||
{
|
||
behcontext.Context->OutputToConsole("CallBehavior, recursion>max recursion depth, BB break");
|
||
return CKBR_OK;
|
||
}
|
||
beh->SetLocalParameterValue(ePL_RECURSION_DEPTH_V1,¤tDepth);
|
||
|
||
//optim
|
||
int noRestoreParam = FALSE;
|
||
beh->GetLocalParameterValue(eDO_NOT_RESTORE_PARAMETERS_V1,&noRestoreParam);
|
||
|
||
|
||
if (wc) {
|
||
int loop = 0;
|
||
int maxloop = behcontext.Context->GetBehaviorManager()->GetBehaviorMaxIteration();
|
||
for(;;++loop)
|
||
{
|
||
if (loop > maxloop) {
|
||
behcontext.Context->OutputToConsoleExBeep("Call Behavior: Behavior %s executed too much times",target?target->GetName():"NA");
|
||
target->Activate(FALSE,FALSE);
|
||
break;
|
||
}
|
||
|
||
BehaviorsParameters behParams;
|
||
if (noRestoreParam==FALSE)
|
||
behParams.SaveBehaviorParameters(target);
|
||
BehaviorsParameters::SetBehaviorParameters(beh,target,ePI_INPUTS_V1-ePI_INPUTS);
|
||
CKERROR result = target->Execute(behcontext.DeltaTime);
|
||
if (noRestoreParam==FALSE)
|
||
behParams.LoadBehaviorParameters(target);
|
||
// The target loop on itself too much times
|
||
if (result == CKBR_INFINITELOOP) {
|
||
target->Activate(FALSE,FALSE);
|
||
break;
|
||
}
|
||
if(!target->IsActive())
|
||
break;
|
||
}
|
||
} else { // we execute only one frame of the target
|
||
BehaviorsParameters behParams;
|
||
if (noRestoreParam==FALSE)
|
||
behParams.SaveBehaviorParameters(target);
|
||
BehaviorsParameters::SetBehaviorParameters(beh,target,ePI_INPUTS_V1-ePI_INPUTS);
|
||
target->Execute(behcontext.DeltaTime);
|
||
if (noRestoreParam==FALSE)
|
||
behParams.LoadBehaviorParameters(target);
|
||
target->Activate(FALSE,FALSE);
|
||
}
|
||
|
||
//recursive depth update
|
||
currentDepth--;
|
||
beh->SetLocalParameterValue(ePL_RECURSION_DEPTH_V1,¤tDepth);
|
||
|
||
// IO Activation
|
||
//beh->ActivateInput(0,FALSE);
|
||
//beh->ActivateOutput(0);
|
||
for (int i=eI_INS_V1;i<eI_INS_V1+ioCount;++i)
|
||
beh->ActivateInput(i,FALSE);
|
||
ioCount = target->GetOutputCount();
|
||
for (int i=eO_OUTS_V1;i<eO_OUTS_V1+ioCount;++i)
|
||
beh->ActivateOutput(i,target->IsOutputActive(i-eO_OUTS_V1));
|
||
|
||
if (stopAtExit)
|
||
{
|
||
for (int i=0;i<ioCount;++i)
|
||
target->ActivateOutput(i,FALSE);
|
||
}
|
||
|
||
return CKBR_OK;
|
||
}
|
||
|
||
void RemoveIOxParams(CKBehavior* beh)
|
||
{
|
||
CKContext* ctx = beh->GetCKContext();
|
||
int count = beh->GetInputParameterCount()-ePI_INPUTS_V1;
|
||
for (int i=0;i<count;++i)
|
||
ctx->DestroyObject(beh->RemoveInputParameter(ePI_INPUTS_V1),CK_DESTROY_NONOTIFY,0);
|
||
|
||
count = beh->GetOutputParameterCount()-ePO_OUTPUTS_V1;
|
||
for (int i=0;i<count;++i)
|
||
ctx->DestroyObject(beh->RemoveOutputParameter(ePO_OUTPUTS_V1),CK_DESTROY_NONOTIFY,0);
|
||
|
||
count = beh->GetInputCount()-eI_INS_V1;
|
||
for (int i=0;i<count;++i)
|
||
beh->DeleteInput(eI_INS_V1);
|
||
|
||
count = beh->GetOutputCount()-eO_OUTS_V1;
|
||
for (int i=0;i<count;++i)
|
||
beh->DeleteOutput(eO_OUTS_V1);
|
||
}
|
||
|
||
CKERROR CallBehaviorCallback(const CKBehaviorContext& behcontext)
|
||
{
|
||
CKBehavior* beh = behcontext.Behavior;
|
||
switch( behcontext.CallbackMessage )
|
||
{
|
||
//create same ios as in target behavior
|
||
case CKM_BEHAVIOREDITED:
|
||
{
|
||
CKBehavior* target = (CKBehavior*) beh->GetLocalParameterObject(ePI_TARGET_BEHAVIOR_V1);
|
||
//update behavior ios & types just in case
|
||
BehaviorsParameters::NameBehaviorParameters(beh,target,ePI_INPUTS_V1-ePI_INPUTS);
|
||
}
|
||
break;
|
||
case CKM_BEHAVIORSETTINGSEDITED:
|
||
{
|
||
CKBehavior* target = (CKBehavior*) beh->GetLocalParameterObject(ePI_TARGET_BEHAVIOR_V1);
|
||
BOOL bb = FALSE;
|
||
if (target)
|
||
bb = (target->GetFlags() & CKBEHAVIOR_BUILDINGBLOCK)?TRUE:FALSE;
|
||
|
||
DWORD flags=0;
|
||
beh->GetLocalParameterValue(ePL_SETTINGS,&flags);
|
||
/*try to have a inside doc
|
||
if ((flags & eSetting_SaveInternalStates)==0)
|
||
{
|
||
MessageBox(0,"text\ntext2","caption",MB_OK);
|
||
}
|
||
*/
|
||
|
||
if (target==beh)// || bb) allow bb finally
|
||
{
|
||
//if (bb)
|
||
// behcontext.Context->OutputToConsole("CallBehavior BB cannot target another BB");
|
||
//else
|
||
behcontext.Context->OutputToConsole("CallBehavior BB cannot target itself");
|
||
beh->SetLocalParameterObject(ePI_TARGET_BEHAVIOR_V1,0);
|
||
beh->SetName(CALLBEHAVIOR_NAME);
|
||
RemoveIOxParams(beh);
|
||
|
||
behcontext.Context->SendInterfaceMessage(CKUIM_CALLBEHAVIORBB_CHANGE,(CKDWORD)beh,eCallBehavior_Edit,0);//warn interface
|
||
|
||
return CKBR_PARAMETERERROR;
|
||
}
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
//Fit IOs & Params
|
||
if (CKIsChildClassOf(target,CKCID_BEHAVIOR) && target->GetOwner())
|
||
{
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
//Params
|
||
int inCountTarget = target->GetInputParameterCount();
|
||
int outCountTarget = target->GetOutputParameterCount();
|
||
|
||
int inCountCaller = beh->GetInputParameterCount();
|
||
int outCountCaller = beh->GetOutputParameterCount();
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
//remove params if too much
|
||
for (int i=inCountCaller-1;i>=ePI_INPUTS_V1+inCountTarget;i--)
|
||
behcontext.Context->DestroyObject(beh->RemoveInputParameter(i),CK_DESTROY_NONOTIFY,0);
|
||
for (int i=outCountCaller-1;i>=ePO_OUTPUTS_V1+outCountTarget;i--)
|
||
behcontext.Context->DestroyObject(beh->RemoveOutputParameter(i),CK_DESTROY_NONOTIFY,0);
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
//create params if not enough
|
||
inCountCaller = beh->GetInputParameterCount();
|
||
outCountCaller = beh->GetOutputParameterCount();
|
||
|
||
for (int i=inCountCaller-ePI_INPUTS_V1;i<inCountTarget;i++)
|
||
{
|
||
CKParameterIn* pin = target->GetInputParameter(i);
|
||
beh->CreateInputParameter(pin->GetName(),pin->GetGUID());
|
||
}
|
||
for (int i=outCountCaller-ePO_OUTPUTS_V1;i<outCountTarget;i++)
|
||
{
|
||
CKParameterOut* pout = target->GetOutputParameter(i);
|
||
beh->CreateOutputParameter(pout->GetName(),pout->GetGUID());
|
||
}
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
//IOs
|
||
inCountTarget = target->GetInputCount();
|
||
outCountTarget = target->GetOutputCount();
|
||
|
||
inCountCaller = beh->GetInputCount();
|
||
outCountCaller = beh->GetOutputCount();
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
//remove IOS if too much
|
||
for (int i=inCountCaller-1;i>=eI_INS_V1+inCountTarget;i--)
|
||
beh->DeleteInput(i);
|
||
for (int i=outCountCaller-1;i>=eO_OUTS_V1+outCountTarget;i--)
|
||
beh->DeleteOutput(i);
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
//create IOS if not enough
|
||
inCountCaller = beh->GetInputCount();
|
||
outCountCaller = beh->GetOutputCount();
|
||
|
||
for (int i=inCountCaller-eI_INS_V1;i<inCountTarget;i++)
|
||
{
|
||
CKBehaviorIO* io = target->GetInput(i);
|
||
beh->CreateInput(io->GetName());
|
||
}
|
||
for (int i=outCountCaller-eO_OUTS_V1;i<outCountTarget;i++)
|
||
{
|
||
CKBehaviorIO* io = target->GetOutput(i);
|
||
beh->CreateOutput(io->GetName());
|
||
}
|
||
|
||
//rename
|
||
BehaviorsParameters::NameBehaviorParameters(beh,target,ePI_INPUTS_V1-ePI_INPUTS);
|
||
if (target && target->GetName())
|
||
{
|
||
XString finalName;
|
||
finalName.Format("%s:%s",CALLBEHAVIOR_NAME,target->GetName());
|
||
beh->SetName(finalName.Str());
|
||
}
|
||
}
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
else //remove all supplementary pins & pouts from BB
|
||
{
|
||
RemoveIOxParams(beh);
|
||
beh->SetName(CALLBEHAVIOR_NAME);
|
||
}
|
||
|
||
{
|
||
CKBehavior* target = (CKBehavior*) beh->GetLocalParameterObject(ePI_TARGET_BEHAVIOR_V1);
|
||
behcontext.Context->SendInterfaceMessage(CKUIM_CALLBEHAVIORBB_CHANGE,(CKDWORD)beh,eCallBehavior_Edit,(CKDWORD)target);//warn interface
|
||
}
|
||
break;
|
||
}
|
||
break;
|
||
case CKM_BEHAVIORDELETE:
|
||
case CKM_BEHAVIORDETACH:
|
||
{
|
||
CKBehavior* target = (CKBehavior*) beh->GetLocalParameterObject(ePI_TARGET_BEHAVIOR_V1);
|
||
behcontext.Context->SendInterfaceMessage(CKUIM_CALLBEHAVIORBB_CHANGE,(CKDWORD)beh,eCallBehavior_Detach,(CKDWORD)target);//warn interface
|
||
}
|
||
break;
|
||
case CKM_BEHAVIORLOAD:
|
||
case CKM_BEHAVIORATTACH:
|
||
{
|
||
CKBehavior* target = (CKBehavior*) beh->GetLocalParameterObject(ePI_TARGET_BEHAVIOR_V1);
|
||
behcontext.Context->SendInterfaceMessage(CKUIM_CALLBEHAVIORBB_CHANGE,(CKDWORD)beh,eCallBehavior_Attach,(CKDWORD)target);//warn interface
|
||
if (behcontext.Context->IsInInterfaceMode())
|
||
{
|
||
if (target && target->GetName())
|
||
{
|
||
XString finalName;
|
||
finalName.Format("%s:%s",CALLBEHAVIOR_NAME,target->GetName());
|
||
beh->SetName(finalName.Str());
|
||
}
|
||
}
|
||
|
||
}
|
||
break;
|
||
}
|
||
return CK_OK;
|
||
}
|
||
|
||
|
||
//////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////
|
||
//BehaviorsParameters
|
||
//////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////
|
||
|
||
void BehaviorsParameters::Clear()
|
||
{
|
||
if (sources)
|
||
delete [] sources;
|
||
if (destinations)
|
||
{
|
||
for (int i=0;i<destinationsCount;i++)
|
||
{
|
||
delete [] destinations[i];
|
||
}
|
||
delete [] destinations;
|
||
}
|
||
memset(this,0,sizeof(this));
|
||
}
|
||
|
||
|
||
void BehaviorsParameters::SaveBehaviorParameters(CKBehavior* beh)
|
||
{
|
||
if (!beh)
|
||
return;
|
||
Clear();
|
||
//save pins
|
||
sourcesCount = beh->GetInputParameterCount();
|
||
sources = new CK_ID[sourcesCount*2];
|
||
for (int i=0;i<sourcesCount;++i)
|
||
{
|
||
CKParameterIn* pin = beh->GetInputParameter(i);
|
||
if (pin)
|
||
{
|
||
if (CKParameterIn* shared = pin->GetSharedSource())
|
||
{
|
||
sources[i*2] = 1;
|
||
sources[i*2+1] = shared->GetID();
|
||
}
|
||
else if (CKParameter* p = pin->GetDirectSource())
|
||
{
|
||
sources[i*2] = 0;
|
||
sources[i*2+1] = p->GetID();
|
||
}
|
||
else
|
||
{
|
||
sources[i*2] = 0;
|
||
sources[i*2+1] = 0;
|
||
}
|
||
}
|
||
}
|
||
//save pouts
|
||
destinationsCount = beh->GetOutputParameterCount();
|
||
destinations = new CK_ID*[destinationsCount];
|
||
for (int i=0;i<destinationsCount;++i)
|
||
{
|
||
CKParameterOut* pout = beh->GetOutputParameter(i);
|
||
if (pout)
|
||
{
|
||
if (int destCount = pout->GetDestinationCount())
|
||
{
|
||
destinations[i] = new CK_ID[destCount+1];
|
||
destinations[i][0] = destCount;
|
||
for (int j=0;j<destCount;++j)
|
||
{
|
||
CKParameter* dest = pout->GetDestination(j);
|
||
destinations[i][j+1] = dest?dest->GetID():0;
|
||
}
|
||
}
|
||
else
|
||
destinations[i] = 0;
|
||
}
|
||
}
|
||
}
|
||
|
||
void BehaviorsParameters::LoadBehaviorParameters(CKBehavior* beh)
|
||
{
|
||
if (!beh)
|
||
return;
|
||
//restore pins
|
||
for (int i=0;i<sourcesCount;++i)
|
||
{
|
||
CKParameterIn* pin = beh->GetInputParameter(i);
|
||
if (pin)
|
||
{
|
||
CK_ID id = sources[2*i+1];
|
||
if (id==0)
|
||
{
|
||
pin->ShareSourceWith(0);
|
||
pin->SetDirectSource(0);
|
||
}
|
||
else
|
||
{
|
||
CKObject* obj = beh->GetCKContext()->GetObject(id);
|
||
if (sources[2*i]==0)
|
||
{
|
||
pin->ShareSourceWith(0);
|
||
pin->SetDirectSource((CKParameter*)obj);
|
||
}
|
||
else
|
||
{
|
||
pin->SetDirectSource(0);
|
||
pin->ShareSourceWith((CKParameterIn*)obj);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
//restore pouts
|
||
for (int i=0;i<destinationsCount;++i)
|
||
{
|
||
CKParameterOut* pout = beh->GetOutputParameter(i);
|
||
if (pout)
|
||
{
|
||
pout->RemoveAllDestinations();
|
||
if (destinations[i])
|
||
{
|
||
int count = destinations[i][0];
|
||
for (int j=0;j<count;++j)
|
||
{
|
||
CKParameter* p = (CKParameter*)beh->GetCKContext()->GetObject(destinations[i][j+1]);
|
||
if (CKIsChildClassOf(p,CKCID_PARAMETER))
|
||
pout->AddDestination(p);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
void BehaviorsParameters::SetBehaviorParameters(CKBehavior* callBB,CKBehavior* calledBeh,int iPinOffset)
|
||
{
|
||
if (!callBB || !calledBeh)
|
||
return;
|
||
|
||
int inCountTarget = calledBeh->GetInputParameterCount();
|
||
int outCountTarget = calledBeh->GetOutputParameterCount();
|
||
//set sources & dest
|
||
for (int i=0;i<inCountTarget;++i)
|
||
{
|
||
CKParameterIn* pin1 = calledBeh->GetInputParameter(i);
|
||
CKParameterIn* pin2 = callBB->GetInputParameter(i+ePI_INPUTS+iPinOffset);
|
||
if (pin1 && pin2)
|
||
pin1->SetDirectSource(pin2->GetRealSource());
|
||
}
|
||
for (int i=0;i<outCountTarget;++i)
|
||
{
|
||
CKParameterOut* pout1 = calledBeh->GetOutputParameter(i);
|
||
CKParameterOut* pout2 = callBB->GetOutputParameter(i+ePO_OUTPUTS);
|
||
if (pout1 && pout2)
|
||
{
|
||
pout1->RemoveAllDestinations();
|
||
pout1->AddDestination(pout2);
|
||
}
|
||
}
|
||
}
|
||
|
||
void BehaviorsParameters::NameBehaviorParameters(CKBehavior* callBB,CKBehavior* calledBeh,int iPinOffset)
|
||
{
|
||
if (!calledBeh)
|
||
return;
|
||
|
||
int count = calledBeh->GetInputParameterCount();
|
||
for (int i=0;i<count;++i)
|
||
{
|
||
CKParameterIn* p1 = calledBeh->GetInputParameter(i);
|
||
CKParameterIn* p2 = callBB->GetInputParameter(i+ePI_INPUTS+iPinOffset);
|
||
if (p1 && p2)
|
||
{
|
||
p2->SetName(p1->GetName());
|
||
if (p1->GetType()!=p2->GetType())
|
||
{
|
||
p2->SetType(p1->GetType());
|
||
//CKParameter* psource = p2->GetRealSource();
|
||
//if (psource)
|
||
// psource->SetType(p1->GetType());
|
||
}
|
||
}
|
||
}
|
||
|
||
count = calledBeh->GetOutputParameterCount();
|
||
for (int i=0;i<count;++i)
|
||
{
|
||
CKParameter* p1 = calledBeh->GetOutputParameter(i);
|
||
CKParameter* p2 = callBB->GetOutputParameter(i+ePO_OUTPUTS);
|
||
if (p1 && p2)
|
||
{
|
||
p2->SetName(p1->GetName());
|
||
if (p1->GetType()!=p2->GetType())
|
||
{
|
||
p2->SetType(p1->GetType());
|
||
}
|
||
}
|
||
}
|
||
|
||
count = calledBeh->GetInputCount();
|
||
for (int i=0;i<count;++i)
|
||
{
|
||
CKBehaviorIO* p1 = calledBeh->GetInput(i);
|
||
CKBehaviorIO* p2 = callBB->GetInput(i+eI_INS);
|
||
if (p1 && p2)
|
||
p2->SetName(p1->GetName());
|
||
}
|
||
|
||
count = calledBeh->GetOutputCount();
|
||
for (int i=0;i<count;++i)
|
||
{
|
||
CKBehaviorIO* p1 = calledBeh->GetOutput(i);
|
||
CKBehaviorIO* p2 = callBB->GetOutput(i+eO_OUTS);
|
||
if (p1 && p2)
|
||
p2->SetName(p1->GetName());
|
||
}
|
||
}
|
||
|
||
void BehaviorsParameters::ResetBehaviorParameters(CKBehavior* behavior)
|
||
{
|
||
if (!behavior)
|
||
return;
|
||
|
||
int inCountTarget = behavior->GetInputParameterCount();
|
||
int outCountTarget = behavior->GetOutputParameterCount();
|
||
//set sources & dest
|
||
for (int i=0;i<inCountTarget;++i)
|
||
{
|
||
CKParameterIn* pin1 = behavior->GetInputParameter(i);
|
||
if (pin1)
|
||
{
|
||
pin1->SetDirectSource(0);
|
||
pin1->ShareSourceWith(0);
|
||
}
|
||
}
|
||
for (int i=0;i<outCountTarget;++i)
|
||
{
|
||
CKParameterOut* pout1 = behavior->GetOutputParameter(i);
|
||
if (pout1)
|
||
pout1->RemoveAllDestinations();
|
||
}
|
||
}
|
||
|
||
void BehaviorInternalStates::SaveAllSubBehaviorLocalParameterValues(CKBehavior* beh,int iDepth)
|
||
{
|
||
if (!m_Chunk)
|
||
{
|
||
m_Chunk = CreateCKStateChunk(CKCID_OBJECT);
|
||
m_Flags |= eInternallyCreatedChunk ;
|
||
|
||
/*
|
||
m_Chunk->StartWrite();
|
||
m_Chunk->WriteInt(-2);
|
||
m_Chunk->CloseChunk();
|
||
|
||
m_Chunk->StartRead();
|
||
int toto = m_Chunk->ReadInt();
|
||
m_Chunk->CloseChunk();
|
||
*/
|
||
}
|
||
|
||
if (iDepth>0) //Save local datas of this iBeh
|
||
{
|
||
m_Chunk->WriteInt(eST_Behavior);
|
||
m_Chunk->WriteObject(beh);
|
||
m_Chunk->WriteInt(eST_ActiveStates);
|
||
m_Chunk->WriteDword(GetBehaviorActiveStates(beh));
|
||
|
||
if ((beh->GetFlags() & CKBEHAVIOR_BUILDINGBLOCK)) //IF BUILDING BLOCK
|
||
{//if bb
|
||
|
||
int localCount = beh->GetLocalParameterCount();
|
||
int poutCount = beh->GetOutputParameterCount();
|
||
//localCount = poutCount = 0;
|
||
/*
|
||
if (localCount ||poutCount)
|
||
{
|
||
m_Chunk->WriteInt(eST_Behavior);
|
||
m_Chunk->WriteObject(beh);
|
||
}
|
||
*/
|
||
|
||
if (localCount)
|
||
{//if localcount
|
||
for (int i=0;i<localCount;++i)
|
||
{//for all locals
|
||
if (!beh->IsLocalParameterSetting(i))
|
||
{//if not a setting
|
||
CKParameter* param = beh->GetLocalParameter(i);
|
||
int datasize = param->GetDataSize();
|
||
if (datasize)
|
||
{
|
||
BYTE* buffer = new BYTE[datasize];
|
||
CKERROR ckerror = param->GetValue(buffer);
|
||
if (ckerror==CK_OK)
|
||
{
|
||
m_Chunk->WriteInt(i); //write index of local
|
||
m_Chunk->WriteBuffer(datasize,buffer); //write buffer
|
||
}
|
||
delete[] buffer;
|
||
}//if datasize
|
||
}//if not a setting
|
||
}//for all locals
|
||
}//if localcount
|
||
|
||
//save pouts
|
||
if (poutCount>0)
|
||
{
|
||
m_Chunk->WriteInt(eST_OutputParameters);
|
||
m_Chunk->WriteInt(poutCount);
|
||
for (int i=0;i<poutCount;++i)
|
||
{
|
||
CKParameterOut* param= beh->GetOutputParameter(i);
|
||
int datasize = param->GetDataSize();
|
||
if (datasize)
|
||
{
|
||
BYTE* buffer = new BYTE[datasize];
|
||
CKERROR ckerror = param->GetValue(buffer);
|
||
if (ckerror==CK_OK)
|
||
m_Chunk->WriteBuffer(datasize,buffer); //write buffer
|
||
else
|
||
m_Chunk->WriteBuffer(0,0); //write buffer
|
||
delete[] buffer;
|
||
}
|
||
else
|
||
m_Chunk->WriteBuffer(0,0); //write buffer
|
||
}
|
||
}//save pouts
|
||
|
||
}//if bb
|
||
}//if depth>0
|
||
else if (iDepth==0)
|
||
{
|
||
m_Chunk->StartWrite();
|
||
m_Chunk->WriteInt(eST_Behavior);
|
||
m_Chunk->WriteObject(beh);
|
||
m_Chunk->WriteInt(eST_ActiveStates);
|
||
m_Chunk->WriteDword(GetBehaviorActiveStates(beh));
|
||
}
|
||
|
||
//parse children
|
||
int childrenCount = beh->GetSubBehaviorCount();
|
||
for (int i=0;i<childrenCount;++i)
|
||
SaveAllSubBehaviorLocalParameterValues(beh->GetSubBehavior(i),iDepth+1);
|
||
|
||
if (iDepth==0)
|
||
{
|
||
m_Chunk->WriteInt(eST_End);
|
||
m_Chunk->CloseChunk();
|
||
}
|
||
|
||
}
|
||
|
||
void BehaviorInternalStates::LoadAllSubBehaviorLocalParameterValues(CKBehavior* beh,int iDepth)
|
||
{
|
||
if (m_Chunk && m_Chunk->GetDataSize()>0)
|
||
{
|
||
m_Chunk->StartRead();
|
||
CKBehavior* currentBeh = 0;
|
||
int tag = m_Chunk->ReadInt();
|
||
while (tag!=eST_End)
|
||
{
|
||
if (tag==eST_Behavior)
|
||
{
|
||
currentBeh = (CKBehavior*)m_Chunk->ReadObject(beh->GetCKContext());
|
||
}
|
||
else if (tag==eST_OutputParameters)
|
||
{
|
||
int poutCount = m_Chunk->ReadInt();
|
||
for (int i=0;i<poutCount;++i)
|
||
{
|
||
void* buffer = 0;
|
||
int datasize = m_Chunk->ReadBuffer(&buffer);
|
||
if (currentBeh)
|
||
{
|
||
CKParameterOut* param = currentBeh->GetOutputParameter(i);
|
||
param->SetValue(buffer,datasize);
|
||
}
|
||
if (datasize)
|
||
CKDeletePointer(buffer);
|
||
}
|
||
}
|
||
else if (tag==eST_ActiveStates)
|
||
{
|
||
SetBehaviorActiveStates(currentBeh,m_Chunk->ReadDword());
|
||
}
|
||
else if (tag>=0)
|
||
{
|
||
void* buffer = 0;
|
||
int datasize = m_Chunk->ReadBuffer(&buffer);
|
||
if (currentBeh)
|
||
{
|
||
CKParameter* param = currentBeh->GetLocalParameter(tag);
|
||
param->SetValue(buffer,datasize);
|
||
}
|
||
if (datasize>0)
|
||
CKDeletePointer(buffer);
|
||
}
|
||
tag = m_Chunk->ReadInt();
|
||
}
|
||
m_Chunk->CloseChunk();
|
||
}
|
||
else
|
||
{
|
||
//restore default values
|
||
if (iDepth>0)
|
||
{
|
||
if ((beh->GetFlags() & CKBEHAVIOR_BUILDINGBLOCK)) //IF BUILDING BLOCK
|
||
{//if bb
|
||
CKBehaviorPrototype* proto = beh->GetPrototype();
|
||
if (proto)
|
||
{//restore local default values
|
||
int localCount = beh->GetLocalParameterCount();
|
||
if (localCount)
|
||
{//if localcount
|
||
const XClassArray<CKPARAMETER_DESC>& LocalParamList = proto->GetLocalParameterList();
|
||
localCount = LocalParamList.Size();
|
||
for (int i=0;i<localCount;++i)
|
||
{//for all locals
|
||
if (!beh->IsLocalParameterSetting(i))
|
||
{//if not a setting
|
||
CKParameter* param = beh->GetLocalParameter(i);
|
||
if (LocalParamList[i].DefaultValueString)
|
||
param->SetStringValue(LocalParamList[i].DefaultValueString);
|
||
else if (LocalParamList[i].DefaultValue && LocalParamList[i].DefaultValueSize)
|
||
param->SetValue((void*)LocalParamList[i].DefaultValue,LocalParamList[i].DefaultValueSize);
|
||
}//if not a setting
|
||
}//for all locals
|
||
}//if localcount
|
||
|
||
//restore pout default values
|
||
int poutCount = beh->GetOutputParameterCount();
|
||
if (poutCount)
|
||
{
|
||
const XClassArray<CKPARAMETER_DESC>& OutParamList=proto->GetOutParameterList();
|
||
poutCount = OutParamList.Size();
|
||
for(int i=0;i<poutCount;i++)
|
||
{
|
||
CKParameterOut* param = beh->GetOutputParameter(i);
|
||
if (OutParamList[i].DefaultValueString)
|
||
param->SetStringValue(OutParamList[i].DefaultValueString);
|
||
else if (OutParamList[i].DefaultValue && OutParamList[i].DefaultValueSize)
|
||
param->SetValue((void*)OutParamList[i].DefaultValue,OutParamList[i].DefaultValueSize);
|
||
}
|
||
}//if poutcount
|
||
}//if proto
|
||
|
||
}//if bb
|
||
}//if depth>0
|
||
|
||
//parse children
|
||
int childrenCount = beh->GetSubBehaviorCount();
|
||
for (int i=0;i<childrenCount;++i)
|
||
LoadAllSubBehaviorLocalParameterValues(beh->GetSubBehavior(i),iDepth+1);
|
||
}
|
||
}
|
||
|
||
DWORD BehaviorInternalStates::GetBehaviorActiveStates(CKBehavior* beh)
|
||
{
|
||
DWORD activeStates = 0;
|
||
if (beh->IsActive())
|
||
activeStates |= 1<<31;
|
||
int outputCount = beh->GetOutputCount();
|
||
for (int i=0;i<outputCount;++i)
|
||
{
|
||
if (beh->IsOutputActive(i))
|
||
activeStates |= 1<<i;
|
||
}
|
||
return activeStates;
|
||
}
|
||
|
||
void BehaviorInternalStates::SetBehaviorActiveStates(CKBehavior* beh,DWORD activeStates)
|
||
{
|
||
if (activeStates & 1<<31)
|
||
beh->Activate(TRUE,FALSE);
|
||
int outputCount = beh->GetOutputCount();
|
||
for (int i=0;i<outputCount;++i)
|
||
{
|
||
if (activeStates & 1<<i)
|
||
beh->ActivateOutput(i);
|
||
}
|
||
}
|