@@ 5,9 5,17 @@
export let disabled = false;
export let style = "";
export let variant = "normal";
+ export let selected = false;
</script>
-<button {id} class="btn-{variant} {clazz}" {disabled} on:click on:focus {style}>
+<button
+ {id}
+ class="btn-{variant} {clazz}"
+ {disabled}
+ on:click
+ on:focus
+ {style}
+ class:btn-selected={selected}>
<slot />
</button>
@@ 34,6 42,9 @@
@extend %standard-hover;
background-color: var(--links-transparent);
}
+ .btn-selected {
+ background-color: var(--links-semitransparent);
+ }
.btn-danger {
@extend %standard;
@@ 49,6 49,7 @@
--subtle: rgb(var(--overlay1));
--links: rgb(var(--blue));
--links-transparent: rgba(var(--blue), 0.35);
+ --links-semitransparent: rgba(var(--blue), 0.45);
--links-ultratransparent: rgba(var(--blue), 0.15);
--success: rgb(var(--green));
--warning: rgb(var(--yellow));
@@ 10,6 10,7 @@
import { onMount } from "svelte";
import { part_texture_url } from "../textures.ts";
import Button from "../components/ui/Button.svelte";
+ import WarningIcon from "../icons/WarningIcon.svelte";
let config = DEFAULT_CONFIG;
// Top-level await. Sets the default config, and overwrites it when the new config is avail. Thanks reactivity!
@@ 17,6 18,8 @@
config = await loadConfig();
})();
+ let selected: PartType | null = null;
+
const logger = createDebug("main");
logger(
`Hello, world! StarKingdoms ${APP_VERSION} (${COMMIT_HASH}) at your service!`,
@@ 54,11 57,6 @@
let last_cx = -1;
let last_cy = -1;
- function mousedown(e: MouseEvent) {
- isdragging = true;
- last_cx = e.clientX;
- last_cy = e.clientY;
- }
function mouseup(e) {
isdragging = false;
}
@@ 104,6 102,28 @@
let textures: Map<PartType, HTMLImageElement> = new Map();
let context: CanvasRenderingContext2D | null = null;
+ let cantplace_reason: string | null = null;
+
+ function canPlace(): boolean {
+ if (selected === null) {
+ cantplace_reason = "No part selected";
+ return false;
+ }
+ if (grid.get(grid_x)?.has(grid_y)) {
+ cantplace_reason = "Part already exists in this slot";
+ return false;
+ }
+ let counts = part_counts.get(selected)!;
+ if (counts.used === counts.available) {
+ cantplace_reason = "Out of this part";
+ return false;
+ }
+ cantplace_reason = null;
+ return true;
+ }
+
+ $: selected, grid, canPlace();
+
function render(
ctx: CanvasRenderingContext2D | null,
x: number,
@@ 146,7 166,15 @@
});
ctx.beginPath();
- ctx.strokeStyle = "rgb(166, 227, 161)";
+
+ if (selected === null) {
+ ctx.strokeStyle = "rgb(24, 24, 37)";
+ } else if (canPlace()) {
+ ctx.strokeStyle = "rgb(166, 227, 161)";
+ } else {
+ ctx.strokeStyle = "rgb(243, 139, 169)";
+ }
+
ctx.lineWidth = 2;
ctx.strokeRect(
grid_x * grid_size + x,
@@ 241,12 269,60 @@
confirm_save = false;
}, 5000);
}
+
+ function toggle_select(type: PartType) {
+ console.log(type);
+ if (selected == type) {
+ selected = null;
+ } else {
+ selected = type;
+ }
+ }
+
+ function mousedown(e: MouseEvent) {
+ if (e.button === 0) {
+ if (canPlace()) {
+ if (!grid.has(grid_x)) {
+ grid.set(grid_x, new Map());
+ }
+ grid.get(grid_x)!.set(grid_y, selected!);
+ part_counts.set(selected!, {
+ used: part_counts.get(selected!)!.used + 1,
+ available: part_counts.get(selected!)!.available,
+ });
+ part_counts = part_counts;
+ grid = grid;
+ }
+
+ // This gets unset immediately if a normal click
+ isdragging = true;
+ last_cx = e.clientX;
+ last_cy = e.clientY;
+ } else if (e.button == 2) {
+ // removal
+ if (grid.get(grid_x)?.has(grid_y)) {
+ let type = grid.get(grid_x)!.get(grid_y)!;
+ grid.get(grid_x)?.delete(grid_y);
+ part_counts.set(type, {
+ used: part_counts.get(type)!.used - 1,
+ available: part_counts.get(type)!.available,
+ });
+ part_counts = part_counts;
+ grid = grid;
+ }
+ }
+ }
</script>
<Popup title="Parts" id="parts" draggable minimizable style="width: 15em;">
{#each part_counts.entries() as [type, counts]}
{#if type !== PartType.Hearty}
- <Button style="margin-top: 5px; width: 100%;">
+ <Button
+ selected={type === selected}
+ style="margin-top: 5px; width: 100%;"
+ on:click={() => {
+ toggle_select(type);
+ }}>
<img
style="vertical-align: middle;"
src={part_texture_url(type, true)}
@@ 257,6 333,12 @@
</Button>
{/if}
{/each}
+ {#if cantplace_reason !== null}
+ <span class="server-danger">
+ <WarningIcon class="server-danger-icon" />
+ Cannot place: {cantplace_reason}
+ </span>
+ {/if}
</Popup>
<Popup
@@ 300,6 382,9 @@
on:mouseup|preventDefault={mouseup}
on:mousemove|preventDefault={mousemove}
on:wheel|preventDefault={handleWheel}
+ on:contextmenu|preventDefault={() => {
+ return false;
+ }}
style="background-size: {grid_size}px {grid_size}px; background-position: {x}px {y}px;"
bind:this={canvas} />