diff options
Diffstat (limited to 'scripts/main.js')
-rw-r--r-- | scripts/main.js | 110 |
1 files changed, 93 insertions, 17 deletions
diff --git a/scripts/main.js b/scripts/main.js index 7a8b9d4..01301a1 100644 --- a/scripts/main.js +++ b/scripts/main.js | |||
@@ -1,3 +1,10 @@ | |||
1 | const DEFAULT_APP_STATE = { | ||
2 | floor: 1, | ||
3 | plan: new Array(GRID_SIZE_X * GRID_SIZE_Y).fill(0), | ||
4 | // mouse_state can be “normal”, or “dnd”. | ||
5 | mouse_state: "normal", | ||
6 | }; | ||
7 | |||
1 | function genGrid(x_count, y_count, cell_size) | 8 | function genGrid(x_count, y_count, cell_size) |
2 | { | 9 | { |
3 | let lines = []; | 10 | let lines = []; |
@@ -18,22 +25,25 @@ function genGrid(x_count, y_count, cell_size) | |||
18 | return h("g", {"stroke": "black", "stroke-width": 1}, lines); | 25 | return h("g", {"stroke": "black", "stroke-width": 1}, lines); |
19 | } | 26 | } |
20 | 27 | ||
21 | function AssetView({asset_index}) | 28 | function AssetView({asset_index, on_drag_begin, on_drag_end}) |
22 | { | 29 | { |
23 | return h("div", {"class": "Asset", "draggable": true, | 30 | return h("div", {"class": "Asset", "draggable": true, |
24 | "id": `Asset${asset_index}`}, | 31 | "data-asset-index": asset_index, |
32 | "ondragstart": on_drag_begin, | ||
33 | "ondragend": on_drag_end,}, | ||
25 | h("svg", ASSET_SVG_PROPS, ASSET_WHITE_BG, | 34 | h("svg", ASSET_SVG_PROPS, ASSET_WHITE_BG, |
26 | TILES[asset_index].inner_svg)); | 35 | TILES[asset_index].inner_svg)); |
27 | } | 36 | } |
28 | 37 | ||
29 | function AssetsView() | 38 | function AssetsView({on_drag_begin, on_drag_end}) |
30 | { | 39 | { |
31 | let views = TILES.slice(1).map((t, i) => | 40 | let views = TILES.slice(1).map((t, i) => |
32 | h(AssetView, {asset_index: i + 1})); | 41 | h(AssetView, {asset_index: i + 1, on_drag_begin: on_drag_begin, |
42 | on_drag_end: on_drag_end})); | ||
33 | return h("div", {}, views); | 43 | return h("div", {}, views); |
34 | } | 44 | } |
35 | 45 | ||
36 | function PlanGridView({content}) | 46 | function PlanGridView({content, mouse_state}) |
37 | { | 47 | { |
38 | const [mouse_coord, setMouseCoord] = preactHooks.useState(null); | 48 | const [mouse_coord, setMouseCoord] = preactHooks.useState(null); |
39 | 49 | ||
@@ -52,7 +62,14 @@ function PlanGridView({content}) | |||
52 | } | 62 | } |
53 | 63 | ||
54 | let hilight_box = null; | 64 | let hilight_box = null; |
55 | if(mouse_coord !== null) | 65 | console.debug(mouse_coord); |
66 | |||
67 | if(mouse_coord !== null && mouse_state != "dnd") | ||
68 | { | ||
69 | setMouseCoord(null); | ||
70 | } | ||
71 | |||
72 | if(mouse_coord !== null && mouse_state == "dnd") | ||
56 | { | 73 | { |
57 | let cell_x = Math.floor(mouse_coord[0] / (CELL_SIZE + 1)); | 74 | let cell_x = Math.floor(mouse_coord[0] / (CELL_SIZE + 1)); |
58 | let cell_y = Math.floor(mouse_coord[1] / (CELL_SIZE + 1)); | 75 | let cell_y = Math.floor(mouse_coord[1] / (CELL_SIZE + 1)); |
@@ -62,32 +79,91 @@ function PlanGridView({content}) | |||
62 | "stroke": "#2ed573", "stroke-width": 3, "fill": "transparent"}); | 79 | "stroke": "#2ed573", "stroke-width": 3, "fill": "transparent"}); |
63 | } | 80 | } |
64 | let grid_content = content.map((idx, i) => { | 81 | let grid_content = content.map((idx, i) => { |
82 | if(idx == 0) return null; | ||
65 | let cell_x = i % GRID_SIZE_X; | 83 | let cell_x = i % GRID_SIZE_X; |
66 | let cell_y = Math.floor(i / GRID_SIZE_Y); | 84 | let cell_y = Math.floor(i / GRID_SIZE_Y); |
67 | return h("g", {"transform": `translate(${cell_x * (CELL_SIZE + 1)} \ | 85 | return h("g", {"transform": `translate(${cell_x * (CELL_SIZE + 1) + 1} \ |
68 | ${cell_y * (CELL_SIZE + 1)})`}, TILES[idx]); | 86 | ${cell_y * (CELL_SIZE + 1) + 1})`}, ASSET_WHITE_BG, TILES[idx].inner_svg); |
69 | }); | 87 | }); |
70 | 88 | ||
71 | return h("svg", {"width": GRID_SIZE_X * (CELL_SIZE + 1) + 1, | 89 | let img_width = GRID_SIZE_X * (CELL_SIZE + 1) + 1; |
72 | "height": GRID_SIZE_Y * (CELL_SIZE + 1) + 1, | 90 | let img_height = GRID_SIZE_Y * (CELL_SIZE + 1) + 1; |
91 | return h("svg", {"width": img_width, "height": img_height, | ||
73 | "version": "1.1", "ondragover": onDragOver, | 92 | "version": "1.1", "ondragover": onDragOver, |
74 | "id": "Grid", "ondragleave": onDragLeave}, | 93 | "id": "Grid", "ondragleave": onDragLeave,}, |
94 | h("rect", {x: 0, y: 0, width: img_width, height: img_height, | ||
95 | fill: "#a4b0be", "stroke-width": 0}), | ||
75 | grid_content, genGrid(GRID_SIZE_X, GRID_SIZE_Y, CELL_SIZE + 1), | 96 | grid_content, genGrid(GRID_SIZE_X, GRID_SIZE_Y, CELL_SIZE + 1), |
76 | hilight_box); | 97 | hilight_box); |
77 | } | 98 | } |
78 | 99 | ||
79 | function PlanView(props) | 100 | function PlanView({plan, mouse_state}) |
80 | { | 101 | { |
81 | return h("div", {}, | 102 | return h("div", {}, |
82 | h("p", {}, "The plan:"), | 103 | h("p", {}, "The plan:"), |
83 | h(PlanGridView, {})); | 104 | h(PlanGridView, {content: plan, mouse_state: mouse_state})); |
84 | } | 105 | } |
85 | 106 | ||
86 | function App(props) | 107 | function App({initial_state}) |
87 | { | 108 | { |
109 | const [state, setState] = preactHooks.useState(initial_state); | ||
110 | |||
111 | function onDragAssetBegin(e) | ||
112 | { | ||
113 | let new_state = structuredClone(state); | ||
114 | new_state.mouse_state = "dnd"; | ||
115 | setState(new_state); | ||
116 | } | ||
117 | function onDragAssetEnd(e) | ||
118 | { | ||
119 | if(e.dragEffect === "none") return; | ||
120 | let grid = document.getElementById("Grid"); | ||
121 | let b = grid.getBoundingClientRect(); | ||
122 | let x = e.clientX - b.left; | ||
123 | let y = e.clientY - b.top; | ||
124 | if(x < 0 || y < 0 || x > b.width || y > b.height) return; | ||
125 | let cell_x = Math.floor(x / (CELL_SIZE + 1)); | ||
126 | let cell_y = Math.floor(y / (CELL_SIZE + 1)); | ||
127 | let cell_index = cell_y * GRID_SIZE_X + cell_x; | ||
128 | let asset_index = parseInt(e.target.getAttribute("data-asset-index")); | ||
129 | |||
130 | let new_state = structuredClone(state); | ||
131 | new_state.plan[cell_index] = asset_index; | ||
132 | new_state.mouse_state = "normal"; | ||
133 | setState(new_state); | ||
134 | } | ||
135 | |||
136 | function onClickSaveImg() | ||
137 | { | ||
138 | let grid_width = GRID_SIZE_X * (CELL_SIZE + 1) + 1; | ||
139 | let grid_height = GRID_SIZE_Y * (CELL_SIZE + 1) + 1; | ||
140 | let canvas = document.createElement('canvas'); | ||
141 | canvas.width = grid_width; | ||
142 | canvas.height = grid_height; | ||
143 | let context = canvas.getContext("2d"); | ||
144 | var svg_str = new XMLSerializer().serializeToString( | ||
145 | document.getElementById("Grid")); | ||
146 | var img = new Image(); | ||
147 | img.onload = function() | ||
148 | { | ||
149 | context.drawImage(this, 0, 0); | ||
150 | // Open PNG image in new tab. | ||
151 | var dataURL = canvas.toDataURL("image/png"); | ||
152 | var new_tab = window.open('about:blank', 'image from canvas'); | ||
153 | new_tab.document.write("<img src='" + dataURL + "' alt='from canvas'/>"); | ||
154 | } | ||
155 | img.src = 'data:image/svg+xml; charset=utf8, ' + | ||
156 | encodeURIComponent(svg_str); | ||
157 | } | ||
158 | |||
88 | return h("div", {}, | 159 | return h("div", {}, |
89 | h(AssetsView, {}), | 160 | h(AssetsView, {on_drag_begin: onDragAssetBegin, |
90 | h(PlanView, {})); | 161 | on_drag_end: onDragAssetEnd}), |
162 | h(PlanView, {plan: state.plan, mouse_state: state.mouse_state}), | ||
163 | h("div", {}, | ||
164 | h("a", {"href": "javascript:void(0);", onclick: onClickSaveImg}, | ||
165 | "Open Image!"))); | ||
91 | } | 166 | } |
92 | 167 | ||
93 | preact.render(h(App, {}), document.getElementById("Plan")); | 168 | preact.render(h(App, {initial_state: DEFAULT_APP_STATE}), |
169 | document.getElementById("Plan")); | ||