diff options
author | pommicket <pommicket@gmail.com> | 2023-06-16 22:45:49 +0100 |
---|---|---|
committer | pommicket <pommicket@gmail.com> | 2023-06-16 22:45:49 +0100 |
commit | 44ff1b24757c79baf375536ba58816d1c8e66ca6 (patch) | |
tree | 6f04b4e938ce7168ebfb1c95ba34c0aff9df2ed7 | |
parent | 62f8c586e9bda227657b4e0330adbe5437e2c180 (diff) |
tools
-rw-r--r-- | fractiform.js | 139 | ||||
-rw-r--r-- | index.html | 26 |
2 files changed, 90 insertions, 75 deletions
diff --git a/fractiform.js b/fractiform.js index b8ea3f4..5d4f886 100644 --- a/fractiform.js +++ b/fractiform.js @@ -27,16 +27,16 @@ let ui_shown = true; let mouse_x, mouse_y; let viewport_width, viewport_height, viewport_scale; let ui_shape = []; -let ui_make_parallelogram = false; let ui_vertex_positions = []; let ui_color_input; let ui_color_mix_input; let ui_div; -const TOOL_VERTEX = 1; +const TOOL_TRIANGLE = 1; const TOOL_UV = 2; +const TOOL_SELECT = 3; -let ui_tool = TOOL_VERTEX; +let ui_tool = TOOL_TRIANGLE; const vertex_radius = 10; @@ -55,7 +55,8 @@ function ui_get_color() { } function ui_get_color_mix() { - return ui_color_mix_input.value; + let v = parseFloat(ui_color_mix_input.value); + return !isNaN(v) && v >= 0.0 && v <= 1.0 ? v : 0.0; } function ui_get_color_rgba() { @@ -75,17 +76,44 @@ function hex_to_rgba(hex) { }; } +function ui_escape_tool() { + ui_vertex_positions = []; + ui_shape = []; + ui_tool = TOOL_SELECT; +} + +function ui_set_tool(tool) { + if (ui_tool === tool) { + return; + } + ui_escape_tool(); + ui_tool = tool; +} + function on_key_press(e) { let code = e.keyCode; - console.log('key press:', code); + if (e.target.tagName === 'INPUT') { + return; + } + switch (code) { case 32: // space - perform_step(); + if (canvas_is_target) + perform_step(); break; case 9: // tab set_ui_shown(!ui_shown); e.preventDefault(); break; + case 27: // escape + ui_escape_tool(); + break; + case 49: // 1 + ui_set_tool(TOOL_SELECT); + break; + case 50: // 2 + ui_set_tool(TOOL_TRIANGLE); + break; } } @@ -155,7 +183,7 @@ function convert_viewport_pos_to_ndc(pos) { function convert_viewport_pos_to_uv(pos) { return { x: pos.x / width, - y: pos.y / height, + y: 1.0 - pos.y / height, }; } @@ -169,32 +197,22 @@ function on_click(e) { } if (ui_is_editing_shape()) { - if (ui_shape.length < 3) { - let vertex = { - x: mouse_x, - y: mouse_y, - }; - Object.preventExtensions(vertex); - ui_shape.push(vertex); - } else { - if (ui_make_parallelogram) { - const v0 = ui_shape[0]; - const v1 = ui_shape[1]; - const v2 = ui_shape[2]; - let v3 = { - x: v2.x - v1.x + v0.x, - y: v2.y - v1.y + v0.y, - }; - ui_shape.push(v3); - } - - switch (ui_tool) { - case TOOL_VERTEX: + let vertex = { + x: mouse_x, + y: mouse_y, + }; + Object.preventExtensions(vertex); + ui_shape.push(vertex); + switch (ui_tool) { + case TOOL_TRIANGLE: + if (ui_shape.length === 3) { ui_tool = TOOL_UV; ui_vertex_positions = ui_shape; ui_shape = []; - break; - case TOOL_UV: { + } + break; + case TOOL_UV: + if (ui_shape.length === ui_vertex_positions.length) { let pos = ui_vertex_positions; let uv = ui_shape; let vertices = []; @@ -215,11 +233,11 @@ function on_click(e) { } else { console.error('bad shape length'); } - ui_tool = TOOL_VERTEX; + ui_tool = TOOL_TRIANGLE; ui_shape = []; ui_vertex_positions = []; - } break; } + break; } } } @@ -307,7 +325,7 @@ function startup() { } function ui_is_editing_shape() { - return ui_tool == TOOL_VERTEX || ui_tool == TOOL_UV; + return ui_tool == TOOL_TRIANGLE || ui_tool == TOOL_UV; } function frame(time) { @@ -381,24 +399,30 @@ function frame(time) { if (ui_shown) { if (ui_tool === TOOL_UV) { ui_polygon(ui_vertex_positions, { - strokeStyle: ui_get_color(), - fillStyle: ui_get_color() + '44', + strokeStyle: '#ffffff', + fillStyle: '#ffffff44', }); } if (ui_is_editing_shape()) { - let color = ui_get_color_rgba(); + let options_vertex, options_shape; if (ui_tool == TOOL_UV) { - color = '#3333ff44'; + let color = '#3333ff'; + options_vertex = { + strokeStyle: color, + fillStyle: color + '44' + }; + options_shape = options_vertex; + } else { + options_vertex = { + strokeStyle: '#ffffff', + fillStyle: ui_get_color() + '44', + }; + options_shape = { + strokeStyle: '#ffffff', + fillStyle: '#ffffff44', + }; } - let options_vertex = { - strokeStyle: color.substr(0, 7), - fillStyle: color, - }; - let options_shape = { - strokeStyle: color.substr(0, 7), - fillStyle: color.substr(0, 7) + '44', - }; if (ui_shape.length < 3 && is_mouse_in_canvas()) { // vertex where the mouse is @@ -413,31 +437,6 @@ function frame(time) { } } - if (ui_shape.length >= 3) { - let v0 = ui_shape[0]; - let v1 = ui_shape[1]; - let v2 = ui_shape[2]; - let vm = {x: mouse_x, y: mouse_y}; - let vm0 = {x: vm.x - v0.x, y: vm.y - v0.y}; - let v10 = {x: v1.x - v0.x, y: v1.y - v0.y}; - let v20 = {x: v2.x - v0.x, y: v2.y - v0.y}; - ui_make_parallelogram = Math.sign(vm0.x * v20.y - vm0.y * v20.x) !== - Math.sign(v10.x * v20.y - v10.y * v20.x); - - if (ui_vertex_positions.length > 0) { - ui_make_parallelogram = ui_vertex_positions.length === 4; - } - - if (ui_make_parallelogram) { - // parallelogram - let v3 = {x: v2.x - v1.x + v0.x, y: v2.y - v1.y + v0.y}; - ui_polygon([v0, v1, v2, v3], options_shape); - ui_circle(v3.x, v3.y, vertex_radius, options_vertex); - } else { - // triangle - ui_polygon([v0, v1, v2], options_shape); - } - } for (let i in ui_shape) { let vertex = ui_shape[i]; @@ -13,6 +13,7 @@ overflow: hidden; } + :root { --ui-border: white; --ui-height: 2.5em; @@ -77,10 +78,18 @@ vertical-align: middle; display: inline-block; height: 2.0em; - margin: 0.5em 0.2em 0.5em 0.5em; - padding: 0; + margin: 0.3em 0.1em 0.3em 0.3em; border: 2px solid var(--ui-border); background-color: #333; + color: white; + } + #ui input[type=color] { + padding: 0; + } + #ui input[type=text] { + width: 3em; + font-size: inherit; + height: 1.5em; } #ui label { margin-right: 0.5em; @@ -152,9 +161,16 @@ void main() { <canvas id="ui-canvas"></canvas> </div> <div id="ui"> - <input type="color" value="#ffffff" name="color-input" id="color-input"> - <label for="color-input">color</label> - <input type="range" value="0.1" min="0" max="1" step="any" name="color-mix-input" id="color-mix-input"> + <!-- + <input type="text" value="1.0" name="red-input" id="red-input"> + <label for="red-input">R</label> + <input type="text" value="1.0" name="green-input" id="green-input"> + <label for="green-input">G</label> + <input type="text" value="1.0" name="blue-input" id="blue-input"> + <label for="blue-input">B</label> + --> + <input type="color" value="#ffffff" name="color-input" id="color-input" aria-label="Color"> + <input type="text" value="0.1" name="color-mix-input" id="color-mix-input"> <label for="color-mix-input">opacity</label> </div> |