diff --git a/js/5etools-bootstrap.js b/js/5etools-bootstrap.js index e3c885f5..84a8ec6c 100644 --- a/js/5etools-bootstrap.js +++ b/js/5etools-bootstrap.js @@ -69,6 +69,7 @@ const betteR205etools = function () { d20plus.ut.fix3dDice(); d20plus.engine.addLayers(); d20plus.weather.addWeather(); + d20plus.views.addViews(); d20plus.engine.repairPrototypeMethods(); d20plus.engine.disableFrameRecorder(); // d20plus.ut.fixSidebarLayout(); diff --git a/js/base-engine.js b/js/base-engine.js index c50be5e2..de0ac51f 100644 --- a/js/base-engine.js +++ b/js/base-engine.js @@ -932,6 +932,20 @@ function d20plusEngine () { d20plus.anim.animatorTool.doStartScene(sceneUid); }); i(); + } else if (["assignview0", "assignview1", "assignview2", "assignview3"].includes(e)) { + const viewId = e.at(-1); + d20.engine.selected().forEach(it => { + if (it.model) { + if (it.model.get(`bR20_view${viewId}`)) { + it.model.set(`bR20_view${viewId}`, false); + } else { + it.model.set(`bR20_view${viewId}`, true); + } + it.saveState(); + it.model.save(); + } + }); + i(); } // END MOD return !1 @@ -1254,6 +1268,62 @@ function d20plusEngine () { }) }; + d20plus.engine.objectsStashProps = (obj, state) => { + const props = [ + "emits_bright_light", + "emits_low_light", + "has_directional_bright_light", + "has_directional_dim_light", + "showplayers_bar1", + "showplayers_bar2", + "showplayers_bar3", + "showname", + ]; + props.each((prop) => { + if (!state) { + if (obj.attributes[prop]) { + obj.attributes[`bR20_${prop}`] = true; + obj.attributes[prop] = false; + } + } else { + if (obj.attributes[`bR20_${prop}`]) { + obj.attributes[prop] = true; + obj.attributes[`bR20_${prop}`] = false; + delete obj.attributes[`bR20_${prop}`]; + } + } + }); + } + + d20plus.engine.objectsHideUnhide = (query, val, prefix, state) => { + let some = false; + for (const o of d20.engine.canvas._objects) { + const model = o.model; + if (!model) continue; + if (`${model.get(query)}`.search(val) > -1) { + const l = model.attributes.layer; + if (state) { + if (l.search(prefix) > -1) { + model.attributes.layer = l.replace(`${prefix}_`, ""); + d20plus.engine.objectsStashProps(model, true); + o.saveState(); + model.save(); + some = true; + } + } else { + if (l.search(prefix) === -1) { + model.attributes.layer = `${prefix}_${l}`; + d20plus.engine.objectsStashProps(model, false); + o.saveState(); + model.save(); + some = true; + } + } + } + } + return some; + }; + d20plus.engine.addLayers = () => { d20plus.ut.log("Adding layers"); diff --git a/js/base-template.js b/js/base-template.js index c6f369af..edfe0f85 100644 --- a/js/base-template.js +++ b/js/base-template.js @@ -211,6 +211,28 @@ const baseTemplate = function () { <$ } $> + + <$ if(this.view && this.get && d20.Campaign.activePage().get && d20.Campaign.activePage().get('bR20cfg_viewsEnable')) { $> +
  • + Assign view » + +
  • + <$ } $> + + <$ if(this.view && this.get && this.get("sides") !== "" && this.get("cardid") === "") { $>
  • Multi-Sided » diff --git a/js/base-util.js b/js/base-util.js index 9840db39..acd41390 100644 --- a/js/base-util.js +++ b/js/base-util.js @@ -539,6 +539,14 @@ function baseUtil () { } }; + d20plus.ut.dynamicStyles = (slug) => { + if (!d20plus.css.dynamic) d20plus.css.dynamic = {}; + if (!d20plus.css.dynamic[slug]) { + d20plus.css.dynamic[slug] = $("").appendTo("body"); + } + return d20plus.css.dynamic[slug]; + } + /** * Assumes any other lists have been searched using the same term */ diff --git a/js/base-views.js b/js/base-views.js new file mode 100644 index 00000000..a3de579d --- /dev/null +++ b/js/base-views.js @@ -0,0 +1,268 @@ +function baseViews () { + d20plus.views = {}; + + d20plus.views._lastSettingsPageId = null; + + d20plus.views._initSettingsButton = () => { + $(`body`).on("click", ".Ve-btn-views", function () { + // close the parent page settings + hide the page overlay + const $this = $(this); + $this.closest(`[role="dialog"]`).find(`.ui-dialog-buttonpane button:contains("Save")`).click(); + const $barPage = $(`#page-toolbar`); + if (!$barPage.hasClass("closed")) { + $barPage.find(`.handle`).click() + } + + function doShowDialog (page) { + const mutExclusiveHelp = "Check this, if enabling this or PREVIOUS view should disable another one of them"; + const $dialog = $(` +
    + + +
    +

    Default view

    +
    + +
    +

    View 1

    +
    +
    + + +
    + +
    +

    View 2

    +
    +
    + + +
    + +
    +

    View 3

    +
    +
    + + +
    + +
    + `).appendTo($("body")); + + const handleProp = (propName) => $dialog.find(`[name="${propName}"]`).each((i, e) => { + const $e = $(e); + if ($e.is(":checkbox")) { + $e.prop("checked", !!page.get(`bR20cfg_${propName}`)); + } else { + $e.val(page.get(`bR20cfg_${propName}`)); + } + }); + const props = [ + "viewsEnable", + "views0Name", + "views1Enable", + "views1Exclusive", + "views1Name", + "views2Enable", + "views2Exclusive", + "views2Name", + "views3Enable", + "views3Exclusive", + "views3Name", + ]; + props.forEach(handleProp); + + function doSaveValues () { + props.forEach(propName => { + page.set(`bR20cfg_${propName}`, (() => { + const $e = $dialog.find(`[name="${propName}"]`); + if ($e.is(":checkbox")) { + return !!$e.prop("checked"); + } else { + return $e.val(); + } + })()) + }); + page.save(); + } + + $dialog.dialog({ + width: 500, + dialogClass: "no-close", + buttons: [ + { + text: "OK", + click: function () { + $(this).dialog("close"); + $dialog.remove(); + doSaveValues(); + }, + }, + { + text: "Apply", + click: function () { + doSaveValues(); + }, + }, + { + text: "Cancel", + click: function () { + $(this).dialog("close"); + $dialog.remove(); + }, + }, + ], + }); + } + + if (d20plus.views._lastSettingsPageId) { + const page = d20.Campaign.pages.get(d20plus.views._lastSettingsPageId); + if (page) { + doShowDialog(page); + } else d20plus.ut.error(`No page found with ID "${d20plus.views._lastSettingsPageId}"`); + } else d20plus.ut.error(`No page settings button was clicked?!`); + }).on("mousedown", ".chooseablepage .js__settings-page", function () { + const $this = $(this); + d20plus.views._lastSettingsPageId = $this.closest(`[data-pageid]`).data("pageid"); + }); + }; + + d20plus.views._initMenuActions = () => { + $(`body`).on("click", ".chooseViews > li", function () { + const page = d20.Campaign.activePage(); + const items = $(".chooseViews > li") + const id = items.index(this); + const startgroupindex = (() => { for (let i = id; i >= 0; i--) { if (!page.get(`bR20cfg_views${i}Exclusive`)) return i; } })(); + const endgroupindex = (() => { for (let i = id + 1; i <= 5; i++) { if (!page.get(`bR20cfg_views${i}Exclusive`)) return i - 1; } })(); + if (page.get(`bR20cfg_views${id}Off`)) { + d20plus.views.changeViewState(id, true); + for (let i = startgroupindex; i <= endgroupindex; i++) { + if (i !== id) d20plus.views.changeViewState(i, false); + } + } else { + d20plus.views.changeViewState(id, false); + } + }); + } + + d20plus.views._initViewsCss = () => { + d20plus.ut.dynamicStyles("viewsSelect").html(` + .ui-dialog label.half {display: inline-block; margin-bottom: 6px;} + .ui-dialog label.half span {margin-right: 20px;} + #floatingtoolbar ul.chooseViews li {border-width: 1px;border-style: solid; border-color: var(--dark-surface1);} + #floatingtoolbar ul.chooseViews:empty {display:none;} + #floatingtoolbar ul.chooseViews li {height: 19px; border-radius: 12px;} + #floatingtoolbar ul.chooseViews li.fst {border-bottom-left-radius: 0px; border-bottom-right-radius: 0px; border-bottom-width: 0px;} + #floatingtoolbar ul.chooseViews li.lst {border-top-left-radius: 0px; border-top-right-radius: 0px; border-top-width: 0px;} + #floatingtoolbar ul.chooseViews li.mst {border-radius: 0px; border-top: 0px; border-bottom: 0px;} + #floatingtoolbar ul.chooseViews .pictos {padding: 0 3px 0 3px;} + #floatingtoolbar ul.chooseViews .view_toggle {padding: 4px 8px 3px 4px; margin-right: 8px; border-right: 1px solid; border-color: inherit;} + #floatingtoolbar ul.chooseViews li.off .view_toggle .pictos {color: #fff0;} + `); + } + + d20plus.views._initLayerMenu = () => { + d20plus.views.layerMenu = $(``).appendTo($("#editinglayer .submenu")); + } + + d20plus.views.populateMenu = () => { + const page = d20.Campaign.activePage(); + if (!page) return; + let menuhtml = ""; + if (page.get("bR20cfg_viewsEnable")) { + for (let id = 0; id <= 4; id++) { + if (!id || page.get(`bR20cfg_views${id}Enable`)) { + const viewname = page.get(`bR20cfg_views${id}Name`) || (id ? `View ${id}` : `Default view`); + const viewicon = page.get(`bR20cfg_views${id}Icon`) || "P"; + const viewexcl = page.get(`bR20cfg_views${id}Exclusive`) ? (page.get(`bR20cfg_views${id + 1}Exclusive`) ? "mst" : "lst") : page.get(`bR20cfg_views${id + 1}Exclusive`) ? "fst" : ""; + const viewactive = page.get(`bR20cfg_views${id}Off`) ? "off" : ""; + menuhtml += `
  • + E + ${viewicon} + ${viewname} +
  • `; + } + } + } + d20plus.views.layerMenu.html(menuhtml); + } + + d20plus.views.changeViewState = (id, state) => { + const page = d20.Campaign.activePage(); + const menuItem = $(".chooseViews > li").get(id); + if (state) { + $(menuItem).removeClass("off"); + page.set(`bR20cfg_views${id}Off`, false); + d20plus.engine.objectsHideUnhide(`bR20_view${id}`, true, `off${id}`, true); + } else { + $(menuItem).addClass("off"); + page.set(`bR20cfg_views${id}Off`, true); + d20plus.engine.objectsHideUnhide(`bR20_view${id}`, true, `off${id}`, false); + } + page.save(); + $(`#editinglayer .choose${window.currentEditingLayer}`).click(); + } + + d20plus.views.checkPageSettings = () => { + if (!d20.Campaign.activePage() || !d20.Campaign.activePage().get) { + setTimeout(d20plus.views.checkPageSettings, 50); + } else { + d20plus.views.populateMenu(); + } + } + + d20plus.views.addViews = () => { + if (window.is_gm) { + d20plus.views._initSettingsButton(); + d20plus.views._initViewsCss(); + d20plus.views._initLayerMenu(); + d20plus.views._initMenuActions(); + document.addEventListener("VePageChange", d20plus.views.checkPageSettings); + d20plus.views.checkPageSettings(); + } + } +} + +SCRIPT_EXTENSIONS.push(baseViews); \ No newline at end of file diff --git a/js/core-bootstrap.js b/js/core-bootstrap.js index 72723ad6..072462f4 100644 --- a/js/core-bootstrap.js +++ b/js/core-bootstrap.js @@ -49,6 +49,7 @@ const betteR20Core = function () { d20plus.ut.fix3dDice(); d20plus.engine.addLayers(); d20plus.weather.addWeather(); + d20plus.views.addViews(); d20plus.engine.repairPrototypeMethods(); d20plus.engine.disableFrameRecorder(); // d20plus.ut.fixSidebarLayout(); diff --git a/js/templates/template-page-settings.js b/js/templates/template-page-settings.js index 9f6b8c1a..dc0670f8 100644 --- a/js/templates/template-page-settings.js +++ b/js/templates/template-page-settings.js @@ -379,10 +379,13 @@ Updated
    -

    Weather

    +

    Extensions by betteR20

    +
    diff --git a/node/build-scripts.js b/node/build-scripts.js index 7ad19525..83d10691 100644 --- a/node/build-scripts.js +++ b/node/build-scripts.js @@ -157,6 +157,7 @@ const SCRIPTS = { "overwrites/canvas-handler", "base-engine", "base-weather", + "base-views", "base-journal", "base-css", "base-ui", @@ -194,6 +195,7 @@ const SCRIPTS = { "overwrites/canvas-handler", "base-engine", "base-weather", + "base-views", "base-journal", "base-css", "base-ui",