///////////////////////////////////////////////////// ///////////////////////////////////////////////////// // // FlowLayout3D // ///////////////////////////////////////////////////// ///////////////////////////////////////////////////// #include "CKAll.h" #include "Layout.h" CKObjectDeclaration *FillBehaviorFlowLayout3DDecl(); CKERROR CreateFlowLayout3DProto(CKBehaviorPrototype** pproto); int FlowLayout3D(const CKBehaviorContext& behcontext); //------------------------------------------------- // Creates a declaration of this behavior // //------------------------------------------------- CKObjectDeclaration *FillBehaviorFlowLayout3DDecl() { CKObjectDeclaration *od = CreateCKObjectDeclaration("3D Flow Layout"); od->SetDescription("Organize a set of 3D entities belong a direction in space"); /* rem: In: triggers the process.
Out: is activated when the process is completed.

Model: 3D Entity determining the position and direction of the flow.
Flow Direction:on which axis of the target referencial the flow must lie.
Flow Alignement: alignement to use / target.
Support: select depth start of the flow / target.
Top Margin: margin from the top of the target.
Side Margin: margin from the left or right side of the target (depends on alignement).
Offset Margin: margin from the XY plan of the target (depends on alignement).
Gap Size: space between the displaced entities.
Keep Children?: if checked, displace the childs of the entities in group.

