From b0cd01b425a1ba3817c50f97df73113d11dde344 Mon Sep 17 00:00:00 2001 From: David Capello Date: Sun, 10 Nov 2013 18:27:11 -0300 Subject: [PATCH] Add the old "Animation Editor" as a timeline at the bottom of sprite editors (Workspace) - Renamed AnimationEditor (dialogs/aniedit.h) to Timeline class (app/ui/timeline.h) - Renamed FilmEditor command to Timeline --- TODO.md | 2 - data/gui.xml | 8 +- data/widgets/main_window.xml | 7 +- src/app/CMakeLists.txt | 4 +- src/app/commands/cmd_copy_cel.cpp | 6 +- src/app/commands/cmd_film_editor.cpp | 63 ----- src/app/commands/cmd_move_cel.cpp | 6 +- src/app/commands/cmd_timeline.cpp | 94 +++++++ src/app/commands/commands_list.h | 4 +- src/app/dialogs/aniedit.h | 31 --- src/app/ui/main_window.cpp | 38 ++- src/app/ui/main_window.h | 9 + .../{dialogs/aniedit.cpp => ui/timeline.cpp} | 254 +++++------------- src/app/ui/timeline.h | 130 +++++++++ src/app/ui_context.cpp | 10 +- 15 files changed, 372 insertions(+), 294 deletions(-) delete mode 100644 src/app/commands/cmd_film_editor.cpp create mode 100644 src/app/commands/cmd_timeline.cpp delete mode 100644 src/app/dialogs/aniedit.h rename src/app/{dialogs/aniedit.cpp => ui/timeline.cpp} (87%) create mode 100644 src/app/ui/timeline.h diff --git a/TODO.md b/TODO.md index 7a6673782..edb91a6d4 100644 --- a/TODO.md +++ b/TODO.md @@ -31,8 +31,6 @@ * Add "Remap" button to palette editor after a palette entry is modified: This button should apply a color curve to the whole sprite to remap old indexes to the new positions. -* Move src/app/dialogs/aniedit,filesel to src/app/ui - (remove app/dialogs/ directory). * Merge everything related to configuration/settings in one class (allow configuration per document). Use cfg.cpp and settings/ dir. * Refactor src/file/ in several layers. diff --git a/data/gui.xml b/data/gui.xml index 590f06e07..c3f6e34ad 100644 --- a/data/gui.xml +++ b/data/gui.xml @@ -74,7 +74,9 @@ - + + + @@ -362,7 +364,9 @@ - + + + diff --git a/data/widgets/main_window.xml b/data/widgets/main_window.xml index b4b3d3113..b77f065c6 100644 --- a/data/widgets/main_window.xml +++ b/data/widgets/main_window.xml @@ -11,7 +11,12 @@ - + + + + diff --git a/src/app/CMakeLists.txt b/src/app/CMakeLists.txt index 70954fb39..d4ab07c48 100644 --- a/src/app/CMakeLists.txt +++ b/src/app/CMakeLists.txt @@ -33,7 +33,6 @@ add_library(app-library commands/cmd_exit.cpp commands/cmd_export_sprite_sheet.cpp commands/cmd_eyedropper.cpp - commands/cmd_film_editor.cpp commands/cmd_flatten_layers.cpp commands/cmd_flip.cpp commands/cmd_frame_properties.cpp @@ -76,6 +75,7 @@ add_library(app-library commands/cmd_sprite_properties.cpp commands/cmd_sprite_size.cpp commands/cmd_switch_colors.cpp + commands/cmd_timeline.cpp commands/cmd_undo.cpp commands/command.cpp commands/commands.cpp @@ -96,7 +96,6 @@ add_library(app-library context_flags.cpp context_observer_list.cpp data_recovery.cpp - dialogs/aniedit.cpp dialogs/maskcol.cpp document.cpp document_api.cpp @@ -181,6 +180,7 @@ add_library(app-library ui/skin/skin_theme.cpp ui/status_bar.cpp ui/tabs.cpp + ui/timeline.cpp ui/toolbar.cpp ui/workspace.cpp ui/workspace_part.cpp diff --git a/src/app/commands/cmd_copy_cel.cpp b/src/app/commands/cmd_copy_cel.cpp index 361c65f84..4f5c59fd8 100644 --- a/src/app/commands/cmd_copy_cel.cpp +++ b/src/app/commands/cmd_copy_cel.cpp @@ -20,9 +20,11 @@ #include "config.h" #endif +#include "app/app.h" #include "app/commands/command.h" #include "app/context_access.h" -#include "app/dialogs/aniedit.h" +#include "app/ui/timeline.h" +#include "app/ui/main_window.h" #include "app/util/celmove.h" #include "ui/base.h" @@ -47,7 +49,7 @@ CopyCelCommand::CopyCelCommand() bool CopyCelCommand::onEnabled(Context* context) { - return animation_editor_is_movingcel(); + return App::instance()->getMainWindow()->getTimeline()->isMovingCel(); } void CopyCelCommand::onExecute(Context* context) diff --git a/src/app/commands/cmd_film_editor.cpp b/src/app/commands/cmd_film_editor.cpp deleted file mode 100644 index 33f675bab..000000000 --- a/src/app/commands/cmd_film_editor.cpp +++ /dev/null @@ -1,63 +0,0 @@ -/* Aseprite - * Copyright (C) 2001-2013 David Capello - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "ui/ui.h" - -#include "app/commands/command.h" -#include "app/context.h" -#include "app/dialogs/aniedit.h" - -namespace app { - -class FilmEditorCommand : public Command { -public: - FilmEditorCommand(); - Command* clone() { return new FilmEditorCommand(*this); } - -protected: - bool onEnabled(Context* context); - void onExecute(Context* context); -}; - -FilmEditorCommand::FilmEditorCommand() - : Command("FilmEditor", - "Animation Editor", - CmdUIOnlyFlag) -{ -} - -bool FilmEditorCommand::onEnabled(Context* context) -{ - return context->checkFlags(ContextFlags::ActiveDocumentIsWritable); -} - -void FilmEditorCommand::onExecute(Context* context) -{ - switch_between_animation_and_sprite_editor(context); -} - -Command* CommandFactory::createFilmEditorCommand() -{ - return new FilmEditorCommand; -} - -} // namespace app diff --git a/src/app/commands/cmd_move_cel.cpp b/src/app/commands/cmd_move_cel.cpp index 88c735e6b..0778b5b13 100644 --- a/src/app/commands/cmd_move_cel.cpp +++ b/src/app/commands/cmd_move_cel.cpp @@ -20,9 +20,11 @@ #include "config.h" #endif +#include "app/app.h" #include "app/commands/command.h" #include "app/context_access.h" -#include "app/dialogs/aniedit.h" +#include "app/ui/main_window.h" +#include "app/ui/timeline.h" #include "app/util/celmove.h" #include "ui/base.h" @@ -47,7 +49,7 @@ MoveCelCommand::MoveCelCommand() bool MoveCelCommand::onEnabled(Context* context) { - return animation_editor_is_movingcel(); + return App::instance()->getMainWindow()->getTimeline()->isMovingCel(); } void MoveCelCommand::onExecute(Context* context) diff --git a/src/app/commands/cmd_timeline.cpp b/src/app/commands/cmd_timeline.cpp new file mode 100644 index 000000000..a90cecc52 --- /dev/null +++ b/src/app/commands/cmd_timeline.cpp @@ -0,0 +1,94 @@ +/* Aseprite + * Copyright (C) 2001-2013 David Capello + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "ui/ui.h" + +#include "app/app.h" +#include "app/commands/command.h" +#include "app/commands/params.h" +#include "app/context.h" +#include "app/ui/main_window.h" +#include "app/ui/timeline.h" + +namespace app { + +class TimelineCommand : public Command { +public: + TimelineCommand(); + Command* clone() { return new TimelineCommand(*this); } + +protected: + void onLoadParams(Params* params) OVERRIDE; + void onExecute(Context* context) OVERRIDE; + + bool m_open; + bool m_close; + bool m_switch; +}; + +TimelineCommand::TimelineCommand() + : Command("Timeline", + "Switch Timeline", + CmdUIOnlyFlag) +{ + m_open = true; + m_close = false; + m_switch = false; +} + +void TimelineCommand::onLoadParams(Params* params) +{ + std::string open_str = params->get("open"); + if (open_str == "true") m_open = true; + else m_open = false; + + std::string close_str = params->get("close"); + if (close_str == "true") m_close = true; + else m_close = false; + + std::string switch_str = params->get("switch"); + if (switch_str == "true") m_switch = true; + else m_switch = false; +} + +void TimelineCommand::onExecute(Context* context) +{ + bool visible = App::instance()->getMainWindow()->getTimelineVisibility(); + bool newVisible = visible; + + if (m_switch) + newVisible = !visible; + else if (m_close) + newVisible = false; + else if (m_open) + newVisible = true; + + if (visible != newVisible) + App::instance()->getMainWindow()->setTimelineVisibility(newVisible); +} + +Command* CommandFactory::createTimelineCommand() +{ + return new TimelineCommand; +} + +} // namespace app diff --git a/src/app/commands/commands_list.h b/src/app/commands/commands_list.h index 11d0fc5c6..57278e372 100644 --- a/src/app/commands/commands_list.h +++ b/src/app/commands/commands_list.h @@ -44,7 +44,6 @@ FOR_EACH_COMMAND(DuplicateSprite) FOR_EACH_COMMAND(Exit) FOR_EACH_COMMAND(ExportSpriteSheet) FOR_EACH_COMMAND(Eyedropper) -FOR_EACH_COMMAND(FilmEditor) FOR_EACH_COMMAND(FlattenLayers) FOR_EACH_COMMAND(Flip) FOR_EACH_COMMAND(FrameProperties) @@ -53,9 +52,9 @@ FOR_EACH_COMMAND(GotoFrame) FOR_EACH_COMMAND(GotoLastFrame) FOR_EACH_COMMAND(GotoNextFrame) FOR_EACH_COMMAND(GotoNextLayer) +FOR_EACH_COMMAND(GotoNextTab) FOR_EACH_COMMAND(GotoPreviousFrame) FOR_EACH_COMMAND(GotoPreviousLayer) -FOR_EACH_COMMAND(GotoNextTab) FOR_EACH_COMMAND(GotoPreviousTab) FOR_EACH_COMMAND(GridSettings) FOR_EACH_COMMAND(ImportSpriteSheet) @@ -102,4 +101,5 @@ FOR_EACH_COMMAND(SplitEditorVertically) FOR_EACH_COMMAND(SpriteProperties) FOR_EACH_COMMAND(SpriteSize) FOR_EACH_COMMAND(SwitchColors) +FOR_EACH_COMMAND(Timeline) FOR_EACH_COMMAND(Undo) diff --git a/src/app/dialogs/aniedit.h b/src/app/dialogs/aniedit.h deleted file mode 100644 index f48ad9b77..000000000 --- a/src/app/dialogs/aniedit.h +++ /dev/null @@ -1,31 +0,0 @@ -/* Aseprite - * Copyright (C) 2001-2013 David Capello - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef APP_DIALOGS_ANIEDIT_H_INCLUDED -#define APP_DIALOGS_ANIEDIT_H_INCLUDED - -namespace app { - class Context; - - bool animation_editor_is_movingcel(); - - void switch_between_animation_and_sprite_editor(Context* context); - -} // namespace app - -#endif diff --git a/src/app/ui/main_window.cpp b/src/app/ui/main_window.cpp index cdd436e69..97511c327 100644 --- a/src/app/ui/main_window.cpp +++ b/src/app/ui/main_window.cpp @@ -24,7 +24,9 @@ #include "app/app.h" #include "app/app_menus.h" +#include "app/commands/commands.h" #include "app/load_widget.h" +#include "app/modules/editors.h" #include "app/ui/color_bar.h" #include "app/ui/context_bar.h" #include "app/ui/document_view.h" @@ -34,14 +36,13 @@ #include "app/ui/mini_editor.h" #include "app/ui/status_bar.h" #include "app/ui/tabs.h" +#include "app/ui/timeline.h" #include "app/ui/toolbar.h" #include "app/ui/workspace.h" -#include "app/commands/commands.h" -#include "app/modules/editors.h" +#include "app/ui_context.h" #include "ui/splitter.h" #include "ui/system.h" #include "ui/view.h" -#include "app/ui_context.h" namespace app { @@ -50,6 +51,7 @@ using namespace ui; MainWindow::MainWindow() : Window(true, "") , m_lastSplitterPos(0.0) + , m_lastTimelineSplitterPos(75.0) , m_advancedMode(false) { setId("main_window"); @@ -67,6 +69,7 @@ MainWindow::MainWindow() Widget* box_statusbar = findChild("statusbar"); Widget* box_tabsbar = findChild("tabsbar"); Widget* box_workspace = findChild("workspace"); + Widget* box_timeline = findChild("timeline"); m_menuBar = new MainMenuBar(); m_contextBar = new ContextBar(); @@ -77,7 +80,11 @@ MainWindow::MainWindow() m_workspace = new Workspace(); m_workspace->ActiveViewChanged.connect(&MainWindow::onActiveViewChange, this); m_miniEditor = new MiniEditorWindow(); + m_timeline = new Timeline(); m_colorBarSplitter = findChildT("colorbarsplitter"); + m_timelineSplitter = findChildT("timelinesplitter"); + + m_lastTimelineSplitterPos = m_timelineSplitter->getPosition(); // configure all widgets to expansives m_menuBar->setExpansive(true); @@ -86,6 +93,7 @@ MainWindow::MainWindow() m_colorBar->setExpansive(true); m_toolBar->setExpansive(true); m_tabsBar->setExpansive(true); + m_timeline->setExpansive(true); m_workspace->setExpansive(true); // Setup the menus @@ -99,6 +107,7 @@ MainWindow::MainWindow() if (box_statusbar) box_statusbar->addChild(m_statusBar); if (box_tabsbar) box_tabsbar->addChild(m_tabsBar); if (box_workspace) box_workspace->addChild(m_workspace); + if (box_timeline) box_timeline->addChild(m_timeline); // Prepare the window remapWindow(); @@ -153,6 +162,29 @@ void MainWindow::setAdvancedMode(bool advanced) layout(); } +bool MainWindow::getTimelineVisibility() const +{ + return m_timeline->isVisible(); +} + +void MainWindow::setTimelineVisibility(bool visible) +{ + m_timeline->setVisible(visible); + + if (visible) { + if (m_timelineSplitter->getPosition() >= 100.0) + m_timelineSplitter->setPosition(m_lastTimelineSplitterPos); + } + else { + if (m_timelineSplitter->getPosition() < 100.0) { + m_lastTimelineSplitterPos = m_timelineSplitter->getPosition(); + m_timelineSplitter->setPosition(100.0); + } + } + + layout(); +} + void MainWindow::onSaveLayout(SaveLayoutEvent& ev) { Window::onSaveLayout(ev); diff --git a/src/app/ui/main_window.h b/src/app/ui/main_window.h index bb1fbaee1..884c341e7 100644 --- a/src/app/ui/main_window.h +++ b/src/app/ui/main_window.h @@ -27,12 +27,14 @@ namespace ui { } namespace app { + class ColorBar; class ContextBar; class MainMenuBar; class MiniEditorWindow; class StatusBar; class Tabs; + class Timeline; class Workspace; class MainWindow : public ui::Window @@ -44,6 +46,7 @@ namespace app { MainMenuBar* getMenuBar() { return m_menuBar; } ContextBar* getContextBar() { return m_contextBar; } Tabs* getTabsBar() { return m_tabsBar; } + Timeline* getTimeline() { return m_timeline; } Workspace* getWorkspace() { return m_workspace; } MiniEditorWindow* getMiniEditor() { return m_miniEditor; } @@ -52,6 +55,9 @@ namespace app { bool isAdvancedMode() const { return m_advancedMode; } void setAdvancedMode(bool advanced); + bool getTimelineVisibility() const; + void setTimelineVisibility(bool visible); + // TabsDelegate implementation. void clickTab(Tabs* tabs, TabView* tabView, ui::MouseButtons buttons); void mouseOverTab(Tabs* tabs, TabView* tabView); @@ -66,10 +72,13 @@ namespace app { StatusBar* m_statusBar; ColorBar* m_colorBar; ui::Splitter* m_colorBarSplitter; + ui::Splitter* m_timelineSplitter; ui::Widget* m_toolBar; Tabs* m_tabsBar; double m_lastSplitterPos; + double m_lastTimelineSplitterPos; bool m_advancedMode; + Timeline* m_timeline; Workspace* m_workspace; MiniEditorWindow* m_miniEditor; }; diff --git a/src/app/dialogs/aniedit.cpp b/src/app/ui/timeline.cpp similarity index 87% rename from src/app/dialogs/aniedit.cpp rename to src/app/ui/timeline.cpp index 12edb714b..543a0b125 100644 --- a/src/app/dialogs/aniedit.cpp +++ b/src/app/ui/timeline.cpp @@ -20,6 +20,8 @@ #include "config.h" #endif +#include "app/ui/timeline.h" + #include "app/app_menus.h" #include "app/commands/command.h" #include "app/commands/commands.h" @@ -29,11 +31,11 @@ #include "app/document.h" #include "app/document_api.h" #include "app/document_event.h" -#include "app/document_observer.h" #include "app/document_undo.h" #include "app/modules/editors.h" #include "app/modules/gfx.h" #include "app/modules/gui.h" +#include "app/ui/document_view.h" #include "app/ui/editor/editor.h" #include "app/ui/skin/skin_theme.h" #include "app/ui_context.h" @@ -51,7 +53,7 @@ #include /* - Animator Editor + Timeline Frames ... @@ -105,146 +107,30 @@ enum { A_PART_CEL }; -class AnimationEditor : public Widget - , public DocumentObserver { -public: - enum State { - STATE_STANDBY, - STATE_SCROLLING, - STATE_MOVING_SEPARATOR, - STATE_MOVING_LAYER, - STATE_MOVING_CEL, - STATE_MOVING_FRAME, - }; - - AnimationEditor(Context* context); - ~AnimationEditor(); - - Sprite* getSprite() { return m_sprite; } - Layer* getLayer() { return m_layer; } - FrameNumber getFrame() { return m_frame; } - - void setLayer(Layer* layer) { - m_layer = layer; - if (current_editor) - current_editor->setLayer(m_layer); - } - void setFrame(FrameNumber frame) { - m_frame = frame; - if (current_editor) - current_editor->setFrame(m_frame); - } - - void centerCurrentCel(); - State getState() const { return m_state; } - -protected: - bool onProcessMessage(Message* msg) OVERRIDE; - void onPreferredSize(PreferredSizeEvent& ev) OVERRIDE; - - // DocumentObserver impl. - void onAddLayer(DocumentEvent& ev) OVERRIDE; - void onRemoveLayer(DocumentEvent& ev) OVERRIDE; - void onAddFrame(DocumentEvent& ev) OVERRIDE; - void onRemoveFrame(DocumentEvent& ev) OVERRIDE; - void onTotalFramesChanged(DocumentEvent& ev) OVERRIDE; - -private: - void setCursor(int x, int y); - void getDrawableLayers(const gfx::Rect& clip, int* first_layer, int* last_layer); - void getDrawableFrames(const gfx::Rect& clip, FrameNumber* first_frame, FrameNumber* last_frame); - void drawHeader(const gfx::Rect& clip); - void drawHeaderFrame(const gfx::Rect& clip, FrameNumber frame); - void drawHeaderPart(const gfx::Rect& clip, int x1, int y1, int x2, int y2, - bool is_hot, bool is_clk, - const char* line1, int align1, - const char* line2, int align2); - void drawSeparator(const gfx::Rect& clip); - void drawLayer(const gfx::Rect& clip, int layer_index); - void drawLayerPadding(); - void drawCel(const gfx::Rect& clip, int layer_index, FrameNumber frame, Cel* cel); - bool drawPart(int part, int layer, FrameNumber frame); - void regenerateLayers(); - void hotThis(int hot_part, int hot_layer, FrameNumber hotFrame); - void centerCel(int layer, FrameNumber frame); - void showCel(int layer, FrameNumber frame); - void showCurrentCel(); - void cleanClk(); - void setScroll(int x, int y, bool use_refresh_region); - int getLayerIndex(const Layer* layer); - - Context* m_context; - Document* m_document; - Sprite* m_sprite; - Layer* m_layer; - FrameNumber m_frame; - State m_state; - std::vector m_layers; - int m_scroll_x; - int m_scroll_y; - int m_separator_x; - int m_separator_w; - // The 'hot' part is where the mouse is on top of - int m_hot_part; - int m_hot_layer; - FrameNumber m_hot_frame; - // The 'clk' part is where the mouse's button was pressed (maybe for a drag & drop operation) - int m_clk_part; - int m_clk_layer; - FrameNumber m_clk_frame; - // Keys - bool m_space_pressed; -}; - -static AnimationEditor* current_anieditor = NULL; - static void icon_rect(BITMAP* icon_normal, BITMAP* icon_selected, int x1, int y1, int x2, int y2, bool is_selected, bool is_hot, bool is_clk); -bool animation_editor_is_movingcel() -{ - return - current_anieditor != NULL && - current_anieditor->getState() == AnimationEditor::STATE_MOVING_CEL; -} - -// Shows the animation editor for the current sprite. -void switch_between_animation_and_sprite_editor(Context* context) -{ - const Document* document; - const Sprite* sprite; - { - const ContextReader reader(context); - document = reader.document(); - sprite = reader.sprite(); - } - - // Create the window & the animation-editor - { - base::UniquePtr window(new Window(true, "")); - AnimationEditor anieditor(context); - - window->addChild(&anieditor); - window->remapWindow(); - - anieditor.centerCurrentCel(); - - // Show the window - window->openWindowInForeground(); - } - - // Destroy thumbnails - destroy_thumbnails(); -} - -////////////////////////////////////////////////////////////////////// -// The Animation Editor - -AnimationEditor::AnimationEditor(Context* context) +Timeline::Timeline() : Widget(kGenericWidget) - , m_context(context) + , m_context(UIContext::instance()) + , m_document(NULL) { - DocumentLocation location = context->getActiveLocation(); +} + +Timeline::~Timeline() +{ + if (m_document) + m_document->removeObserver(this); +} + +void Timeline::updateUsingEditor(Editor* editor) +{ + if (m_document) + m_document->removeObserver(this); + + DocumentView* view = editor->getDocumentView(); + DocumentLocation location; + view->getDocumentLocation(&location); m_document = location.document(); m_sprite = location.sprite(); @@ -259,22 +145,36 @@ AnimationEditor::AnimationEditor(Context* context) m_clk_part = A_PART_NOTHING; m_space_pressed = false; - this->setFocusStop(true); - + setFocusStop(true); regenerateLayers(); - current_anieditor = this; m_document->addObserver(this); } -AnimationEditor::~AnimationEditor() +bool Timeline::isMovingCel() const { - current_anieditor = NULL; - m_document->removeObserver(this); + return (m_state == Timeline::STATE_MOVING_CEL); } -bool AnimationEditor::onProcessMessage(Message* msg) +void Timeline::setLayer(Layer* layer) { + m_layer = layer; + if (current_editor) + current_editor->setLayer(m_layer); +} + +void Timeline::setFrame(FrameNumber frame) +{ + m_frame = frame; + if (current_editor) + current_editor->setFrame(m_frame); +} + +bool Timeline::onProcessMessage(Message* msg) +{ + if (!m_document) + return Widget::onProcessMessage(msg); + switch (msg->type()) { case kPaintMessage: { @@ -724,18 +624,12 @@ bool AnimationEditor::onProcessMessage(Message* msg) } break; +#if 0 case kKeyDownMessage: { Command* command = NULL; Params* params = NULL; get_command_from_key_message(msg, &command, ¶ms); - // Close animation editor. - if ((command && (strcmp(command->short_name(), CommandId::FilmEditor) == 0)) || - (static_cast(msg)->scancode() == kKeyEsc)) { - closeWindow(); - return true; - } - // Undo or redo. if (command && (strcmp(command->short_name(), CommandId::Undo) == 0 || strcmp(command->short_name(), CommandId::Redo) == 0)) { @@ -790,6 +684,7 @@ bool AnimationEditor::onProcessMessage(Message* msg) break; } +#endif case kKeyUpMessage: switch (static_cast(msg)->scancode()) { @@ -838,20 +733,19 @@ bool AnimationEditor::onProcessMessage(Message* msg) return Widget::onProcessMessage(msg); } -void AnimationEditor::onPreferredSize(PreferredSizeEvent& ev) +void Timeline::onPreferredSize(PreferredSizeEvent& ev) { // This doesn't matter, the AniEditor'll use the entire screen anyway. ev.setPreferredSize(Size(32, 32)); } - -void AnimationEditor::onAddLayer(DocumentEvent& ev) +void Timeline::onAddLayer(DocumentEvent& ev) { ASSERT(ev.layer() != NULL); setLayer(ev.layer()); } -void AnimationEditor::onRemoveLayer(DocumentEvent& ev) +void Timeline::onRemoveLayer(DocumentEvent& ev) { Sprite* sprite = ev.sprite(); Layer* layer = ev.layer(); @@ -874,12 +768,12 @@ void AnimationEditor::onRemoveLayer(DocumentEvent& ev) } } -void AnimationEditor::onAddFrame(DocumentEvent& ev) +void Timeline::onAddFrame(DocumentEvent& ev) { setFrame(ev.frame()); } -void AnimationEditor::onRemoveFrame(DocumentEvent& ev) +void Timeline::onRemoveFrame(DocumentEvent& ev) { // Adjust current frame of all editors that are in a frame more // advanced that the removed one. @@ -894,14 +788,14 @@ void AnimationEditor::onRemoveFrame(DocumentEvent& ev) } } -void AnimationEditor::onTotalFramesChanged(DocumentEvent& ev) +void Timeline::onTotalFramesChanged(DocumentEvent& ev) { if (getFrame() >= getSprite()->getTotalFrames()) { setFrame(getSprite()->getLastFrame()); } } -void AnimationEditor::setCursor(int x, int y) +void Timeline::setCursor(int x, int y) { int mx = x - getBounds().x; //int my = y - getBounds().y; @@ -946,19 +840,19 @@ void AnimationEditor::setCursor(int x, int y) } } -void AnimationEditor::getDrawableLayers(const gfx::Rect& clip, int* first_layer, int* last_layer) +void Timeline::getDrawableLayers(const gfx::Rect& clip, int* first_layer, int* last_layer) { *first_layer = 0; *last_layer = m_layers.size()-1; } -void AnimationEditor::getDrawableFrames(const gfx::Rect& clip, FrameNumber* first_frame, FrameNumber* last_frame) +void Timeline::getDrawableFrames(const gfx::Rect& clip, FrameNumber* first_frame, FrameNumber* last_frame) { *first_frame = FrameNumber(0); *last_frame = m_sprite->getLastFrame(); } -void AnimationEditor::drawHeader(const gfx::Rect& clip) +void Timeline::drawHeader(const gfx::Rect& clip) { // bool is_hot = (m_hot_part == A_PART_HEADER_LAYER); // bool is_clk = (m_clk_part == A_PART_HEADER_LAYER); @@ -977,7 +871,7 @@ void AnimationEditor::drawHeader(const gfx::Rect& clip) "Layers", -1); } -void AnimationEditor::drawHeaderFrame(const gfx::Rect& clip, FrameNumber frame) +void Timeline::drawHeaderFrame(const gfx::Rect& clip, FrameNumber frame) { SkinTheme* theme = static_cast(getTheme()); bool is_hot = (m_hot_part == A_PART_HEADER_FRAME && @@ -1033,7 +927,7 @@ void AnimationEditor::drawHeaderFrame(const gfx::Rect& clip, FrameNumber frame) set_clip_rect(ji_screen, cx1, cy1, cx2, cy2); } -void AnimationEditor::drawHeaderPart(const gfx::Rect& clip, int x1, int y1, int x2, int y2, +void Timeline::drawHeaderPart(const gfx::Rect& clip, int x1, int y1, int x2, int y2, bool is_hot, bool is_clk, const char *line1, int align1, const char *line2, int align2) @@ -1079,7 +973,7 @@ void AnimationEditor::drawHeaderPart(const gfx::Rect& clip, int x1, int y1, int } } -void AnimationEditor::drawSeparator(const gfx::Rect& clip) +void Timeline::drawSeparator(const gfx::Rect& clip) { SkinTheme* theme = static_cast(getTheme()); bool is_hot = (m_hot_part == A_PART_SEPARATOR); @@ -1098,7 +992,7 @@ void AnimationEditor::drawSeparator(const gfx::Rect& clip) theme->getColor(ThemeColor::Text))); } -void AnimationEditor::drawLayer(const gfx::Rect& clip, int layer_index) +void Timeline::drawLayer(const gfx::Rect& clip, int layer_index) { Layer* layer = m_layers[layer_index]; SkinTheme* theme = static_cast(this->getTheme()); @@ -1161,7 +1055,7 @@ void AnimationEditor::drawLayer(const gfx::Rect& clip, int layer_index) (m_clk_part == A_PART_LAYER_EYE_ICON && m_clk_layer == layer_index)); - u += u+ICONBORDER+icon1->w+ICONBORDER; + u += ICONBORDER+icon1->w+ICONBORDER; // Draw the padlock (writable flag). icon_rect(icon2, icon2_selected, @@ -1178,7 +1072,7 @@ void AnimationEditor::drawLayer(const gfx::Rect& clip, int layer_index) u += ICONBORDER+icon2->w+ICONBORDER+ICONSEP; // Draw the layer's name. - jdraw_text(ji_screen, this->getFont(), layer->getName().c_str(), + jdraw_text(ji_screen, getFont(), layer->getName().c_str(), u, y_mid - ji_font_get_size(this->getFont())/2, fg, bg, true, jguiscale()); @@ -1194,7 +1088,7 @@ void AnimationEditor::drawLayer(const gfx::Rect& clip, int layer_index) set_clip_rect(ji_screen, cx1, cy1, cx2, cy2); } -void AnimationEditor::drawLayerPadding() +void Timeline::drawLayerPadding() { SkinTheme* theme = static_cast(this->getTheme()); int layer_index = m_layers.size()-1; @@ -1216,7 +1110,7 @@ void AnimationEditor::drawLayerPadding() } } -void AnimationEditor::drawCel(const gfx::Rect& clip, int layer_index, FrameNumber frame, Cel* cel) +void Timeline::drawCel(const gfx::Rect& clip, int layer_index, FrameNumber frame, Cel* cel) { SkinTheme* theme = static_cast(this->getTheme()); Layer *layer = m_layers[layer_index]; @@ -1311,7 +1205,7 @@ void AnimationEditor::drawCel(const gfx::Rect& clip, int layer_index, FrameNumbe set_clip_rect(ji_screen, cx1, cy1, cx2, cy2); } -bool AnimationEditor::drawPart(int part, int layer, FrameNumber frame) +bool Timeline::drawPart(int part, int layer, FrameNumber frame) { switch (part) { case A_PART_NOTHING: @@ -1351,7 +1245,7 @@ bool AnimationEditor::drawPart(int part, int layer, FrameNumber frame) return false; } -void AnimationEditor::regenerateLayers() +void Timeline::regenerateLayers() { m_layers.clear(); size_t nlayers = m_sprite->countLayers(); @@ -1362,7 +1256,7 @@ void AnimationEditor::regenerateLayers() } } -void AnimationEditor::hotThis(int hot_part, int hot_layer, FrameNumber hot_frame) +void Timeline::hotThis(int hot_part, int hot_layer, FrameNumber hot_frame) { int old_hot_part; @@ -1393,7 +1287,7 @@ void AnimationEditor::hotThis(int hot_part, int hot_layer, FrameNumber hot_frame } } -void AnimationEditor::centerCel(int layer, FrameNumber frame) +void Timeline::centerCel(int layer, FrameNumber frame) { int target_x = (getBounds().x + m_separator_x + m_separator_w + getBounds().x2())/2 - FRMSIZE/2; int target_y = (getBounds().y + HDRSIZE + getBounds().y2())/2 - LAYSIZE/2; @@ -1403,7 +1297,7 @@ void AnimationEditor::centerCel(int layer, FrameNumber frame) setScroll(scroll_x, scroll_y, false); } -void AnimationEditor::showCel(int layer, FrameNumber frame) +void Timeline::showCel(int layer, FrameNumber frame) { int scroll_x, scroll_y; int x1, y1, x2, y2; @@ -1435,21 +1329,21 @@ void AnimationEditor::showCel(int layer, FrameNumber frame) setScroll(scroll_x, scroll_y, true); } -void AnimationEditor::centerCurrentCel() +void Timeline::centerCurrentCel() { int layer = getLayerIndex(m_layer); if (layer >= 0) centerCel(layer, m_frame); } -void AnimationEditor::showCurrentCel() +void Timeline::showCurrentCel() { int layer = getLayerIndex(m_layer); if (layer >= 0) showCel(layer, m_frame); } -void AnimationEditor::cleanClk() +void Timeline::cleanClk() { int clk_part = m_clk_part; m_clk_part = A_PART_NOTHING; @@ -1459,7 +1353,7 @@ void AnimationEditor::cleanClk() m_clk_frame); } -void AnimationEditor::setScroll(int x, int y, bool use_refresh_region) +void Timeline::setScroll(int x, int y, bool use_refresh_region) { int old_scroll_x = 0; int old_scroll_y = 0; @@ -1519,7 +1413,7 @@ void AnimationEditor::setScroll(int x, int y, bool use_refresh_region) } } -int AnimationEditor::getLayerIndex(const Layer* layer) +int Timeline::getLayerIndex(const Layer* layer) { for (size_t i=0; i + +namespace raster { + class Cel; + class Layer; + class Sprite; +} + +namespace app { + using namespace raster; + + class Context; + class Document; + class Editor; + + class Timeline : public ui::Widget + , public DocumentObserver { + public: + enum State { + STATE_STANDBY, + STATE_SCROLLING, + STATE_MOVING_SEPARATOR, + STATE_MOVING_LAYER, + STATE_MOVING_CEL, + STATE_MOVING_FRAME, + }; + + Timeline(); + ~Timeline(); + + void updateUsingEditor(Editor* editor); + + Sprite* getSprite() { return m_sprite; } + Layer* getLayer() { return m_layer; } + FrameNumber getFrame() { return m_frame; } + + void setLayer(Layer* layer); + void setFrame(FrameNumber frame); + + void centerCurrentCel(); + State getState() const { return m_state; } + bool isMovingCel() const; + + protected: + bool onProcessMessage(ui::Message* msg) OVERRIDE; + void onPreferredSize(ui::PreferredSizeEvent& ev) OVERRIDE; + + // DocumentObserver impl. + void onAddLayer(DocumentEvent& ev) OVERRIDE; + void onRemoveLayer(DocumentEvent& ev) OVERRIDE; + void onAddFrame(DocumentEvent& ev) OVERRIDE; + void onRemoveFrame(DocumentEvent& ev) OVERRIDE; + void onTotalFramesChanged(DocumentEvent& ev) OVERRIDE; + + private: + void setCursor(int x, int y); + void getDrawableLayers(const gfx::Rect& clip, int* first_layer, int* last_layer); + void getDrawableFrames(const gfx::Rect& clip, FrameNumber* first_frame, FrameNumber* last_frame); + void drawHeader(const gfx::Rect& clip); + void drawHeaderFrame(const gfx::Rect& clip, FrameNumber frame); + void drawHeaderPart(const gfx::Rect& clip, int x1, int y1, int x2, int y2, + bool is_hot, bool is_clk, + const char* line1, int align1, + const char* line2, int align2); + void drawSeparator(const gfx::Rect& clip); + void drawLayer(const gfx::Rect& clip, int layer_index); + void drawLayerPadding(); + void drawCel(const gfx::Rect& clip, int layer_index, FrameNumber frame, Cel* cel); + bool drawPart(int part, int layer, FrameNumber frame); + void regenerateLayers(); + void hotThis(int hot_part, int hot_layer, FrameNumber hotFrame); + void centerCel(int layer, FrameNumber frame); + void showCel(int layer, FrameNumber frame); + void showCurrentCel(); + void cleanClk(); + void setScroll(int x, int y, bool use_refresh_region); + int getLayerIndex(const Layer* layer); + + Context* m_context; + Document* m_document; + Sprite* m_sprite; + Layer* m_layer; + FrameNumber m_frame; + State m_state; + std::vector m_layers; + int m_scroll_x; + int m_scroll_y; + int m_separator_x; + int m_separator_w; + // The 'hot' part is where the mouse is on top of + int m_hot_part; + int m_hot_layer; + FrameNumber m_hot_frame; + // The 'clk' part is where the mouse's button was pressed (maybe for a drag & drop operation) + int m_clk_part; + int m_clk_layer; + FrameNumber m_clk_frame; + // Keys + bool m_space_pressed; + }; + +} // namespace app + +#endif diff --git a/src/app/ui_context.cpp b/src/app/ui_context.cpp index ff7ff715b..8d555af78 100644 --- a/src/app/ui_context.cpp +++ b/src/app/ui_context.cpp @@ -21,20 +21,21 @@ #endif #include "app/app.h" +#include "app/document.h" +#include "app/modules/editors.h" +#include "app/settings/ui_settings_impl.h" #include "app/ui/color_bar.h" #include "app/ui/document_view.h" #include "app/ui/editor/editor.h" #include "app/ui/main_window.h" #include "app/ui/mini_editor.h" #include "app/ui/tabs.h" +#include "app/ui/timeline.h" #include "app/ui/workspace.h" +#include "app/ui_context.h" #include "base/mutex.h" #include "base/path.h" -#include "app/document.h" -#include "app/modules/editors.h" #include "raster/sprite.h" -#include "app/settings/ui_settings_impl.h" -#include "app/ui_context.h" #include "undo/undo_history.h" #include @@ -82,6 +83,7 @@ void UIContext::setActiveView(DocumentView* docView) current_editor->requestFocus(); App::instance()->getMainWindow()->getMiniEditor()->updateUsingEditor(current_editor); + App::instance()->getMainWindow()->getTimeline()->updateUsingEditor(current_editor); // Change the image-type of color bar. ColorBar::instance()->setPixelFormat(app_get_current_pixel_format());