diff --git a/editor/index.html b/editor/index.html index 45996514..ae6e648d 100644 --- a/editor/index.html +++ b/editor/index.html @@ -51,9 +51,14 @@
-
+
+ @@ -125,7 +130,7 @@
-
+
@@ -833,6 +838,7 @@
+
diff --git a/editor/index.js b/editor/index.js index ce64e759..d383ac46 100644 --- a/editor/index.js +++ b/editor/index.js @@ -6,12 +6,13 @@ import {start, openFindToolWithCurrentPaintCategory, togglePaintGrid, on_paint_frame1, on_paint_frame2, prevPalette, nextPalette, newPalette, duplicatePalette, deletePalette, changeColorPickerIndex, prevDialog, nextDialog, addNewDialog, duplicateDialog, deleteDialog, openFindTool, toggleAlwaysShowDrawingDialog, showInventoryItem, showInventoryVariable, startRecordingGif, stopRecordingGif, takeSnapshotGif, toggleSnapshotMode, - toggleExitOptions, grabCard, onDialogNameChange, onChangeExitTransitionEffect, - on_drawing_name_change, on_toggle_wall, on_toggle_animated, on_palette_name_change + toggleExitOptions, grabCard, onDialogNameChange, onChangeExitTransitionEffect, blockScrollBackpage, copyInstanceURL, + on_drawing_name_change, on_toggle_wall, on_toggle_animated, on_palette_name_change } from "./script/editor.js" import {aboutOpenTab} from "./script/tools/about.js" -import {showPanel, hidePanel} from "./script/editor_state.js" +import {showPanel, hidePanel, loadIcons} from "./script/editor_state.js" +loadIcons() start() export function testShim (gameTool) { @@ -23,6 +24,7 @@ export function bindToolDialogs () { // I get called during editor initialization by start() document.querySelectorAll(".bitsy-card-title").forEach(u => u.addEventListener("onmousedown", grabCard)) + document.querySelector("#editorWindow").addEventListener("onmousewheel", blockScrollBackpage) document.querySelector("#dialogShowCodeCheck").addEventListener("click", toggleDialogCode) document.querySelector("#toolsCheck").addEventListener("click", toggleToolBar) @@ -118,4 +120,6 @@ export function bindToolDialogs () { document.querySelector("#wallCheckbox").addEventListener("change", on_toggle_wall) document.querySelector("#animatedCheckbox").addEventListener("change", on_toggle_animated) document.querySelector("#paletteName").addEventListener("change", on_palette_name_change) + + document.querySelector("#instanceNameCopy").addEventListener("click", copyInstanceURL) } \ No newline at end of file diff --git a/editor/script/dialog_editor.js b/editor/script/dialog_editor.js index c25cf6f6..31e82106 100644 --- a/editor/script/dialog_editor.js +++ b/editor/script/dialog_editor.js @@ -1,6 +1,8 @@ import { rgbToHex } from "./util.js" import { scriptInterpreter, scriptUtils, titleDialogId } from "./engine/world.js" -import { getTitle, getPal, curDefaultPal, sprite, tile, room, item, dialog, palette, setTitle } from "./engine/bitsy.js" +import { getTitle, getPal, curDefaultPal, sprite, tile, room, item, dialog, palette, blip, tune, + setTitle } from "./engine/bitsy.js" +import { tilesize } from "./system/system.js" import { ThumbnailRenderer } from "./thumbnail.js" import { iconUtils, events } from "./editor_state.js" diff --git a/editor/script/editor.js b/editor/script/editor.js index 0a8a4415..0b6a140d 100644 --- a/editor/script/editor.js +++ b/editor/script/editor.js @@ -2,10 +2,10 @@ import { TileType, labelElementFactory, rgbToHex, rgbToHsl, getDrawingDialogId, import { initSystem, bitsyLog, tilesize, scale, mapsize, width, attachCanvas, loadGame, quitGame } from "./system/system.js" import { Resources } from "./generated/resources.js" -import { clearGameData, getPal, getRoomPal, animationTime, initRoom, - curDefaultPal, sprite, tile, room, item, renderer, state, dialog, palette, flags, +import { clearGameData, getPal, getRoomPal, animationTime, initRoom, soundPlayer, + curDefaultPal, sprite, tile, room, item, renderer, state, dialog, palette, flags, fontName, setInventoryCallback, setVariableCallback, setGameResetCallback, setInitRoomCallback, textDirection, - loadWorldFromGameData, serializeWorld, updateNamesFromCurData } from "./engine/bitsy.js" + loadWorldFromGameData, serializeWorld, updateNamesFromCurData, resetAllAnimations } from "./engine/bitsy.js" import { titleDialogId, version, defaultFontName, createDrawingData, createExitData, createEndingData} from "./engine/world.js" @@ -30,7 +30,7 @@ import { makeTuneTool } from "./tools/tune.js" import { makeBlipTool } from "./tools/blip.js" import { setAboutPage, initAbout } from "./tools/about.js" // FIXME -import { localization, readUrlParameters, iconUtils, fontManager, +import { localization, readUrlParameters, iconUtils, fontManager, defaultFonts, events, getPanelPrefs, showPanel, updatePanelPrefs, togglePanel, togglePanelCore } from "./editor_state.js" import { attachServer, updateText, userId } from "./system/multiplayer.js" // FIXME @@ -324,7 +324,7 @@ export let curDialogEditor = null; export let curPlaintextDialogEditor = null; // the duplication is a bit weird, but better than recreating editors all the time? export function openDialogTool(dialogId, insertNextToId, showIfHidden) { // todo : rename since it doesn't always "open" it? - // console.log(new Error("who opened the dialog tool?")) + console.log("dialog tool reload: " + new Error().stack) if (showIfHidden === undefined || showIfHidden === null) { showIfHidden = true; @@ -529,7 +529,7 @@ export function deleteDialog() { // TODO : move into the paint tool var paintDialogWidget = null; -function reloadDialogUI() { +export function reloadDialogUI() { var dialogContent = document.getElementById("dialog"); dialogContent.innerHTML = ""; @@ -641,6 +641,13 @@ function Timer() { } var editMode = EditMode.Edit; // TODO : move to core.js? +const editorWindow = document.querySelector("#editorWindow") +let instanceTextInput + +/* MULTIPLAYER */ +export let server +export let copresenceContext +export const peerCursors = {} /* TOOL CONTROLLERS */ export let roomTool; @@ -660,7 +667,7 @@ export function setItemIndex(idx) { itemIndex = idx; } var roomIndex = 0; /* BROWSER COMPATIBILITY */ -var browserFeatures = { +export var browserFeatures = { colorPicker : false, fileDownload : false, blobURL : false @@ -671,8 +678,8 @@ var gifencoder = new gif(); var gifFrameData = []; /* EXPORT HTML */ -var makeURL = null; -var exporter = new Exporter(); +export var makeURL = null; +export var exporter = new Exporter(); function detectBrowserFeatures() { bitsyLog("BROWSER FEATURES", "editor"); @@ -739,7 +746,6 @@ export function resetFindTool() { }); } -export let server export async function start() { initSystem(); @@ -747,10 +753,13 @@ export async function start() { events.Listen("game_data_change", function(event) { // TODO : refactor "openDialogTool" to split out the actual opening from reloading // force re-load the dialog tool - openDialogTool(titleDialogId, /*insertNextToId*/ null, /*showIfHidden*/ false); + // openDialogTool(titleDialogId, null, false); // titleDialogId, insertNextToId, showIfHidden }); detectBrowserFeatures(); + resizeCanvasOverlay() + copresenceContext = document.getElementById('pointerOverlay').getContext('2d'); + // enable multiplayer editing server = await attachServer(true) let handle = server.handle @@ -788,16 +797,76 @@ export async function start() { // listen to multiplayer server handle.on("change", () => { - // console.log('sync crdt') - var gamedataChanged = handle.doc().bitsy; Store.set("game_data", gamedataChanged) mutex = handle.doc().mutex + console.log('sync crdt: update from ' + Object.entries(mutex)) - on_game_data_change_core() - // reload_game_data(); // causes flicker + // on_game_data_change_core() + reload_game_data(); }) + + // share my cursor + document.addEventListener("mousemove", cursorOverlay) + document.addEventListener("mousedown", cursorDownOverlay) + + // render shared cursors + const cursorIcon = bakeCursor() + handle.on("ephemeral-message", ({handle, senderId, message}) => { + let ctx = copresenceContext + + // HACK: initialize peers on connection, not in the mousemove handler + let u = peerCursors[senderId] + if (u === undefined) { + let randomColor = '#000' + console.log('saw peer with color ' + handle[senderId]) + if (!handle[senderId]) + handle[senderId] = randomColor + peerCursors[senderId] = {color: handle[senderId]}; + } + + // update this peer's cursor ghost + if (message.type == "mousemove") { + u.mouseX = message.mouseX; + u.mouseY = message.mouseY; + u.age = 0; + } + + // clear out timed-out peers + for (let i in peerCursors) { + if (peerCursors[i].age > 500) + delete peerCursors[i] + } + + // redraw cursors + ctx.clearRect(0, 0, window.innerWidth, window.innerHeight); + ctx.fillStyle = '#fff' + + if (message.type == "mousedown") { + ctx.save() + ctx.fillStyle = '#ffa7' + ctx.translate(u.mouseX - editorWindow.scrollLeft, + u.mouseY - editorWindow.scrollTop); + ctx.beginPath() + ctx.arc(0, 0, 10, 0, 2*Math.PI) + ctx.fill() + ctx.restore() + } + + for (let i in peerCursors) { + let msg = peerCursors[i] + ++msg.age; + ctx.strokeStyle = msg.color; // always black + + ctx.save(); + ctx.translate(msg.mouseX - editorWindow.scrollLeft, + msg.mouseY - editorWindow.scrollTop); + ctx.fill(cursorIcon); + ctx.stroke(cursorIcon); + ctx.restore(); + } + }) // now world data like `sprite` and `tile` is loaded // let's make the find tool so that tool cards can use it @@ -922,7 +991,7 @@ export async function start() { } let instanceNameWidget = document.getElementsByClassName("instanceNameContainer")[0]; - let instanceTextInput = document.createElement("input"); + instanceTextInput = document.createElement("input"); instanceTextInput.classList.add("textInputField"); instanceTextInput.style.width = "calc(100% - 15px)" instanceTextInput.type = "text"; @@ -969,6 +1038,36 @@ export async function start() { bindToolDialogs(); } +function bakeCursor(scale = 1) { + const p = new Path2D(); + p.moveTo(0, 0); // tip (hotspot) + p.lineTo(0, 16 * scale); // left edge bottom + p.lineTo(4 * scale, 12 * scale); // inner notch + p.lineTo(7 * scale, 18 * scale); // stylus tip + p.lineTo(9 * scale, 17 * scale); // stylus right + p.lineTo(6 * scale, 11 * scale); // back to body + p.lineTo(11 * scale, 11 * scale); // right shoulder + p.closePath(); + return p; +} + +function resizeCanvasOverlay() { + let canvas = document.getElementById('pointerOverlay') + canvas.width = window.innerWidth; + canvas.height = window.innerHeight; +} +window.addEventListener('resize', resizeCanvasOverlay, false) + +export function copyInstanceURL() { + navigator.clipboard.writeText(`${location.origin}${location.pathname}?instance=${Store.get("instance_name")}`) + instanceTextInput.value = "Copied instance URL!" + this.readOnly = true + setTimeout(() => { + instanceTextInput.value = Store.get("instance_name") + this.readOnly = false + }, 1000); +} + export function newDrawing() { paintTool.newDrawing(); } @@ -1924,6 +2023,7 @@ export function on_change_adv_dialog() { export function reload_game_data() { // FIXME: why does palette revert? // console.log(roomTool?.selectedId, getRoomPal(roomTool?.selectedId)) + console.log("reload_game_data") // same as core, but doesn't reset editor state var gamedataStorage = Store.get("game_data"); @@ -1932,7 +2032,11 @@ export function reload_game_data() { clearGameData(); loadWorldFromGameData(gamedataStorage); - events.Raise("game_data_change"); // who consumes this? + // reset animations + resetAllAnimations(); + renderer.ClearCache(); // reset the renderer after loading the world to avoid nondeterminism + + // events.Raise("game_data_change"); // callback defined in start() } export function on_game_data_change() { @@ -1945,6 +2049,7 @@ export function on_game_data_change() { export function on_game_data_change_core() { var gamedataStorage = Store.get("game_data"); bitsyLog(gamedataStorage, "editor"); + console.log("on_game_data_change_core") console.log('which tool?: ' + mutex[userId]) // FIXME: don't clobber the tool we're holding @@ -1956,6 +2061,7 @@ export function on_game_data_change_core() { spriteId = sortedSpriteIdList().filter(function (id) { return id != "A"; })[spriteIndex]; clearGameData(); + renderer.ClearCache(); loadWorldFromGameData(gamedataStorage); // reparse world if user directly manipulates game data /* @@ -1980,6 +2086,7 @@ export function on_game_data_change_core() { if (drawing) { curPaintMode = drawing.type; } + */ //fallback if there are no tiles, sprites, map // TODO : switch to using stored default file data (requires separated parser / game data code) @@ -1998,13 +2105,9 @@ export function on_game_data_change_core() { if (Object.keys(item).length == 0) { makeItem("0"); } - */ - - // refresh images - renderer.ClearCache(); // try not to clobber editor state - /* roomIndex = 0; + // roomIndex = 0; /* var curPaintMode = TileType.Avatar; @@ -2027,17 +2130,17 @@ export function on_game_data_change_core() { // paintTool.reloadDrawing(); // this reloads the dialog UI updateInventoryUI(localization); - */ + */ // FIXME: catch undefined fontName on startup // if user pasted in a custom font into game data - update the stored custom font - /* if (defaultFonts.indexOf(fontName + fontManager.GetExtension()) == -1) { + if (defaultFonts.indexOf(fontName + fontManager.GetExtension()) == -1) { var fontStorage = { name : fontName, fontdata : fontManager.GetData(fontName) }; Store.set('custom_font', fontStorage); - } */ + } // TODO -- start using this for more things // events.Raise("game_data_change"); // this event reloads all the panels, which we don't want @@ -2754,7 +2857,7 @@ export function panel_onMouseMove(e) { bitsyLog("********", "editor") } -document.addEventListener("mousemove",panel_onMouseMove); +document.addEventListener("mousemove", panel_onMouseMove); export function panel_onMouseUp(e) { if (grabbedPanel.card == null) return; @@ -2799,7 +2902,7 @@ export function getElementSize(e) { /* gets visible size */ } // sort of a hack to avoid accidentally activating backpage and nextpage while scrolling through editor panels -function blockScrollBackpage(e) { +export function blockScrollBackpage(e) { var el = document.getElementById("editorWindow"); var maxX = el.scrollWidth - el.offsetWidth; @@ -2810,6 +2913,21 @@ function blockScrollBackpage(e) { // } } +// show other peoples' cursors in multiplayer +export function cursorOverlay(e) { + server.handle.broadcast({ + type: "mousemove", + mouseX: e.pageX + editorWindow.scrollLeft, + mouseY: e.pageY + editorWindow.scrollTop + }) +} +export function cursorDownOverlay(e) { + server.handle.broadcast({ + type: "mousedown", + target: e.target + }) +} + export function toggleDialogCode(e) { console.log('toggling dialogue code') @@ -2938,7 +3056,7 @@ export function hackUpdateEditorToolMenusOnLanguageChange() { } var curEditorLanguageCode = "en"; -function updateEditorLanguageStyle(newCode) { +export function updateEditorLanguageStyle(newCode) { document.body.classList.remove("lang_" + curEditorLanguageCode); curEditorLanguageCode = newCode; document.body.classList.add("lang_" + curEditorLanguageCode); diff --git a/editor/script/editor_state.js b/editor/script/editor_state.js index 140596b5..2e7179c5 100644 --- a/editor/script/editor_state.js +++ b/editor/script/editor_state.js @@ -8,7 +8,7 @@ import {EventManager} from "./event_manager.js" export let isPlayerEmbeddedInEditor = true // FIXME: flag for game player to make changes specific to editor /* FONT MANAGER */ -var defaultFonts = [ +export var defaultFonts = [ "ascii_small.bitsyfont", "unicode_european_small.bitsyfont", "unicode_european_large.bitsyfont", @@ -46,16 +46,17 @@ export function readUrlParameters() { /* ICONS */ export let iconUtils = new IconUtils() +export function loadIcons() { + // load icons and replace placeholder elements + var elements = document.getElementsByClassName("bitsy_icon"); + for(var i = 0; i < elements.length; i++) { + iconUtils.LoadIcon(elements[i]); + } -// load icons and replace placeholder elements -var elements = document.getElementsByClassName("bitsy_icon"); -for(var i = 0; i < elements.length; i++) { - iconUtils.LoadIcon(elements[i]); -} - -var elements = document.getElementsByClassName("bitsy_icon_anim"); -for(var i = 0; i < elements.length; i++) { - iconUtils.LoadIconAnimated(elements[i]); + var elements = document.getElementsByClassName("bitsy_icon_anim"); + for(var i = 0; i < elements.length; i++) { + iconUtils.LoadIconAnimated(elements[i]); + } } /* EVENTS */ diff --git a/editor/script/engine/bitsy.js b/editor/script/engine/bitsy.js index 93aad134..4bc1501a 100644 --- a/editor/script/engine/bitsy.js +++ b/editor/script/engine/bitsy.js @@ -122,7 +122,7 @@ export function clearGameData() { } // engine event hooks for the editor -var onInventoryChanged = null; +export var onInventoryChanged = null; var onVariableChanged = null; var onGameReset = null; var onInitRoom = null; @@ -663,7 +663,7 @@ export function movePlayer(direction, isFirstMove) { } } -var transition; +export var transition; if (engineFeatureFlags.isTransitionEnabled) { transition = new TransitionManager(); } @@ -1710,12 +1710,12 @@ export function getRoomPal(roomId) { } var isDialogMode = false; -var isNarrating = false; -var isEnding = false; +export var isNarrating = false; +export var isEnding = false; var dialogModule; -var dialogRenderer; -var dialogBuffer; +export var dialogRenderer; +export var dialogBuffer; if (engineFeatureFlags.isDialogEnabled) { dialogModule = new Dialog(); dialogRenderer = dialogModule.CreateRenderer(); diff --git a/editor/script/engine/script.js b/editor/script/engine/script.js index 5d2a4f6a..3bed1be2 100644 --- a/editor/script/engine/script.js +++ b/editor/script/engine/script.js @@ -1,6 +1,8 @@ -import { initRoom } from "./bitsy.js"; +import { initRoom, names, fontName, sprite, tile, item, state, tune, blip, + player, transition, dialogRenderer, dialogBuffer, soundPlayer, + onInventoryChanged, isEnding, isNarrating, updatePalette, drawRoom } from "./bitsy.js"; import { bitsy } from "../system/system.js"; -import { events, isPlayerEmbeddedInEditor } from "../editor_state.js" +import { events, isPlayerEmbeddedInEditor, fontManager } from "../editor_state.js" export function Script() { diff --git a/editor/script/engine/world.js b/editor/script/engine/world.js index d272e113..10629b19 100644 --- a/editor/script/engine/world.js +++ b/editor/script/engine/world.js @@ -1,5 +1,6 @@ import {bitsy} from "../system/system.js" import {Script} from "./script.js" +import { fontManager } from "../editor_state.js"; /* BITSY VERSION */ // is this the right place for this to live? diff --git a/editor/script/exporter.js b/editor/script/exporter.js index c7eb13d3..ea1796b1 100644 --- a/editor/script/exporter.js +++ b/editor/script/exporter.js @@ -1,4 +1,7 @@ -import {Resources} from "./generated/resources.js" +import { Resources } from "./generated/resources.js" +import { fontManager } from "../script/editor_state.js" +import { browserFeatures, makeURL } from "../script/editor.js" +import { bitsyLog } from "./system/system.js" export function Exporter() { @@ -142,7 +145,7 @@ this.importGame = function( html ) { } // Exporter() -var ExporterUtils = { +export var ExporterUtils = { DownloadFile : function(filename, text) { if( browserFeatures.blobURL ) { diff --git a/editor/script/localization.js b/editor/script/localization.js index b5b31536..514d363b 100644 --- a/editor/script/localization.js +++ b/editor/script/localization.js @@ -178,7 +178,7 @@ this.GetStringOrFallback = function(id, englishFallback) { } function localizationContains(id, text) { // TODO : rename to be more descriptive? - for (lang in localizationStrings) { + for (var lang in localizationStrings) { var locString = getLocaleString(lang, id); if (locString != null && locString.length > 0 && locString === text) { return true; diff --git a/editor/script/room_markers.js b/editor/script/room_markers.js index f87749ce..f740150a 100644 --- a/editor/script/room_markers.js +++ b/editor/script/room_markers.js @@ -1,6 +1,6 @@ import {bitsyLog} from "./system/system.js" import {scale, mapsize} from "./system/system.js" -import { room } from "./engine/bitsy.js" +import { room, dialog } from "./engine/bitsy.js" import { createExitData, createEndingData } from "./engine/world.js" import { clamp, deleteUnreferencedDialog } from "./util.js" import {iconUtils, events, localization} from "./editor_state.js" diff --git a/editor/script/system/multiplayer.js b/editor/script/system/multiplayer.js index 840267d3..dbf04fe2 100644 --- a/editor/script/system/multiplayer.js +++ b/editor/script/system/multiplayer.js @@ -11,7 +11,7 @@ import { BrowserWebSocketClientAdapter } from "https://esm.sh/@automerge/automer import { Resources } from "../generated/resources.js" import { Store } from "../store.js" -export const DEBUG_LOCAL = true +export const DEBUG_LOCAL = false export const serverURL = DEBUG_LOCAL ? "http://localhost:3030" : "https://duck-composed-closely.ngrok-free.app" export const updateText = AutomergeRepo.updateText diff --git a/editor/script/system/system.js b/editor/script/system/system.js index 316c214c..f4a604da 100644 --- a/editor/script/system/system.js +++ b/editor/script/system/system.js @@ -464,6 +464,7 @@ export function BitsySystem(name) { memory.changed[next] = false; + // bitsy.log('_allocate', next, memory.blocks) // Error().stack return next; }; diff --git a/editor/script/thumbnail.js b/editor/script/thumbnail.js index f7b0b830..5e4d2682 100644 --- a/editor/script/thumbnail.js +++ b/editor/script/thumbnail.js @@ -2,7 +2,9 @@ import {TileType, labelElementFactory, rgbToHex} from "./util.js" import {gif} from "./gif.js" import {bitsyLog, tilesize, scale} from "./system/system.js" -import { state, room, getPal, getRoomPal, animationTime } from "./engine/bitsy.js"; +import { state, room, item, tile, getPal, getRoomPal, animationTime, + getSpriteFrame, getItemFrame, getTileFrame + } from "./engine/bitsy.js"; import { roomTool, getDrawingImageSource } from "./editor.js"; // renders a tile to canvas (kind of hackily recreates some of the TileRenderer logic - oh well) @@ -299,7 +301,6 @@ export function ThumbnailControl(iconUtils, options) { this.LoadThumbnailImage = function() { if (id && renderer) { var entry = renderer.GetCacheEntry(id); - if (entry.uri != null) { renderOptions.callback(entry.uri); } diff --git a/editor/script/tools/game.js b/editor/script/tools/game.js index 179f9d3b..96d84112 100644 --- a/editor/script/tools/game.js +++ b/editor/script/tools/game.js @@ -1,12 +1,15 @@ -import { fontName, setFont, serializeWorld } from "../engine/bitsy.js"; import { makeToolCard } from "../card.js" import { Store } from "../store.js"; -import { flags, setTextDirection } from "../engine/bitsy.js"; +import { fontName, setFont, serializeWorld, flags, setTextDirection, getTitle, setTitle } from "../engine/bitsy.js"; import { TextDirection } from "../engine/world.js"; import { bitsy, bitsyLog } from "../system/system.js"; +import { ExporterUtils } from "../exporter.js" -import { server, grabCard, findTool, togglePanelAnimated, refreshGameData, setDefaultGameState, updateEditorTextDirection} from "../editor.js" +import { server, grabCard, findTool, togglePanelAnimated, refreshGameData, reloadDialogUI, + setDefaultGameState, updateEditorTextDirection, exporter, updateEditorLanguageStyle, + hackUpdatePlaceholderText, hackUpdateEditorToolMenusOnLanguageChange } from "../editor.js" import { fontManager } from "../editor_state.js"; +import { updateInventoryUI } from "../inventory.js"; import { updateText } from "../system/multiplayer.js"; @@ -224,11 +227,18 @@ export function makeGameTool(localization) { } window.newGameDialog = function newGameDialog() { - var resetMessage = localization.GetStringOrFallback("reset_game_message", "Starting a new game will erase your old data. Consider exporting your work first! Are you sure you want to start over?"); + // TODO: extend localization to multiplayer Bitsy features + // localization.getStringOrFallback("reset_game_message", ...) + var resetMessage = "Save this URL if you want to find this instance again. Really start a new instance?"; // todo : move the confirm dialog into tool.menu code? if (confirm(resetMessage)) { // todo : move into file.js - resetGameData(); + // resetGameData(); + + const url = new URL(window.location.href); + url.searchParams.delete('instance'); + window.history.pushState({}, document.title, url); + location.reload(); } } diff --git a/editor/script/tools/room.js b/editor/script/tools/room.js index 43a55f84..ccb7f9a1 100644 --- a/editor/script/tools/room.js +++ b/editor/script/tools/room.js @@ -11,7 +11,8 @@ import { drawGrid } from "../paint.js" import { MarkerType, LinkState } from "../room_markers.js" import { grabCard, findTool, markerTool, paintTool, isPlayMode, nextObjectId, sortedBase36IdList, sortedPaletteIdList, sortedRoomIdList, togglePanelAnimated, getContrastingColor, isColorDark, isSnapshotInProgress, refreshGameData, - on_paint_sprite_ui_update, on_paint_avatar_ui_update, on_paint_tile_ui_update, on_paint_item_ui_update } from "../editor.js" + on_paint_sprite_ui_update, on_paint_avatar_ui_update, on_paint_tile_ui_update, on_paint_item_ui_update, + CreateDefaultName } from "../editor.js" import { getPanelSetting, setPanelSetting } from "../editor_state.js" export function makeRoomTool(localization, showPanelRef) { diff --git a/editor/style/bitsyEditorStyle.css b/editor/style/bitsyEditorStyle.css index 6c4d5a1b..9bfd167f 100644 --- a/editor/style/bitsyEditorStyle.css +++ b/editor/style/bitsyEditorStyle.css @@ -56,6 +56,14 @@ body { } /* canvas */ +#pointerOverlay { + position: absolute; + z-index: 2; + pointer-events: none; + margin-bottom: 0; + height: 100%; +} + canvas { width: 100%; margin-bottom: var(--bitsy-space-s); @@ -97,7 +105,7 @@ textarea { background: black; color: white; resize: none; - border: none + border: none; padding: var(--bitsy-space-s); border-radius: var(--bitsy-space-xs); flex-grow: 1;