//----------------------------------------------------------------------------- // Copyright (c) 2012 GarageGames, LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. //----------------------------------------------------------------------------- #include "platform/platform.h" #include "gui/controls/guiDecoyCtrl.h" #include "gui/buttons/guiButtonBaseCtrl.h" #include "console/consoleTypes.h" #include "console/engineAPI.h" #include "gfx/primBuilder.h" //----------------------------------------------------------------------------- // GuiDecoyCtrl //----------------------------------------------------------------------------- /* So far this control has been designed in mind solely for button controls. I'm pretty sure it can be used for other things, but to do anything more in depth; it has to be extended. Make sure you know a little about how guiCanvas hands out signals to gui controls before you tinker in this class. Been thinking about this class a little more. I tried pretty hard to protect this class into being guiControl like agnostic. But I ended up adding a check specifically for buttons in the onMouseUp function. Its been protected with a dynamic_cast and a NULL check; but in the end, the only way too solve the main problem, that GuiCanvas cannot process more than one mouse action for more than one gui control at a time, is for it to get a rewrite. */ IMPLEMENT_CONOBJECT(GuiDecoyCtrl); ConsoleDocClass( GuiDecoyCtrl, "@brief Designed soley for buttons, primarily used in editor.\n\n" "Currently editor use only, no real application without extension.\n\n " "@internal"); GuiDecoyCtrl::GuiDecoyCtrl() : mMouseOver(false), mIsDecoy(true), mDecoyReference(NULL), mMouseOverDecoy(false) { } GuiDecoyCtrl::~GuiDecoyCtrl() { } void GuiDecoyCtrl::initPersistFields() { addField("isDecoy", TypeBool, Offset(mIsDecoy, GuiDecoyCtrl), "Sets this control to decoy mode"); Parent::initPersistFields(); } void GuiDecoyCtrl::onMouseUp(const GuiEvent &event) { mouseUnlock(); setUpdate(); //this code is pretty hacky. right now there is no way that guiCanvas will allow sending more than //one signal to one gui control at a time. if(mIsDecoy == true) { mVisible = false; GuiControl *parent = getParent(); Point2I localPoint = parent->globalToLocalCoord(event.mousePoint); GuiControl *tempControl = parent->findHitControl(localPoint); //the decoy control has the responsibility of keeping track of the decoyed controls status if( mDecoyReference != NULL && tempControl == mDecoyReference) tempControl->onMouseUp(event); else if(mDecoyReference != NULL && tempControl != mDecoyReference) { //as explained earlier, this control was written in the mindset for buttons. //nothing bad should ever happen if not a button due to the checks in this function though. GuiButtonBaseCtrl *unCastCtrl = NULL; unCastCtrl = dynamic_cast( mDecoyReference ); if(unCastCtrl != NULL) unCastCtrl->resetState(); } mVisible = true; } } void GuiDecoyCtrl::onMouseDown(const GuiEvent &event) { if ( !mVisible || !mAwake ) return; mouseLock(); if(mIsDecoy == true) { mVisible = false; GuiControl *parent = getParent(); Point2I localPoint = parent->globalToLocalCoord(event.mousePoint); GuiControl *tempControl = parent->findHitControl(localPoint); tempControl->onMouseDown(event); mVisible = true; } execConsoleCallback(); setUpdate(); } void GuiDecoyCtrl::onMouseMove(const GuiEvent &event) { //if this control is a dead end, make sure the event stops here if ( !mVisible || !mAwake ) return; //pass the event to the parent GuiControl *parent = getParent(); if ( parent ) parent->onMouseMove( event ); Point2I localPoint = parent->globalToLocalCoord(event.mousePoint); //also pretty hacky. since guiCanvas, *NOT* GuiControl, distributes the calls for onMouseEnter //and onMouseLeave, we simulate those calls here through a series of checks. if(mIsDecoy == true) { mVisible = false; GuiControl *tempControl = parent->findHitControl(localPoint); //the decoy control has the responsibility of keeping track of the decoyed controls status if(mMouseOverDecoy == false && mDecoyReference != NULL && !mDecoyReference->isDeleted() && !mDecoyReference->isRemoved()) { tempControl->onMouseEnter(event); mMouseOverDecoy = true; } else if(tempControl != mDecoyReference && mDecoyReference != NULL && !mDecoyReference->isDeleted() && !mDecoyReference->isRemoved()) { mDecoyReference->onMouseLeave(event); mMouseOverDecoy = false; } mDecoyReference = tempControl; mVisible = true; } } void GuiDecoyCtrl::onMouseDragged(const GuiEvent &event) { } void GuiDecoyCtrl::onMouseEnter(const GuiEvent &event) { if ( !mVisible || !mAwake ) return; setUpdate(); Con::executef( this , "onMouseEnter" ); mMouseOver = true; } void GuiDecoyCtrl::onMouseLeave(const GuiEvent &event) { if ( !mVisible || !mAwake ) return; setUpdate(); Con::executef( this , "onMouseLeave" ); mMouseOver = false; } bool GuiDecoyCtrl::onMouseWheelUp( const GuiEvent &event ) { //if this control is a dead end, make sure the event stops here if ( !mVisible || !mAwake ) return true; //pass the event to the parent GuiControl *parent = getParent(); if ( parent ) return parent->onMouseWheelUp( event ); else return false; } bool GuiDecoyCtrl::onMouseWheelDown( const GuiEvent &event ) { //if this control is a dead end, make sure the event stops here if ( !mVisible || !mAwake ) return true; //pass the event to the parent GuiControl *parent = getParent(); if ( parent ) return parent->onMouseWheelDown( event ); else return false; } void GuiDecoyCtrl::onRightMouseDown(const GuiEvent &) { } void GuiDecoyCtrl::onRightMouseUp(const GuiEvent &) { } void GuiDecoyCtrl::onRightMouseDragged(const GuiEvent &) { } void GuiDecoyCtrl::onMiddleMouseDown(const GuiEvent &) { } void GuiDecoyCtrl::onMiddleMouseUp(const GuiEvent &) { } void GuiDecoyCtrl::onMiddleMouseDragged(const GuiEvent &) { }