mirror of
https://github.com/aseprite/aseprite.git
synced 2025-01-01 18:00:26 +00:00
Use a desktop Window in PreviewCommand to avoid a special events loop
This commit is contained in:
parent
dfaf097b88
commit
6ccd95e22d
@ -20,9 +20,6 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
|
||||
#include <allegro.h>
|
||||
|
||||
#include "ui/ui.h"
|
||||
|
||||
#include "app/app.h"
|
||||
@ -37,7 +34,7 @@
|
||||
#include "app/ui/editor/editor.h"
|
||||
#include "app/ui/status_bar.h"
|
||||
#include "app/util/render.h"
|
||||
#include "raster/conversion_alleg.h"
|
||||
#include "raster/conversion_she.h"
|
||||
#include "raster/image.h"
|
||||
#include "raster/palette.h"
|
||||
#include "raster/primitives.h"
|
||||
@ -52,6 +49,205 @@ using namespace ui;
|
||||
using namespace raster;
|
||||
using namespace filters;
|
||||
|
||||
class PreviewWindow : public Window {
|
||||
public:
|
||||
PreviewWindow(Context* context, Editor* editor)
|
||||
: Window(DesktopWindow)
|
||||
, m_context(context)
|
||||
, m_editor(editor)
|
||||
, m_doc(editor->document())
|
||||
, m_sprite(editor->sprite())
|
||||
, m_pal(m_sprite->getPalette(editor->frame()))
|
||||
, m_index_bg_color(-1)
|
||||
, m_doublebuf(Image::create(IMAGE_RGB, JI_SCREEN_W, JI_SCREEN_H)) {
|
||||
// Do not use DocumentWriter (do not lock the document) because we
|
||||
// will call other sub-commands (e.g. previous frame, next frame,
|
||||
// etc.).
|
||||
View* view = View::getView(editor);
|
||||
IDocumentSettings* docSettings = context->settings()->getDocumentSettings(m_doc);
|
||||
m_tiled = docSettings->getTiledMode();
|
||||
|
||||
// Free mouse
|
||||
editor->getManager()->freeMouse();
|
||||
|
||||
// Clear extras (e.g. pen preview)
|
||||
m_doc->destroyExtraCel();
|
||||
|
||||
gfx::Rect vp = view->getViewportBounds();
|
||||
gfx::Point scroll = view->getViewScroll();
|
||||
|
||||
m_first_mouse_pos = m_old_pos = ui::get_mouse_position();
|
||||
ui::set_mouse_position(gfx::Point(JI_SCREEN_W/2, JI_SCREEN_H/2));
|
||||
|
||||
m_pos.x = -scroll.x + vp.x + editor->offsetX();
|
||||
m_pos.y = -scroll.y + vp.y + editor->offsetY();
|
||||
m_zoom = editor->zoom();
|
||||
|
||||
ui::set_mouse_position(m_first_mouse_pos);
|
||||
|
||||
setFocusStop(true); // To receive keyboard messages
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual bool onProcessMessage(Message* msg) OVERRIDE {
|
||||
switch (msg->type()) {
|
||||
|
||||
case kCloseMessage:
|
||||
ui::set_mouse_position(m_first_mouse_pos);
|
||||
break;
|
||||
|
||||
case kMouseMoveMessage: {
|
||||
MouseMessage* mouseMsg = static_cast<MouseMessage*>(msg);
|
||||
gfx::Point mousePos = mouseMsg->position();
|
||||
|
||||
gfx::Rect bounds = getBounds();
|
||||
gfx::Border border;
|
||||
if (bounds.w > 64*jguiscale()) {
|
||||
border.left(32*jguiscale());
|
||||
border.right(32*jguiscale());
|
||||
}
|
||||
if (bounds.h > 64*jguiscale()) {
|
||||
border.top(32*jguiscale());
|
||||
border.bottom(32*jguiscale());
|
||||
}
|
||||
|
||||
m_delta += mousePos - m_old_pos;
|
||||
mousePos = ui::control_infinite_scroll(this, bounds.shrink(border), mousePos);
|
||||
m_old_pos = mousePos;
|
||||
|
||||
invalidate();
|
||||
break;
|
||||
}
|
||||
|
||||
case kMouseUpMessage: {
|
||||
closeWindow(this);
|
||||
break;
|
||||
}
|
||||
|
||||
case kKeyDownMessage: {
|
||||
KeyMessage* keyMsg = static_cast<KeyMessage*>(msg);
|
||||
Command* command = NULL;
|
||||
get_command_from_key_message(msg, &command, NULL);
|
||||
|
||||
// Change frame
|
||||
if (command != NULL &&
|
||||
(strcmp(command->short_name(), CommandId::GotoFirstFrame) == 0 ||
|
||||
strcmp(command->short_name(), CommandId::GotoPreviousFrame) == 0 ||
|
||||
strcmp(command->short_name(), CommandId::GotoNextFrame) == 0 ||
|
||||
strcmp(command->short_name(), CommandId::GotoLastFrame) == 0)) {
|
||||
m_context->executeCommand(command);
|
||||
invalidate();
|
||||
m_render.reset(NULL); // Re-render
|
||||
}
|
||||
#if 0
|
||||
// Play the animation
|
||||
else if (command != NULL &&
|
||||
strcmp(command->short_name(), CommandId::PlayAnimation) == 0) {
|
||||
// TODO
|
||||
}
|
||||
#endif
|
||||
// Change background color
|
||||
else if (keyMsg->scancode() == kKeyPlusPad ||
|
||||
keyMsg->unicodeChar() == '+') {
|
||||
if (m_index_bg_color == -1 ||
|
||||
m_index_bg_color < m_pal->size()-1) {
|
||||
++m_index_bg_color;
|
||||
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
else if (keyMsg->scancode() == kKeyMinusPad ||
|
||||
keyMsg->unicodeChar() == '-') {
|
||||
if (m_index_bg_color >= 0) {
|
||||
--m_index_bg_color; // can be -1 which is the checked background
|
||||
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
else {
|
||||
closeWindow(this);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
case kSetCursorMessage:
|
||||
jmouse_set_cursor(kNoCursor);
|
||||
return true;
|
||||
}
|
||||
|
||||
return Window::onProcessMessage(msg);
|
||||
}
|
||||
|
||||
virtual void onPaint(PaintEvent& ev) OVERRIDE {
|
||||
Graphics* g = ev.getGraphics();
|
||||
|
||||
// Render sprite and leave the result in 'render' variable
|
||||
if (m_render == NULL) {
|
||||
RenderEngine renderEngine(
|
||||
m_doc, m_sprite,
|
||||
m_editor->layer(),
|
||||
m_editor->frame());
|
||||
|
||||
m_render.reset(
|
||||
renderEngine.renderSprite(
|
||||
0, 0, m_sprite->width(), m_sprite->height(),
|
||||
m_editor->frame(), 0, false, false));
|
||||
}
|
||||
|
||||
int x, y, w, h, u, v;
|
||||
x = m_pos.x + ((m_delta.x >> m_zoom) << m_zoom);
|
||||
y = m_pos.y + ((m_delta.y >> m_zoom) << m_zoom);
|
||||
w = (m_sprite->width()<<m_zoom);
|
||||
h = (m_sprite->height()<<m_zoom);
|
||||
|
||||
if (m_tiled & TILED_X_AXIS) x = SGN(x) * (ABS(x)%w);
|
||||
if (m_tiled & TILED_Y_AXIS) y = SGN(y) * (ABS(y)%h);
|
||||
|
||||
if (m_index_bg_color == -1)
|
||||
RenderEngine::renderCheckedBackground(m_doublebuf, -m_pos.x, -m_pos.y, m_zoom);
|
||||
else
|
||||
raster::clear_image(m_doublebuf, m_pal->getEntry(m_index_bg_color));
|
||||
|
||||
switch (m_tiled) {
|
||||
case TILED_NONE:
|
||||
RenderEngine::renderImage(m_doublebuf, m_render, m_pal, x, y, m_zoom);
|
||||
break;
|
||||
case TILED_X_AXIS:
|
||||
for (u=x-w; u<JI_SCREEN_W+w; u+=w)
|
||||
RenderEngine::renderImage(m_doublebuf, m_render, m_pal, u, y, m_zoom);
|
||||
break;
|
||||
case TILED_Y_AXIS:
|
||||
for (v=y-h; v<JI_SCREEN_H+h; v+=h)
|
||||
RenderEngine::renderImage(m_doublebuf, m_render, m_pal, x, v, m_zoom);
|
||||
break;
|
||||
case TILED_BOTH:
|
||||
for (v=y-h; v<JI_SCREEN_H+h; v+=h)
|
||||
for (u=x-w; u<JI_SCREEN_W+w; u+=w)
|
||||
RenderEngine::renderImage(m_doublebuf, m_render, m_pal, u, v, m_zoom);
|
||||
break;
|
||||
}
|
||||
|
||||
raster::convert_image_to_surface(m_doublebuf, g->getInternalSurface(), 0, 0, m_pal);
|
||||
}
|
||||
|
||||
private:
|
||||
Context* m_context;
|
||||
Editor* m_editor;
|
||||
Document* m_doc;
|
||||
Sprite* m_sprite;
|
||||
const Palette* m_pal;
|
||||
gfx::Point m_pos;
|
||||
gfx::Point m_old_pos;
|
||||
gfx::Point m_first_mouse_pos;
|
||||
gfx::Point m_delta;
|
||||
int m_zoom;
|
||||
int m_index_bg_color;
|
||||
base::UniquePtr<Image> m_render;
|
||||
base::UniquePtr<Image> m_doublebuf;
|
||||
filters::TiledMode m_tiled;
|
||||
};
|
||||
|
||||
class PreviewCommand : public Command {
|
||||
public:
|
||||
PreviewCommand();
|
||||
@ -84,170 +280,8 @@ void PreviewCommand::onExecute(Context* context)
|
||||
if (!editor || !editor->sprite())
|
||||
return;
|
||||
|
||||
// Do not use DocumentWriter (do not lock the document) because we
|
||||
// will call other sub-commands (e.g. previous frame, next frame,
|
||||
// etc.).
|
||||
Document* document = editor->document();
|
||||
Sprite* sprite = editor->sprite();
|
||||
const Palette* pal = sprite->getPalette(editor->frame());
|
||||
View* view = View::getView(editor);
|
||||
int u, v, x, y;
|
||||
int index_bg_color = -1;
|
||||
IDocumentSettings* docSettings = context->settings()->getDocumentSettings(document);
|
||||
filters::TiledMode tiled = docSettings->getTiledMode();
|
||||
|
||||
// Free mouse
|
||||
editor->getManager()->freeMouse();
|
||||
|
||||
// Clear extras (e.g. pen preview)
|
||||
document->destroyExtraCel();
|
||||
|
||||
gfx::Rect vp = view->getViewportBounds();
|
||||
gfx::Point scroll = view->getViewScroll();
|
||||
|
||||
int old_mouse_x = jmouse_x(0);
|
||||
int old_mouse_y = jmouse_y(0);
|
||||
|
||||
jmouse_set_cursor(kNoCursor);
|
||||
ui::set_mouse_position(gfx::Point(JI_SCREEN_W/2, JI_SCREEN_H/2));
|
||||
|
||||
int pos_x = - scroll.x + vp.x + editor->offsetX();
|
||||
int pos_y = - scroll.y + vp.y + editor->offsetY();
|
||||
int delta_x = 0;
|
||||
int delta_y = 0;
|
||||
|
||||
int zoom = editor->zoom();
|
||||
int w = sprite->width() << zoom;
|
||||
int h = sprite->height() << zoom;
|
||||
|
||||
bool redraw = true;
|
||||
|
||||
// Render the sprite
|
||||
base::UniquePtr<Image> render;
|
||||
base::UniquePtr<Image> doublebuf(Image::create(IMAGE_RGB, JI_SCREEN_W, JI_SCREEN_H));
|
||||
|
||||
do {
|
||||
// Update scroll
|
||||
if (jmouse_poll()) {
|
||||
delta_x += (jmouse_x(0) - JI_SCREEN_W/2);
|
||||
delta_y += (jmouse_y(0) - JI_SCREEN_H/2);
|
||||
ui::set_mouse_position(gfx::Point(JI_SCREEN_W/2, JI_SCREEN_H/2));
|
||||
jmouse_poll();
|
||||
|
||||
redraw = true;
|
||||
}
|
||||
|
||||
// Render sprite and leave the result in 'render' variable
|
||||
if (render == NULL) {
|
||||
RenderEngine renderEngine(document, sprite,
|
||||
editor->layer(),
|
||||
editor->frame());
|
||||
|
||||
render.reset(
|
||||
renderEngine.renderSprite(
|
||||
0, 0, sprite->width(), sprite->height(),
|
||||
editor->frame(), 0, false, false));
|
||||
}
|
||||
|
||||
// Redraw the screen
|
||||
if (redraw) {
|
||||
redraw = false;
|
||||
dirty_display_flag = true;
|
||||
|
||||
x = pos_x + ((delta_x >> zoom) << zoom);
|
||||
y = pos_y + ((delta_y >> zoom) << zoom);
|
||||
|
||||
if (tiled & TILED_X_AXIS) x = SGN(x) * (ABS(x)%w);
|
||||
if (tiled & TILED_Y_AXIS) y = SGN(y) * (ABS(y)%h);
|
||||
|
||||
if (index_bg_color == -1)
|
||||
RenderEngine::renderCheckedBackground(doublebuf, -pos_x, -pos_y, zoom);
|
||||
else
|
||||
raster::clear_image(doublebuf, pal->getEntry(index_bg_color));
|
||||
|
||||
switch (tiled) {
|
||||
case TILED_NONE:
|
||||
RenderEngine::renderImage(doublebuf, render, pal, x, y, zoom);
|
||||
break;
|
||||
case TILED_X_AXIS:
|
||||
for (u=x-w; u<JI_SCREEN_W+w; u+=w)
|
||||
RenderEngine::renderImage(doublebuf, render, pal, u, y, zoom);
|
||||
break;
|
||||
case TILED_Y_AXIS:
|
||||
for (v=y-h; v<JI_SCREEN_H+h; v+=h)
|
||||
RenderEngine::renderImage(doublebuf, render, pal, x, v, zoom);
|
||||
break;
|
||||
case TILED_BOTH:
|
||||
for (v=y-h; v<JI_SCREEN_H+h; v+=h)
|
||||
for (u=x-w; u<JI_SCREEN_W+w; u+=w)
|
||||
RenderEngine::renderImage(doublebuf, render, pal, u, v, zoom);
|
||||
break;
|
||||
}
|
||||
|
||||
raster::convert_image_to_allegro(doublebuf, ji_screen, 0, 0, pal);
|
||||
}
|
||||
|
||||
// It is necessary in case ji_screen is double-bufferred
|
||||
gui_feedback();
|
||||
|
||||
if (keypressed()) {
|
||||
int readkey_value = readkey();
|
||||
Message* msg = create_message_from_readkey_value(kKeyDownMessage, readkey_value);
|
||||
Command* command = NULL;
|
||||
get_command_from_key_message(msg, &command, NULL);
|
||||
delete msg;
|
||||
|
||||
// Change frame
|
||||
if (command != NULL &&
|
||||
(strcmp(command->short_name(), CommandId::GotoFirstFrame) == 0 ||
|
||||
strcmp(command->short_name(), CommandId::GotoPreviousFrame) == 0 ||
|
||||
strcmp(command->short_name(), CommandId::GotoNextFrame) == 0 ||
|
||||
strcmp(command->short_name(), CommandId::GotoLastFrame) == 0)) {
|
||||
// Execute the command
|
||||
context->executeCommand(command);
|
||||
|
||||
// Redraw
|
||||
redraw = true;
|
||||
|
||||
// Re-render
|
||||
render.reset(NULL);
|
||||
}
|
||||
// Play the animation
|
||||
else if (command != NULL &&
|
||||
strcmp(command->short_name(), CommandId::PlayAnimation) == 0) {
|
||||
// TODO
|
||||
}
|
||||
// Change background color
|
||||
else if ((readkey_value>>8) == KEY_PLUS_PAD ||
|
||||
(readkey_value&0xff) == '+') {
|
||||
if (index_bg_color == -1 ||
|
||||
index_bg_color < pal->size()-1) {
|
||||
++index_bg_color;
|
||||
redraw = true;
|
||||
}
|
||||
}
|
||||
else if ((readkey_value>>8) == KEY_MINUS_PAD ||
|
||||
(readkey_value&0xff) == '-') {
|
||||
if (index_bg_color >= 0) {
|
||||
--index_bg_color; // can be -1 which is the checked background
|
||||
redraw = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
} while (jmouse_b(0) == kButtonNone);
|
||||
|
||||
do {
|
||||
jmouse_poll();
|
||||
gui_feedback();
|
||||
} while (jmouse_b(0) != kButtonNone);
|
||||
clear_keybuf();
|
||||
|
||||
ui::set_mouse_position(gfx::Point(old_mouse_x, old_mouse_y));
|
||||
jmouse_set_cursor(kArrowCursor);
|
||||
|
||||
ui::Manager::getDefault()->invalidate();
|
||||
PreviewWindow window(context, editor);
|
||||
window.openWindowInForeground();
|
||||
}
|
||||
|
||||
Command* CommandFactory::createPreviewCommand()
|
||||
|
@ -1046,12 +1046,10 @@ void Manager::_openWindow(Window* window)
|
||||
|
||||
void Manager::_closeWindow(Window* window, bool redraw_background)
|
||||
{
|
||||
Message* msg;
|
||||
gfx::Region reg1;
|
||||
|
||||
if (!hasChild(window))
|
||||
return;
|
||||
|
||||
gfx::Region reg1;
|
||||
if (redraw_background)
|
||||
window->getRegion(reg1);
|
||||
|
||||
@ -1085,7 +1083,7 @@ void Manager::_closeWindow(Window* window, bool redraw_background)
|
||||
window->setVisible(false);
|
||||
|
||||
// Close message.
|
||||
msg = new Message(kCloseMessage);
|
||||
Message* msg = new Message(kCloseMessage);
|
||||
msg->addRecipient(window);
|
||||
enqueueMessage(msg);
|
||||
|
||||
|
@ -77,11 +77,4 @@ KeyMessage::KeyMessage(MessageType type, KeyScancode scancode, int unicodeChar,
|
||||
{
|
||||
}
|
||||
|
||||
KeyMessage* create_message_from_readkey_value(MessageType type, int readkey_value)
|
||||
{
|
||||
return new KeyMessage(type,
|
||||
static_cast<KeyScancode>((readkey_value >> 8) & 0xff),
|
||||
(readkey_value & 0xff), 0);
|
||||
}
|
||||
|
||||
} // namespace ui
|
||||
|
@ -82,9 +82,6 @@ namespace ui {
|
||||
bool m_propagate_to_parent : 1;
|
||||
};
|
||||
|
||||
// Deprecated
|
||||
KeyMessage* create_message_from_readkey_value(MessageType type, int readkey_value);
|
||||
|
||||
class PaintMessage : public Message
|
||||
{
|
||||
public:
|
||||
|
Loading…
Reference in New Issue
Block a user