| 
									
										
										
										
											2015-02-12 23:16:25 +08:00
										 |  |  | // Aseprite
 | 
					
						
							| 
									
										
										
										
											2017-01-07 04:44:08 +08:00
										 |  |  | // Copyright (C) 2001-2017  David Capello
 | 
					
						
							| 
									
										
										
										
											2015-02-12 23:16:25 +08:00
										 |  |  | //
 | 
					
						
							| 
									
										
										
										
											2016-08-27 04:02:58 +08:00
										 |  |  | // This program is distributed under the terms of
 | 
					
						
							|  |  |  | // the End-User License Agreement for Aseprite.
 | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-08-06 08:20:19 +08:00
										 |  |  | #ifdef HAVE_CONFIG_H
 | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  | #include "config.h"
 | 
					
						
							| 
									
										
										
										
											2013-08-06 08:20:19 +08:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-08-06 08:20:19 +08:00
										 |  |  | #include "app/ui/editor/standby_state.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "app/app.h"
 | 
					
						
							| 
									
										
										
										
											2017-03-07 06:27:43 +08:00
										 |  |  | #include "app/app_menus.h"
 | 
					
						
							| 
									
										
										
										
											2014-01-29 10:56:44 +08:00
										 |  |  | #include "app/color_picker.h"
 | 
					
						
							| 
									
										
										
										
											2015-07-03 05:13:47 +08:00
										 |  |  | #include "app/commands/cmd_eyedropper.h"
 | 
					
						
							| 
									
										
										
										
											2015-07-30 03:35:34 +08:00
										 |  |  | #include "app/commands/commands.h"
 | 
					
						
							| 
									
										
										
										
											2013-08-06 08:20:19 +08:00
										 |  |  | #include "app/commands/params.h"
 | 
					
						
							| 
									
										
										
										
											2015-12-04 01:05:28 +08:00
										 |  |  | #include "app/document_range.h"
 | 
					
						
							| 
									
										
										
										
											2013-08-06 08:20:19 +08:00
										 |  |  | #include "app/ini_file.h"
 | 
					
						
							| 
									
										
										
										
											2015-05-13 22:46:49 +08:00
										 |  |  | #include "app/pref/preferences.h"
 | 
					
						
							| 
									
										
										
										
											2016-12-01 08:07:30 +08:00
										 |  |  | #include "app/tools/active_tool.h"
 | 
					
						
							| 
									
										
										
										
											2013-08-06 08:20:19 +08:00
										 |  |  | #include "app/tools/ink.h"
 | 
					
						
							| 
									
										
										
										
											2014-02-24 19:08:34 +08:00
										 |  |  | #include "app/tools/pick_ink.h"
 | 
					
						
							| 
									
										
										
										
											2013-08-06 08:20:19 +08:00
										 |  |  | #include "app/tools/tool.h"
 | 
					
						
							| 
									
										
										
										
											2017-03-07 06:27:43 +08:00
										 |  |  | #include "app/ui/app_menuitem.h"
 | 
					
						
							| 
									
										
										
										
											2015-08-15 00:06:26 +08:00
										 |  |  | #include "app/ui/document_view.h"
 | 
					
						
							| 
									
										
										
										
											2013-08-06 08:20:19 +08:00
										 |  |  | #include "app/ui/editor/drawing_state.h"
 | 
					
						
							|  |  |  | #include "app/ui/editor/editor.h"
 | 
					
						
							|  |  |  | #include "app/ui/editor/editor_customization_delegate.h"
 | 
					
						
							| 
									
										
										
										
											2017-06-17 03:28:48 +08:00
										 |  |  | #include "app/ui/editor/glue.h"
 | 
					
						
							| 
									
										
										
										
											2013-08-06 08:20:19 +08:00
										 |  |  | #include "app/ui/editor/handle_type.h"
 | 
					
						
							|  |  |  | #include "app/ui/editor/moving_cel_state.h"
 | 
					
						
							|  |  |  | #include "app/ui/editor/moving_pixels_state.h"
 | 
					
						
							| 
									
										
										
										
											2017-04-07 02:26:01 +08:00
										 |  |  | #include "app/ui/editor/moving_selection_state.h"
 | 
					
						
							| 
									
										
										
										
											2017-03-07 06:27:43 +08:00
										 |  |  | #include "app/ui/editor/moving_slice_state.h"
 | 
					
						
							| 
									
										
										
										
											2015-12-04 01:05:28 +08:00
										 |  |  | #include "app/ui/editor/moving_symmetry_state.h"
 | 
					
						
							| 
									
										
										
										
											2015-07-30 03:35:34 +08:00
										 |  |  | #include "app/ui/editor/pivot_helpers.h"
 | 
					
						
							| 
									
										
										
										
											2013-08-06 08:20:19 +08:00
										 |  |  | #include "app/ui/editor/pixels_movement.h"
 | 
					
						
							|  |  |  | #include "app/ui/editor/scrolling_state.h"
 | 
					
						
							|  |  |  | #include "app/ui/editor/tool_loop_impl.h"
 | 
					
						
							|  |  |  | #include "app/ui/editor/transform_handles.h"
 | 
					
						
							| 
									
										
										
										
											2014-04-20 07:08:21 +08:00
										 |  |  | #include "app/ui/editor/zooming_state.h"
 | 
					
						
							| 
									
										
										
										
											2015-12-04 01:05:28 +08:00
										 |  |  | #include "app/ui/main_window.h"
 | 
					
						
							| 
									
										
										
										
											2015-10-29 07:00:18 +08:00
										 |  |  | #include "app/ui/skin/skin_theme.h"
 | 
					
						
							| 
									
										
										
										
											2013-08-06 08:20:19 +08:00
										 |  |  | #include "app/ui/status_bar.h"
 | 
					
						
							| 
									
										
										
										
											2017-03-27 00:33:12 +08:00
										 |  |  | #include "app/ui/timeline/timeline.h"
 | 
					
						
							| 
									
										
										
										
											2013-08-06 08:20:19 +08:00
										 |  |  | #include "app/ui_context.h"
 | 
					
						
							| 
									
										
										
										
											2015-04-02 20:55:18 +08:00
										 |  |  | #include "app/util/new_image_from_mask.h"
 | 
					
						
							| 
									
										
										
										
											2015-07-30 03:35:34 +08:00
										 |  |  | #include "base/bind.h"
 | 
					
						
							| 
									
										
										
										
											2015-06-17 02:04:00 +08:00
										 |  |  | #include "base/pi.h"
 | 
					
						
							| 
									
										
										
										
											2014-10-21 09:21:31 +08:00
										 |  |  | #include "doc/layer.h"
 | 
					
						
							|  |  |  | #include "doc/mask.h"
 | 
					
						
							| 
									
										
										
										
											2017-03-07 06:27:43 +08:00
										 |  |  | #include "doc/slice.h"
 | 
					
						
							| 
									
										
										
										
											2014-10-21 09:21:31 +08:00
										 |  |  | #include "doc/sprite.h"
 | 
					
						
							| 
									
										
										
										
											2015-04-02 20:55:18 +08:00
										 |  |  | #include "fixmath/fixmath.h"
 | 
					
						
							|  |  |  | #include "gfx/rect.h"
 | 
					
						
							| 
									
										
										
										
											2015-10-29 07:00:18 +08:00
										 |  |  | #include "she/surface.h"
 | 
					
						
							| 
									
										
										
										
											2017-09-08 23:07:21 +08:00
										 |  |  | #include "she/system.h"
 | 
					
						
							| 
									
										
										
										
											2012-06-18 09:49:58 +08:00
										 |  |  | #include "ui/alert.h"
 | 
					
						
							|  |  |  | #include "ui/message.h"
 | 
					
						
							|  |  |  | #include "ui/system.h"
 | 
					
						
							|  |  |  | #include "ui/view.h"
 | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-14 08:47:30 +08:00
										 |  |  | #include <cmath>
 | 
					
						
							| 
									
										
										
										
											2016-04-20 01:24:27 +08:00
										 |  |  | #include <cstring>
 | 
					
						
							| 
									
										
										
										
											2015-08-14 08:47:30 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-08-06 08:20:19 +08:00
										 |  |  | namespace app { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-18 09:02:54 +08:00
										 |  |  | using namespace ui; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-07 05:41:18 +08:00
										 |  |  | static CursorType rotated_size_cursors[8] = { | 
					
						
							| 
									
										
										
										
											2014-08-11 06:51:14 +08:00
										 |  |  |   kSizeECursor, | 
					
						
							|  |  |  |   kSizeNECursor, | 
					
						
							|  |  |  |   kSizeNCursor, | 
					
						
							|  |  |  |   kSizeNWCursor, | 
					
						
							|  |  |  |   kSizeWCursor, | 
					
						
							|  |  |  |   kSizeSWCursor, | 
					
						
							|  |  |  |   kSizeSCursor, | 
					
						
							|  |  |  |   kSizeSECursor | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-15 10:38:06 +08:00
										 |  |  | #ifdef _MSC_VER
 | 
					
						
							| 
									
										
										
										
											2012-01-08 03:32:03 +08:00
										 |  |  | #pragma warning(disable:4355) // warning C4355: 'this' : used in base member initializer list
 | 
					
						
							| 
									
										
										
										
											2014-08-15 10:38:06 +08:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2012-01-08 03:32:03 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  | StandbyState::StandbyState() | 
					
						
							|  |  |  |   : m_decorator(new Decorator(this)) | 
					
						
							| 
									
										
										
										
											2016-04-26 02:26:46 +08:00
										 |  |  |   , m_transformSelectionHandlesAreVisible(false) | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | StandbyState::~StandbyState() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   delete m_decorator; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-11 06:32:42 +08:00
										 |  |  | void StandbyState::onEnterState(Editor* editor) | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-02-18 22:40:11 +08:00
										 |  |  |   StateWithWheelBehavior::onEnterState(editor); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  |   editor->setDecorator(m_decorator); | 
					
						
							| 
									
										
										
										
											2015-07-30 03:35:34 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-14 21:09:15 +08:00
										 |  |  |   m_pivotVisConn = | 
					
						
							|  |  |  |     Preferences::instance().selection.pivotVisibility.AfterChange.connect( | 
					
						
							| 
									
										
										
										
											2015-12-05 02:17:42 +08:00
										 |  |  |       base::Bind<void>(&StandbyState::onPivotChange, this, editor)); | 
					
						
							| 
									
										
										
										
											2015-08-14 21:09:15 +08:00
										 |  |  |   m_pivotPosConn = | 
					
						
							|  |  |  |     Preferences::instance().selection.pivotPosition.AfterChange.connect( | 
					
						
							| 
									
										
										
										
											2015-12-05 02:17:42 +08:00
										 |  |  |       base::Bind<void>(&StandbyState::onPivotChange, this, editor)); | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-26 02:20:53 +08:00
										 |  |  | void StandbyState::onActiveToolChange(Editor* editor, tools::Tool* tool) | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  | { | 
					
						
							|  |  |  |   // If the user change from a selection tool to a non-selection tool,
 | 
					
						
							|  |  |  |   // or viceversa, we've to show or hide the transformation handles.
 | 
					
						
							| 
									
										
										
										
											2016-04-26 02:26:46 +08:00
										 |  |  |   bool needDecorators = (tool && tool->getInk(0)->isSelection()); | 
					
						
							| 
									
										
										
										
											2016-10-26 06:15:36 +08:00
										 |  |  |   if (m_transformSelectionHandlesAreVisible != needDecorators || | 
					
						
							|  |  |  |       !editor->layer() || | 
					
						
							|  |  |  |       !editor->layer()->isReference()) { | 
					
						
							| 
									
										
										
										
											2016-04-26 02:26:46 +08:00
										 |  |  |     m_transformSelectionHandlesAreVisible = false; | 
					
						
							|  |  |  |     editor->invalidate(); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-07-29 08:17:07 +08:00
										 |  |  | bool StandbyState::onMouseDown(Editor* editor, MouseMessage* msg) | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  | { | 
					
						
							|  |  |  |   if (editor->hasCapture()) | 
					
						
							|  |  |  |     return true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   UIContext* context = UIContext::instance(); | 
					
						
							| 
									
										
										
										
											2014-08-19 19:17:57 +08:00
										 |  |  |   tools::Ink* clickedInk = editor->getCurrentEditorInk(); | 
					
						
							| 
									
										
										
										
											2015-04-21 03:27:09 +08:00
										 |  |  |   Site site; | 
					
						
							|  |  |  |   editor->getSite(&site); | 
					
						
							|  |  |  |   app::Document* document = static_cast<app::Document*>(site.document()); | 
					
						
							|  |  |  |   Layer* layer = site.layer(); | 
					
						
							| 
									
										
										
										
											2013-01-21 05:40:37 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // When an editor is clicked the current view is changed.
 | 
					
						
							|  |  |  |   context->setActiveView(editor->getDocumentView()); | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // Start scroll loop
 | 
					
						
							| 
									
										
										
										
											2017-01-07 04:44:08 +08:00
										 |  |  |   if (editor->checkForScroll(msg) || | 
					
						
							|  |  |  |       editor->checkForZoom(msg)) | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  |     return true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Move cel X,Y coordinates
 | 
					
						
							| 
									
										
										
										
											2012-01-12 11:46:04 +08:00
										 |  |  |   if (clickedInk->isCelMovement()) { | 
					
						
							| 
									
										
										
										
											2014-11-17 05:33:31 +08:00
										 |  |  |     // Handle "Auto Select Layer"
 | 
					
						
							|  |  |  |     if (editor->isAutoSelectLayer()) { | 
					
						
							| 
									
										
										
										
											2016-10-14 06:58:42 +08:00
										 |  |  |       gfx::PointF cursor = editor->screenToEditorF(msg->position()); | 
					
						
							| 
									
										
										
										
											2014-11-24 11:09:22 +08:00
										 |  |  |       ColorPicker picker; | 
					
						
							| 
									
										
										
										
											2016-10-14 06:58:42 +08:00
										 |  |  |       picker.pickColor(site, cursor, | 
					
						
							|  |  |  |                        editor->projection(), | 
					
						
							|  |  |  |                        ColorPicker::FromComposition); | 
					
						
							| 
									
										
										
										
											2014-11-17 05:33:31 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-23 00:19:06 +08:00
										 |  |  |       auto range = App::instance()->timeline()->range(); | 
					
						
							| 
									
										
										
										
											2017-02-08 11:28:46 +08:00
										 |  |  |       if (picker.layer() && | 
					
						
							|  |  |  |           !range.contains(picker.layer())) { | 
					
						
							| 
									
										
										
										
											2014-11-17 05:33:31 +08:00
										 |  |  |         layer = picker.layer(); | 
					
						
							|  |  |  |         if (layer) { | 
					
						
							|  |  |  |           editor->setLayer(layer); | 
					
						
							|  |  |  |           editor->flashCurrentLayer(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-01 06:58:04 +08:00
										 |  |  |     if (layer) { | 
					
						
							| 
									
										
										
										
											2014-11-24 22:50:02 +08:00
										 |  |  |       // TODO we should be able to move the `Background' with tiled mode
 | 
					
						
							| 
									
										
										
										
											2013-03-12 07:29:45 +08:00
										 |  |  |       if (layer->isBackground()) { | 
					
						
							| 
									
										
										
										
											2014-11-24 22:50:02 +08:00
										 |  |  |         StatusBar::instance()->showTip(1000, | 
					
						
							|  |  |  |           "The background layer cannot be moved"); | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2016-06-16 02:27:38 +08:00
										 |  |  |       else if (!layer->isVisibleHierarchy()) { | 
					
						
							| 
									
										
										
										
											2014-11-30 20:43:33 +08:00
										 |  |  |         StatusBar::instance()->showTip(1000, | 
					
						
							|  |  |  |           "Layer '%s' is hidden", layer->name().c_str()); | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2016-06-16 02:27:38 +08:00
										 |  |  |       else if (!layer->isMovable() || !layer->isEditableHierarchy()) { | 
					
						
							| 
									
										
										
										
											2014-11-24 22:50:02 +08:00
										 |  |  |         StatusBar::instance()->showTip(1000, | 
					
						
							|  |  |  |           "Layer '%s' is locked", layer->name().c_str()); | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  |       } | 
					
						
							|  |  |  |       else { | 
					
						
							| 
									
										
										
										
											2016-12-01 06:58:04 +08:00
										 |  |  |         MovingCelCollect collect(editor, layer); | 
					
						
							|  |  |  |         if (collect.empty()) { | 
					
						
							|  |  |  |           StatusBar::instance()->showTip( | 
					
						
							|  |  |  |             1000, "Nothing to move"); | 
					
						
							| 
									
										
										
										
											2016-11-08 04:16:40 +08:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2016-12-01 06:58:04 +08:00
										 |  |  |         else { | 
					
						
							|  |  |  |           try { | 
					
						
							|  |  |  |             // Change to MovingCelState
 | 
					
						
							| 
									
										
										
										
											2017-04-07 02:26:01 +08:00
										 |  |  |             HandleType handle = MovePixelsHandle; | 
					
						
							| 
									
										
										
										
											2016-12-01 06:58:04 +08:00
										 |  |  |             if (resizeCelBounds(editor).contains(msg->position())) | 
					
						
							|  |  |  |               handle = ScaleSEHandle; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             MovingCelState* newState = new MovingCelState( | 
					
						
							|  |  |  |               editor, msg, handle, collect); | 
					
						
							|  |  |  |             editor->setState(EditorStatePtr(newState)); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           catch (const LockedDocumentException&) { | 
					
						
							|  |  |  |             // TODO break the background task that is locking this sprite
 | 
					
						
							|  |  |  |             StatusBar::instance()->showTip( | 
					
						
							|  |  |  |               1000, "Sprite is used by a backup/data recovery task"); | 
					
						
							|  |  |  |           } | 
					
						
							| 
									
										
										
										
											2016-11-08 04:16:40 +08:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2014-11-17 05:33:31 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  |     return true; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-13 22:23:45 +08:00
										 |  |  |   // Call the eyedropper command
 | 
					
						
							|  |  |  |   if (clickedInk->isEyedropper()) { | 
					
						
							| 
									
										
										
										
											2015-08-20 05:05:03 +08:00
										 |  |  |     editor->captureMouse(); | 
					
						
							| 
									
										
										
										
											2014-11-13 22:23:45 +08:00
										 |  |  |     callEyedropper(editor); | 
					
						
							|  |  |  |     return true; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-07 06:27:43 +08:00
										 |  |  |   if (clickedInk->isSlice()) { | 
					
						
							|  |  |  |     EditorHit hit = editor->calcHit(msg->position()); | 
					
						
							|  |  |  |     switch (hit.type()) { | 
					
						
							|  |  |  |       case EditorHit::SliceBounds: | 
					
						
							|  |  |  |       case EditorHit::SliceCenter: | 
					
						
							|  |  |  |         if (msg->left()) { | 
					
						
							|  |  |  |           MovingSliceState* newState = new MovingSliceState(editor, msg, hit); | 
					
						
							|  |  |  |           editor->setState(EditorStatePtr(newState)); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else { | 
					
						
							|  |  |  |           Menu* popupMenu = AppMenus::instance()->getSlicePopupMenu(); | 
					
						
							|  |  |  |           if (popupMenu) { | 
					
						
							|  |  |  |             Params params; | 
					
						
							|  |  |  |             params.set("id", base::convert_to<std::string>(hit.slice()->id()).c_str()); | 
					
						
							|  |  |  |             AppMenuItem::setContextParams(params); | 
					
						
							|  |  |  |             popupMenu->showPopup(msg->position()); | 
					
						
							|  |  |  |             AppMenuItem::setContextParams(Params()); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-01 08:07:30 +08:00
										 |  |  |   // Only if the selected tool or quick tool is selection, we give the
 | 
					
						
							|  |  |  |   // possibility to transform/move the selection. In other case,
 | 
					
						
							|  |  |  |   // e.g. when selection is used with right-click mode, the
 | 
					
						
							|  |  |  |   // transformation is disabled.
 | 
					
						
							|  |  |  |   auto activeToolManager = App::instance()->activeToolManager(); | 
					
						
							|  |  |  |   if (clickedInk->isSelection() && | 
					
						
							|  |  |  |       ((activeToolManager->selectedTool() && | 
					
						
							|  |  |  |         activeToolManager->selectedTool()->getInk(0)->isSelection()) || | 
					
						
							|  |  |  |        (activeToolManager->quickTool() && | 
					
						
							|  |  |  |         activeToolManager->quickTool()->getInk(0)->isSelection()))) { | 
					
						
							| 
									
										
										
										
											2014-11-13 22:23:45 +08:00
										 |  |  |     // Transform selected pixels
 | 
					
						
							| 
									
										
										
										
											2015-10-29 07:00:18 +08:00
										 |  |  |     if (editor->isActive() && | 
					
						
							|  |  |  |         document->isMaskVisible() && | 
					
						
							| 
									
										
										
										
											2017-09-08 23:07:21 +08:00
										 |  |  |         m_decorator->getTransformHandles(editor) && | 
					
						
							|  |  |  |         (!Preferences::instance().selection.modifiersDisableHandles() || | 
					
						
							|  |  |  |          msg->modifiers() == kKeyNoneModifier)) { | 
					
						
							| 
									
										
										
										
											2014-11-13 22:23:45 +08:00
										 |  |  |       TransformHandles* transfHandles = m_decorator->getTransformHandles(editor); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // Get the handle covered by the mouse.
 | 
					
						
							|  |  |  |       HandleType handle = transfHandles->getHandleAtPoint(editor, | 
					
						
							|  |  |  |         msg->position(), | 
					
						
							|  |  |  |         document->getTransformation()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (handle != NoHandle) { | 
					
						
							|  |  |  |         int x, y, opacity; | 
					
						
							| 
									
										
										
										
											2015-04-21 03:27:09 +08:00
										 |  |  |         Image* image = site.image(&x, &y, &opacity); | 
					
						
							| 
									
										
										
										
											2015-01-28 22:04:07 +08:00
										 |  |  |         if (layer && image) { | 
					
						
							| 
									
										
										
										
											2016-06-16 02:27:38 +08:00
										 |  |  |           if (!layer->isEditableHierarchy()) { | 
					
						
							| 
									
										
										
										
											2014-11-24 22:50:02 +08:00
										 |  |  |             StatusBar::instance()->showTip(1000, | 
					
						
							|  |  |  |               "Layer '%s' is locked", layer->name().c_str()); | 
					
						
							| 
									
										
										
										
											2014-11-13 22:23:45 +08:00
										 |  |  |             return true; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           // Change to MovingPixelsState
 | 
					
						
							|  |  |  |           transformSelection(editor, msg, handle); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return true; | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-07 02:26:01 +08:00
										 |  |  |     // Move selection edges
 | 
					
						
							|  |  |  |     if (overSelectionEdges(editor, msg->position())) { | 
					
						
							|  |  |  |       transformSelection(editor, msg, MoveSelectionHandle); | 
					
						
							|  |  |  |       return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-13 22:23:45 +08:00
										 |  |  |     // Move selected pixels
 | 
					
						
							| 
									
										
										
										
											2017-09-28 00:07:37 +08:00
										 |  |  |     if (layer && editor->canStartMovingSelectionPixels() && msg->left()) { | 
					
						
							| 
									
										
										
										
											2016-06-16 02:27:38 +08:00
										 |  |  |       if (!layer->isEditableHierarchy()) { | 
					
						
							| 
									
										
										
										
											2014-11-24 22:50:02 +08:00
										 |  |  |         StatusBar::instance()->showTip(1000, | 
					
						
							|  |  |  |           "Layer '%s' is locked", layer->name().c_str()); | 
					
						
							| 
									
										
										
										
											2014-11-13 22:23:45 +08:00
										 |  |  |         return true; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // Change to MovingPixelsState
 | 
					
						
							| 
									
										
										
										
											2017-04-07 02:26:01 +08:00
										 |  |  |       transformSelection(editor, msg, MovePixelsHandle); | 
					
						
							| 
									
										
										
										
											2014-08-25 06:37:24 +08:00
										 |  |  |       return true; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-29 07:00:18 +08:00
										 |  |  |   // Move symmetry
 | 
					
						
							| 
									
										
										
										
											2017-03-28 02:27:37 +08:00
										 |  |  |   Decorator::Handles handles; | 
					
						
							|  |  |  |   if (m_decorator->getSymmetryHandles(editor, handles)) { | 
					
						
							|  |  |  |     for (const auto& handle : handles) { | 
					
						
							|  |  |  |       if (handle.bounds.contains(msg->position())) { | 
					
						
							|  |  |  |         auto mode = (handle.align & (TOP | BOTTOM) ? app::gen::SymmetryMode::HORIZONTAL: | 
					
						
							|  |  |  |                                                      app::gen::SymmetryMode::VERTICAL); | 
					
						
							|  |  |  |         bool horz = (mode == app::gen::SymmetryMode::HORIZONTAL); | 
					
						
							|  |  |  |         auto& symmetry = Preferences::instance().document(editor->document()).symmetry; | 
					
						
							|  |  |  |         auto& axis = (horz ? symmetry.xAxis: | 
					
						
							|  |  |  |                              symmetry.yAxis); | 
					
						
							|  |  |  |         editor->setState( | 
					
						
							|  |  |  |           EditorStatePtr(new MovingSymmetryState(editor, msg, mode, axis))); | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-10-29 07:00:18 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  |   // Start the Tool-Loop
 | 
					
						
							| 
									
										
										
										
											2016-12-08 20:37:28 +08:00
										 |  |  |   if (layer && (layer->isImage() || clickedInk->isSelection())) { | 
					
						
							| 
									
										
										
										
											2017-09-09 03:04:18 +08:00
										 |  |  |     // Shift+click on Pencil tool starts a line onMouseDown() when the
 | 
					
						
							|  |  |  |     // preview (onKeyDown) is disabled.
 | 
					
						
							|  |  |  |     if (!Preferences::instance().editor.straightLinePreview() && | 
					
						
							|  |  |  |         checkStartDrawingStraightLine(editor)) { | 
					
						
							|  |  |  |       // Send first mouse down to draw the straight line and start the
 | 
					
						
							|  |  |  |       // freehand mode.
 | 
					
						
							|  |  |  |       editor->getState()->onMouseDown(editor, msg); | 
					
						
							|  |  |  |       return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-04 23:32:39 +08:00
										 |  |  |     // Disable layer edges to avoid showing the modified cel
 | 
					
						
							|  |  |  |     // information by ExpandCelCanvas (i.e. the cel origin is changed
 | 
					
						
							|  |  |  |     // to 0,0 coordinate.)
 | 
					
						
							|  |  |  |     auto& layerEdgesOption = editor->docPref().show.layerEdges; | 
					
						
							|  |  |  |     bool layerEdges = layerEdgesOption(); | 
					
						
							|  |  |  |     if (layerEdges) | 
					
						
							|  |  |  |       layerEdgesOption(false); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-17 03:28:48 +08:00
										 |  |  |     startDrawingState(editor, | 
					
						
							|  |  |  |                       DrawingType::Regular, | 
					
						
							|  |  |  |                       pointer_from_msg(editor, msg)); | 
					
						
							| 
									
										
										
										
											2016-05-04 23:32:39 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // Restore layer edges
 | 
					
						
							|  |  |  |     if (layerEdges) | 
					
						
							|  |  |  |       layerEdgesOption(true); | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  |     return true; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-07-29 08:17:07 +08:00
										 |  |  | bool StandbyState::onMouseUp(Editor* editor, MouseMessage* msg) | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  | { | 
					
						
							|  |  |  |   editor->releaseMouse(); | 
					
						
							|  |  |  |   return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-07-29 08:17:07 +08:00
										 |  |  | bool StandbyState::onMouseMove(Editor* editor, MouseMessage* msg) | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2014-08-19 19:17:57 +08:00
										 |  |  |   // We control eyedropper tool from here. TODO move this to another place
 | 
					
						
							|  |  |  |   if (msg->left() || msg->right()) { | 
					
						
							|  |  |  |     tools::Ink* clickedInk = editor->getCurrentEditorInk(); | 
					
						
							| 
									
										
										
										
											2015-08-20 05:05:03 +08:00
										 |  |  |     if (clickedInk->isEyedropper() && | 
					
						
							|  |  |  |         editor->hasCapture()) { | 
					
						
							| 
									
										
										
										
											2014-11-13 22:23:45 +08:00
										 |  |  |       callEyedropper(editor); | 
					
						
							| 
									
										
										
										
											2015-08-20 05:05:03 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2014-08-19 19:17:57 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  |   editor->updateStatusBar(); | 
					
						
							|  |  |  |   return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-19 22:33:05 +08:00
										 |  |  | bool StandbyState::onDoubleClick(Editor* editor, MouseMessage* msg) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (editor->hasCapture()) | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   tools::Ink* ink = editor->getCurrentEditorInk(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Select a tile with double-click
 | 
					
						
							|  |  |  |   if (ink->isSelection()) { | 
					
						
							|  |  |  |     Command* selectTileCmd = | 
					
						
							|  |  |  |       CommandsModule::instance()->getCommandByName(CommandId::SelectTile); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-19 23:09:03 +08:00
										 |  |  |     Params params; | 
					
						
							| 
									
										
										
										
											2016-04-05 05:46:48 +08:00
										 |  |  |     if (int(editor->getToolLoopModifiers()) & int(tools::ToolLoopModifiers::kAddSelection)) | 
					
						
							|  |  |  |       params.set("mode", "add"); | 
					
						
							|  |  |  |     else if (int(editor->getToolLoopModifiers()) & int(tools::ToolLoopModifiers::kSubtractSelection)) | 
					
						
							|  |  |  |       params.set("mode", "subtract"); | 
					
						
							| 
									
										
										
										
											2016-03-19 23:09:03 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     UIContext::instance()->executeCommand(selectTileCmd, params); | 
					
						
							| 
									
										
										
										
											2016-03-19 23:04:39 +08:00
										 |  |  |     return true; | 
					
						
							| 
									
										
										
										
											2016-03-19 22:33:05 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-25 23:44:47 +08:00
										 |  |  | bool StandbyState::onSetCursor(Editor* editor, const gfx::Point& mouseScreenPos) | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2014-08-19 19:17:57 +08:00
										 |  |  |   tools::Ink* ink = editor->getCurrentEditorInk(); | 
					
						
							| 
									
										
										
										
											2015-10-29 07:00:18 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // See if the cursor is in some selection handle.
 | 
					
						
							|  |  |  |   if (m_decorator->onSetCursor(ink, editor, mouseScreenPos)) | 
					
						
							|  |  |  |     return true; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-19 19:17:57 +08:00
										 |  |  |   if (ink) { | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  |     // If the current tool change selection (e.g. rectangular marquee, etc.)
 | 
					
						
							| 
									
										
										
										
											2014-08-19 19:17:57 +08:00
										 |  |  |     if (ink->isSelection()) { | 
					
						
							| 
									
										
										
										
											2017-04-07 02:26:01 +08:00
										 |  |  |       if (overSelectionEdges(editor, mouseScreenPos)) { | 
					
						
							| 
									
										
										
										
											2017-04-07 05:41:18 +08:00
										 |  |  |         editor->showMouseCursor( | 
					
						
							|  |  |  |           kCustomCursor, skin::SkinTheme::instance()->cursors.moveSelection()); | 
					
						
							| 
									
										
										
										
											2017-04-07 02:26:01 +08:00
										 |  |  |         return true; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  |       // Move pixels
 | 
					
						
							| 
									
										
										
										
											2017-09-28 00:07:37 +08:00
										 |  |  |       if (editor->canStartMovingSelectionPixels()) { | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  |         EditorCustomizationDelegate* customization = editor->getCustomizationDelegate(); | 
					
						
							| 
									
										
										
										
											2015-08-26 00:29:19 +08:00
										 |  |  |         if ((customization) && | 
					
						
							| 
									
										
										
										
											2015-09-12 07:04:02 +08:00
										 |  |  |             int(customization->getPressedKeyAction(KeyContext::TranslatingSelection) & KeyAction::CopySelection)) | 
					
						
							| 
									
										
										
										
											2015-06-25 23:44:47 +08:00
										 |  |  |           editor->showMouseCursor(kArrowPlusCursor); | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  |         else | 
					
						
							| 
									
										
										
										
											2015-06-25 23:44:47 +08:00
										 |  |  |           editor->showMouseCursor(kMoveCursor); | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2016-05-03 05:42:02 +08:00
										 |  |  |       else | 
					
						
							|  |  |  |         editor->showBrushPreview(mouseScreenPos); | 
					
						
							|  |  |  |       return true; | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2014-08-19 19:17:57 +08:00
										 |  |  |     else if (ink->isEyedropper()) { | 
					
						
							| 
									
										
										
										
											2017-04-07 05:41:18 +08:00
										 |  |  |       editor->showMouseCursor( | 
					
						
							|  |  |  |         kCustomCursor, skin::SkinTheme::instance()->cursors.eyedropper()); | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  |       return true; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2014-08-19 19:17:57 +08:00
										 |  |  |     else if (ink->isZoom()) { | 
					
						
							| 
									
										
										
										
											2017-04-07 05:41:18 +08:00
										 |  |  |       editor->showMouseCursor( | 
					
						
							|  |  |  |         kCustomCursor, skin::SkinTheme::instance()->cursors.magnifier()); | 
					
						
							| 
									
										
										
										
											2014-04-20 07:08:21 +08:00
										 |  |  |       return true; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2014-08-19 19:17:57 +08:00
										 |  |  |     else if (ink->isScrollMovement()) { | 
					
						
							| 
									
										
										
										
											2015-06-25 23:44:47 +08:00
										 |  |  |       editor->showMouseCursor(kScrollCursor); | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  |       return true; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2014-08-19 19:17:57 +08:00
										 |  |  |     else if (ink->isCelMovement()) { | 
					
						
							| 
									
										
										
										
											2016-10-26 06:15:36 +08:00
										 |  |  |       if (resizeCelBounds(editor).contains(mouseScreenPos)) | 
					
						
							|  |  |  |         editor->showMouseCursor(kSizeSECursor); | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  |         editor->showMouseCursor(kMoveCursor); | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  |       return true; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2014-08-19 19:17:57 +08:00
										 |  |  |     else if (ink->isSlice()) { | 
					
						
							| 
									
										
										
										
											2017-03-07 06:27:43 +08:00
										 |  |  |       EditorHit hit = editor->calcHit(mouseScreenPos); | 
					
						
							|  |  |  |       switch (hit.type()) { | 
					
						
							|  |  |  |         case EditorHit::None: | 
					
						
							|  |  |  |           // Do nothing, continue
 | 
					
						
							|  |  |  |           break; | 
					
						
							|  |  |  |         case EditorHit::SliceBounds: | 
					
						
							|  |  |  |         case EditorHit::SliceCenter: | 
					
						
							|  |  |  |           switch (hit.border()) { | 
					
						
							| 
									
										
										
										
											2017-03-16 23:08:56 +08:00
										 |  |  |             case CENTER | MIDDLE: | 
					
						
							|  |  |  |               editor->showMouseCursor(kMoveCursor); | 
					
						
							|  |  |  |               break; | 
					
						
							| 
									
										
										
										
											2017-03-07 06:27:43 +08:00
										 |  |  |             case TOP | LEFT: | 
					
						
							|  |  |  |               editor->showMouseCursor(kSizeNWCursor); | 
					
						
							|  |  |  |               break; | 
					
						
							|  |  |  |             case TOP: | 
					
						
							|  |  |  |               editor->showMouseCursor(kSizeNCursor); | 
					
						
							|  |  |  |               break; | 
					
						
							|  |  |  |             case TOP | RIGHT: | 
					
						
							|  |  |  |               editor->showMouseCursor(kSizeNECursor); | 
					
						
							|  |  |  |               break; | 
					
						
							|  |  |  |             case LEFT: | 
					
						
							|  |  |  |               editor->showMouseCursor(kSizeWCursor); | 
					
						
							|  |  |  |               break; | 
					
						
							|  |  |  |             case RIGHT: | 
					
						
							|  |  |  |               editor->showMouseCursor(kSizeECursor); | 
					
						
							|  |  |  |               break; | 
					
						
							|  |  |  |             case BOTTOM | LEFT: | 
					
						
							|  |  |  |               editor->showMouseCursor(kSizeSWCursor); | 
					
						
							|  |  |  |               break; | 
					
						
							|  |  |  |             case BOTTOM: | 
					
						
							|  |  |  |               editor->showMouseCursor(kSizeSCursor); | 
					
						
							|  |  |  |               break; | 
					
						
							|  |  |  |             case BOTTOM | RIGHT: | 
					
						
							|  |  |  |               editor->showMouseCursor(kSizeSECursor); | 
					
						
							|  |  |  |               break; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           return true; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2014-06-28 09:58:38 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Draw
 | 
					
						
							|  |  |  |   if (editor->canDraw()) { | 
					
						
							| 
									
										
										
										
											2015-06-25 23:44:47 +08:00
										 |  |  |     editor->showBrushPreview(mouseScreenPos); | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  |   } | 
					
						
							|  |  |  |   // Forbidden
 | 
					
						
							|  |  |  |   else { | 
					
						
							| 
									
										
										
										
											2015-06-25 23:44:47 +08:00
										 |  |  |     editor->showMouseCursor(kForbiddenCursor); | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-07-29 08:17:07 +08:00
										 |  |  | bool StandbyState::onKeyDown(Editor* editor, KeyMessage* msg) | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2017-09-09 03:04:18 +08:00
										 |  |  |   if (Preferences::instance().editor.straightLinePreview() && | 
					
						
							|  |  |  |       checkStartDrawingStraightLine(editor)) | 
					
						
							| 
									
										
										
										
											2017-06-17 03:42:37 +08:00
										 |  |  |     return true; | 
					
						
							| 
									
										
										
										
											2014-08-13 11:22:29 +08:00
										 |  |  |   return false; | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-07-29 08:17:07 +08:00
										 |  |  | bool StandbyState::onKeyUp(Editor* editor, KeyMessage* msg) | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  | { | 
					
						
							|  |  |  |   return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool StandbyState::onUpdateStatusBar(Editor* editor) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2014-08-19 19:17:57 +08:00
										 |  |  |   tools::Ink* ink = editor->getCurrentEditorInk(); | 
					
						
							| 
									
										
										
										
											2014-07-30 12:28:15 +08:00
										 |  |  |   const Sprite* sprite = editor->sprite(); | 
					
						
							| 
									
										
										
										
											2016-10-14 06:58:42 +08:00
										 |  |  |   gfx::PointF spritePos = editor->screenToEditorF(ui::get_mouse_position()); | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (!sprite) { | 
					
						
							| 
									
										
										
										
											2012-07-10 00:20:58 +08:00
										 |  |  |     StatusBar::instance()->clearText(); | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  |   } | 
					
						
							|  |  |  |   // For eye-dropper
 | 
					
						
							| 
									
										
										
										
											2014-08-19 19:17:57 +08:00
										 |  |  |   else if (ink->isEyedropper()) { | 
					
						
							| 
									
										
										
										
											2015-07-03 05:13:47 +08:00
										 |  |  |     EyedropperCommand cmd; | 
					
						
							|  |  |  |     app::Color color = Preferences::instance().colorBar.fgColor(); | 
					
						
							| 
									
										
										
										
											2016-10-14 06:58:42 +08:00
										 |  |  |     cmd.pickSample(editor->getSite(), | 
					
						
							|  |  |  |                    spritePos, | 
					
						
							|  |  |  |                    editor->projection(), | 
					
						
							|  |  |  |                    color); | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     char buf[256]; | 
					
						
							| 
									
										
										
										
											2016-10-14 06:58:42 +08:00
										 |  |  |     sprintf(buf, " :pos: %d %d", | 
					
						
							| 
									
										
										
										
											2016-12-27 03:44:40 +08:00
										 |  |  |             int(std::floor(spritePos.x)), | 
					
						
							|  |  |  |             int(std::floor(spritePos.y))); | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-03 05:13:47 +08:00
										 |  |  |     StatusBar::instance()->showColor(0, buf, color); | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							| 
									
										
										
										
											2013-03-12 07:29:45 +08:00
										 |  |  |     Mask* mask = | 
					
						
							| 
									
										
										
										
											2015-02-12 23:16:25 +08:00
										 |  |  |       (editor->document()->isMaskVisible() ? | 
					
						
							| 
									
										
										
										
											2014-07-30 12:28:15 +08:00
										 |  |  |        editor->document()->mask(): NULL); | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-20 00:45:23 +08:00
										 |  |  |     char buf[1024]; | 
					
						
							|  |  |  |     sprintf( | 
					
						
							|  |  |  |       buf, ":pos: %d %d :%s: %d %d", | 
					
						
							| 
									
										
										
										
											2016-12-27 03:44:40 +08:00
										 |  |  |       int(std::floor(spritePos.x)), | 
					
						
							|  |  |  |       int(std::floor(spritePos.y)), | 
					
						
							| 
									
										
										
										
											2016-04-20 00:45:23 +08:00
										 |  |  |       (mask ? "selsize": "size"), | 
					
						
							| 
									
										
										
										
											2014-07-30 12:28:15 +08:00
										 |  |  |       (mask ? mask->bounds().w: sprite->width()), | 
					
						
							| 
									
										
										
										
											2016-04-20 00:45:23 +08:00
										 |  |  |       (mask ? mask->bounds().h: sprite->height())); | 
					
						
							| 
									
										
										
										
											2016-04-20 02:51:34 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-20 00:45:23 +08:00
										 |  |  |     if (sprite->totalFrames() > 1) { | 
					
						
							|  |  |  |       sprintf( | 
					
						
							| 
									
										
										
										
											2016-04-20 01:24:27 +08:00
										 |  |  |         buf+std::strlen(buf), " :frame: %d :clock: %d", | 
					
						
							| 
									
										
										
										
											2016-11-23 05:05:56 +08:00
										 |  |  |         editor->frame()+editor->docPref().timeline.firstFrame(), | 
					
						
							| 
									
										
										
										
											2016-04-20 00:45:23 +08:00
										 |  |  |         sprite->frameDuration(editor->frame())); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-20 02:51:34 +08:00
										 |  |  |     if (editor->docPref().show.grid()) { | 
					
						
							|  |  |  |       auto gb = editor->docPref().grid.bounds(); | 
					
						
							| 
									
										
										
										
											2017-04-20 06:25:57 +08:00
										 |  |  |       int col = int((std::floor(spritePos.x) - (gb.x % gb.w)) / gb.w); | 
					
						
							|  |  |  |       int row = int((std::floor(spritePos.y) - (gb.y % gb.h)) / gb.h); | 
					
						
							| 
									
										
										
										
											2016-04-20 02:51:34 +08:00
										 |  |  |       sprintf( | 
					
						
							|  |  |  |         buf+std::strlen(buf), " :grid: %d %d", col, row); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-07 06:27:43 +08:00
										 |  |  |     if (editor->docPref().show.slices()) { | 
					
						
							|  |  |  |       int count = 0; | 
					
						
							|  |  |  |       for (auto slice : editor->document()->sprite()->slices()) { | 
					
						
							|  |  |  |         auto key = slice->getByFrame(editor->frame()); | 
					
						
							|  |  |  |         if (key && | 
					
						
							|  |  |  |             key->bounds().contains( | 
					
						
							|  |  |  |               int(std::floor(spritePos.x)), | 
					
						
							|  |  |  |               int(std::floor(spritePos.y)))) { | 
					
						
							|  |  |  |           if (++count == 3) { | 
					
						
							|  |  |  |             sprintf( | 
					
						
							|  |  |  |               buf+std::strlen(buf), " :slice: ..."); | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           sprintf( | 
					
						
							|  |  |  |             buf+std::strlen(buf), " :slice: %s", | 
					
						
							|  |  |  |             slice->name().c_str()); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-20 00:45:23 +08:00
										 |  |  |     StatusBar::instance()->setStatusText(0, buf); | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-17 03:28:48 +08:00
										 |  |  | DrawingState* StandbyState::startDrawingState(Editor* editor, | 
					
						
							|  |  |  |                                               const DrawingType drawingType, | 
					
						
							|  |  |  |                                               const tools::Pointer& pointer) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   // We need to clear and redraw the brush boundaries after the
 | 
					
						
							|  |  |  |   // first mouse pressed/point shape if drawn. This is to avoid
 | 
					
						
							|  |  |  |   // graphical glitches (invalid areas in the ToolLoop's src/dst
 | 
					
						
							|  |  |  |   // images).
 | 
					
						
							|  |  |  |   HideBrushPreview hide(editor->brushPreview()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   tools::ToolLoop* toolLoop = create_tool_loop( | 
					
						
							|  |  |  |     editor, | 
					
						
							|  |  |  |     UIContext::instance(), | 
					
						
							|  |  |  |     (drawingType == DrawingType::LineFreehand)); | 
					
						
							|  |  |  |   if (!toolLoop) | 
					
						
							|  |  |  |     return nullptr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   EditorStatePtr newState( | 
					
						
							| 
									
										
										
										
											2017-06-20 00:17:09 +08:00
										 |  |  |     new DrawingState(editor, | 
					
						
							|  |  |  |                      toolLoop, | 
					
						
							| 
									
										
										
										
											2017-06-17 03:28:48 +08:00
										 |  |  |                      drawingType)); | 
					
						
							|  |  |  |   editor->setState(newState); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   static_cast<DrawingState*>(newState.get()) | 
					
						
							|  |  |  |     ->initToolLoop(editor, | 
					
						
							|  |  |  |                    pointer); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return static_cast<DrawingState*>(newState.get()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-17 03:42:37 +08:00
										 |  |  | bool StandbyState::checkStartDrawingStraightLine(Editor* editor) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   // Start line preview with shift key
 | 
					
						
							|  |  |  |   if (editor->startStraightLineWithFreehandTool()) { | 
					
						
							|  |  |  |     DrawingState* drawingState = | 
					
						
							|  |  |  |       startDrawingState(editor, | 
					
						
							|  |  |  |                         DrawingType::LineFreehand, | 
					
						
							|  |  |  |                         tools::Pointer( | 
					
						
							|  |  |  |                           editor->document()->lastDrawingPoint(), | 
					
						
							|  |  |  |                           tools::Pointer::Left)); | 
					
						
							|  |  |  |     if (drawingState) { | 
					
						
							|  |  |  |       drawingState->sendMovementToToolLoop( | 
					
						
							|  |  |  |         tools::Pointer( | 
					
						
							|  |  |  |           editor->screenToEditor(ui::get_mouse_position()), | 
					
						
							|  |  |  |           tools::Pointer::Left)); | 
					
						
							|  |  |  |       return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-12 01:16:01 +08:00
										 |  |  | Transformation StandbyState::getTransformation(Editor* editor) | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-07-12 01:16:01 +08:00
										 |  |  |   Transformation t = editor->document()->getTransformation(); | 
					
						
							| 
									
										
										
										
											2015-07-30 03:35:34 +08:00
										 |  |  |   set_pivot_from_preferences(t); | 
					
						
							|  |  |  |   return t; | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-14 08:47:30 +08:00
										 |  |  | void StandbyState::startSelectionTransformation(Editor* editor, | 
					
						
							|  |  |  |                                                 const gfx::Point& move, | 
					
						
							|  |  |  |                                                 double angle) | 
					
						
							| 
									
										
										
										
											2014-08-08 12:00:02 +08:00
										 |  |  | { | 
					
						
							|  |  |  |   transformSelection(editor, NULL, NoHandle); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-14 08:47:30 +08:00
										 |  |  |   if (MovingPixelsState* movingPixels = dynamic_cast<MovingPixelsState*>(editor->getState().get())) { | 
					
						
							| 
									
										
										
										
											2014-11-24 11:09:22 +08:00
										 |  |  |     movingPixels->translate(move); | 
					
						
							| 
									
										
										
										
											2015-08-14 08:47:30 +08:00
										 |  |  |     if (std::fabs(angle) > 1e-5) | 
					
						
							|  |  |  |       movingPixels->rotate(angle); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-08-08 12:00:02 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-07-29 08:17:07 +08:00
										 |  |  | void StandbyState::transformSelection(Editor* editor, MouseMessage* msg, HandleType handle) | 
					
						
							| 
									
										
										
										
											2012-01-06 10:21:51 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-08-15 00:06:26 +08:00
										 |  |  |   Document* document = editor->document(); | 
					
						
							|  |  |  |   for (auto docView : UIContext::instance()->getAllDocumentViews(document)) { | 
					
						
							| 
									
										
										
										
											2016-02-13 12:33:43 +08:00
										 |  |  |     if (docView->editor()->isMovingPixels()) { | 
					
						
							| 
									
										
										
										
											2015-08-15 00:06:26 +08:00
										 |  |  |       // TODO Transfer moving pixels state to this editor
 | 
					
						
							| 
									
										
										
										
											2016-02-13 12:33:43 +08:00
										 |  |  |       docView->editor()->dropMovingPixels(); | 
					
						
							| 
									
										
										
										
											2015-08-15 00:06:26 +08:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-07 02:26:01 +08:00
										 |  |  |   // Special case: Move only selection edges
 | 
					
						
							|  |  |  |   if (handle == MoveSelectionHandle) { | 
					
						
							|  |  |  |     EditorStatePtr newState(new MovingSelectionState(editor, msg)); | 
					
						
							|  |  |  |     editor->setState(newState); | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-07 21:30:40 +08:00
										 |  |  |   Layer* layer = editor->layer(); | 
					
						
							|  |  |  |   if (layer && layer->isReference()) { | 
					
						
							|  |  |  |     StatusBar::instance()->showTip( | 
					
						
							|  |  |  |       1000, "Layer '%s' is reference, cannot be transformed", | 
					
						
							|  |  |  |       layer->name().c_str()); | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-12-30 06:53:28 +08:00
										 |  |  |   try { | 
					
						
							| 
									
										
										
										
											2015-06-08 23:13:55 +08:00
										 |  |  |     // Clear brush preview, as the extra cel will be replaced with the
 | 
					
						
							|  |  |  |     // transformed image.
 | 
					
						
							| 
									
										
										
										
											2015-06-25 23:44:47 +08:00
										 |  |  |     editor->brushPreview().hide(); | 
					
						
							| 
									
										
										
										
											2015-06-08 23:13:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-12-30 06:53:28 +08:00
										 |  |  |     EditorCustomizationDelegate* customization = editor->getCustomizationDelegate(); | 
					
						
							| 
									
										
										
										
											2015-04-21 03:27:09 +08:00
										 |  |  |     base::UniquePtr<Image> tmpImage(new_image_from_mask(editor->getSite())); | 
					
						
							| 
									
										
										
										
											2015-06-26 01:54:06 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-12-30 06:53:28 +08:00
										 |  |  |     PixelsMovementPtr pixelsMovement( | 
					
						
							|  |  |  |       new PixelsMovement(UIContext::instance(), | 
					
						
							| 
									
										
										
										
											2015-07-24 09:42:14 +08:00
										 |  |  |                          editor->getSite(), | 
					
						
							|  |  |  |                          tmpImage, | 
					
						
							|  |  |  |                          document->mask(), | 
					
						
							|  |  |  |                          "Transformation")); | 
					
						
							| 
									
										
										
										
											2013-12-30 06:53:28 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // If the Ctrl key is pressed start dragging a copy of the selection
 | 
					
						
							| 
									
										
										
										
											2015-08-26 00:29:19 +08:00
										 |  |  |     if ((customization) && | 
					
						
							| 
									
										
										
										
											2015-09-12 07:04:02 +08:00
										 |  |  |         int(customization->getPressedKeyAction(KeyContext::TranslatingSelection) & KeyAction::CopySelection)) | 
					
						
							| 
									
										
										
										
											2013-12-30 06:53:28 +08:00
										 |  |  |       pixelsMovement->copyMask(); | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |       pixelsMovement->cutMask(); | 
					
						
							| 
									
										
										
										
											2012-01-06 10:21:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-12-30 06:53:28 +08:00
										 |  |  |     editor->setState(EditorStatePtr(new MovingPixelsState(editor, msg, pixelsMovement, handle))); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   catch (const LockedDocumentException&) { | 
					
						
							|  |  |  |     // Other editor is locking the document.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // TODO steal the PixelsMovement of the other editor and use it for this one.
 | 
					
						
							| 
									
										
										
										
											2014-11-03 03:15:52 +08:00
										 |  |  |     StatusBar::instance()->showTip(1000, "The sprite is locked in other editor"); | 
					
						
							| 
									
										
										
										
											2015-06-25 23:44:47 +08:00
										 |  |  |     editor->showMouseCursor(kForbiddenCursor); | 
					
						
							| 
									
										
										
										
											2013-12-30 06:53:28 +08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-04-16 00:59:41 +08:00
										 |  |  |   catch (const std::bad_alloc&) { | 
					
						
							|  |  |  |     StatusBar::instance()->showTip(1000, "Not enough memory to transform the selection"); | 
					
						
							| 
									
										
										
										
											2015-06-25 23:44:47 +08:00
										 |  |  |     editor->showMouseCursor(kForbiddenCursor); | 
					
						
							| 
									
										
										
										
											2015-04-16 00:59:41 +08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2012-01-06 10:21:51 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-13 22:23:45 +08:00
										 |  |  | void StandbyState::callEyedropper(Editor* editor) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   tools::Ink* clickedInk = editor->getCurrentEditorInk(); | 
					
						
							|  |  |  |   if (!clickedInk->isEyedropper()) | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Command* eyedropper_cmd = | 
					
						
							|  |  |  |     CommandsModule::instance()->getCommandByName(CommandId::Eyedropper); | 
					
						
							|  |  |  |   bool fg = (static_cast<tools::PickInk*>(clickedInk)->target() == tools::PickInk::Fg); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Params params; | 
					
						
							|  |  |  |   params.set("target", fg ? "foreground": "background"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-12 02:40:22 +08:00
										 |  |  |   UIContext::instance()->executeCommand(eyedropper_cmd, params); | 
					
						
							| 
									
										
										
										
											2014-11-13 22:23:45 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-30 03:35:34 +08:00
										 |  |  | void StandbyState::onPivotChange(Editor* editor) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (editor->isActive() && | 
					
						
							|  |  |  |       editor->editorFlags() & Editor::kShowMask && | 
					
						
							|  |  |  |       editor->document()->isMaskVisible() && | 
					
						
							|  |  |  |       !editor->document()->mask()->isFrozen()) { | 
					
						
							|  |  |  |     editor->invalidate(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-26 06:15:36 +08:00
										 |  |  | gfx::Rect StandbyState::resizeCelBounds(Editor* editor) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   gfx::Rect bounds; | 
					
						
							|  |  |  |   Cel* refCel = (editor->layer() && | 
					
						
							|  |  |  |                  editor->layer()->isReference() ? | 
					
						
							|  |  |  |                  editor->layer()->cel(editor->frame()): nullptr); | 
					
						
							|  |  |  |   if (refCel) { | 
					
						
							|  |  |  |     bounds = editor->editorToScreen(refCel->boundsF()); | 
					
						
							|  |  |  |     bounds.w /= 4; | 
					
						
							|  |  |  |     bounds.h /= 4; | 
					
						
							|  |  |  |     bounds.x += 3*bounds.w; | 
					
						
							|  |  |  |     bounds.y += 3*bounds.h; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return bounds; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-07 02:26:01 +08:00
										 |  |  | bool StandbyState::overSelectionEdges(Editor* editor, | 
					
						
							|  |  |  |                                       const gfx::Point& mouseScreenPos) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   // Move selection edges
 | 
					
						
							| 
									
										
										
										
											2017-04-07 05:41:18 +08:00
										 |  |  |   if (Preferences::instance().selection.moveEdges() && | 
					
						
							|  |  |  |       editor->isActive() && | 
					
						
							| 
									
										
										
										
											2017-04-07 02:26:01 +08:00
										 |  |  |       editor->document()->isMaskVisible() && | 
					
						
							|  |  |  |       editor->document()->getMaskBoundaries() && | 
					
						
							| 
									
										
										
										
											2017-04-07 05:41:18 +08:00
										 |  |  |       // TODO improve this check, how we can know that we aren't in the MovingPixelsState
 | 
					
						
							|  |  |  |       !dynamic_cast<MovingPixelsState*>(editor->getState().get())) { | 
					
						
							| 
									
										
										
										
											2017-11-09 02:59:33 +08:00
										 |  |  |     gfx::Point mainOffset(editor->mainTilePosition()); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-07 02:26:01 +08:00
										 |  |  |     // For each selection edge
 | 
					
						
							|  |  |  |     for (const auto& seg : *editor->document()->getMaskBoundaries()) { | 
					
						
							| 
									
										
										
										
											2017-11-09 02:59:33 +08:00
										 |  |  |       gfx::Rect segBounds = seg.bounds(); | 
					
						
							|  |  |  |       segBounds.offset(mainOffset); | 
					
						
							|  |  |  |       segBounds = editor->editorToScreen(segBounds); | 
					
						
							| 
									
										
										
										
											2017-04-07 02:26:01 +08:00
										 |  |  |       if (seg.vertical()) | 
					
						
							|  |  |  |         segBounds.w = 1; | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  |         segBounds.h = 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (gfx::Rect(segBounds).enlarge(2*guiscale()).contains(mouseScreenPos) && | 
					
						
							|  |  |  |           !gfx::Rect(segBounds).shrink(2*guiscale()).contains(mouseScreenPos)) { | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  | //////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | // Decorator
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | StandbyState::Decorator::Decorator(StandbyState* standbyState) | 
					
						
							|  |  |  |   : m_transfHandles(NULL) | 
					
						
							|  |  |  |   , m_standbyState(standbyState) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | StandbyState::Decorator::~Decorator() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   delete m_transfHandles; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TransformHandles* StandbyState::Decorator::getTransformHandles(Editor* editor) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (!m_transfHandles) | 
					
						
							|  |  |  |     m_transfHandles = new TransformHandles(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return m_transfHandles; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-29 07:00:18 +08:00
										 |  |  | bool StandbyState::Decorator::onSetCursor(tools::Ink* ink, Editor* editor, const gfx::Point& mouseScreenPos) | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-10-29 07:00:18 +08:00
										 |  |  |   if (!editor->isActive()) | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  |     return false; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-08 23:07:21 +08:00
										 |  |  |   if (ink && | 
					
						
							|  |  |  |       ink->isSelection() && | 
					
						
							|  |  |  |       editor->document()->isMaskVisible() && | 
					
						
							|  |  |  |       (!Preferences::instance().selection.modifiersDisableHandles() || | 
					
						
							|  |  |  |        she::instance()->keyModifiers() == kKeyNoneModifier)) { | 
					
						
							| 
									
										
										
										
											2017-04-07 05:41:18 +08:00
										 |  |  |     auto theme = skin::SkinTheme::instance(); | 
					
						
							| 
									
										
										
										
											2016-07-12 01:16:01 +08:00
										 |  |  |     const Transformation transformation(m_standbyState->getTransformation(editor)); | 
					
						
							| 
									
										
										
										
											2015-10-29 07:00:18 +08:00
										 |  |  |     TransformHandles* tr = getTransformHandles(editor); | 
					
						
							|  |  |  |     HandleType handle = tr->getHandleAtPoint( | 
					
						
							|  |  |  |       editor, mouseScreenPos, transformation); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-07 05:41:18 +08:00
										 |  |  |     CursorType newCursorType = kArrowCursor; | 
					
						
							|  |  |  |     const Cursor* newCursor = nullptr; | 
					
						
							| 
									
										
										
										
											2015-10-29 07:00:18 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     switch (handle) { | 
					
						
							| 
									
										
										
										
											2017-04-07 05:41:18 +08:00
										 |  |  |       case ScaleNWHandle:         newCursorType = kSizeNWCursor; break; | 
					
						
							|  |  |  |       case ScaleNHandle:          newCursorType = kSizeNCursor; break; | 
					
						
							|  |  |  |       case ScaleNEHandle:         newCursorType = kSizeNECursor; break; | 
					
						
							|  |  |  |       case ScaleWHandle:          newCursorType = kSizeWCursor; break; | 
					
						
							|  |  |  |       case ScaleEHandle:          newCursorType = kSizeECursor; break; | 
					
						
							|  |  |  |       case ScaleSWHandle:         newCursorType = kSizeSWCursor; break; | 
					
						
							|  |  |  |       case ScaleSHandle:          newCursorType = kSizeSCursor; break; | 
					
						
							|  |  |  |       case ScaleSEHandle:         newCursorType = kSizeSECursor; break; | 
					
						
							|  |  |  |       case RotateNWHandle:        newCursor = theme->cursors.rotateNw(); break; | 
					
						
							|  |  |  |       case RotateNHandle:         newCursor = theme->cursors.rotateN(); break; | 
					
						
							|  |  |  |       case RotateNEHandle:        newCursor = theme->cursors.rotateNe(); break; | 
					
						
							|  |  |  |       case RotateWHandle:         newCursor = theme->cursors.rotateW(); break; | 
					
						
							|  |  |  |       case RotateEHandle:         newCursor = theme->cursors.rotateE(); break; | 
					
						
							|  |  |  |       case RotateSWHandle:        newCursor = theme->cursors.rotateSw(); break; | 
					
						
							|  |  |  |       case RotateSHandle:         newCursor = theme->cursors.rotateS(); break; | 
					
						
							|  |  |  |       case RotateSEHandle:        newCursor = theme->cursors.rotateSe(); break; | 
					
						
							|  |  |  |       case PivotHandle:           newCursorType = kHandCursor; break; | 
					
						
							| 
									
										
										
										
											2015-10-29 07:00:18 +08:00
										 |  |  |       default: | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-29 07:00:18 +08:00
										 |  |  |     // Adjust the cursor depending the current transformation angle.
 | 
					
						
							|  |  |  |     fixmath::fixed angle = fixmath::ftofix(128.0 * transformation.angle() / PI); | 
					
						
							|  |  |  |     angle = fixmath::fixadd(angle, fixmath::itofix(16)); | 
					
						
							|  |  |  |     angle &= (255<<16); | 
					
						
							|  |  |  |     angle >>= 16; | 
					
						
							|  |  |  |     angle /= 32; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-07 05:41:18 +08:00
										 |  |  |     if (newCursorType >= kSizeNCursor && | 
					
						
							|  |  |  |         newCursorType <= kSizeNWCursor) { | 
					
						
							| 
									
										
										
										
											2015-10-29 07:00:18 +08:00
										 |  |  |       size_t num = sizeof(rotated_size_cursors) / sizeof(rotated_size_cursors[0]); | 
					
						
							|  |  |  |       size_t c; | 
					
						
							|  |  |  |       for (c=num-1; c>0; --c) | 
					
						
							| 
									
										
										
										
											2017-04-07 05:41:18 +08:00
										 |  |  |         if (rotated_size_cursors[c] == newCursorType) | 
					
						
							| 
									
										
										
										
											2015-10-29 07:00:18 +08:00
										 |  |  |           break; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-07 05:41:18 +08:00
										 |  |  |       newCursorType = rotated_size_cursors[(c+angle) % num]; | 
					
						
							| 
									
										
										
										
											2015-10-29 07:00:18 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-04-07 05:41:18 +08:00
										 |  |  |     else if (newCursor) { | 
					
						
							|  |  |  |       auto theme = skin::SkinTheme::instance(); | 
					
						
							|  |  |  |       const Cursor* rotated_rotate_cursors[8] = { | 
					
						
							|  |  |  |         theme->cursors.rotateE(), | 
					
						
							|  |  |  |         theme->cursors.rotateNe(), | 
					
						
							|  |  |  |         theme->cursors.rotateN(), | 
					
						
							|  |  |  |         theme->cursors.rotateNw(), | 
					
						
							|  |  |  |         theme->cursors.rotateW(), | 
					
						
							|  |  |  |         theme->cursors.rotateSw(), | 
					
						
							|  |  |  |         theme->cursors.rotateS(), | 
					
						
							|  |  |  |         theme->cursors.rotateSe() | 
					
						
							|  |  |  |       }; | 
					
						
							| 
									
										
										
										
											2015-10-29 07:00:18 +08:00
										 |  |  |       size_t num = sizeof(rotated_rotate_cursors) / sizeof(rotated_rotate_cursors[0]); | 
					
						
							|  |  |  |       size_t c; | 
					
						
							|  |  |  |       for (c=num-1; c>0; --c) | 
					
						
							|  |  |  |         if (rotated_rotate_cursors[c] == newCursor) | 
					
						
							|  |  |  |           break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       newCursor = rotated_rotate_cursors[(c+angle) % num]; | 
					
						
							| 
									
										
										
										
											2017-04-07 05:41:18 +08:00
										 |  |  |       newCursorType = kCustomCursor; | 
					
						
							| 
									
										
										
										
											2015-10-29 07:00:18 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-07 05:41:18 +08:00
										 |  |  |     editor->showMouseCursor(newCursorType, newCursor); | 
					
						
							| 
									
										
										
										
											2015-10-29 07:00:18 +08:00
										 |  |  |     return true; | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-07 06:27:43 +08:00
										 |  |  |   // Move symmetry
 | 
					
						
							| 
									
										
										
										
											2017-03-28 02:27:37 +08:00
										 |  |  |   Handles handles; | 
					
						
							|  |  |  |   if (getSymmetryHandles(editor, handles)) { | 
					
						
							|  |  |  |     for (const auto& handle : handles) { | 
					
						
							|  |  |  |       if (handle.bounds.contains(mouseScreenPos)) { | 
					
						
							|  |  |  |         switch (handle.align) { | 
					
						
							|  |  |  |           case TOP: | 
					
						
							|  |  |  |           case BOTTOM: | 
					
						
							|  |  |  |             editor->showMouseCursor(kSizeWECursor); | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |           case LEFT: | 
					
						
							|  |  |  |           case RIGHT: | 
					
						
							|  |  |  |             editor->showMouseCursor(kSizeNSCursor); | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2015-10-29 07:00:18 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-29 07:00:18 +08:00
										 |  |  |   return false; | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void StandbyState::Decorator::preRenderDecorator(EditorPreRender* render) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   // Do nothing
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void StandbyState::Decorator::postRenderDecorator(EditorPostRender* render) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   Editor* editor = render->getEditor(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Draw transformation handles (if the mask is visible and isn't frozen).
 | 
					
						
							| 
									
										
										
										
											2015-04-27 21:08:48 +08:00
										 |  |  |   if (editor->isActive() && | 
					
						
							|  |  |  |       editor->editorFlags() & Editor::kShowMask && | 
					
						
							| 
									
										
										
										
											2014-08-09 23:24:04 +08:00
										 |  |  |       editor->document()->isMaskVisible() && | 
					
						
							| 
									
										
										
										
											2014-07-30 12:28:15 +08:00
										 |  |  |       !editor->document()->mask()->isFrozen()) { | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  |     // And draw only when the user has a selection tool as active tool.
 | 
					
						
							| 
									
										
										
										
											2014-08-19 19:17:57 +08:00
										 |  |  |     tools::Ink* ink = editor->getCurrentEditorInk(); | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-26 02:26:46 +08:00
										 |  |  |     if (ink->isSelection()) { | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  |       getTransformHandles(editor)->drawHandles(editor, | 
					
						
							| 
									
										
										
										
											2014-08-09 23:24:04 +08:00
										 |  |  |         m_standbyState->getTransformation(editor)); | 
					
						
							| 
									
										
										
										
											2016-04-26 02:26:46 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |       m_standbyState->m_transformSelectionHandlesAreVisible = true; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-10-29 07:00:18 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // Draw transformation handles (if the mask is visible and isn't frozen).
 | 
					
						
							| 
									
										
										
										
											2017-03-28 02:27:37 +08:00
										 |  |  |   Handles handles; | 
					
						
							|  |  |  |   if (StandbyState::Decorator::getSymmetryHandles(editor, handles)) { | 
					
						
							| 
									
										
										
										
											2016-12-12 20:48:58 +08:00
										 |  |  |     skin::SkinTheme* theme = static_cast<skin::SkinTheme*>(ui::get_theme()); | 
					
						
							| 
									
										
										
											
												Refactor several "getNoun()" getters to "noun()"
This is a work-in-progress to create a consistent API and finally
separate the whole Aseprite base/gfx/ui libs into a reusable C++ library.
Classes:
app::IFileItem, app::AppMenuItem, app::skin::SkinPart,
gfx::Rect, gfx::Border, she::FileDialog,
ui::IButtonIcon, ui::Graphics, ui::Overlay, ui::Widget,
ui::ScrollableViewDelegate, and UI events
											
										 
											2015-12-05 01:39:04 +08:00
										 |  |  |     she::Surface* part = theme->parts.transformationHandle()->bitmap(0); | 
					
						
							| 
									
										
										
										
											2015-10-29 07:00:18 +08:00
										 |  |  |     ScreenGraphics g; | 
					
						
							| 
									
										
										
										
											2017-03-28 02:27:37 +08:00
										 |  |  |     for (const auto& handle : handles) | 
					
						
							|  |  |  |       g.drawRgbaSurface(part, handle.bounds.x, handle.bounds.y); | 
					
						
							| 
									
										
										
										
											2015-10-29 07:00:18 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-08 02:25:10 +08:00
										 |  |  | void StandbyState::Decorator::getInvalidDecoratoredRegion(Editor* editor, gfx::Region& region) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2017-03-28 02:27:37 +08:00
										 |  |  |   Handles handles; | 
					
						
							|  |  |  |   if (getSymmetryHandles(editor, handles)) { | 
					
						
							|  |  |  |     for (const auto& handle : handles) | 
					
						
							|  |  |  |       region.createUnion(region, gfx::Region(handle.bounds)); | 
					
						
							| 
									
										
										
										
											2015-12-08 02:25:10 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-28 02:27:37 +08:00
										 |  |  | bool StandbyState::Decorator::getSymmetryHandles(Editor* editor, Handles& handles) | 
					
						
							| 
									
										
										
										
											2015-10-29 07:00:18 +08:00
										 |  |  | { | 
					
						
							|  |  |  |   // Draw transformation handles (if the mask is visible and isn't frozen).
 | 
					
						
							|  |  |  |   if (editor->isActive() && | 
					
						
							|  |  |  |       editor->editorFlags() & Editor::kShowSymmetryLine && | 
					
						
							|  |  |  |       Preferences::instance().symmetryMode.enabled()) { | 
					
						
							|  |  |  |     const auto& symmetry = Preferences::instance().document(editor->document()).symmetry; | 
					
						
							|  |  |  |     auto mode = symmetry.mode(); | 
					
						
							|  |  |  |     if (mode != app::gen::SymmetryMode::NONE) { | 
					
						
							| 
									
										
										
										
											2016-12-06 02:20:17 +08:00
										 |  |  |       gfx::RectF spriteBounds = gfx::RectF(editor->sprite()->bounds()); | 
					
						
							|  |  |  |       gfx::RectF editorViewport = gfx::RectF(View::getView(editor)->viewportBounds()); | 
					
						
							| 
									
										
										
										
											2016-12-12 20:48:58 +08:00
										 |  |  |       skin::SkinTheme* theme = static_cast<skin::SkinTheme*>(ui::get_theme()); | 
					
						
							| 
									
										
										
											
												Refactor several "getNoun()" getters to "noun()"
This is a work-in-progress to create a consistent API and finally
separate the whole Aseprite base/gfx/ui libs into a reusable C++ library.
Classes:
app::IFileItem, app::AppMenuItem, app::skin::SkinPart,
gfx::Rect, gfx::Border, she::FileDialog,
ui::IButtonIcon, ui::Graphics, ui::Overlay, ui::Widget,
ui::ScrollableViewDelegate, and UI events
											
										 
											2015-12-05 01:39:04 +08:00
										 |  |  |       she::Surface* part = theme->parts.transformationHandle()->bitmap(0); | 
					
						
							| 
									
										
										
										
											2015-12-06 21:56:53 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-28 02:27:37 +08:00
										 |  |  |       if (int(mode) & int(app::gen::SymmetryMode::HORIZONTAL)) { | 
					
						
							|  |  |  |         double pos = symmetry.xAxis(); | 
					
						
							|  |  |  |         gfx::PointF pt1, pt2; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-06 02:20:17 +08:00
										 |  |  |         pt1 = gfx::PointF(spriteBounds.x+pos, spriteBounds.y); | 
					
						
							|  |  |  |         pt1 = editor->editorToScreenF(pt1); | 
					
						
							|  |  |  |         pt2 = gfx::PointF(spriteBounds.x+pos, spriteBounds.y+spriteBounds.h); | 
					
						
							|  |  |  |         pt2 = editor->editorToScreenF(pt2); | 
					
						
							| 
									
										
										
										
											2015-12-06 21:56:53 +08:00
										 |  |  |         pt1.y = std::max(pt1.y-part->height(), editorViewport.y); | 
					
						
							|  |  |  |         pt2.y = std::min(pt2.y, editorViewport.point2().y-part->height()); | 
					
						
							| 
									
										
										
										
											2015-10-29 07:00:18 +08:00
										 |  |  |         pt1.x -= part->width()/2; | 
					
						
							|  |  |  |         pt2.x -= part->width()/2; | 
					
						
							| 
									
										
										
										
											2017-03-28 02:27:37 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         handles.push_back( | 
					
						
							|  |  |  |           Handle(TOP, | 
					
						
							| 
									
										
										
										
											2017-04-20 06:25:57 +08:00
										 |  |  |                  gfx::Rect(int(pt1.x), int(pt1.y), part->width(), part->height()))); | 
					
						
							| 
									
										
										
										
											2017-03-28 02:27:37 +08:00
										 |  |  |         handles.push_back( | 
					
						
							|  |  |  |           Handle(BOTTOM, | 
					
						
							| 
									
										
										
										
											2017-04-20 06:25:57 +08:00
										 |  |  |                  gfx::Rect(int(pt2.x), int(pt2.y), part->width(), part->height()))); | 
					
						
							| 
									
										
										
										
											2015-10-29 07:00:18 +08:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2017-03-28 02:27:37 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |       if (int(mode) & int(app::gen::SymmetryMode::VERTICAL)) { | 
					
						
							|  |  |  |         double pos = symmetry.yAxis(); | 
					
						
							|  |  |  |         gfx::PointF pt1, pt2; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-06 02:20:17 +08:00
										 |  |  |         pt1 = gfx::PointF(spriteBounds.x, spriteBounds.y+pos); | 
					
						
							|  |  |  |         pt1 = editor->editorToScreenF(pt1); | 
					
						
							|  |  |  |         pt2 = gfx::PointF(spriteBounds.x+spriteBounds.w, spriteBounds.y+pos); | 
					
						
							|  |  |  |         pt2 = editor->editorToScreenF(pt2); | 
					
						
							| 
									
										
										
										
											2015-12-06 21:56:53 +08:00
										 |  |  |         pt1.x = std::max(pt1.x-part->width(), editorViewport.x); | 
					
						
							|  |  |  |         pt2.x = std::min(pt2.x, editorViewport.point2().x-part->width()); | 
					
						
							| 
									
										
										
										
											2015-10-29 07:00:18 +08:00
										 |  |  |         pt1.y -= part->height()/2; | 
					
						
							|  |  |  |         pt2.y -= part->height()/2; | 
					
						
							| 
									
										
										
										
											2017-03-28 02:27:37 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         handles.push_back( | 
					
						
							|  |  |  |           Handle(LEFT, | 
					
						
							| 
									
										
										
										
											2017-04-20 06:25:57 +08:00
										 |  |  |                  gfx::Rect(int(pt1.x), int(pt1.y), part->width(), part->height()))); | 
					
						
							| 
									
										
										
										
											2017-03-28 02:27:37 +08:00
										 |  |  |         handles.push_back( | 
					
						
							|  |  |  |           Handle(RIGHT, | 
					
						
							| 
									
										
										
										
											2017-04-20 06:25:57 +08:00
										 |  |  |                  gfx::Rect(int(pt2.x), int(pt2.y), part->width(), part->height()))); | 
					
						
							| 
									
										
										
										
											2015-10-29 07:00:18 +08:00
										 |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return false; | 
					
						
							| 
									
										
										
										
											2012-01-06 06:45:03 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2013-08-06 08:20:19 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | } // namespace app
 |