*/ // Category in Virtools interface od->SetCategory("Interface/Layouts"); od->SetType( CKDLL_BEHAVIORPROTOTYPE); // Unique identifier of this prototype od->SetGuid(CKGUID(0x245fb72c,0xa5e437e6)); od->SetAuthorGuid(VIRTOOLS_GUID); od->SetAuthorName("Virtools"); od->SetVersion(0x00010000); // Function that will create the behavior prototype od->SetCreationFunction(CreateFlowLayout3DProto); // Class ID of the objects to which the behavior can applied od->SetCompatibleClassId(CKCID_GROUP); return od; } //------------------------------------------------- // FlowLayout3D behavior prototype creation function // //------------------------------------------------- CKERROR CreateFlowLayout3DProto(CKBehaviorPrototype **pproto) { CKBehaviorPrototype *proto = CreateCKBehaviorPrototype("3D Flow Layout"); if(!proto) return CKERR_OUTOFMEMORY; // Input/Outputs declaration proto->DeclareInput("In"); proto->DeclareOutput("Out"); proto->DeclareInParameter("Model", CKPGUID_3DENTITY); proto->DeclareInParameter("Flow Direction", CKPGUID_FLOW_DIRECTION, "Left/Right"); proto->DeclareInParameter("Flow Alignment", CKPGUID_FLOW_ALIGNMENT, "Left"); proto->DeclareInParameter("Support", CKPGUID_FLOW_SUPPORT, "Front"); proto->DeclareInParameter("Top Margin", CKPGUID_FLOAT, "0.5"); proto->DeclareInParameter("Side Margin", CKPGUID_FLOAT, "0.5"); proto->DeclareInParameter("Offset Margin", CKPGUID_FLOAT, "0"); proto->DeclareInParameter("Gap Size", CKPGUID_FLOAT, "0.5"); proto->DeclareInParameter("Keep Children ?", CKPGUID_BOOL, "FALSE"); proto->SetFlags(CK_BEHAVIORPROTOTYPE_NORMAL); proto->SetBehaviorFlags(CKBEHAVIOR_TARGETABLE); // Function that will be called upon behavior execution proto->SetFunction(FlowLayout3D); *pproto = proto; return CK_OK; } #define DIR_LEFT_RIGHT 1 #define DIR_UP_DOWN 2 #define DIR_REAR_FRONT 4 #define ALIGN_LEFT 1 #define ALIGN_CENTER 2 #define ALIGN_RIGHT 4 #define ALIGN_FRONT 1 #define ALIGN_IN 2 #define ALIGN_REAR 4 //------------------------------------------------- // FlowLayout3D behavior execution function // //------------------------------------------------- int FlowLayout3D(const CKBehaviorContext& behcontext) { CKBehavior* beh = behcontext.Behavior; // Deactivate Input beh->ActivateInput(0, FALSE); beh->ActivateOutput(0); // Group of Array CKGroup* group = (CKGroup*)beh->GetTarget(); if (!group) return CKBR_OWNERERROR; // Check if the group is only formed of 3D entities if (!CKIsChildClassOf(group->GetCommonClassID(),CKCID_3DENTITY)) return CKBR_OK; int objectCount = group->GetObjectCount(); if (objectCount == 0) return CKBR_OK; // Get the reference 3D frame CK3dEntity* rootFrame = (CK3dEntity*)beh->GetInputParameterObject(0); if (!rootFrame) return CKBR_PARAMETERERROR; // Get the layout parameters int direction = 1, alignment = ALIGN_LEFT, support = ALIGN_FRONT; float topMargin = 0.5, sideMargin = 0.5, offsetMargin = 0.0, gapSize = 0.5; CKBOOL keepChildren = FALSE; beh->GetInputParameterValue(1, &direction); beh->GetInputParameterValue(2, &alignment); beh->GetInputParameterValue(3, &support); beh->GetInputParameterValue(4, &topMargin); beh->GetInputParameterValue(5, &sideMargin); beh->GetInputParameterValue(6, &offsetMargin); beh->GetInputParameterValue(7, &gapSize); beh->GetInputParameterValue(8, &keepChildren); // Position of each entity in the group relative to the reference frame VxBbox currentBoundingBox; VxVector currentPosition; VxVector rootDir, rootUp; // Position and orientation of the reference frame rootFrame->GetPosition(¤tPosition); rootFrame->GetOrientation(&rootDir, &rootUp); // Dimension of the root frame VxVector currentScale; rootFrame->GetScale(¤tScale, FALSE); currentPosition.y += (currentScale.y - topMargin); if(support & ALIGN_FRONT) // Front currentPosition.z -= (currentScale.z + offsetMargin); else if(support & ALIGN_IN) // In currentPosition.z -= offsetMargin; else // Rear currentPosition.z += (currentScale.z - offsetMargin); if(alignment & ALIGN_LEFT) // Left currentPosition.x += (sideMargin - currentScale.x); else if(alignment & ALIGN_CENTER) {// Center if(direction & DIR_LEFT_RIGHT) { // Left/Right int real3DEntity = 0; float totalSize = 0.0; for(int i = 0 ; i < objectCount ; i++) { CKBeObject* obj = group->GetObject(i); if(CKIsChildClassOf(obj, CKCID_3DENTITY)) { CK3dEntity* ent = (CK3dEntity*)obj; const VxMatrix& mat = ent->GetWorldMatrix(); real3DEntity++; //totalSize += currentScale.x ; totalSize += Magnitude(mat[0]) * 2.0f; // scale X } } if(real3DEntity == 0) return CKBR_OK; currentPosition.x -= ((totalSize + (real3DEntity-1)*gapSize)/2); } } else // alignment == 3 : Right currentPosition.x += (currentScale.x - sideMargin); for(int i = 0 ; i < objectCount ; i++) { CKBeObject* obj = group->GetObject(i); if(CKIsChildClassOf(obj, CKCID_3DENTITY)) { CK3dEntity* ent = (CK3dEntity*)obj; ent->GetScale(¤tScale, FALSE); VxVector objPosition(currentPosition); if((direction & DIR_LEFT_RIGHT) && (alignment & ( ALIGN_LEFT | ALIGN_CENTER)) ) { // (Left or Center) and Left/Right objPosition.x += currentScale.x; } else { if(alignment & ALIGN_RIGHT) // Right objPosition.x -= currentScale.x; } objPosition.y -= currentScale.y; ent->SetPosition(&objPosition, NULL, keepChildren); ent->SetOrientation(&rootDir, &rootUp, NULL, NULL, keepChildren); ent->SetParent(rootFrame); if(direction & DIR_LEFT_RIGHT) { // Left/Right if(alignment & (ALIGN_LEFT | ALIGN_CENTER)) // Left or Center currentPosition.x += (2*currentScale.x + gapSize); else if(alignment & ALIGN_RIGHT) // Right currentPosition.x -= (2*currentScale.x + gapSize); } else { if (direction & DIR_UP_DOWN) // Up/Down currentPosition.y -= (2*currentScale.y + gapSize); else // direction == 3 Rear/Front currentPosition.z -= (2*currentScale.z + gapSize); } } } return CKBR_OK; }