1 // Aseprite 2 // Copyright (C) 2001-2018 David Capello 3 // 4 // This program is distributed under the terms of 5 // the End-User License Agreement for Aseprite. 6 7 #ifndef APP_UI_TIMELINE_TIMELINE_H_INCLUDED 8 #define APP_UI_TIMELINE_TIMELINE_H_INCLUDED 9 #pragma once 10 11 #include "app/doc_observer.h" 12 #include "app/docs_observer.h" 13 #include "app/doc_range.h" 14 #include "app/loop_tag.h" 15 #include "app/pref/preferences.h" 16 #include "app/ui/editor/editor_observer.h" 17 #include "app/ui/input_chain_element.h" 18 #include "app/ui/timeline/ani_controls.h" 19 #include "doc/frame.h" 20 #include "doc/layer.h" 21 #include "doc/selected_frames.h" 22 #include "doc/selected_layers.h" 23 #include "doc/sprite.h" 24 #include "obs/connection.h" 25 #include "ui/scroll_bar.h" 26 #include "ui/timer.h" 27 #include "ui/widget.h" 28 29 #include <vector> 30 31 namespace doc { 32 class Cel; 33 class Layer; 34 class LayerImage; 35 class Sprite; 36 } 37 38 namespace ui { 39 class Graphics; 40 } 41 42 namespace app { 43 44 namespace skin { 45 class SkinTheme; 46 } 47 48 using namespace doc; 49 50 class CommandExecutionEvent; 51 class ConfigureTimelinePopup; 52 class Context; 53 class Doc; 54 class Editor; 55 56 class Timeline : public ui::Widget, 57 public ui::ScrollableViewDelegate, 58 public ContextObserver, 59 public DocsObserver, 60 public DocObserver, 61 public EditorObserver, 62 public InputChainElement, 63 public FrameTagProvider { 64 public: 65 typedef DocRange Range; 66 67 enum State { 68 STATE_STANDBY, 69 STATE_SCROLLING, 70 STATE_SELECTING_LAYERS, 71 STATE_SELECTING_FRAMES, 72 STATE_SELECTING_CELS, 73 STATE_MOVING_SEPARATOR, 74 STATE_MOVING_RANGE, 75 STATE_MOVING_ONIONSKIN_RANGE_LEFT, 76 STATE_MOVING_ONIONSKIN_RANGE_RIGHT, 77 // Changing layers flags states 78 STATE_SHOWING_LAYERS, 79 STATE_HIDING_LAYERS, 80 STATE_LOCKING_LAYERS, 81 STATE_UNLOCKING_LAYERS, 82 STATE_ENABLING_CONTINUOUS_LAYERS, 83 STATE_DISABLING_CONTINUOUS_LAYERS, 84 STATE_EXPANDING_LAYERS, 85 STATE_COLLAPSING_LAYERS, 86 }; 87 88 enum DropOp { kMove, kCopy }; 89 90 Timeline(); 91 ~Timeline(); 92 93 void updateUsingEditor(Editor* editor); 94 sprite()95 Sprite* sprite() { return m_sprite; } getLayer()96 Layer* getLayer() { return m_layer; } getFrame()97 frame_t getFrame() { return m_frame; } 98 getState()99 State getState() const { return m_state; } 100 bool isMovingCel() const; 101 range()102 Range range() const { return m_range; } selectedLayers()103 const SelectedLayers& selectedLayers() const { return m_range.selectedLayers(); } selectedFrames()104 const SelectedFrames& selectedFrames() const { return m_range.selectedFrames(); } 105 106 void prepareToMoveRange(); 107 void moveRange(const Range& range); 108 void setRange(const Range& range); 109 110 void activateClipboardRange(); 111 112 // Drag-and-drop operations. These actions are used by commands 113 // called from popup menus. 114 void dropRange(DropOp op); 115 116 // FrameTagProvider impl 117 // Returns the active frame tag depending on the timeline status 118 // E.g. if other frame tags are collapsed, the focused band has 119 // priority and tags in other bands are ignored. 120 FrameTag* getFrameTagByFrame(const frame_t frame, 121 const bool getLoopTagIfNone) override; 122 123 // ScrollableViewDelegate impl 124 gfx::Size visibleSize() const override; 125 gfx::Point viewScroll() const override; 126 void setViewScroll(const gfx::Point& pt) override; 127 128 void lockRange(); 129 void unlockRange(); 130 131 protected: 132 bool onProcessMessage(ui::Message* msg) override; 133 void onInitTheme(ui::InitThemeEvent& ev) override; 134 void onInvalidateRegion(const gfx::Region& region) override; 135 void onSizeHint(ui::SizeHintEvent& ev) override; 136 void onResize(ui::ResizeEvent& ev) override; 137 void onPaint(ui::PaintEvent& ev) override; 138 139 // DocObserver impl. 140 void onGeneralUpdate(DocEvent& ev) override; 141 void onAddLayer(DocEvent& ev) override; 142 void onAfterRemoveLayer(DocEvent& ev) override; 143 void onAddFrame(DocEvent& ev) override; 144 void onRemoveFrame(DocEvent& ev) override; 145 void onSelectionChanged(DocEvent& ev) override; 146 void onLayerNameChange(DocEvent& ev) override; 147 void onAddFrameTag(DocEvent& ev) override; 148 void onRemoveFrameTag(DocEvent& ev) override; 149 150 // app::Context slots. 151 void onAfterCommandExecution(CommandExecutionEvent& ev); 152 153 // ContextObserver impl 154 void onActiveSiteChange(const Site& site) override; 155 156 // DocsObserver impl. 157 void onRemoveDocument(Doc* document) override; 158 159 // EditorObserver impl. 160 void onStateChanged(Editor* editor) override; 161 void onAfterFrameChanged(Editor* editor) override; 162 void onAfterLayerChanged(Editor* editor) override; 163 void onDestroyEditor(Editor* editor) override; 164 165 // InputChainElement impl 166 void onNewInputPriority(InputChainElement* element, 167 const ui::Message* msg) override; 168 bool onCanCut(Context* ctx) override; 169 bool onCanCopy(Context* ctx) override; 170 bool onCanPaste(Context* ctx) override; 171 bool onCanClear(Context* ctx) override; 172 bool onCut(Context* ctx) override; 173 bool onCopy(Context* ctx) override; 174 bool onPaste(Context* ctx) override; 175 bool onClear(Context* ctx) override; 176 void onCancel(Context* ctx) override; 177 178 private: 179 struct DrawCelData; 180 181 struct Hit { 182 int part; 183 layer_t layer; 184 frame_t frame; 185 ObjectId frameTag; 186 bool veryBottom; 187 int band; 188 189 Hit(int part = 0, 190 layer_t layer = -1, 191 frame_t frame = 0, 192 ObjectId frameTag = NullId, 193 int band = -1); 194 bool operator!=(const Hit& other) const; 195 FrameTag* getFrameTag() const; 196 }; 197 198 struct DropTarget { 199 enum HHit { 200 HNone, 201 Before, 202 After 203 }; 204 enum VHit { 205 VNone, 206 Bottom, 207 Top, 208 FirstChild, 209 VeryBottom 210 }; 211 DropTarget(); 212 DropTarget(const DropTarget& o); 213 bool operator!=(const DropTarget& o) const { 214 return (hhit != o.hhit || 215 vhit != o.vhit || 216 outside != o.outside); 217 } 218 HHit hhit; 219 VHit vhit; 220 bool outside; 221 }; 222 223 struct Row { 224 Row(); 225 Row(Layer* layer, 226 const int level, 227 const LayerFlags inheritedFlags); 228 layerRow229 Layer* layer() const { return m_layer; } levelRow230 int level() const { return m_level; } 231 232 bool parentVisible() const; 233 bool parentEditable() const; 234 235 private: 236 Layer* m_layer; 237 int m_level; 238 LayerFlags m_inheritedFlags; 239 }; 240 241 bool selectedLayersBounds(const SelectedLayers& layers, 242 layer_t* first, layer_t* last) const; 243 244 void setLayer(Layer* layer); 245 void setFrame(frame_t frame, bool byUser); 246 bool allLayersVisible(); 247 bool allLayersInvisible(); 248 bool allLayersLocked(); 249 bool allLayersUnlocked(); 250 bool allLayersContinuous(); 251 bool allLayersDiscontinuous(); 252 void detachDocument(); 253 void setCursor(ui::Message* msg, const Hit& hit); 254 void getDrawableLayers(ui::Graphics* g, layer_t* firstLayer, layer_t* lastLayer); 255 void getDrawableFrames(ui::Graphics* g, frame_t* firstFrame, frame_t* lastFrame); 256 void drawPart(ui::Graphics* g, const gfx::Rect& bounds, 257 const std::string* text, 258 ui::Style* style, 259 const bool is_active = false, 260 const bool is_hover = false, 261 const bool is_clicked = false, 262 const bool is_disabled = false); 263 void drawTop(ui::Graphics* g); 264 void drawHeader(ui::Graphics* g); 265 void drawHeaderFrame(ui::Graphics* g, frame_t frame); 266 void drawLayer(ui::Graphics* g, layer_t layerIdx); 267 void drawCel(ui::Graphics* g, layer_t layerIdx, frame_t frame, Cel* cel, DrawCelData* data); 268 void drawCelLinkDecorators(ui::Graphics* g, const gfx::Rect& bounds, 269 Cel* cel, frame_t frame, bool is_active, bool is_hover, 270 DrawCelData* data); 271 void drawFrameTags(ui::Graphics* g); 272 void drawRangeOutline(ui::Graphics* g); 273 void drawPaddings(ui::Graphics* g); 274 bool drawPart(ui::Graphics* g, int part, layer_t layer, frame_t frame); 275 void drawClipboardRange(ui::Graphics* g); 276 gfx::Rect getLayerHeadersBounds() const; 277 gfx::Rect getFrameHeadersBounds() const; 278 gfx::Rect getOnionskinFramesBounds() const; 279 gfx::Rect getCelsBounds() const; 280 gfx::Rect getPartBounds(const Hit& hit) const; 281 gfx::Rect getRangeBounds(const Range& range) const; 282 gfx::Rect getRangeClipBounds(const Range& range) const; 283 void invalidateHit(const Hit& hit); 284 void invalidateLayer(const Layer* layer); 285 void invalidateFrame(const frame_t frame); 286 void invalidateRange(); 287 void regenerateRows(); 288 void regenerateTagBands(); 289 int visibleTagBands() const; 290 void updateScrollBars(); 291 void updateByMousePos(ui::Message* msg, const gfx::Point& mousePos); 292 Hit hitTest(ui::Message* msg, const gfx::Point& mousePos); 293 Hit hitTestCel(const gfx::Point& mousePos); 294 void setHot(const Hit& hit); 295 void showCel(layer_t layer, frame_t frame); 296 void showCurrentCel(); 297 void focusTagBand(int band); 298 void cleanClk(); 299 gfx::Size getScrollableSize() const; 300 gfx::Point getMaxScrollablePos() const; 301 layer_t getLayerIndex(const Layer* layer) const; 302 bool isLayerActive(const layer_t layerIdx) const; 303 bool isFrameActive(const frame_t frame) const; 304 bool isCelActive(const layer_t layerIdx, const frame_t frame) const; 305 bool isCelLooselyActive(const layer_t layerIdx, const frame_t frame) const; 306 void updateStatusBar(ui::Message* msg); 307 void updateStatusBarForFrame(const frame_t frame, 308 const FrameTag* frameTag, 309 const Cel* cel); 310 void updateDropRange(const gfx::Point& pt); 311 void clearClipboardRange(); 312 void clearAndInvalidateRange(); 313 314 // The layer of the bottom (e.g. Background layer) firstLayer()315 layer_t firstLayer() const { return 0; } 316 // The layer of the top. lastLayer()317 layer_t lastLayer() const { return m_rows.size()-1; } 318 firstFrame()319 frame_t firstFrame() const { return frame_t(0); } lastFrame()320 frame_t lastFrame() const { return m_sprite->lastFrame(); } 321 validLayer(layer_t layer)322 bool validLayer(layer_t layer) const { return layer >= firstLayer() && layer <= lastLayer(); } validFrame(frame_t frame)323 bool validFrame(frame_t frame) const { return frame >= firstFrame() && frame <= lastFrame(); } 324 325 int topHeight() const; 326 327 DocumentPreferences& docPref() const; 328 329 // Theme/dimensions 330 skin::SkinTheme* skinTheme() const; 331 gfx::Size celBoxSize() const; 332 int headerBoxWidth() const; 333 int headerBoxHeight() const; 334 int layerBoxHeight() const; 335 int frameBoxWidth() const; 336 int outlineWidth() const; 337 int oneTagHeight() const; 338 int calcTagVisibleToFrame(FrameTag* frameTag) const; 339 340 void updateCelOverlayBounds(const Hit& hit); 341 void drawCelOverlay(ui::Graphics* g); 342 void onThumbnailsPrefChange(); 343 void setZoom(const double zoom); 344 void setZoomAndUpdate(const double zoom, 345 const bool updatePref); 346 347 double zoom() const; 348 int tagFramesDuration(const FrameTag* frameTag) const; 349 // Calculate the duration of the selected range of frames 350 int selectedFramesDuration() const; 351 352 void setLayerVisibleFlag(const layer_t layer, const bool state); 353 void setLayerEditableFlag(const layer_t layer, const bool state); 354 void setLayerContinuousFlag(const layer_t layer, const bool state); 355 void setLayerCollapsedFlag(const layer_t layer, const bool state); 356 357 ui::ScrollBar m_hbar; 358 ui::ScrollBar m_vbar; 359 gfx::Rect m_viewportArea; 360 double m_zoom; 361 Context* m_context; 362 Editor* m_editor; 363 Doc* m_document; 364 Sprite* m_sprite; 365 Layer* m_layer; 366 frame_t m_frame; 367 int m_rangeLocks; 368 Range m_range; 369 Range m_startRange; 370 Range m_dropRange; 371 State m_state; 372 373 // Data used to display each row in the timeline 374 std::vector<Row> m_rows; 375 376 // Data used to display frame tags 377 int m_tagBands; 378 int m_tagFocusBand; 379 std::map<FrameTag*, int> m_tagBand; 380 381 int m_separator_x; 382 int m_separator_w; 383 int m_origFrames; 384 Hit m_hot; // The 'hot' part is where the mouse is on top of 385 DropTarget m_dropTarget; 386 Hit m_clk; // The 'clk' part is where the mouse's button was pressed (maybe for a drag & drop operation) 387 // Absolute mouse positions for scrolling. 388 gfx::Point m_oldPos; 389 // Configure timeline 390 ConfigureTimelinePopup* m_confPopup; 391 obs::scoped_connection m_ctxConn; 392 obs::connection m_firstFrameConn; 393 394 // Marching ants stuff to show the range in the clipboard. 395 // TODO merge this with the marching ants of the sprite editor (ui::Editor) 396 ui::Timer m_clipboard_timer; 397 int m_offset_count; 398 bool m_redrawMarchingAntsOnly; 399 400 bool m_scroll; // True if the drag-and-drop operation is a scroll operation. 401 bool m_copy; // True if the drag-and-drop operation is a copy. 402 bool m_fromTimeline; 403 404 AniControls m_aniControls; 405 406 // Data used for thumbnails. 407 bool m_thumbnailsOverlayVisible; 408 gfx::Rect m_thumbnailsOverlayInner; 409 gfx::Rect m_thumbnailsOverlayOuter; 410 Hit m_thumbnailsOverlayHit; 411 gfx::Point m_thumbnailsOverlayDirection; 412 obs::connection m_thumbnailsPrefConn; 413 414 // Temporal data used to move the range. 415 struct MoveRange { 416 layer_t activeRelativeLayer; 417 frame_t activeRelativeFrame; 418 } m_moveRangeData; 419 }; 420 421 class LockTimelineRange { 422 public: LockTimelineRange(Timeline * timeline)423 LockTimelineRange(Timeline* timeline) 424 : m_timeline(timeline) { 425 m_timeline->lockRange(); 426 } ~LockTimelineRange()427 ~LockTimelineRange() { 428 m_timeline->unlockRange(); 429 } 430 private: 431 Timeline* m_timeline; 432 }; 433 434 } // namespace app 435 436 #endif 437