/////////////////////////////////////////////////////
/////////////////////////////////////////////////////
//
// Slider
//
/////////////////////////////////////////////////////
/////////////////////////////////////////////////////
#include "CKAll.h"
#include "CKFontManager.h"
CKObjectDeclaration *FillBehaviorSliderDecl();
CKERROR CreateSliderProto(CKBehaviorPrototype **);
int Slider(const CKBehaviorContext& behcontext);
CKERROR SliderCallback(const CKBehaviorContext& behcontext);
CKBOOL SliderRenderCallback(CKRenderContext *context,CKRenderObject* ent,void *Argument);
CKObjectDeclaration *FillBehaviorSliderDecl()
{
CKObjectDeclaration *od = CreateCKObjectDeclaration("Slider");
od->SetDescription("");
/* rem:
In: triggers the process.
Out: is activated when the process is completed.
Material: .
*/
od->SetType(CKDLL_BEHAVIORPROTOTYPE);
od->SetGuid(CKGUID(0x571379bf,0xe8233bd));
od->SetAuthorGuid(VIRTOOLS_GUID);
od->SetAuthorName("Virtools");
od->SetVersion(0x00010000);
od->SetCreationFunction(CreateSliderProto);
od->SetCompatibleClassId(CKCID_2DENTITY);
od->SetCategory("Interface/Controls");
return od;
}
CKERROR CreateSliderProto(CKBehaviorPrototype **pproto)
{
CKBehaviorPrototype *proto = CreateCKBehaviorPrototype("Slider");
if(!proto) return CKERR_OUTOFMEMORY;
proto->DeclareInput("On");
proto->DeclareInput("Off");
proto->DeclareOutput("Exit On");
proto->DeclareOutput("Exit Off");
proto->DeclareOutput("Value Changed");
proto->DeclareInParameter("Steps", CKPGUID_INT,"10");
proto->DeclareInParameter("Initial Value", CKPGUID_INT,"0");
proto->DeclareInParameter("Slider", CKPGUID_2DENTITY);
proto->DeclareInParameter("Relative", CKPGUID_BOOL,"FALSE");
proto->DeclareInParameter("Plus Arrow", CKPGUID_2DENTITY);
proto->DeclareInParameter("Minus Arrow", CKPGUID_2DENTITY);
proto->DeclareInParameter("Slider Background", CKPGUID_MATERIAL);
proto->DeclareLocalParameter(NULL,CKPGUID_INT,"0"); // State
proto->DeclareSetting("Vertical",CKPGUID_BOOL,"FALSE");
proto->DeclareOutParameter("Value",CKPGUID_INT,"0");
proto->DeclareOutParameter("Percentage",CKPGUID_PERCENTAGE,"0");
proto->SetFlags(CK_BEHAVIORPROTOTYPE_NORMAL);
proto->SetFunction(Slider);
*pproto = proto;
return CK_OK;
}
#define RELEASED 0
#define PRESSED 1
#define ROLLOVER 2
void MoveSlider(int value,int steps,CK2dEntity* slider, VxRect& framerect,CKBOOL scale,CKBOOL vert)
{
VxRect sliderrect;
slider->GetRect(sliderrect);
if (vert) { // Vertical slider
// Horizontal placement (center for now)
sliderrect.VMove(framerect.left+framerect.GetWidth()*0.5f-sliderrect.GetWidth()*0.5f);
float f = (float)value/steps;
if (f > 1.0f) f = 1.0f;
else if (f < 0.0f) f = 0.0f;
if (scale) {
sliderrect.top = framerect.top;
sliderrect.bottom = framerect.top+f*framerect.GetHeight();
} else {
sliderrect.VMove(framerect.top+f*(framerect.GetHeight() - sliderrect.GetHeight()));
}
} else { // Horizontal slider
// Vertical placement (center for now)
sliderrect.VMove(framerect.top+framerect.GetHeight()*0.5f-sliderrect.GetHeight()*0.5f);
float f = (float)value/steps;
if (f > 1.0f) f = 1.0f;
else if (f < 0.0f) f = 0.0f;
if (scale) {
sliderrect.left = framerect.left;
sliderrect.right = framerect.left+f*framerect.GetWidth();
} else {
sliderrect.HMove(framerect.left+f*(framerect.GetWidth() - sliderrect.GetWidth()));
}
}
slider->SetRect(sliderrect);
}
int Slider(const CKBehaviorContext& behcontext)
{
CKBehavior* beh = behcontext.Behavior;
if(beh->IsInputActive(1)) {
beh->ActivateInput(1, FALSE);
return CKBR_OK;
}
CK2dEntity* frame = (CK2dEntity*)beh->GetTarget();
if (!frame) return CKBR_ACTIVATENEXTFRAME;
VxRect framerect;
frame->GetRect(framerect);
CK2dEntity* slider = (CK2dEntity*)beh->GetInputParameterObject(2);
if (!slider) return CKBR_ACTIVATENEXTFRAME;
int* oldvalue = (int*)beh->GetOutputParameterWriteDataPtr(0);
int steps = 10;
beh->GetInputParameterValue(0,&steps);
CKBOOL scale = FALSE;
beh->GetInputParameterValue(3,&scale);
CKBOOL vert = FALSE;
beh->GetLocalParameterValue(1,&vert);
if(beh->IsInputActive(0)) {
beh->ActivateInput(0, FALSE);
int state = 0;
beh->SetLocalParameterValue(0,&state);
int initialvalue = 0;
beh->GetInputParameterValue(1,&initialvalue);
MoveSlider(initialvalue,steps,slider,framerect,scale,vert);
}
CKInputManager* im = (CKInputManager*)behcontext.Context->GetManagerByGuid(INPUT_MANAGER_GUID);
if (!im) return CKBR_ACTIVATENEXTFRAME;
// TODO : button configurable
int button = 0;
VxRect rect;
slider->GetRect(rect);
Vx2DVector mp;
im->GetMousePosition(mp,FALSE);
CKBOOL inside = FALSE;
if (rect.IsInside(mp)) inside = TRUE;
int state = 0;
beh->GetLocalParameterValue(0,&state);
int oldstate = state;
if (state & PRESSED) {
// we calculate the new value, according to the mouse position
int value = (int)((steps+1)*(mp.x - framerect.left)/framerect.GetWidth());
if (value != *oldvalue) {
*oldvalue = value;
MoveSlider(value,steps,slider,framerect,scale,vert);
}
}
if (im->IsMouseClicked(CK_MOUSEBUTTON(button)) && inside) {
state = PRESSED;
} else {
if (im->IsMouseButtonDown(CK_MOUSEBUTTON(button))) {
if (framerect.IsInside(mp)) { // we clicked on the slider background : direct jump
// we calculate the new value, according to the mouse position
int value = (int)((steps+1)*(mp.x - framerect.left)/framerect.GetWidth());
if (value != *oldvalue) {
*oldvalue = value;
MoveSlider(value,steps,slider,framerect,scale,vert);
}
}
} else {
if (state & PRESSED) {
state = RELEASED;
} else if (inside) state = ROLLOVER;
else state = RELEASED;
}
}
if (state != oldstate) { // State change
// we activate the corresponding output
beh->ActivateOutput(state);
// we store the new state
beh->SetLocalParameterValue(0,&state);
}
// add pre render callback
frame->AddPreRenderCallBack(SliderRenderCallback,(void*)beh->GetID(),TRUE);
return CKBR_ACTIVATENEXTFRAME;
}
CKBOOL
SliderRenderCallback(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);
CK2dEntity* frame = (CK2dEntity*)beh->GetTarget();
if (!frame) return TRUE;
// 2D Frame Zone
VxRect rect;
frame->GetRect(rect);
int state = 0;
beh->GetLocalParameterValue(0,&state);
CKMaterial* mat = (CKMaterial*)beh->GetInputParameterObject(6);
VxColor col(1.0f,1.0f,1.0f,1.0f);if (mat) col = mat->GetDiffuse();
// We draw the button background
DrawFillRectangle(dev,col.GetRGBA(),mat,rect,fulluv);
return TRUE;
}