From b272afdcb8d8aa7100a3ce5431fc1f1fb7051961 Mon Sep 17 00:00:00 2001 From: Lennert Claeys Date: Tue, 25 Jun 2024 19:48:02 +0200 Subject: [PATCH] Make ImageInput component --- src/components/molecules/ImageInput.vue | 118 ++++++++++++++++ src/components/pages/Builder.vue | 173 ++++++++++-------------- 2 files changed, 193 insertions(+), 98 deletions(-) create mode 100644 src/components/molecules/ImageInput.vue diff --git a/src/components/molecules/ImageInput.vue b/src/components/molecules/ImageInput.vue new file mode 100644 index 0000000..c85c37e --- /dev/null +++ b/src/components/molecules/ImageInput.vue @@ -0,0 +1,118 @@ + + + + + diff --git a/src/components/pages/Builder.vue b/src/components/pages/Builder.vue index 2248fa0..5ca49b8 100644 --- a/src/components/pages/Builder.vue +++ b/src/components/pages/Builder.vue @@ -14,20 +14,22 @@ import MapSelect from "../organisms/MapSelect.vue"; import BuilderSettings, { AdvancedSettings, } from "../organisms/BuilderSettings.vue"; +import ImageInput from "../molecules/ImageInput.vue"; +import IconButton from "../atoms/IconButton.vue"; +import plus from "pixelarticons/svg/plus.svg"; const { onPlay, config } = defineProps<{ onPlay: (key: string, map: Map | Config, settings: GameSettings) => void; config?: Config; }>(); const router = useRouter(); - -const terrain = ref(""); -const mask = ref(""); -const background = ref(""); -const layers = ref([]); const preview = ref(); const name = ref(""); +const terrain = ref({ data: "", visible: false }); +const mask = ref({ data: "", visible: false }); +const background = ref({ data: "", visible: false }); +const layers = ref>([]); const settingsOpen = ref(false); const advancedSettings = ref({ @@ -48,43 +50,41 @@ watch( () => advancedSettings.value.customMask, (useMask) => { if (!useMask) { - mask.value = ""; + mask.value = { data: "", visible: false }; } } ); -const addImageFactory = (ref: Ref) => (event: Event) => { - const file = (event.target as HTMLInputElement).files![0]; - - if (!file) { - return; - } - - var reader = new FileReader(); - reader.readAsDataURL(file); - - reader.onload = () => { - ref.value = reader.result as string; +const addImageFactory = + (ref: Ref, visible = true) => + (_: File, data: string) => { + ref.value = { data, visible }; if (advancedSettings.value.bbox.isEmpty()) { var image = new Image(); - image.src = ref.value; + image.src = data; image.onload = () => { advancedSettings.value.bbox = BBox.create(image.width, image.height); }; } }; -}; const handleAddTerrain = addImageFactory(terrain); -const handleAddMask = addImageFactory(mask); +const handleSetTerrainVisibility = (visible: boolean) => + (terrain.value.visible = visible); +const handleAddMask = addImageFactory(mask, false); +const handleSetMaskVisibility = (visible: boolean) => + (mask.value.visible = visible); + const handleAddBackground = addImageFactory(background); +const handleSetBackgroundVisibility = (visible: boolean) => + (background.value.visible = visible); const handleBuild = async () => { const map = await Map.fromConfig({ - terrain: { data: terrain.value, mask: mask.value }, - background: { data: background.value || terrain.value }, + terrain: { data: terrain.value.data, mask: mask.value.data }, + background: { data: background.value.data || terrain.value.data }, layers: layers.value .filter((layer) => !!layer.data) .map((layer) => ({ ...layer })), @@ -109,8 +109,8 @@ const handleBuild = async () => { const handleTest = async () => { const config: Config = { - terrain: { data: terrain.value, mask: mask.value }, - background: { data: background.value || terrain.value }, + terrain: { data: terrain.value.data, mask: mask.value.data }, + background: { data: background.value.data || terrain.value.data }, layers: layers.value .filter((layer) => !!layer.data) .map((layer) => ({ ...layer })), @@ -128,9 +128,9 @@ const handleTest = async () => { }; const loadMap = (config: Config, map: string) => { - terrain.value = config.terrain.data as string; - background.value = config.background.data as string; - layers.value = config.layers; + terrain.value = { data: config.terrain.data as string, visible: true }; + background.value = { data: config.background.data as string, visible: true }; + layers.value = config.layers.map((layer) => ({ ...layer, visible: true })); advancedSettings.value = { bbox: BBox.fromJS(config.bbox) || BBox.create(0, 0), scale: config.scale, @@ -141,9 +141,9 @@ const loadMap = (config: Config, map: string) => { name.value = map; if (config.terrain.mask) { - mask.value = config.terrain.mask as string; + mask.value = { data: config.terrain.mask as string, visible: true }; } else { - mask.value = ""; + mask.value = { data: "", visible: false }; } }; @@ -152,22 +152,15 @@ const handleAddLayer = () => data: "", x: Math.round(preview.value!.scrollLeft / 6), y: Math.round(preview.value!.scrollTop / 6), + visible: true, }); const handleRemoveLayer = (index: number) => { layers.value = layers.value.filter((_, i) => i !== index); }; -const handleAddLayerImage = (event: Event, layer: Layer) => { - const file = (event.target as HTMLInputElement).files![0]; - - if (!file) { - return; - } - - var reader = new FileReader(); - reader.readAsDataURL(file); - reader.onload = () => (layer.data = reader.result as string); +const handleSetLayerVisibility = (visible: boolean, index: number) => { + layers.value[index].visible = visible; }; const handleMouseDown = (event: MouseEvent, layer: Layer) => { @@ -205,65 +198,47 @@ const handleBBoxChange = (newBBox: BBox) => {
- - - + + +

Overlays - +

-
-

- Layer {{ i }} - -

- +
@@ -291,7 +266,7 @@ const handleBBoxChange = (newBBox: BBox) => {
-
+

Build your own map by drawing a terrain and background image. All opaque pixels on the terrain will be used as collision map for the @@ -301,11 +276,12 @@ const handleBBoxChange = (newBBox: BBox) => {

- - + + +