diff --git a/inspector/data.js b/inspector/data.js
index 43ab339..685dfc5 100644
--- a/inspector/data.js
+++ b/inspector/data.js
@@ -1,6 +1,6 @@
import { signal, effect } from "@preact/signals"
import { parse } from "./mudparse.js"
-import { parseHabitatObject } from "./neohabitat.js"
+import { parseHabitatRegion } from "./neohabitat.js"
import { decodeCharset } from "./codec.js"
import { getFile } from "./shim.js"
@@ -104,23 +104,7 @@ export const useJson = (url, defaultValue) => {
}
export const useHabitatJson = (url) => {
- return fetchAndCache(url, async (response) => {
- const value = parseHabitatObject(await response.text())
- if (!Array.isArray(value) || value.length == 0) {
- throw new Error(`Not a valid Habitat JSON file: ${url}`)
- }
- return value.map(obj => {
- if (obj && obj.mods && obj.mods.length > 0) {
- const mod = obj.mods[0]
- mod.x = mod.x ?? 0
- mod.y = mod.y ?? 0
- mod.orientation = mod.orientation ?? 0
- mod.style = mod.style ?? 0
- mod.gr_state = mod.gr_state ?? 0
- }
- return obj
- })
- }, [])
+ return fetchAndCache(url, async (response) => parseHabitatRegion(await response.text()), [])
}
export const betaMud = lazySignal(null, async () =>
diff --git a/inspector/edit.html b/inspector/edit.html
index dd45d5b..8724dd6 100644
--- a/inspector/edit.html
+++ b/inspector/edit.html
@@ -23,7 +23,8 @@
import { useHabitatJson, errorBucket, until } from "./data.js"
import { regionView } from "./region.js"
import { navigationView } from "./navigate.js"
- import { selectionInteraction, propEditor, objectChooser, createEditTracker } from "./edit.js"
+ import { parseHabitatRegion } from "./neohabitat.js"
+ import { selectionInteraction, propEditor, objectPanel, createEditTracker } from "./edit.js"
import { jsonDump, jsonDownload } from "./show.js"
const q = (k) => (new URLSearchParams(window.location.search)).get(k)
@@ -47,11 +48,23 @@
Region Editor - <${regionName} objects=${objectList.value}/>
<${propEditor} objects=${objectList.value}/>
-
-
tracker.undo()}>Undo |
-
tracker.redo()}>Redo
+
+
- <${objectChooser} objects=${objectList.value}/>
+ <${objectPanel} objectList=${objectList} tracker=${tracker}/>
<${jsonDump} heading=${html`Region JSON (<${jsonDownload} value=${objectList.value}>Download/>)`}
diff --git a/inspector/edit.js b/inspector/edit.js
index 04a98ed..dd8f4cd 100644
--- a/inspector/edit.js
+++ b/inspector/edit.js
@@ -26,17 +26,21 @@ export const createEditTracker = () => {
const editHistory = []
const redoHistory = []
- const update = (obj, key, value) => {
+ const update = (obj, key, value, splicing = null) => {
const result = Array.isArray(obj) ? [...obj] : {...obj}
- result[key] = value
+ if (splicing === null) {
+ result[key] = value
+ } else {
+ result.splice(key, splicing, ...value)
+ }
return result
}
- const updateIn = (obj, place, key, value) => {
+ const updateIn = (obj, place, key, value, splicing) => {
if (place.length == 0) {
- return update(obj, key, value)
+ return update(obj, key, value, splicing)
} else {
- return update(obj, place[0], updateIn(obj[place[0]], place.slice(1), key, value))
+ return update(obj, place[0], updateIn(obj[place[0]], place.slice(1), key, value, splicing))
}
}
@@ -48,25 +52,28 @@ export const createEditTracker = () => {
return value
}
- const performEdit = (sig, place, key, value, history) => {
- const previous = valueAt(sig, place)[key]
- sig.value = updateIn(sig.value, place, key, value)
- history.push({ sig, place, key, value, previous })
+ const performEdit = (sig, place, key, value, splicing, history) => {
+ const obj = valueAt(sig, place)
+ const previous = splicing === null ? obj[key] : obj.slice(key, key + splicing)
+ sig.value = updateIn(sig.value, place, key, value, splicing)
+ history.push({ sig, place, key, value, splicing, previous })
}
- const change = (sig, place, key, value) => {
- performEdit(sig, place, key, value, editHistory)
+ const change = (sig, place, key, value, splicing = null) => {
+ performEdit(sig, place, key, value, splicing, editHistory)
redoHistory.length = 0
}
const undo = (fromHistory = editHistory, toHistory = redoHistory) => {
const edit = fromHistory.pop()
if (edit) {
- performEdit(edit.sig, edit.place, edit.key, edit.previous, toHistory)
+ const splicing = edit.splicing === null ? null : edit.value.length
+ performEdit(edit.sig, edit.place, edit.key, edit.previous, splicing, toHistory)
}
}
const redo = () => undo(redoHistory, editHistory)
+
const dynamicProxy = (targetGetter, handler) => {
return new Proxy(targetGetter(), {
ownKeys(target) { return Reflect.ownKeys(targetGetter(target)) },
@@ -99,6 +106,7 @@ export const createEditTracker = () => {
return {
undo,
redo,
+ change,
editHistory,
redoHistory,
trackSignal(sig) {
@@ -259,12 +267,28 @@ export const propEditor = ({ objects }) => {
}
}
-export const objectChooser = ({ objects }) => {
+const swapItemsAtIndex = (sig, tracker, index) => {
+ const newValue = [sig.value[index + 1], sig.value[index]]
+ tracker.change(sig, [], index, newValue, 2)
+}
+
+export const objectPanel = ({ objectList, tracker }) => {
const selectionRef = useContext(Selection)
+ const iselection = objectList.value.findIndex(o => o.ref === selectionRef.value)
+ const deleteDisabled = iselection <= 0
+ const moveUpDisabled = iselection <= 1
+ const moveDownDisabled = iselection <= 0 || iselection >= objectList.value.length - 1
+ const buttonStyle = "border-radius: 8px; font-size: 16px;"
+ const disabledStyle = `background-color: #777; color: #ccc; ${buttonStyle}`
+ const dangerousStyle = `background-color: red; color: white; ${buttonStyle}`
+
return html`
+
`
}
diff --git a/inspector/neohabitat.js b/inspector/neohabitat.js
index 23a3f08..b0e2a78 100644
--- a/inspector/neohabitat.js
+++ b/inspector/neohabitat.js
@@ -74,6 +74,24 @@ export function parseHabitatObject(data) {
return JSON.parse(templateHabitatObject(data))
}
+export function parseHabitatRegion(data) {
+ const region = parseHabitatObject(data)
+ if (!Array.isArray(region) || region.length == 0) {
+ throw new Error(`Not valid Habitat region JSON`)
+ }
+ return region.map(obj => {
+ if (obj && obj.mods && obj.mods.length > 0) {
+ const mod = obj.mods[0]
+ mod.x = mod.x ?? 0
+ mod.y = mod.y ?? 0
+ mod.orientation = mod.orientation ?? 0
+ mod.style = mod.style ?? 0
+ mod.gr_state = mod.gr_state ?? 0
+ }
+ return obj
+ })
+}
+
export function colorsFromOrientation(orientation) {
const colorVal = (orientation & 0x78) >> 3
if (orientation & 0x80) {