Add button in status bar to change the transparent color of pixels in movement in the current editor.

* Add Editor::setMaskColorForPixelsMovement() method.
* EDITOR_STATE_MOVING_PIXELS is not a particular state because we can move scroll while we are moving pixels.
* Rename EDITOR_STATE_MOVING_SCROLL to EDITOR_STATE_SCROLLING.
* Add StatusBar::show/hideMovePixelsOptions and StatusBar::getTransparentColor().
This commit is contained in:
David Capello 2010-08-11 21:48:12 -03:00
parent 328fab545c
commit 7b272f86f7
4 changed files with 221 additions and 136 deletions

View File

@ -68,8 +68,7 @@ class Editor : public Widget
// editor states
enum State {
EDITOR_STATE_STANDBY,
EDITOR_STATE_MOVING_SCROLL,
EDITOR_STATE_MOVING_PIXELS,
EDITOR_STATE_SCROLLING,
EDITOR_STATE_DRAWING,
};
@ -142,6 +141,7 @@ public:
void editor_draw_mask_safe();
void flashCurrentLayer();
void setMaskColorForPixelsMovement(color_t color);
void screen_to_editor(int xin, int yin, int *xout, int *yout);
void editor_to_screen(int xin, int yin, int *xout, int *yout);

View File

@ -131,9 +131,16 @@ void Editor::editor_set_sprite(Sprite* sprite)
if (this->hasMouse())
jmanager_free_mouse(); // TODO Why is this here? Review this code
// The editor must be stand-by state
ASSERT(m_state == EDITOR_STATE_STANDBY);
// Change the sprite
m_sprite = sprite;
if (m_sprite) {
// Get the preferred sprite's settings to edit it
PreferredEditorSettings preferred = m_sprite->getPreferredEditorSettings();
// Change the editor's configuration using the retrieved sprite's settings
m_zoom = preferred.zoom;
editor_update();
@ -141,11 +148,13 @@ void Editor::editor_set_sprite(Sprite* sprite)
m_offset_y + preferred.scroll_y,
false);
}
// In this case sprite is NULL
else {
editor_update();
editor_set_scroll(0, 0, false);
editor_set_scroll(0, 0, false); // No scroll
}
// Redraw the entire editor (because we have a new sprite to draw)
dirty();
}
@ -562,6 +571,15 @@ void Editor::flashCurrentLayer()
}
}
void Editor::setMaskColorForPixelsMovement(color_t color)
{
ASSERT(m_sprite != NULL);
ASSERT(m_pixelsMovement != NULL);
int imgtype = m_sprite->getImgType();
m_pixelsMovement->setMaskColor(get_color_for_image(imgtype, color));
}
void Editor::deleteDecorators()
{
for (std::vector<Decorator*>::iterator
@ -653,6 +671,7 @@ void Editor::dropPixels()
m_state = EDITOR_STATE_STANDBY;
releaseMouse();
app_get_statusbar()->hideMovePixelsOptions();
editor_update_statusbar_for_standby();
}
@ -745,7 +764,7 @@ void Editor::editor_update_statusbar_for_pixel_movement()
{
Rect bounds = m_pixelsMovement->getImageBounds();
app_get_statusbar()->setStatusText
(100, "Pos %d %d, Size %d %d [Press ENTER to drop]",
(100, "Pos %d %d, Size %d %d",
bounds.x, bounds.y, bounds.w, bounds.h);
}
@ -976,19 +995,6 @@ bool Editor::onProcessMessage(JMessage msg)
return true;
}
}
// Moving pixels loop
else if (m_state == EDITOR_STATE_MOVING_PIXELS) {
if (m_insideSelection) {
// Re-catch the image
int x, y;
screen_to_editor(msg->mouse.x, msg->mouse.y, &x, &y);
m_pixelsMovement->catchImageAgain(x, y);
return true;
}
else {
dropPixels();
}
}
if (!hasCapture()) {
UIContext* context = UIContext::instance();
@ -997,18 +1003,39 @@ bool Editor::onProcessMessage(JMessage msg)
set_current_editor(this);
context->set_current_sprite(m_sprite);
// Move the scroll
// Start scroll loop
if (msg->mouse.middle ||
m_space_pressed ||
current_tool->getInk(msg->mouse.right ? 1: 0)->isScrollMovement()) {
m_state = EDITOR_STATE_MOVING_SCROLL;
m_state = EDITOR_STATE_SCROLLING;
editor_setcursor(msg->mouse.x, msg->mouse.y);
captureMouse();
return true;
}
if (m_pixelsMovement) {
// Start "moving pixels" loop
if (m_insideSelection) {
// Re-catch the image
int x, y;
screen_to_editor(msg->mouse.x, msg->mouse.y, &x, &y);
m_pixelsMovement->catchImageAgain(x, y);
captureMouse();
return true;
}
// End "moving pixels" loop
else {
// Drop pixels (e.g. to start drawing)
dropPixels();
}
}
// Move frames position
else if ((m_ctrl_pressed &&
!current_tool->getInk(msg->mouse.right ? 1: 0)->isSelection()) ||
current_tool->getInk(msg->mouse.right ? 1: 0)->isCelMovement()) {
if ((m_ctrl_pressed &&
!current_tool->getInk(msg->mouse.right ? 1: 0)->isSelection()) ||
current_tool->getInk(msg->mouse.right ? 1: 0)->isCelMovement()) {
if ((m_sprite->getCurrentLayer()) &&
(m_sprite->getCurrentLayer()->type == GFXOBJ_LAYER_IMAGE)) {
// TODO you can move the `Background' with tiled mode
@ -1026,9 +1053,8 @@ bool Editor::onProcessMessage(JMessage msg)
bool click2 = get_config_bool("Options", "MoveClick2", FALSE);
interactive_move_layer(click2 ? MODE_CLICKANDCLICK:
MODE_CLICKANDRELEASE,
TRUE, NULL);
TRUE, NULL); // TODO remove this routine
}
return true;
}
}
// Move selected pixels
@ -1045,9 +1071,6 @@ bool Editor::onProcessMessage(JMessage msg)
return true;
}
// Change editor's state
m_state = EDITOR_STATE_MOVING_PIXELS;
// Copy the mask to the extra cel image
Image* tmpImage = NewImageFromMask(m_sprite);
x = m_sprite->getMask()->x;
@ -1064,8 +1087,14 @@ bool Editor::onProcessMessage(JMessage msg)
screen_to_editor(msg->mouse.x, msg->mouse.y, &x, &y);
m_pixelsMovement->catchImage(x, y);
// Setup mask color
setMaskColorForPixelsMovement(app_get_statusbar()->getTransparentColor());
// Update status bar
editor_update_statusbar_for_pixel_movement();
app_get_statusbar()->showMovePixelsOptions();
}
captureMouse();
}
// Call the eyedropper command
else if (m_alt_pressed ||
@ -1104,10 +1133,9 @@ bool Editor::onProcessMessage(JMessage msg)
// Redraw it (without pen preview)
if (thick)
editor_draw_cursor(msg->mouse.x, msg->mouse.y);
}
// Capture the mouse
captureMouse();
captureMouse();
}
}
return true;
@ -1116,7 +1144,7 @@ bool Editor::onProcessMessage(JMessage msg)
break;
// Move the scroll
if (m_state == EDITOR_STATE_MOVING_SCROLL) {
if (m_state == EDITOR_STATE_SCROLLING) {
JWidget view = jwidget_get_view(this);
JRect vp = jview_get_viewport_position(view);
int scroll_x, scroll_y;
@ -1137,12 +1165,12 @@ bool Editor::onProcessMessage(JMessage msg)
}
}
// Moving pixels
else if (m_state == EDITOR_STATE_MOVING_PIXELS) {
// Infinite scroll
controlInfiniteScroll(msg);
else if (m_pixelsMovement) {
// If there is a button pressed
if (m_pixelsMovement->isDragging()) {
// Infinite scroll
controlInfiniteScroll(msg);
// Get the position of the mouse in the sprite
int x, y;
screen_to_editor(msg->mouse.x, msg->mouse.y, &x, &y);
@ -1254,16 +1282,15 @@ bool Editor::onProcessMessage(JMessage msg)
clear_keybuf();
}
// Moving pixels
else if (m_state == EDITOR_STATE_MOVING_PIXELS) {
// Drop the image temporarily in this location (where the user releases the mouse)
m_pixelsMovement->dropImageTemporarily();
return true;
}
else {
else if (m_state != EDITOR_STATE_STANDBY) {
ASSERT(m_toolLoopManager == NULL);
m_state = EDITOR_STATE_STANDBY;
}
// Moving pixels
else if (m_pixelsMovement) {
// Drop the image temporarily in this location (where the user releases the mouse)
m_pixelsMovement->dropImageTemporarily();
}
editor_setcursor(msg->mouse.x, msg->mouse.y);
editor_update_statusbar_for_standby();
@ -1290,7 +1317,7 @@ bool Editor::onProcessMessage(JMessage msg)
case KEY_LCONTROL:
case KEY_RCONTROL:
// If the user press the CTRL key when he is dragging pixels (but not pressing the mouse buttons)...
if (!m_ctrl_pressed && !jmouse_b(0) && m_state == EDITOR_STATE_MOVING_PIXELS) {
if (!m_ctrl_pressed && !jmouse_b(0) && m_pixelsMovement) {
// Drop pixels (sure the user will press the mouse button to start dragging a copy)
dropPixels();
}
@ -1309,20 +1336,6 @@ bool Editor::onProcessMessage(JMessage msg)
if (m_state == EDITOR_STATE_DRAWING)
return true;
if (m_state == EDITOR_STATE_MOVING_PIXELS) {
dropPixels();
// Resend the key/message to the manager
if (msg->key.scancode != KEY_ENTER &&
msg->key.scancode != KEY_ENTER_PAD) {
JMessage newmsg = jmessage_new_copy_without_dests(msg);
jmessage_add_dest(newmsg, ji_get_default_manager());
jmanager_enqueue_message(newmsg);
}
// Used
return true;
}
break;
case JM_KEYRELEASED:
@ -1361,8 +1374,7 @@ bool Editor::onProcessMessage(JMessage msg)
case JM_WHEEL:
if (m_state == EDITOR_STATE_STANDBY ||
m_state == EDITOR_STATE_DRAWING ||
m_state == EDITOR_STATE_MOVING_PIXELS) {
m_state == EDITOR_STATE_DRAWING) {
// There are and sprite in the editor and the mouse is inside
if (m_sprite && this->hasMouse()) {
int dz = jmouse_z(1) - jmouse_z(0);
@ -1518,46 +1530,11 @@ void Editor::editor_setcursor(int x, int y)
switch (m_state) {
case EDITOR_STATE_MOVING_SCROLL:
case EDITOR_STATE_SCROLLING:
hide_drawing_cursor();
jmouse_set_cursor(JI_CURSOR_SCROLL);
break;
case EDITOR_STATE_MOVING_PIXELS:
{
UIContext* context = UIContext::instance();
Tool* current_tool = context->getSettings()->getCurrentTool();
int x, y;
screen_to_editor(jmouse_x(0), jmouse_y(0), &x, &y);
// Move selection
if (m_pixelsMovement->isDragging() ||
m_sprite->getMask()->contains_point(x, y)) {
hide_drawing_cursor();
jmouse_set_cursor(JI_CURSOR_MOVE);
if (!m_insideSelection)
m_insideSelection = true;
return;
}
if (m_insideSelection)
m_insideSelection = false;
// Draw
if (m_cursor_candraw) {
jmouse_set_cursor(JI_CURSOR_NULL);
show_drawing_cursor();
}
// Forbidden
else {
hide_drawing_cursor();
jmouse_set_cursor(JI_CURSOR_FORBIDDEN);
}
}
break;
case EDITOR_STATE_DRAWING:
if (current_tool->getInk(0)->isEyedropper()) {
hide_drawing_cursor();
@ -1577,8 +1554,38 @@ void Editor::editor_setcursor(int x, int y)
editor_update_candraw(); // TODO remove this
// Pixels movement
if (m_pixelsMovement) {
int x, y;
screen_to_editor(jmouse_x(0), jmouse_y(0), &x, &y);
// Move selection
if (m_pixelsMovement->isDragging() ||
m_sprite->getMask()->contains_point(x, y)) {
hide_drawing_cursor();
jmouse_set_cursor(JI_CURSOR_MOVE);
if (!m_insideSelection)
m_insideSelection = true;
return;
}
if (m_insideSelection)
m_insideSelection = false;
// Draw
if (m_cursor_candraw) {
jmouse_set_cursor(JI_CURSOR_NULL);
show_drawing_cursor();
}
// Forbidden
else {
hide_drawing_cursor();
jmouse_set_cursor(JI_CURSOR_FORBIDDEN);
}
}
// Eyedropper
if (m_alt_pressed) {
else if (m_alt_pressed) {
hide_drawing_cursor();
jmouse_set_cursor(JI_CURSOR_EYEDROPPER);
}

View File

@ -24,6 +24,7 @@
#include <cstring>
#include "jinete/jinete.h"
#include "Vaca/Size.h"
#include "app.h"
#include "commands/commands.h"
@ -35,6 +36,7 @@
#include "modules/palettes.h"
#include "modules/skinneable_theme.h"
#include "raster/cel.h"
#include "raster/image.h"
#include "raster/layer.h"
#include "raster/sprite.h"
#include "raster/undo.h"
@ -42,6 +44,7 @@
#include "tools/tool.h"
#include "ui_context.h"
#include "util/misc.h"
#include "widgets/colbut.h"
#include "widgets/editor.h"
#include "widgets/statebar.h"
@ -55,6 +58,7 @@ enum {
static bool tipwindow_msg_proc(JWidget widget, JMessage msg);
static bool transparent_color_change_hook(JWidget widget, void *data);
static bool slider_change_hook(JWidget widget, void *data);
static void button_command(JWidget widget, void *data);
@ -91,40 +95,62 @@ StatusBar::StatusBar()
m_tipwindow = NULL;
m_hot_layer = -1;
// The extra pixel in left and right borders are necessary so
// m_commandsBox and m_movePixelsBox do not overlap the upper-left
// and upper-right pixels drawn in JM_DRAW message (see putpixels)
jwidget_set_border(this, 1*jguiscale(), 0, 1*jguiscale(), 0);
// Construct the commands box
Widget* box1 = jbox_new(JI_HORIZONTAL);
Widget* box2 = jbox_new(JI_HORIZONTAL | JI_HOMOGENEOUS);
Widget* box3 = jbox_new(JI_HORIZONTAL);
m_slider = jslider_new(0, 255, 255);
{
Widget* box1 = jbox_new(JI_HORIZONTAL);
Widget* box2 = jbox_new(JI_HORIZONTAL | JI_HOMOGENEOUS);
Widget* box3 = jbox_new(JI_HORIZONTAL);
m_slider = jslider_new(0, 255, 255);
setup_mini_look(m_slider);
setup_mini_look(m_slider);
ICON_NEW(m_b_first, GFX_ANI_FIRST, ACTION_FIRST);
ICON_NEW(m_b_prev, GFX_ANI_PREV, ACTION_PREV);
ICON_NEW(m_b_play, GFX_ANI_PLAY, ACTION_PLAY);
ICON_NEW(m_b_next, GFX_ANI_NEXT, ACTION_NEXT);
ICON_NEW(m_b_last, GFX_ANI_LAST, ACTION_LAST);
ICON_NEW(m_b_first, GFX_ANI_FIRST, ACTION_FIRST);
ICON_NEW(m_b_prev, GFX_ANI_PREV, ACTION_PREV);
ICON_NEW(m_b_play, GFX_ANI_PLAY, ACTION_PLAY);
ICON_NEW(m_b_next, GFX_ANI_NEXT, ACTION_NEXT);
ICON_NEW(m_b_last, GFX_ANI_LAST, ACTION_LAST);
HOOK(m_slider, JI_SIGNAL_SLIDER_CHANGE, slider_change_hook, 0);
jwidget_set_min_size(m_slider, JI_SCREEN_W/5, 0);
HOOK(m_slider, JI_SIGNAL_SLIDER_CHANGE, slider_change_hook, 0);
jwidget_set_min_size(m_slider, JI_SCREEN_W/5, 0);
jwidget_set_border(this, 1*jguiscale(), 0, 0, 0);
jwidget_set_border(box1, 2*jguiscale(), 1*jguiscale(), 2*jguiscale(), 2*jguiscale());
jwidget_noborders(box2);
jwidget_noborders(box3);
jwidget_expansive(box3, true);
jwidget_set_border(box1, 2*jguiscale(), 1*jguiscale(), 2*jguiscale(), 2*jguiscale());
jwidget_noborders(box2);
jwidget_noborders(box3);
jwidget_expansive(box3, true);
jwidget_add_child(box2, m_b_first);
jwidget_add_child(box2, m_b_prev);
jwidget_add_child(box2, m_b_play);
jwidget_add_child(box2, m_b_next);
jwidget_add_child(box2, m_b_last);
jwidget_add_child(box2, m_b_first);
jwidget_add_child(box2, m_b_prev);
jwidget_add_child(box2, m_b_play);
jwidget_add_child(box2, m_b_next);
jwidget_add_child(box2, m_b_last);
jwidget_add_child(box1, box3);
jwidget_add_child(box1, box2);
jwidget_add_child(box1, m_slider);
jwidget_add_child(box1, box3);
jwidget_add_child(box1, box2);
jwidget_add_child(box1, m_slider);
m_commandsBox = box1;
m_commandsBox = box1;
}
// Construct move-pixels box
{
Widget* filler = jbox_new(JI_HORIZONTAL);
jwidget_expansive(filler, true);
m_movePixelsBox = jbox_new(JI_HORIZONTAL);
m_transparentLabel = new Label("Transparent Color:");
m_transparentColor = colorbutton_new(color_mask(), IMAGE_RGB);
jwidget_add_child(m_movePixelsBox, filler);
jwidget_add_child(m_movePixelsBox, m_transparentLabel);
jwidget_add_child(m_movePixelsBox, m_transparentColor);
HOOK(m_transparentColor, SIGNAL_COLORBUTTON_CHANGE, transparent_color_change_hook, 1);
}
App::instance()->CurrentToolChange.connect(&StatusBar::onCurrentToolChange, this);
}
@ -253,6 +279,27 @@ void StatusBar::showTool(int msecs, Tool* tool)
}
}
void StatusBar::showMovePixelsOptions()
{
if (!jwidget_has_child(this, m_movePixelsBox)) {
jwidget_add_child(this, m_movePixelsBox);
jwidget_dirty(this);
}
}
void StatusBar::hideMovePixelsOptions()
{
if (jwidget_has_child(this, m_movePixelsBox)) {
jwidget_remove_child(this, m_movePixelsBox);
jwidget_dirty(this);
}
}
color_t StatusBar::getTransparentColor()
{
return colorbutton_get_color(m_transparentColor);
}
//////////////////////////////////////////////////////////////////////
// Progress bars stuff
@ -321,13 +368,25 @@ bool StatusBar::onProcessMessage(JMessage msg)
jwidget_set_rect(m_commandsBox, rc);
jrect_free(rc);
}
{
JRect rc = jrect_new_copy(this->rc);
Vaca::Size reqSize = m_movePixelsBox->getPreferredSize();
rc->x1 = rc->x2 - reqSize.w;
rc->x2 -= this->border_width.r;
jwidget_set_rect(m_movePixelsBox, rc);
jrect_free(rc);
}
return true;
case JM_CLOSE:
if (!jwidget_has_child(this, m_commandsBox)) {
/* append the "commands_box" to destroy it in the jwidget_free */
// Append the "m_commandsBox" so it is destroyed in StatusBar dtor.
jwidget_add_child(this, m_commandsBox);
}
if (!jwidget_has_child(this, m_movePixelsBox)) {
// Append the "m_movePixelsBox" so it is destroyed in StatusBar dtor.
jwidget_add_child(this, m_movePixelsBox);
}
break;
case JM_DRAW: {
@ -515,21 +574,23 @@ bool StatusBar::onProcessMessage(JMessage msg)
case JM_MOUSEENTER: {
bool state = (UIContext::instance()->get_current_sprite() != NULL);
if (!jwidget_has_child(this, m_commandsBox) && state) {
m_b_first->setEnabled(state);
m_b_prev->setEnabled(state);
m_b_play->setEnabled(state);
m_b_next->setEnabled(state);
m_b_last->setEnabled(state);
if (!jwidget_has_child(this, m_movePixelsBox)) {
if (!jwidget_has_child(this, m_commandsBox) && state) {
m_b_first->setEnabled(state);
m_b_prev->setEnabled(state);
m_b_play->setEnabled(state);
m_b_next->setEnabled(state);
m_b_last->setEnabled(state);
updateFromLayer();
updateFromLayer();
jwidget_add_child(this, m_commandsBox);
jwidget_dirty(this);
}
else {
// Status text for donations
setStatusText(0, "Click the \"Donate\" button to support ASE development");
jwidget_add_child(this, m_commandsBox);
jwidget_dirty(this);
}
else {
// Status text for donations
setStatusText(0, "Click the \"Donate\" button to support ASE development");
}
}
break;
}
@ -669,6 +730,13 @@ static bool tipwindow_msg_proc(JWidget widget, JMessage msg)
return false;
}
static bool transparent_color_change_hook(JWidget widget, void *data)
{
if (current_editor)
current_editor->setMaskColorForPixelsMovement(app_get_statusbar()->getTransparentColor());
return true;
}
static bool slider_change_hook(JWidget widget, void *data)
{
try {

View File

@ -57,6 +57,11 @@ public:
void showColor(int msecs, const char* text, color_t color, int alpha);
void showTool(int msecs, Tool* tool);
void showMovePixelsOptions();
void hideMovePixelsOptions();
color_t getTransparentColor();
// Methods to add and remove progress bars
Progress* addProgress();
void removeProgress(Progress* progress);
@ -92,6 +97,11 @@ private:
Widget* m_b_next; // Go to next frame
Widget* m_b_last; // Go to last frame
// Box with move-pixels commands (when the user drag-and-drop selected pixels using the editor)
Widget* m_movePixelsBox;
Widget* m_transparentLabel;
Widget* m_transparentColor;
// Tip window
Frame* m_tipwindow;