diff --git a/programs/cmm/iconedit/actions_history.h b/programs/cmm/iconedit/actions_history.h index 9f44854e66..adfbbff5b3 100644 --- a/programs/cmm/iconedit/actions_history.h +++ b/programs/cmm/iconedit/actions_history.h @@ -25,7 +25,7 @@ void _ActionsHistory::init() { currentIndex = -1; for (i = 0; i < MAX_ACTIONS_COUNT; i++) - stack[i] = malloc(image.columns * image.rows); + stack[i] = malloc(image.columns * image.rows * 4); saveCurrentState(); } @@ -84,43 +84,47 @@ void _ActionsHistory::restoreState(dword index) { void _ActionsHistory::undoLastAction() { dword previousAction; - // Если вышли за левую границу, перемещаемся в конец массива - if (currentIndex == 0) { - previousAction = MAX_ACTIONS_COUNT - 1; - } - else { - previousAction = currentIndex - 1; - } - - if (isEmpty()) - return; - else { - if (currentIndex != head) { - restoreState(previousAction); - DrawCanvas(); + if (!is_selection_moving()) { + // Если вышли за левую границу, перемещаемся в конец массива + if (currentIndex == 0) { + previousAction = MAX_ACTIONS_COUNT - 1; + } + else { + previousAction = currentIndex - 1; } - if (currentIndex != head) - currentIndex = previousAction; + if (isEmpty()) + return; + else { + if (currentIndex != head) { + restoreState(previousAction); + DrawCanvas(); + } + + if (currentIndex != head) + currentIndex = previousAction; + } } } void _ActionsHistory::redoLastAction() { dword nextAction = calc(currentIndex + 1); - // Если вышли за левую границу, возвращаемся в начало - if (nextAction >= MAX_ACTIONS_COUNT) - nextAction = nextAction % MAX_ACTIONS_COUNT; + if (!is_selection_moving()) { + // Если вышли за левую границу, возвращаемся в начало + if (nextAction >= MAX_ACTIONS_COUNT) + nextAction = nextAction % MAX_ACTIONS_COUNT; - if (isEmpty()) - return; - else { - if (nextAction != tail) { - restoreState(nextAction); - DrawCanvas(); + if (isEmpty()) + return; + else { + if (nextAction != tail) { + restoreState(nextAction); + DrawCanvas(); + } + + if (nextAction != tail) + currentIndex = nextAction; } - - if (nextAction != tail) - currentIndex = nextAction; } } \ No newline at end of file diff --git a/programs/cmm/iconedit/iconedit.c b/programs/cmm/iconedit/iconedit.c index 333ad06696..df5ae7ec39 100644 --- a/programs/cmm/iconedit/iconedit.c +++ b/programs/cmm/iconedit/iconedit.c @@ -18,6 +18,7 @@ pipet aside color view #include "../lib/mem.h" #include "../lib/obj/libimg.h" #include "../lib/patterns/rgb.h" +#include "../lib/patterns/libimg_load_skin.h" #include "colors_mas.h" @@ -27,7 +28,7 @@ pipet aside color view // // //===================================================// -#define T_TITLE "Icon Editor 0.39" +#define T_TITLE "Icon Editor 0.45" #define TOOLBAR_H 24+8 #define PANEL_LEFT_W 16+5+5+3+3 @@ -38,6 +39,9 @@ pipet aside color view #define COLSIZE 18 #define RIGHT_BAR_W PAL_ITEMS_X_COUNT*COLSIZE +#define TO_CANVAS_X(xval) xval - canvas.x/zoom.value +#define TO_CANVAS_Y(yval) yval - canvas.y/zoom.value + block canvas = { NULL, NULL, NULL, NULL }; block wrapper = { PANEL_LEFT_W, TOOLBAR_H, NULL, NULL }; block right_bar = { NULL, TOOLBAR_H, RIGHT_BAR_W+10, NULL }; @@ -67,6 +71,9 @@ enum { BTN_FILL, BTN_LINE, BTN_RECT, + BTN_SELECT, + BTN_ZOOM_IN, + BTN_ZOOM_OUT, BTNS_PALETTE_COLOR_MAS = 100, BTNS_LAST_USED_COLORS = 400 }; @@ -109,6 +116,7 @@ enum { TOOL_FILL, TOOL_LINE, TOOL_RECT, + TOOL_SELECT }; struct Tool { @@ -117,10 +125,11 @@ struct Tool { void (*activate)(); void (*deactivate)(); void (*onMouseEvent)(int x, int y, int lkm, int pkm); + void (*onKeyEvent)(dword keycode); void (*onCanvasDraw)(); }; -Tool tools[5]; +Tool tools[6]; int currentTool = -1; void resetCurrentTool() { @@ -140,6 +149,7 @@ void setCurrentTool(int index) { tools[index].activate(); DrawLeftPanel(); + DrawCanvas(); } //===================================================// @@ -308,6 +318,269 @@ void SimpleFigureTool_onCanvasDraw() { } } +// Selection +int selection_start_x = -1; +int selection_start_y = -1; +int selection_end_x = -1; +int selection_end_y = -1; +bool selection_active = false; + +dword SelectionTool_buffer = 0; +dword SelectionTool_buffer_r = 0; +dword SelectionTool_buffer_c = 0; + +bool selection_moving_started = false; +int selection_pivot_x = -1; +int selection_pivot_y = -1; + +void SelectTool_normalizeSelection() { + int t; + + // Restructuring of the selection coordinates + if (selection_end_x < selection_start_x) { + t = selection_start_x; + selection_start_x = selection_end_x; + selection_end_x = t; + } + + if (selection_end_y < selection_start_y) { + t = selection_end_y; + selection_end_y = selection_start_y; + selection_start_y = t; + } +} + +void reset_selection_moving() { + if (selection_moving_started) { + SelectTool_drawBuffer(selection_start_x, selection_start_y, 1); + + selection_pivot_x = -1; + selection_pivot_y = -1; + + selection_moving_started = false; + + actionsHistory.saveCurrentState(); + DrawCanvas(); + } +} + +bool is_selection_moving() { + return selection_moving_started; +} + +void reset_selection() { + reset_selection_moving(); + + selection_start_x = -1; + selection_start_y = -1; + selection_end_x = -1; + selection_end_y = -1; +} + +void SelectTool_activate() { + reset_selection(); + + selection_active = false; +} + +void SelectTool_deactivate() { + reset_selection_moving(); +} + +bool SelectTool_pointInSelection(int x, int y) { + if (x >= selection_start_x) && (x <= selection_end_x) && (y >= selection_start_y) && (y <= selection_end_y) + return true; + else + return false; +} + + +void SelectTool_copyToBuffer() { + dword offset, r, c; + + if (SelectionTool_buffer != 0) + free(SelectionTool_buffer); + + SelectionTool_buffer_r = selection_end_y - selection_start_y + 1; + SelectionTool_buffer_c = selection_end_x - selection_start_x + 1; + SelectionTool_buffer = malloc(SelectionTool_buffer_r * SelectionTool_buffer_c * 4); + + for (r = selection_start_y; r <= selection_end_y; r++) { + for (c = selection_start_x; c <= selection_end_x; c++) { + offset = calc(SelectionTool_buffer_c * calc(r - selection_start_y) + calc(c - selection_start_x)) * 4; + + ESDWORD[SelectionTool_buffer + offset] = image.get_pixel(r, c); + } + } +} + +void SelectTool_onMouseEvent(int mouseX, int mouseY, int lkm, int pkm) { + int click_x, click_y, dx, dy, m_x, m_y, r, c, color; + dword pixel; + + m_x = TO_CANVAS_X(mouseX); + m_y = TO_CANVAS_Y(mouseY); + + if (mouse.down) && (canvas.hovered()) && (!selection_active) { + if (selection_start_x != -1) && (SelectTool_pointInSelection(m_x, m_y)) { + if (selection_pivot_x == -1) { + selection_pivot_x = m_x; + selection_pivot_y = m_y; + + GetKeys(); + + if (!selection_moving_started) && ( !(key_modifier&KEY_LSHIFT) ) { + for (r = selection_start_y; r <= selection_end_y; r++) + for (c = selection_start_x; c <= selection_end_x; c++) { + image.set_pixel(r, c, color2); + } + } + + selection_moving_started = true; + } + } + else { + + reset_selection(); + selection_active = true; + } + } + + if (selection_pivot_x != -1) { + dx = m_x - selection_pivot_x; + dy = m_y - selection_pivot_y; + + if (selection_start_x + dx < 0) + dx = selection_start_x; + + if (selection_end_x + dx >= 32) + dx = 31 - selection_end_x; + + if (selection_start_y + dy < 0) + dy = selection_start_y; + + if (selection_end_y + dy >= 32) + dy = 31 - selection_end_y; + + + selection_start_x += dx; + selection_end_x += dx; + + selection_start_y += dy; + selection_end_y += dy; + + selection_pivot_x += dx; + selection_pivot_y += dy; + + DrawCanvas(); + } + + if (selection_active) + { + if (mouseX>canvas.x+canvas.w-zoom.value) mouseX = canvas.x+canvas.w-zoom.value; + if (mouseY>canvas.y+canvas.h-zoom.value) mouseY = canvas.y+canvas.h-zoom.value; + + if (mouseX= 0) && (selection_start_y >= 0) && (selection_end_x >= 0) && (selection_end_y >= 0)) { + DrawSelection(selection_start_x, selection_start_y, selection_end_x, selection_end_y); + } +} + +void SelectTool_drawBuffer(int insert_x, int insert_y, int target) { + dword color; + dword offset, r, c; + dword insert_to_x, insert_to_y; + + if (SelectionTool_buffer != 0) { + insert_to_x = insert_x + SelectionTool_buffer_c - 1; + + if (insert_to_x >= image.columns) + insert_to_x = image.columns-1; + + insert_to_y = insert_y + SelectionTool_buffer_r - 1; + + if (insert_to_y >= image.rows) + insert_to_y = image.rows-1; + + for (r = insert_y; r <= insert_to_y; r++) { + for (c = insert_x; c <= insert_to_x; c++) { + offset = calc(SelectionTool_buffer_c * calc(r - insert_y) + calc(c - insert_x)) * 4; + + color = ESDWORD[SelectionTool_buffer + offset]; + + if (target == 1) + image.set_pixel(r, c, color); + else + DrawBar(c*zoom.value + canvas.x, r*zoom.value + canvas.y, + zoom.value, zoom.value, color); + } + } + } +} + +void SelectTool_onKeyEvent(dword keycode) { + dword offset, r, c; + dword insert_x, insert_y, insert_to_x, insert_to_y; + + if (keycode == SCAN_CODE_KEY_V) { + if (SelectionTool_buffer != 0) { + reset_selection(); + + selection_moving_started = true; + selection_start_x = 0; + selection_end_x = SelectionTool_buffer_c - 1; + + selection_start_y = 0; + selection_end_y = SelectionTool_buffer_r - 1; + + DrawCanvas(); + + } + } +} + void initTools() { tools[0].id = TOOL_PENCIL; @@ -332,6 +605,13 @@ void initTools() tools[4].deactivate = #SimpleFigureTool_Reset; tools[4].onMouseEvent = #SimpleFigureTool_onMouseEvent; tools[4].onCanvasDraw = #SimpleFigureTool_onCanvasDraw; + + tools[5].id = TOOL_SELECT; + tools[5].activate = #SelectTool_activate; + tools[5].deactivate = #SelectTool_deactivate; + tools[5].onMouseEvent = #SelectTool_onMouseEvent; + tools[5].onCanvasDraw = #SelectTool_onCanvasDraw; + tools[5].onKeyEvent = #SelectTool_onKeyEvent; } void main() @@ -394,7 +674,7 @@ void main() case evButton: btn = GetButtonID(); - if (zoom.click(btn)) DrawEditArea(); + switch(btn) { case BTN_NEW: @@ -448,6 +728,17 @@ void main() case BTN_RECT: setCurrentTool(TOOL_RECT); break; + case BTN_SELECT: + setCurrentTool(TOOL_SELECT); + break; + case BTN_ZOOM_IN: + zoom.inc(); + DrawEditArea(); + break; + case BTN_ZOOM_OUT: + zoom.dec(); + DrawEditArea(); + break; case CLOSE_BTN: ExitProcess(); break; @@ -456,6 +747,10 @@ void main() case evKey: GetKeys(); + + if (currentTool != TOOL_NONE) && (tools[currentTool].onKeyEvent != 0) + tools[currentTool].onKeyEvent(key_scancode); + if (key_scancode == SCAN_CODE_ESC) setCurrentTool(TOOL_PENCIL); if (key_scancode == SCAN_CODE_KEY_P) setCurrentTool(TOOL_PENCIL); if (key_scancode == SCAN_CODE_KEY_I) setCurrentTool(TOOL_PIPETTE); @@ -463,11 +758,12 @@ void main() if (key_scancode == SCAN_CODE_KEY_L) setCurrentTool(TOOL_LINE); if (key_scancode == SCAN_CODE_KEY_R) setCurrentTool(TOOL_RECT); - if (key_scancode == SCAN_CODE_KEY_S) actionsHistory.undoLastAction(); - if (key_scancode == SCAN_CODE_KEY_C) actionsHistory.redoLastAction(); + if (key_scancode == SCAN_CODE_KEY_Z) && (key_modifier&KEY_LCTRL) actionsHistory.undoLastAction(); + if (key_scancode == SCAN_CODE_KEY_Y) && (key_modifier&KEY_LCTRL) actionsHistory.redoLastAction(); + + if (key_scancode == SCAN_CODE_MINUS) {zoom.dec(); DrawEditArea();} + if (key_scancode == SCAN_CODE_PLUS) {zoom.inc(); DrawEditArea();} - if (key_scancode == SCAN_CODE_MINUS) {zoom.inc(); DrawEditArea();} - if (key_scancode == SCAN_CODE_PLUS) {zoom.dec(); DrawEditArea();} break; case evReDraw: @@ -545,6 +841,7 @@ void DrawLeftPanel() DrawLeftPanelButton(BTN_FILL, ty.inc(TB_ICON_PADDING), 40); DrawLeftPanelButton(BTN_LINE, ty.inc(TB_ICON_PADDING), 41); DrawLeftPanelButton(BTN_RECT, ty.inc(TB_ICON_PADDING), 42); + DrawLeftPanelButton(BTN_SELECT, ty.inc(TB_ICON_PADDING), 43); DrawRectangle3D(5, currentTool*TB_ICON_PADDING+TOOLBAR_H, 16+3+2, 16+3+2, 0x333333, 0x777777); } @@ -820,4 +1117,48 @@ void DrawRectangleInCanvas(int x1, int y1, int x2, int y2, dword color, int targ DrawLine(x2, y1, x2, y2, color, target); DrawLine(x2, y2, x1, y2, color, target); DrawLine(x1, y2, x1, y1, color, target); +} + +#define SELECTION_COLOR 0xAAE5EF + +void DrawSelection(int x1, int y1, int x2, int y2) { + int p1x, p1y, p2x, p2y, r, c, old_color, new_color; + dword offset; + + if (x1 <= x2) { + p1x = x1; + p2x = x2; + } + else { + p1x = x2; + p2x = x1; + } + + if (y1 <= y2) { + p2y = y1; + p1y = y2; + } + else { + p2y = y2; + p1y = y1; + } + + for (r = p1y; r >= p2y; r--) { + for (c = p1x; c <= p2x; c++) { + + if (selection_moving_started) && (SelectTool_pointInSelection(c, r)) { + offset = calc(SelectionTool_buffer_c * calc(r - selection_start_y) + calc(c - selection_start_x)) * 4; + old_color = ESDWORD[SelectionTool_buffer + offset]; + } + else { + old_color = image.get_pixel(r, c); + } + + new_color = MixColors(old_color, SELECTION_COLOR, 64); + + DrawBar(c*zoom.value + canvas.x, r*zoom.value + canvas.y, + zoom.value, zoom.value, new_color); + + } + } } \ No newline at end of file