/////////////////////////////////////////////////////
/////////////////////////////////////////////////////
//
// MouseCursor
//
/////////////////////////////////////////////////////
/////////////////////////////////////////////////////
#include "CKAll.h"
CKObjectDeclaration *FillBehaviorMouseCursorDecl();
CKERROR CreateMouseCursorProto(CKBehaviorPrototype **);
int MouseCursor(const CKBehaviorContext& behcontext);
CKERROR MouseCursorCallbackDisp(const CKBehaviorContext& behcontext);
void MouseCursorRender(CKRenderContext* dev, void *arg);
CKObjectDeclaration *FillBehaviorMouseCursorDecl()
{
CKObjectDeclaration *od = CreateCKObjectDeclaration("Mouse Cursor");
od->SetDescription("Display a texture instead of the standard cursor.");
/* rem:
On: activates it.
Off: disables it.
Cursor Texture: texture to use to represent the mouse cursor.
Cursor Size: size in screen coordinates of the mouse cursor.
Cursor Color: color and transparency of the cursor.
Shadow: either to draw a shadow under the cursor.
Shadow Distance: distance of the shadow in screen coordinates.
Shadow Angle: angle of projection of the shadow.
Shadow Intensity: intensity of the shadow.
*/
od->SetType( CKDLL_BEHAVIORPROTOTYPE);
od->SetGuid(CKGUID(0x140c3eac,0x6e502a81));
od->SetAuthorGuid(VIRTOOLS_GUID);
od->SetAuthorName("Virtools");
od->SetVersion(0x00010000);
od->SetCreationFunction(CreateMouseCursorProto);
od->SetCompatibleClassId(CKCID_BEOBJECT);
od->SetCategory("Interface/Screen");
return od;
}
CKERROR CreateMouseCursorProto(CKBehaviorPrototype **pproto)
{
CKBehaviorPrototype *proto = CreateCKBehaviorPrototype("Mouse Cursor");
if(!proto) return CKERR_OUTOFMEMORY;
proto->DeclareInput("On");
proto->DeclareInput("Off");
proto->DeclareInParameter("Cursor Texture", CKPGUID_TEXTURE );
proto->DeclareInParameter("Cursor Size", CKPGUID_2DVECTOR,"32,32");
proto->DeclareInParameter("Cursor Color", CKPGUID_COLOR,"255,255,255,255");
proto->DeclareInParameter("Shadow", CKPGUID_BOOL);
proto->DeclareInParameter("Shadow Distance", CKPGUID_FLOAT,"4.0");
proto->DeclareInParameter("Shadow Angle", CKPGUID_ANGLE,"0:120");
proto->DeclareInParameter("Shadow Intensity", CKPGUID_PERCENTAGE,"30");
// TODO : center - left - right
// TODO : center - top - bottom
// TODO : offset
// TODO : setting = screen relative
proto->SetFlags(CK_BEHAVIORPROTOTYPE_NORMAL);
proto->SetFunction(MouseCursor);
proto->SetBehaviorCallbackFct( MouseCursorCallbackDisp );
*pproto = proto;
return CK_OK;
}
int
MouseCursor(const CKBehaviorContext& behcontext)
{
CKBehavior* beh = behcontext.Behavior;
if( beh->IsInputActive(1) ){ // we enter by 'OFF'
beh->ActivateInput(1, FALSE);
beh->ActivateOutput(1);
CKInputManager* im = (CKInputManager*) behcontext.Context->GetManagerByGuid(INPUT_MANAGER_GUID);
if(im){
im->ShowCursor(TRUE);
}
return CKBR_OK;
}
if( beh->IsInputActive(0) ){ // we enter by 'ON'
beh->ActivateInput(0, FALSE);
beh->ActivateOutput(0);
CKInputManager* im = (CKInputManager*) behcontext.Context->GetManagerByGuid(INPUT_MANAGER_GUID);
if(im)
im->ShowCursor(FALSE);
}
behcontext.CurrentRenderContext->AddPostSpriteRenderCallBack(MouseCursorRender,(void *)behcontext.Behavior->GetID(),TRUE);
return CKBR_ACTIVATENEXTFRAME;
}
/*******************************************************/
/******************** INIT CALLBACK ********************/
CKERROR MouseCursorCallbackDisp(const CKBehaviorContext& behcontext)
{
CKBehavior* beh = behcontext.Behavior;
switch(behcontext.CallbackMessage) {
case CKM_BEHAVIORPAUSE:
case CKM_BEHAVIORDEACTIVATESCRIPT:
{
CKInputManager* im = (CKInputManager*) behcontext.Context->GetManagerByGuid(INPUT_MANAGER_GUID);
if(im)
im->ShowCursor(TRUE);
}
break;
case CKM_BEHAVIORNEWSCENE:
case CKM_BEHAVIORRESUME:
case CKM_BEHAVIORACTIVATESCRIPT:
{
// TODO : foire dans le load !!!!!!!!!
if( beh->IsParentScriptActiveInScene(behcontext.CurrentScene)){
if(beh->IsActive()) {
CKInputManager* im = (CKInputManager*) behcontext.Context->GetManagerByGuid(INPUT_MANAGER_GUID);
if(im)
im->ShowCursor(FALSE);
}
}
}
break;
}
return CKBR_OK;
}
void
MouseCursorRender(CKRenderContext* dev, void *arg)
{
CKBehavior* beh = (CKBehavior*)CKGetObject(dev->GetCKContext(),(CK_ID)arg);
if (!beh) return;
CKContext* ctx = beh->GetCKContext();
CKTexture* cursortex = (CKTexture*)beh->GetInputParameterObject(0);
// extend the clipping
VxRect oldclip;
dev->GetViewRect(oldclip);
VxRect clip = oldclip;
dev->GetWindowRect(clip);
clip.Translate(-clip.GetTopLeft());
dev->SetViewRect(clip);
// SET STATES
// we don't let write to the ZBuffer
dev->SetTexture(cursortex);
dev->SetTextureStageState(CKRST_TSS_TEXTUREMAPBLEND, VXTEXTUREBLEND_MODULATEALPHA);
dev->SetState(VXRENDERSTATE_CULLMODE, VXCULL_NONE);
dev->SetState(VXRENDERSTATE_SRCBLEND, VXBLEND_SRCALPHA);
dev->SetState(VXRENDERSTATE_DESTBLEND, VXBLEND_INVSRCALPHA);
dev->SetState(VXRENDERSTATE_ALPHABLENDENABLE, TRUE);
dev->SetState(VXRENDERSTATE_ZENABLE , FALSE);
dev->SetState(VXRENDERSTATE_ZWRITEENABLE , FALSE);
dev->SetTextureStageState(CKRST_TSS_TEXTUREMAPBLEND,VXTEXTUREBLEND_MODULATEALPHA);
dev->SetTextureStageState(CKRST_TSS_MAGFILTER , VXTEXTUREFILTER_NEAREST);
dev->SetTextureStageState(CKRST_TSS_MINFILTER , VXTEXTUREFILTER_NEAREST);
dev->SetState(VXRENDERSTATE_WRAP0 , 0);
dev->SetTextureStageState(CKRST_TSS_STAGEBLEND,0,1);
dev->SetTextureStageState(CKRST_TSS_TEXTURETRANSFORMFLAGS, 0);
dev->SetTextureStageState(CKRST_TSS_TEXCOORDINDEX, 0);
//prevents anti-aliasing artifacts :
dev->SetTextureStageState(CKRST_TSS_ADDRESSU, VXTEXTURE_ADDRESSCLAMP);
dev->SetTextureStageState(CKRST_TSS_ADDRESSV, VXTEXTURE_ADDRESSCLAMP);
WORD indices[4]={0,1,2,3};
float vertices[16] = {0.0f,0.0f,0.5f,1.0f,640.0f,0.0f,0.5f,1.0f,0.0f,480.0f,0.5f,1.0f,640.0f,480.0f,0.5f,1.0f};
DWORD colors[4];
float uv[8]={0,0, 1,0, 1,1, 0,1};
VxDrawPrimitiveDataSimple data;
data.VertexCount = 4;
data.Flags = CKRST_DP_STAGES0;
data.Positions.Set(vertices,sizeof(VxVector4));
data.Colors.Set(colors,sizeof(DWORD));
data.TexCoord.Set(uv,sizeof(VxUV));
// we get the input parameters
Vx2DVector cursorsize;
beh->GetInputParameterValue(1,&cursorsize);
VxColor cursorcolor;
beh->GetInputParameterValue(2,&cursorcolor);
/////////////////////////////
// Mouse position
Vx2DVector mousePos;
CKInputManager *input = (CKInputManager*)ctx->GetManagerByGuid(INPUT_MANAGER_GUID);
input->GetMousePosition(mousePos,FALSE);
VxRect rect;
rect.left = mousePos.x;
rect.top = mousePos.y;
rect.right = rect.left + cursorsize.x;
rect.bottom = rect.top + cursorsize.y;
///////////////////////////////
// Shadow
CKBOOL shadow = FALSE;
beh->GetInputParameterValue(3,&shadow);
if(shadow) {
float shadowdistance = 4.0f;
beh->GetInputParameterValue(4,&shadowdistance);
float shadowangle= 1.0f;
beh->GetInputParameterValue(5,&shadowangle);
float shadowintensity = 0.8f;
beh->GetInputParameterValue(6,&shadowintensity);
float offsetx = 4.0f;
float offsety = 4.0f;
offsetx = -shadowdistance*cosf(shadowangle);
offsety = shadowdistance*sinf(shadowangle);
data.Positions[0].Set(rect.left+offsetx , rect.top+offsety , 0.5f);
data.Positions[1].Set(rect.right+offsetx , rect.top+offsety , 0.5f);
data.Positions[2].Set(rect.right+offsetx , rect.bottom+offsety , 0.5f);
data.Positions[3].Set(rect.left+offsetx , rect.bottom+offsety , 0.5f);
for(int i=0;i<4;i++) {
colors[i] = RGBAFTOCOLOR(0.0f,0.0f,0.0f,shadowintensity);
}
dev->DrawPrimitive(VX_TRIANGLEFAN,indices,4,(VxDrawPrimitiveData*)&data);
}
////////////////
// Cursor
data.Positions[0].Set(rect.left , rect.top , 0.5f);
data.Positions[1].Set(rect.right , rect.top , 0.5f);
data.Positions[2].Set(rect.right , rect.bottom , 0.5f);
data.Positions[3].Set(rect.left , rect.bottom , 0.5f);
DWORD col = RGBAFTOCOLOR(&cursorcolor);
for(int i=0;i<4;i++) {
colors[i] = col;
}
dev->DrawPrimitive(VX_TRIANGLEFAN,indices,4,(VxDrawPrimitiveData*)&data);
// restore clipping
dev->SetViewRect(oldclip);
}