📄 guicanvas.cc
字号:
GuiControl *ctrl = static_cast<GuiControl *>(*i);
ctrl->buildAcceleratorMap();
if (ctrl->mProfile->mModal)
break;
}
#endif
refreshMouseControl();
}
GuiControl *GuiCanvas::getContentControl()
{
if(size() > 0)
return (GuiControl *) first();
return NULL;
}
void GuiCanvas::pushDialogControl(GuiControl *gui, S32 layer)
{
//add the gui
gui->mLayer = layer;
//IME
//保证输入法在reorder时永远在最顶上
if(m_pIMEControl && m_pIMEControl->mLayer <= layer)
{
m_pIMEControl->mLayer = layer + 1;
}
// GuiControl::addObject wakes the object
bool wakedGui = !gui->isAwake();
addObject(gui);
//reorder it to the correct layer
iterator i;
for (i = begin(); i != end(); i++)
{
GuiControl *ctrl = static_cast<GuiControl*>(*i);
if (ctrl->mLayer > gui->mLayer)
{
reOrder(gui, ctrl);
break;
}
}
//IME
//需要在重排后调用
UpdateTopControl();
//call the dialog push method
gui->onDialogPush();
//find the top most dialog
GuiControl *topCtrl = m_pTopControl ;//static_cast<GuiControl *>(last()); //IME
//save the old
GuiControl *oldResponder = mFirstResponder;
//find the first responder
mFirstResponder = gui->findFirstTabable();
if (oldResponder && oldResponder != mFirstResponder)
oldResponder->onLoseFirstResponder();
// call the 'onWake' method?
//if(wakedGui)
// Con::executef(gui, 1, "onWake");
//refresh the entire gui
resetUpdateRegions();
//rebuild the accelerator map
#ifdef TGE_RPG
addAccelMaps(gui);
#else
mAcceleratorMap.clear();
if (size() > 0)
{
GuiControl *ctrl = m_pTopControl ;//static_cast<GuiControl *>(last()); //IME
ctrl->buildAcceleratorMap();
}
#endif
refreshMouseControl();
}
void GuiCanvas::popDialogControl(GuiControl *gui)
{
if (size() < 1)
return;
//first, find the dialog, and call the "onDialogPop()" method
GuiControl *ctrl = NULL;
if (gui)
{
//make sure the gui really exists on the stack
iterator i;
bool found = false;
for(i = begin(); i != end(); i++)
{
GuiControl *check = static_cast<GuiControl *>(*i);
if (check == gui)
{
ctrl = check;
found = true;
}
}
if (! found)
return;
}
else
ctrl = m_pTopControl ;//static_cast<GuiControl *>(last()); //IME
//call the "on pop" function
ctrl->onDialogPop();
// sleep the object
bool didSleep = ctrl->isAwake();
//now pop the last child (will sleep if awake)
removeObject(ctrl);
UpdateTopControl();//IME
// Save the old responder:
GuiControl *oldResponder = mFirstResponder;
Sim::getGuiGroup()->addObject(ctrl);
if (size() > 0)
{
GuiControl *ctrl = m_pTopControl ;//static_cast<GuiControl *>(last()); //IME
mFirstResponder = ctrl->mFirstResponder;
}
else
{
mFirstResponder = NULL;
}
if (oldResponder && oldResponder != mFirstResponder)
oldResponder->onLoseFirstResponder();
//refresh the entire gui
resetUpdateRegions();
#ifdef TGE_RPG
removeAccelMap(gui);
#else
//rebuild the accelerator map
mAcceleratorMap.clear();
if (size() > 0)
{
GuiControl *ctrl = m_pTopControl ;//static_cast<GuiControl *>(last()); //IME
ctrl->buildAcceleratorMap();
}
#endif
refreshMouseControl();
}
void GuiCanvas::popDialogControl(S32 layer)
{
if (size() < 1)
return;
GuiControl *ctrl = NULL;
iterator i = end(); // find in z order (last to first)
while (i != begin())
{
i--;
ctrl = static_cast<GuiControl*>(*i);
if (ctrl->mLayer == layer)
break;
}
if (ctrl)
popDialogControl(ctrl);
}
void GuiCanvas::mouseLock(GuiControl *lockingControl)
{
if (bool(mMouseCapturedControl))
return;
mMouseCapturedControl = lockingControl;
if(mMouseControl && mMouseControl != mMouseCapturedControl)
{
GuiEvent evt;
evt.mousePoint.x = S32(cursorPt.x);
evt.mousePoint.y = S32(cursorPt.y);
mMouseControl->onMouseLeave(evt);
}
}
void GuiCanvas::mouseUnlock(GuiControl *lockingControl)
{
if (static_cast<GuiControl*>(mMouseCapturedControl) != lockingControl)
return;
GuiEvent evt;
evt.mousePoint.x = S32(cursorPt.x);
evt.mousePoint.y = S32(cursorPt.y);
GuiControl * controlHit = findHitControl(evt.mousePoint);
if(controlHit != mMouseCapturedControl)
{
mMouseControl = controlHit;
mMouseControlClicked = false;
if(bool(mMouseControl))
mMouseControl->onMouseEnter(evt);
}
mMouseCapturedControl = NULL;
}
void GuiCanvas::paint()
{
resetUpdateRegions();
// inhibit explicit refreshes in the case we're swapped out
if (gDGLRender)
renderFrame(false);
}
void GuiCanvas::renderFrame(bool preRenderOnly, bool bufferSwap /* = true */)
{
PROFILE_START(CanvasPreRender);
if(mRenderFront)
glDrawBuffer(GL_FRONT);
else
glDrawBuffer(GL_BACK);
// Render all RTT Gui's HERE
//DynamicTexture::updateGuiTextures();
Point2I size = Platform::getWindowSize();
if(size.x == 0 || size.y == 0)
return;
RectI screenRect(0, 0, size.x, size.y);
mBounds = screenRect;
//all bottom level controls should be the same dimensions as the canvas
//this is necessary for passing mouse events accurately
iterator i;
for (i = begin(); i != end(); i++)
{
AssertFatal(static_cast<GuiControl*>((*i))->isAwake(), "GuiCanvas::renderFrame: ctrl is not awake");
GuiControl *ctrl = static_cast<GuiControl*>(*i);
Point2I ext = ctrl->getExtent();
Point2I pos = ctrl->getPosition();
#ifdef TGE_RPG
/*ctrl->m_bAutoSize*/
if(ctrl->mProfile->mModal &&( pos != screenRect.point || ext != screenRect.extent))
{
ctrl->resize(screenRect.point, screenRect.extent);
resetUpdateRegions();
}
#else
if(pos != screenRect.point || ext != screenRect.extent)
{
ctrl->resize(screenRect.point, screenRect.extent);
resetUpdateRegions();
}
#endif
}
//preRender (recursive) all controls
preRender();
PROFILE_END();
if(preRenderOnly)
return;
// for now, just always reset the update regions - this is a
// fix for FSAA on ATI cards
resetUpdateRegions();
// finish the gl render so we don't get too far ahead of ourselves
#if defined(TORQUE_OS_WIN32)
PROFILE_START(glFinish);
glFinish();
PROFILE_END();
#endif
//draw the mouse, but not using tags...
PROFILE_START(CanvasRenderControls);
GuiCursor *mouseCursor = NULL;
bool cursorVisible = true;
#ifdef TGE_RPG
if(m_pDragCaret)
mouseCursor = m_pDragCaret;
else
#endif
if(bool(mMouseCapturedControl))
mMouseCapturedControl->getCursor(mouseCursor, cursorVisible, mLastEvent);
else if(bool(mMouseControl))
mMouseControl->getCursor(mouseCursor, cursorVisible, mLastEvent);
Point2I cursorPos((S32)cursorPt.x, (S32)cursorPt.y);
if(!mouseCursor)
mouseCursor = defaultCursor;
if(lastCursorON && lastCursor)
{
Point2I spot = lastCursor->getHotSpot();
Point2I cext = lastCursor->getExtent();
Point2I pos = lastCursorPt - spot;
addUpdateRegion(pos - Point2I(2, 2), Point2I(cext.x + 4, cext.y + 4));
}
if(cursorVisible && mouseCursor)
{
Point2I spot = mouseCursor->getHotSpot();
Point2I cext = mouseCursor->getExtent();
Point2I pos = cursorPos - spot;
addUpdateRegion(pos - Point2I(2, 2), Point2I(cext.x + 4, cext.y + 4));
}
lastCursorON = cursorVisible;
lastCursor = mouseCursor;
lastCursorPt = cursorPos;
RectI updateUnion;
buildUpdateUnion(&updateUnion);
if (updateUnion.intersect(screenRect))
{
//fill in with black first
//glClearColor(0, 0, 0, 0);
//glClear(GL_COLOR_BUFFER_BIT);
//render the dialogs
iterator i;
for(i = begin(); i != end(); i++)
{
GuiControl *contentCtrl = static_cast<GuiControl*>(*i);
dglSetClipRect(updateUnion);
glDisable( GL_CULL_FACE );
contentCtrl->onRender(contentCtrl->getPosition(), updateUnion);
}
// Tooltip resource
if(bool(mMouseControl))
{
U32 curTime = Platform::getRealMilliseconds();
if(hoverControl == mMouseControl)
{
if(hoverPositionSet || (curTime - hoverControlStart) >= 1000 || (curTime - hoverLeftControlTime) <= 1000)
{
if(!hoverPositionSet)
{
hoverPosition = cursorPos;
}
hoverPositionSet = mMouseControl->renderTooltip(hoverPosition);
}
} else
{
if(hoverPositionSet)
{
hoverLeftControlTime = curTime;
hoverPositionSet = false;
}
hoverControl = mMouseControl;
hoverControlStart = curTime;
}
}
//end tooltip
dglSetClipRect(updateUnion);
//temp draw the mouse
if (cursorON && mShowCursor && !mouseCursor)
{
glColor4ub(255, 0, 0, 255);
glRecti((S32)cursorPt.x, (S32)cursorPt.y, (S32)(cursorPt.x + 2), (S32)(cursorPt.y + 2));
}
//DEBUG
//draw the help ctrl
//if (helpCtrl)
//{
// helpCtrl->render(srf);
//}
if (cursorON && mouseCursor && mShowCursor)
{
Point2I pos((S32)cursorPt.x, (S32)cursorPt.y);
Point2I spot = mouseCursor->getHotSpot();
pos -= spot;
mouseCursor->render(pos);
}
}
PROFILE_END();
// Render all RTT end of frame updates HERE
//DynamicTexture::updateScreenTextures();
//DynamicTexture::updateEndOfFrameTextures();
if( bufferSwap )
swapBuffers();
}
void GuiCanvas::swapBuffers()
{
PROFILE_START(SwapBuffers);
//flip the surface
if(!mRenderFront)
Video::swapBuffers();
PROFILE_END();
}
void GuiCanvas::buildUpdateUnion(RectI *updateUnion)
{
*updateUnion = mOldUpdateRects[0];
//the update region should encompass the oldUpdateRects, and the curUpdateRect
Point2I upperL;
Point2I lowerR;
upperL.x = getMin(mOldUpdateRects[0].point.x, mOldUpdateRects[1].point.x);
upperL.x = getMin(upperL.x, mCurUpdateRect.point.x);
upperL.y = getMin(mOldUpdateRects[0].point.y, mOldUpdateRects[1].point.y);
upperL.y = getMin(upperL.y, mCurUpdateRect.point.y);
lowerR.x = getMax(mOldUpdateRects[0].point.x + mOldUpdateRects[0].extent.x, mOldUpdateRects[1].point.x + mOldUpdateRects[1].extent.x);
lowerR.x = getMax(lowerR.x, mCurUpdateRect.point.x + mCurUpdateRect.extent.x);
lowerR.y = getMax(mOldUpdateRects[0].point.y + mOldUpdateRects[0].extent.y, mOldUpdateRects[1].point.y + mOldUpdateRects[1].extent.y);
lowerR.y = getMax(lowerR.y, mCurUpdateRect.point.y + mCurUpdateRect.extent.y);
updateUnion->point = upperL;
updateUnion->extent = lowerR - upperL;
//shift the oldUpdateRects
mOldUpdateRects[0] = mOldUpdateRects[1];
mOldUpdateRects[1] = mCurUpdateRect;
mCurUpdateRect.point.set(0,0);
mCurUpdateRect.extent.set(0,0);
}
void GuiCanvas::addUpdateRegion(Point2I pos, Point2I ext)
{
if(mCurUpdateRect.extent.x == 0)
{
mCurUpdateRect.point = pos;
mCurUpdateRect.extent = ext;
}
else
{
Point2I upperL;
upperL.x = getMin(mCurUpdateRect.point.x, pos.x);
upperL.y = getMin(mCurUpdateRect.point.y, pos.y);
Point2I lowerR;
lowerR.x = getMax(mCurUpdateRect.point.x + mCurUpdateRect.extent.x, pos.x + ext.x);
lowerR.y = getMax(mCurUpdateRect.point.y + mCurUpdateRect.extent.y, pos.y + ext.y);
mCurUpdateRect.point = upperL;
mCurUpdateRect.extent = lowerR - upperL;
}
}
void GuiCanvas::resetUpdateRegions()
{
//DEBUG - get surface width and height
mOldUpdateRects[0].set(mBounds.point, mBounds.extent);
mOldUpdateRects[1] = mOldUpdateRects[0];
mCurUpdateRect = mOldUpdateRects[0];
}
void GuiCanvas::setFirstResponder( GuiControl* newResponder )
{
GuiControl* oldResponder = mFirstResponder;
Parent::setFirstResponder( newResponder );
if ( oldResponder && ( oldResponder != mFirstResponder ) )
oldResponder->onLoseFirstResponder();
}
#ifdef TGE_RPG
void GuiCanvas::addAccelMaps(GuiControl* pOwner)
{
if(pOwner == NULL)
return;
m_arAccelMapOwners.increment();
m_arAccelMapOwners.last().pOwner = pOwner;
m_pAccelMap = &m_arAccelMapOwners.last().accelMap;
constructInPlace(m_pAccelMap);
for(iterator i = pOwner->end(); i != pOwner->begin() ; )
{
i--;
GuiControl *ctrl = static_cast<GuiControl *>(*i);
ctrl->buildAcceleratorMap();
#ifndef TGE_RPG
if (ctrl->mProfile->mModal)
break;
#endif
}
//Con::printf(" @@@ addAccelMaps %s" ,pOwner->getName());
}
void GuiCanvas::removeAllAccelMaps()
{
//Con::printf(" @@@ removeAllAccelMaps");
for(U32 n=0; n<m_arAccelMapOwners.size(); n++)
{
m_arAccelMapOwners[n].accelMap.clear();
destructInPlace(&m_arAccelMapOwners[n].accelMap);
}
m_arAccelMapOwners.clear();
m_pAccelMap = NULL;
}
void GuiCanvas::removeAccelMap(GuiControl* pOwner)
{
for(S32 n=m_arAccelMapOwners.size()-1; n>= 0; n--)
{
if(m_arAccelMapOwners[n].pOwner == pOwner)
{
if(m_pAccelMap == &m_arAccelMapOwners[n].accelMap)
m_pAccelMap = NULL;
m_arAccelMapOwners[n].accelMap.clear();
destructInPlace(&m_arAccelMapOwners[n].accelMap);
m_arAccelMapOwners.erase(n);
break;
}
}
if(m_pAccelMap == NULL && m_arAccelMapOwners.size())
m_pAccelMap = &m_arAccelMapOwners.last().accelMap;
//if(pOwner)
//Con::printf(" @@@ removeAccelMap %s" ,pOwner->getName());
}
bool GuiCanvas::processAccelKey(const InputEvent *event,U32 eventModifier, AccKeyTypes type)
{
if(event == NULL)
return false;
U32 i;
S32 n;
Vector<AccKeyMap>* pMap;
for(n=m_arAccelMapOwners.size()-1; n>= 0; n--)
{
Vector<AccKeyMap>& accMap = m_arAccelMapOwners[n].accelMap;
for(i = 0; i < accMap.size(); i++)
{
if ((U32)accMap[i].keyCode == (U32)event->objInst && (U32)accMap[i].modifier == eventModifier)
{
switch(type)
{
case AKT_PRESS:
accMap[i].ctrl->acceleratorKeyPress(accMap[i].index);
break;
case AKT_RELEASE:
accMap[i].ctrl->acceleratorKeyRelease(accMap[i].index);
break;
default:
return false;
}
return true;
}
}//for
}//for
return false;
}
void GuiCanvas::initAccelMap()
{
addAccelMaps(this);
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -