mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-04-22 04:45:31 +00:00
Engine directory for ticket #1
This commit is contained in:
parent
352279af7a
commit
7dbfe6994d
3795 changed files with 1363358 additions and 0 deletions
569
Engine/source/gui/core/guiArrayCtrl.cpp
Normal file
569
Engine/source/gui/core/guiArrayCtrl.cpp
Normal file
|
|
@ -0,0 +1,569 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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/core/guiArrayCtrl.h"
|
||||
|
||||
#include "console/console.h"
|
||||
#include "console/engineAPI.h"
|
||||
#include "platform/event.h"
|
||||
#include "gui/containers/guiScrollCtrl.h"
|
||||
#include "gfx/gfxDrawUtil.h"
|
||||
#include "gui/core/guiDefaultControlRender.h"
|
||||
|
||||
|
||||
IMPLEMENT_CONOBJECT(GuiArrayCtrl);
|
||||
|
||||
ConsoleDocClass( GuiArrayCtrl,
|
||||
"@brief Abstract base class for controls that store and display multiple elements in a single view.\n\n"
|
||||
|
||||
"You cannot actually instantiate this class. Instead you can use its childre:\n\n"
|
||||
|
||||
"- GuiConsole\n"
|
||||
"- GuiTextListCtrl\n"
|
||||
"- GuiTreeViewCtrl\n"
|
||||
"- DbgFileView\n"
|
||||
"- CreatorTree\n"
|
||||
|
||||
"This base class is primarily used by other internal classes or those dedicated to editors.\n\n"
|
||||
|
||||
"@ingroup GuiCore\n"
|
||||
|
||||
"@internal"
|
||||
);
|
||||
|
||||
IMPLEMENT_CALLBACK( GuiArrayCtrl, onCellSelected, void, ( const Point2I& cell ), ( cell ),
|
||||
"Call when a cell in the array is selected (clicked).\n\n"
|
||||
"@param @cell Coordinates of the cell"
|
||||
);
|
||||
IMPLEMENT_CALLBACK( GuiArrayCtrl, onCellHighlighted, void, ( const Point2I& cell ), ( cell ),
|
||||
"Call when a cell in the array is highlighted (moused over).\n\n"
|
||||
"@param @cell Coordinates of the cell"
|
||||
);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
GuiArrayCtrl::GuiArrayCtrl()
|
||||
{
|
||||
mActive = true;
|
||||
|
||||
mCellSize.set(80, 30);
|
||||
mSize = Point2I(5, 30);
|
||||
mSelectedCell.set(-1, -1);
|
||||
mMouseOverCell.set(-1, -1);
|
||||
mHeaderDim.set(0, 0);
|
||||
mIsContainer = true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool GuiArrayCtrl::onWake()
|
||||
{
|
||||
if (! Parent::onWake())
|
||||
return false;
|
||||
|
||||
//get the font
|
||||
mFont = mProfile->mFont;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiArrayCtrl::onSleep()
|
||||
{
|
||||
Parent::onSleep();
|
||||
mFont = NULL;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiArrayCtrl::setSize(Point2I newSize)
|
||||
{
|
||||
mSize = newSize;
|
||||
Point2I newExtent(newSize.x * mCellSize.x + mHeaderDim.x, newSize.y * mCellSize.y + mHeaderDim.y);
|
||||
|
||||
setExtent(newExtent);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiArrayCtrl::getScrollDimensions(S32 &cell_size, S32 &num_cells)
|
||||
{
|
||||
cell_size = mCellSize.y;
|
||||
num_cells = mSize.y;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool GuiArrayCtrl::cellSelected(Point2I cell)
|
||||
{
|
||||
if (cell.x < 0 || cell.x >= mSize.x || cell.y < 0 || cell.y >= mSize.y)
|
||||
{
|
||||
mSelectedCell = Point2I(-1,-1);
|
||||
return false;
|
||||
}
|
||||
|
||||
mSelectedCell = cell;
|
||||
scrollSelectionVisible();
|
||||
onCellSelected(cell);
|
||||
setUpdate();
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiArrayCtrl::onCellSelected(Point2I cell)
|
||||
{
|
||||
// [rene, 21-Jan-11 ] clashes with callbacks defined in derived classes
|
||||
Con::executef(this, "onSelect", Con::getFloatArg(cell.x), Con::getFloatArg(cell.y));
|
||||
|
||||
onCellSelected_callback( cell );
|
||||
|
||||
//call the console function
|
||||
execConsoleCallback();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiArrayCtrl::onCellHighlighted(Point2I cell)
|
||||
{
|
||||
onCellHighlighted_callback( cell );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiArrayCtrl::setSelectedCell(Point2I cell)
|
||||
{
|
||||
cellSelected(cell);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
Point2I GuiArrayCtrl::getSelectedCell()
|
||||
{
|
||||
return mSelectedCell;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiArrayCtrl::scrollSelectionVisible()
|
||||
{
|
||||
scrollCellVisible(mSelectedCell);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiArrayCtrl::scrollCellVisible(Point2I cell)
|
||||
{
|
||||
//make sure we have a parent
|
||||
//make sure we have a valid cell selected
|
||||
GuiScrollCtrl *parent = dynamic_cast<GuiScrollCtrl*>(getParent());
|
||||
if(!parent || cell.x < 0 || cell.y < 0)
|
||||
return;
|
||||
|
||||
RectI cellBounds(cell.x * mCellSize.x, cell.y * mCellSize.y, mCellSize.x, mCellSize.y);
|
||||
parent->scrollRectVisible(cellBounds);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiArrayCtrl::onRenderColumnHeaders(Point2I offset, Point2I parentOffset, Point2I headerDim)
|
||||
{
|
||||
if (mProfile->mBorder)
|
||||
{
|
||||
RectI cellR(offset.x + headerDim.x, parentOffset.y, getWidth() - headerDim.x, headerDim.y);
|
||||
GFX->getDrawUtil()->drawRectFill(cellR, mProfile->mBorderColor);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiArrayCtrl::onRenderRowHeader(Point2I offset, Point2I parentOffset, Point2I headerDim, Point2I cell)
|
||||
{
|
||||
ColorI color;
|
||||
RectI cellR;
|
||||
if (cell.x % 2)
|
||||
color.set(255, 0, 0, 255);
|
||||
else
|
||||
color.set(0, 255, 0, 255);
|
||||
|
||||
cellR.point.set(parentOffset.x, offset.y);
|
||||
cellR.extent.set(headerDim.x, mCellSize.y);
|
||||
GFX->getDrawUtil()->drawRectFill(cellR, color);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiArrayCtrl::onRenderCell(Point2I offset, Point2I cell, bool selected, bool mouseOver)
|
||||
{
|
||||
ColorI color(255 * (cell.x % 2), 255 * (cell.y % 2), 255 * ((cell.x + cell.y) % 2), 255);
|
||||
if (selected)
|
||||
{
|
||||
color.set(255, 0, 0, 255);
|
||||
}
|
||||
else if (mouseOver)
|
||||
{
|
||||
color.set(0, 0, 255, 255);
|
||||
}
|
||||
|
||||
//draw the cell
|
||||
RectI cellR(offset.x, offset.y, mCellSize.x, mCellSize.y);
|
||||
GFX->getDrawUtil()->drawRectFill(cellR, color);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiArrayCtrl::onRender(Point2I offset, const RectI &updateRect)
|
||||
{
|
||||
// The unmodified offset which was passed into this method.
|
||||
const Point2I inOffset( offset );
|
||||
|
||||
//Parent::onRender( offset, updateRect );
|
||||
|
||||
// We render our fill, borders, and child controls ourself.
|
||||
// This allows us to render child controls after we render cells,
|
||||
// so child controls appear on-top, as they should.
|
||||
|
||||
// Render our fill and borders.
|
||||
// This code from GuiControl::onRender().
|
||||
{
|
||||
RectI ctrlRect(offset, getExtent());
|
||||
|
||||
//if opaque, fill the update rect with the fill color
|
||||
if ( mProfile->mOpaque )
|
||||
GFX->getDrawUtil()->drawRectFill(ctrlRect, mProfile->mFillColor);
|
||||
|
||||
//if there's a border, draw the border
|
||||
if ( mProfile->mBorder )
|
||||
renderBorder(ctrlRect, mProfile);
|
||||
}
|
||||
|
||||
//make sure we have a parent
|
||||
GuiControl *parent = getParent();
|
||||
if (! parent)
|
||||
return;
|
||||
|
||||
S32 i, j;
|
||||
RectI headerClip;
|
||||
RectI clipRect(updateRect.point, updateRect.extent);
|
||||
|
||||
Point2I parentOffset = parent->localToGlobalCoord(Point2I(0, 0));
|
||||
|
||||
//if we have column headings
|
||||
if (mHeaderDim.y > 0)
|
||||
{
|
||||
headerClip.point.x = parentOffset.x + mHeaderDim.x;
|
||||
headerClip.point.y = parentOffset.y;
|
||||
headerClip.extent.x = clipRect.extent.x;// - headerClip.point.x; // This seems to fix some strange problems with some Gui's, bug? -pw
|
||||
headerClip.extent.y = mHeaderDim.y;
|
||||
|
||||
if (headerClip.intersect(clipRect))
|
||||
{
|
||||
GFX->setClipRect(headerClip);
|
||||
|
||||
//now render the header
|
||||
onRenderColumnHeaders(offset, parentOffset, mHeaderDim);
|
||||
|
||||
clipRect.point.y = headerClip.point.y + headerClip.extent.y - 1;
|
||||
}
|
||||
offset.y += mHeaderDim.y;
|
||||
}
|
||||
|
||||
//if we have row headings
|
||||
if (mHeaderDim.x > 0)
|
||||
{
|
||||
clipRect.point.x = getMax(clipRect.point.x, parentOffset.x + mHeaderDim.x);
|
||||
offset.x += mHeaderDim.x;
|
||||
}
|
||||
|
||||
//save the original for clipping the row headers
|
||||
RectI origClipRect = clipRect;
|
||||
|
||||
for (j = 0; j < mSize.y; j++)
|
||||
{
|
||||
//skip until we get to a visible row
|
||||
if ((j + 1) * mCellSize.y + offset.y < updateRect.point.y)
|
||||
continue;
|
||||
|
||||
//break once we've reached the last visible row
|
||||
if(j * mCellSize.y + offset.y >= updateRect.point.y + updateRect.extent.y)
|
||||
break;
|
||||
|
||||
//render the header
|
||||
if (mHeaderDim.x > 0)
|
||||
{
|
||||
headerClip.point.x = parentOffset.x;
|
||||
headerClip.extent.x = mHeaderDim.x;
|
||||
headerClip.point.y = offset.y + j * mCellSize.y;
|
||||
headerClip.extent.y = mCellSize.y;
|
||||
if (headerClip.intersect(origClipRect))
|
||||
{
|
||||
GFX->setClipRect(headerClip);
|
||||
|
||||
//render the row header
|
||||
onRenderRowHeader(Point2I(0, offset.y + j * mCellSize.y),
|
||||
Point2I(parentOffset.x, offset.y + j * mCellSize.y),
|
||||
mHeaderDim, Point2I(0, j));
|
||||
}
|
||||
}
|
||||
|
||||
//render the cells for the row
|
||||
for (i = 0; i < mSize.x; i++)
|
||||
{
|
||||
//skip past columns off the left edge
|
||||
if ((i + 1) * mCellSize.x + offset.x < updateRect.point.x)
|
||||
continue;
|
||||
|
||||
//break once past the last visible column
|
||||
if (i * mCellSize.x + offset.x >= updateRect.point.x + updateRect.extent.x)
|
||||
break;
|
||||
|
||||
S32 cellx = offset.x + i * mCellSize.x;
|
||||
S32 celly = offset.y + j * mCellSize.y;
|
||||
|
||||
RectI cellClip(cellx, celly, mCellSize.x, mCellSize.y);
|
||||
|
||||
//make sure the cell is within the update region
|
||||
if (cellClip.intersect(clipRect))
|
||||
{
|
||||
//set the clip rect
|
||||
GFX->setClipRect(cellClip);
|
||||
|
||||
//render the cell
|
||||
onRenderCell(Point2I(cellx, celly), Point2I(i, j),
|
||||
i == mSelectedCell.x && j == mSelectedCell.y,
|
||||
i == mMouseOverCell.x && j == mMouseOverCell.y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Done rendering cells.
|
||||
// Render child controls, if any, on top.
|
||||
renderChildControls( inOffset, updateRect );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiArrayCtrl::onMouseDown( const GuiEvent &event )
|
||||
{
|
||||
if ( !mActive || !mAwake || !mVisible )
|
||||
return;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiArrayCtrl::onMouseUp( const GuiEvent &event )
|
||||
{
|
||||
if ( !mActive || !mAwake || !mVisible )
|
||||
return;
|
||||
|
||||
//let the guiControl method take care of the rest
|
||||
Parent::onMouseUp(event);
|
||||
|
||||
Point2I pt = globalToLocalCoord(event.mousePoint);
|
||||
pt.x -= mHeaderDim.x; pt.y -= mHeaderDim.y;
|
||||
Point2I cell(
|
||||
(pt.x < 0 ? -1 : pt.x / mCellSize.x),
|
||||
(pt.y < 0 ? -1 : pt.y / mCellSize.y)
|
||||
);
|
||||
|
||||
if (cell.x >= 0 && cell.x < mSize.x && cell.y >= 0 && cell.y < mSize.y)
|
||||
{
|
||||
//store the previously selected cell
|
||||
Point2I prevSelected = mSelectedCell;
|
||||
|
||||
//select the new cell
|
||||
cellSelected(Point2I(cell.x, cell.y));
|
||||
|
||||
//if we double clicked on the *same* cell, evaluate the altConsole Command
|
||||
if ( ( event.mouseClickCount > 1 ) && ( prevSelected == mSelectedCell ) )
|
||||
execAltConsoleCallback();
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiArrayCtrl::onMouseEnter(const GuiEvent &event)
|
||||
{
|
||||
Point2I pt = globalToLocalCoord(event.mousePoint);
|
||||
pt.x -= mHeaderDim.x; pt.y -= mHeaderDim.y;
|
||||
|
||||
//get the cell
|
||||
Point2I cell((pt.x < 0 ? -1 : pt.x / mCellSize.x), (pt.y < 0 ? -1 : pt.y / mCellSize.y));
|
||||
if (cell.x >= 0 && cell.x < mSize.x && cell.y >= 0 && cell.y < mSize.y)
|
||||
{
|
||||
mMouseOverCell = cell;
|
||||
setUpdateRegion(Point2I(cell.x * mCellSize.x + mHeaderDim.x,
|
||||
cell.y * mCellSize.y + mHeaderDim.y), mCellSize );
|
||||
onCellHighlighted(mMouseOverCell);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiArrayCtrl::onMouseLeave(const GuiEvent & /*event*/)
|
||||
{
|
||||
setUpdateRegion(Point2I(mMouseOverCell.x * mCellSize.x + mHeaderDim.x,
|
||||
mMouseOverCell.y * mCellSize.y + mHeaderDim.y), mCellSize);
|
||||
mMouseOverCell.set(-1,-1);
|
||||
onCellHighlighted(mMouseOverCell);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiArrayCtrl::onMouseDragged(const GuiEvent &event)
|
||||
{
|
||||
// for the array control, the behavior of onMouseDragged is the same
|
||||
// as on mouse moved - basically just recalc the current mouse over cell
|
||||
// and set the update regions if necessary
|
||||
GuiArrayCtrl::onMouseMove(event);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiArrayCtrl::onMouseMove(const GuiEvent &event)
|
||||
{
|
||||
Point2I pt = globalToLocalCoord(event.mousePoint);
|
||||
pt.x -= mHeaderDim.x; pt.y -= mHeaderDim.y;
|
||||
Point2I cell((pt.x < 0 ? -1 : pt.x / mCellSize.x), (pt.y < 0 ? -1 : pt.y / mCellSize.y));
|
||||
if (cell.x != mMouseOverCell.x || cell.y != mMouseOverCell.y)
|
||||
{
|
||||
if (mMouseOverCell.x != -1)
|
||||
{
|
||||
setUpdateRegion(Point2I(mMouseOverCell.x * mCellSize.x + mHeaderDim.x,
|
||||
mMouseOverCell.y * mCellSize.y + mHeaderDim.y), mCellSize);
|
||||
}
|
||||
|
||||
if (cell.x >= 0 && cell.x < mSize.x && cell.y >= 0 && cell.y < mSize.y)
|
||||
{
|
||||
setUpdateRegion(Point2I(cell.x * mCellSize.x + mHeaderDim.x,
|
||||
cell.y * mCellSize.y + mHeaderDim.y), mCellSize);
|
||||
mMouseOverCell = cell;
|
||||
}
|
||||
else
|
||||
mMouseOverCell.set(-1,-1);
|
||||
}
|
||||
onCellHighlighted(mMouseOverCell);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool GuiArrayCtrl::onKeyDown(const GuiEvent &event)
|
||||
{
|
||||
//if this control is a dead end, kill the event
|
||||
if ((! mVisible) || (! mActive) || (! mAwake)) return true;
|
||||
|
||||
//get the parent
|
||||
S32 pageSize = 1;
|
||||
GuiControl *parent = getParent();
|
||||
if (parent && mCellSize.y > 0)
|
||||
{
|
||||
pageSize = getMax(1, (parent->getHeight() / mCellSize.y) - 1);
|
||||
}
|
||||
|
||||
Point2I delta(0,0);
|
||||
switch (event.keyCode)
|
||||
{
|
||||
case KEY_LEFT:
|
||||
delta.set(-1, 0);
|
||||
break;
|
||||
case KEY_RIGHT:
|
||||
delta.set(1, 0);
|
||||
break;
|
||||
case KEY_UP:
|
||||
delta.set(0, -1);
|
||||
break;
|
||||
case KEY_DOWN:
|
||||
delta.set(0, 1);
|
||||
break;
|
||||
case KEY_PAGE_UP:
|
||||
delta.set(0, -pageSize);
|
||||
break;
|
||||
case KEY_PAGE_DOWN:
|
||||
delta.set(0, pageSize);
|
||||
break;
|
||||
case KEY_HOME:
|
||||
cellSelected( Point2I( 0, 0 ) );
|
||||
return( true );
|
||||
case KEY_END:
|
||||
cellSelected( Point2I( 0, mSize.y - 1 ) );
|
||||
return( true );
|
||||
default:
|
||||
return Parent::onKeyDown(event);
|
||||
}
|
||||
if (mSize.x < 1 || mSize.y < 1)
|
||||
return true;
|
||||
|
||||
//select the first cell if no previous cell was selected
|
||||
if (mSelectedCell.x == -1 || mSelectedCell.y == -1)
|
||||
{
|
||||
cellSelected(Point2I(0,0));
|
||||
return true;
|
||||
}
|
||||
|
||||
//select the cell
|
||||
Point2I cell = mSelectedCell;
|
||||
cell.x = getMax(0, getMin(mSize.x - 1, cell.x + delta.x));
|
||||
cell.y = getMax(0, getMin(mSize.y - 1, cell.y + delta.y));
|
||||
cellSelected(cell);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GuiArrayCtrl::onRightMouseDown(const GuiEvent &event)
|
||||
{
|
||||
if ( !mActive || !mAwake || !mVisible )
|
||||
return;
|
||||
|
||||
Parent::onRightMouseDown( event );
|
||||
|
||||
Point2I cell;
|
||||
if( _findHitCell( event.mousePoint, cell ) )
|
||||
{
|
||||
char buf[32];
|
||||
dSprintf( buf, sizeof( buf ), "%d %d", event.mousePoint.x, event.mousePoint.y );
|
||||
|
||||
// [rene, 21-Jan-11 ] clashes with callbacks defined in derived classes
|
||||
|
||||
// Pass it to the console:
|
||||
Con::executef(this, "onRightMouseDown", Con::getIntArg(cell.x), Con::getIntArg(cell.y), buf);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool GuiArrayCtrl::_findHitCell( const Point2I& pos, Point2I& cellOut )
|
||||
{
|
||||
Point2I pt = globalToLocalCoord( pos );
|
||||
pt.x -= mHeaderDim.x; pt.y -= mHeaderDim.y;
|
||||
Point2I cell( ( pt.x < 0 ? -1 : pt.x / mCellSize.x ), ( pt.y < 0 ? -1 : pt.y / mCellSize.y ) );
|
||||
if( cell.x >= 0 && cell.x < mSize.x && cell.y >= 0 && cell.y < mSize.y )
|
||||
{
|
||||
cellOut = cell;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
108
Engine/source/gui/core/guiArrayCtrl.h
Normal file
108
Engine/source/gui/core/guiArrayCtrl.h
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GUIARRAYCTRL_H_
|
||||
#define _GUIARRAYCTRL_H_
|
||||
|
||||
#ifndef _GUITYPES_H_
|
||||
#include "gui/core/guiTypes.h"
|
||||
#endif
|
||||
#ifndef _GUITEXTCTRL_H_
|
||||
#include "gui/controls/guiTextCtrl.h"
|
||||
#endif
|
||||
|
||||
/// Renders a grid of cells.
|
||||
class GuiArrayCtrl : public GuiControl
|
||||
{
|
||||
typedef GuiControl Parent;
|
||||
|
||||
protected:
|
||||
|
||||
Point2I mHeaderDim;
|
||||
Point2I mSize;
|
||||
Point2I mCellSize;
|
||||
Point2I mSelectedCell;
|
||||
Point2I mMouseOverCell;
|
||||
|
||||
Resource<GFont> mFont;
|
||||
|
||||
virtual bool cellSelected(Point2I cell);
|
||||
virtual void onCellSelected(Point2I cell);
|
||||
virtual void onCellHighlighted(Point2I cell);
|
||||
|
||||
bool _findHitCell( const Point2I& pos, Point2I& cellOut );
|
||||
|
||||
/// @name Callbacks
|
||||
/// @{
|
||||
|
||||
DECLARE_CALLBACK( void, onCellHighlighted, ( const Point2I& cell ) );
|
||||
DECLARE_CALLBACK( void, onCellSelected, ( const Point2I& cell ) );
|
||||
|
||||
/// @}
|
||||
|
||||
public:
|
||||
|
||||
GuiArrayCtrl();
|
||||
DECLARE_CONOBJECT(GuiArrayCtrl);
|
||||
|
||||
bool onWake();
|
||||
void onSleep();
|
||||
|
||||
/// @name Array attribute methods
|
||||
/// @{
|
||||
Point2I getSize() { return mSize; }
|
||||
virtual void setSize(Point2I size);
|
||||
void setHeaderDim(const Point2I &dim) { mHeaderDim = dim; }
|
||||
void getScrollDimensions(S32 &cell_size, S32 &num_cells);
|
||||
/// @}
|
||||
|
||||
/// @name Selected cell methods
|
||||
/// @{
|
||||
void setSelectedCell(Point2I cell);
|
||||
void deselectCells() { mSelectedCell.set(-1,-1); }
|
||||
Point2I getSelectedCell();
|
||||
void scrollSelectionVisible();
|
||||
void scrollCellVisible(Point2I cell);
|
||||
/// @}
|
||||
|
||||
/// @name Rendering methods
|
||||
/// @{
|
||||
virtual void onRenderColumnHeaders(Point2I offset, Point2I parentOffset, Point2I headerDim);
|
||||
virtual void onRenderRowHeader(Point2I offset, Point2I parentOffset, Point2I headerDim, Point2I cell);
|
||||
virtual void onRenderCell(Point2I offset, Point2I cell, bool selected, bool mouseOver);
|
||||
void onRender(Point2I offset, const RectI &updateRect);
|
||||
/// @}
|
||||
|
||||
/// @name Mouse input methods
|
||||
/// @{
|
||||
void onMouseDown( const GuiEvent &event );
|
||||
void onMouseUp( const GuiEvent &event );
|
||||
void onMouseMove( const GuiEvent &event );
|
||||
void onMouseDragged( const GuiEvent &event );
|
||||
void onMouseEnter( const GuiEvent &event );
|
||||
void onMouseLeave( const GuiEvent &event );
|
||||
bool onKeyDown( const GuiEvent &event );
|
||||
void onRightMouseDown( const GuiEvent &event );
|
||||
/// @}
|
||||
};
|
||||
|
||||
#endif //_GUI_ARRAY_CTRL_H
|
||||
2652
Engine/source/gui/core/guiCanvas.cpp
Normal file
2652
Engine/source/gui/core/guiCanvas.cpp
Normal file
File diff suppressed because it is too large
Load diff
455
Engine/source/gui/core/guiCanvas.h
Normal file
455
Engine/source/gui/core/guiCanvas.h
Normal file
|
|
@ -0,0 +1,455 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GUICANVAS_H_
|
||||
#define _GUICANVAS_H_
|
||||
|
||||
#ifndef _SIMBASE_H_
|
||||
#include "console/simBase.h"
|
||||
#endif
|
||||
#ifndef _EVENT_H_
|
||||
#include "platform/event.h"
|
||||
#endif
|
||||
#ifndef _GUICONTROL_H_
|
||||
#include "gui/core/guiControl.h"
|
||||
#endif
|
||||
#ifndef _PLATFORMINPUT_H_
|
||||
#include "platform/platformInput.h"
|
||||
#endif
|
||||
|
||||
#include "component/interfaces/IProcessInput.h"
|
||||
#include "windowManager/platformWindowMgr.h"
|
||||
#include "gfx/gfxFence.h"
|
||||
|
||||
#ifdef TORQUE_DEMO_PURCHASE
|
||||
#ifndef _PURCHASESCREEN_H_
|
||||
#include "demo/purchase/purchaseScreen.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/// A canvas on which rendering occurs.
|
||||
///
|
||||
///
|
||||
/// @section GuiCanvas_contents What a GUICanvas Can Contain...
|
||||
///
|
||||
/// @subsection GuiCanvas_content_contentcontrol Content Control
|
||||
/// A content control is the top level GuiControl for a screen. This GuiControl
|
||||
/// will be the parent control for all other GuiControls on that particular
|
||||
/// screen.
|
||||
///
|
||||
/// @subsection GuiCanvas_content_dialogs Dialogs
|
||||
///
|
||||
/// A dialog is essentially another screen, only it gets overlaid on top of the
|
||||
/// current content control, and all input goes to the dialog. This is most akin
|
||||
/// to the "Open File" dialog box found in most operating systems. When you
|
||||
/// choose to open a file, and the "Open File" dialog pops up, you can no longer
|
||||
/// send input to the application, and must complete or cancel the open file
|
||||
/// request. Torque keeps track of layers of dialogs. The dialog with the highest
|
||||
/// layer is on top and will get all the input, unless the dialog is
|
||||
/// modeless, which is a profile option.
|
||||
///
|
||||
/// @see GuiControlProfile
|
||||
///
|
||||
/// @section GuiCanvas_dirty Dirty Rectangles
|
||||
///
|
||||
/// The GuiCanvas is based on dirty regions.
|
||||
///
|
||||
/// Every frame the canvas paints only the areas of the canvas that are 'dirty'
|
||||
/// or need updating. In most cases, this only is the area under the mouse cursor.
|
||||
/// This is why if you look in guiCanvas.cc the call to glClear is commented out.
|
||||
/// If you want a really good idea of what exactly dirty regions are and how they
|
||||
/// work, un-comment that glClear line in the renderFrame method of guiCanvas.cc
|
||||
///
|
||||
/// What you will see is a black screen, except in the dirty regions, where the
|
||||
/// screen will be painted normally. If you are making an animated GuiControl
|
||||
/// you need to add your control to the dirty areas of the canvas.
|
||||
///
|
||||
class GuiCanvas : public GuiControl, public IProcessInput
|
||||
{
|
||||
|
||||
protected:
|
||||
typedef GuiControl Parent;
|
||||
|
||||
/// @name Rendering
|
||||
/// @{
|
||||
RectI mOldUpdateRects[2];
|
||||
RectI mCurUpdateRect;
|
||||
U32 mLastRenderMs;
|
||||
/// @}
|
||||
|
||||
/// @name Cursor Properties
|
||||
/// @{
|
||||
|
||||
bool mCursorEnabled;
|
||||
bool mShowCursor;
|
||||
bool mRenderFront;
|
||||
Point2F mCursorPt; ///< Current cursor position in local coordinates.
|
||||
Point2I mLastCursorPt;
|
||||
GuiCursor *mDefaultCursor;
|
||||
GuiCursor *mLastCursor;
|
||||
bool mLastCursorEnabled;
|
||||
bool mForceMouseToGUI;
|
||||
bool mClampTorqueCursor;
|
||||
bool mAlwaysHandleMouseButtons;
|
||||
|
||||
/// @}
|
||||
|
||||
/// @name Mouse Input
|
||||
/// @{
|
||||
|
||||
SimObjectPtr<GuiControl> mMouseCapturedControl; ///< All mouse events will go to this ctrl only
|
||||
SimObjectPtr<GuiControl> mMouseControl; ///< the control the mouse was last seen in unless some other one captured it
|
||||
bool mMouseControlClicked; ///< whether the current ctrl has been clicked - used by helpctrl
|
||||
U32 mPrevMouseTime; ///< this determines how long the mouse has been in the same control
|
||||
bool mMouseButtonDown; ///< Flag to determine if the button is depressed
|
||||
bool mMouseRightButtonDown; ///< bool to determine if the right button is depressed
|
||||
bool mMouseMiddleButtonDown; ///< Middle button flag
|
||||
GuiEvent mLastEvent;
|
||||
|
||||
U8 mLastMouseClickCount;
|
||||
S32 mLastMouseDownTime;
|
||||
bool mLeftMouseLast;
|
||||
bool mMiddleMouseLast;
|
||||
bool mRightMouseLast;
|
||||
Point2F mMouseDownPoint;
|
||||
|
||||
/// Processes keyboard input events. Helper method for processInputEvent
|
||||
///
|
||||
/// \param inputEvent Information on the input even to be processed.
|
||||
/// \return True if the event was handled or false if it was not.
|
||||
virtual bool processKeyboardEvent(InputEventInfo &inputEvent);
|
||||
|
||||
/// Processes mouse input events. Helper method for processInputEvent
|
||||
///
|
||||
/// \param inputEvent Information on the input even to be processed.
|
||||
/// \return True if the event was handled or false if it was not.
|
||||
virtual bool processMouseEvent(InputEventInfo &inputEvent);
|
||||
|
||||
/// Processes gamepad input events. Helper method for processInputEvent
|
||||
///
|
||||
/// \param inputEvent Information on the input even to be processed.
|
||||
/// \return True if the event was handled or false if it was not.
|
||||
virtual bool processGamepadEvent(InputEventInfo &inputEvent);
|
||||
|
||||
virtual void findMouseControl(const GuiEvent &event);
|
||||
virtual void refreshMouseControl();
|
||||
/// @}
|
||||
|
||||
/// @name Keyboard Input
|
||||
/// @{
|
||||
|
||||
/// Accelerator key map
|
||||
struct AccKeyMap
|
||||
{
|
||||
GuiControl *ctrl;
|
||||
U32 index;
|
||||
U32 keyCode;
|
||||
U32 modifier;
|
||||
};
|
||||
Vector <AccKeyMap> mAcceleratorMap;
|
||||
|
||||
//for tooltip rendering
|
||||
U32 mHoverControlStart;
|
||||
GuiControl* mHoverControl;
|
||||
Point2I mHoverPosition;
|
||||
bool mHoverPositionSet;
|
||||
U32 mHoverLeftControlTime;
|
||||
|
||||
/// @}
|
||||
|
||||
// Internal event handling callbacks for use with PlatformWindow.
|
||||
void handleResize (WindowId did, S32 width, S32 height);
|
||||
void handleAppEvent (WindowId did, S32 event);
|
||||
void handlePaintEvent (WindowId did);
|
||||
|
||||
PlatformWindow *mPlatformWindow;
|
||||
GFXFence **mFences;
|
||||
S32 mNextFenceIdx;
|
||||
S32 mNumFences;
|
||||
|
||||
static bool setProtectedNumFences( void *object, const char *index, const char *data );
|
||||
virtual void setupFences();
|
||||
|
||||
void checkLockMouseMove( const GuiEvent& event );
|
||||
|
||||
public:
|
||||
DECLARE_CONOBJECT(GuiCanvas);
|
||||
DECLARE_CATEGORY( "Gui Core" );
|
||||
|
||||
GuiCanvas();
|
||||
virtual ~GuiCanvas();
|
||||
|
||||
virtual bool onAdd();
|
||||
virtual void onRemove();
|
||||
|
||||
static void initPersistFields();
|
||||
|
||||
/// @name Rendering methods
|
||||
///
|
||||
/// @{
|
||||
|
||||
/// Repaints the dirty regions of the canvas
|
||||
/// @param preRenderOnly If set to true, only the onPreRender methods of all the GuiControls will be called
|
||||
/// @param bufferSwap If set to true, it will swap buffers at the end. This is to support canvas-subclassing.
|
||||
virtual void renderFrame(bool preRenderOnly, bool bufferSwap = true);
|
||||
|
||||
/// Repaints the canvas by calling the platform window display event.
|
||||
virtual void paint();
|
||||
|
||||
/// Repaints the canvas skipping rendering if the target time
|
||||
/// has not yet elapsed.
|
||||
/// @param elapsedMS The time since the last frame.
|
||||
virtual void repaint(U32 elapsedMS);
|
||||
|
||||
/// This signal is triggered at the beginning and end of each render frame
|
||||
///
|
||||
/// @param beginFrame true at the beginning of the frame, false at the end
|
||||
///
|
||||
typedef Signal <void ( bool beginFrame )> GuiCanvasFrameSignal;
|
||||
|
||||
static GuiCanvasFrameSignal& getGuiCanvasFrameSignal();
|
||||
|
||||
/// Adds a dirty area to the canvas so it will be updated on the next frame
|
||||
/// @param pos Screen-coordinates of the upper-left hand corner of the dirty area
|
||||
/// @param ext Width/height of the dirty area
|
||||
virtual void addUpdateRegion(Point2I pos, Point2I ext);
|
||||
|
||||
/// Resets the update regions so that the next call to renderFrame will
|
||||
/// repaint the whole canvas
|
||||
virtual void resetUpdateRegions();
|
||||
|
||||
/// Resizes the content control to match the canvas size.
|
||||
void maintainSizing();
|
||||
|
||||
/// This builds a rectangle which encompasses all of the dirty regions to be
|
||||
/// repainted
|
||||
/// @param updateUnion (out) Rectangle which surrounds all dirty areas
|
||||
virtual void buildUpdateUnion(RectI *updateUnion);
|
||||
|
||||
/// This will swap the buffers at the end of renderFrame. It was added for canvas
|
||||
/// sub-classes in case they wanted to do some custom code before the buffer
|
||||
/// flip occured.
|
||||
virtual void swapBuffers();
|
||||
|
||||
/// @}
|
||||
|
||||
/// @name Canvas Content Management
|
||||
/// @{
|
||||
|
||||
/// This returns the PlatformWindow owned by this Canvas
|
||||
virtual PlatformWindow *getPlatformWindow()
|
||||
{
|
||||
return mPlatformWindow;
|
||||
}
|
||||
|
||||
/// This sets the content control to something different
|
||||
/// @param gui New content control
|
||||
virtual void setContentControl(GuiControl *gui);
|
||||
|
||||
/// Returns the content control
|
||||
virtual GuiControl *getContentControl();
|
||||
|
||||
/// Adds a dialog control onto the stack of dialogs
|
||||
/// @param gui Dialog to add
|
||||
/// @param layer Layer to put dialog on
|
||||
/// @param center Center dialog on canvas.
|
||||
virtual void pushDialogControl(GuiControl *gui, S32 layer = 0, bool center = false);
|
||||
|
||||
/// Removes a specific layer of dialogs
|
||||
/// @param layer Layer to pop off from
|
||||
virtual void popDialogControl(S32 layer = 0);
|
||||
|
||||
/// Removes a specific dialog control
|
||||
/// @param gui Dialog to remove from the dialog stack
|
||||
virtual void popDialogControl(GuiControl *gui);
|
||||
///@}
|
||||
|
||||
/// This turns on/off front-buffer rendering
|
||||
/// @param front True if all rendering should be done to the front buffer
|
||||
virtual void setRenderFront(bool front) { mRenderFront = front; }
|
||||
|
||||
/// @name Cursor commands
|
||||
/// A cursor can be on, but not be shown. If a cursor is not on, than it does not
|
||||
/// process input.
|
||||
/// @{
|
||||
|
||||
/// Sets the cursor for the canvas.
|
||||
/// @param cursor New cursor to use.
|
||||
virtual void setCursor(GuiCursor *cursor);
|
||||
S32 mCursorChanged;
|
||||
|
||||
/// Returns true if the cursor is on.
|
||||
virtual bool isCursorON() { return mCursorEnabled; }
|
||||
|
||||
/// Sets if mouse events should be passed to the GUI even if the cursor is off.
|
||||
/// @param onOff True if events should be passed to the GUI if the cursor is off
|
||||
virtual void setForceMouseToGUI(bool onOff);
|
||||
|
||||
/// Sets if the Torque cursor should be clamped to the window.
|
||||
/// @param onOff True if the Torque cursor should be clamped against the window
|
||||
virtual void setClampTorqueCursor(bool onOff);
|
||||
|
||||
/// Returns if the Torque cursor is clamped to the window
|
||||
virtual bool getClampTorqueCursor() { return mClampTorqueCursor; }
|
||||
|
||||
/// Turns the cursor on or off.
|
||||
/// @param onOff True if the cursor should be on.
|
||||
virtual void setCursorON(bool onOff);
|
||||
|
||||
/// Sets the position of the cursor
|
||||
/// @param pt Point, in screenspace for the cursor
|
||||
virtual void setCursorPos(const Point2I &pt);
|
||||
|
||||
/// Returns the point, in screenspace, at which the cursor is located.
|
||||
virtual Point2I getCursorPos();
|
||||
|
||||
/// Enable/disable rendering of the cursor.
|
||||
/// @param state True if we should render cursor
|
||||
virtual void showCursor(bool state);
|
||||
|
||||
/// Returns true if the cursor is being rendered.
|
||||
virtual bool isCursorShown();
|
||||
/// @}
|
||||
|
||||
///used by the tooltip resource
|
||||
Point2I getCursorExtent() { return mDefaultCursor->getExtent(); }
|
||||
|
||||
/// @name Input Processing
|
||||
/// @{
|
||||
|
||||
/// Processes an input event
|
||||
/// @see InputEvent
|
||||
/// @param event Input event to process
|
||||
virtual bool processInputEvent(InputEventInfo &inputEvent);
|
||||
/// @}
|
||||
|
||||
/// @name Mouse Methods
|
||||
/// @{
|
||||
|
||||
/// When a control gets the mouse lock this means that that control gets
|
||||
/// ALL mouse input and no other control receives any input.
|
||||
/// @param lockingControl Control to lock mouse to
|
||||
virtual void mouseLock(GuiControl *lockingControl);
|
||||
|
||||
/// Unlocks the mouse from a control
|
||||
/// @param lockingControl Control to unlock from
|
||||
virtual void mouseUnlock(GuiControl *lockingControl);
|
||||
|
||||
/// Returns the control which the mouse is over
|
||||
virtual GuiControl* getMouseControl() { return mMouseControl; }
|
||||
|
||||
/// Returns the control which the mouse is locked to if any
|
||||
virtual GuiControl* getMouseLockedControl() { return mMouseCapturedControl; }
|
||||
|
||||
/// Returns true if the left mouse button is down
|
||||
virtual bool mouseButtonDown(void) { return mMouseButtonDown; }
|
||||
|
||||
/// Returns true if the right mouse button is down
|
||||
virtual bool mouseRightButtonDown(void) { return mMouseRightButtonDown; }
|
||||
|
||||
/// @}
|
||||
|
||||
/// @name Mouse input methods
|
||||
/// These events process the events before passing them down to the
|
||||
/// controls they effect. This allows for things such as the input
|
||||
/// locking and such.
|
||||
///
|
||||
/// Each of these methods corresponds to the action in it's method name
|
||||
/// and processes the GuiEvent passed as a parameter
|
||||
/// @{
|
||||
virtual void rootMouseUp(const GuiEvent &event);
|
||||
virtual void rootMouseDown(const GuiEvent &event);
|
||||
virtual void rootMouseMove(const GuiEvent &event);
|
||||
virtual void rootMouseDragged(const GuiEvent &event);
|
||||
|
||||
virtual void rootRightMouseDown(const GuiEvent &event);
|
||||
virtual void rootRightMouseUp(const GuiEvent &event);
|
||||
virtual void rootRightMouseDragged(const GuiEvent &event);
|
||||
|
||||
virtual void rootMiddleMouseDown(const GuiEvent &event);
|
||||
virtual void rootMiddleMouseUp(const GuiEvent &event);
|
||||
virtual void rootMiddleMouseDragged(const GuiEvent &event);
|
||||
|
||||
virtual bool rootMouseWheelUp(const GuiEvent &event);
|
||||
virtual bool rootMouseWheelDown(const GuiEvent &event);
|
||||
/// @}
|
||||
|
||||
/// @name Keyboard input methods
|
||||
/// First responders
|
||||
///
|
||||
/// A first responder is a the GuiControl which responds first to input events
|
||||
/// before passing them off for further processing.
|
||||
/// @{
|
||||
|
||||
/// Moves the first responder to the next tabable controle
|
||||
virtual bool tabNext(void);
|
||||
|
||||
/// Moves the first responder to the previous tabable control
|
||||
virtual bool tabPrev(void);
|
||||
|
||||
/// Setups a keyboard accelerator which maps to a GuiControl.
|
||||
///
|
||||
/// @param ctrl GuiControl to map to.
|
||||
/// @param index
|
||||
/// @param keyCode Key code.
|
||||
/// @param modifier Shift, ctrl, etc.
|
||||
virtual void addAcceleratorKey(GuiControl *ctrl, U32 index, U32 keyCode, U32 modifier);
|
||||
|
||||
/// Sets the first responder.
|
||||
/// @param firstResponder Control to designate as first responder
|
||||
virtual void setFirstResponder(GuiControl *firstResponder);
|
||||
|
||||
/// This is used to toggle processing of native OS accelerators, not
|
||||
/// to be confused with the Torque accelerator key system, to keep them
|
||||
/// from swallowing up keystrokes. Both GuiTextEditCtrl and GuiTextPadCtrl
|
||||
/// use this method.
|
||||
virtual void setNativeAcceleratorsEnabled( bool enabled );
|
||||
/// @}
|
||||
|
||||
///
|
||||
virtual Point2I getWindowSize();
|
||||
|
||||
virtual void enableKeyboardTranslation();
|
||||
virtual void disableKeyboardTranslation();
|
||||
|
||||
virtual void setWindowTitle(const char *newTitle);
|
||||
|
||||
private:
|
||||
static const U32 MAX_GAMEPADS = 4; ///< The maximum number of supported gamepads
|
||||
|
||||
#ifdef TORQUE_DEMO_PURCHASE
|
||||
private:
|
||||
PurchaseScreen* mPurchaseScreen;
|
||||
U32 mLastPurchaseHideTime;
|
||||
|
||||
public:
|
||||
void showPurchaseScreen(bool show, bool startBlocker, const char* location, bool doExit);
|
||||
void updatePurchaseScreen(const char* value);
|
||||
#endif
|
||||
|
||||
#ifdef TORQUE_DEMO_TIMEOUT
|
||||
private:
|
||||
void checkTimeOut();
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
2846
Engine/source/gui/core/guiControl.cpp
Normal file
2846
Engine/source/gui/core/guiControl.cpp
Normal file
File diff suppressed because it is too large
Load diff
830
Engine/source/gui/core/guiControl.h
Normal file
830
Engine/source/gui/core/guiControl.h
Normal file
|
|
@ -0,0 +1,830 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GUICONTROL_H_
|
||||
#define _GUICONTROL_H_
|
||||
|
||||
#ifndef _MPOINT3_H_
|
||||
#include "math/mPoint3.h"
|
||||
#endif
|
||||
#ifndef _MRECT_H_
|
||||
#include "math/mRect.h"
|
||||
#endif
|
||||
#ifndef _COLOR_H_
|
||||
#include "core/color.h"
|
||||
#endif
|
||||
#ifndef _SIMBASE_H_
|
||||
#include "console/simBase.h"
|
||||
#endif
|
||||
#ifndef _GUITYPES_H_
|
||||
#include "gui/core/guiTypes.h"
|
||||
#endif
|
||||
#ifndef _EVENT_H_
|
||||
#include "platform/event.h"
|
||||
#endif
|
||||
#ifndef _UTIL_DELEGATE_H_
|
||||
#include "core/util/delegate.h"
|
||||
#endif
|
||||
#ifndef _LANG_H_
|
||||
#include "i18n/lang.h"
|
||||
#endif
|
||||
|
||||
class GuiCanvas;
|
||||
class GuiEditCtrl;
|
||||
class GuiWindowCtrl;
|
||||
|
||||
|
||||
DECLARE_SCOPE( GuiAPI );
|
||||
|
||||
|
||||
/// A delegate used in tool tip rendering.
|
||||
///
|
||||
/// @param hoverPos position to display the tip near
|
||||
/// @param cursorPos the actual position of the cursor when the delegate is called
|
||||
/// @param tipText optional alternate tip to be rendered
|
||||
/// @return Returns true if the tooltip was rendered.
|
||||
///
|
||||
/// @see GuiControl::mRenderTooltipDelegate
|
||||
typedef Delegate<bool( const Point2I &hoverPos, const Point2I &cursorPos, const char *tipText )> RenderTooltipDelegate;
|
||||
|
||||
/// @defgroup gui_group Gui System
|
||||
/// The GUI system in Torque provides a powerful way of creating
|
||||
/// WYSIWYG User Interfaces for your Game or Application written
|
||||
/// in Torque.
|
||||
///
|
||||
/// The GUI Provides a range of different controls that you may use
|
||||
/// to arrange and layout your GUI's, including Buttons, Lists, Bitmaps
|
||||
/// Windows, Containers, and HUD elements.
|
||||
///
|
||||
/// The Base Control Class GuiControl provides a basis upon which to
|
||||
/// write GuiControl's that may be specific to your particular type
|
||||
/// of game.
|
||||
|
||||
|
||||
/// @addtogroup gui_core_group Core
|
||||
/// @section GuiControl_Intro Introduction
|
||||
///
|
||||
/// GuiControl is the base class for GUI controls in Torque. It provides these
|
||||
/// basic areas of functionality:
|
||||
/// - Inherits from SimGroup, so that controls can have children.
|
||||
/// - Interfacing with a GuiControlProfile.
|
||||
/// - An abstraction from the details of handling user input
|
||||
/// and so forth, providing friendly hooks like onMouseEnter(), onMouseMove(),
|
||||
/// and onMouseLeave(), onKeyDown(), and so forth.
|
||||
/// - An abstraction from the details of rendering and resizing.
|
||||
/// - Helper functions to manipulate the mouse (mouseLock and
|
||||
/// mouseUnlock), and convert coordinates (localToGlobalCoord() and
|
||||
/// globalToLocalCoord()).
|
||||
///
|
||||
/// @ref GUI has an overview of the GUI system.
|
||||
///
|
||||
///
|
||||
/// @ingroup gui_group Gui System
|
||||
/// @{
|
||||
class GuiControl : public SimGroup
|
||||
{
|
||||
public:
|
||||
|
||||
typedef SimGroup Parent;
|
||||
|
||||
friend class GuiWindowCtrl; // mCollapseGroupVec
|
||||
friend class GuiCanvas;
|
||||
friend class GuiEditCtrl;
|
||||
friend class GuiDragAndDropControl; // drag callbacks
|
||||
|
||||
/// Additional write flags for GuiControls.
|
||||
enum
|
||||
{
|
||||
NoCheckParentCanSave = BIT( 31 ), ///< Don't inherit mCanSave=false from parents.
|
||||
};
|
||||
|
||||
enum horizSizingOptions
|
||||
{
|
||||
horizResizeRight = 0, ///< fixed on the left and width
|
||||
horizResizeWidth, ///< fixed on the left and right
|
||||
horizResizeLeft, ///< fixed on the right and width
|
||||
horizResizeCenter,
|
||||
horizResizeRelative, ///< resize relative
|
||||
horizResizeWindowRelative ///< resize window relative
|
||||
};
|
||||
enum vertSizingOptions
|
||||
{
|
||||
vertResizeBottom = 0, ///< fixed on the top and in height
|
||||
vertResizeHeight, ///< fixed on the top and bottom
|
||||
vertResizeTop, ///< fixed in height and on the bottom
|
||||
vertResizeCenter,
|
||||
vertResizeRelative, ///< resize relative
|
||||
vertResizeWindowRelative ///< resize window relative
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
SimGroup *mAddGroup; ///< The internal name of a SimGroup child of the global GuiGroup in which to organize this gui on creation
|
||||
RectI mBounds; ///< The internal bounds of this control
|
||||
|
||||
protected:
|
||||
|
||||
GuiControlProfile* mProfile; ///< The profile for this gui (data settings that are likely to be shared by multiple guis)
|
||||
GuiControlProfile* mTooltipProfile; ///< The profile for any tooltips
|
||||
|
||||
/// @name Control State
|
||||
/// @{
|
||||
|
||||
static bool setProfileProt( void *object, const char *index, const char *data );
|
||||
static bool setTooltipProfileProt( void *object, const char *index, const char *data );
|
||||
|
||||
S32 mTipHoverTime;
|
||||
|
||||
/// Delegate called to render a tooltip for this control.
|
||||
/// By default this will be set to defaultTooltipRender.
|
||||
RenderTooltipDelegate mRenderTooltipDelegate;
|
||||
|
||||
/// The default tooltip rendering function.
|
||||
/// @see RenderTooltipDelegate
|
||||
bool defaultTooltipRender( const Point2I &hoverPos, const Point2I &cursorPos, const char* tipText = NULL );
|
||||
|
||||
bool mVisible;
|
||||
bool mActive;
|
||||
bool mAwake;
|
||||
bool mSetFirstResponder;
|
||||
bool mIsContainer; ///< if true, then the GuiEditor can drag other controls into this one.
|
||||
bool mCanResize;
|
||||
bool mCanHit;
|
||||
|
||||
S32 mLayer;
|
||||
Point2I mMinExtent;
|
||||
StringTableEntry mLangTableName;
|
||||
LangTable *mLangTable;
|
||||
|
||||
bool mNotifyChildrenResized;
|
||||
|
||||
// Contains array of windows located inside GuiControl
|
||||
typedef Vector< Vector< GuiWindowCtrl *> > CollapseGroupVec;
|
||||
CollapseGroupVec mCollapseGroupVec;
|
||||
|
||||
static bool smDesignTime; ///< static GuiControl boolean that specifies if the GUI Editor is active
|
||||
/// @}
|
||||
|
||||
/// @name Design Time Editor Access
|
||||
/// @{
|
||||
static GuiEditCtrl *smEditorHandle; ///< static GuiEditCtrl pointer that gives controls access to editor-NULL if editor is closed
|
||||
/// @}
|
||||
|
||||
/// @name Keyboard Input
|
||||
/// @{
|
||||
GuiControl *mFirstResponder;
|
||||
static GuiControl *smPrevResponder;
|
||||
static GuiControl *smCurResponder;
|
||||
/// @}
|
||||
|
||||
/// @name Control State
|
||||
/// @{
|
||||
|
||||
S32 mHorizSizing; ///< Set from horizSizingOptions.
|
||||
S32 mVertSizing; ///< Set from vertSizingOptions.
|
||||
|
||||
StringTableEntry mAcceleratorKey;
|
||||
StringTableEntry mConsoleVariable;
|
||||
|
||||
String mConsoleCommand;
|
||||
String mAltConsoleCommand;
|
||||
|
||||
String mTooltip;
|
||||
|
||||
/// @}
|
||||
|
||||
/// @name Console
|
||||
/// The console variable collection of functions allows a console variable to be bound to the GUI control.
|
||||
///
|
||||
/// This allows, say, an edit field to be bound to '$foo'. The value of the console
|
||||
/// variable '$foo' would then be equal to the text inside the text field. Changing
|
||||
/// either changes the other.
|
||||
/// @{
|
||||
|
||||
/// $ThisControl variable for callback execution.
|
||||
static GuiControl* smThisControl;
|
||||
|
||||
/// Set $ThisControl and evaluate the given script code.
|
||||
const char* evaluate( const char* str );
|
||||
|
||||
/// Sets the value of the console variable bound to this control
|
||||
/// @param value String value to assign to control's console variable
|
||||
void setVariable(const char *value);
|
||||
|
||||
/// Sets the value of the console variable bound to this control
|
||||
/// @param value Integer value to assign to control's console variable
|
||||
void setIntVariable(S32 value);
|
||||
|
||||
/// Sets the value of the console variable bound to this control
|
||||
/// @param value Float value to assign to control's console variable
|
||||
void setFloatVariable(F32 value);
|
||||
|
||||
const char* getVariable(); ///< Returns value of control's bound variable as a string
|
||||
S32 getIntVariable(); ///< Returns value of control's bound variable as a integer
|
||||
F32 getFloatVariable(); ///< Returns value of control's bound variable as a float
|
||||
|
||||
GFXStateBlockRef mDefaultGuiSB;
|
||||
|
||||
/// @name Callbacks
|
||||
/// @{
|
||||
|
||||
DECLARE_CALLBACK( void, onAdd, () );
|
||||
DECLARE_CALLBACK( void, onRemove, () );
|
||||
|
||||
DECLARE_CALLBACK( void, onWake, () );
|
||||
DECLARE_CALLBACK( void, onSleep, () );
|
||||
|
||||
DECLARE_CALLBACK( void, onLoseFirstResponder, () );
|
||||
DECLARE_CALLBACK( void, onGainFirstResponder, () );
|
||||
|
||||
DECLARE_CALLBACK( void, onAction, () );
|
||||
DECLARE_CALLBACK( void, onVisible, ( bool state ) );
|
||||
DECLARE_CALLBACK( void, onActive, ( bool state ) );
|
||||
|
||||
DECLARE_CALLBACK( void, onDialogPush, () );
|
||||
DECLARE_CALLBACK( void, onDialogPop, () );
|
||||
|
||||
DECLARE_CALLBACK( void, onControlDragEnter, ( GuiControl* control, const Point2I& dropPoint ) );
|
||||
DECLARE_CALLBACK( void, onControlDragExit, ( GuiControl* control, const Point2I& dropPoint ) );
|
||||
DECLARE_CALLBACK( void, onControlDragged, ( GuiControl* control, const Point2I& dropPoint ) );
|
||||
DECLARE_CALLBACK( void, onControlDropped, ( GuiControl* control, const Point2I& dropPoint ) );
|
||||
|
||||
/// @}
|
||||
|
||||
public:
|
||||
|
||||
/// Set the name of the console variable which this GuiObject is bound to
|
||||
/// @param variable Variable name
|
||||
void setConsoleVariable(const char *variable);
|
||||
|
||||
/// Set the name of the console function bound to, such as a script function
|
||||
/// a button calls when clicked.
|
||||
/// @param newCmd Console function to attach to this GuiControl
|
||||
void setConsoleCommand( const String& newCmd );
|
||||
const char * getConsoleCommand(); ///< Returns the name of the function bound to this GuiControl
|
||||
LangTable *getGUILangTable(void);
|
||||
const UTF8 *getGUIString(S32 id);
|
||||
|
||||
/// @}
|
||||
|
||||
/// @name Callbacks
|
||||
/// @{
|
||||
/// Executes a console command, and returns the result.
|
||||
///
|
||||
/// The global console variable $ThisControl is set to the id of the calling
|
||||
/// control. WARNING: because multiple controls may set $ThisControl, at any time,
|
||||
/// the value of $ThisControl should be stored in a local variable by the
|
||||
/// callback code. The use of the $ThisControl variable is not thread safe.
|
||||
|
||||
/// Executes mConsoleCommand, and returns the result.
|
||||
const char* execConsoleCallback();
|
||||
/// Executes mAltConsoleCommand, and returns the result.
|
||||
const char* execAltConsoleCallback();
|
||||
/// @}
|
||||
|
||||
static bool _setVisible( void *object, const char *index, const char *data ) { static_cast<GuiControl*>(object)->setVisible( dAtob( data ) ); return false; };
|
||||
static bool _setActive( void *object, const char *index, const char *data ) { static_cast<GuiControl*>(object)->setActive( dAtob( data ) ); return false; };
|
||||
|
||||
/// @name Editor
|
||||
/// These functions are used by the GUI Editor
|
||||
/// @{
|
||||
|
||||
/// Sets the size of the GuiControl
|
||||
/// @param horz Width of the control
|
||||
/// @param vert Height of the control
|
||||
void setSizing(S32 horz, S32 vert);
|
||||
|
||||
/// Overrides Parent Serialization to allow specific controls to not be saved (Dynamic Controls, etc)
|
||||
void write(Stream &stream, U32 tabStop, U32 flags);
|
||||
|
||||
/// Returns boolean as to whether any parent of this control has the 'no serialization' flag set.
|
||||
bool getCanSaveParent();
|
||||
|
||||
/// @}
|
||||
|
||||
/// @name Initialization
|
||||
/// @{
|
||||
|
||||
DECLARE_CONOBJECT(GuiControl);
|
||||
DECLARE_CATEGORY( "Gui Core" );
|
||||
DECLARE_DESCRIPTION( "Base class for GUI controls. Can also be used as a generic container." );
|
||||
|
||||
GuiControl();
|
||||
virtual ~GuiControl();
|
||||
virtual bool processArguments(S32 argc, const char **argv);
|
||||
|
||||
static void initPersistFields();
|
||||
static void consoleInit();
|
||||
|
||||
/// @}
|
||||
|
||||
/// @name Accessors
|
||||
/// @{
|
||||
|
||||
inline const Point2I& getPosition() const { return mBounds.point; } ///< Returns position of the control
|
||||
inline const Point2I& getExtent() const { return mBounds.extent; } ///< Returns extents of the control
|
||||
inline const RectI getBounds()const { return mBounds; } ///< Returns the bounds of the control
|
||||
inline const RectI getGlobalBounds() ///< Returns the bounds of this object, in global coordinates
|
||||
{
|
||||
RectI retRect = getBounds();
|
||||
retRect.point = localToGlobalCoord( Point2I(0,0) );
|
||||
|
||||
return retRect;
|
||||
};
|
||||
virtual Point2I getMinExtent() const { return mMinExtent; } ///< Returns minimum size the control can be
|
||||
virtual void setMinExtent( const Point2I &newMinExtent ) { mMinExtent = newMinExtent; };
|
||||
inline const S32 getLeft() const { return mBounds.point.x; } ///< Returns the X position of the control
|
||||
inline const S32 getTop() const { return mBounds.point.y; } ///< Returns the Y position of the control
|
||||
inline const S32 getWidth() const { return mBounds.extent.x; } ///< Returns the width of the control
|
||||
inline const S32 getHeight() const { return mBounds.extent.y; } ///< Returns the height of the control
|
||||
|
||||
inline const S32 getHorizSizing() const { return mHorizSizing; }
|
||||
inline const S32 getVertSizing() const { return mVertSizing; }
|
||||
|
||||
/// @}
|
||||
|
||||
/// @name Flags
|
||||
/// @{
|
||||
|
||||
/// Sets the visibility of the control
|
||||
/// @param value True if object should be visible
|
||||
virtual void setVisible(bool value);
|
||||
inline bool isVisible() const { return mVisible; } ///< Returns true if the object is visible
|
||||
virtual bool isHidden() const { return !isVisible(); }
|
||||
virtual void setHidden( bool state ) { setVisible( !state ); }
|
||||
|
||||
void setCanHit( bool value ) { mCanHit = value; }
|
||||
|
||||
/// Sets the status of this control as active and responding or inactive
|
||||
/// @param value True if this is active
|
||||
virtual void setActive(bool value);
|
||||
bool isActive() { return mActive; } ///< Returns true if this control is active
|
||||
|
||||
bool isAwake() { return mAwake; } ///< Returns true if this control is awake
|
||||
|
||||
/// @}
|
||||
|
||||
/// Get information about the size of a scroll line.
|
||||
///
|
||||
/// @param rowHeight The height, in pixels, of a row
|
||||
/// @param columnWidth The width, in pixels, of a column
|
||||
virtual void getScrollLineSizes(U32 *rowHeight, U32 *columnWidth);
|
||||
|
||||
/// Get information about the cursor.
|
||||
/// @param cursor Cursor information will be stored here
|
||||
/// @param showCursor Will be set to true if the cursor is visible
|
||||
/// @param lastGuiEvent GuiEvent containing cursor position and modifier keys (ie ctrl, shift, alt etc)
|
||||
virtual void getCursor(GuiCursor *&cursor, bool &showCursor, const GuiEvent &lastGuiEvent);
|
||||
|
||||
/// @name Children
|
||||
/// @{
|
||||
|
||||
/// Adds an object as a child of this object.
|
||||
/// @param obj New child object of this control
|
||||
void addObject(SimObject *obj);
|
||||
|
||||
/// Removes a child object from this control.
|
||||
/// @param obj Object to remove from this control
|
||||
void removeObject(SimObject *obj);
|
||||
|
||||
GuiControl *getParent(); ///< Returns the control which owns this one.
|
||||
GuiCanvas *getRoot(); ///< Returns the root canvas of this control.
|
||||
|
||||
virtual bool acceptsAsChild( SimObject* object ) const;
|
||||
|
||||
virtual void onGroupRemove();
|
||||
|
||||
/// @}
|
||||
|
||||
/// @name Coordinates
|
||||
/// @{
|
||||
|
||||
/// Translates local coordinates (wrt this object) into global coordinates
|
||||
///
|
||||
/// @param src Local coordinates to translate
|
||||
Point2I localToGlobalCoord(const Point2I &src);
|
||||
|
||||
/// Returns global coordinates translated into local space
|
||||
///
|
||||
/// @param src Global coordinates to translate
|
||||
Point2I globalToLocalCoord(const Point2I &src);
|
||||
/// @}
|
||||
|
||||
/// @name Resizing
|
||||
/// @{
|
||||
|
||||
/// Changes the size and/or position of this control
|
||||
/// @param newPosition New position of this control
|
||||
/// @param newExtent New size of this control
|
||||
virtual bool resize(const Point2I &newPosition, const Point2I &newExtent);
|
||||
|
||||
/// Changes the position of this control
|
||||
/// @param newPosition New position of this control
|
||||
virtual bool setPosition( const Point2I &newPosition );
|
||||
inline void setPosition( const S32 x, const S32 y ) { setPosition(Point2I(x,y)); }
|
||||
|
||||
/// Changes the size of this control
|
||||
/// @param newExtent New size of this control
|
||||
virtual bool setExtent( const Point2I &newExtent );
|
||||
inline void setExtent( const S32 width, const S32 height) { setExtent(Point2I(width, height)); }
|
||||
|
||||
/// Changes the bounds of this control
|
||||
/// @param newBounds New bounds of this control
|
||||
virtual bool setBounds( const RectI &newBounds );
|
||||
inline void setBounds( const S32 left, const S32 top,
|
||||
const S32 width, const S32 height) { setBounds(RectI(left, top, width, height)); }
|
||||
|
||||
/// Changes the X position of this control
|
||||
/// @param newXPosition New X Position of this control
|
||||
virtual void setLeft( S32 newLeft );
|
||||
|
||||
/// Changes the Y position of this control
|
||||
/// @param newYPosition New Y Position of this control
|
||||
virtual void setTop( S32 newTop );
|
||||
|
||||
/// Changes the width of this control
|
||||
/// @param newWidth New width of this control
|
||||
virtual void setWidth( S32 newWidth );
|
||||
|
||||
/// Changes the height of this control
|
||||
/// @param newHeight New Height of this control
|
||||
virtual void setHeight( S32 newHeight );
|
||||
|
||||
/// Called when a child control of the object is resized
|
||||
/// @param child Child object
|
||||
virtual void childResized(GuiControl *child);
|
||||
|
||||
/// Called when this objects parent is resized
|
||||
/// @param oldParentRect The old rectangle of the parent object
|
||||
/// @param newParentRect The new rectangle of the parent object
|
||||
virtual void parentResized(const RectI &oldParentRect, const RectI &newParentRect);
|
||||
/// @}
|
||||
|
||||
/// @name Rendering
|
||||
/// @{
|
||||
|
||||
/// Called when this control is to render itself
|
||||
/// @param offset The location this control is to begin rendering
|
||||
/// @param updateRect The screen area this control has drawing access to
|
||||
virtual void onRender(Point2I offset, const RectI &updateRect);
|
||||
|
||||
/// Called when this control should render its children
|
||||
/// @param offset The location this control is to begin rendering
|
||||
/// @param updateRect The screen area this control has drawing access to
|
||||
void renderChildControls(Point2I offset, const RectI &updateRect);
|
||||
|
||||
/// Sets the area (local coordinates) this control wants refreshed each frame
|
||||
/// @param pos UpperLeft point on rectangle of refresh area
|
||||
/// @param ext Extent of update rect
|
||||
void setUpdateRegion(Point2I pos, Point2I ext);
|
||||
|
||||
/// Sets the update area of the control to encompass the whole control
|
||||
virtual void setUpdate();
|
||||
/// @}
|
||||
|
||||
//child hierarchy calls
|
||||
void awaken(); ///< Called when this control and its children have been wired up.
|
||||
void sleep(); ///< Called when this control is no more.
|
||||
void preRender(); ///< Pre-render this control and all its children.
|
||||
|
||||
/// @name Events
|
||||
///
|
||||
/// If you subclass these, make sure to call the Parent::'s versions.
|
||||
///
|
||||
/// @{
|
||||
|
||||
/// Called when this object is asked to wake up returns true if it's actually awake at the end
|
||||
virtual bool onWake();
|
||||
|
||||
/// Called when this object is asked to sleep
|
||||
virtual void onSleep();
|
||||
|
||||
/// Do special pre-render processing
|
||||
virtual void onPreRender();
|
||||
|
||||
/// Called when this object is removed
|
||||
virtual void onRemove();
|
||||
|
||||
/// Called when one of this objects children is removed
|
||||
virtual void onChildRemoved( GuiControl *child );
|
||||
|
||||
/// Called when this object is added to the scene
|
||||
virtual bool onAdd();
|
||||
|
||||
/// Called when the mProfile or mToolTipProfile is deleted
|
||||
virtual void onDeleteNotify(SimObject *object);
|
||||
|
||||
/// Called when this object has a new child
|
||||
virtual void onChildAdded( GuiControl *child );
|
||||
|
||||
/// @}
|
||||
|
||||
/// @name Console
|
||||
/// @{
|
||||
|
||||
/// Returns the value of the variable bound to this object
|
||||
virtual const char *getScriptValue();
|
||||
|
||||
/// Sets the value of the variable bound to this object
|
||||
virtual void setScriptValue(const char *value);
|
||||
/// @}
|
||||
|
||||
/// @name Input (Keyboard/Mouse)
|
||||
/// @{
|
||||
|
||||
/// This function will return true if the provided coordinates (wrt parent object) are
|
||||
/// within the bounds of this control
|
||||
/// @param parentCoordPoint Coordinates to test
|
||||
virtual bool pointInControl(const Point2I& parentCoordPoint);
|
||||
|
||||
/// Returns true if the global cursor is inside this control
|
||||
bool cursorInControl();
|
||||
|
||||
/// Returns the control which the provided point is under, with layering
|
||||
/// @param pt Point to test
|
||||
/// @param initialLayer Layer of gui objects to begin the search
|
||||
virtual GuiControl* findHitControl(const Point2I &pt, S32 initialLayer = -1 );
|
||||
|
||||
enum EHitTestFlags
|
||||
{
|
||||
HIT_FullBoxOnly = BIT( 0 ), ///< Hit only counts if all of a control's bounds are within the hit rectangle.
|
||||
HIT_ParentPreventsChildHit = BIT( 1 ), ///< A positive hit test on a parent control will prevent hit tests on children.
|
||||
HIT_AddParentHits = BIT( 2 ), ///< Parent's that get hit should be added regardless of whether any of their children get hit, too.
|
||||
HIT_NoCanHitNoRecurse = BIT( 3 ), ///< A hit-disabled control will not recurse into children.
|
||||
};
|
||||
|
||||
///
|
||||
virtual bool findHitControls( const RectI& rect, Vector< GuiControl* >& outResult, U32 flags = 0, S32 initialLayer = -1, U32 depth = 0 );
|
||||
|
||||
/// Lock the mouse within the provided control
|
||||
/// @param lockingControl Control to lock the mouse within
|
||||
void mouseLock(GuiControl *lockingControl);
|
||||
|
||||
/// Turn on mouse locking with last used lock control
|
||||
void mouseLock();
|
||||
|
||||
/// Unlock the mouse
|
||||
void mouseUnlock();
|
||||
|
||||
/// Returns true if the mouse is locked
|
||||
bool isMouseLocked();
|
||||
/// @}
|
||||
|
||||
|
||||
/// General input handler.
|
||||
virtual bool onInputEvent(const InputEventInfo &event);
|
||||
|
||||
/// @name Mouse Events
|
||||
/// These functions are called when the input event which is
|
||||
/// in the name of the function occurs.
|
||||
/// @{
|
||||
virtual void onMouseUp(const GuiEvent &event);
|
||||
virtual void onMouseDown(const GuiEvent &event);
|
||||
virtual void onMouseMove(const GuiEvent &event);
|
||||
virtual void onMouseDragged(const GuiEvent &event);
|
||||
virtual void onMouseEnter(const GuiEvent &event);
|
||||
virtual void onMouseLeave(const GuiEvent &event);
|
||||
|
||||
virtual bool onMouseWheelUp(const GuiEvent &event);
|
||||
virtual bool onMouseWheelDown(const GuiEvent &event);
|
||||
|
||||
virtual void onRightMouseDown(const GuiEvent &event);
|
||||
virtual void onRightMouseUp(const GuiEvent &event);
|
||||
virtual void onRightMouseDragged(const GuiEvent &event);
|
||||
|
||||
virtual void onMiddleMouseDown(const GuiEvent &event);
|
||||
virtual void onMiddleMouseUp(const GuiEvent &event);
|
||||
virtual void onMiddleMouseDragged(const GuiEvent &event);
|
||||
/// @}
|
||||
|
||||
/// @name Gamepad Events
|
||||
/// These functions are called when the input event which is in the name of
|
||||
/// the function occurs.
|
||||
/// @{
|
||||
virtual bool onGamepadButtonDown(const GuiEvent &event); ///< Default behavior is call-through to onKeyDown
|
||||
virtual bool onGamepadButtonUp(const GuiEvent &event); ///< Default behavior is call-through to onKeyUp
|
||||
virtual bool onGamepadAxisUp(const GuiEvent &event);
|
||||
virtual bool onGamepadAxisDown(const GuiEvent &event);
|
||||
virtual bool onGamepadAxisLeft(const GuiEvent &event);
|
||||
virtual bool onGamepadAxisRight(const GuiEvent &event);
|
||||
virtual bool onGamepadTrigger(const GuiEvent &event);
|
||||
/// @}
|
||||
|
||||
/// @name Editor Mouse Events
|
||||
///
|
||||
/// These functions are called when the input event which is
|
||||
/// in the name of the function occurs. Conversely from normal
|
||||
/// mouse events, these have a boolean return value that, if
|
||||
/// they return true, the editor will NOT act on them or be able
|
||||
/// to respond to this particular event.
|
||||
///
|
||||
/// This is particularly useful for when writing controls so that
|
||||
/// they may become aware of the editor and allow customization
|
||||
/// of their data or appearance as if they were actually in use.
|
||||
/// For example, the GuiTabBookCtrl catches on mouse down to select
|
||||
/// a tab and NOT let the editor do any instant group manipulation.
|
||||
///
|
||||
/// @{
|
||||
|
||||
/// Called when a mouseDown event occurs on a control and the GUI editor is active
|
||||
/// @param event the GuiEvent which caused the call to this function
|
||||
/// @param offset the offset which is representative of the units x and y that the editor takes up on screen
|
||||
virtual bool onMouseDownEditor(const GuiEvent &event, Point2I offset) { return false; };
|
||||
|
||||
/// Called when a mouseUp event occurs on a control and the GUI editor is active
|
||||
/// @param event the GuiEvent which caused the call to this function
|
||||
/// @param offset the offset which is representative of the units x and y that the editor takes up on screen
|
||||
virtual bool onMouseUpEditor(const GuiEvent &event, Point2I offset) { return false; };
|
||||
|
||||
/// Called when a rightMouseDown event occurs on a control and the GUI editor is active
|
||||
/// @param event the GuiEvent which caused the call to this function
|
||||
/// @param offset the offset which is representative of the units x and y that the editor takes up on screen
|
||||
virtual bool onRightMouseDownEditor(const GuiEvent &event, Point2I offset) { return false; };
|
||||
|
||||
/// Called when a mouseDragged event occurs on a control and the GUI editor is active
|
||||
/// @param event the GuiEvent which caused the call to this function
|
||||
/// @param offset the offset which is representative of the units x and y that the editor takes up on screen
|
||||
virtual bool onMouseDraggedEditor(const GuiEvent &event, Point2I offset) { return false; };
|
||||
|
||||
/// @}
|
||||
|
||||
/// @name Tabs
|
||||
/// @{
|
||||
|
||||
/// Find the first tab-accessible child of this control
|
||||
virtual GuiControl* findFirstTabable();
|
||||
|
||||
/// Find the last tab-accessible child of this control
|
||||
/// @param firstCall Set to true to clear the global previous responder
|
||||
virtual GuiControl* findLastTabable(bool firstCall = true);
|
||||
|
||||
/// Find previous tab-accessible control with respect to the provided one
|
||||
/// @param curResponder Current control
|
||||
/// @param firstCall Set to true to clear the global previous responder
|
||||
virtual GuiControl* findPrevTabable(GuiControl *curResponder, bool firstCall = true);
|
||||
|
||||
/// Find next tab-accessible control with regards to the provided control.
|
||||
///
|
||||
/// @param curResponder Current control
|
||||
/// @param firstCall Set to true to clear the global current responder
|
||||
virtual GuiControl* findNextTabable(GuiControl *curResponder, bool firstCall = true);
|
||||
/// @}
|
||||
|
||||
/// Returns true if the provided control is a child (grandchild, or great-grandchild) of this one.
|
||||
///
|
||||
/// @param child Control to test
|
||||
virtual bool controlIsChild(GuiControl *child);
|
||||
|
||||
/// @name First Responder
|
||||
/// A first responder is the control which reacts first, in it's responder chain, to keyboard events
|
||||
/// The responder chain is set for each parent and so there is only one first responder amongst it's
|
||||
/// children.
|
||||
/// @{
|
||||
|
||||
/// Sets the first responder for child controls
|
||||
/// @param firstResponder First responder for this chain
|
||||
virtual void setFirstResponder(GuiControl *firstResponder);
|
||||
|
||||
/// Sets up this control to be the first in it's group to respond to an input event
|
||||
/// @param value True if this should be a first responder
|
||||
virtual void makeFirstResponder(bool value);
|
||||
|
||||
/// Returns true if this control is a first responder
|
||||
bool isFirstResponder();
|
||||
|
||||
/// Sets this object to be a first responder
|
||||
virtual void setFirstResponder();
|
||||
|
||||
/// Clears the first responder for this chain
|
||||
void clearFirstResponder();
|
||||
|
||||
/// Returns the first responder for this chain
|
||||
GuiControl *getFirstResponder() { return mFirstResponder; }
|
||||
|
||||
/// Occurs when the control gains first-responder status.
|
||||
virtual void onGainFirstResponder();
|
||||
|
||||
/// Occurs when the control loses first-responder status.
|
||||
virtual void onLoseFirstResponder();
|
||||
/// @}
|
||||
|
||||
/// @name Keyboard Events
|
||||
/// @{
|
||||
|
||||
/// Adds the accelerator key for this object to the canvas
|
||||
void addAcceleratorKey();
|
||||
|
||||
/// Adds this control's accelerator key to the accelerator map, and
|
||||
/// recursively tells all children to do the same.
|
||||
virtual void buildAcceleratorMap();
|
||||
|
||||
/// Occurs when the accelerator key for this control is pressed
|
||||
///
|
||||
/// @param index Index in the accelerator map of the key
|
||||
virtual void acceleratorKeyPress(U32 index);
|
||||
|
||||
/// Occurs when the accelerator key for this control is released
|
||||
///
|
||||
/// @param index Index in the accelerator map of the key
|
||||
virtual void acceleratorKeyRelease(U32 index);
|
||||
|
||||
/// Happens when a key is depressed
|
||||
/// @param event Event descriptor (which contains the key)
|
||||
virtual bool onKeyDown(const GuiEvent &event);
|
||||
|
||||
/// Happens when a key is released
|
||||
/// @param event Event descriptor (which contains the key)
|
||||
virtual bool onKeyUp(const GuiEvent &event);
|
||||
|
||||
/// Happens when a key is held down, resulting in repeated keystrokes.
|
||||
/// @param event Event descriptor (which contains the key)
|
||||
virtual bool onKeyRepeat(const GuiEvent &event);
|
||||
/// @}
|
||||
|
||||
/// Return the delegate used to render tooltips on this control.
|
||||
RenderTooltipDelegate& getRenderTooltipDelegate() { return mRenderTooltipDelegate; }
|
||||
const RenderTooltipDelegate& getRenderTooltipDelegate() const { return mRenderTooltipDelegate; }
|
||||
|
||||
/// Returns our tooltip profile (and finds the profile if it hasn't been set yet)
|
||||
GuiControlProfile* getTooltipProfile() { return mTooltipProfile; }
|
||||
|
||||
/// Sets the tooltip profile for this control.
|
||||
///
|
||||
/// @see GuiControlProfile
|
||||
/// @param prof Tooltip profile to apply
|
||||
void setTooltipProfile(GuiControlProfile *prof);
|
||||
|
||||
/// Returns our profile (and finds the profile if it hasn't been set yet)
|
||||
GuiControlProfile* getControlProfile() { return mProfile; }
|
||||
|
||||
/// Sets the control profile for this control.
|
||||
///
|
||||
/// @see GuiControlProfile
|
||||
/// @param prof Control profile to apply
|
||||
void setControlProfile(GuiControlProfile *prof);
|
||||
|
||||
/// Occurs when this control performs its "action"
|
||||
virtual void onAction();
|
||||
|
||||
/// @name Peer Messaging
|
||||
/// Used to send a message to other GUIControls which are children of the same parent.
|
||||
///
|
||||
/// This is mostly used by radio controls.
|
||||
/// @{
|
||||
void messageSiblings(S32 message); ///< Send a message to all siblings
|
||||
virtual void onMessage(GuiControl *sender, S32 msg); ///< Receive a message from another control
|
||||
/// @}
|
||||
|
||||
/// @name Canvas Events
|
||||
/// Functions called by the canvas
|
||||
/// @{
|
||||
|
||||
/// Called if this object is a dialog, when it is added to the visible layers
|
||||
virtual void onDialogPush();
|
||||
|
||||
/// Called if this object is a dialog, when it is removed from the visible layers
|
||||
virtual void onDialogPop();
|
||||
/// @}
|
||||
|
||||
/// Renders justified text using the profile.
|
||||
///
|
||||
/// @note This should move into the graphics library at some point
|
||||
void renderJustifiedText(Point2I offset, Point2I extent, const char *text);
|
||||
|
||||
/// Returns text clipped to fit within a pixel width. The clipping
|
||||
/// occurs on the right side and "..." is appended. It returns width
|
||||
/// of the final clipped text in pixels.
|
||||
U32 clipText( String &inOutText, U32 width ) const;
|
||||
|
||||
void inspectPostApply();
|
||||
void inspectPreApply();
|
||||
};
|
||||
|
||||
typedef GuiControl::horizSizingOptions GuiHorizontalSizing;
|
||||
typedef GuiControl::vertSizingOptions GuiVerticalSizing;
|
||||
|
||||
DefineEnumType( GuiHorizontalSizing );
|
||||
DefineEnumType( GuiVerticalSizing );
|
||||
|
||||
/// @}
|
||||
|
||||
#endif
|
||||
547
Engine/source/gui/core/guiDefaultControlRender.cpp
Normal file
547
Engine/source/gui/core/guiDefaultControlRender.cpp
Normal file
|
|
@ -0,0 +1,547 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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/core/guiDefaultControlRender.h"
|
||||
|
||||
#include "gui/core/guiTypes.h"
|
||||
#include "core/color.h"
|
||||
#include "math/mRect.h"
|
||||
#include "gfx/gfxDevice.h"
|
||||
#include "gfx/gfxDrawUtil.h"
|
||||
|
||||
|
||||
static ColorI colorLightGray(192, 192, 192);
|
||||
static ColorI colorGray(128, 128, 128);
|
||||
static ColorI colorDarkGray(64, 64, 64);
|
||||
static ColorI colorWhite(255,255,255);
|
||||
static ColorI colorBlack(0,0,0);
|
||||
|
||||
void renderRaisedBox( const RectI &bounds, GuiControlProfile *profile )
|
||||
{
|
||||
S32 l = bounds.point.x, r = bounds.point.x + bounds.extent.x - 1;
|
||||
S32 t = bounds.point.y, b = bounds.point.y + bounds.extent.y - 1;
|
||||
|
||||
GFX->getDrawUtil()->drawRectFill( bounds, profile->mFillColor);
|
||||
GFX->getDrawUtil()->drawLine(l, t, l, b - 1, colorWhite);
|
||||
GFX->getDrawUtil()->drawLine(l, t, r - 1, t, colorWhite);
|
||||
|
||||
GFX->getDrawUtil()->drawLine(l, b, r, b, colorBlack);
|
||||
GFX->getDrawUtil()->drawLine(r, b - 1, r, t, colorBlack);
|
||||
|
||||
GFX->getDrawUtil()->drawLine(l + 1, b - 1, r - 1, b - 1, profile->mBorderColor);
|
||||
GFX->getDrawUtil()->drawLine(r - 1, b - 2, r - 1, t + 1, profile->mBorderColor);
|
||||
}
|
||||
|
||||
void renderSlightlyRaisedBox( const RectI &bounds, GuiControlProfile *profile )
|
||||
{
|
||||
S32 l = bounds.point.x + 1, r = bounds.point.x + bounds.extent.x - 1;
|
||||
S32 t = bounds.point.y + 1, b = bounds.point.y + bounds.extent.y - 1;
|
||||
|
||||
GFXDrawUtil *drawer = GFX->getDrawUtil();
|
||||
drawer->drawRectFill( bounds, profile->mFillColor);
|
||||
drawer->drawLine(l, t, l, b, profile->mBorderColor);
|
||||
drawer->drawLine(l, t, r, t, profile->mBorderColor);
|
||||
drawer->drawLine(l + 1, b, r, b, profile->mBorderColor);
|
||||
drawer->drawLine(r, t + 1, r, b - 1, profile->mBorderColor);
|
||||
}
|
||||
|
||||
void renderLoweredBox( const RectI &bounds, GuiControlProfile *profile )
|
||||
{
|
||||
S32 l = bounds.point.x, r = bounds.point.x + bounds.extent.x - 1;
|
||||
S32 t = bounds.point.y, b = bounds.point.y + bounds.extent.y - 1;
|
||||
|
||||
GFX->getDrawUtil()->drawRectFill( bounds, profile->mFillColor);
|
||||
|
||||
GFX->getDrawUtil()->drawLine(l, b, r, b, colorWhite);
|
||||
GFX->getDrawUtil()->drawLine(r, b - 1, r, t, colorWhite);
|
||||
|
||||
GFX->getDrawUtil()->drawLine(l, t, r - 1, t, colorBlack);
|
||||
GFX->getDrawUtil()->drawLine(l, t + 1, l, b - 1, colorBlack);
|
||||
|
||||
GFX->getDrawUtil()->drawLine(l + 1, t + 1, r - 2, t + 1, profile->mBorderColor);
|
||||
GFX->getDrawUtil()->drawLine(l + 1, t + 2, l + 1, b - 2, profile->mBorderColor);
|
||||
}
|
||||
|
||||
void renderSlightlyLoweredBox( const RectI &bounds, GuiControlProfile *profile )
|
||||
{
|
||||
S32 l = bounds.point.x + 1, r = bounds.point.x + bounds.extent.x - 1;
|
||||
S32 t = bounds.point.y + 1, b = bounds.point.y + bounds.extent.y - 1;
|
||||
|
||||
GFX->getDrawUtil()->drawRectFill( bounds, profile->mFillColor);
|
||||
GFX->getDrawUtil()->drawLine(l, b, r, b, profile->mBorderColor);
|
||||
GFX->getDrawUtil()->drawLine(r, t, r, b - 1, profile->mBorderColor);
|
||||
GFX->getDrawUtil()->drawLine(l, t, l, b - 1, profile->mBorderColor);
|
||||
GFX->getDrawUtil()->drawLine(l + 1, t, r - 1, t, profile->mBorderColor);
|
||||
}
|
||||
|
||||
void renderBorder( const RectI &bounds, GuiControlProfile *profile )
|
||||
{
|
||||
S32 l = bounds.point.x, r = bounds.point.x + bounds.extent.x - 1;
|
||||
S32 t = bounds.point.y, b = bounds.point.y + bounds.extent.y - 1;
|
||||
|
||||
GFXDrawUtil *drawer = GFX->getDrawUtil();
|
||||
|
||||
switch(profile->mBorder)
|
||||
{
|
||||
case 1:
|
||||
drawer->drawRect(bounds, profile->mBorderColor);
|
||||
break;
|
||||
case 2:
|
||||
drawer->drawLine(l + 1, t + 1, l + 1, b - 2, profile->mBevelColorHL);
|
||||
drawer->drawLine(l + 2, t + 1, r - 2, t + 1, profile->mBevelColorHL);
|
||||
drawer->drawLine(r, t, r, b, profile->mBevelColorHL);
|
||||
drawer->drawLine(l, b, r - 1, b, profile->mBevelColorHL);
|
||||
drawer->drawLine(l, t, r - 1, t, profile->mBorderColorNA);
|
||||
drawer->drawLine(l, t + 1, l, b - 1, profile->mBorderColorNA);
|
||||
drawer->drawLine(l + 1, b - 1, r - 1, b - 1, profile->mBorderColorNA);
|
||||
drawer->drawLine(r - 1, t + 1, r - 1, b - 2, profile->mBorderColorNA);
|
||||
break;
|
||||
case 3:
|
||||
drawer->drawLine(l, b, r, b, profile->mBevelColorHL);
|
||||
drawer->drawLine(r, t, r, b - 1, profile->mBevelColorHL);
|
||||
drawer->drawLine(l + 1, b - 1, r - 1, b - 1, profile->mFillColor);
|
||||
drawer->drawLine(r - 1, t + 1, r - 1, b - 2, profile->mFillColor);
|
||||
drawer->drawLine(l, t, l, b - 1, profile->mBorderColorNA);
|
||||
drawer->drawLine(l + 1, t, r - 1, t, profile->mBorderColorNA);
|
||||
drawer->drawLine(l + 1, t + 1, l + 1, b - 2, profile->mBevelColorLL);
|
||||
drawer->drawLine(l + 2, t + 1, r - 2, t + 1, profile->mBevelColorLL);
|
||||
break;
|
||||
case 4:
|
||||
drawer->drawLine(l, t, l, b - 1, profile->mBevelColorHL);
|
||||
drawer->drawLine(l + 1, t, r, t, profile->mBevelColorHL);
|
||||
drawer->drawLine(l, b, r, b, profile->mBevelColorLL);
|
||||
drawer->drawLine(r, t + 1, r, b - 1, profile->mBevelColorLL);
|
||||
drawer->drawLine(l + 1, b - 1, r - 1, b - 1, profile->mBorderColor);
|
||||
drawer->drawLine(r - 1, t + 1, r - 1, b - 2, profile->mBorderColor);
|
||||
break;
|
||||
case 5:
|
||||
renderFilledBorder( bounds, profile );
|
||||
break;
|
||||
//
|
||||
case -1:
|
||||
// Draw a simple sizable border with corners
|
||||
// Taken from the 'Skinnable GUI Controls in TGE' resource by Justin DuJardin
|
||||
if(profile->mBitmapArrayRects.size() >= 8)
|
||||
{
|
||||
drawer->clearBitmapModulation();
|
||||
|
||||
RectI destRect;
|
||||
RectI stretchRect;
|
||||
RectI* mBitmapBounds = profile->mBitmapArrayRects.address();
|
||||
|
||||
// Indices into the bitmap array
|
||||
enum
|
||||
{
|
||||
BorderTopLeft = 0,
|
||||
BorderTop,
|
||||
BorderTopRight,
|
||||
BorderLeft,
|
||||
//Fill,
|
||||
BorderRight,
|
||||
BorderBottomLeft,
|
||||
BorderBottom,
|
||||
BorderBottomRight,
|
||||
NumBitmaps
|
||||
};
|
||||
|
||||
// Draw all corners first.
|
||||
|
||||
//top left border
|
||||
drawer->drawBitmapSR(profile->mTextureObject,Point2I(bounds.point.x,bounds.point.y),mBitmapBounds[BorderTopLeft]);
|
||||
//top right border
|
||||
drawer->drawBitmapSR(profile->mTextureObject,Point2I(bounds.point.x + bounds.extent.x - mBitmapBounds[BorderTopRight].extent.x,bounds.point.y),mBitmapBounds[BorderTopRight]);
|
||||
|
||||
//bottom left border
|
||||
drawer->drawBitmapSR(profile->mTextureObject,Point2I(bounds.point.x,bounds.point.y + bounds.extent.y - mBitmapBounds[BorderBottomLeft].extent.y),mBitmapBounds[BorderBottomLeft]);
|
||||
//bottom right border
|
||||
drawer->drawBitmapSR(profile->mTextureObject,Point2I(
|
||||
bounds.point.x + bounds.extent.x - mBitmapBounds[BorderBottomRight].extent.x,
|
||||
bounds.point.y + bounds.extent.y - mBitmapBounds[BorderBottomRight].extent.y),
|
||||
mBitmapBounds[BorderBottomRight]);
|
||||
|
||||
// End drawing corners
|
||||
|
||||
// Begin drawing sides and top stretched borders
|
||||
|
||||
//start with top line stretch
|
||||
destRect.point.x = bounds.point.x + mBitmapBounds[BorderTopLeft].extent.x;
|
||||
destRect.extent.x = bounds.extent.x - mBitmapBounds[BorderTopRight].extent.x - mBitmapBounds[BorderTopLeft].extent.x;
|
||||
destRect.extent.y = mBitmapBounds[BorderTop].extent.y;
|
||||
destRect.point.y = bounds.point.y;
|
||||
//stretch it
|
||||
stretchRect = mBitmapBounds[BorderTop];
|
||||
stretchRect.inset(1,0);
|
||||
//draw it
|
||||
drawer->drawBitmapStretchSR(profile->mTextureObject,destRect,stretchRect);
|
||||
//bottom line stretch
|
||||
destRect.point.x = bounds.point.x + mBitmapBounds[BorderBottomLeft].extent.x;
|
||||
destRect.extent.x = bounds.extent.x - mBitmapBounds[BorderBottomRight].extent.x - mBitmapBounds[BorderBottomLeft].extent.x;
|
||||
destRect.extent.y = mBitmapBounds[BorderBottom].extent.y;
|
||||
destRect.point.y = bounds.point.y + bounds.extent.y - mBitmapBounds[BorderBottom].extent.y;
|
||||
//stretch it
|
||||
stretchRect = mBitmapBounds[BorderBottom];
|
||||
stretchRect.inset(1,0);
|
||||
//draw it
|
||||
drawer->drawBitmapStretchSR(profile->mTextureObject,destRect,stretchRect);
|
||||
//left line stretch
|
||||
destRect.point.x = bounds.point.x;
|
||||
destRect.extent.x = mBitmapBounds[BorderLeft].extent.x;
|
||||
destRect.extent.y = bounds.extent.y - mBitmapBounds[BorderTopLeft].extent.y - mBitmapBounds[BorderBottomLeft].extent.y;
|
||||
destRect.point.y = bounds.point.y + mBitmapBounds[BorderTopLeft].extent.y;
|
||||
//stretch it
|
||||
stretchRect = mBitmapBounds[BorderLeft];
|
||||
stretchRect.inset(0,1);
|
||||
//draw it
|
||||
drawer->drawBitmapStretchSR(profile->mTextureObject,destRect,stretchRect);
|
||||
//right line stretch
|
||||
destRect.point.x = bounds.point.x + bounds.extent.x - mBitmapBounds[BorderRight].extent.x;
|
||||
destRect.extent.x = mBitmapBounds[BorderRight].extent.x;
|
||||
destRect.extent.y = bounds.extent.y - mBitmapBounds[BorderTopRight].extent.y - mBitmapBounds[BorderBottomRight].extent.y;
|
||||
destRect.point.y = bounds.point.y + mBitmapBounds[BorderTopRight].extent.y;
|
||||
//stretch it
|
||||
stretchRect = mBitmapBounds[BorderRight];
|
||||
stretchRect.inset(0,1);
|
||||
//draw it
|
||||
drawer->drawBitmapStretchSR(profile->mTextureObject,destRect,stretchRect);
|
||||
|
||||
// End drawing sides and top stretched borders
|
||||
break;
|
||||
}
|
||||
case -2:
|
||||
// Draw a simple sizable border with corners that is filled in
|
||||
renderSizableBitmapBordersFilled(bounds, 1, profile);
|
||||
break;
|
||||
case -3:
|
||||
// Draw a simple fixed height border with center fill horizontally.
|
||||
renderFixedBitmapBordersFilled( bounds, 1, profile );
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void renderFilledBorder( const RectI &bounds, GuiControlProfile *profile )
|
||||
{
|
||||
renderFilledBorder( bounds, profile->mBorderColor, profile->mFillColor, profile->mBorderThickness );
|
||||
}
|
||||
|
||||
void renderFilledBorder( const RectI &bounds, const ColorI &borderColor, const ColorI &fillColor, U32 thickness )
|
||||
{
|
||||
RectI fillBounds = bounds;
|
||||
fillBounds.inset( thickness, thickness );
|
||||
|
||||
GFX->getDrawUtil()->drawRectFill( bounds, borderColor );
|
||||
GFX->getDrawUtil()->drawRectFill( fillBounds, fillColor );
|
||||
}
|
||||
|
||||
// Render out the sizable bitmap borders based on a multiplier into the bitmap array
|
||||
// Based on the 'Skinnable GUI Controls in TGE' resource by Justin DuJardin
|
||||
void renderSizableBitmapBordersFilled( const RectI &bounds, S32 baseMultiplier, GuiControlProfile *profile)
|
||||
{
|
||||
// Indices into the bitmap array
|
||||
S32 numBitmaps = 9;
|
||||
S32 borderTopLeft = numBitmaps * baseMultiplier - numBitmaps;
|
||||
S32 borderTop = 1 + borderTopLeft;
|
||||
S32 borderTopRight = 2 + borderTopLeft;
|
||||
S32 borderLeft = 3 + borderTopLeft;
|
||||
S32 fill = 4 + borderTopLeft;
|
||||
S32 borderRight = 5 + borderTopLeft;
|
||||
S32 borderBottomLeft = 6 + borderTopLeft;
|
||||
S32 borderBottom = 7 + borderTopLeft;
|
||||
S32 borderBottomRight = 8 + borderTopLeft;
|
||||
|
||||
GFXDrawUtil *drawer = GFX->getDrawUtil();
|
||||
|
||||
drawer->clearBitmapModulation();
|
||||
|
||||
if(profile->mBitmapArrayRects.size() >= (numBitmaps * baseMultiplier))
|
||||
{
|
||||
RectI destRect;
|
||||
RectI stretchRect;
|
||||
RectI* mBitmapBounds = profile->mBitmapArrayRects.address();
|
||||
|
||||
// Draw all corners first.
|
||||
|
||||
//top left border
|
||||
drawer->drawBitmapSR(profile->mTextureObject,Point2I(bounds.point.x,bounds.point.y),mBitmapBounds[borderTopLeft]);
|
||||
//top right border
|
||||
drawer->drawBitmapSR(profile->mTextureObject,Point2I(bounds.point.x + bounds.extent.x - mBitmapBounds[borderTopRight].extent.x,bounds.point.y),mBitmapBounds[borderTopRight]);
|
||||
|
||||
//bottom left border
|
||||
drawer->drawBitmapSR(profile->mTextureObject,Point2I(bounds.point.x,bounds.point.y + bounds.extent.y - mBitmapBounds[borderBottomLeft].extent.y),mBitmapBounds[borderBottomLeft]);
|
||||
//bottom right border
|
||||
drawer->drawBitmapSR(profile->mTextureObject,Point2I(
|
||||
bounds.point.x + bounds.extent.x - mBitmapBounds[borderBottomRight].extent.x,
|
||||
bounds.point.y + bounds.extent.y - mBitmapBounds[borderBottomRight].extent.y),
|
||||
mBitmapBounds[borderBottomRight]);
|
||||
|
||||
// End drawing corners
|
||||
|
||||
// Begin drawing sides and top stretched borders
|
||||
|
||||
//start with top line stretch
|
||||
destRect.point.x = bounds.point.x + mBitmapBounds[borderTopLeft].extent.x;
|
||||
destRect.extent.x = bounds.extent.x - mBitmapBounds[borderTopRight].extent.x - mBitmapBounds[borderTopLeft].extent.x;
|
||||
destRect.extent.y = mBitmapBounds[borderTop].extent.y;
|
||||
destRect.point.y = bounds.point.y;
|
||||
//stretch it
|
||||
stretchRect = mBitmapBounds[borderTop];
|
||||
stretchRect.inset(1,0);
|
||||
//draw it
|
||||
drawer->drawBitmapStretchSR(profile->mTextureObject,destRect,stretchRect);
|
||||
//bottom line stretch
|
||||
destRect.point.x = bounds.point.x + mBitmapBounds[borderBottomLeft].extent.x;
|
||||
destRect.extent.x = bounds.extent.x - mBitmapBounds[borderBottomRight].extent.x - mBitmapBounds[borderBottomLeft].extent.x;
|
||||
destRect.extent.y = mBitmapBounds[borderBottom].extent.y;
|
||||
destRect.point.y = bounds.point.y + bounds.extent.y - mBitmapBounds[borderBottom].extent.y;
|
||||
//stretch it
|
||||
stretchRect = mBitmapBounds[borderBottom];
|
||||
stretchRect.inset(1,0);
|
||||
//draw it
|
||||
drawer->drawBitmapStretchSR(profile->mTextureObject,destRect,stretchRect);
|
||||
//left line stretch
|
||||
destRect.point.x = bounds.point.x;
|
||||
destRect.extent.x = mBitmapBounds[borderLeft].extent.x;
|
||||
destRect.extent.y = bounds.extent.y - mBitmapBounds[borderTopLeft].extent.y - mBitmapBounds[borderBottomLeft].extent.y;
|
||||
destRect.point.y = bounds.point.y + mBitmapBounds[borderTopLeft].extent.y;
|
||||
//stretch it
|
||||
stretchRect = mBitmapBounds[borderLeft];
|
||||
stretchRect.inset(0,1);
|
||||
//draw it
|
||||
drawer->drawBitmapStretchSR(profile->mTextureObject,destRect,stretchRect);
|
||||
//right line stretch
|
||||
destRect.point.x = bounds.point.x + bounds.extent.x - mBitmapBounds[borderRight].extent.x;
|
||||
destRect.extent.x = mBitmapBounds[borderRight].extent.x;
|
||||
destRect.extent.y = bounds.extent.y - mBitmapBounds[borderTopRight].extent.y - mBitmapBounds[borderBottomRight].extent.y;
|
||||
destRect.point.y = bounds.point.y + mBitmapBounds[borderTopRight].extent.y;
|
||||
//stretch it
|
||||
stretchRect = mBitmapBounds[borderRight];
|
||||
stretchRect.inset(0,1);
|
||||
//draw it
|
||||
drawer->drawBitmapStretchSR(profile->mTextureObject,destRect,stretchRect);
|
||||
//fill stretch
|
||||
destRect.point.x = bounds.point.x + mBitmapBounds[borderLeft].extent.x;
|
||||
destRect.extent.x = (bounds.extent.x) - mBitmapBounds[borderLeft].extent.x - mBitmapBounds[borderRight].extent.x;
|
||||
destRect.extent.y = bounds.extent.y - mBitmapBounds[borderTop].extent.y - mBitmapBounds[borderBottom].extent.y;
|
||||
destRect.point.y = bounds.point.y + mBitmapBounds[borderTop].extent.y;
|
||||
//stretch it
|
||||
stretchRect = mBitmapBounds[fill];
|
||||
stretchRect.inset(1,1);
|
||||
//draw it
|
||||
drawer->drawBitmapStretchSR(profile->mTextureObject,destRect,stretchRect);
|
||||
|
||||
// End drawing sides and top stretched borders
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Render out the sizable bitmap borders based on a multiplier into the bitmap array
|
||||
// Based on the 'Skinnable GUI Controls in TGE' resource by Justin DuJardin
|
||||
void renderSizableBitmapBordersFilledIndex( const RectI &bounds, S32 startIndex, GuiControlProfile *profile )
|
||||
{
|
||||
// Indices into the bitmap array
|
||||
S32 numBitmaps = 9;
|
||||
S32 borderTopLeft = startIndex;
|
||||
S32 borderTop = 1 + borderTopLeft;
|
||||
S32 borderTopRight = 2 + borderTopLeft;
|
||||
S32 borderLeft = 3 + borderTopLeft;
|
||||
S32 fill = 4 + borderTopLeft;
|
||||
S32 borderRight = 5 + borderTopLeft;
|
||||
S32 borderBottomLeft = 6 + borderTopLeft;
|
||||
S32 borderBottom = 7 + borderTopLeft;
|
||||
S32 borderBottomRight = 8 + borderTopLeft;
|
||||
|
||||
GFXDrawUtil *drawer = GFX->getDrawUtil();
|
||||
|
||||
drawer->clearBitmapModulation();
|
||||
if(profile->mBitmapArrayRects.size() >= (startIndex + numBitmaps))
|
||||
{
|
||||
RectI destRect;
|
||||
RectI stretchRect;
|
||||
RectI* mBitmapBounds = profile->mBitmapArrayRects.address();
|
||||
|
||||
// Draw all corners first.
|
||||
|
||||
//top left border
|
||||
drawer->drawBitmapSR(profile->mTextureObject,Point2I(bounds.point.x,bounds.point.y),mBitmapBounds[borderTopLeft]);
|
||||
//top right border
|
||||
drawer->drawBitmapSR(profile->mTextureObject,Point2I(bounds.point.x + bounds.extent.x - mBitmapBounds[borderTopRight].extent.x,bounds.point.y),mBitmapBounds[borderTopRight]);
|
||||
|
||||
//bottom left border
|
||||
drawer->drawBitmapSR(profile->mTextureObject,Point2I(bounds.point.x,bounds.point.y + bounds.extent.y - mBitmapBounds[borderBottomLeft].extent.y),mBitmapBounds[borderBottomLeft]);
|
||||
//bottom right border
|
||||
drawer->drawBitmapSR(profile->mTextureObject,Point2I(
|
||||
bounds.point.x + bounds.extent.x - mBitmapBounds[borderBottomRight].extent.x,
|
||||
bounds.point.y + bounds.extent.y - mBitmapBounds[borderBottomRight].extent.y),
|
||||
mBitmapBounds[borderBottomRight]);
|
||||
|
||||
// End drawing corners
|
||||
|
||||
// Begin drawing sides and top stretched borders
|
||||
|
||||
//start with top line stretch
|
||||
destRect.point.x = bounds.point.x + mBitmapBounds[borderTopLeft].extent.x;
|
||||
destRect.extent.x = bounds.extent.x - mBitmapBounds[borderTopRight].extent.x - mBitmapBounds[borderTopLeft].extent.x;
|
||||
destRect.extent.y = mBitmapBounds[borderTop].extent.y;
|
||||
destRect.point.y = bounds.point.y;
|
||||
//stretch it
|
||||
stretchRect = mBitmapBounds[borderTop];
|
||||
stretchRect.inset(1,0);
|
||||
//draw it
|
||||
drawer->drawBitmapStretchSR(profile->mTextureObject,destRect,stretchRect);
|
||||
//bottom line stretch
|
||||
destRect.point.x = bounds.point.x + mBitmapBounds[borderBottomLeft].extent.x;
|
||||
destRect.extent.x = bounds.extent.x - mBitmapBounds[borderBottomRight].extent.x - mBitmapBounds[borderBottomLeft].extent.x;
|
||||
destRect.extent.y = mBitmapBounds[borderBottom].extent.y;
|
||||
destRect.point.y = bounds.point.y + bounds.extent.y - mBitmapBounds[borderBottom].extent.y;
|
||||
//stretch it
|
||||
stretchRect = mBitmapBounds[borderBottom];
|
||||
stretchRect.inset(1,0);
|
||||
//draw it
|
||||
drawer->drawBitmapStretchSR(profile->mTextureObject,destRect,stretchRect);
|
||||
//left line stretch
|
||||
destRect.point.x = bounds.point.x;
|
||||
destRect.extent.x = mBitmapBounds[borderLeft].extent.x;
|
||||
destRect.extent.y = bounds.extent.y - mBitmapBounds[borderTopLeft].extent.y - mBitmapBounds[borderBottomLeft].extent.y;
|
||||
destRect.point.y = bounds.point.y + mBitmapBounds[borderTopLeft].extent.y;
|
||||
//stretch it
|
||||
stretchRect = mBitmapBounds[borderLeft];
|
||||
stretchRect.inset(0,1);
|
||||
//draw it
|
||||
drawer->drawBitmapStretchSR(profile->mTextureObject,destRect,stretchRect);
|
||||
//left line stretch
|
||||
destRect.point.x = bounds.point.x + bounds.extent.x - mBitmapBounds[borderRight].extent.x;
|
||||
destRect.extent.x = mBitmapBounds[borderRight].extent.x;
|
||||
destRect.extent.y = bounds.extent.y - mBitmapBounds[borderTopRight].extent.y - mBitmapBounds[borderBottomRight].extent.y;
|
||||
destRect.point.y = bounds.point.y + mBitmapBounds[borderTopRight].extent.y;
|
||||
//stretch it
|
||||
stretchRect = mBitmapBounds[borderRight];
|
||||
stretchRect.inset(0,1);
|
||||
//draw it
|
||||
drawer->drawBitmapStretchSR(profile->mTextureObject,destRect,stretchRect);
|
||||
//fill stretch
|
||||
destRect.point.x = bounds.point.x + mBitmapBounds[borderLeft].extent.x;
|
||||
destRect.extent.x = (bounds.extent.x) - mBitmapBounds[borderLeft].extent.x - mBitmapBounds[borderRight].extent.x;
|
||||
destRect.extent.y = bounds.extent.y - mBitmapBounds[borderTop].extent.y - mBitmapBounds[borderBottom].extent.y;
|
||||
destRect.point.y = bounds.point.y + mBitmapBounds[borderTop].extent.y;
|
||||
//stretch it
|
||||
stretchRect = mBitmapBounds[fill];
|
||||
stretchRect.inset(1,1);
|
||||
//draw it
|
||||
drawer->drawBitmapStretchSR(profile->mTextureObject,destRect,stretchRect);
|
||||
|
||||
// End drawing sides and top stretched borders
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Render out the fixed bitmap borders based on a multiplier into the bitmap array
|
||||
// It renders left and right caps, with a sizable fill area in the middle to reach
|
||||
// the x extent. It does not stretch in the y direction.
|
||||
void renderFixedBitmapBordersFilled( const RectI &bounds, S32 baseMultiplier, GuiControlProfile *profile )
|
||||
{
|
||||
// Indices into the bitmap array
|
||||
S32 numBitmaps = 3;
|
||||
S32 borderLeft = numBitmaps * baseMultiplier - numBitmaps;
|
||||
S32 fill = 1 + borderLeft;
|
||||
S32 borderRight = 2 + borderLeft;
|
||||
|
||||
GFXDrawUtil *drawer = GFX->getDrawUtil();
|
||||
|
||||
drawer->clearBitmapModulation();
|
||||
if(profile->mBitmapArrayRects.size() >= (numBitmaps * baseMultiplier))
|
||||
{
|
||||
RectI destRect;
|
||||
RectI stretchRect;
|
||||
RectI* mBitmapBounds = profile->mBitmapArrayRects.address();
|
||||
|
||||
// Draw all corners first.
|
||||
|
||||
//left border
|
||||
drawer->drawBitmapSR(profile->mTextureObject,Point2I(bounds.point.x,bounds.point.y),mBitmapBounds[borderLeft]);
|
||||
//right border
|
||||
drawer->drawBitmapSR(profile->mTextureObject,Point2I(bounds.point.x + bounds.extent.x - mBitmapBounds[borderRight].extent.x,bounds.point.y),mBitmapBounds[borderRight]);
|
||||
|
||||
// End drawing corners
|
||||
|
||||
// Begin drawing fill
|
||||
|
||||
//fill stretch
|
||||
destRect.point.x = bounds.point.x + mBitmapBounds[borderLeft].extent.x;
|
||||
destRect.extent.x = (bounds.extent.x) - mBitmapBounds[borderLeft].extent.x - mBitmapBounds[borderRight].extent.x;
|
||||
destRect.extent.y = mBitmapBounds[fill].extent.y;
|
||||
destRect.point.y = bounds.point.y;
|
||||
//stretch it
|
||||
stretchRect = mBitmapBounds[fill];
|
||||
stretchRect.inset(1,0);
|
||||
//draw it
|
||||
drawer->drawBitmapStretchSR(profile->mTextureObject,destRect,stretchRect);
|
||||
|
||||
// End drawing fill
|
||||
}
|
||||
}
|
||||
|
||||
// Render out the fixed bitmap borders based on a multiplier into the bitmap array
|
||||
// It renders left and right caps, with a sizable fill area in the middle to reach
|
||||
// the x extent. It does not stretch in the y direction.
|
||||
void renderFixedBitmapBordersFilledIndex( const RectI &bounds, S32 startIndex, GuiControlProfile *profile )
|
||||
{
|
||||
// Indices into the bitmap array
|
||||
S32 numBitmaps = 3;
|
||||
S32 borderLeft = startIndex;
|
||||
S32 fill = 1 + startIndex;
|
||||
S32 borderRight = 2 + startIndex;
|
||||
|
||||
GFXDrawUtil *drawer = GFX->getDrawUtil();
|
||||
drawer->clearBitmapModulation();
|
||||
if(profile->mBitmapArrayRects.size() >= (startIndex + numBitmaps))
|
||||
{
|
||||
RectI destRect;
|
||||
RectI stretchRect;
|
||||
RectI* mBitmapBounds = profile->mBitmapArrayRects.address();
|
||||
|
||||
// Draw all corners first.
|
||||
|
||||
//left border
|
||||
drawer->drawBitmapSR(profile->mTextureObject,Point2I(bounds.point.x,bounds.point.y),mBitmapBounds[borderLeft]);
|
||||
//right border
|
||||
drawer->drawBitmapSR(profile->mTextureObject,Point2I(bounds.point.x + bounds.extent.x - mBitmapBounds[borderRight].extent.x,bounds.point.y),mBitmapBounds[borderRight]);
|
||||
|
||||
// End drawing corners
|
||||
|
||||
// Begin drawing fill
|
||||
|
||||
//fill stretch
|
||||
destRect.point.x = bounds.point.x + mBitmapBounds[borderLeft].extent.x;
|
||||
destRect.extent.x = (bounds.extent.x) - mBitmapBounds[borderLeft].extent.x - mBitmapBounds[borderRight].extent.x;
|
||||
destRect.extent.y = mBitmapBounds[fill].extent.y;
|
||||
destRect.point.y = bounds.point.y;
|
||||
//stretch it
|
||||
stretchRect = mBitmapBounds[fill];
|
||||
stretchRect.inset(1,0);
|
||||
//draw it
|
||||
drawer->drawBitmapStretchSR(profile->mTextureObject,destRect,stretchRect);
|
||||
|
||||
// End drawing fill
|
||||
}
|
||||
}
|
||||
45
Engine/source/gui/core/guiDefaultControlRender.h
Normal file
45
Engine/source/gui/core/guiDefaultControlRender.h
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _H_GUIDEFAULTCONTROLRENDER_
|
||||
#define _H_GUIDEFAULTCONTROLRENDER_
|
||||
|
||||
#ifndef _MRECT_H_
|
||||
#include "math/mRect.h"
|
||||
#endif
|
||||
|
||||
class GuiControlProfile;
|
||||
class ColorI;
|
||||
|
||||
void renderRaisedBox( const RectI &bounds, GuiControlProfile *profile);
|
||||
void renderSlightlyRaisedBox( const RectI &bounds, GuiControlProfile *profile);
|
||||
void renderLoweredBox( const RectI &bounds, GuiControlProfile *profile);
|
||||
void renderSlightlyLoweredBox( const RectI &bounds, GuiControlProfile *profile);
|
||||
void renderBorder( const RectI &bounds, GuiControlProfile *profile);
|
||||
void renderFilledBorder( const RectI &bounds, GuiControlProfile *profile );
|
||||
void renderFilledBorder( const RectI &bounds, const ColorI &borderColor, const ColorI &fillColor, U32 thickness = 1 );
|
||||
void renderSizableBitmapBordersFilled( const RectI &bounds, S32 baseMultiplier, GuiControlProfile *profile); // Added
|
||||
void renderSizableBitmapBordersFilledIndex( const RectI &bounds, S32 startIndex, GuiControlProfile *profile);
|
||||
void renderFixedBitmapBordersFilled( const RectI &bounds, S32 baseMultiplier, GuiControlProfile *profile); // Added
|
||||
void renderFixedBitmapBordersFilled( const RectI &bounds, S32 startIndex, GuiControlProfile *profile);
|
||||
|
||||
#endif
|
||||
285
Engine/source/gui/core/guiScriptNotifyControl.cpp
Normal file
285
Engine/source/gui/core/guiScriptNotifyControl.cpp
Normal file
|
|
@ -0,0 +1,285 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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 "gui/core/guiScriptNotifyControl.h"
|
||||
#include "console/consoleTypes.h"
|
||||
#include "console/engineAPI.h"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
IMPLEMENT_CONOBJECT(GuiScriptNotifyCtrl);
|
||||
|
||||
ConsoleDocClass( GuiScriptNotifyCtrl,
|
||||
"@brief A control which adds several reactions to other GUIs via callbacks.\n\n"
|
||||
|
||||
"GuiScriptNotifyCtrl does not exist to render anything. When parented or made a child of "
|
||||
"other controls, you can toggle flags on or off to make use of its specialized callbacks. "
|
||||
"Normally these callbacks are used as utility functions by the GUI Editor, or other container "
|
||||
"classes. However, for very fancy GUI work where controls interact with each other "
|
||||
"constantly, this is a handy utility to make use of.\n\n "
|
||||
|
||||
"@tsexample\n"
|
||||
"// Common member fields left out for sake of example\n"
|
||||
"new GuiScriptNotifyCtrl()\n"
|
||||
"{\n"
|
||||
" onChildAdded = \"0\";\n"
|
||||
" onChildRemoved = \"0\";\n"
|
||||
" onChildResized = \"0\";\n"
|
||||
" onParentResized = \"0\";\n"
|
||||
"};\n"
|
||||
"@endtsexample\n\n"
|
||||
|
||||
"@ingroup GuiUtil\n");
|
||||
|
||||
GuiScriptNotifyCtrl::GuiScriptNotifyCtrl()
|
||||
{
|
||||
mOnChildAdded = false;
|
||||
mOnChildRemoved = false;
|
||||
mOnResize = false;
|
||||
mOnChildResized = false;
|
||||
mOnParentResized = false;
|
||||
}
|
||||
|
||||
GuiScriptNotifyCtrl::~GuiScriptNotifyCtrl()
|
||||
{
|
||||
}
|
||||
|
||||
void GuiScriptNotifyCtrl::initPersistFields()
|
||||
{
|
||||
// Callbacks Group
|
||||
addGroup("Callbacks");
|
||||
addField("onChildAdded", TypeBool, Offset( mOnChildAdded, GuiScriptNotifyCtrl ), "Enables/disables onChildAdded callback" );
|
||||
addField("onChildRemoved", TypeBool, Offset( mOnChildRemoved, GuiScriptNotifyCtrl ), "Enables/disables onChildRemoved callback" );
|
||||
addField("onChildResized", TypeBool, Offset( mOnChildResized, GuiScriptNotifyCtrl ), "Enables/disables onChildResized callback" );
|
||||
addField("onParentResized", TypeBool, Offset( mOnParentResized, GuiScriptNotifyCtrl ), "Enables/disables onParentResized callback" );
|
||||
addField("onResize", TypeBool, Offset( mOnResize, GuiScriptNotifyCtrl ), "Enables/disables onResize callback" );
|
||||
addField("onLoseFirstResponder", TypeBool, Offset( mOnLoseFirstResponder, GuiScriptNotifyCtrl ), "Enables/disables onLoseFirstResponder callback" );
|
||||
addField("onGainFirstResponder", TypeBool, Offset( mOnGainFirstResponder, GuiScriptNotifyCtrl ), "Enables/disables onGainFirstResponder callback" );
|
||||
endGroup("Callbacks");
|
||||
|
||||
Parent::initPersistFields();
|
||||
}
|
||||
|
||||
IMPLEMENT_CALLBACK( GuiScriptNotifyCtrl, onResize, void, ( SimObjectId ID ), ( ID ),
|
||||
"Called when this GUI is resized.\n\n"
|
||||
"@param ID Unique object ID assigned when created (%this in script).\n"
|
||||
);
|
||||
IMPLEMENT_CALLBACK( GuiScriptNotifyCtrl, onChildAdded, void, ( SimObjectId ID, SimObjectId childID ), ( ID, childID ),
|
||||
"Called when a child is added to this GUI.\n\n"
|
||||
"@param ID Unique object ID assigned when created (%this in script).\n"
|
||||
"@param childID Unique object ID of child being added.\n"
|
||||
);
|
||||
IMPLEMENT_CALLBACK( GuiScriptNotifyCtrl, onChildRemoved, void, ( SimObjectId ID, SimObjectId childID ), ( ID, childID ),
|
||||
"Called when a child is removed from this GUI.\n\n"
|
||||
"@param ID Unique object ID assigned when created (%this in script).\n"
|
||||
"@param childID Unique object ID of child being removed.\n"
|
||||
);
|
||||
IMPLEMENT_CALLBACK( GuiScriptNotifyCtrl, onChildResized, void, ( SimObjectId ID, SimObjectId childID ), ( ID, childID ),
|
||||
"Called when a child is of this GUI is being resized.\n\n"
|
||||
"@param ID Unique object ID assigned when created (%this in script).\n"
|
||||
"@param childID Unique object ID of child being resized.\n"
|
||||
);
|
||||
IMPLEMENT_CALLBACK( GuiScriptNotifyCtrl, onParentResized, void, ( SimObjectId ID ), ( ID ),
|
||||
"Called when this GUI's parent is resized.\n\n"
|
||||
"@param ID Unique object ID assigned when created (%this in script).\n"
|
||||
);
|
||||
IMPLEMENT_CALLBACK( GuiScriptNotifyCtrl, onLoseFirstResponder, void, ( SimObjectId ID ), ( ID ),
|
||||
"Called when this GUI loses focus.\n\n"
|
||||
"@param ID Unique object ID assigned when created (%this in script).\n"
|
||||
);
|
||||
IMPLEMENT_CALLBACK( GuiScriptNotifyCtrl, onGainFirstResponder, void, ( SimObjectId ID ), ( ID ),
|
||||
"Called when this GUI gains focus.\n\n"
|
||||
"@param ID Unique object ID assigned when created (%this in script).\n"
|
||||
);
|
||||
|
||||
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- //
|
||||
void GuiScriptNotifyCtrl::onChildAdded( GuiControl *child )
|
||||
{
|
||||
Parent::onChildAdded( child );
|
||||
|
||||
// Call Script.
|
||||
if( mOnChildAdded )
|
||||
onChildAdded_callback(getId(), child->getId());
|
||||
}
|
||||
|
||||
void GuiScriptNotifyCtrl::onChildRemoved( GuiControl *child )
|
||||
{
|
||||
Parent::onChildRemoved( child );
|
||||
|
||||
// Call Script.
|
||||
if( mOnChildRemoved )
|
||||
onChildRemoved_callback(getId(), child->getId());
|
||||
}
|
||||
//----------------------------------------------------------------
|
||||
|
||||
bool GuiScriptNotifyCtrl::resize(const Point2I &newPosition, const Point2I &newExtent)
|
||||
{
|
||||
if( !Parent::resize( newPosition, newExtent ) )
|
||||
return false;
|
||||
|
||||
// Call Script.
|
||||
if( mOnResize )
|
||||
onResize_callback(getId());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GuiScriptNotifyCtrl::childResized(GuiScriptNotifyCtrl *child)
|
||||
{
|
||||
Parent::childResized( child );
|
||||
|
||||
// Call Script.
|
||||
if( mOnChildResized )
|
||||
onChildResized_callback(getId(), child->getId());
|
||||
}
|
||||
|
||||
void GuiScriptNotifyCtrl::parentResized(const RectI &oldParentRect, const RectI &newParentRect)
|
||||
{
|
||||
Parent::parentResized( oldParentRect, newParentRect );
|
||||
|
||||
// Call Script.
|
||||
if( mOnParentResized )
|
||||
onParentResized_callback(getId());
|
||||
}
|
||||
|
||||
void GuiScriptNotifyCtrl::onLoseFirstResponder()
|
||||
{
|
||||
Parent::onLoseFirstResponder();
|
||||
|
||||
// Call Script.
|
||||
if( mOnLoseFirstResponder )
|
||||
onLoseFirstResponder_callback(getId());
|
||||
}
|
||||
|
||||
void GuiScriptNotifyCtrl::setFirstResponder( GuiControl* firstResponder )
|
||||
{
|
||||
Parent::setFirstResponder( firstResponder );
|
||||
|
||||
// Call Script.
|
||||
if( mOnGainFirstResponder && isFirstResponder() )
|
||||
onGainFirstResponder_callback(getId());
|
||||
}
|
||||
|
||||
void GuiScriptNotifyCtrl::setFirstResponder()
|
||||
{
|
||||
Parent::setFirstResponder();
|
||||
|
||||
// Call Script.
|
||||
if( mOnGainFirstResponder && isFirstResponder() )
|
||||
onGainFirstResponder_callback(getId());
|
||||
}
|
||||
|
||||
void GuiScriptNotifyCtrl::onMessage(GuiScriptNotifyCtrl *sender, S32 msg)
|
||||
{
|
||||
Parent::onMessage( sender, msg );
|
||||
}
|
||||
|
||||
void GuiScriptNotifyCtrl::onDialogPush()
|
||||
{
|
||||
Parent::onDialogPush();
|
||||
}
|
||||
|
||||
void GuiScriptNotifyCtrl::onDialogPop()
|
||||
{
|
||||
Parent::onDialogPop();
|
||||
}
|
||||
|
||||
|
||||
//void GuiScriptNotifyCtrl::onMouseUp(const GuiEvent &event)
|
||||
//{
|
||||
//}
|
||||
//
|
||||
//void GuiScriptNotifyCtrl::onMouseDown(const GuiEvent &event)
|
||||
//{
|
||||
//}
|
||||
//
|
||||
//void GuiScriptNotifyCtrl::onMouseMove(const GuiEvent &event)
|
||||
//{
|
||||
//}
|
||||
//
|
||||
//void GuiScriptNotifyCtrl::onMouseDragged(const GuiEvent &event)
|
||||
//{
|
||||
//}
|
||||
//
|
||||
//void GuiScriptNotifyCtrl::onMouseEnter(const GuiEvent &)
|
||||
//{
|
||||
//}
|
||||
//
|
||||
//void GuiScriptNotifyCtrl::onMouseLeave(const GuiEvent &)
|
||||
//{
|
||||
//}
|
||||
//
|
||||
//bool GuiScriptNotifyCtrl::onMouseWheelUp( const GuiEvent &event )
|
||||
//{
|
||||
//}
|
||||
//
|
||||
//bool GuiScriptNotifyCtrl::onMouseWheelDown( const GuiEvent &event )
|
||||
//{
|
||||
//}
|
||||
//
|
||||
//void GuiScriptNotifyCtrl::onRightMouseDown(const GuiEvent &)
|
||||
//{
|
||||
//}
|
||||
//
|
||||
//void GuiScriptNotifyCtrl::onRightMouseUp(const GuiEvent &)
|
||||
//{
|
||||
//}
|
||||
//
|
||||
//void GuiScriptNotifyCtrl::onRightMouseDragged(const GuiEvent &)
|
||||
//{
|
||||
//}
|
||||
//
|
||||
//void GuiScriptNotifyCtrl::onMiddleMouseDown(const GuiEvent &)
|
||||
//{
|
||||
//}
|
||||
//
|
||||
//void GuiScriptNotifyCtrl::onMiddleMouseUp(const GuiEvent &)
|
||||
//{
|
||||
//}
|
||||
//
|
||||
//void GuiScriptNotifyCtrl::onMiddleMouseDragged(const GuiEvent &)
|
||||
//{
|
||||
//}
|
||||
//void GuiScriptNotifyCtrl::onMouseDownEditor(const GuiEvent &event, Point2I offset)
|
||||
//{
|
||||
//}
|
||||
//void GuiScriptNotifyCtrl::onRightMouseDownEditor(const GuiEvent &event, Point2I offset)
|
||||
//{
|
||||
//}
|
||||
|
||||
//bool GuiScriptNotifyCtrl::onKeyDown(const GuiEvent &event)
|
||||
//{
|
||||
// if ( Parent::onKeyDown( event ) )
|
||||
// return true;
|
||||
//}
|
||||
//
|
||||
//bool GuiScriptNotifyCtrl::onKeyRepeat(const GuiEvent &event)
|
||||
//{
|
||||
// // default to just another key down.
|
||||
// return onKeyDown(event);
|
||||
//}
|
||||
//
|
||||
//bool GuiScriptNotifyCtrl::onKeyUp(const GuiEvent &event)
|
||||
//{
|
||||
// if ( Parent::onKeyUp( event ) )
|
||||
// return true;
|
||||
//}
|
||||
115
Engine/source/gui/core/guiScriptNotifyControl.h
Normal file
115
Engine/source/gui/core/guiScriptNotifyControl.h
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GUISCRIPTNOTIFYCTRL_H_
|
||||
#define _GUISCRIPTNOTIFYCTRL_H_
|
||||
|
||||
#ifndef _GUICONTROL_H_
|
||||
#include "gui/core/guiControl.h"
|
||||
#endif
|
||||
|
||||
class GuiScriptNotifyCtrl : public GuiControl
|
||||
{
|
||||
private:
|
||||
typedef GuiControl Parent;
|
||||
public:
|
||||
|
||||
/// @name Event Callbacks
|
||||
/// @{
|
||||
bool mOnChildAdded; ///< Script Notify : onAddObject(%object)
|
||||
bool mOnChildRemoved; ///< Script Notify : onRemoveObject(%object)
|
||||
bool mOnResize; ///< Script Notify : onResize()
|
||||
bool mOnChildResized; ///< Script Notify : onChildResized(%child)
|
||||
bool mOnParentResized; ///< Script Notify : onParentResized()
|
||||
bool mOnLoseFirstResponder; ///< Script Notify : onLoseFirstResponder()
|
||||
bool mOnGainFirstResponder; ///< Script Notify : onGainFirstResponder()
|
||||
/// @}
|
||||
|
||||
public:
|
||||
/// @name Initialization
|
||||
/// @{
|
||||
DECLARE_CONOBJECT(GuiScriptNotifyCtrl);
|
||||
DECLARE_CATEGORY( "Gui Other Script" );
|
||||
DECLARE_DESCRIPTION( "A control that implements various script callbacks for\n"
|
||||
"certain GUI events." );
|
||||
|
||||
GuiScriptNotifyCtrl();
|
||||
virtual ~GuiScriptNotifyCtrl();
|
||||
static void initPersistFields();
|
||||
|
||||
virtual bool resize(const Point2I &newPosition, const Point2I &newExtent);
|
||||
virtual void childResized(GuiScriptNotifyCtrl *child);
|
||||
virtual void parentResized(const RectI &oldParentRect, const RectI &newParentRect);
|
||||
virtual void onChildRemoved( GuiControl *child );
|
||||
virtual void onChildAdded( GuiControl *child );
|
||||
|
||||
DECLARE_CALLBACK(void, onResize, (SimObjectId ID) );
|
||||
DECLARE_CALLBACK(void, onChildAdded, (SimObjectId ID, SimObjectId childID));
|
||||
DECLARE_CALLBACK(void, onChildRemoved, (SimObjectId ID, SimObjectId childID));
|
||||
DECLARE_CALLBACK(void, onChildResized, (SimObjectId ID, SimObjectId childID));
|
||||
DECLARE_CALLBACK(void, onParentResized, (SimObjectId ID));
|
||||
DECLARE_CALLBACK(void, onLoseFirstResponder, (SimObjectId ID));
|
||||
DECLARE_CALLBACK(void, onGainFirstResponder, (SimObjectId ID));
|
||||
|
||||
|
||||
|
||||
|
||||
//virtual void onMouseUp(const GuiEvent &event);
|
||||
//virtual void onMouseDown(const GuiEvent &event);
|
||||
//virtual void onMouseMove(const GuiEvent &event);
|
||||
//virtual void onMouseDragged(const GuiEvent &event);
|
||||
//virtual void onMouseEnter(const GuiEvent &event);
|
||||
//virtual void onMouseLeave(const GuiEvent &event);
|
||||
|
||||
//virtual bool onMouseWheelUp(const GuiEvent &event);
|
||||
//virtual bool onMouseWheelDown(const GuiEvent &event);
|
||||
|
||||
//virtual void onRightMouseDown(const GuiEvent &event);
|
||||
//virtual void onRightMouseUp(const GuiEvent &event);
|
||||
//virtual void onRightMouseDragged(const GuiEvent &event);
|
||||
|
||||
//virtual void onMiddleMouseDown(const GuiEvent &event);
|
||||
//virtual void onMiddleMouseUp(const GuiEvent &event);
|
||||
//virtual void onMiddleMouseDragged(const GuiEvent &event);
|
||||
|
||||
//virtual void onMouseDownEditor(const GuiEvent &event, Point2I offset);
|
||||
//virtual void onRightMouseDownEditor(const GuiEvent &event, Point2I offset);
|
||||
|
||||
virtual void setFirstResponder(GuiControl *firstResponder);
|
||||
virtual void setFirstResponder();
|
||||
void clearFirstResponder();
|
||||
virtual void onLoseFirstResponder();
|
||||
|
||||
//virtual void acceleratorKeyPress(U32 index);
|
||||
//virtual void acceleratorKeyRelease(U32 index);
|
||||
//virtual bool onKeyDown(const GuiEvent &event);
|
||||
//virtual bool onKeyUp(const GuiEvent &event);
|
||||
//virtual bool onKeyRepeat(const GuiEvent &event);
|
||||
|
||||
virtual void onMessage(GuiScriptNotifyCtrl *sender, S32 msg); ///< Receive a message from another control
|
||||
|
||||
virtual void onDialogPush();
|
||||
virtual void onDialogPop();
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
737
Engine/source/gui/core/guiTypes.cpp
Normal file
737
Engine/source/gui/core/guiTypes.cpp
Normal file
|
|
@ -0,0 +1,737 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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 "platform/types.h"
|
||||
#include "console/consoleTypes.h"
|
||||
#include "console/console.h"
|
||||
#include "gui/core/guiTypes.h"
|
||||
#include "gui/core/guiControl.h"
|
||||
#include "gfx/gFont.h"
|
||||
#include "gfx/bitmap/gBitmap.h"
|
||||
#include "gfx/gfxDevice.h"
|
||||
#include "gfx/gfxDrawUtil.h"
|
||||
#include "sfx/sfxTrack.h"
|
||||
#include "sfx/sfxTypes.h"
|
||||
#include "console/engineAPI.h"
|
||||
|
||||
//#define DEBUG_SPEW
|
||||
|
||||
|
||||
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- //
|
||||
IMPLEMENT_CONOBJECT(GuiCursor);
|
||||
|
||||
ConsoleDocClass( GuiCursor,
|
||||
"@brief Acts as a skin for the cursor, where each GuiCursor object can have its own look and click-zone.\n\n"
|
||||
|
||||
"GuiCursors act as skins for the cursor in the game, where each individual GuiCursor can have its own defined imagemap,\n"
|
||||
"click zone and render offset. This allows a game to easily support a wide range of cursors. The active cursor can de changed\n"
|
||||
"for each Canvas using %canvasObj.setCursor(GuiCursor);."
|
||||
|
||||
"@tsexample\n"
|
||||
"new GuiCursor(DefaultCursor)\n"
|
||||
"{\n"
|
||||
" hotSpot = \"1 1\";\n"
|
||||
" renderOffset = \"0 0\";\n"
|
||||
" bitmapName = \"~/art/gui/images/defaultCursor\";\n"
|
||||
"};\n"
|
||||
"@endtsexample\n\n"
|
||||
"@see GuiCanvas\n\n"
|
||||
"@ingroup GuiCore\n"
|
||||
);
|
||||
|
||||
GFX_ImplementTextureProfile(GFXGuiCursorProfile,
|
||||
GFXTextureProfile::DiffuseMap,
|
||||
GFXTextureProfile::PreserveSize |
|
||||
GFXTextureProfile::Static,
|
||||
GFXTextureProfile::None);
|
||||
GFX_ImplementTextureProfile(GFXDefaultGUIProfile,
|
||||
GFXTextureProfile::DiffuseMap,
|
||||
GFXTextureProfile::PreserveSize |
|
||||
GFXTextureProfile::Static |
|
||||
GFXTextureProfile::NoPadding,
|
||||
GFXTextureProfile::None);
|
||||
|
||||
|
||||
GuiCursor::GuiCursor()
|
||||
{
|
||||
mHotSpot.set(0,0);
|
||||
mRenderOffset.set(0.0f,0.0f);
|
||||
mExtent.set(1,1);
|
||||
mTextureObject = NULL;
|
||||
}
|
||||
|
||||
GuiCursor::~GuiCursor()
|
||||
{
|
||||
}
|
||||
|
||||
void GuiCursor::initPersistFields()
|
||||
{
|
||||
addField("hotSpot", TypePoint2I, Offset(mHotSpot, GuiCursor), "The location of the cursor's hot spot (which pixel carries the click).");
|
||||
addField("renderOffset",TypePoint2F, Offset(mRenderOffset, GuiCursor), "Offset of the bitmap, where 0 signifies left edge of the bitmap, 1, the right. Similarly for the Y-component.");
|
||||
addField("bitmapName", TypeFilename, Offset(mBitmapName, GuiCursor), "File name of the bitmap for the cursor.");
|
||||
Parent::initPersistFields();
|
||||
}
|
||||
|
||||
bool GuiCursor::onAdd()
|
||||
{
|
||||
if(!Parent::onAdd())
|
||||
return false;
|
||||
|
||||
Sim::getGuiDataGroup()->addObject(this);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GuiCursor::onRemove()
|
||||
{
|
||||
Parent::onRemove();
|
||||
}
|
||||
|
||||
void GuiCursor::render(const Point2I &pos)
|
||||
{
|
||||
if (!mTextureObject && mBitmapName && mBitmapName[0])
|
||||
{
|
||||
mTextureObject.set( mBitmapName, &GFXGuiCursorProfile, avar("%s() - mTextureObject (line %d)", __FUNCTION__, __LINE__));
|
||||
if(!mTextureObject)
|
||||
return;
|
||||
mExtent.set(mTextureObject->getWidth(), mTextureObject->getHeight());
|
||||
}
|
||||
|
||||
// Render the cursor centered according to dimensions of texture
|
||||
S32 texWidth = mTextureObject.getWidth();
|
||||
S32 texHeight = mTextureObject.getHeight();
|
||||
|
||||
Point2I renderPos = pos;
|
||||
renderPos.x -= (S32)( texWidth * mRenderOffset.x );
|
||||
renderPos.y -= (S32)( texHeight * mRenderOffset.y );
|
||||
|
||||
GFX->getDrawUtil()->clearBitmapModulation();
|
||||
GFX->getDrawUtil()->drawBitmap(mTextureObject, renderPos);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
IMPLEMENT_CONOBJECT(GuiControlProfile);
|
||||
|
||||
ConsoleDocClass( GuiControlProfile,
|
||||
"@brief A collection of properties that determine control behavior and rendering.\n"
|
||||
"@ingroup GuiCore\n"
|
||||
|
||||
""
|
||||
);
|
||||
|
||||
ImplementEnumType( GuiAlignmentType,
|
||||
"\n\n"
|
||||
"@ingroup GuiCore" )
|
||||
{ GuiControlProfile::LeftJustify, "Left" },
|
||||
{ GuiControlProfile::CenterJustify, "Center" },
|
||||
{ GuiControlProfile::RightJustify, "Right" },
|
||||
{ GuiControlProfile::TopJustify, "Top" },
|
||||
{ GuiControlProfile::BottomJustify, "Bottom" }
|
||||
EndImplementEnumType;
|
||||
|
||||
ImplementEnumType( GuiFontCharset,
|
||||
"\n\n"
|
||||
"@ingroup GuiCore" )
|
||||
{ TGE_ANSI_CHARSET, "ANSI" },
|
||||
{ TGE_SYMBOL_CHARSET, "SYMBOL" },
|
||||
{ TGE_SHIFTJIS_CHARSET, "SHIFTJIS" },
|
||||
{ TGE_HANGEUL_CHARSET, "HANGEUL" },
|
||||
{ TGE_HANGUL_CHARSET, "HANGUL" },
|
||||
{ TGE_GB2312_CHARSET, "GB2312" },
|
||||
{ TGE_CHINESEBIG5_CHARSET, "CHINESEBIG5" },
|
||||
{ TGE_OEM_CHARSET, "OEM" },
|
||||
{ TGE_JOHAB_CHARSET, "JOHAB" },
|
||||
{ TGE_HEBREW_CHARSET, "HEBREW" },
|
||||
{ TGE_ARABIC_CHARSET, "ARABIC" },
|
||||
{ TGE_GREEK_CHARSET, "GREEK" },
|
||||
{ TGE_TURKISH_CHARSET, "TURKISH" },
|
||||
{ TGE_VIETNAMESE_CHARSET, "VIETNAMESE" },
|
||||
{ TGE_THAI_CHARSET, "THAI" },
|
||||
{ TGE_EASTEUROPE_CHARSET, "EASTEUROPE" },
|
||||
{ TGE_RUSSIAN_CHARSET, "RUSSIAN" },
|
||||
{ TGE_MAC_CHARSET, "MAC" },
|
||||
{ TGE_BALTIC_CHARSET, "BALTIC" },
|
||||
EndImplementEnumType;
|
||||
|
||||
|
||||
StringTableEntry GuiControlProfile::sFontCacheDirectory = "";
|
||||
|
||||
void GuiControlProfile::setBitmapHandle(GFXTexHandle handle)
|
||||
{
|
||||
mTextureObject = handle;
|
||||
|
||||
mBitmapName = StringTable->insert("texhandle");
|
||||
}
|
||||
|
||||
bool GuiControlProfile::protectedSetBitmap( void *object, const char *index, const char *data )
|
||||
{
|
||||
GuiControlProfile *profile = static_cast<GuiControlProfile*>( object );
|
||||
|
||||
profile->mBitmapName = StringTable->insert(data);
|
||||
|
||||
if ( !profile->isProperlyAdded() )
|
||||
return false;
|
||||
|
||||
if( profile->mLoadCount > 0 )
|
||||
{
|
||||
profile->mBitmapArrayRects.clear();
|
||||
profile->mTextureObject = NULL;
|
||||
|
||||
//verify the bitmap
|
||||
if (profile->mBitmapName && profile->mBitmapName[0] && dStricmp(profile->mBitmapName, "texhandle") != 0 &&
|
||||
!profile->mTextureObject.set( profile->mBitmapName, &GFXDefaultPersistentProfile, avar("%s() - mTextureObject (line %d)", __FUNCTION__, __LINE__) ))
|
||||
Con::errorf("Failed to load profile bitmap (%s)",profile->mBitmapName);
|
||||
|
||||
// If we've got a special border, make sure it's usable.
|
||||
//if( profile->mBorder == -1 || profile->mBorder == -2 )
|
||||
profile->constructBitmapArray();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* GuiControlProfile::protectedGetSoundButtonDown( void* object, const char* data )
|
||||
{
|
||||
GuiControlProfile* profile = reinterpret_cast< GuiControlProfile* >( object );
|
||||
|
||||
SFXTrack* track = profile->mSoundButtonDown;
|
||||
if( !track )
|
||||
return "";
|
||||
|
||||
return track->getName();
|
||||
}
|
||||
|
||||
bool GuiControlProfile::protectedSetSoundButtonDown( void* object, const char* index, const char* data )
|
||||
{
|
||||
GuiControlProfile* profile = reinterpret_cast< GuiControlProfile* >( object );
|
||||
|
||||
SFXTrack* track = NULL;
|
||||
if( data && data[ 0] && !Sim::findObject( data, track ) )
|
||||
{
|
||||
Con::errorf( "GuiControlProfile::protectedSetSoundButtonDown - no SFXTrack '%s'", data );
|
||||
return false;
|
||||
}
|
||||
|
||||
profile->mSoundButtonDown = track;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* GuiControlProfile::protectedGetSoundButtonOver( void* object, const char* data )
|
||||
{
|
||||
GuiControlProfile* profile = reinterpret_cast< GuiControlProfile* >( object );
|
||||
|
||||
SFXTrack* track = profile->mSoundButtonOver;
|
||||
if( !track )
|
||||
return "";
|
||||
|
||||
return track->getName();
|
||||
}
|
||||
|
||||
bool GuiControlProfile::protectedSetSoundButtonOver( void* object, const char* index, const char* data )
|
||||
{
|
||||
GuiControlProfile* profile = reinterpret_cast< GuiControlProfile* >( object );
|
||||
|
||||
SFXTrack* track = NULL;
|
||||
if( data && data[ 0] && !Sim::findObject( data, track ) )
|
||||
{
|
||||
Con::errorf( "GuiControlProfile::protectedSetSoundButtonOver - no SFXTrack '%s'", data );
|
||||
return false;
|
||||
}
|
||||
|
||||
profile->mSoundButtonOver = track;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
GuiControlProfile::GuiControlProfile(void) :
|
||||
mFillColor(255,0,255,255),
|
||||
mFillColorHL(255,0,255,255),
|
||||
mFillColorNA(255,0,255,255),
|
||||
mFillColorSEL(255,0,255,255),
|
||||
mBorderColor(255,0,255,255),
|
||||
mBorderColorHL(255,0,255,255),
|
||||
mBorderColorNA(255,0,255,255),
|
||||
mBevelColorHL(255,0,255,255),
|
||||
mBevelColorLL(255,0,255,255),
|
||||
// initialize these references to locations in the font colors array
|
||||
// the array is initialized below.
|
||||
mFontColor(mFontColors[BaseColor]),
|
||||
mFontColorHL(mFontColors[ColorHL]),
|
||||
mFontColorNA(mFontColors[ColorNA]),
|
||||
mFontColorSEL(mFontColors[ColorSEL]),
|
||||
mCursorColor(255,0,255,255),
|
||||
mTextOffset(0,0),
|
||||
mBitmapArrayRects(0)
|
||||
{
|
||||
mLoadCount = 0;
|
||||
mUseCount = 0;
|
||||
|
||||
// event focus behavior
|
||||
mTabable = false;
|
||||
mCanKeyFocus = false;
|
||||
mModal = false;
|
||||
|
||||
// fill and border
|
||||
mOpaque = false;
|
||||
mBorder = 1;
|
||||
mBorderThickness = 1;
|
||||
|
||||
// font members
|
||||
mFontType = "Arial";
|
||||
mFontSize = 10;
|
||||
|
||||
for(U32 i = 0; i < 10; i++)
|
||||
mFontColors[i].set(255,0,255,255);
|
||||
|
||||
mFontCharset = TGE_ANSI_CHARSET;
|
||||
|
||||
// sizing and alignment
|
||||
mAlignment = LeftJustify;
|
||||
mAutoSizeWidth = false;
|
||||
mAutoSizeHeight= false;
|
||||
mReturnTab = false;
|
||||
mNumbersOnly = false;
|
||||
mMouseOverSelected = false;
|
||||
|
||||
// bitmap members
|
||||
mBitmapName = NULL;
|
||||
mUseBitmapArray = false;
|
||||
mTextureObject = NULL; // initialized in incLoadCount()
|
||||
|
||||
mChildrenProfileName = NULL;
|
||||
mChildrenProfile = NULL;
|
||||
|
||||
// inherit/copy values from GuiDefaultProfile
|
||||
GuiControlProfile *def = dynamic_cast<GuiControlProfile*>(Sim::findObject("GuiDefaultProfile"));
|
||||
if (def)
|
||||
{
|
||||
mTabable = def->mTabable;
|
||||
mCanKeyFocus = def->mCanKeyFocus;
|
||||
|
||||
mOpaque = def->mOpaque;
|
||||
mFillColor = def->mFillColor;
|
||||
mFillColorHL = def->mFillColorHL;
|
||||
mFillColorNA = def->mFillColorNA;
|
||||
mFillColorSEL = def->mFillColorSEL;
|
||||
|
||||
mBorder = def->mBorder;
|
||||
mBorderThickness = def->mBorderThickness;
|
||||
mBorderColor = def->mBorderColor;
|
||||
mBorderColorHL = def->mBorderColorHL;
|
||||
mBorderColorNA = def->mBorderColorNA;
|
||||
|
||||
mBevelColorHL = def->mBevelColorHL;
|
||||
mBevelColorLL = def->mBevelColorLL;
|
||||
|
||||
// default font
|
||||
mFontType = def->mFontType;
|
||||
mFontSize = def->mFontSize;
|
||||
mFontCharset = def->mFontCharset;
|
||||
|
||||
for(U32 i = 0; i < 10; i++)
|
||||
mFontColors[i] = def->mFontColors[i];
|
||||
|
||||
// default bitmap
|
||||
mBitmapName = def->mBitmapName;
|
||||
mUseBitmapArray = def->mUseBitmapArray;
|
||||
mTextOffset = def->mTextOffset;
|
||||
|
||||
// default sound
|
||||
mSoundButtonDown = def->mSoundButtonDown;
|
||||
mSoundButtonOver = def->mSoundButtonOver;
|
||||
|
||||
//used by GuiTextCtrl
|
||||
mModal = def->mModal;
|
||||
mAlignment = def->mAlignment;
|
||||
mAutoSizeWidth = def->mAutoSizeWidth;
|
||||
mAutoSizeHeight= def->mAutoSizeHeight;
|
||||
mReturnTab = def->mReturnTab;
|
||||
mNumbersOnly = def->mNumbersOnly;
|
||||
mCursorColor = def->mCursorColor;
|
||||
mChildrenProfileName = def->mChildrenProfileName;
|
||||
setChildrenProfile(def->mChildrenProfile);
|
||||
}
|
||||
}
|
||||
|
||||
GuiControlProfile::~GuiControlProfile()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void GuiControlProfile::initPersistFields()
|
||||
{
|
||||
addGroup( "Behavior" );
|
||||
|
||||
addField( "tab", TypeBool, Offset(mTabable, GuiControlProfile));
|
||||
addField("canKeyFocus", TypeBool, Offset(mCanKeyFocus, GuiControlProfile),
|
||||
"Whether the control can have the keyboard focus." );
|
||||
addField("mouseOverSelected", TypeBool, Offset(mMouseOverSelected, GuiControlProfile));
|
||||
addField("modal", TypeBool, Offset(mModal, GuiControlProfile));
|
||||
|
||||
endGroup( "Behavior" );
|
||||
|
||||
addGroup( "Appearance" );
|
||||
|
||||
addField("opaque", TypeBool, Offset(mOpaque, GuiControlProfile));
|
||||
addField("fillColor", TypeColorI, Offset(mFillColor, GuiControlProfile));
|
||||
addField("fillColorHL", TypeColorI, Offset(mFillColorHL, GuiControlProfile));
|
||||
addField("fillColorNA", TypeColorI, Offset(mFillColorNA, GuiControlProfile));
|
||||
addField("fillColorSEL", TypeColorI, Offset(mFillColorSEL, GuiControlProfile));
|
||||
addField("border", TypeS32, Offset(mBorder, GuiControlProfile),
|
||||
"Border type (0=no border)." );
|
||||
addField("borderThickness",TypeS32, Offset(mBorderThickness, GuiControlProfile),
|
||||
"Thickness of border in pixels." );
|
||||
addField("borderColor", TypeColorI, Offset(mBorderColor, GuiControlProfile),
|
||||
"Color to draw border with." );
|
||||
addField("borderColorHL", TypeColorI, Offset(mBorderColorHL, GuiControlProfile));
|
||||
addField("borderColorNA", TypeColorI, Offset(mBorderColorNA, GuiControlProfile));
|
||||
|
||||
addField("bevelColorHL", TypeColorI, Offset(mBevelColorHL, GuiControlProfile));
|
||||
addField("bevelColorLL", TypeColorI, Offset(mBevelColorLL, GuiControlProfile));
|
||||
|
||||
endGroup( "Appearance" );
|
||||
|
||||
addGroup( "Text" );
|
||||
|
||||
addField("fontType", TypeString, Offset(mFontType, GuiControlProfile),
|
||||
"Name of font family and typeface (e.g. \"Arial Bold\")." );
|
||||
addField("fontSize", TypeS32, Offset(mFontSize, GuiControlProfile),
|
||||
"Font size in points." );
|
||||
addField("fontCharset", TYPEID< FontCharset >(), Offset(mFontCharset, GuiControlProfile) );
|
||||
addField("fontColors", TypeColorI, Offset(mFontColors, GuiControlProfile), 10,
|
||||
"Font colors to use for different text types/states." );
|
||||
addField("fontColor", TypeColorI, Offset(mFontColors[BaseColor], GuiControlProfile),
|
||||
"Font color for normal text (same as fontColors[0])." );
|
||||
addField("fontColorHL", TypeColorI, Offset(mFontColors[ColorHL], GuiControlProfile),
|
||||
"Font color for highlighted text (same as fontColors[1])." );
|
||||
addField("fontColorNA", TypeColorI, Offset(mFontColors[ColorNA], GuiControlProfile),
|
||||
"Font color when control is not active/disabled (same as fontColors[2])." );
|
||||
addField("fontColorSEL", TypeColorI, Offset(mFontColors[ColorSEL], GuiControlProfile),
|
||||
"Font color for selected text (same as fontColors[3])." );
|
||||
addField("fontColorLink", TypeColorI, Offset(mFontColors[ColorUser0], GuiControlProfile),
|
||||
"Font color for links in text (same as fontColors[4])." );
|
||||
addField("fontColorLinkHL", TypeColorI, Offset(mFontColors[ColorUser1], GuiControlProfile),
|
||||
"Font color for highlighted links in text (same as fontColors[5])." );
|
||||
|
||||
addField( "justify", TYPEID< GuiControlProfile::AlignmentType >(), Offset(mAlignment, GuiControlProfile),
|
||||
"Horizontal alignment for text." );
|
||||
addField( "textOffset", TypePoint2I, Offset(mTextOffset, GuiControlProfile));
|
||||
addField( "autoSizeWidth", TypeBool, Offset(mAutoSizeWidth, GuiControlProfile),
|
||||
"Automatically adjust width of control to fit contents." );
|
||||
addField("autoSizeHeight",TypeBool, Offset(mAutoSizeHeight, GuiControlProfile),
|
||||
"Automatically adjust height of control to fit contents." );
|
||||
addField("returnTab", TypeBool, Offset(mReturnTab, GuiControlProfile),
|
||||
"Whether to add automatic tab event when return is pressed so focus moves on to next control (GuiTextEditCtrl)." );
|
||||
addField("numbersOnly", TypeBool, Offset(mNumbersOnly, GuiControlProfile),
|
||||
"Whether control should only accept numerical data (GuiTextEditCtrl)." );
|
||||
addField("cursorColor", TypeColorI, Offset(mCursorColor, GuiControlProfile),
|
||||
"Color to use for the text cursor." );
|
||||
|
||||
endGroup( "Text" );
|
||||
|
||||
addGroup( "Misc" );
|
||||
|
||||
addProtectedField( "bitmap", TypeFilename, Offset(mBitmapName, GuiControlProfile),
|
||||
&GuiControlProfile::protectedSetBitmap, &defaultProtectedGetFn,
|
||||
"Texture to use for rendering control." );
|
||||
addField("hasBitmapArray", TypeBool, Offset(mUseBitmapArray, GuiControlProfile),
|
||||
"If true, 'bitmap' is an array of images." );
|
||||
|
||||
addProtectedField( "soundButtonDown", TypeSFXTrackName, Offset(mSoundButtonDown, GuiControlProfile),
|
||||
&GuiControlProfile::protectedSetSoundButtonDown, &GuiControlProfile::protectedGetSoundButtonDown,
|
||||
"Sound to play when mouse has been pressed on control." );
|
||||
addProtectedField( "soundButtonOver", TypeSFXTrackName, Offset(mSoundButtonOver, GuiControlProfile),
|
||||
&GuiControlProfile::protectedSetSoundButtonOver, &GuiControlProfile::protectedGetSoundButtonOver,
|
||||
"Sound to play when mouse is hovering over control." );
|
||||
addField("profileForChildren", TypeString, Offset(mChildrenProfileName, GuiControlProfile));
|
||||
|
||||
endGroup( "Misc" );
|
||||
|
||||
addField( "category", TypeRealString, Offset( mCategory, GuiControlProfile ),
|
||||
"Category under which the profile will appear in the editor."
|
||||
);
|
||||
|
||||
Parent::initPersistFields();
|
||||
}
|
||||
|
||||
bool GuiControlProfile::onAdd()
|
||||
{
|
||||
if(!Parent::onAdd())
|
||||
return false;
|
||||
|
||||
Sim::getGuiDataGroup()->addObject(this);
|
||||
|
||||
// Make sure we have an up-to-date children profile
|
||||
getChildrenProfile();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GuiControlProfile::onStaticModified(const char* slotName, const char* newValue)
|
||||
{
|
||||
if( mLoadCount > 0 )
|
||||
{
|
||||
if ( !dStricmp(slotName, "fontType") ||
|
||||
!dStricmp(slotName, "fontCharset") ||
|
||||
!dStricmp(slotName, "fontSize" ) )
|
||||
{
|
||||
// Reload the font
|
||||
mFont = GFont::create(mFontType, mFontSize, sFontCacheDirectory, mFontCharset);
|
||||
if ( mFont == NULL )
|
||||
Con::errorf("Failed to load/create profile font (%s/%d)", mFontType, mFontSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GuiControlProfile::onDeleteNotify(SimObject *object)
|
||||
{
|
||||
if (object == mChildrenProfile)
|
||||
mChildrenProfile = NULL;
|
||||
}
|
||||
|
||||
GuiControlProfile* GuiControlProfile::getChildrenProfile()
|
||||
{
|
||||
// We can early out if we still have a valid profile
|
||||
if (mChildrenProfile)
|
||||
return mChildrenProfile;
|
||||
|
||||
// Attempt to find the profile specified
|
||||
if (mChildrenProfileName)
|
||||
{
|
||||
GuiControlProfile *profile = dynamic_cast<GuiControlProfile*>(Sim::findObject( mChildrenProfileName ));
|
||||
|
||||
if( profile )
|
||||
setChildrenProfile(profile);
|
||||
}
|
||||
|
||||
return mChildrenProfile;
|
||||
}
|
||||
|
||||
void GuiControlProfile::setChildrenProfile(GuiControlProfile *prof)
|
||||
{
|
||||
if(prof == mChildrenProfile)
|
||||
return;
|
||||
|
||||
// Clear the delete notification we previously set up
|
||||
if (mChildrenProfile)
|
||||
clearNotify(mChildrenProfile);
|
||||
|
||||
mChildrenProfile = prof;
|
||||
|
||||
// Make sure that the new profile will notify us when it is deleted
|
||||
if (mChildrenProfile)
|
||||
deleteNotify(mChildrenProfile);
|
||||
}
|
||||
|
||||
RectI GuiControlProfile::getBitmapArrayRect(U32 i)
|
||||
{
|
||||
if(!mBitmapArrayRects.size())
|
||||
constructBitmapArray();
|
||||
|
||||
if( i >= mBitmapArrayRects.size())
|
||||
return RectI(0,0,0,0);
|
||||
|
||||
return mBitmapArrayRects[i];
|
||||
}
|
||||
|
||||
S32 GuiControlProfile::constructBitmapArray()
|
||||
{
|
||||
if(mBitmapArrayRects.size())
|
||||
return mBitmapArrayRects.size();
|
||||
|
||||
if( mTextureObject.isNull() )
|
||||
{
|
||||
if ( !mBitmapName || !mBitmapName[0] || !mTextureObject.set( mBitmapName, &GFXDefaultPersistentProfile, avar("%s() - mTextureObject (line %d)", __FUNCTION__, __LINE__) ))
|
||||
return 0;
|
||||
}
|
||||
|
||||
GBitmap *bmp = mTextureObject->getBitmap();
|
||||
|
||||
//get the separator color
|
||||
ColorI sepColor;
|
||||
if ( !bmp || !bmp->getColor( 0, 0, sepColor ) )
|
||||
{
|
||||
Con::errorf("Failed to create bitmap array from %s for profile %s - couldn't ascertain seperator color!", mBitmapName, getName());
|
||||
AssertFatal( false, avar("Failed to create bitmap array from %s for profile %s - couldn't ascertain seperator color!", mBitmapName, getName()));
|
||||
return 0;
|
||||
}
|
||||
|
||||
//now loop through all the scroll pieces, and find the bounding rectangle for each piece in each state
|
||||
S32 curY = 0;
|
||||
|
||||
// ascertain the height of this row...
|
||||
ColorI color;
|
||||
mBitmapArrayRects.clear();
|
||||
while(curY < bmp->getHeight())
|
||||
{
|
||||
// skip any sep colors
|
||||
bmp->getColor( 0, curY, color);
|
||||
if(color == sepColor)
|
||||
{
|
||||
curY++;
|
||||
continue;
|
||||
}
|
||||
// ok, process left to right, grabbing bitmaps as we go...
|
||||
S32 curX = 0;
|
||||
while(curX < bmp->getWidth())
|
||||
{
|
||||
bmp->getColor(curX, curY, color);
|
||||
if(color == sepColor)
|
||||
{
|
||||
curX++;
|
||||
continue;
|
||||
}
|
||||
S32 startX = curX;
|
||||
while(curX < bmp->getWidth())
|
||||
{
|
||||
bmp->getColor(curX, curY, color);
|
||||
if(color == sepColor)
|
||||
break;
|
||||
curX++;
|
||||
}
|
||||
S32 stepY = curY;
|
||||
while(stepY < bmp->getHeight())
|
||||
{
|
||||
bmp->getColor(startX, stepY, color);
|
||||
if(color == sepColor)
|
||||
break;
|
||||
stepY++;
|
||||
}
|
||||
mBitmapArrayRects.push_back(RectI(startX, curY, curX - startX, stepY - curY));
|
||||
}
|
||||
// ok, now skip to the next separation color on column 0
|
||||
while(curY < bmp->getHeight())
|
||||
{
|
||||
bmp->getColor(0, curY, color);
|
||||
if(color == sepColor)
|
||||
break;
|
||||
curY++;
|
||||
}
|
||||
}
|
||||
return mBitmapArrayRects.size();
|
||||
}
|
||||
|
||||
void GuiControlProfile::incLoadCount()
|
||||
{
|
||||
if( !mLoadCount )
|
||||
{
|
||||
#ifdef DEBUG_SPEW
|
||||
Platform::outputDebugString( "[GuiControlProfile] Loading profile %i:%s (%s:%s)",
|
||||
getId(), getClassName(), getName(), getInternalName() );
|
||||
#endif
|
||||
|
||||
sFontCacheDirectory = Con::getVariable( "$GUI::fontCacheDirectory" );
|
||||
|
||||
// Load font (if not already loaded).
|
||||
|
||||
if( mFont == NULL )
|
||||
loadFont();
|
||||
|
||||
//
|
||||
|
||||
if (mBitmapName && mBitmapName[0] && dStricmp(mBitmapName, "texhandle") != 0 &&
|
||||
!mTextureObject.set( mBitmapName, &GFXDefaultPersistentProfile, avar("%s() - mTextureObject (line %d)", __FUNCTION__, __LINE__) ))
|
||||
Con::errorf("Failed to load profile bitmap (%s)",mBitmapName);
|
||||
|
||||
constructBitmapArray();
|
||||
}
|
||||
|
||||
mLoadCount ++;
|
||||
|
||||
// Quick check to make sure our children profile is up-to-date
|
||||
getChildrenProfile();
|
||||
}
|
||||
|
||||
void GuiControlProfile::decLoadCount()
|
||||
{
|
||||
AssertFatal( mLoadCount, "GuiControlProfile::decLoadCount - zero load count" );
|
||||
if(!mLoadCount)
|
||||
return;
|
||||
|
||||
-- mLoadCount;
|
||||
if( !mLoadCount )
|
||||
{
|
||||
#ifdef DEBUG_SPEW
|
||||
Platform::outputDebugString( "[GuiControlProfile] Unloading profile %i:%s (%s:%s)",
|
||||
getId(), getClassName(), getName(), getInternalName() );
|
||||
#endif
|
||||
|
||||
if( !mBitmapName || !mBitmapName[0] || dStricmp(mBitmapName, "texhandle") != 0 )
|
||||
mTextureObject = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool GuiControlProfile::loadFont()
|
||||
{
|
||||
mFont = GFont::create( mFontType, mFontSize, sFontCacheDirectory, mFontCharset );
|
||||
if( mFont == NULL )
|
||||
{
|
||||
Con::errorf( "GuiControlProfile::loadFont - Failed to load/create profile font (%s/%d)", mFontType, mFontSize );
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ConsoleMethod( GuiControlProfile, getStringWidth, S32, 3, 3, "( pString )" )
|
||||
{
|
||||
return object->mFont->getStrNWidth( argv[2], dStrlen( argv[2] ) );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// TypeRectSpacingI
|
||||
//-----------------------------------------------------------------------------
|
||||
IMPLEMENT_STRUCT( RectSpacingI,
|
||||
RectSpacingI, GuiAPI,
|
||||
"" )
|
||||
|
||||
FIELD( left, leftPadding, 1, "" )
|
||||
FIELD( right, rightPadding, 1, "" )
|
||||
FIELD( top, topPadding, 1, "" )
|
||||
FIELD( bottom, bottomPadding, 1, "" )
|
||||
|
||||
END_IMPLEMENT_STRUCT;
|
||||
|
||||
ConsoleType( RectSpacingI, TypeRectSpacingI, RectSpacingI )
|
||||
ImplementConsoleTypeCasters( TypeRectSpacingI, RectSpacingI )
|
||||
|
||||
ConsoleGetType( TypeRectSpacingI )
|
||||
{
|
||||
RectSpacingI *rect = (RectSpacingI *) dptr;
|
||||
char* returnBuffer = Con::getReturnBuffer(256);
|
||||
dSprintf(returnBuffer, 256, "%d %d %d %d", rect->top, rect->bottom,
|
||||
rect->left, rect->right);
|
||||
return returnBuffer;
|
||||
}
|
||||
|
||||
ConsoleSetType( TypeRectSpacingI )
|
||||
{
|
||||
if(argc == 1)
|
||||
dSscanf(argv[0], "%d %d %d %d", &((RectSpacingI *) dptr)->top, &((RectSpacingI *) dptr)->bottom,
|
||||
&((RectSpacingI *) dptr)->left, &((RectSpacingI *) dptr)->right);
|
||||
else if(argc == 4)
|
||||
*((RectSpacingI *) dptr) = RectSpacingI(dAtoi(argv[0]), dAtoi(argv[1]), dAtoi(argv[2]), dAtoi(argv[3]));
|
||||
else
|
||||
Con::printf("RectSpacingI must be set as { t, b, l, r } or \"t b l r\"");
|
||||
}
|
||||
523
Engine/source/gui/core/guiTypes.h
Normal file
523
Engine/source/gui/core/guiTypes.h
Normal file
|
|
@ -0,0 +1,523 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _GUITYPES_H_
|
||||
#define _GUITYPES_H_
|
||||
|
||||
#ifndef _GFONT_H_
|
||||
#include "gfx/gFont.h"
|
||||
#endif
|
||||
#ifndef _COLOR_H_
|
||||
#include "core/color.h"
|
||||
#endif
|
||||
#ifndef _SIMBASE_H_
|
||||
#include "console/simBase.h"
|
||||
#endif
|
||||
#ifndef _DYNAMIC_CONSOLETYPES_H_
|
||||
#include "console/dynamicTypes.h"
|
||||
#endif
|
||||
|
||||
|
||||
#include "gfx/gfxDevice.h"
|
||||
#include "platform/event.h"
|
||||
|
||||
class GBitmap;
|
||||
class SFXTrack;
|
||||
|
||||
/// Represents a single GUI event.
|
||||
///
|
||||
/// This is passed around to all the relevant controls so they know what's going on.
|
||||
struct GuiEvent
|
||||
{
|
||||
U16 ascii; ///< ascii character code 'a', 'A', 'b', '*', etc (if device==keyboard) - possibly a uchar or something
|
||||
U8 modifier; ///< SI_LSHIFT, etc
|
||||
InputObjectInstances keyCode; ///< for unprintables, 'tab', 'return', ...
|
||||
Point2I mousePoint; ///< for mouse events
|
||||
U8 mouseClickCount; ///< to determine double clicks, etc...
|
||||
U8 mouseAxis; ///< mousewheel axis (0 == X, 1 == Y)
|
||||
F32 fval; ///< used for mousewheel events
|
||||
|
||||
GuiEvent()
|
||||
: ascii( 0 ),
|
||||
modifier( 0 ),
|
||||
keyCode( KEY_NULL ),
|
||||
mousePoint( 0, 0 ),
|
||||
mouseClickCount( 0 ),
|
||||
mouseAxis( 0 ),
|
||||
fval( 0.f ) {}
|
||||
};
|
||||
|
||||
/// Represent a mouse event with a 3D position and vector.
|
||||
///
|
||||
/// This event used by the EditTSCtrl derived controls.
|
||||
struct Gui3DMouseEvent : public GuiEvent
|
||||
{
|
||||
Point3F vec;
|
||||
Point3F pos;
|
||||
|
||||
Gui3DMouseEvent()
|
||||
: vec( 0.f, 0.f, 0.f ),
|
||||
pos( 0.f, 0.f, 0.f ) {}
|
||||
};
|
||||
|
||||
|
||||
/// @name Docking Flag
|
||||
/// @{
|
||||
/// @brief Docking Options available to all GuiControl subclasses.
|
||||
namespace Docking
|
||||
{
|
||||
enum DockingType
|
||||
{
|
||||
dockNone = BIT(0), ///< Do not align this control to it's parent, let the control specify it's position/extent (default)
|
||||
dockClient = BIT(1), ///< Align this control to the client area available in the parent
|
||||
dockTop = BIT(2), ///< Align this control to the topmost border of it's parent (Width will be parent width)
|
||||
dockBottom = BIT(3), ///< Align this control to the bottommost border of it's parent (Width will be parent width)
|
||||
dockLeft = BIT(4), ///< Align this control to the leftmost border of it's parent (Height will be parent height)
|
||||
dockRight = BIT(5), ///< Align this control to the rightmost border of it's parent (Height will be parent height)
|
||||
dockInvalid = BIT(6), ///< Default NOT specified docking mode, this allows old sizing to takeover when needed by controls
|
||||
dockAny = dockClient | dockTop | dockBottom | dockLeft | dockRight
|
||||
};
|
||||
};
|
||||
|
||||
typedef Docking::DockingType GuiDockingType;
|
||||
DefineEnumType( GuiDockingType );
|
||||
|
||||
/// @}
|
||||
|
||||
|
||||
/// @name Margin Padding Structure
|
||||
/// @{
|
||||
struct RectSpacingI
|
||||
{
|
||||
S32 left;
|
||||
S32 top;
|
||||
S32 bottom;
|
||||
S32 right;
|
||||
RectSpacingI() { left = right = top = bottom = 0; };
|
||||
RectSpacingI( S32 in_top, S32 in_bottom, S32 in_left, S32 in_right )
|
||||
{
|
||||
top = in_top;
|
||||
bottom = in_bottom;
|
||||
left = in_left;
|
||||
right = in_right;
|
||||
}
|
||||
void setAll( S32 value ) { left = right = top = bottom = value; };
|
||||
void set( S32 in_top, S32 in_bottom, S32 in_left, S32 in_right )
|
||||
{
|
||||
top = in_top;
|
||||
bottom = in_bottom;
|
||||
left = in_left;
|
||||
right = in_right;
|
||||
}
|
||||
void insetRect( RectI &rectRef )
|
||||
{
|
||||
// Inset by padding
|
||||
rectRef.point.x += left;
|
||||
rectRef.point.y += top;
|
||||
rectRef.extent.x -= (left + right );
|
||||
rectRef.extent.y -= (bottom + top );
|
||||
}
|
||||
void expandRect( RectI &rectRef )
|
||||
{
|
||||
// Inset by padding
|
||||
rectRef.point.x -= left;
|
||||
rectRef.point.y -= top;
|
||||
rectRef.extent.x += (left + right );
|
||||
rectRef.extent.y += (bottom + top );
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
DECLARE_STRUCT( RectSpacingI );
|
||||
DefineConsoleType( TypeRectSpacingI, RectSpacingI );
|
||||
/// @}
|
||||
|
||||
|
||||
/// @name Axis-Aligned Edge Structure
|
||||
/// @{
|
||||
///
|
||||
struct Edge
|
||||
{
|
||||
Point2F normal; ///< The Normal of this edge
|
||||
Point2I position;///< The Position of the edge
|
||||
Point2I extent; ///< The X/Y extents of the edge
|
||||
F32 margin; ///< The Size of the edge
|
||||
|
||||
Edge(): normal(0.f,0.f),
|
||||
position(0,0),
|
||||
extent(0,0),
|
||||
margin(1.f){};
|
||||
Edge( const Point2I &inPoint, const Point2F &inNormal )
|
||||
{
|
||||
normal = inNormal;
|
||||
margin = 2.f;
|
||||
|
||||
if( normal.x == 1.f || normal.x == -1.f )
|
||||
{
|
||||
// Vertical Edge
|
||||
position.x = inPoint.x;
|
||||
position.y = 0;
|
||||
|
||||
extent.x = 1;
|
||||
extent.y = 1;
|
||||
}
|
||||
else if( normal.y == 1.f || normal.y == -1.f )
|
||||
{
|
||||
// Horizontal Edge
|
||||
position.y = inPoint.y;
|
||||
position.x = 0;
|
||||
|
||||
extent.x = 1;
|
||||
extent.y = 1;
|
||||
}
|
||||
else
|
||||
AssertFatal(false,"Edge point constructor cannot construct an Edge without an axis-aligned normal.");
|
||||
}
|
||||
|
||||
// Copy Constructor
|
||||
Edge( const Edge &inEdge )
|
||||
{
|
||||
normal = inEdge.normal;
|
||||
position = inEdge.position;
|
||||
extent = inEdge.extent;
|
||||
margin = inEdge.margin;
|
||||
}
|
||||
|
||||
// RectI cast operator overload
|
||||
operator const RectI() const
|
||||
{
|
||||
if( normal.x == 1.f || normal.x == -1.f )
|
||||
{
|
||||
// Vertical Edge
|
||||
RectI retRect = RectI( position.x, position.y, 1, position.y + extent.y );
|
||||
// Expand Rect by Margin along the X Axis
|
||||
retRect.inset(-margin,0);
|
||||
|
||||
return retRect;
|
||||
}
|
||||
else if( normal.y == 1.f || normal.y == -1.f )
|
||||
{
|
||||
// Horizontal Edge
|
||||
RectI retRect = RectI( position.x, position.y , position.x + extent.x, 1 );
|
||||
// Expand Rect by Margin along the Y Axis
|
||||
retRect.inset(0,-margin);
|
||||
return retRect;
|
||||
}
|
||||
|
||||
// CodeReview this code only deals with axis-aligned edges [6/8/2007 justind]
|
||||
AssertFatal(false,"Edge cast operator cannot construct a Rect from an Edge that is not axis-aligned.");
|
||||
return RectI( 0,0,0,0 );
|
||||
}
|
||||
|
||||
inline bool hit( const Edge &inEdge ) const
|
||||
{
|
||||
const RectI thisRect = *this;
|
||||
const RectI thatRect = inEdge;
|
||||
|
||||
return thisRect.overlaps( thatRect );
|
||||
}
|
||||
};
|
||||
/// @}
|
||||
|
||||
|
||||
struct EdgeRectI
|
||||
{
|
||||
Edge left;
|
||||
Edge top;
|
||||
Edge bottom;
|
||||
Edge right;
|
||||
|
||||
EdgeRectI(){ }
|
||||
|
||||
EdgeRectI( const RectI &inRect, F32 inMargin )
|
||||
{
|
||||
// Left Edge
|
||||
left.normal = Point2F( -1.f, 0.f );
|
||||
left.position.x= inRect.point.x;
|
||||
left.position.y= 0;
|
||||
left.extent = Point2I(inRect.point.y, inRect.point.y + inRect.extent.y);
|
||||
left.margin = inMargin;
|
||||
|
||||
// Right Edge
|
||||
right.normal = Point2F( 1.f, 0.f );
|
||||
right.position.x = inRect.point.x + inRect.extent.x;
|
||||
right.position.y = 0;
|
||||
right.extent = Point2I(inRect.point.y, inRect.point.y + inRect.extent.y);
|
||||
right.margin = inMargin;
|
||||
|
||||
// Top Edge
|
||||
top.normal = Point2F( 0.f, 1.f );
|
||||
top.position.y = inRect.point.y;
|
||||
top.position.x = 0;
|
||||
top.extent = Point2I(inRect.point.x + inRect.extent.x, inRect.point.x);
|
||||
top.margin = inMargin;
|
||||
|
||||
// Bottom Edge
|
||||
bottom.normal = Point2F( 0.f, -1.f );
|
||||
bottom.position.y= inRect.point.y + inRect.extent.y;
|
||||
bottom.position.x=0;
|
||||
bottom.extent = Point2I(inRect.point.x + inRect.extent.x, inRect.point.x);
|
||||
bottom.margin = inMargin;
|
||||
}
|
||||
|
||||
// Copy constructor
|
||||
EdgeRectI( const EdgeRectI &inEdgeRect )
|
||||
{
|
||||
left = inEdgeRect.left;
|
||||
right = inEdgeRect.right;
|
||||
top = inEdgeRect.top;
|
||||
bottom = inEdgeRect.bottom;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/// Represents the Sizing Options for a GuiControl
|
||||
struct ControlSizing
|
||||
{
|
||||
ControlSizing()
|
||||
{
|
||||
mDocking = Docking::dockInvalid;
|
||||
mPadding.setAll( 0 );
|
||||
mInternalPadding.setAll( 0 );
|
||||
|
||||
// Default anchors to full top/left
|
||||
mAnchorBottom = false;
|
||||
mAnchorLeft = true;
|
||||
mAnchorTop = true;
|
||||
mAnchorRight = false;
|
||||
};
|
||||
|
||||
S32 mDocking; ///< Docking Flag
|
||||
|
||||
RectSpacingI mPadding; ///< Padding for each side of the control to have as spacing between other controls
|
||||
/// For example 1,1,1,1 would mean one pixel at least of spacing between this control and the
|
||||
/// one next to it.
|
||||
RectSpacingI mInternalPadding; ///< Interior Spacing of the control
|
||||
|
||||
|
||||
/// @name Anchoring
|
||||
/// @{
|
||||
/// @brief Anchors are applied to @b ONLY controls that are children of any derivative of a
|
||||
/// GuiContainer control. Anchors are applied when a parent is resized and a child
|
||||
/// element should be resized to accommodate the new parent extent
|
||||
///
|
||||
/// Anchors are specified as true or false and control whether a certain edge of a control
|
||||
/// will be locked to a certain edge of a parent, when the parent resizes. Anchors are specified
|
||||
/// as a Mask and therefore you may lock any number of edges to a parent container and when the parent
|
||||
/// is resized, any locked edges on a control will remain the same distance from the parent edge it
|
||||
/// is locked to, after the resize happens.
|
||||
///
|
||||
bool mAnchorTop; ///< Anchor to the Top edge of the parent when created
|
||||
bool mAnchorBottom; ///< Anchor to the Bottom edge of the parent when created
|
||||
bool mAnchorLeft; ///< Anchor to the Left edge of the parent when created
|
||||
bool mAnchorRight; ///< Anchor to the Right edge of the parent when created
|
||||
/// @}
|
||||
|
||||
};
|
||||
|
||||
class GuiCursor : public SimObject
|
||||
{
|
||||
private:
|
||||
typedef SimObject Parent;
|
||||
StringTableEntry mBitmapName;
|
||||
|
||||
Point2I mHotSpot;
|
||||
Point2F mRenderOffset;
|
||||
Point2I mExtent;
|
||||
GFXTexHandle mTextureObject;
|
||||
|
||||
public:
|
||||
Point2I getHotSpot() { return mHotSpot; }
|
||||
Point2I getExtent() { return mExtent; }
|
||||
|
||||
DECLARE_CONOBJECT(GuiCursor);
|
||||
GuiCursor(void);
|
||||
~GuiCursor(void);
|
||||
static void initPersistFields();
|
||||
|
||||
bool onAdd(void);
|
||||
void onRemove();
|
||||
void render(const Point2I &pos);
|
||||
};
|
||||
|
||||
/// A GuiControlProfile is used by every GuiObject and is akin to a
|
||||
/// datablock. It is used to control information that does not change
|
||||
/// or is unlikely to change during execution of a program. It is also
|
||||
/// a level of abstraction between script and GUI control so that you can
|
||||
/// use the same control, say a button, and have it look completly different
|
||||
/// just with a different profile.
|
||||
class GuiControlProfile : public SimObject
|
||||
{
|
||||
private:
|
||||
typedef SimObject Parent;
|
||||
|
||||
public:
|
||||
static StringTableEntry sFontCacheDirectory; ///< Directory where Torque will store font *.uft files.
|
||||
|
||||
U32 mUseCount; ///< Total number of controls currently referencing this profile.
|
||||
U32 mLoadCount; ///< Number of controls in woken state using this profile; resources for the profile are loaded when this is >0.
|
||||
bool mTabable; ///< True if this object is accessable from using the tab key
|
||||
|
||||
bool mCanKeyFocus; ///< True if the object can be given keyboard focus (in other words, made a first responder @see GuiControl)
|
||||
bool mModal; ///< True if this is a Modeless dialog meaning it will pass input through instead of taking it all
|
||||
|
||||
bool mOpaque; ///< True if this object is not translucent, and should draw a fill
|
||||
ColorI mFillColor; ///< Fill color, this is used to fill the bounds of the control if it is opaque
|
||||
ColorI mFillColorHL; ///< This is used instead of mFillColor if the object is highlighted
|
||||
ColorI mFillColorNA; ///< This is used instead of mFillColor if the object is not active or disabled
|
||||
ColorI mFillColorSEL; ///< This is used instead of mFillColor if the object is selected
|
||||
|
||||
S32 mBorder; ///< For most controls, if mBorder is > 0 a border will be drawn, some controls use this to draw different types of borders however @see guiDefaultControlRender.cc
|
||||
S32 mBorderThickness; ///< Border thickness
|
||||
ColorI mBorderColor; ///< Border color, used to draw a border around the bounds if border is enabled
|
||||
ColorI mBorderColorHL; ///< Used instead of mBorderColor when the object is highlighted
|
||||
ColorI mBorderColorNA; ///< Used instead of mBorderColor when the object is not active or disabled
|
||||
|
||||
ColorI mBevelColorHL; ///< Used for the high-light part of the bevel
|
||||
ColorI mBevelColorLL; ///< Used for the low-light part of the bevel
|
||||
|
||||
// font members
|
||||
StringTableEntry mFontType; ///< Font face name for the control
|
||||
S32 mFontSize; ///< Font size for the control
|
||||
enum {
|
||||
BaseColor = 0,
|
||||
ColorHL,
|
||||
ColorNA,
|
||||
ColorSEL,
|
||||
ColorUser0,
|
||||
ColorUser1,
|
||||
ColorUser2,
|
||||
ColorUser3,
|
||||
ColorUser4,
|
||||
ColorUser5,
|
||||
};
|
||||
ColorI mFontColors[10]; ///< Array of font colors used for drawText with escape characters for changing color mid-string
|
||||
ColorI& mFontColor; ///< Main font color
|
||||
ColorI& mFontColorHL; ///< Highlighted font color
|
||||
ColorI& mFontColorNA; ///< Font color when object is not active/disabled
|
||||
ColorI& mFontColorSEL; ///< Font color when object/text is selected
|
||||
FontCharset mFontCharset; ///< Font character set
|
||||
|
||||
Resource<GFont> mFont; ///< Font resource
|
||||
|
||||
enum AlignmentType
|
||||
{
|
||||
LeftJustify,
|
||||
RightJustify,
|
||||
CenterJustify,
|
||||
TopJustify,
|
||||
BottomJustify
|
||||
};
|
||||
|
||||
AlignmentType mAlignment; ///< Horizontal text alignment
|
||||
bool mAutoSizeWidth; ///< Auto-size the width-bounds of the control to fit it's contents
|
||||
bool mAutoSizeHeight; ///< Auto-size the height-bounds of the control to fit it's contents
|
||||
bool mReturnTab; ///< Used in GuiTextEditCtrl to specify if a tab-event should be simulated when return is pressed.
|
||||
bool mNumbersOnly; ///< For text controls, true if this should only accept numerical data
|
||||
bool mMouseOverSelected; ///< True if this object should be "selected" while the mouse is over it
|
||||
ColorI mCursorColor; ///< Color for the blinking cursor in text fields (for example)
|
||||
|
||||
Point2I mTextOffset; ///< Text offset for the control
|
||||
|
||||
// bitmap members
|
||||
StringTableEntry mBitmapName; ///< Bitmap file name for the bitmap of the control
|
||||
bool mUseBitmapArray; ///< Flag to use the bitmap array or to fallback to non-array rendering
|
||||
GFXTexHandle mTextureObject;
|
||||
Vector<RectI> mBitmapArrayRects; ///< Used for controls which use an array of bitmaps such as checkboxes
|
||||
|
||||
// sound members
|
||||
SimObjectPtr< SFXTrack > mSoundButtonDown; ///< Sound played when the object is "down" ie a button is pushed
|
||||
SimObjectPtr< SFXTrack > mSoundButtonOver; ///< Sound played when the mouse is over the object
|
||||
|
||||
StringTableEntry mChildrenProfileName; ///< The name of the profile to use for the children controls
|
||||
|
||||
/// Returns our children profile (and finds the profile if it hasn't been set yet)
|
||||
GuiControlProfile* getChildrenProfile();
|
||||
|
||||
/// Category name for editing in the Gui Editor.
|
||||
String mCategory;
|
||||
|
||||
/// Sets the children profile for this profile
|
||||
///
|
||||
/// @see GuiControlProfile
|
||||
/// @param prof Tooltip profile to apply
|
||||
void setChildrenProfile(GuiControlProfile *prof);
|
||||
protected:
|
||||
GuiControlProfile* mChildrenProfile; ///< Profile used with children controls (such as the scroll bar on a popup menu) when defined.
|
||||
|
||||
static bool protectedSetBitmap( void *object, const char *index, const char *data );
|
||||
static bool protectedSetSoundButtonDown( void* object, const char* index, const char* data );
|
||||
static bool protectedSetSoundButtonOver( void* object, const char* index, const char* data );
|
||||
static const char* protectedGetSoundButtonDown( void* object, const char* data );
|
||||
static const char* protectedGetSoundButtonOver( void* object, const char* data );
|
||||
|
||||
public:
|
||||
DECLARE_CONOBJECT(GuiControlProfile);
|
||||
GuiControlProfile();
|
||||
~GuiControlProfile();
|
||||
static void initPersistFields();
|
||||
|
||||
bool onAdd();
|
||||
|
||||
void onStaticModified(const char* slotName, const char* newValue = NULL );
|
||||
|
||||
/// Called when mProfileForChildren is deleted
|
||||
virtual void onDeleteNotify(SimObject *object);
|
||||
|
||||
/// This method creates an array of bitmaps from one single bitmap with
|
||||
/// separator color. The separator color is whatever color is in pixel 0,0
|
||||
/// of the bitmap. For an example see darkWindow.png and some of the other
|
||||
/// UI textures. It returns the number of bitmaps in the array it created
|
||||
/// It also stores the sizes in the mBitmapArrayRects vector.
|
||||
S32 constructBitmapArray();
|
||||
|
||||
/// This method returns the ith bitmap array rect, first ensuring that i is a
|
||||
/// valid index into mBitmapArrayRects. If the vector is empty, we call
|
||||
/// constructBitmapArray() automatically. If it is still empty, we return a
|
||||
/// zeroed RectI.
|
||||
RectI getBitmapArrayRect(U32 i);
|
||||
|
||||
///
|
||||
bool isInUse() const { return ( mUseCount != 0 ); }
|
||||
|
||||
void incUseCount() { mUseCount ++; }
|
||||
void decUseCount() { if( mUseCount > 0 ) mUseCount --; }
|
||||
|
||||
void incLoadCount();
|
||||
void decLoadCount();
|
||||
|
||||
bool loadFont();
|
||||
|
||||
void setBitmapHandle(GFXTexHandle handle);
|
||||
};
|
||||
|
||||
typedef GuiControlProfile::AlignmentType GuiAlignmentType;
|
||||
DefineEnumType( GuiAlignmentType );
|
||||
|
||||
typedef FontCharset GuiFontCharset;
|
||||
DefineEnumType( GuiFontCharset );
|
||||
|
||||
GFX_DeclareTextureProfile(GFXGuiCursorProfile);
|
||||
GFX_DeclareTextureProfile(GFXDefaultGUIProfile);
|
||||
|
||||
#endif //_GUITYPES_H
|
||||
Loading…
Add table
Add a link
Reference in a new issue