📄 guicanvas.cc
字号:
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#include "console/console.h"
#include "platform/profiler.h"
#include "dgl/dgl.h"
#include "platform/event.h"
#include "platform/platform.h"
#include "platform/platformVideo.h"
#include "gui/core/guiTypes.h"
#include "gui/core/guiControl.h"
#include "gui/core/guiCanvas.h"
#include "dgl/gDynamicTexture.h"
#include "gui/controls/guiCellButtonCtrl.h"
extern bool gDGLRender;
#ifdef TGE_RPG
#define MOUSE_DRAG_DIFF 5*5
#endif
// We formerly kept all the GUI related IMPLEMENT_CONOBJECT macros here.
// Now they belong with their implementations. -- BJG
IMPLEMENT_CONOBJECT(GuiCanvas);
GuiCanvas *Canvas = NULL;
ConsoleMethod( GuiCanvas, getContent, S32, 2, 2, "Get the GuiControl which is being used as the content.")
{
GuiControl *ctrl = object->getContentControl();
if(ctrl)
return ctrl->getId();
return -1;
}
#ifdef TGE_RPG
ConsoleMethod( GuiCanvas, pushPanel, bool, 3, 3, "pushPanel(ctrl) 把控件当作面板追加到当前content子集中")
{
object;
argc;
GuiControl *ctrl = object->getContentControl();
if(ctrl)
{
GuiControl *gui = NULL;
if(argv[2][0])
{
if (Sim::findObject(argv[2], gui))
{
ctrl->addObject(gui);
return true;
}
}
}
return false;
}
ConsoleMethod( GuiCanvas, popPanel, bool, 3, 3, "pushPanel(ctrl) 把控件当作面板从当前content子集中去掉")
{
object;
argc;
GuiControl *ctrl = object->getContentControl();
if(ctrl)
{
GuiControl *gui = NULL;
if(argv[2][0])
{
if (Sim::findObject(argv[2], gui))
{
ctrl->removeObject(gui);
return true;
}
}
}
return false;
}
#endif
ConsoleMethod( GuiCanvas, setContent, void, 3, 3, "(GuiControl ctrl)"
"Set the content of the canvas.")
{
object;
argc;
GuiControl *gui = NULL;
if(argv[2][0])
{
if (!Sim::findObject(argv[2], gui))
{
Con::printf("%s(): Invalid control: %s", argv[0], argv[2]);
return;
}
}
//set the new content control
Canvas->setContentControl(gui);
}
ConsoleMethod( GuiCanvas, pushDialog, void, 3, 4, "(GuiControl ctrl, int layer)")
{
object;
GuiControl *gui;
if (! Sim::findObject(argv[2], gui))
{
Con::printf("%s(): Invalid control: %s", argv[0], argv[2]);
return;
}
//find the layer
S32 layer = 0;
if (argc == 4)
layer = dAtoi(argv[3]);
//set the new content control
Canvas->pushDialogControl(gui, layer);
}
ConsoleMethod( GuiCanvas, popDialog, void, 2, 3, "(GuiControl ctrl=NULL)")
{
object;
GuiControl *gui;
if (argc == 3)
{
if (!Sim::findObject(argv[2], gui))
{
Con::printf("%s(): Invalid control: %s", argv[0], argv[2]);
return;
}
}
if (gui)
Canvas->popDialogControl(gui);
else
Canvas->popDialogControl();
}
ConsoleMethod( GuiCanvas, popLayer, void, 2, 3, "(int layer)")
{
object;
S32 layer = 0;
if (argc == 3)
layer = dAtoi(argv[2]);
Canvas->popDialogControl(layer);
}
ConsoleMethod(GuiCanvas, cursorOn, void, 2, 2, "")
{
object;
argc;
argv;
Canvas->setCursorON(true);
}
ConsoleMethod(GuiCanvas, cursorOff, void, 2, 2, "")
{
object;
argc;
argv;
Canvas->setCursorON(false);
}
ConsoleMethod( GuiCanvas, setCursor, void, 3, 3, "(bool visible)")
{
object;
argc;
GuiCursor *curs = NULL;
if(argv[2][0])
{
if(!Sim::findObject(argv[2], curs))
{
Con::printf("%s is not a valid cursor.", argv[2]);
return;
}
}
Canvas->setCursor(curs);
}
ConsoleMethod( GuiCanvas, renderFront, void, 3, 3, "(bool enable)")
{
Canvas->setRenderFront(dAtob(argv[2]));
}
ConsoleMethod( GuiCanvas, showCursor, void, 2, 2, "")
{
Canvas->showCursor(true);
}
ConsoleMethod( GuiCanvas, hideCursor, void, 2, 2, "")
{
Canvas->showCursor(false);
}
ConsoleMethod( GuiCanvas, isCursorOn, bool, 2, 2, "")
{
return Canvas->isCursorON();
}
ConsoleMethod( GuiCanvas, repaint, void, 2, 2, "Force canvas to redraw.")
{
Canvas->paint();
}
ConsoleMethod( GuiCanvas, reset, void, 2, 2, "Reset the update regions for the canvas.")
{
Canvas->resetUpdateRegions();
}
ConsoleMethod( GuiCanvas, getCursorPos, const char*, 2, 2, "Get the current position of the cursor.")
{
Point2I pos = Canvas->getCursorPos();
char * ret = Con::getReturnBuffer(32);
dSprintf(ret, 32, "%d %d", pos.x, pos.y);
return(ret);
}
ConsoleMethod( GuiCanvas, setCursorPos, void, 3, 4, "(Point2I pos)")
{
Point2I pos(0,0);
if(argc == 4)
pos.set(dAtoi(argv[2]), dAtoi(argv[3]));
else
dSscanf(argv[2], "%d %d", &pos.x, &pos.y);
Canvas->setCursorPos(pos);
}
ConsoleFunction( createCanvas, bool, 2, 2, "(string windowTitle)"
"Create the game window/canvas, with the specified window title.")
{
AssertISV(!Canvas, "CreateCanvas: canvas has already been instantiated");
#if !defined(TORQUE_OS_MAC) // macs can only run one instance in general.
#if !defined(TORQUE_DEBUG) && !defined(INTERNAL_RELEASE)
if(!Platform::excludeOtherInstances("TorqueTest"))
return false;
#endif
#endif
Platform::initWindow(Point2I(800, 600), argv[1]);
// create the canvas, and add it to the manager
Canvas = new GuiCanvas();
Canvas->registerObject("Canvas"); // automatically adds to GuiGroup
#ifdef TGE_RPG
Canvas->initAccelMap();
#endif
return true;
}
GuiCanvas::GuiCanvas()
{
#ifdef TGE_RPG
mBounds.set(0, 0, 800, 600);
#else
mBounds.set(0, 0, 640, 480);
#endif
mAwake = true;
mPixelsPerMickey = 1.0f;
lastCursorON = false;
cursorON = true;
mShowCursor = true;
rLastFrameTime = 0.0f;
mMouseCapturedControl = NULL;
mMouseControl = NULL;
mMouseControlClicked = false;
mMouseButtonDown = false;
mMouseRightButtonDown = false;
mMouseMiddleButtonDown = false;
#ifdef TGE_RPG
mMouseButtonDrag = false;
mPointDragStart.set(0,0);
#endif
lastCursor = NULL;
lastCursorPt.set(0,0);
cursorPt.set(0,0);
mLastMouseClickCount = 0;
mLastMouseDownTime = 0;
mPrevMouseTime = 0;
defaultCursor = NULL;
mRenderFront = false;
hoverControlStart = Platform::getRealMilliseconds();
hoverControl = NULL;
hoverPosition = getCursorPos();
hoverPositionSet = false;
hoverLeftControlTime = 0;
m_pIMEControl = NULL;
m_pTopControl = NULL;
#ifdef TGE_RPG
m_dblClkCursorPt.set(0.,0.);
m_pDragCaret = NULL;
m_pAccelMap = NULL;
SimObject::setModStaticFields(true);
SimObject::setModDynamicFields(true);
#endif
}
GuiCanvas::~GuiCanvas()
{
if(Canvas == this)
Canvas = 0;
}
//------------------------------------------------------------------------------
void GuiCanvas::setCursor(GuiCursor *curs)
{
defaultCursor = curs;
}
void GuiCanvas::setCursorON(bool onOff)
{
cursorON = onOff;
if(!cursorON)
mMouseControl = NULL;
}
#ifdef TGE_RPG
GuiCursor *GuiCanvas::createDragCursor(GuiCellButtonCtrl *pDragCell)
{
static GuiCursor sDragCursor;
sDragCursor.setDragCell(pDragCell);
m_pDragCaret = &sDragCursor;
return m_pDragCaret;
}
void GuiCanvas::clearDragCursor()
{
if(m_pDragCaret)
m_pDragCaret->setDragCell(0);
m_pDragCaret = NULL;
}
#endif
void GuiCanvas::addAcceleratorKey(GuiControl *ctrl, U32 index, U32 keyCode, U32 modifier)
{
if (keyCode > 0 && ctrl)
{
AccKeyMap newMap;
newMap.ctrl = ctrl;
newMap.index = index;
newMap.keyCode = keyCode;
newMap.modifier = modifier;
#ifdef TGE_RPG
AssertFatal(m_pAccelMap,"需要先创建AccelMap实例");
if(m_pAccelMap)
m_pAccelMap->push_back(newMap);
#else
mAcceleratorMap.push_back(newMap);
#endif
}
}
void GuiCanvas::tabNext(void)
{
GuiControl *ctrl = m_pTopControl;//static_cast<GuiControl *>(last()); //IME
if (ctrl)
{
//save the old
GuiControl *oldResponder = mFirstResponder;
GuiControl* newResponder = ctrl->findNextTabable(mFirstResponder);
if ( !newResponder )
newResponder = ctrl->findFirstTabable();
if ( newResponder && newResponder != oldResponder )
{
newResponder->setFirstResponder();
if ( oldResponder )
oldResponder->onLoseFirstResponder();
}
}
}
void GuiCanvas::tabPrev(void)
{
GuiControl *ctrl = m_pTopControl ;//static_cast<GuiControl *>(last()); //IME
if (ctrl)
{
//save the old
GuiControl *oldResponder = mFirstResponder;
GuiControl* newResponder = ctrl->findPrevTabable(mFirstResponder);
if ( !newResponder )
newResponder = ctrl->findLastTabable();
if ( newResponder && newResponder != oldResponder )
{
newResponder->setFirstResponder();
if ( oldResponder )
oldResponder->onLoseFirstResponder();
}
}
}
void GuiCanvas::processMouseMoveEvent(const MouseMoveEvent *event)
{
if( cursorON )
{
//copy the modifier into the new event
mLastEvent.modifier = event->modifier;
Point2F pt(cursorPt.x, cursorPt.y);
pt.x += ( F32(event->xPos - cursorPt.x) * mPixelsPerMickey);
cursorPt.x = getMax(0, getMin((S32)pt.x, mBounds.extent.x - 1));
pt.y += ( F32(event->yPos - cursorPt.y) * mPixelsPerMickey);
cursorPt.y = getMax(0, getMin((S32)pt.y, mBounds.extent.y - 1));
mLastEvent.mousePoint.x = S32(cursorPt.x);
mLastEvent.mousePoint.y = S32(cursorPt.y);
#ifdef TGE_RPG
if (mMouseButtonDrag)
{
if (mMouseButtonDown)
rootMouseDragged(mLastEvent);
else if (mMouseRightButtonDown)
rootRightMouseDragged(mLastEvent);
else if(mMouseMiddleButtonDown)
rootMiddleMouseDragged(mLastEvent);
else
rootMouseMove(mLastEvent);
}
else
{
rootMouseMove(mLastEvent);
}
#else
if (mMouseButtonDown)
rootMouseDragged(mLastEvent);
else if (mMouseRightButtonDown)
rootRightMouseDragged(mLastEvent);
else if(mMouseMiddleButtonDown)
rootMiddleMouseDragged(mLastEvent);
else
rootMouseMove(mLastEvent);
#endif
}
}
bool GuiCanvas::processInputEvent(const InputEvent *event)
{
#ifdef TGE_RPG
AssertFatal(m_pAccelMap,"需要先创建AccelMap实例");
#endif
// First call the general input handler (on the extremely off-chance that it will be handled):
if ( mFirstResponder )
{
if ( mFirstResponder->onInputEvent( *event ) )
return( true );
}
if(event->deviceType == KeyboardDeviceType)
{
mLastEvent.ascii = event->ascii;
mLastEvent.modifier = event->modifier;
mLastEvent.keyCode = event->objInst;
U32 eventModifier = event->modifier;
if(eventModifier & SI_SHIFT)
eventModifier |= SI_SHIFT;
if(eventModifier & SI_CTRL)
eventModifier |= SI_CTRL;
if(eventModifier & SI_ALT)
eventModifier |= SI_ALT;
if (event->action == SI_MAKE)
{
//see if we should tab next/prev
//see if we should now pass the event to the first responder
if (mFirstResponder)
{
if(mFirstResponder->onKeyDown(mLastEvent))
return true;
}
if ( isCursorON() && ( event->objInst == KEY_TAB ) )
{
if (size() > 0)
{
if (event->modifier & SI_SHIFT)
{
tabPrev();
return true;
}
else if (event->modifier == 0)
{
tabNext();
return true;
}
}
}
//if not handled, search for an accelerator
#ifdef TGE_RPG
if(processAccelKey(event,eventModifier,AKT_PRESS))
return true;
#else
for (U32 i = 0; i < mAcceleratorMap.size(); i++)
{
if ((U32)mAcceleratorMap[i].keyCode == (U32)event->objInst && (U32)mAcceleratorMap[i].modifier == eventModifier)
{
mAcceleratorMap[i].ctrl->acceleratorKeyPress(mAcceleratorMap[i].index);
return true;
}
}
#endif
}
else if(event->action == SI_BREAK)
{
if(mFirstResponder)
if(mFirstResponder->onKeyUp(mLastEvent))
return true;
//see if there's an accelerator
#ifdef TGE_RPG
if(processAccelKey(event,eventModifier,AKT_RELEASE))
return true;
#else
for (U32 i = 0; i < mAcceleratorMap.size(); i++)
{
if ((U32)mAcceleratorMap[i].keyCode == (U32)event->objInst && (U32)mAcceleratorMap[i].modifier == eventModifier)
{
mAcceleratorMap[i].ctrl->acceleratorKeyRelease(mAcceleratorMap[i].index);
return true;
}
}
#endif
}
else if(event->action == SI_REPEAT)
{
//if not handled, search for an accelerator
#ifdef TGE_RPG
if(processAccelKey(event,eventModifier,AKT_PRESS))
return true;
#else
for (U32 i = 0; i < mAcceleratorMap.size(); i++)
{
if ((U32)mAcceleratorMap[i].keyCode == (U32)event->objInst && (U32)mAcceleratorMap[i].modifier == eventModifier)
{
mAcceleratorMap[i].ctrl->acceleratorKeyPress(mAcceleratorMap[i].index);
return true;
}
}
#endif
if(mFirstResponder)
mFirstResponder->onKeyRepeat(mLastEvent);
return true;
}
}
else if(event->deviceType == MouseDeviceType && cursorON)
{
//copy the modifier into the new event
mLastEvent.modifier = event->modifier;
if(event->objType == SI_XAXIS || event->objType == SI_YAXIS)
{
bool moved = false;
Point2I oldpt((S32)cursorPt.x, (S32)cursorPt.y);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -