Skip to content

Commit

Permalink
Merge pull request #165 from islocated/master
Browse files Browse the repository at this point in the history
Add support for canvas rotation with rectangles and grids
  • Loading branch information
serge-rgb committed May 17, 2020
2 parents ff723c6 + bcbf845 commit 64aa76b
Show file tree
Hide file tree
Showing 8 changed files with 197 additions and 34 deletions.
14 changes: 11 additions & 3 deletions src/bindings.cc
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,9 @@ set_default_bindings(MiltonBindings* bs)
binding(bs, Modifier_NONE, 'e', Action_MODE_ERASER);
binding(bs, Modifier_NONE, 'b', Action_MODE_PEN);
binding(bs, Modifier_NONE, 'i', Action_MODE_EYEDROPPER);
binding(bs, Modifier_NONE, 'l', Action_MODE_PRIMITIVE);
binding(bs, Modifier_NONE, 'l', Action_MODE_PRIMITIVE_LINE);
binding(bs, Modifier_NONE, 'r', Action_MODE_PRIMITIVE_RECTANGLE);
binding(bs, Modifier_NONE, 'g', Action_MODE_PRIMITIVE_GRID);
binding(bs, Modifier_NONE, Binding::F1, Action_HELP);
binding(bs, Modifier_NONE, Binding::TAB, Action_TOGGLE_GUI);

Expand Down Expand Up @@ -212,8 +214,14 @@ binding_dispatch_action(BindableAction a, MiltonInput* input, Milton* milton, v2
case Action_MODE_EYEDROPPER: {
input->mode_to_set = MiltonMode::EYEDROPPER;
} break;
case Action_MODE_PRIMITIVE: {
input->mode_to_set = MiltonMode::PRIMITIVE;
case Action_MODE_PRIMITIVE_LINE: {
input->mode_to_set = MiltonMode::PRIMITIVE_LINE;
} break;
case Action_MODE_PRIMITIVE_RECTANGLE: {
input->mode_to_set = MiltonMode::PRIMITIVE_RECTANGLE;
} break;
case Action_MODE_PRIMITIVE_GRID: {
input->mode_to_set = MiltonMode::PRIMITIVE_GRID;
} break;
case Action_SET_BRUSH_ALPHA_10: {
milton_set_brush_alpha(milton, 0.1f);
Expand Down
4 changes: 3 additions & 1 deletion src/bindings.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ enum BindableAction
Action_MODE_ERASER,
Action_MODE_PEN,
Action_MODE_EYEDROPPER,
Action_MODE_PRIMITIVE,
Action_MODE_PRIMITIVE_LINE,
Action_MODE_PRIMITIVE_RECTANGLE,
Action_MODE_PRIMITIVE_GRID,
Action_SET_BRUSH_ALPHA_10,
Action_SET_BRUSH_ALPHA_20,
Action_SET_BRUSH_ALPHA_30,
Expand Down
33 changes: 24 additions & 9 deletions src/gui.cc
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ gui_brush_window(MiltonInput* input, PlatformState* platform, Milton* milton, Pl
if ( show_brush_window ) {
if ( ImGui::Begin(loc(TXT_brushes), NULL, imgui_window_flags) ) {
if ( milton->current_mode == MiltonMode::PEN ||
milton->current_mode == MiltonMode::PRIMITIVE ) {
mode_is_for_primitives(milton->current_mode) ) {
const float pen_alpha = milton_get_brush_alpha(milton);
mlt_assert(pen_alpha >= 0.0f && pen_alpha <= 1.0f);
float mut_alpha = pen_alpha*100;
Expand Down Expand Up @@ -351,23 +351,38 @@ gui_brush_window(MiltonInput* input, PlatformState* platform, Milton* milton, Pl
milton->gui->flags |= (i32)MiltonGuiFlags_SHOWING_PREVIEW;
}

if ( milton->current_mode != MiltonMode::PEN ) {
if ( ImGui::Button(loc(TXT_switch_to_brush)) ) {
input->mode_to_set = MiltonMode::PEN;
}
if ( ImGui::Button(loc(TXT_switch_to_primitive_line)) ) {
input->mode_to_set = MiltonMode::PRIMITIVE_LINE;
}

if ( milton->current_mode != MiltonMode::PRIMITIVE ) {
if ( ImGui::Button(loc(TXT_switch_to_primitive)) ) {
input->mode_to_set = MiltonMode::PRIMITIVE;
}
ImGui::SameLine();

if ( ImGui::Button(loc(TXT_switch_to_primitive_rectangle)) ) {
input->mode_to_set = MiltonMode::PRIMITIVE_RECTANGLE;
}

ImGui::SameLine();

if ( ImGui::Button(loc(TXT_switch_to_primitive_grid)) ) {
input->mode_to_set = MiltonMode::PRIMITIVE_GRID;
}

if ( ImGui::Button(loc(TXT_switch_to_brush)) ) {
input->mode_to_set = MiltonMode::PEN;
}

ImGui::SameLine();

if ( milton->current_mode != MiltonMode::ERASER ) {
if ( ImGui::Button(loc(TXT_switch_to_eraser)) ) {
input->mode_to_set = MiltonMode::ERASER;
}
}

if (milton->current_mode == MiltonMode::PRIMITIVE_GRID ) {
ImGui::SliderInt(loc(TXT_grid_columns), &milton->grid_columns, 1, 32);
ImGui::SliderInt(loc(TXT_grid_rows), &milton->grid_rows, 1, 32);
}
}

{
Expand Down
14 changes: 11 additions & 3 deletions src/localization.cc
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ init_localization()
EN(TXT_brush_size, "Brush size");
EN(TXT_switch_to_brush, "Brush");
EN(TXT_switch_to_eraser, "Eraser");
EN(TXT_switch_to_primitive, "Lines");
EN(TXT_switch_to_primitive_line, "Lines");
EN(TXT_switch_to_primitive_rectangle, "Rectangle");
EN(TXT_switch_to_primitive_grid, "Grid");
EN(TXT_choose_background_color, "Choose background color");
EN(TXT_color, "Color");
EN(TXT_export_DOTS, "Export...");
Expand Down Expand Up @@ -113,6 +115,8 @@ init_localization()
EN(TXT_reset_view_at_origin, "Reset view at origin");
EN(TXT_reset_GUI, "Reset GUI layout (tool windows)");
EN(TXT_size_relative_to_canvas, "Size relative to canvas");
EN(TXT_grid_columns, "Grid Columns");
EN(TXT_grid_rows, "Grid Rows");

EN(TXT_Action_DECREASE_BRUSH_SIZE, "Decrease brush size");
EN(TXT_Action_INCREASE_BRUSH_SIZE, "Increase brush size");
Expand All @@ -131,7 +135,9 @@ init_localization()
EN(TXT_Action_MODE_ERASER, "Eraser");
EN(TXT_Action_MODE_PEN, "Pen");
EN(TXT_Action_MODE_EYEDROPPER, "Eyedropper");
EN(TXT_Action_MODE_PRIMITIVE, "Primitive");
EN(TXT_Action_MODE_PRIMITIVE_LINE, "Primitive Line");
EN(TXT_Action_MODE_PRIMITIVE_RECTANGLE, "Primitive Rectangle");
EN(TXT_Action_MODE_PRIMITIVE_GRID, "Primitive Grid");
EN(TXT_Action_SET_BRUSH_ALPHA_10, "Set alpha to 10%");
EN(TXT_Action_SET_BRUSH_ALPHA_20, "Set alpha to 20%");
EN(TXT_Action_SET_BRUSH_ALPHA_30, "Set alpha to 30%");
Expand Down Expand Up @@ -205,7 +211,9 @@ init_localization()
g_command_abbreviations [TXT_increase_brush_size] = " ] ";
g_command_abbreviations [TXT_eye_dropper] = "i";
g_command_abbreviations [TXT_switch_to_brush] = "B";
g_command_abbreviations [TXT_switch_to_primitive] = "L";
g_command_abbreviations [TXT_switch_to_primitive_line] = "L";
g_command_abbreviations [TXT_switch_to_primitive_rectangle] = "R";
g_command_abbreviations [TXT_switch_to_primitive_grid] = "G";
g_command_abbreviations [TXT_switch_to_eraser] = "E";
g_command_abbreviations [TXT_peek_out] = "`";
}
Expand Down
10 changes: 8 additions & 2 deletions src/localization.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@ enum Texts
// ==== Translation to spanish completed until this point

TXT_settings,
TXT_switch_to_primitive,
TXT_switch_to_primitive_line,
TXT_switch_to_primitive_rectangle,
TXT_switch_to_primitive_grid,
TXT_help_me,
TXT_new_layer,
TXT_rename,
Expand Down Expand Up @@ -96,6 +98,8 @@ enum Texts
TXT_reset_view_at_origin,
TXT_reset_GUI,
TXT_size_relative_to_canvas,
TXT_grid_columns,
TXT_grid_rows,

// Actions
TXT_Action_FIRST,
Expand All @@ -116,7 +120,9 @@ enum Texts
TXT_Action_MODE_ERASER,
TXT_Action_MODE_PEN,
TXT_Action_MODE_EYEDROPPER,
TXT_Action_MODE_PRIMITIVE,
TXT_Action_MODE_PRIMITIVE_LINE,
TXT_Action_MODE_PRIMITIVE_RECTANGLE,
TXT_Action_MODE_PRIMITIVE_GRID,
TXT_Action_SET_BRUSH_ALPHA_10,
TXT_Action_SET_BRUSH_ALPHA_20,
TXT_Action_SET_BRUSH_ALPHA_30,
Expand Down
144 changes: 130 additions & 14 deletions src/milton.cc
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,9 @@ milton_get_brush_enum(Milton const* milton)
case MiltonMode::ERASER: {
brush_enum = BrushEnum_ERASER;
} break;
case MiltonMode::PRIMITIVE: {
case MiltonMode::PRIMITIVE_LINE:
case MiltonMode::PRIMITIVE_RECTANGLE:
case MiltonMode::PRIMITIVE_GRID: {
brush_enum = BrushEnum_PRIMITIVE;
} break;
case MiltonMode::DRAG_BRUSH_SIZE: {
Expand Down Expand Up @@ -157,8 +159,8 @@ mode_is_for_drawing(MiltonMode mode)
{
b32 result = mode == MiltonMode::PEN ||
mode == MiltonMode::ERASER ||
mode == MiltonMode::PRIMITIVE ||
mode == MiltonMode::DRAG_BRUSH_SIZE;
mode == MiltonMode::DRAG_BRUSH_SIZE ||
mode_is_for_primitives(mode);
return result;
}

Expand Down Expand Up @@ -195,6 +197,14 @@ current_mode_is_for_drawing(Milton const* milton)
return mode_is_for_drawing(milton->current_mode);
}

b32
mode_is_for_primitives(MiltonMode mode)
{
return mode == MiltonMode::PRIMITIVE_LINE ||
mode == MiltonMode::PRIMITIVE_RECTANGLE ||
mode == MiltonMode::PRIMITIVE_GRID;
}

static void
clear_stroke_redo(Milton* milton)
{
Expand All @@ -213,7 +223,7 @@ clear_stroke_redo(Milton* milton)
}

static void
milton_primitive_input(Milton* milton, MiltonInput const* input, b32 end_stroke)
milton_primitive_line_input(Milton* milton, MiltonInput const* input, b32 end_stroke)
{
if ( end_stroke && milton->primitive_fsm == Primitive_DRAWING) {
milton->primitive_fsm = Primitive_WAITING;
Expand All @@ -235,6 +245,102 @@ milton_primitive_input(Milton* milton, MiltonInput const* input, b32 end_stroke)
}
}

static void
milton_primitive_rectangle_input(Milton* milton, MiltonInput const* input, b32 end_stroke)
{
if ( end_stroke && milton->primitive_fsm == Primitive_DRAWING) {
milton->primitive_fsm = Primitive_WAITING;
}
else if (input->input_count > 0) {
v2l point = raster_to_canvas(milton->view, input->points[input->input_count - 1]);

Stroke* ws = &milton->working_stroke;
if ( milton->primitive_fsm == Primitive_WAITING ) {
milton->primitive_fsm = Primitive_DRAWING;
for (int i = 0; i < 5; ++i) {
ws->points[i] = point;
ws->pressures[i] = 1.0f;
}
ws->num_points = 5;
ws->brush = milton_get_brush(milton);
ws->layer_id = milton->view->working_layer_id;
}
else if ( milton->primitive_fsm == Primitive_DRAWING ) {
v2l p0 = canvas_to_raster(milton->view, ws->points[0]);
v2l p2 = input->points[input->input_count - 1];

ws->points[1] = raster_to_canvas(milton->view, { p2.x, p0.y });
ws->points[2] = point;
ws->points[3] = raster_to_canvas(milton->view, { p0.x, p2.y });
ws->points[4] = ws->points[0];
}
}
}

static void
milton_primitive_grid_input(Milton* milton, MiltonInput const* input, b32 end_stroke)
{
int c = milton->grid_columns;
int r = milton->grid_rows;

if ( end_stroke && milton->primitive_fsm == Primitive_DRAWING) {
milton->primitive_fsm = Primitive_WAITING;
}
else if (input->input_count > 0) {
v2l point = raster_to_canvas(milton->view, input->points[input->input_count - 1]);
Stroke* ws = &milton->working_stroke;
if ( milton->primitive_fsm == Primitive_WAITING ) {
milton->primitive_fsm = Primitive_DRAWING;
ws->num_points = 4 + 2 * c + 2 * r;
for (int i = 0; i < ws->num_points; ++i) {
ws->points[i] = point;
ws->pressures[i] = 1.0f;
}
ws->brush = milton_get_brush(milton);
ws->layer_id = milton->view->working_layer_id;
}
else if ( milton->primitive_fsm == Primitive_DRAWING ) {
v2l p0 = canvas_to_raster(milton->view, ws->points[0]);
v2l p2 = input->points[input->input_count - 1];

ws->points[1] = raster_to_canvas(milton->view, { p2.x, p0.y });
ws->points[2] = point;
ws->points[3] = raster_to_canvas(milton->view, { p0.x, p2.y });
ws->points[4] = ws->points[0];

v2l current_point = p0;
int index = 5;
int h = p2.y - p0.y;
int w = p2.x - p0.x;
int y_sign = 1;

f32 cw = (f32) w / (f32)c;
f32 rh = (f32) h / (f32)r;

for (int i = 0; i < c; ++i) {
current_point.y = y_sign == 1 ? p2.y : p0.y;
y_sign *= -1;
ws->points[index++] = raster_to_canvas(milton->view, current_point);

current_point.x = p0.x + (cw * (i+1));
ws->points[index++] = raster_to_canvas(milton->view, current_point);
}

y_sign = c % 2 == 0 ? 1 : -1;
int x_sign = -1;

for (int i = 0; i < r; ++i) {
current_point.x = x_sign == 1 ? p2.x : p0.x;
x_sign *= -1;
ws->points[index++] = raster_to_canvas(milton->view, current_point);

current_point.y = y_sign == 1 ? p2.y - (rh * (i+1)) : p0.y + (rh * (i+1));
ws->points[index++] = raster_to_canvas(milton->view, current_point);
}
}
}
}

void
stroke_append_point(Stroke* stroke, v2l canvas_point, f32 pressure)
{
Expand Down Expand Up @@ -641,11 +747,14 @@ milton_init(Milton* milton, i32 width, i32 height, f32 ui_scale, PATH_CHAR* file
profiler_init();
#endif

#if MILTON_SAVE_ASYNC
milton->save_mutex = SDL_CreateMutex();
milton->save_cond = SDL_CreateCond();
milton->save_thread = SDL_CreateThread(milton_save_thread, "Save thread", (void*)milton);
#endif
#if MILTON_SAVE_ASYNC
milton->save_mutex = SDL_CreateMutex();
milton->save_cond = SDL_CreateCond();
milton->save_thread = SDL_CreateThread(milton_save_thread, "Save thread", (void*)milton);
#endif

milton->grid_rows = 4;
milton->grid_columns = 4;
}

void
Expand Down Expand Up @@ -1420,9 +1529,14 @@ milton_update_and_render(Milton* milton, MiltonInput const* input)
}
else if ( !milton->gui->owns_user_input
&& (milton->canvas->working_layer->flags & LayerFlags_VISIBLE) ) {
if ( milton->current_mode == MiltonMode::PRIMITIVE ) {
// Input for primitive.
milton_primitive_input(milton, input, end_stroke);
if ( milton->current_mode == MiltonMode::PRIMITIVE_LINE ) {
milton_primitive_line_input(milton, input, end_stroke);
}
else if ( milton->current_mode == MiltonMode::PRIMITIVE_RECTANGLE ) {
milton_primitive_rectangle_input(milton, input, end_stroke);
}
else if ( milton->current_mode == MiltonMode::PRIMITIVE_GRID ) {
milton_primitive_grid_input(milton, input, end_stroke);
}
else if ( milton->current_mode != MiltonMode::DRAG_BRUSH_SIZE ) { // Input for eraser and pen
Stroke* ws = &milton->working_stroke;
Expand Down Expand Up @@ -1489,7 +1603,7 @@ milton_update_and_render(Milton* milton, MiltonInput const* input)
if ( milton->working_stroke.num_points > 0 ) {
// We used the selected color to draw something. Push.
if ( (milton->current_mode == MiltonMode::PEN ||
milton->current_mode == MiltonMode::PRIMITIVE)
mode_is_for_primitives(milton->current_mode))
&& gui_mark_color_used(milton->gui) ) {
// Tell the renderer to update the picker
gpu_update_picker(milton->renderer, &milton->gui->picker);
Expand Down Expand Up @@ -1545,7 +1659,9 @@ milton_update_and_render(Milton* milton, MiltonInput const* input)
// Modes we can toggle
MiltonMode toggleable_modes[] = {
MiltonMode::EYEDROPPER,
MiltonMode::PRIMITIVE,
MiltonMode::PRIMITIVE_LINE,
MiltonMode::PRIMITIVE_RECTANGLE,
MiltonMode::PRIMITIVE_GRID,
};

for ( size_t i = 0; i < array_count(toggleable_modes); ++i ) {
Expand Down
Loading

0 comments on commit 64aa76b

Please sign in to comment.