///////////////////////////////////////////////////// ///////////////////////////////////////////////////// // // PushButton // ///////////////////////////////////////////////////// ///////////////////////////////////////////////////// #include "CKAll.h" #include "CKFontManager.h" CKObjectDeclaration *FillBehaviorPushButtonDecl(); CKERROR CreatePushButtonProto(CKBehaviorPrototype **); int PushButton(const CKBehaviorContext& behcontext); CKBOOL PushButtonRenderCallback(CKRenderContext *context,CKRenderObject* ent,void *Argument); CKERROR PushButtonCallBack(const CKBehaviorContext& behcontext); #define CKPGUID_PUSHBUTTONOPTION CKGUID(0x25064124,0x1fbe6aae) CKObjectDeclaration *FillBehaviorPushButtonDecl() { CKObjectDeclaration *od = CreateCKObjectDeclaration("PushButton"); od->SetDescription("Transforms a 2D Frame into a push button."); /* rem: On: activates the process.
Off: deactivates the process.

Released: is activated when button is released.
Pressed: is activated when button is pressed.
Roll Over: is activated when button is rolled over.

Released Material: Material to use as the button is released.
Pressed Material: Material to use as the button is pressed.
RollOver Material: Material to use when the mouss is on the button.
Font: font to use if the button must have a text on it.
Text: text to display on the button.
Pressed Offset: Offset to apply to the text when the button is pressed.
*/ od->SetType(CKDLL_BEHAVIORPROTOTYPE); od->SetGuid(CKGUID(0x761b7e64,0x2b4c6911)); od->SetAuthorGuid(VIRTOOLS_GUID); od->SetAuthorName("Virtools"); od->SetVersion(0x00030000); od->SetCreationFunction(CreatePushButtonProto); od->SetCompatibleClassId(CKCID_2DENTITY); od->SetCategory("Interface/Controls"); return od; } CKERROR CreatePushButtonProto(CKBehaviorPrototype **pproto) { CKBehaviorPrototype *proto = CreateCKBehaviorPrototype("PushButton"); if(!proto) return CKERR_OUTOFMEMORY; proto->DeclareInput("On"); proto->DeclareInput("Off"); proto->DeclareInput("Disable"); proto->DeclareOutput("Pressed"); proto->DeclareOutput("Released"); proto->DeclareOutput("Active"); proto->DeclareOutput("Enter Button"); proto->DeclareOutput("Exit Button"); proto->DeclareOutput("In Button"); proto->DeclareInParameter("Released Material", CKPGUID_MATERIAL); proto->DeclareInParameter("Pressed Material", CKPGUID_MATERIAL); proto->DeclareInParameter("RollOver Material", CKPGUID_MATERIAL); proto->DeclareInParameter("Font",CKPGUID_FONT); proto->DeclareInParameter("Text",CKPGUID_STRING); proto->DeclareInParameter("Pressed Offset",CKPGUID_2DVECTOR,"1,1"); proto->DeclareInParameter("Disabled Material", CKPGUID_MATERIAL); proto->DeclareLocalParameter(NULL,CKPGUID_INT,"0"); // State proto->DeclareSetting("Events",CKPGUID_PUSHBUTTONOPTION,"Pressed,Released,Active,Enter Button,Exit Button,In Button"); // State proto->DeclareOutParameter("Current Material", CKPGUID_MATERIAL); proto->SetFlags(CK_BEHAVIORPROTOTYPE_NORMAL); proto->SetFunction(PushButton); proto->SetBehaviorFlags((CK_BEHAVIOR_FLAGS)(CKBEHAVIOR_INTERNALLYCREATEDOUTPUTS)); proto->SetBehaviorCallbackFct(PushButtonCallBack); *pproto = proto; return CK_OK; } #define RELEASED 0 #define PRESSED 1 #define ROLLOVER 2 #define PUSHED 3 #define DISABLED 4 enum { BOM_PRESSED = 1, BOM_RELEASED = 2, BOM_ACTIVE = 4, BOM_ENTERREGION = 8, BOM_EXITREGION = 16, BOM_INREGION = 32 }; enum { BO_PRESSED, BO_RELEASED, BO_ACTIVE, BO_ENTERREGION, BO_EXITREGION, BO_INREGION }; int PushButton(const CKBehaviorContext& behcontext) { CKBehavior* beh = behcontext.Behavior; CK2dEntity* frame = (CK2dEntity*)beh->GetTarget(); int state = 0; if(beh->IsInputActive(0)) { beh->ActivateInput(0, FALSE); beh->SetLocalParameterValue(0,&state); } if(beh->IsInputActive(1)) { beh->ActivateInput(1, FALSE); return CKBR_OK; } if(beh->IsInputActive(2)) { beh->ActivateInput(2, FALSE); state = DISABLED; beh->SetLocalParameterValue(0,&state); } int oldstate = 0; beh->GetLocalParameterValue(0,&oldstate); if (!(oldstate & DISABLED)) { // If button is disabled, nothing to test int eventMask = 63; beh->GetLocalParameterValue(1,&eventMask); CKInputManager* im = (CKInputManager*)behcontext.Context->GetManagerByGuid(INPUT_MANAGER_GUID); if (!im) return CKBR_ACTIVATENEXTFRAME; // TODO : button configurable int button = 0; CKFontManager* fm = (CKFontManager*)behcontext.Context->GetManagerByGuid(FONT_MANAGER_GUID); CKBOOL inside = FALSE; if (frame == fm->GetEntityUnderMouse()) inside = TRUE; CKBOOL mousepressed = im->IsMouseButtonDown(CK_MOUSEBUTTON(button)); if (inside) state |= ROLLOVER; if (mousepressed) state |= PRESSED; if (state != oldstate) { // State change // we store the new state beh->SetLocalParameterValue(0,&state); } if (beh->GetVersion() > 0x00020000) { // new version int pos = 0; // Button state if (eventMask&BOM_PRESSED) { if (!(oldstate&PRESSED) && (state&PRESSED) && (state&ROLLOVER)) beh->ActivateOutput(pos); ++pos; } if (eventMask&BOM_RELEASED) { if ((oldstate == PUSHED) && !(state&PRESSED) && (state&ROLLOVER)) beh->ActivateOutput(pos); ++pos; } if (eventMask&BOM_ACTIVE) { if ((state&PRESSED) && (state&ROLLOVER)) beh->ActivateOutput(pos); ++pos; } // region if (eventMask&BOM_ENTERREGION) { if (!(oldstate & ROLLOVER) && (state&ROLLOVER)) beh->ActivateOutput(pos); ++pos; } if (eventMask&BOM_EXITREGION) { if ((oldstate & ROLLOVER) && !(state&ROLLOVER)) beh->ActivateOutput(pos); ++pos; } if (eventMask&BOM_INREGION) { if (state&ROLLOVER) beh->ActivateOutput(pos); ++pos; } } else { // old version if (state != oldstate) { // State change // We activate the roll over if we enter it if ((oldstate & ROLLOVER) && !(state&ROLLOVER)) beh->ActivateOutput(RELEASED); // We activate the roll over if we enter it if (!(oldstate & ROLLOVER) && (state&ROLLOVER)) beh->ActivateOutput(ROLLOVER); // We activate the pressed output when we release the button if ((oldstate == PUSHED) && (state == ROLLOVER)) beh->ActivateOutput(PRESSED); } } } // we add the render callback if (frame) frame->AddPreRenderCallBack(PushButtonRenderCallback,(void*)beh->GetID(),TRUE); return CKBR_ACTIVATENEXTFRAME; } CKBOOL PushButtonRenderCallback(CKRenderContext *dev,CKRenderObject* ent,void *iArg) { static VxRect fulluv(0,0,1.0f,1.0f); CKContext* ctx = dev->GetCKContext(); CKBehavior* beh = (CKBehavior*)ctx->GetObject((CK_ID)iArg); if (!beh) return TRUE; CKFontManager* fm = (CKFontManager*)ctx->GetManagerByGuid(FONT_MANAGER_GUID); // Old version care for space changing fm->m_VersionUpdate = (beh->GetVersion() >= 0x00020000); CK2dEntity* frame = (CK2dEntity*)ent; /// // Clipping : necessary because i m being clipped to the camera otherwise!!! VxRect oldclip; CKBOOL isnotclippedtocamera = !frame->IsClippedToCamera(); if (isnotclippedtocamera) { dev->GetViewRect(oldclip); VxRect clip = oldclip; dev->GetWindowRect(clip); clip.Translate(-clip.GetTopLeft()); dev->SetViewRect(clip); dev->SetProjectionTransformationMatrix( VxMatrix::Identity() ); } // 2D Frame Zone VxRect rect; frame->GetExtents(fulluv,rect); int state = 0; beh->GetLocalParameterValue(0,&state); if (state == PRESSED) state = RELEASED; // Pressed Outside of the button if (state == PUSHED) state = PRESSED; // Pressed inside the button if (state == DISABLED) state = 6; CKMaterial* mat = (CKMaterial*)beh->GetInputParameterObject(state); VxColor col(1.0f,1.0f,1.0f,1.0f);if (mat) col = mat->GetDiffuse(); if (mat) beh->SetOutputParameterObject(0,mat); // We draw the button background DrawFillRectangle(dev,col.GetRGBA(),mat,rect,fulluv); // We get the texture font int fontindex = 0; beh->GetInputParameterValue(3,&fontindex); CKTextureFont* font = fm->GetFont(fontindex); if(!font) return TRUE; // Init of the font : hopefully temporary VxRect margins(2,2,2,2);font->m_Margins = margins; Vx2DVector off(0.0f,0.0f);font->m_Offset = off; font->m_ParagraphIndentation = 0.0f; CKTexture* fonttexture = font->GetFontTexture(); // font->m_ScreenExtents.Set(fonttexture->GetWidth(),fonttexture->GetHeight()); // We get the string CKSTRING string = (CKSTRING)beh->GetInputParameterReadDataPtr(4); if(!string) return TRUE; if (state == PRESSED) { Vx2DVector offset;beh->GetInputParameterValue(5,&offset); rect.Translate(offset); } // we draw the button text font->DrawCKText(dev,frame,string,0,rect,NULL,4, TRUE); // Clipping if (isnotclippedtocamera) { dev->SetViewRect(oldclip); dev->SetProjectionTransformationMatrix( VxMatrix::Identity() ); } return TRUE; } /*******************************************************/ /* CALLBACK */ /*******************************************************/ CKERROR PushButtonCallBack(const CKBehaviorContext& behcontext) { CKBehavior* beh = behcontext.Behavior; if (beh->GetVersion() < 0x00030000) return CK_OK; switch( behcontext.CallbackMessage ) { case CKM_BEHAVIORSETTINGSEDITED: { int eventMask = 63; beh->GetLocalParameterValue(1,&eventMask); int pos = 0; CKBehaviorIO* out = NULL; // Outputs Creation/Deletion if(eventMask&BOM_PRESSED) { if(out = beh->GetOutput(pos)) { out->SetName("Pressed"); } else beh->AddOutput("Pressed"); ++pos; } if(eventMask&BOM_RELEASED) { if(out = beh->GetOutput(pos)) { out->SetName("Released"); } else beh->AddOutput("Released"); ++pos; } if(eventMask&BOM_ACTIVE) { if(out = beh->GetOutput(pos)) { out->SetName("Active"); } else beh->AddOutput("Active"); ++pos; } if(eventMask&BOM_ENTERREGION) { if(out = beh->GetOutput(pos)) { out->SetName("Enter Button"); } else beh->AddOutput("Enter Button"); ++pos; } if(eventMask&BOM_EXITREGION) { if(out = beh->GetOutput(pos)) { out->SetName("Exit Button"); } else beh->AddOutput("Exit Button"); ++pos; } if(eventMask&BOM_INREGION) { if(out = beh->GetOutput(pos)) { out->SetName("In Button"); } else beh->AddOutput("In Button"); ++pos; } // we delete the unusefull outputs while(posGetOutputCount()) beh->DeleteOutput(pos); } break; } return CKBR_OK; }