deargui-vpl/ref/virtools/Samples/Behaviors/Narratives/CallBehavior2.cpp

1524 lines
46 KiB
C++
Raw Permalink Blame History

//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,&currentDepth);
//update current Depth
currentDepth++;
beh->SetLocalParameterValue(ePL_RECURSION_DEPTH,&currentDepth);
//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,&currentDepth);
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,&currentDepth);
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,&currentDepth);
//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,&currentDepth);
// 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);
}
}