Skip to content

Commit

Permalink
Implement object deletion, moving, editing local files
Browse files Browse the repository at this point in the history
  • Loading branch information
jeremypenner committed Feb 4, 2024
1 parent e8129a1 commit 4174a1f
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 37 deletions.
20 changes: 2 additions & 18 deletions inspector/data.js
Original file line number Diff line number Diff line change
@@ -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"

Expand Down Expand Up @@ -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 () =>
Expand Down
23 changes: 18 additions & 5 deletions inspector/edit.html
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -47,11 +48,23 @@ <h1>Region Editor - <${regionName} objects=${objectList.value}/></h1>
<${propEditor} objects=${objectList.value}/>
</div>
<div>
<div style="padding: 5px;">
<a href="javascript:;" onclick=${() => tracker.undo()}>Undo</a> |
<a href="javascript:;" onclick=${() => tracker.redo()}>Redo</a>
<div>
<label>
Edit local file: <input type="file" accept=".json" onchange=${(e) => {
if (e.target.files.length > 0) {
(async (file) => {
try {
tracker.change(objectList, [], 0, parseHabitatRegion(await file.text()), objectList.value.length)
} catch (e) {
console.error(e)
alert(`Failed to parse JSON: ${e}`)
}
})(e.target.files[0])
}
}}/>
</label>
</div>
<${objectChooser} objects=${objectList.value}/>
<${objectPanel} objectList=${objectList} tracker=${tracker}/>
</div>
</div>
<${jsonDump} heading=${html`Region JSON (<${jsonDownload} value=${objectList.value}>Download<//>)`}
Expand Down
64 changes: 50 additions & 14 deletions inspector/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -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))
}
}

Expand All @@ -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)) },
Expand Down Expand Up @@ -99,6 +106,7 @@ export const createEditTracker = () => {
return {
undo,
redo,
change,
editHistory,
redoHistory,
trackSignal(sig) {
Expand Down Expand Up @@ -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`
<div style="padding: 5px;">
<a href="javascript:;" onclick=${() => tracker.undo()}>Undo</a> | <a href="javascript:;" onclick=${() => tracker.redo()}>Redo</a>
</div>
<fieldset>
<legend>Objects</legend>
${objects.map(o => html`
${objectList.value.map(o => html`
<div>
<label>
<input type="radio" checked=${o.ref === selectionRef.value}
Expand All @@ -273,5 +297,17 @@ export const objectChooser = ({ objects }) => {
</label>
</div>
`)}
<button style="${moveUpDisabled ? disabledStyle : buttonStyle}" disabled=${moveUpDisabled}
onclick=${() => { swapItemsAtIndex(objectList, tracker, iselection - 1)}}>
</button>
<button style="${moveDownDisabled ? disabledStyle : buttonStyle}" disabled=${moveDownDisabled}
onclick=${() => { swapItemsAtIndex(objectList, tracker, iselection)}}>
</button>
<button style="${deleteDisabled ? disabledStyle : dangerousStyle}" disabled=${deleteDisabled}
onclick=${() => { tracker.change(objectList, [], iselection, [], 1) }}>
Delete
</button>
</fieldset>`
}
18 changes: 18 additions & 0 deletions inspector/neohabitat.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down

0 comments on commit 4174a1f

Please sign in to comment.