summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpommicket <pommicket@gmail.com>2023-06-18 15:06:07 +0100
committerpommicket <pommicket@gmail.com>2023-06-18 15:06:07 +0100
commit750df23e7e2a73b4351239c263e83c094433fa5c (patch)
tree7e17808a1ebb263963defaebb5649b9d26937ac6
parent2986d5e91ce376f633b41da61f29ad1f10db62d9 (diff)
start parallelogram
-rw-r--r--fractiform.js105
-rw-r--r--index.html5
-rw-r--r--parallelogram.pngbin0 -> 1316 bytes
-rw-r--r--triangle.pngbin0 -> 1527 bytes
4 files changed, 72 insertions, 38 deletions
diff --git a/fractiform.js b/fractiform.js
index 6c1f92d..2b3a8cc 100644
--- a/fractiform.js
+++ b/fractiform.js
@@ -37,10 +37,11 @@ let ui_div;
let vertex_id = 0;
let shift_key = false;
let ctrl_key = false;
+let ui_specify_uv = false;
const TOOL_TRIANGLE = 1;
-const TOOL_UV = 2;
const TOOL_SELECT = 3;
+const TOOL_PARALLELOGRAM = 4;
let ui_tool;
@@ -104,6 +105,7 @@ function ui_escape_tool() {
ui_vertices = [];
ui_shape = [];
ui_tool = TOOL_SELECT;
+ ui_specify_uv = false;
}
function ui_set_tool(tool) {
@@ -149,6 +151,9 @@ function on_key_press(e) {
case 50: // 2
ui_set_tool(TOOL_TRIANGLE);
break;
+ case 51: // 3
+ ui_set_tool(TOOL_PARALLELOGRAM);
+ break;
}
}
@@ -273,10 +278,24 @@ function ui_commit_vertices() {
}
indices.push(i);
});
- if (indices.length === 3) {
+ switch (ui_tool) {
+ case TOOL_TRIANGLE:
indices_main.push(indices[0], indices[1], indices[2]);
- } else {
- console.error('bad shape length');
+ break;
+ case TOOL_PARALLELOGRAM: {
+ indices.push(vertices_main.length);
+ let v0 = vertices_main[indices[0]];
+ let v1 = vertices_main[indices[1]];
+ let v2 = vertices_main[indices[2]];
+ let v3 = Object.assign({}, v1);
+ v3.x = v0.x + v2.x - v1.x;
+ v3.y = v0.x + v2.y - v1.y;
+ v3.uv.x = v0.uv.x + v2.uv.x - v1.uv.x;
+ v3.uv.y = v0.uv.x + v2.uv.y - v1.uv.y;
+ vertices_main.push(v3);
+ indices_main.push(indices[0], indices[1], indices[2],
+ indices[0], indices[2], indices[3]);
+ } break;
}
vertices_changed = true;
@@ -305,8 +324,17 @@ function on_click(e) {
ui_shape.push(vertex);
switch (ui_tool) {
case TOOL_TRIANGLE:
- if (ui_shape.length === 3) {
- ui_tool = TOOL_UV;
+ case TOOL_PARALLELOGRAM:
+ if (ui_specify_uv && ui_shape.length == ui_vertices.length) {
+ let uv = ui_shape;
+ let vertices = ui_vertices;
+ for (let i = 0; i < vertices.length; i++) {
+ vertices[i].uv = {x: uv[i].x * 0.5 + 0.5, y: uv[i].y * 0.5 + 0.5};
+ }
+ ui_commit_vertices();
+ ui_set_tool(TOOL_SELECT);
+ } else if (ui_shape.length === 3) {
+ ui_specify_uv = true;
ui_vertices = ui_shape;
ui_shape = [];
let all_full_alpha = true;
@@ -323,17 +351,6 @@ function on_click(e) {
}
}
break;
- case TOOL_UV:
- if (ui_shape.length === ui_vertices.length) {
- let uv = ui_shape;
- let vertices = ui_vertices;
- for (let i = 0; i < vertices.length; i++) {
- vertices[i].uv = {x: uv[i].x * 0.5 + 0.5, y: uv[i].y * 0.5 + 0.5};
- }
- ui_commit_vertices();
- ui_set_tool(TOOL_SELECT);
- }
- break;
}
}
}
@@ -410,11 +427,11 @@ function startup() {
}
function ui_is_editing_shape() {
- return ui_tool === TOOL_TRIANGLE || ui_tool === TOOL_UV;
+ return ui_tool === TOOL_TRIANGLE || ui_tool === TOOL_PARALLELOGRAM;
}
function ui_is_editing_vertex() {
- return ui_tool === TOOL_TRIANGLE;
+ return ui_tool === TOOL_TRIANGLE || ui_tool === TOOL_PARALLELOGRAM;
}
function draw_vertex(vertex) {
@@ -493,21 +510,21 @@ function frame(time) {
ui_ctx.clearRect(0, 0, width, height);
if (ui_shown) {
- for (let i = 0; i < vertices_main.length; i++) {
- let vertex = vertices_main[i];
- draw_vertex(vertex);
- if (i % 3 === 0) {
- console.assert(i + 2 < vertices_main.length, 'vertices_main.length not a multiple of 3');
- const line_options = {
- strokeStyle: '#ffffff'
- };
- ui_line(vertex, vertices_main[i+1], line_options);
- ui_line(vertex, vertices_main[i+2], line_options);
- ui_line(vertices_main[i+1], vertices_main[i+2], line_options);
- }
+ vertices_main.forEach(draw_vertex);
+
+ for (let i = 0; i < indices_main.length / 3; i++) {
+ const line_options = {
+ strokeStyle: '#ffffff'
+ };
+ let v0 = vertices_main[indices_main[3*i]];
+ let v1 = vertices_main[indices_main[3*i+1]];
+ let v2 = vertices_main[indices_main[3*i+2]];
+ ui_line(v0, v1, line_options);
+ ui_line(v0, v2, line_options);
+ ui_line(v1, v2, line_options);
}
- if (ui_tool === TOOL_UV) {
+ if (ui_specify_uv) {
ui_polygon(ui_vertices, {
strokeStyle: '#ffffff',
fillStyle: '#ffffff44',
@@ -517,7 +534,7 @@ function frame(time) {
if (ui_is_editing_shape()) {
let color;
- if (ui_tool == TOOL_UV) {
+ if (ui_specify_uv) {
color = '#3333ff';
} else {
color = '#ffffff';
@@ -533,14 +550,28 @@ function frame(time) {
// vertex where the mouse is
ui_circle(mpos, vertex_radius, {
strokeStyle: options_shape.strokeStyle,
- fillStyle: ui_tool === TOOL_UV ? color + '44' : ui_get_color_rgba(),
+ fillStyle: ui_specify_uv ? color + '44' : ui_get_color_rgba(),
});
if (ui_shape.length === 1) {
ui_line(ui_shape[0], mpos, options_shape);
} else if (ui_shape.length === 2) {
- // triangle preview
- ui_polygon([ui_shape[0], ui_shape[1], mpos], options_shape);
+ if (ui_tool === TOOL_TRIANGLE) {
+ // triangle preview
+ ui_polygon([ui_shape[0], ui_shape[1], mpos], options_shape);
+ } else if (ui_tool === TOOL_PARALLELOGRAM) {
+ // parallelogram preview
+ let v0 = ui_shape[0];
+ let v1 = ui_shape[1];
+ let v2 = mpos;
+ let v3 = {
+ x: v0.x + v2.x - v1.x,
+ y: v0.y + v2.y - v1.y,
+ };
+ ui_polygon([v0, v1, v2, v3], options_shape);
+ } else {
+ console.assert(false, 'bad tool');
+ }
}
}
@@ -554,7 +585,7 @@ function frame(time) {
ui_circle(vertex, vertex_radius, {
strokeStyle: options_shape.strokeStyle,
- fillStyle: ui_tool === TOOL_UV ? color + '44' : rgba_float_to_hex(vertex.color),
+ fillStyle: ui_specify_uv ? color + '44' : rgba_float_to_hex(vertex.color),
});
}
diff --git a/index.html b/index.html
index 262f894..d184202 100644
--- a/index.html
+++ b/index.html
@@ -200,7 +200,10 @@ void main() {
<img alt="select" class="icon" src="data:image/png;base64,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">
</button>
<button class="tool-button" data-tool="1" title="triangle tool (2)">
- <img alt="triangle" class="icon" src="data:image/png;base64,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">
+ <img alt="triangle" class="icon" src="data:image/png;base64,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">
+ </button>
+ <button class="tool-button" data-tool="4" title="parallelogram tool (3)">
+ <img alt="parallelogram" class="icon" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFAAAABQCAQAAAAkGDomAAAE60lEQVRo3u2ay28bVRSHv7Gd5kHTlqZB1EUKooi3UCsERChqQEgsWNAqLFiyy97wB0RZ0GXCthVrpC5aVIkFIJBaNQIlKapYNIJFKopIQKR5Omrc2p4fi0zmYc/YM54Zu5VyZpe5c+bLnXt+95x7DPv2WJpGNaU5bWrXNjWnKY1GdeJ7JQA3osvyt8saiQWXBKTGtaRgW9J4bLw4iBrXPTW2e00RFepKCa85okJfLay92o97TQW9qYKu1X3okdh40RFrQuOGxlz3xnTDGy6NAX1FIB6gRj0AF5SvuZ/XBc+I0SC8hiLQOqKmPLOX9xmR98zilD9gUxFoGXDO5WcsYMyYa8xcyyLQIuCmExoNRjnhshlDBMIDKqse9WtQx10eCg3GF5xhu3/JOSLABAOe0de5ygwjnMW9YAeYYIGZICC66KKHHDl6OcIxhniOEx7PPzf4j+r82oAUyHsGThtXAJhnWmMUcJQpT8FxpCw99JEjSy8HeZohTnKCAY4yQD8HyJEjg+Hy/S6zgYB1+mfsiQDulXGRSWPZG2FM4Nb3c8xZczTEq5xkkCc5Qj+9HLCAvFBu+8V4J3gN2l9ryzjcQATUTAT+0Pea1x2tqKiSyqqoKlNhLXoUe0XAPwD0sWuMqUpoIFNVVVSNpYNuEQiKUWV0MwJQWSUVtaq/9btm9Z1+aG0n2QuSQ/bIq27h9iyjLHO8EbBDmgiTCg/ZocgG66ywyG3+YosyJapU+IqP7CfGeUV7YQjUhCFcMa57g8SZrreY94kiQBnO4WziJiZVypQossoaqyyxyF3+ZZsdqlS4T8mourMZLpEPIWSwzCfGTK3MOIE+750cF9ILrhs/8h+L3OYuG+xQoUKJMmU3Uo1gzGiS8x5FHMUvJVhl0phpsBE1SLCcjaio4xrUE8q2KaP2i+K6q9lWnmZNUq+DdVfzZCjNqq4+nazDa55ORq+Li7a/ki7p/YgJuefjhkvIo2K+pn8sj6t6T5n0S5qogKe0Zvnc0HB7isKogOuW13WdbldZ3SrgqfYdTIQHPB0ZMKGjnbDvGtaG5XstNKAtAjdVsh5+qN80HVdYfOuVD7VlvWNFr0d9/Fn9qqokU3d0Rl0pnBF261NtW4DLetl/VLD2HCRPBjA4TJZqCqeYGQ7Z7y8HlYjBgDm67TxwxzBTADTo8hxqRAR0UkHxIKWTYCPMNIc7cO2YZeL8d7Hnr9d6izCjA3a7PnE6luWY/f5SUBhmAo8wjtr3qpipAHbzlPUOUaQUbQZzDLokoJzSDPbbX2k7aBJycTSq9XSVs4zwEv32ahzibb6J4qJPn+m+pfJ/6sUE4ZLZ69Wnz9MATCxbSgewlXwzE0ejouLVlO1+NsD5cM2wQ/pSD6yjoAU9n8jaS7Lm0aC+VlmSVNWsnkkAMIk2jitdvWXh7TZyLiZQB8dv46SZ8CfSxkmzZGpjG6dFwHa2cSKVRTHbOPZe7NvG+ZZbDPMBZzw6NaEFo21tHCdZCGrj/MQXnWzjWHnzY9fGaSoCnW3jBDz+qLRxAqe/I22cvSDxbePUJegdaOPsBYmrjWPMB81gJ9o49TVJTRvHFe6mHo02TqiNqLNtnBa38jRrkoSSofSqusTSySgnuNF+3phgQp6OdaKNk3zNmnifhDaJQFsR29jG6eTRTsqQSfzGed/2bd/aZf8DSKJozbS2TtQAAAAASUVORK5CYII=">
</button>
</div>
</div>
diff --git a/parallelogram.png b/parallelogram.png
new file mode 100644
index 0000000..f067c7f
--- /dev/null
+++ b/parallelogram.png
Binary files differ
diff --git a/triangle.png b/triangle.png
new file mode 100644
index 0000000..9725c99
--- /dev/null
+++ b/triangle.png
Binary files differ