Implement Live State Editing
This commit is contained in:
@ -18,6 +18,7 @@
|
||||
<button disabled id="model_name"></button>
|
||||
<button id="select_state_button">Select State</button>
|
||||
<button disabled id="state_name"></button>
|
||||
<button id="edit_state_button">Edit State</button>
|
||||
<button id="up_button">UP</button>
|
||||
<button id="down_button">DOWN</button>
|
||||
<button id="left_button">LEFT</button>
|
||||
|
120
src/main.js
120
src/main.js
@ -101,6 +101,34 @@ const clear_visualization = () => {
|
||||
canvas.height = vh - 43;
|
||||
|
||||
context.clearRect(0, 0, canvas.width, canvas.height);
|
||||
|
||||
draw_grid();
|
||||
};
|
||||
|
||||
const draw_grid = () => {
|
||||
const canvas = document.getElementById("model_canvas");
|
||||
const context = canvas.getContext("2d");
|
||||
|
||||
const [vw, vh] = get_viewport_dims();
|
||||
canvas.width = vw / 2 - 9.5;
|
||||
canvas.height = vh - 43;
|
||||
|
||||
const square_width = canvas.width / current_state.width;
|
||||
const square_height = canvas.height / current_state.height;
|
||||
|
||||
// Horizontal lines
|
||||
for (let y = 1; y < current_state.height; y += 1) {
|
||||
context.moveTo(0, y * square_height);
|
||||
context.lineTo(canvas.width, y * square_height);
|
||||
context.stroke();
|
||||
}
|
||||
|
||||
// Vertical lines
|
||||
for (let x = 1; x < current_state.width; x += 1) {
|
||||
context.moveTo(x * square_width, 0);
|
||||
context.lineTo(x * square_width, canvas.height);
|
||||
context.stroke();
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
@ -138,6 +166,76 @@ const node_click_view_state = (node, graph) => {
|
||||
// Set up model event-handlers
|
||||
//
|
||||
|
||||
let editing = false;
|
||||
let startpos = null;
|
||||
|
||||
document
|
||||
.getElementById("model_canvas")
|
||||
.addEventListener("mousedown", (event) => {
|
||||
if (model.select(current_state, event.offsetX, event.offsetY) === null) {
|
||||
startpos = [event.offsetX, event.offsetY];
|
||||
}
|
||||
});
|
||||
|
||||
document.getElementById("model_canvas").addEventListener("mouseup", (event) => {
|
||||
if (startpos === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
let endpos = [event.offsetX, event.offsetY];
|
||||
|
||||
const canvas = document.getElementById("model_canvas");
|
||||
|
||||
const square_width = canvas.width / current_state.width;
|
||||
const square_height = canvas.height / current_state.height;
|
||||
|
||||
// Coordinates
|
||||
const startx = Math.floor(startpos[0] / square_width);
|
||||
const starty = Math.floor(startpos[1] / square_height);
|
||||
const endx = Math.floor(endpos[0] / square_width);
|
||||
const endy = Math.floor(endpos[1] / square_height);
|
||||
|
||||
// Check that the block to be added doesn't collide with anything
|
||||
for (let ix = startx; ix <= endx; ix++) {
|
||||
for (let iy = starty; iy <= endy; iy++) {
|
||||
if (
|
||||
model.select(current_state, ix * square_width, iy * square_height) !==
|
||||
null
|
||||
) {
|
||||
startpos = null;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add block
|
||||
let new_block = model.add_block(
|
||||
current_state,
|
||||
Math.min(startx, endx),
|
||||
Math.min(starty, endy),
|
||||
Math.max(startx, endx),
|
||||
Math.max(starty, endy),
|
||||
);
|
||||
|
||||
if (new_block === null) {
|
||||
startpos = null;
|
||||
return;
|
||||
}
|
||||
|
||||
// Clear graph + visualize
|
||||
selected_element = new_block;
|
||||
clear_visualization();
|
||||
model.visualize(current_state);
|
||||
model.highlight(current_state, selected_element);
|
||||
|
||||
// Generate graph for new state
|
||||
clear_graph();
|
||||
model.generate(states, initial_state, graph, null);
|
||||
reset_graph_view(graph);
|
||||
|
||||
startpos = null;
|
||||
});
|
||||
|
||||
document.getElementById("model_canvas").addEventListener("click", (event) => {
|
||||
const element = model.select(current_state, event.offsetX, event.offsetY);
|
||||
|
||||
@ -218,6 +316,7 @@ document.getElementById("select_model_button").addEventListener("click", () => {
|
||||
clear_graph();
|
||||
clear_visualization();
|
||||
model.visualize(initial_state);
|
||||
editing = false;
|
||||
document.getElementById("model_name").innerHTML = model.name;
|
||||
document.getElementById("state_name").innerHTML = initial_state.name;
|
||||
});
|
||||
@ -232,12 +331,29 @@ document.getElementById("select_state_button").addEventListener("click", () => {
|
||||
states.add(initial_state);
|
||||
clear_graph();
|
||||
clear_visualization();
|
||||
// graph = null;
|
||||
// graph = generate_graph(data, node_click_view_state);
|
||||
model.visualize(initial_state);
|
||||
editing = false;
|
||||
document.getElementById("state_name").innerHTML = initial_state.name;
|
||||
});
|
||||
|
||||
document.getElementById("edit_state_button").addEventListener("click", () => {
|
||||
if (editing === false) {
|
||||
current_initial_state = 0;
|
||||
initial_state = model.empty_state;
|
||||
current_state = initial_state;
|
||||
selected_element = null;
|
||||
clear_states();
|
||||
states.add(initial_state);
|
||||
clear_graph();
|
||||
clear_visualization();
|
||||
model.visualize(initial_state);
|
||||
editing = true;
|
||||
document.getElementById("state_name").innerHTML = initial_state.name;
|
||||
} else {
|
||||
editing = false;
|
||||
}
|
||||
});
|
||||
|
||||
document
|
||||
.getElementById("generate_graph_button")
|
||||
.addEventListener("click", () => {
|
||||
|
@ -183,6 +183,22 @@ const visualize_path = (from_state, to_state) => {
|
||||
// For each state in path: visualize(state)
|
||||
};
|
||||
|
||||
const add_block = (state, x0, y0, x1, y1) => {
|
||||
let dir;
|
||||
if (x1 - x0 > y1 - y0) {
|
||||
dir = HORIZONTAL;
|
||||
} else if (x1 - x0 < y1 - y0) {
|
||||
dir = VERTICAL;
|
||||
} else {
|
||||
// No square blocks for this model
|
||||
return null;
|
||||
}
|
||||
|
||||
let new_block = [state.board.length, dir, x0, y0, x1, y1];
|
||||
state.board.push(new_block);
|
||||
return new_block;
|
||||
};
|
||||
|
||||
export const restricted_sliding_blocks_model = {
|
||||
name: "Restricted Sliding Blocks",
|
||||
generate,
|
||||
@ -192,4 +208,11 @@ export const restricted_sliding_blocks_model = {
|
||||
initial_states,
|
||||
select,
|
||||
move,
|
||||
empty_state: {
|
||||
name: "Custom",
|
||||
width: 5,
|
||||
height: 5,
|
||||
board: [],
|
||||
},
|
||||
add_block,
|
||||
};
|
||||
|
@ -162,6 +162,12 @@ const visualize_path = (from_state, to_state) => {
|
||||
// For each state in path: visualize(state)
|
||||
};
|
||||
|
||||
const add_block = (state, x0, y0, x1, y1) => {
|
||||
let new_block = [state.board.length, x0, y0, x1, y1];
|
||||
state.board.push(new_block);
|
||||
return new_block;
|
||||
};
|
||||
|
||||
export const sliding_blocks_model = {
|
||||
name: "Sliding Blocks",
|
||||
generate,
|
||||
@ -171,4 +177,11 @@ export const sliding_blocks_model = {
|
||||
initial_states,
|
||||
select,
|
||||
move,
|
||||
empty_state: {
|
||||
name: "Custom",
|
||||
width: 5,
|
||||
height: 6,
|
||||
board: [],
|
||||
},
|
||||
add_block,
|
||||
};
|
||||
|
Reference in New Issue
Block a user