/////////////////////////////////////////////////////
/////////////////////////////////////////////////////
//
// 2d Picking
//
/////////////////////////////////////////////////////
/////////////////////////////////////////////////////
#include "CKALL.h"
CKObjectDeclaration *FillBehaviorPicking2dDecl();
CKERROR CreatePicking2dProto(CKBehaviorPrototype **);
int Picking2d(const CKBehaviorContext& context);
CKERROR Picking2dCallBackObject(const CKBehaviorContext& behcontext);
CKObjectDeclaration *FillBehaviorPicking2dDecl()
{
CKObjectDeclaration *od = CreateCKObjectDeclaration("2D Picking");
od->SetDescription("Returns the 3D Entity, the normal and the exact position of the 2d mouse picking");
/* rem:
In : triggers the process.
True : is activated when the ray intersects an object or a sprite.
False : is activated when the ray doesn't intersect an object.
Window Relative : Check this parameter if you give coordinates in the render window coordinate system,
or leave it uncheck if you give them in the entire screen coordinates (like the values returned by the
GetMousePosition behavior). For fullscreen mode, this parameter makes no difference.
Object intersected : The first object in Z order, under the picking.
Intersection Point : exact 3d point coordinates of the intersection point (this point is given in world space coordinates).
Intersection Normal : coordinates of the normal vector on the picked object.
UV Coordinates : coordinates on the 'texel' picked (pixel on the texture).
Distance from The Viewpoint : distance of the exact 3d point from the viewpoint
Face Index : index, on the object, of the picked face
Sprite: picked sprite, if any.
*/
od->SetCategory("Interface/Screen");
od->SetType( CKDLL_BEHAVIORPROTOTYPE);
od->SetGuid(CKGUID(0x1616120f,0x5b2f48ce));
od->SetAuthorGuid(VIRTOOLS_GUID);
od->SetAuthorName("Virtools");
od->SetVersion(0x00030000);
od->SetCreationFunction(CreatePicking2dProto);
od->SetCompatibleClassId(CKCID_BEOBJECT);
od->NeedManager(INPUT_MANAGER_GUID);
return od;
}
CKERROR CreatePicking2dProto(CKBehaviorPrototype **pproto)
{
CKBehaviorPrototype *proto = CreateCKBehaviorPrototype("2D Picking");
if(!proto) return CKERR_OUTOFMEMORY;
proto->DeclareInput("In");
proto->DeclareOutput("True");
proto->DeclareOutput("False");
proto->DeclareInParameter("Pos", CKPGUID_2DVECTOR,"0");
proto->DeclareInParameter("Window Relative", CKPGUID_BOOL,"FALSE");
proto->DeclareSetting("Use 2D Vector?", CKPGUID_BOOL,"TRUE");
proto->DeclareSetting("Use Mouse Coordinates?", CKPGUID_BOOL,"TRUE");
proto->DeclareSetting("Local Output", CKPGUID_BOOL, "FALSE");
proto->DeclareSetting("In Render View", CKPGUID_BOOL, "FALSE");
proto->DeclareOutParameter("Object Picked", CKPGUID_3DENTITY);
proto->DeclareOutParameter("Intersection Point", CKPGUID_VECTOR);
proto->DeclareOutParameter("Intersection Normal", CKPGUID_VECTOR);
proto->DeclareOutParameter("UV Coordinates", CKPGUID_2DVECTOR);
proto->DeclareOutParameter("Distance from The Viewpoint", CKPGUID_FLOAT);
proto->DeclareOutParameter("Face Index", CKPGUID_INT);
proto->DeclareOutParameter("Sprite", CKPGUID_SPRITE);
proto->SetFlags(CK_BEHAVIORPROTOTYPE_NORMAL);
proto->SetBehaviorFlags((CK_BEHAVIOR_FLAGS)(CKBEHAVIOR_INTERNALLYCREATEDINPUTPARAMS));
proto->SetFunction(Picking2d);
proto->SetBehaviorCallbackFct( Picking2dCallBackObject );
*pproto = proto;
return CK_OK;
}
#ifdef macintosh
#include "Interfacedefine.h"
#endif
/***********************************************/
/* Main Function */
/***********************************************/
int Picking2d(const CKBehaviorContext& behcontext)
{
CKBehavior* beh = behcontext.Behavior;
CKContext* ctx = behcontext.Context;
beh->ActivateInput(0,FALSE);
Vx2DVector point;
CKBOOL mouse = FALSE;
beh->GetLocalParameterValue(1, &mouse);
CKRenderContext* rend = ctx->GetPlayerRenderContext();
if (mouse) {
CKInputManager* input = (CKInputManager*)behcontext.Context->GetManagerByGuid(INPUT_MANAGER_GUID);
if (!input) return CKBR_GENERICERROR;
input->GetMousePosition(point,TRUE);
rend->ScreenToClient(&point);
} else {
CKBOOL use2dvector = FALSE;
beh->GetLocalParameterValue(0, &use2dvector);
BOOL wr = FALSE;
if( use2dvector ){
beh->GetInputParameterValue(0, &point);
beh->GetInputParameterValue(1, &wr);
} else {
int x,y;
beh->GetInputParameterValue(0, &x);
beh->GetInputParameterValue(1, &y);
point.Set(x,y);
beh->GetInputParameterValue(2, &wr);
}
if (!wr) {
rend->ScreenToClient(&point);
}
}
#ifndef MACINTOSHWEBPLAYER
// nicolasp : because in web player the window given by the browser doesn't
// look like PC's one, the test between the point and the ViewRect can fail.
//
//check if position is in render view
if( beh->GetVersion() >= 0x00030000 )
{
VxRect viewRect;
rend->GetViewRect(viewRect);
BOOL bForceInRenderView;
beh->GetLocalParameterValue(3, &bForceInRenderView);
if (bForceInRenderView && !viewRect.IsInside(point))
{
beh->SetOutputParameterObject(0,0); // Clearing purpose
beh->SetOutputParameterObject(6,0);
beh->ActivateOutput(1);
return CKBR_OK;
}
}
#endif
VxIntersectionDesc res;
CK3dEntity* ent = (CK3dEntity*)(rend->Pick((int)point.x,(int)point.y,&res));
if(ent || res.Sprite) {
beh->SetOutputParameterObject(0,ent);
if(ent) {
CKBOOL local = FALSE;
beh->GetLocalParameterValue(2,&local);
VxVector p;
VxVector n;
if(local) {
p = res.IntersectionPoint;
n = res.IntersectionNormal;
}
else {
ent->Transform(&p,&(res.IntersectionPoint));
ent->TransformVector(&n,&(res.IntersectionNormal));
}
beh->SetOutputParameterValue(1,&p);
beh->SetOutputParameterValue(2,&n);
Vx2DVector tex;
tex.x = res.TexU;
tex.y = res.TexV;
beh->SetOutputParameterValue(3,&tex);
beh->SetOutputParameterValue(4,&(res.Distance));
beh->SetOutputParameterValue(5,&(res.FaceIndex));
}
beh->SetOutputParameterObject(6,res.Sprite);
beh->ActivateOutput(0);
} else {
beh->SetOutputParameterObject(0,0); // Clearing purpose
beh->SetOutputParameterObject(6,0);
beh->ActivateOutput(1);
}
return CKBR_OK;
}
/************************************************/
/* CallBack */
/************************************************/
CKERROR Picking2dCallBackObject(const CKBehaviorContext& behcontext){
CKBehavior *beh = behcontext.Behavior;
switch( behcontext.CallbackMessage ){
case CKM_BEHAVIORLOAD:
{
//--- if version < 2 create setting
if( beh->GetVersion() < 0x00020000 ){
CKParameterLocal *p;
p = beh->CreateLocalParameter( "Use 2d Vector ?", CKPGUID_BOOL );
CKBOOL k = FALSE;
p->SetValue( &k );
}
} break;
case CKM_BEHAVIORCREATE:
{
CKBOOL mouse = FALSE;
beh->GetLocalParameterValue(1, &mouse);
if (mouse) {
beh->EnableInputParameter(0,FALSE);
beh->EnableInputParameter(1,FALSE);
beh->EnableInputParameter(2,FALSE);
} else {
CKBOOL use2dvector = FALSE;
beh->GetLocalParameterValue(0, &use2dvector);
beh->EnableInputParameter(0,TRUE);
beh->EnableInputParameter(1,TRUE);
beh->EnableInputParameter(2,TRUE);
}
} break;
case CKM_BEHAVIORSETTINGSEDITED:
{
CKBOOL mouse = FALSE;
beh->GetLocalParameterValue(1, &mouse);
if (mouse) {
beh->EnableInputParameter(0,FALSE);
beh->EnableInputParameter(1,FALSE);
beh->EnableInputParameter(2,FALSE);
} else {
CKBOOL use2dvector = FALSE;
beh->GetLocalParameterValue(0, &use2dvector);
beh->EnableInputParameter(0,TRUE);
beh->EnableInputParameter(1,TRUE);
beh->EnableInputParameter(2,TRUE);
CKParameterIn *pin = beh->GetInputParameter(0);
if( !pin ) return CKBR_OK;
if( use2dvector ){ // if we check 2dvector
if( pin->GetGUID() == CKPGUID_INT ){
CKDestroyObject( beh->RemoveInputParameter(0) );
CKDestroyObject( beh->RemoveInputParameter(0) );
CKDestroyObject( beh->RemoveInputParameter(0) );
beh->CreateInputParameter("Pos", CKPGUID_2DVECTOR );
beh->CreateInputParameter("Window Relative", CKPGUID_BOOL );
}
} else { // if we do not check 2dvector
if( pin->GetGUID() != CKPGUID_INT ){
CKDestroyObject( beh->RemoveInputParameter(0) );
CKDestroyObject( beh->RemoveInputParameter(0) );
beh->CreateInputParameter("X", CKPGUID_INT );
beh->CreateInputParameter("Y", CKPGUID_INT );
beh->CreateInputParameter("Window Relative", CKPGUID_BOOL );
}
}
}
} break;
}
return CK_OK;
}