Skip to content

Commit

Permalink
Mouse vertexes now emit movement, a bug fix
Browse files Browse the repository at this point in the history
- Mouse vertexes now emit movement instead of the mouse's absolute position.
- Ensure each node of the graph is not empty
  • Loading branch information
igrep committed Apr 24, 2022
1 parent e578302 commit 533f241
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 80 deletions.
169 changes: 96 additions & 73 deletions eval.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ type VertexCore = {

type VertexForEvaluation =
| ClickVertexForEvaluation
| CursorVertexForEvaluation
| (VertexCore & {
kind: "constant";
plugs: { value: PlugNumber };
Expand Down Expand Up @@ -59,44 +60,42 @@ type VertexForEvaluation =
config: { initialX: number; initialY: number };
});

type ClickVertexes = {
justWhenClicked: ClickVertexJustWhenClicked[];
whilePointerDown: ClickVertexWhilePointerDown[];
lastPosition: ClickVertexLastPosition[];
type MouseVertexes = {
click: ClickVertexForEvaluation[];
whilePointerDown: CursorVertexWhilePointerDown[];
lastPosition: CursorVertexLastPosition[];
};

type ClickVertexConfigValue =
| "justWhenClicked"
| "whilePointerDown"
| "lastPosition";
type ClickVertexForEvaluationCore = VertexCore & {
type ClickVertexForEvaluation = VertexCore & {
kind: "click";
plugs: { x: PlugNumber; y: PlugNumber };
config: { send: ClickVertexConfigValue };
plugs: { clicked: PlugNumber };
};
type ClickVertexForEvaluation =
| ClickVertexJustWhenClicked
| ClickVertexWhilePointerDown
| ClickVertexLastPosition;
// onclick
type ClickVertexJustWhenClicked = ClickVertexForEvaluationCore & {
config: { send: "justWhenClicked" };

type CursorVertexConfigValue = "whilePointerDown" | "lastPosition";
type CursorVertexForEvaluationCore = VertexCore & {
kind: "cursor";
plugs: { x: PlugNumber; y: PlugNumber };
config: { send: CursorVertexConfigValue };
};
// onmousemove (with mousedown) & onmouseup
type ClickVertexWhilePointerDown = ClickVertexForEvaluationCore & {
type CursorVertexForEvaluation =
| CursorVertexWhilePointerDown
| CursorVertexLastPosition;
// onmousemove (with pointerdown) & onmouseup
type CursorVertexWhilePointerDown = CursorVertexForEvaluationCore & {
config: { send: "whilePointerDown" };
};
// onmousemove (with mousedown)
type ClickVertexLastPosition = ClickVertexForEvaluationCore & {
// onmousemove (with pointerdown)
type CursorVertexLastPosition = CursorVertexForEvaluationCore & {
config: { send: "lastPosition" };
};

function vertexesForEvaluation(
vertexes: Required<VertonVertexJsObject>[]
): {
plugsCount: number;
jacksCount: number;
plugJackOrdered: VertexForEvaluation[];
clickVertexes: ClickVertexes;
mouseVertexes: MouseVertexes;
idOrdered: VertexForEvaluation[];
} {
const vertexes0 = [...vertexes];
Expand All @@ -113,8 +112,11 @@ function vertexesForEvaluation(

const plugJackOrdered: VertexForEvaluation[] = [];
const idOrdered: VertexForEvaluation[] = [];
const clickVertexes: Record<string, ClickVertexForEvaluation[]> = {
justWhenClicked: [],
const mouseVertexes: Record<
string,
(CursorVertexForEvaluation | ClickVertexForEvaluation)[]
> = {
click: [],
whilePointerDown: [],
lastPosition: [],
};
Expand All @@ -124,16 +126,26 @@ function vertexesForEvaluation(
let v1: VertexForEvaluation;
switch (v.kind) {
case "click":
const configClick = validateConfigClick(v);
v1 = {
_id: v._id,
kind: v.kind,
header: v.header,
plugs: { clicked: plugId++ },
jacks: {},
};
mouseVertexes["click"].push(v1);
break;
case "cursor":
const configCursor = validateConfigCursor(v);
v1 = {
_id: v._id,
kind: v.kind,
header: v.header,
plugs: { x: plugId++, y: plugId++ },
config: { send: configClick },
config: { send: configCursor },
jacks: {},
} as ClickVertexForEvaluation;
clickVertexes[configClick].push(v1);
} as CursorVertexForEvaluation;
mouseVertexes[configCursor].push(v1);
break;
case "constant":
if (!("value" in v.config)) {
Expand Down Expand Up @@ -222,9 +234,10 @@ function vertexesForEvaluation(
}
return {
plugsCount: plugId,
jacksCount: jackId,
plugJackOrdered,
idOrdered,
clickVertexes: clickVertexes as ClickVertexes,
mouseVertexes: mouseVertexes as MouseVertexes,
};
}

Expand All @@ -234,17 +247,24 @@ type Graph = PlugNumber[][];
namespace Graph {
export function build(
edges: Edge.JsObject[],
idOrdered: VertexForEvaluation[]
idOrdered: VertexForEvaluation[],
jacksCount: number
): Graph {
const graph: Graph = [];
for (const { from, to } of edges) {
const { plugs } = idOrdered[from.vertexId];
const plugNumber = (plugs as Record<string, PlugNumber>)[from.plugId];
graph[plugNumber] ||= [];
const graph: Graph = new Array(jacksCount);
for (let jackNumber = 0; jackNumber < graph.length; ++jackNumber) {
graph[jackNumber] = [];
}

for (const { from, to } of edges) {
const { jacks } = idOrdered[to.vertexId];
const jackNumber = (jacks as Record<string, JackNumber>)[to.jackId];
graph[plugNumber].push(jackNumber);

const { plugs } = idOrdered[from.vertexId];
const plugNumber = (plugs as Record<string, PlugNumber>)[from.plugId];
if (plugNumber === undefined || jackNumber === undefined) {
console.error("Invalid edge: ", { from, to });
}
graph[jackNumber].push(plugNumber);
}
return graph;
}
Expand All @@ -269,11 +289,12 @@ export function evaluate(
): Stop {
const {
plugsCount,
jacksCount,
plugJackOrdered,
idOrdered,
clickVertexes,
mouseVertexes,
} = vertexesForEvaluation(vertexes);
const graph = Graph.build(edges, idOrdered);
const graph = Graph.build(edges, idOrdered, jacksCount);
const plugState = PlugState.init(plugsCount);

// beforeEvaluate {
Expand All @@ -300,53 +321,49 @@ export function evaluate(
}

stage.addEventListener("click", handleClick);
stage.addEventListener("mousedown", handleMouseDownMove);
stage.addEventListener("mousemove", handleMouseDownMove);
stage.addEventListener("mouseup", handleMouseUp);
function handleClick(e: MouseEvent) {
const { x, y } = stage.getBoundingClientRect();
for (const vertex of clickVertexes.justWhenClicked) {
plugState[vertex.plugs.x] = e.clientX - x;
plugState[vertex.plugs.y] = e.clientY - y;
stage.addEventListener("pointerdown", handlePointerDownMove);
stage.addEventListener("pointermove", handlePointerDownMove);
function handleClick() {
for (const vertex of mouseVertexes.click) {
plugState[vertex.plugs.clicked] = 1;
}
}
function handleMouseDownMove(e: MouseEvent) {
if (e.buttons === 0) {
return;
}
const { x, y } = stage.getBoundingClientRect();
for (const vertex of clickVertexes.whilePointerDown) {
plugState[vertex.plugs.x] = e.clientX - x;
plugState[vertex.plugs.y] = e.clientY - y;
}
for (const vertex of clickVertexes.lastPosition) {
plugState[vertex.plugs.x] = e.clientX - x;
plugState[vertex.plugs.y] = e.clientY - y;

const rect = stage.getBoundingClientRect();
let lastX = rect.left;
let lastY = rect.top;
function handlePointerDownMove(e: MouseEvent) {
for (const vertex of mouseVertexes.lastPosition) {
plugState[vertex.plugs.x] = e.clientX - lastX;
plugState[vertex.plugs.y] = e.clientY - lastY;
}
}
function handleMouseUp() {
for (const vertex of clickVertexes.whilePointerDown) {
plugState[vertex.plugs.x] = 0;
plugState[vertex.plugs.y] = 0;

if (e.buttons !== 0) {
for (const vertex of mouseVertexes.whilePointerDown) {
plugState[vertex.plugs.x] = e.clientX - lastX;
plugState[vertex.plugs.y] = e.clientY - lastY;
}
}
lastX = e.clientX;
lastY = e.clientY;
}
// }

const runState = { shouldStop: false };
doEvaluate(plugJackOrdered, graph, clickVertexes, plugState, runState, stage);
doEvaluate(plugJackOrdered, graph, mouseVertexes, plugState, runState, stage);
return () => {
runState.shouldStop = true;
stage.removeEventListener("click", handleClick);
stage.removeEventListener("mousemove", handleMouseDownMove);
stage.removeEventListener("mouseup", handleMouseUp);
stage.removeEventListener("pointermove", handlePointerDownMove);
stage.removeEventListener("pointerdown", handlePointerDownMove);
stage.innerHTML = "";
};
}

function doEvaluate(
plugJackOrdered: VertexForEvaluation[],
graph: Graph,
{ justWhenClicked }: ClickVertexes,
{ click, whilePointerDown, lastPosition }: MouseVertexes,
plugState: PlugState,
runState: RunState,
stage: HTMLElement
Expand Down Expand Up @@ -444,8 +461,15 @@ function doEvaluate(
}
}

for (const vertex of justWhenClicked) {
// reset the state of `justWhenClicked` click vertexes
// reset the state of mouse related vertexes
for (const vertex of click) {
plugState[vertex.plugs.clicked] = 0;
}
for (const vertex of whilePointerDown) {
plugState[vertex.plugs.x] = 0;
plugState[vertex.plugs.y] = 0;
}
for (const vertex of lastPosition) {
plugState[vertex.plugs.x] = 0;
plugState[vertex.plugs.y] = 0;
}
Expand All @@ -466,14 +490,13 @@ function getJackValue(
return graph[jack].reduce((a, b) => plugState[a] + plugState[b], 0);
}

function validateConfigClick(
function validateConfigCursor(
v: Required<VertonVertexJsObject>
): ClickVertexConfigValue {
): CursorVertexConfigValue {
if (!(v.config.send instanceof Object)) {
throw new Error(`Invalid config for a click vertex: ${v.config.send}`);
}
switch (v.config.send.chosen) {
case "justWhenClicked":
case "whilePointerDown":
case "lastPosition":
return v.config.send.chosen;
Expand Down
3 changes: 2 additions & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

.menuBar {
margin: 1em 0.5em 0 0.5em;
--submenu-width: 7.5em;
--submenu-width: 8.5em;
--vertical-padding: 0.5em;

/* https://qiita.com/BEMU/items/0f500e0306471073ed63 */
Expand Down Expand Up @@ -128,6 +128,7 @@ <h1>「ナビつき!つくってわかる はじめてゲームプログラミ
<a class="topItem">入力</a>
<div class="submenu">
<a data-handler="addClickInstruction">クリック</a>
<a data-handler="addCursorInstruction">マウスの移動</a>
<a data-handler="addConstInstruction">定数</a>
<a data-handler="addTimeInstruction">経過時間</a>
</div>
Expand Down
19 changes: 13 additions & 6 deletions index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,17 +38,24 @@ document
garage.addVertex({
header: "クリック",
kind: "click",
plugs: [{ plugId: "clicked" }],
config: {},
});
break;
case "addCursorInstruction":
garage.addVertex({
header: "マウスの移動",
kind: "cursor",
plugs: [
{ label: "X座標", plugId: "x" },
{ label: "Y座標", plugId: "y" },
{ label: "X方向", plugId: "x" },
{ label: "Y方向", plugId: "y" },
],
config: {
send: {
chosen: "justWhenClicked",
chosen: "whilePointerDown",
candidates: {
justWhenClicked: "クリックした瞬間だけ",
whilePointerDown: "ボタンを押している間ずっと",
lastPosition: "ボタンを放した後もずっと",
whilePointerDown: "ボタンを押している間だけ",
lastPosition: "ボタンを押していなくても",
},
},
},
Expand Down

0 comments on commit 533f241

Please sign in to comment.