guiRectHandles.cpp
Engine/source/gui/editor/guiRectHandles.cpp
Public Functions
ConsoleDocClass(GuiRectHandles , "@brief Draws <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> box with handles <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the user <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">manipulate.\n\n</a>" "Editor use <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">only.\n\n</a>" "@internal" )
Detailed Description
Public Functions
ConsoleDocClass(GuiRectHandles , "@brief Draws <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> box with handles <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the user <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">manipulate.\n\n</a>" "Editor use <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">only.\n\n</a>" "@internal" )
IMPLEMENT_CONOBJECT(GuiRectHandles )
1 2//----------------------------------------------------------------------------- 3// Copyright (c) 2012 GarageGames, LLC 4// 5// Permission is hereby granted, free of charge, to any person obtaining a copy 6// of this software and associated documentation files (the "Software"), to 7// deal in the Software without restriction, including without limitation the 8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9// sell copies of the Software, and to permit persons to whom the Software is 10// furnished to do so, subject to the following conditions: 11// 12// The above copyright notice and this permission notice shall be included in 13// all copies or substantial portions of the Software. 14// 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21// IN THE SOFTWARE. 22//----------------------------------------------------------------------------- 23 24#include "console/console.h" 25#include "console/consoleTypes.h" 26#include "console/engineAPI.h" 27#include "gfx/gfxDevice.h" 28#include "gfx/gfxDrawUtil.h" 29 30#include "gui/editor/guiRectHandles.h" 31 32IMPLEMENT_CONOBJECT(GuiRectHandles); 33 34ConsoleDocClass( GuiRectHandles, 35 "@brief Draws a box with handles for the user to manipulate.\n\n" 36 "Editor use only.\n\n" 37 "@internal" 38); 39 40//-------------------------------------------------------------------------- 41GuiRectHandles::GuiRectHandles() : GuiControl() 42{ 43 mHandleRect.set(0.0f, 0.0f, 1.0f, 1.0f); 44 mHandleSize = 10; 45 mUseCustomColor = false; 46 mHandleColor.set(100,100,100); 47 mHitHandle = 0; 48} 49 50GuiRectHandles::~GuiRectHandles() 51{ 52} 53 54//-------------------------------------------------------------------------- 55void GuiRectHandles::initPersistFields() 56{ 57 addField("handleRect", TypeRectF, Offset(mHandleRect, GuiRectHandles), "RectF of handle's box." ); 58 addField("handleSize", TypeS32, Offset(mHandleSize, GuiRectHandles), "Size of handles in pixels." ); 59 addField("useCustomColor", TypeBool, Offset(mUseCustomColor, GuiRectHandles), "Use given custom color for handles." ); 60 addField("handleColor", TypeColorI, Offset(mHandleColor, GuiRectHandles), "Use given custom color for handles." ); 61 62 Parent::initPersistFields(); 63} 64 65//-------------------------------------------------------------------------- 66 67void GuiRectHandles::onMouseUp(const GuiEvent &event) 68{ 69 mHitHandle = 0; 70} 71 72void GuiRectHandles::onMouseDown(const GuiEvent &event) 73{ 74 // The handles range from 0-1, so scale to fit within the 75 // control's bounds. 76 const Point2I& extent = getExtent(); 77 Point2I pos(extent.x*mHandleRect.point.x, extent.y*mHandleRect.point.y); 78 Point2I size(extent.x*mHandleRect.extent.x, extent.y*mHandleRect.extent.y); 79 RectI box(pos, size); 80 81 Point2I localMousePoint = globalToLocalCoord(event.mousePoint); 82 83 // Check if mouse is within handle rect 84 if(!box.pointInRect(localMousePoint)) 85 { 86 mHitHandle = 0; 87 return; 88 } 89 90 Point2I normalizedMouse = localMousePoint - pos; 91 Point2I halfSize = size / 2; 92 S32 halfHandleSize = mHandleSize / 2; 93 if(normalizedMouse.y < mHandleSize) 94 { 95 // Top handles 96 if(normalizedMouse.x < mHandleSize) 97 mHitHandle = 1; 98 else if(normalizedMouse.x >= (size.x-mHandleSize)) 99 mHitHandle = 3; 100 else if(normalizedMouse.x >= (halfSize.x-halfHandleSize) && normalizedMouse.x < (halfSize.x+halfHandleSize)) 101 mHitHandle = 2; 102 } 103 else if(normalizedMouse.y >= (size.y-mHandleSize)) 104 { 105 // Bottom handles 106 if(normalizedMouse.x < mHandleSize) 107 mHitHandle = 7; 108 else if(normalizedMouse.x >= (size.x-mHandleSize)) 109 mHitHandle = 5; 110 else if(normalizedMouse.x >= (halfSize.x-halfHandleSize) && normalizedMouse.x < (halfSize.x+halfHandleSize)) 111 mHitHandle = 6; 112 } 113 else if(normalizedMouse.y >= (halfSize.y-halfHandleSize) && normalizedMouse.y < (halfSize.y+halfHandleSize)) 114 { 115 // Middle handles 116 if(normalizedMouse.x < mHandleSize) 117 mHitHandle = 8; 118 else if(normalizedMouse.x >= (size.x-mHandleSize)) 119 mHitHandle = 4; 120 else if(normalizedMouse.x >= (halfSize.x-halfHandleSize) && normalizedMouse.x < (halfSize.x+halfHandleSize)) 121 mHitHandle = 9; 122 } 123 124 mHitPoint = localMousePoint; 125} 126 127void GuiRectHandles::onMouseDragged(const GuiEvent &event) 128{ 129 if(mHitHandle == 0) 130 return; 131 132 // The handles range from 0-1, so scale to fit within the 133 // control's bounds. 134 const Point2I& extent = getExtent(); 135 136 Point2I localMousePoint = globalToLocalCoord(event.mousePoint); 137 138 Point2I diffI = localMousePoint - mHitPoint; 139 Point2F diffF(diffI.x/<a href="/coding/file/types_8h/#types_8h_1a841d3674577a1e86afdc2f4845f46c4b">F32</a>(extent.x), diffI.y/<a href="/coding/file/types_8h/#types_8h_1a841d3674577a1e86afdc2f4845f46c4b">F32</a>(extent.y)); 140 141 RectF box(mHandleRect); 142 bool postMoveExtentX = false; 143 bool postMoveExtentY = false; 144 bool keepExtent = false; 145 146 switch(mHitHandle) 147 { 148 case 1: 149 { 150 // Top left 151 box.point += diffF; 152 postMoveExtentX = true; 153 postMoveExtentY = true; 154 break; 155 } 156 157 case 2: 158 { 159 // Top middle 160 box.point.y += diffF.y; 161 postMoveExtentY = true; 162 break; 163 } 164 165 case 3: 166 { 167 // Top right 168 box.point.y += diffF.y; 169 box.extent.x += diffF.x; 170 postMoveExtentY = true; 171 break; 172 } 173 174 case 4: 175 { 176 // Middle right 177 box.extent.x += diffF.x; 178 break; 179 } 180 181 case 5: 182 { 183 // Bottom right 184 box.extent += diffF; 185 break; 186 } 187 188 case 6: 189 { 190 // Bottom middle 191 box.extent.y += diffF.y; 192 break; 193 } 194 195 case 7: 196 { 197 // Bottom left 198 box.point.x += diffF.x; 199 box.extent.y += diffF.y; 200 postMoveExtentX = true; 201 break; 202 } 203 204 case 8: 205 { 206 // Middle left 207 box.point.x += diffF.x; 208 postMoveExtentX = true; 209 break; 210 } 211 212 case 9: 213 { 214 // Centre 215 box.point += diffF; 216 keepExtent = true; 217 break; 218 } 219 220 default: 221 break; 222 } 223 224 // Position limits 225 if(box.point.x < 0.0f) 226 box.point.x = 0.0f; 227 else if(box.point.x > 1.0f) 228 box.point.x = 1.0f; 229 230 if(box.point.y < 0.0f) 231 box.point.y = 0.0f; 232 else if(box.point.y > 1.0f) 233 box.point.y = 1.0f; 234 235 // Move any extent to counter a change in handle position. Do this 236 // after the limits above to make sure the extent doesn't accidentally 237 // grow when the position is clamped. 238 if(postMoveExtentX) 239 box.extent.x += mHandleRect.point.x - box.point.x; 240 if(postMoveExtentY) 241 box.extent.y += mHandleRect.point.y - box.point.y; 242 243 // Extent limits 244 if(box.extent.x < 0.0f) 245 box.extent.x = 0.0f; 246 else if(box.extent.x > 1.0f) 247 box.extent.x = 1.0f; 248 if(box.point.x+box.extent.x > 1.0f) 249 { 250 if(keepExtent) 251 box.point.x = 1.0f-box.extent.x; 252 else 253 box.extent.x = 1.0f-box.point.x; 254 } 255 256 if(box.extent.y < 0.0f) 257 box.extent.y = 0.0f; 258 else if(box.extent.y > 1.0f) 259 box.extent.y = 1.0f; 260 if(box.point.y+box.extent.y > 1.0f) 261 { 262 if(keepExtent) 263 box.point.y = 1.0f-box.extent.y; 264 else 265 box.extent.y = 1.0f-box.point.y; 266 } 267 268 mHandleRect = box; 269 mHitPoint = localMousePoint; 270 271 if( isMethod( "onHandleRectChange" ) ) 272 Con::executef(this, "onHandleRectChange" ); 273} 274 275//-------------------------------------------------------------------------- 276void GuiRectHandles::onRender(Point2I offset, const RectI &updateRect) 277{ 278 Parent::onRender( offset, updateRect ); 279 280 ColorI handleColor = mProfile->mBorderColor; 281 if(mUseCustomColor) 282 handleColor = mHandleColor; 283 284 // The handles range from 0-1, so scale to fit within the 285 // control's bounds. 286 const Point2I& extent = getExtent(); 287 Point2I pos(extent.x*mHandleRect.point.x, extent.y*mHandleRect.point.y); 288 Point2I size(extent.x*mHandleRect.extent.x, extent.y*mHandleRect.extent.y); 289 RectI box(offset+pos, size); 290 291 GFXDrawUtil* drawUtil = GFX->getDrawUtil(); 292 293 // Draw border 294 drawUtil->drawRect(box, handleColor); 295 296 // Draw each handle 297 Point2I handleSize(mHandleSize, mHandleSize); 298 RectI handleRect(box.point, handleSize); 299 drawUtil->drawRectFill(handleRect, handleColor); // Upper left 300 handleRect.point = Point2I(box.point.x+size.x-handleSize.x, box.point.y); 301 drawUtil->drawRectFill(handleRect, handleColor); // Upper right 302 handleRect.point = Point2I(box.point.x, box.point.y+size.y-handleSize.y); 303 drawUtil->drawRectFill(handleRect, handleColor); // Lower left 304 handleRect.point = Point2I(box.point.x+size.x-handleSize.x, box.point.y+size.y-handleSize.y); 305 drawUtil->drawRectFill(handleRect, handleColor); // Lower right 306 307 Point2I halfSize = size / 2; 308 Point2I halfHandleSize = handleSize / 2; 309 handleRect.point = Point2I(box.point.x+halfSize.x-halfHandleSize.x, box.point.y); 310 drawUtil->drawRectFill(handleRect, handleColor); // Upper middle 311 handleRect.point = Point2I(box.point.x+halfSize.x-halfHandleSize.x, box.point.y+size.y-handleSize.y); 312 drawUtil->drawRectFill(handleRect, handleColor); // Lower middle 313 handleRect.point = Point2I(box.point.x, box.point.y+halfSize.y-halfHandleSize.y); 314 drawUtil->drawRectFill(handleRect, handleColor); // Left middle 315 handleRect.point = Point2I(box.point.x+size.x-handleSize.x, box.point.y+halfSize.y-halfHandleSize.y); 316 drawUtil->drawRectFill(handleRect, handleColor); // Right middle 317 318 handleRect.point = Point2I(box.point.x+halfSize.x-halfHandleSize.x, box.point.y+halfSize.y-halfHandleSize.y); 319 drawUtil->drawRectFill(handleRect, handleColor); // Middle 320 321 renderChildControls(offset, updateRect); 322} 323