123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322 |
- //-----------------------------------------------------------------------------
- // 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 "console/console.h"
- #include "console/consoleTypes.h"
- #include "console/engineAPI.h"
- #include "gfx/gfxDevice.h"
- #include "gfx/gfxDrawUtil.h"
- #include "gui/editor/guiRectHandles.h"
- IMPLEMENT_CONOBJECT(GuiRectHandles);
- ConsoleDocClass( GuiRectHandles,
- "@brief Draws a box with handles for the user to manipulate.\n\n"
- "Editor use only.\n\n"
- "@internal"
- );
- //--------------------------------------------------------------------------
- GuiRectHandles::GuiRectHandles() : GuiControl()
- {
- mHandleRect.set(0.0f, 0.0f, 1.0f, 1.0f);
- mHandleSize = 10;
- mUseCustomColor = false;
- mHandleColor.set(100,100,100);
- mHitHandle = 0;
- }
- GuiRectHandles::~GuiRectHandles()
- {
- }
- //--------------------------------------------------------------------------
- void GuiRectHandles::initPersistFields()
- {
- docsURL;
- addField("handleRect", TypeRectF, Offset(mHandleRect, GuiRectHandles), "RectF of handle's box." );
- addField("handleSize", TypeS32, Offset(mHandleSize, GuiRectHandles), "Size of handles in pixels." );
- addField("useCustomColor", TypeBool, Offset(mUseCustomColor, GuiRectHandles), "Use given custom color for handles." );
- addField("handleColor", TypeColorI, Offset(mHandleColor, GuiRectHandles), "Use given custom color for handles." );
- Parent::initPersistFields();
- }
- //--------------------------------------------------------------------------
- void GuiRectHandles::onMouseUp(const GuiEvent &event)
- {
- mHitHandle = 0;
- }
- void GuiRectHandles::onMouseDown(const GuiEvent &event)
- {
- // The handles range from 0-1, so scale to fit within the
- // control's bounds.
- const Point2I& extent = getExtent();
- Point2I pos(extent.x*mHandleRect.point.x, extent.y*mHandleRect.point.y);
- Point2I size(extent.x*mHandleRect.extent.x, extent.y*mHandleRect.extent.y);
- RectI box(pos, size);
- Point2I localMousePoint = globalToLocalCoord(event.mousePoint);
- // Check if mouse is within handle rect
- if(!box.pointInRect(localMousePoint))
- {
- mHitHandle = 0;
- return;
- }
- Point2I normalizedMouse = localMousePoint - pos;
- Point2I halfSize = size / 2;
- S32 halfHandleSize = mHandleSize / 2;
- if(normalizedMouse.y < mHandleSize)
- {
- // Top handles
- if(normalizedMouse.x < mHandleSize)
- mHitHandle = 1;
- else if(normalizedMouse.x >= (size.x-mHandleSize))
- mHitHandle = 3;
- else if(normalizedMouse.x >= (halfSize.x-halfHandleSize) && normalizedMouse.x < (halfSize.x+halfHandleSize))
- mHitHandle = 2;
- }
- else if(normalizedMouse.y >= (size.y-mHandleSize))
- {
- // Bottom handles
- if(normalizedMouse.x < mHandleSize)
- mHitHandle = 7;
- else if(normalizedMouse.x >= (size.x-mHandleSize))
- mHitHandle = 5;
- else if(normalizedMouse.x >= (halfSize.x-halfHandleSize) && normalizedMouse.x < (halfSize.x+halfHandleSize))
- mHitHandle = 6;
- }
- else if(normalizedMouse.y >= (halfSize.y-halfHandleSize) && normalizedMouse.y < (halfSize.y+halfHandleSize))
- {
- // Middle handles
- if(normalizedMouse.x < mHandleSize)
- mHitHandle = 8;
- else if(normalizedMouse.x >= (size.x-mHandleSize))
- mHitHandle = 4;
- else if(normalizedMouse.x >= (halfSize.x-halfHandleSize) && normalizedMouse.x < (halfSize.x+halfHandleSize))
- mHitHandle = 9;
- }
- mHitPoint = localMousePoint;
- }
- void GuiRectHandles::onMouseDragged(const GuiEvent &event)
- {
- if(mHitHandle == 0)
- return;
- // The handles range from 0-1, so scale to fit within the
- // control's bounds.
- const Point2I& extent = getExtent();
- Point2I localMousePoint = globalToLocalCoord(event.mousePoint);
- Point2I diffI = localMousePoint - mHitPoint;
- Point2F diffF(diffI.x/F32(extent.x), diffI.y/F32(extent.y));
- RectF box(mHandleRect);
- bool postMoveExtentX = false;
- bool postMoveExtentY = false;
- bool keepExtent = false;
- switch(mHitHandle)
- {
- case 1:
- {
- // Top left
- box.point += diffF;
- postMoveExtentX = true;
- postMoveExtentY = true;
- break;
- }
- case 2:
- {
- // Top middle
- box.point.y += diffF.y;
- postMoveExtentY = true;
- break;
- }
- case 3:
- {
- // Top right
- box.point.y += diffF.y;
- box.extent.x += diffF.x;
- postMoveExtentY = true;
- break;
- }
- case 4:
- {
- // Middle right
- box.extent.x += diffF.x;
- break;
- }
- case 5:
- {
- // Bottom right
- box.extent += diffF;
- break;
- }
- case 6:
- {
- // Bottom middle
- box.extent.y += diffF.y;
- break;
- }
- case 7:
- {
- // Bottom left
- box.point.x += diffF.x;
- box.extent.y += diffF.y;
- postMoveExtentX = true;
- break;
- }
- case 8:
- {
- // Middle left
- box.point.x += diffF.x;
- postMoveExtentX = true;
- break;
- }
- case 9:
- {
- // Centre
- box.point += diffF;
- keepExtent = true;
- break;
- }
- default:
- break;
- }
- // Position limits
- if(box.point.x < 0.0f)
- box.point.x = 0.0f;
- else if(box.point.x > 1.0f)
- box.point.x = 1.0f;
- if(box.point.y < 0.0f)
- box.point.y = 0.0f;
- else if(box.point.y > 1.0f)
- box.point.y = 1.0f;
- // Move any extent to counter a change in handle position. Do this
- // after the limits above to make sure the extent doesn't accidentally
- // grow when the position is clamped.
- if(postMoveExtentX)
- box.extent.x += mHandleRect.point.x - box.point.x;
- if(postMoveExtentY)
- box.extent.y += mHandleRect.point.y - box.point.y;
- // Extent limits
- if(box.extent.x < 0.0f)
- box.extent.x = 0.0f;
- else if(box.extent.x > 1.0f)
- box.extent.x = 1.0f;
- if(box.point.x+box.extent.x > 1.0f)
- {
- if(keepExtent)
- box.point.x = 1.0f-box.extent.x;
- else
- box.extent.x = 1.0f-box.point.x;
- }
- if(box.extent.y < 0.0f)
- box.extent.y = 0.0f;
- else if(box.extent.y > 1.0f)
- box.extent.y = 1.0f;
- if(box.point.y+box.extent.y > 1.0f)
- {
- if(keepExtent)
- box.point.y = 1.0f-box.extent.y;
- else
- box.extent.y = 1.0f-box.point.y;
- }
- mHandleRect = box;
- mHitPoint = localMousePoint;
- if( isMethod( "onHandleRectChange" ) )
- Con::executef(this, "onHandleRectChange" );
- }
- //--------------------------------------------------------------------------
- void GuiRectHandles::onRender(Point2I offset, const RectI &updateRect)
- {
- Parent::onRender( offset, updateRect );
- ColorI handleColor = mProfile->mBorderColor;
- if(mUseCustomColor)
- handleColor = mHandleColor;
- // The handles range from 0-1, so scale to fit within the
- // control's bounds.
- const Point2I& extent = getExtent();
- Point2I pos(extent.x*mHandleRect.point.x, extent.y*mHandleRect.point.y);
- Point2I size(extent.x*mHandleRect.extent.x, extent.y*mHandleRect.extent.y);
- RectI box(offset+pos, size);
- GFXDrawUtil* drawUtil = GFX->getDrawUtil();
- // Draw border
- drawUtil->drawRect(box, handleColor);
- // Draw each handle
- Point2I handleSize(mHandleSize, mHandleSize);
- RectI handleRect(box.point, handleSize);
- drawUtil->drawRectFill(handleRect, handleColor); // Upper left
- handleRect.point = Point2I(box.point.x+size.x-handleSize.x, box.point.y);
- drawUtil->drawRectFill(handleRect, handleColor); // Upper right
- handleRect.point = Point2I(box.point.x, box.point.y+size.y-handleSize.y);
- drawUtil->drawRectFill(handleRect, handleColor); // Lower left
- handleRect.point = Point2I(box.point.x+size.x-handleSize.x, box.point.y+size.y-handleSize.y);
- drawUtil->drawRectFill(handleRect, handleColor); // Lower right
- Point2I halfSize = size / 2;
- Point2I halfHandleSize = handleSize / 2;
- handleRect.point = Point2I(box.point.x+halfSize.x-halfHandleSize.x, box.point.y);
- drawUtil->drawRectFill(handleRect, handleColor); // Upper middle
- handleRect.point = Point2I(box.point.x+halfSize.x-halfHandleSize.x, box.point.y+size.y-handleSize.y);
- drawUtil->drawRectFill(handleRect, handleColor); // Lower middle
- handleRect.point = Point2I(box.point.x, box.point.y+halfSize.y-halfHandleSize.y);
- drawUtil->drawRectFill(handleRect, handleColor); // Left middle
- handleRect.point = Point2I(box.point.x+size.x-handleSize.x, box.point.y+halfSize.y-halfHandleSize.y);
- drawUtil->drawRectFill(handleRect, handleColor); // Right middle
- handleRect.point = Point2I(box.point.x+halfSize.x-halfHandleSize.x, box.point.y+halfSize.y-halfHandleSize.y);
- drawUtil->drawRectFill(handleRect, handleColor); // Middle
- renderChildControls(offset, updateRect);
- }
|