diff --git a/config.json b/config.json
index d585c70c..3baa09d4 100644
--- a/config.json
+++ b/config.json
@@ -83,7 +83,6 @@
"Trash.5f896a",
"Trash.147e80",
"Trash.f7b6c8",
- "PatchNotes.f47225",
"RulesReference.d99993",
"LatestFAQ.faqfaq",
"Doomtokens.16724b",
diff --git a/objects/PatchNotes.f47225.json b/objects/PatchNotes.f47225.json
deleted file mode 100644
index 8cd39164..00000000
--- a/objects/PatchNotes.f47225.json
+++ /dev/null
@@ -1,113 +0,0 @@
-{
- "AltLookAngle": {
- "x": 0,
- "y": 0,
- "z": 0
- },
- "AttachedDecals": [
- {
- "CustomDecal": {
- "ImageURL": "https://steamusercontent-a.akamaihd.net/ugc/2501268517218943111/803E57A7B3E9765DF342050EE6C71D69473A7388/",
- "Name": "Image #1",
- "Size": 1
- },
- "Transform": {
- "posX": -0.93,
- "posY": 0.105,
- "posZ": 0.66,
- "rotX": 90,
- "rotY": 180,
- "rotZ": 0,
- "scaleX": 0.6,
- "scaleY": 0.6,
- "scaleZ": 1
- }
- },
- {
- "CustomDecal": {
- "ImageURL": "https://steamusercontent-a.akamaihd.net/ugc/2037357792052848566/5DA900C430E97D3DFF2C9B8A3DB1CB2271791FC7/",
- "Name": "Image #2",
- "Size": 1
- },
- "Transform": {
- "posX": -1.05,
- "posY": 0.105,
- "posZ": -0.567,
- "rotX": 90,
- "rotY": 205,
- "rotZ": 0,
- "scaleX": 0.3,
- "scaleY": 0.3,
- "scaleZ": 1
- }
- },
- {
- "CustomDecal": {
- "ImageURL": "https://steamusercontent-a.akamaihd.net/ugc/2501268517219098388/0936FEE03B410319658B5E05DB5D486CEDDE98F5/",
- "Name": "Image #3",
- "Size": 1
- },
- "Transform": {
- "posX": 0,
- "posY": 0.105,
- "posZ": -0.81,
- "rotX": 90,
- "rotY": 180,
- "rotZ": 0,
- "scaleX": 2.4,
- "scaleY": 0.009,
- "scaleZ": 1
- }
- }
- ],
- "Autoraise": true,
- "ColorDiffuse": {
- "b": 1,
- "g": 1,
- "r": 1
- },
- "CustomImage": {
- "CustomTile": {
- "Stackable": false,
- "Stretch": true,
- "Thickness": 0.1,
- "Type": 0
- },
- "ImageScalar": 1,
- "ImageSecondaryURL": "http://sfwallpaper.com/images/parchment-paper-wallpaper-10.jpg",
- "ImageURL": "http://sfwallpaper.com/images/parchment-paper-wallpaper-10.jpg",
- "WidthScale": 0
- },
- "Description": "",
- "DragSelectable": true,
- "GMNotes": "",
- "GUID": "f47225",
- "Grid": true,
- "GridProjection": false,
- "Hands": false,
- "HideWhenFaceDown": false,
- "IgnoreFoW": false,
- "LayoutGroupSortIndex": 0,
- "Locked": false,
- "LuaScriptState_path": "PatchNotes.f47225.luascriptstate",
- "LuaScript_path": "PatchNotes.f47225.ttslua",
- "MeasureMovement": false,
- "Name": "Custom_Tile",
- "Nickname": "Patch Notes",
- "Snap": true,
- "Sticky": true,
- "Tooltip": true,
- "Transform": {
- "posX": -27,
- "posY": 1.481,
- "posZ": -56.165,
- "rotX": 0,
- "rotY": 270,
- "rotZ": 0,
- "scaleX": 7.5,
- "scaleY": 1,
- "scaleZ": 7.5
- },
- "Value": 0,
- "XmlUI": ""
-}
diff --git a/objects/PatchNotes.f47225.luascriptstate b/objects/PatchNotes.f47225.luascriptstate
deleted file mode 100644
index 3590d494..00000000
--- a/objects/PatchNotes.f47225.luascriptstate
+++ /dev/null
@@ -1,145 +0,0 @@
-{
- "checks": [],
- "decals": [
- {
- "locked": false,
- "name": "Arkham SCE logo",
- "pos": {
- "x": 3.1,
- "y": 2.2
- },
- "rotation": 0,
- "scale": {
- "x": "2",
- "y": "2"
- },
- "tooltip": "None",
- "url": "https://steamusercontent-a.akamaihd.net/ugc/2501268517218943111/803E57A7B3E9765DF342050EE6C71D69473A7388/"
- },
- {
- "locked": false,
- "name": "Bootlegger Finn",
- "pos": {
- "x": 3.5,
- "y": -1.89
- },
- "rotation": "25",
- "scale": {
- "x": "1",
- "y": "1"
- },
- "tooltip": "None",
- "url": "https://steamusercontent-a.akamaihd.net/ugc/2037357792052848566/5DA900C430E97D3DFF2C9B8A3DB1CB2271791FC7/"
- },
- {
- "locked": false,
- "name": "black bar",
- "pos": {
- "x": 0,
- "y": -2.7
- },
- "rotation": 0,
- "scale": {
- "x": "8",
- "y": "0.03"
- },
- "tooltip": "None",
- "url": "https://steamusercontent-a.akamaihd.net/ugc/2501268517219098388/0936FEE03B410319658B5E05DB5D486CEDDE98F5/"
- }
- ],
- "fields": [
- {
- "align": 3,
- "array": {
- "x": "1",
- "y": "1"
- },
- "counter": "False",
- "distance": {
- "x": "1",
- "y": "1"
- },
- "fieldColor": {
- "a": 0,
- "b": 1,
- "g": 1,
- "r": 1
- },
- "font": "200",
- "locked": false,
- "name": "Patch Notes",
- "pos": {
- "x": "0",
- "y": -2.9
- },
- "role": "Normal Field",
- "size": {
- "x": "3750",
- "y": "250"
- },
- "textColor": {
- "a": 1,
- "b": 0,
- "g": 0,
- "r": 0
- },
- "tooltip": "None",
- "value": [
- "Arkham Horror LCG SCE 4.0.0 - 11/01/2024"
- ]
- },
- {
- "align": 2,
- "array": {
- "x": "1",
- "y": 1
- },
- "distance": {
- "x": "1",
- "y": "1"
- },
- "fieldColor": {
- "a": 0,
- "b": 1,
- "g": 1,
- "r": 1
- },
- "font": "70",
- "locked": false,
- "name": "Details",
- "pos": {
- "x": "0",
- "y": 0.4
- },
- "role": "Nothing",
- "size": {
- "x": "3750",
- "y": "2750"
- },
- "textColor": {
- "a": 1,
- "b": 0,
- "g": 0,
- "r": 0
- },
- "tooltip": "None",
- "value": [
- "New stuff\n- added Parallel Mateo\n- added a global UI for the Bless / Curse manager\n- added a \"shuffle discard into deck\" button to playermats (for example for the mulligan)\n- added XML helper for \"Stella Clark\", \"The Red Clock\" and \"Elle Rubash\"\n- added \"clickability\" to damage / horror tokens and updated the font / image\n- added investigator specific things spawning when placing (e.g. Bounty tokens for Tony)\n- added a right-click function to the left-most \"Discard\" button on playermats\n- added ability for the \"doom in play\" counter to subtract from the total (e.g. for The Longest Night)\n\nImprovements\n- updated chaos token stat tracker to display the last 5 drawn tokens\n- updated deck importer's handling for attachments (use selection from arkham.build if possible, spawn attachment helpers)\n- smoother token spawning by adding a separate cache for them\n- changed helper visibility to only show when placed on a playermat\n- added teal highlighting for temporary action tokens (reminder: spawnable via numpad 2)\n- updated Deck Instruction Generator to add a card gallery to the ArkhamDB deck description\n- updated download menu with a search and author filter\n- updated Victory Display with a button to spawn \"Additional VP\" cards (e.g. to track interludes etc.)\n- updated memory bag script (used by bags with \"place / recall\" feature)\n- updated doom counter (with color and better message)\n- updated Search-A-Card to support searching by ID\n- updated custom card handling by Playercard Panel\n- combined multiple feedback messages from Bless / Curse manager\n- moved side scenario spawn position higher to not overlap with regular scenario boxes\n- Tour: adapted to support unusual display resolutions and added a \"back\" button\n- Attachment Helper: updated to use metadata and added texture for George Barnaby\n\nBugfixes\n- fixed hotkey for multi-handed Upkeep\n- fixed wrong visibility of playermat option panels after loading\n- fixed issues with token redrawing\n- fixed issues with scenario reference card detection\n- updated Navigation Overlay to not break with removed playermats\n- Clean Up Helper: 'nil' handling for scenario, mini card detection and action token resetting\n\nThe campaigns were also updated with improved helpers and upgraded campaign logs!\nPreviewed / spoiled cards for the upcoming cycle \"The Drowned City\" can be accessed\nvia the download menu (bottom right corner of your screen).\n"
- ]
- }
- ],
- "flip": "False",
- "height": "0.1",
- "locks": {
- "checks": false,
- "decals": false,
- "fields": false
- },
- "nudgeDistance": 0.1,
- "scale": {
- "x": "0.3",
- "y": "0.3"
- },
- "sheetLocked": true,
- "wasCommitted": false
-}
diff --git a/objects/PatchNotes.f47225.ttslua b/objects/PatchNotes.f47225.ttslua
deleted file mode 100644
index 7a0df502..00000000
--- a/objects/PatchNotes.f47225.ttslua
+++ /dev/null
@@ -1,3453 +0,0 @@
----@diagnostic disable
-function onLoad(savedData)
- lookupInputIndexToInfo = {}
- lookupButtonIndexToInfo = {}
- lookupFieldIndices = {}
- lookupCheckIndices = {}
- lookupDecalIndices = {}
- lookupSelectionButtonIndices = {}
- lastFieldLockedMessage = 0
- buttonIndex = 0
- inputIndex = 0
-
- -- load saved data if possible
- local loadedData = JSON.decode(savedData) or {}
- sheetLocked = loadedData.sheetLocked or false
- flip = loadedData.flip or "False"
- height = loadedData.height or 0.5
- fields = loadedData.fields or {}
- checks = loadedData.checks or {}
- decals = loadedData.decals or {}
- wasCommitted = loadedData.wasCommitted or false
- local selfScale = self.getScale()
- scale = loadedData.scale or { x = math.floor(100 / selfScale.x) / 100, y = math.floor(100 / selfScale.z) / 100 }
- locks = loadedData.locks or { fields = false, checks = false, decals = false }
-
- if not wasCommitted then
- self.addContextMenuItem("Edit Layout", showEditPanel)
- self.addContextMenuItem("Commit Layout", showCommitPanel)
- nudgeDistance = self.script_state.nudgeDistance or 0.1
- page = 1
- editingSheet = false
- selectedId = 0
- selectedArrayId = 1
- selectedType = ""
- selectedMax = 5
- creating = false
- else
- makeContextMenuItems()
- end
- createAll()
-end
-
-function makeContextMenuItems()
- self.clearContextMenu()
- if (not sheetLocked) then
- local getLocked = function(element)
- if (locks[element]) then return "◆ Lock" else return "◇ Lock" end
- end
- local allLocked = "Lock"
- if (locks.fields and locks.checks and locks.decals) then allLocked = "Unlock" end
- if (#fields > 0 and #checks > 0 and #decals > 0) then
- self.addContextMenuItem(allLocked .. " everything", toggleAllLocks)
- end
- for k, v in pairs(fields) do
- if (v.locked ~= "True") then
- self.addContextMenuItem(getLocked("fields") .. " texts", toggleLockFields)
- break
- end
- end
- for k, v in pairs(checks) do
- if (v.locked ~= "True") then
- self.addContextMenuItem(getLocked("checks") .. " checkboxes", toggleLockChecks)
- break
- end
- end
- for k, v in pairs(decals) do
- if (v.locked ~= "True") then
- self.addContextMenuItem(getLocked("decals") .. " images", toggleLockDecals)
- break
- end
- end
- end
-end
-
-function toggleAllLocks(ply, pos, obj)
- if (locks.fields and locks.checks and locks.decals) then
- locks.fields, locks.checks, locks.decals = false, false, false
- broadcastToColor("Unlocked everything", ply)
- else
- locks.fields, locks.checks, locks.decals = true, true, true
- broadcastToColor("Locked everything", ply)
- end
- updateSave()
- makeContextMenuItems()
- refresh()
-end
-
-function toggleLockFields(ply, pos, obj)
- locks.fields = not locks.fields
- broadcastToColor(locks.fields and "Locked texts" or "Unlocked texts", ply)
- updateSave()
- makeContextMenuItems()
- refresh()
-end
-
-function toggleLockChecks(ply, pos, obj)
- locks.checks = not locks.checks
- broadcastToColor(locks.checks and "Locked checkboxes" or "Unlocked checkboxes", ply)
- updateSave()
- makeContextMenuItems()
- refresh()
-end
-
-function toggleLockDecals(ply, pos, obj)
- locks.decals = not locks.decals
- broadcastToColor(locks.decals and "Locked images" or "Unlocked images", ply)
- updateSave()
- makeContextMenuItems()
- refresh()
-end
-
-function updateSave()
- self.script_state = JSON.encode({
- scale = scale,
- height = height,
- fields = fields,
- checks = checks,
- decals = decals,
- flip = flip,
- sheetLocked = sheetLocked,
- locks = locks,
- nudgeDistance = not wasCommitted and nudgeDistance or nil,
- wasCommitted = wasCommitted
- })
-end
-
-function null() end
-
-function refresh()
- if (not creating) then
- self.clearInputs()
- self.clearButtons()
- inputIndex = 0
- buttonIndex = 0
- if (editingSheet) then
- createSelectionHighlight()
- end
- createAll()
- end
-end
-
-function createAll()
- lookupInputIndexToInfo = {}
- lookupButtonIndexToInfo = {}
- lookupFieldIndices = {}
- lookupCheckIndices = {}
- lookupDecalIndices = {}
- startLuaCoroutine(self, "createAllCoroutine")
-end
-
-function createAllCoroutine()
- if not wasCommitted then
- UI.setAttribute(getPanelId("Loading"), "active", "True")
- end
- coroutine.yield(0)
- creating = true
- for fieldID, field in pairs(fields) do
- lookupFieldIndices[fieldID] = {
- inputs = {},
- totals = {},
- counterButtons = {},
- selectionButtons = {}
- }
- local posx = field.pos.x
- local posy = field.pos.y
- local func = "edit"
- if (field.vsum == "True") then
- func = 'MarumEditableRecalculateSum_' .. fieldID
- _G[func] = function(obj, ply, input_value, selected)
- local fID = fieldID
- edit(obj, ply, input_value, selected)
- obj.call("recalculateVSums", fID)
- end
- else
- local iIndex = inputIndex
- if (field.locked == "True" or sheetLocked or locks.fields) then
- func = 'MarumEditableRevert_' .. fieldID
- _G[func] = function(obj, ply, input_value, selected)
- local fID = fieldID
- local iID = iIndex
- local sel = selected
- obj.call("revertField", { fID, ply, iID, sel })
- end
- end
- end
-
- local fieldScale = { x = scale.x, y = 1, z = scale.y }
- local rotation = { x = 0, y = 0, z = 0 }
- local posMulx = 1
- local flipped = 1
- if (flip == "True") then
- rotation.y = 180
- flipped = -1
- end
- local upright = self.getTransformUp().y > 0
- local shouldFlip = (field.locked == "True" or sheetLocked or locks.fields) and upright
- local unlockedRotation = { x = rotation.x, y = rotation.y, z = rotation.z }
- if (editingSheet or shouldFlip) then
- rotation.z = 180
- posMulx = -posMulx
- fieldScale.x = -fieldScale.x
- end
- local vsum = 0
- local fontSize = math.min(field.size.y - 24, field.font)
- local color = getFieldTextColor(fieldID)
- for x = 1, field.array.x do
- vsum = 0
- for y = 1, field.array.y do
- local arrayID = x + (y - 1) * field.array.x
- local pos = getFieldPosition(fieldID, x, y)
- self.createInput({
- value = field.value[arrayID],
- tooltip = getFieldTooltip(fieldID, arrayID),
- input_function = func,
- function_owner = self,
- alignment = field.align,
- position = pos,
- width = field.size.x,
- height = field.size.y,
- rotation = rotation,
- font_size = fontSize,
- scale = fieldScale,
- font_color = color,
- color = field.fieldColor,
- tab = 2
- })
- if (field.counter == "True") then
- local counterButtonWidth = fontSize * 0.75
- _G['MarumEditableCounterIncrease_' .. fieldID .. '_' .. arrayID] = function(obj, ply, alt)
- local fID = fieldID
- local aID = arrayID
- obj.call("increaseCounter", { fID, aID, ply })
- end
- buttonIndex = buttonIndex + 1
- lookupButtonIndexToInfo[buttonIndex] = { type = "counter", id = fieldID }
- table.insert(lookupFieldIndices[fieldID].counterButtons, { index = buttonIndex, x = x, y = y, side = 1 })
- self.createButton({
- click_function = 'MarumEditableCounterIncrease_' .. fieldID .. '_' .. arrayID,
- tooltip = "↑ Increase ↑",
- function_owner = self,
- label = "[b]+[/b]",
- position = { x = pos.x + (field.size.x + counterButtonWidth) / 1000 * fieldScale.x * posMulx * flipped, y = pos.y, z = pos.z },
- rotation = unlockedRotation,
- scale = fieldScale,
- width = counterButtonWidth,
- height = counterButtonWidth,
- font_size = fontSize / 2,
- font_color = color,
- color = field.fieldColor,
- })
-
- _G['MarumEditableCounterDecrease_' .. fieldID .. '_' .. arrayID] = function(obj, ply, alt)
- local fID = fieldID
- local aID = arrayID
- obj.call("decreaseCounter", { fID, aID, ply })
- end
- buttonIndex = buttonIndex + 1
- table.insert(lookupFieldIndices[fieldID].counterButtons, { index = buttonIndex, x = x, y = y, side = -1 })
- self.createButton({
- click_function = 'MarumEditableCounterDecrease_' .. fieldID .. '_' .. arrayID,
- tooltip = "↓ Decrease ↓",
- function_owner = self,
- label = "[b]-[/b]",
- position = { x = pos.x - (field.size.x + counterButtonWidth) / 1000 * fieldScale.x * posMulx * flipped, y = pos.y, z = pos.z },
- unlockedRotation = rotation,
- scale = fieldScale,
- width = counterButtonWidth,
- height = counterButtonWidth,
- font_size = fontSize / 2,
- font_color = color,
- color = field.fieldColor,
- })
- end
- inputIndex = inputIndex + 1
- lookupInputIndexToInfo[inputIndex] = { type = "field", id = fieldID, arrayID = arrayID }
- table.insert(lookupFieldIndices[fieldID].inputs, { index = inputIndex, arrayID = arrayID, x = x, y = y })
- if (field.vsum == "True") then
- if (tonumber(field.value[arrayID])) then
- vsum = vsum + tonumber(field.value[arrayID])
- end
- end
-
- if (inputIndex % 10 == 0) then coroutine.yield(0) end
- end
-
- if (field.vsum == "True") then
- local pos = getFieldPosition(fieldID, x, field.array.y + 1)
- local func = 'MarumEditableRevertSum_' .. fieldID
- _G[func] = function(obj, ply, input_value, selected)
- obj.call("revertFieldSum", { fieldID, ply, iIndex, selected })
- end
- self.createInput({
- value = "[u]" .. vsum .. "[/u]",
- tooltip = "[Sum]",
- input_function = func,
- function_owner = self,
- alignment = field.align,
- position = pos,
- width = field.size.x,
- height = field.size.y,
- rotation = { x = unlockedRotation.x, y = unlockedRotation.y, z = unlockedRotation.z + 180 },
- font_size = fontSize,
- scale = { x = -scale.x, y = 1, z = scale.y },
- font_color = color,
- color = field.fieldColor,
- tab = 0
- })
- inputIndex = inputIndex + 1
- table.insert(lookupFieldIndices[fieldID].totals, { index = inputIndex, x = x })
- end
- end
- end
-
- createDecals()
- for decalID, decal in pairs(decals) do
- lookupDecalIndices[decalID] = { inputs = {}, selectionButtons = {} }
- local pos = getDecalPosition(decalID)
- if (decal.locked ~= "True" and not sheetLocked and not locks.decals and not editingSheet) then
- local func = 'MarumEditableSetURL_' .. decalID
- _G[func] = function(obj, ply, alt)
- obj.call("showImageURLPanel", { decalID, ply })
- end
- local tooltip = getDecalTooltip(decalID)
- self.createButton({
- value = decal.url,
- tooltip = tooltip,
- click_function = func,
- function_owner = self,
- position = pos,
- width = 490,
- height = 490,
- rotation = { x = 0, y = 0, z = 0 },
- font_size = 10,
- scale = { x = decal.scale.x * scale.x, y = decal.scale.y * scale.y, z = decal.scale.y * scale.y },
- font_color = { r = 0, g = 0, b = 0, a = 0 },
- color = { r = 0, g = 0, b = 0, a = 0 },
- })
- buttonIndex = buttonIndex + 1
- lookupButtonIndexToInfo[buttonIndex] = { type = "decal", id = decalID }
- table.insert(lookupDecalIndices[decalID].inputs, { index = buttonIndex })
- end
-
- if (inputIndex % 10 == 0) then coroutine.yield(0) end
- end
-
- for checkID, check in pairs(checks) do
- lookupCheckIndices[checkID] = { buttons = {}, selectionButtons = {} }
- local rotationZ = 0
- local checkScale = { x = scale.x * check.size.x, y = 1, z = scale.y * check.size.y }
- local upright = self.getTransformUp().y > 0
- local shouldFlip = (check.locked == "True" or sheetLocked or locks.checks) and upright
- if (editingSheet or shouldFlip) then
- checkScale.x = -checkScale.x
- rotationZ = 180
- end
- for x = 1, check.array.x do
- for y = 1, check.array.y do
- local arrayID = x + (y - 1) * check.array.x
- local func = "MarumEditableClickCheckbox_" .. checkID .. "_" .. arrayID
- if (check.locked == "True" or sheetLocked or locks.checks) then
- func = "null"
- end
- local rotationY = 0
- local posMul = 1
- if (flip == "True") then
- rotationY = 180
- posMul = -posMul
- end
- local pos = getCheckPosition(checkID, x, y)
- local bindex = buttonIndex
- _G['MarumEditableClickCheckbox_' .. checkID .. '_' .. arrayID] = function(obj, ply, alt)
- local fID = checkID
- local aID = arrayID
- local bi = bindex
- obj.call("clickcheck", { fID, aID, alt, bi, ply })
- end
-
- local tooltip = getCheckTooltip(checkID)
- local label, color, alphaCorrectedColor = getCheckLabelAndColor(checkID, arrayID)
- buttonIndex = buttonIndex + 1
- lookupButtonIndexToInfo[buttonIndex] = { type = "check", id = checkID, arrayID = arrayID }
- table.insert(lookupCheckIndices[checkID].buttons, { index = buttonIndex, x = x, y = y, arrayID = arrayID })
- self.createButton({
- label = label,
- tooltip = tooltip,
- click_function = func,
- function_owner = self,
- alignment = 3,
- position = pos,
- width = 250,
- height = 250,
- rotation = { x = 0, y = rotationY, z = rotationZ },
- font_size = check.font,
- scale = { x = checkScale.x, y = checkScale.y, z = checkScale.z },
- font_color = alphaCorrectedColor,
- color = check.checkColor,
- tab = 0
- })
-
- if (buttonIndex % 10 == 0) then coroutine.yield(0) end
- end
- end
- end
- if not wasCommitted and editingSheet then
- createSelectionButtons()
- end
- creating = false
- return 1
-end
-
-function revertField(args)
- local fieldID = args[1]
- local ply = args[2]
- local selected = args[4]
- if (not selected) then
- Wait.frames(
- function()
- for k, v in pairs(lookupFieldIndices[fieldID].inputs) do
- self.editInput({ index = v.index - 1, value = fields[fieldID].value[v.arrayID] })
- end
- end,
- 1
- )
- else
- if (lastFieldLockedMessage ~= fieldID) then
- broadcastToColor("This text is locked", ply, { r = 1, g = 0.5, b = 0 })
- lastFieldLockedMessage = fieldID
- end
- end
-end
-
-function recalculateVSums(fieldID)
- local field = fields[fieldID]
- for k, v in pairs(lookupFieldIndices[fieldID].totals) do
- local vsum = 0
- for y = 1, field.array.y do
- local arrayID = v.x + (y - 1) * field.array.x
- if (tonumber(field.value[arrayID])) then
- vsum = vsum + tonumber(field.value[arrayID])
- end
- end
- self.editInput({ index = v.index - 1, value = "[u]" .. vsum .. "[/u]" })
- end
-end
-
-function revertFieldSum(args)
- local fieldID = args[1]
- local ply = args[2]
- local selected = args[4]
- if (not selected) then
- Wait.frames(function() recalculateVSums(fieldID) end, 1)
- else
- if (lastFieldLockedMessage ~= fieldID) then
- broadcastToColor("This text is reserved for the total sum", ply, { r = 1, g = 1, b = 0 })
- lastFieldLockedMessage = fieldID
- end
- end
-end
-
-function createDecals()
- local decalParameters = {}
- for decalID, decal in pairs(decals) do
- local rotationAdd = 180
- if (flip == "True") then
- rotationAdd = 0
- end
- local pos = getDecalPosition(decalID)
- table.insert(decalParameters, {
- url = decal.url,
- name = "Image #" .. decalID,
- position = { x = -pos.x, y = pos.y, z = pos.z },
- rotation = { x = 90, y = rotationAdd + decal.rotation, z = 0 },
- scale = { x = decal.scale.x * scale.x, y = decal.scale.y * scale.y, z = 1 }
- })
- end
- self.setDecals(decalParameters)
-end
-
-function getFieldPosition(fieldID, x, y)
- local field = fields[fieldID]
- local mul = 1
- if (flip == "True") then mul = -1 end
- return {
- x = (field.pos.x + (x - 1) * field.distance.x) * scale.x * mul,
- y = height + 0.002,
- z = (field.pos.y + (y - 1) * field.distance.y) * scale.y * mul
- }
-end
-
-function getFieldTooltip(fieldID, arrayID)
- local field = fields[fieldID]
- local tooltip = ""
- if (not field.locked) then
- if (field.tooltip == nil or field.tooltip:find("name")) then
- tooltip = field.name or ""
- elseif (field.tooltip:find("content")) then
- tooltip = field.value[arrayID]
- end
- end
- return tooltip
-end
-
-function getCheckPosition(checkID, x, y)
- local check = checks[checkID]
- local mul = 1
- if (flip == "True") then mul = -1 end
- return {
- x = (check.pos.x + (x - 1) * check.distance.x) * mul * scale.x,
- y = height + 0.002,
- z = (check.pos.y + (y - 1) * check.distance.y) * mul * scale.y
- }
-end
-
-function getDecalPosition(decalID)
- local decal = decals[decalID]
- local mul = 1
- if (flip == "True") then mul = -1 end
- return { x = decal.pos.x * mul * scale.x, y = height + 0.005, z = decal.pos.y * mul * scale.y }
-end
-
-function getDecalTooltip(decalID)
- local decal = decals[decalID]
- local tooltip = ""
- if (decal.tooltip == nil) then
- tooltip = decal.name or ""
- elseif (decal.tooltip:find("name")) then
- tooltip = decal.name or ""
- elseif (decal.tooltip:find("hint")) then
- tooltip = "Click to change image"
- end
- return tooltip
-end
-
-function increaseCounter(args)
- local fieldID = tonumber(args[1])
- local arrayID = tonumber(args[2])
- local ply = args[3]
- local field = fields[fieldID]
- if (field.value[arrayID] == nil or field.value[arrayID] == "") then
- field.value[arrayID] = 0
- end
- if (tonumber(field.value[arrayID])) then
- field.value[arrayID] = tonumber(field.value[arrayID]) + 1
- updateFieldNameContentAndTooltip(fieldID)
- if (field.vsum == "True") then
- recalculateVSums(fieldID)
- end
- updateSave()
- else
- broadcastToColor("Field does not contain a valid number", ply)
- end
-end
-
-function decreaseCounter(args)
- local fieldID = tonumber(args[1])
- local arrayID = tonumber(args[2])
- local ply = args[3]
- local field = fields[fieldID]
- if (field.value[arrayID] == nil or field.value[arrayID] == "") then
- field.value[arrayID] = 0
- end
- if (tonumber(field.value[arrayID])) then
- field.value[arrayID] = tonumber(field.value[arrayID]) - 1
- updateFieldNameContentAndTooltip(fieldID)
- if (field.vsum == "True") then
- recalculateVSums(fieldID)
- end
- updateSave()
- else
- broadcastToColor("Field does not contain a valid number", ply)
- end
-end
-
-function edit(obj, ply, value, selected)
- for k, v in pairs(obj.getInputs()) do
- if (lookupInputIndexToInfo[k] ~= nil) then
- if (lookupInputIndexToInfo[k].type == "field") then
- local field = fields[lookupInputIndexToInfo[k].id]
- if (v.value ~= field.value[lookupInputIndexToInfo[k].arrayID]) then
- field.value[lookupInputIndexToInfo[k].arrayID] = v.value
- if (field.tooltip ~= nil) then
- if (field.tooltip:find("content")) then
- self.editInput({ index = k - 1, tooltip = v.value })
- end
- end
- if (field.role ~= nil) then
- if (field.role:find("name")) then
- self.setName(value)
- elseif (field.role:find("description")) then
- self.setDescription(value)
- end
- end
- updateSave()
- break
- end
- end
- end
- end
-end
-
-function editUrl(obj, ply, value, selected)
- for k, v in pairs(obj.getInputs()) do
- if (lookupInputIndexToInfo[k] ~= nil) then
- if (lookupInputIndexToInfo[k].type == "decal") then
- if (v.value ~= decals[lookupInputIndexToInfo[k].id].url) then
- decals[lookupInputIndexToInfo[k].id].url = v.value
- updateSave()
- createDecals()
- break
- end
- end
- end
- end
-end
-
-function clickcheck(args)
- local checkID = tonumber(args[1])
- local arrayID = tonumber(args[2])
- local alt_click = args[3]
- local buttonIndex = args[4]
- local ply = args[5]
- local check = checks[checkID]
- local value = tonumber(check.value[arrayID])
- if (value == nil) then value = 1 end
- if (alt_click) then
- if (value > 0) then
- check.value[arrayID] = 0
- else
- check.value[arrayID] = 1
- end
- else
- if (value == 1) then
- check.value[arrayID] = 2
- else
- if (value == 2) then
- check.value[arrayID] = 1
- elseif (check.fillFromDisabled == "True") then
- check.value[arrayID] = 2
- else
- broadcastToColor("This checkbox is disabled. You can enable/disable checkboxes with Right click.", ply)
- end
- end
- end
-
- local label, color, alphaCorrectedColor = getCheckLabelAndColor(checkID, arrayID)
- self.editButton({ index = buttonIndex, label = label, font_color = alphaCorrectedColor })
- updateSave()
-end
-
-function getFieldTextColor(fieldID)
- local field = fields[fieldID]
- local textAlpha = field.textColor.a
- if (tonumber(field.fieldColor.a) > 0) then
- textAlpha = tonumber(field.textColor.a) / tonumber(field.fieldColor.a)
- else
- textAlpha = tonumber(field.textColor.a) * 100
- end
- return { r = field.textColor.r, g = field.textColor.g, b = field.textColor.b, a = textAlpha }
-end
-
-function getCheckTooltip(checkID)
- local check = checks[checkID]
- local tooltip = ""
- if (not check.locked) then
- if (check.tooltip == nil or check.tooltip:find("name")) then
- tooltip = check.name
- elseif (check.tooltip:find("hint")) then
- tooltip = "Left click to toggle, Right click to enable/disable"
- end
- end
- return tooltip
-end
-
-function getCheckLabelAndColor(checkID, arrayID)
- local check = checks[checkID]
- local label = check.characters.empty
- if (check.value[arrayID] == 0) then
- label = check.characters.disabled
- elseif (check.value[arrayID] == 2) then
- label = check.characters.filled
- end
-
- local color = nil
- if (check.separateColors == "True") then
- if (check.value[arrayID] == 0) then
- color = check.textColorDisabled or check.textColor
- elseif (check.value[arrayID] == 1) then
- color = check.textColorOff or check.textColor
- elseif (check.value[arrayID] == 2) then
- color = check.textColorOn or check.textColor
- else
- color = check.textColorOff or check.textColor
- end
- else
- color = check.textColorOn or check.textColor
- end
-
- local alpha = 1
- local checkAlpha = math.max(1 / 255, check.checkColor.a)
- if (tonumber(check.checkColor.a) > 0) then
- alpha = tonumber(color.a) / tonumber(checkAlpha)
- else
- alpha = tonumber(color.a) * 100
- end
- return label, color, { r = color.r, g = color.g, b = color.b, a = color.a * alpha }
-end
-
-function split(inputstr, sep)
- if sep == nil then
- sep = "%s"
- end
- local t = {}
- for str in string.gmatch(inputstr, "([^" .. sep .. "]+)") do
- table.insert(t, str)
- end
- return t
-end
-
-function onRotate(spin, flip, player_color, old_spin, old_flip)
- updateLockedFieldOrientation(flip < 90)
-end
-
-function onDrop(ply)
- updateLockedFieldOrientation(self.getTransformUp().y >= 0)
-end
-
-function updateLockedFieldOrientation(upright)
- for k, v in pairs(fields) do
- if (v.locked == "True" or sheetLocked or locks.fields or v.vsum == "True") then
- local field = v
- local fieldScale = { x = scale.x, y = 1, z = scale.y }
- local rotation = { x = 0, y = 0, z = 0 }
- if (flip == "True") then
- rotation.y = 180
- end
- if (upright) then
- rotation.z = 180
- fieldScale.x = -scale.x
- end
- if (v.locked == "True" or sheetLocked or locks.fields) then
- for arrayID, inp in pairs(lookupFieldIndices[k].inputs) do
- self.editInput({ index = inp.index - 1, rotation = rotation, scale = fieldScale })
- end
- end
- for arrayID, inp in pairs(lookupFieldIndices[k].totals) do
- self.editInput({ index = inp.index - 1, rotation = rotation, scale = fieldScale })
- end
- end
- end
- for k, v in pairs(checks) do
- if (v.locked == "True" or sheetLocked or locks.fields) then
- local check = v
- local rotationZ = 0
- local checkScale = { x = scale.x * check.size.x, y = 1, z = scale.y * check.size.y }
- if (upright) then
- checkScale.x = -checkScale.x
- rotationZ = 180
- end
- local rotationY = 0
- if (flip == "True") then
- rotationY = 180
- end
- for arrayID, inp in pairs(lookupCheckIndices[k].buttons) do
- self.editButton({
- index = inp.index - 1,
- rotation = { x = 0, y = rotationY, z = rotationZ },
- scale = checkScale
- })
- end
- end
- end
-end
-
-function showImageURLPanel(args)
- local decalID = args[1]
- local ply = args[2]
- Player[ply].showInputDialog("Set image URL",
- function(text, player_color)
- decals[decalID].url = text
- createDecals()
- end
- )
-end
-
-function updateFieldNameContentAndTooltip(fieldID)
- local field = fields[fieldID]
- for k, v in pairs(lookupFieldIndices[fieldID].inputs) do
- self.editInput({
- index = v.index - 1,
- value = field.value[v.arrayID],
- tooltip = getFieldTooltip(fieldID, v.arrayID)
- })
- end
- local name = "T" .. fieldID
- local tooltip = "Select " .. (field.name or name)
- for k, v in pairs(lookupFieldIndices[fieldID].selectionButtons) do
- self.editButton({ index = v.index - 1, tooltip = tooltip })
- end
-end
-
---$
-
-function get_line_count(str)
- local lines = 1
- for i = 1, #str do
- local c = str:sub(i, i)
- if c == 'n' then lines = lines + 1 end
- end
- return lines
-end
-
-function createSelectionButtons()
- coroutine.yield(0)
- local rotation = { x = 0, y = 0, z = 0 }
- if (flip == "True") then
- rotation.y = 180
- end
-
- for fieldID, field in pairs(fields) do
- local posx = field.pos.x
- local posy = field.pos.y
- local fieldScale = { x = scale.x, y = 1, z = scale.y }
- local posMul = 1
- if (flip == "True") then
- posMul = -1
- end
-
- local fontSize = field.font
- fontSize = math.min(field.size.y - 23, fontSize)
- for x = 1, field.array.x do
- for y = 1, field.array.y do
- local name = "T" .. fieldID
- local arrayID = x + (y - 1) * field.array.x
- local tooltip = "Select " .. (field.name or name)
- local pos = {
- x = (posx + (x - 1) * field.distance.x) * fieldScale.x * posMul,
- y = height + 0.005,
- z = (posy + (y - 1) * field.distance.y) * fieldScale.z * posMul
- }
- buttonIndex = buttonIndex + 1
- table.insert(lookupFieldIndices[fieldID].selectionButtons, { index = buttonIndex, x = x, y = y })
- self.createButton({
- click_function = 'MarumEditableSheet_SelectField/' .. fieldID .. '_' .. arrayID,
- tooltip = tooltip,
- function_owner = self,
- label = "",
- position = pos,
- rotation = rotation,
- scale = { x = fieldScale.x * 0.25, y = 1, z = fieldScale.z * 0.25 },
- width = field.size.x * 4 + 200,
- height = field.size.y * 4 + 200,
- font_size = field.font,
- font_color = { r = 1, g = 1, b = 1, a = 1 },
- color = { r = 0, g = 0.5, b = 1, a = 0.5 },
- hover_color = { r = 0, g = 0.5, b = 1, a = 0.8 }
- })
- _G['MarumEditableSheet_SelectField/' .. fieldID .. '_' .. arrayID] = function(obj, ply, alt)
- obj.call("selectField", { id = fieldID, arrayId = arrayID })
- end
- end
- end
- if (buttonIndex % 10 == 0) then coroutine.yield(0) end
- end
-
- for decalID, decal in pairs(decals) do
- local name = "D" .. decalID
- local tooltip = "Select " .. (decal.name or name)
- local pos = getDecalPosition(decalID)
- buttonIndex = buttonIndex + 1
- table.insert(lookupDecalIndices[decalID].selectionButtons, { index = buttonIndex, x = x, y = y })
- self.createButton({
- click_function = 'MarumEditableSheet_SelectDecal_' .. decalID,
- tooltip = tooltip,
- function_owner = self,
- label = "",
- position = pos,
- rotation = rotation,
- scale = { x = decal.scale.x * scale.x * 0.25, y = decal.scale.y * scale.y * 0.25, z = decal.scale.y * scale.y * 0.25 },
- width = 2000,
- height = 2000,
- font_size = 100,
- font_color = { r = 1, g = 1, b = 1, a = 1 },
- color = { r = 0, g = 0.5, b = 1, a = 0.5 },
- hover_color = { r = 0, g = 0.5, b = 1, a = 0.8 }
- })
- _G['MarumEditableSheet_SelectDecal_' .. decalID] = function(obj, ply, alt)
- obj.call("selectDecal", decalID)
- end
- if (buttonIndex % 10 == 0) then coroutine.yield(0) end
- end
-
- for checkID, check in pairs(checks) do
- local posx = check.pos.x
- local posy = check.pos.y
- local checkScale = { x = scale.x * check.size.x, y = 1, z = scale.y * check.size.y }
- local name = "C" .. checkID
- local tooltip = "Select " .. (check.name or name)
- for x = 1, check.array.x do
- for y = 1, check.array.y do
- local arrayID = x + (y - 1) * check.array.x
- local func = "MarumEditableClickCheckbox_" .. checkID .. '_' .. arrayID
- local rotationAdd = 0
- local posMul = 1
- if (flip == "True") then
- rotationAdd = 180
- posMul = -1
- end
- local pos = {
- x = (posx + (x - 1) * check.distance.x) * posMul * scale.x,
- y = height + 0.002,
- z = (posy + (y - 1) * check.distance.y) * posMul * scale.y
- }
- buttonIndex = buttonIndex + 1
- table.insert(lookupCheckIndices[checkID].selectionButtons, {
- index = buttonIndex,
- x = x,
- y = y,
- arrayID = arrayID
- })
- self.createButton({
- label = "",
- tooltip = tooltip,
- click_function = func,
- function_owner = self,
- alignment = 3,
- position = pos,
- width = 1000,
- height = 1000,
- rotation = { x = 0, y = rotationAdd, z = 0 },
- font_size = check.font / 3,
- scale = { x = checkScale.x * 0.25, y = checkScale.y, z = checkScale.z * 0.25 },
- font_color = { r = 1, g = 1, b = 1, a = 1 },
- color = { r = 0, g = 0.5, b = 1, a = 0.5 },
- hover_color = { r = 0, g = 0.5, b = 1, a = 0.8 },
- tab = 0
- })
- _G['MarumEditableClickCheckbox_' .. checkID .. '_' .. arrayID] = function(obj, ply, alt)
- obj.call("selectCheck", { id = checkID, arrayId = arrayID })
- end
- end
- end
- if (buttonIndex % 10 == 0) then coroutine.yield(0) end
- end
-
- UI.setAttribute(getPanelId("Loading"), "active", "False")
-end
-
-function createSelectionHighlight(edit)
- local topLeft = { x = 0, y = 0, z = 0 }
- local topRight = { x = 0, y = 0, z = 0 }
- local bottomLeft = { x = 0, y = 0, z = 0 }
- local bottomRight = { x = 0, y = 0, z = 0 }
- local scale = { x = scale.x, y = 1, z = scale.y }
- local rotation = { x = 0, y = 0, z = 0 }
- if (flip == "True") then
- rotation.y = 180
- end
-
- if (selectedType == "field") then
- local field = fields[selectedId]
- local posx = field.pos.x
- local posy = field.pos.y
- local posMul = 1
- if (flip == "True") then
- posMul = -1
- posy = posy - 0.1
- end
- local x = (selectedArrayId - 1) % field.array.x
- local y = math.floor((selectedArrayId - 1) / field.array.x)
- local gridpos = { x = x * field.distance.x, y = y * field.distance.y }
- bottomLeft = {
- x = (posx - field.size.x / 1000 - 0.1 + gridpos.x) * scale.x * posMul,
- y = height + 0.005,
- z = (posy + field.size.y / 1000 + 0.1 + gridpos.y) * scale.z * posMul
- }
- bottomRight = {
- x = (posx + field.size.x / 1000 + 0.1 + gridpos.x) * scale.x * posMul,
- y = height + 0.005,
- z = (posy + field.size.y / 1000 + 0.1 + gridpos.y) * scale.z * posMul
- }
- topLeft = {
- x = (posx - field.size.x / 1000 - 0.1 + gridpos.x) * scale.x * posMul,
- y = height + 0.005,
- z = (posy - field.size.y / 1000 + gridpos.y) * scale.z * posMul
- }
- topRight = {
- x = (posx + field.size.x / 1000 + 0.1 + gridpos.x) * scale.x * posMul,
- y = height + 0.005,
- z = (posy - field.size.y / 1000 + gridpos.y) * scale.z * posMul
- }
- elseif (selectedType == "decal") then
- local decal = decals[selectedId]
- local posx = decal.pos.x
- local posy = decal.pos.y
- local posMul = 1
- if (flip == "True") then
- posMul = -1
- posy = posy - 0.1
- end
- bottomLeft = {
- x = (posx - decal.scale.x / 2 - 0.1) * scale.x * posMul,
- y = height + 0.005,
- z = (posy + decal.scale.y / 2 + 0.1) * scale.z * posMul
- }
- bottomRight = {
- x = (posx + decal.scale.x / 2 + 0.1) * scale.x * posMul,
- y = height + 0.005,
- z = (posy + decal.scale.y / 2 + 0.1) * scale.z * posMul
- }
- topLeft = {
- x = (posx - decal.scale.x / 2 - 0.1) * scale.x * posMul,
- y = height + 0.005,
- z = (posy - decal.scale.y / 2) * scale.z * posMul
- }
- topRight = {
- x = (posx + decal.scale.x / 2 + 0.1) * scale.x * posMul,
- y = height + 0.005,
- z = (posy - decal.scale.y / 2) * scale.z * posMul
- }
- elseif (selectedType == "check") then
- local check = checks[selectedId]
- local posx = check.pos.x
- local posy = check.pos.y
- local posMul = 1
- if (flip == "True") then
- posMul = -1
- posy = posy - 0.1
- end
- local x = (selectedArrayId - 1) % check.array.x
- local y = math.floor((selectedArrayId - 1) / check.array.x)
- local gridpos = { x = x * check.distance.x, y = y * check.distance.y }
- bottomLeft = {
- x = (posx - check.size.x * 0.25 - 0.1 + gridpos.x) * scale.x * posMul,
- y = height + 0.005,
- z = (posy + check.size.y * 0.25 + 0.1 + gridpos.y) * scale.z * posMul
- }
- bottomRight = {
- x = (posx + check.size.x * 0.25 + 0.1 + gridpos.x) * scale.x * posMul,
- y = height + 0.005,
- z = (posy + check.size.y * 0.25 + 0.1 + gridpos.y) * scale.z * posMul
- }
- topLeft = {
- x = (posx - check.size.x * 0.25 - 0.1 + gridpos.x) * scale.x * posMul,
- y = height + 0.005,
- z = (posy - check.size.y * 0.25 + gridpos.y) * scale.z * posMul
- }
- topRight = {
- x = (posx + check.size.x * 0.25 + 0.1 + gridpos.x) * scale.x * posMul,
- y = height + 0.005,
- z = (posy - check.size.y * 0.25 + gridpos.y) * scale.z * posMul
- }
- end
- if (edit) then
- self.editButton({ index = 0, scale = scale, position = bottomLeft })
- self.editButton({ index = 1, scale = scale, position = topLeft })
- self.editButton({ index = 2, scale = scale, position = bottomRight })
- self.editButton({ index = 3, scale = scale, position = topRight })
- else
- local label = "┗"
- if (flip == "True") then label = "┓" end
- self.createButton({
- click_function = 'null',
- function_owner = self,
- label = label,
- position = bottomLeft,
- rotation = rotation,
- scale = scale,
- width = 0,
- height = 0,
- font_size = 200,
- font_color = { r = 0, g = 0.5, b = 1, a = 100 },
- color = { r = 0, g = 0, b = 0, a = 0.01 },
- })
- label = "┏"
- if (flip == "True") then label = "┛" end
- self.createButton({
- click_function = 'null',
- function_owner = self,
- label = label,
- position = topLeft,
- rotation = rotation,
- scale = scale,
- width = 0,
- height = 0,
- font_size = 200,
- font_color = { r = 0, g = 0.5, b = 1, a = 100 },
- color = { r = 0, g = 0, b = 0, a = 0.01 },
- })
- label = "┛"
- if (flip == "True") then label = "┏" end
- self.createButton({
- click_function = 'null',
- function_owner = self,
- label = label,
- position = bottomRight,
- rotation = rotation,
- scale = scale,
- width = 0,
- height = 0,
- font_size = 200,
- font_color = { r = 0, g = 0.5, b = 1, a = 100 },
- color = { r = 0, g = 0, b = 0, a = 0.01 },
- })
- label = "┓"
- if (flip == "True") then label = "┗" end
- self.createButton({
- click_function = 'null',
- function_owner = self,
- label = label,
- position = topRight,
- rotation = rotation,
- scale = scale,
- width = 0,
- height = 0,
- font_size = 200,
- font_color = { r = 0, g = 0.5, b = 1, a = 100 },
- color = { r = 0, g = 0, b = 0, a = 0.01 },
- })
- buttonIndex = buttonIndex + 4
- end
-end
-
-function selectField(args)
- selectedId = args.id
- selectedArrayId = args.arrayId
- selectedType = "field"
- createSelectionHighlight(true)
- UI.hide(attrId("EmptyPrompt"))
- UI.show(attrId("SelectionPanel"))
- refreshEditPanel()
-end
-
-function selectDecal(id)
- selectedId = id
- selectedType = "decal"
- createSelectionHighlight(true)
- UI.hide(attrId("EmptyPrompt"))
- UI.show(attrId("SelectionPanel"))
- refreshEditPanel()
-end
-
-function selectCheck(args)
- selectedId = args.id
- selectedArrayId = args.arrayId
- selectedType = "check"
- createSelectionHighlight(true)
- UI.hide(attrId("EmptyPrompt"))
- UI.show(attrId("SelectionPanel"))
- refreshEditPanel()
-end
-
-function refreshEditPanel()
- local page = selectedId
- local subpages = 0
- if (selectedType == "field") then
- local field = fields[selectedId]
- local name = ""
- if (field.name ~= "" and field.name ~= nil) then
- name = " - " .. field.name
- end
- local value = field.value[selectedArrayId]
- subpages = field.array.x * field.array.y
- local sub = ""
- if (subpages > 1) then
- sub = ";" .. selectedArrayId
- end
- UI.setAttribute(attrId("Field/ID"), "text", "Text #" .. tostring(selectedId) .. sub .. name .. "")
- UI.setAttribute(attrId("Field/name"), "text", field.name)
- UI.setAttribute(attrId("Field/content"), "text", value or "")
- UI.setAttribute(attrId("Field/font"), "text", field.font)
- UI.setAttribute(attrId("Field/pos/x"), "text", field.pos.x)
- UI.setAttribute(attrId("Field/pos/y"), "text", field.pos.y)
- UI.setAttribute(attrId("Field/size/x"), "text", field.size.x)
- UI.setAttribute(attrId("Field/size/y"), "text", field.size.y)
- UI.setAttribute(attrId("Field/array/x"), "text", field.array.x)
- UI.setAttribute(attrId("Field/array/y"), "text", field.array.y)
- UI.setAttribute(attrId("Field/distance/x"), "text", field.distance.x)
- UI.setAttribute(attrId("Field/distance/y"), "text", field.distance.y)
-
- local textColor = "rgba(" .. field.textColor.r .. "," .. field.textColor.g .. "," .. field.textColor.b .. ",1)"
- local textColor2 = "rgba(" ..
- (field.textColor.r * 0.5 + 0.2) .. "," .. (field.textColor.g * 0.5 + 0.2) ..
- "," .. (field.textColor.b * 0.5 + 0.2) .. ",1)"
- UI.setAttribute(attrId("Field/textColor"), "colors", textColor ..
- "|" .. textColor2 .. "|" .. textColor2 .. "|" .. textColor)
- UI.setAttribute(attrId("Field/textColor/a"), "percentage", field.textColor.a * 100)
-
- local fieldColor = "rgba(" .. field.fieldColor.r .. "," .. field.fieldColor.g .. "," .. field.fieldColor.b ..
- ",1)"
- local fieldColor2 = "rgba(" ..
- (field.fieldColor.r * 0.5 + 0.2) .. "," .. (field.fieldColor.g * 0.5 + 0.2) ..
- "," .. (field.fieldColor.b * 0.5 + 0.2) .. ",1)"
- UI.setAttribute(attrId("Field/fieldColor"), "colors",
- fieldColor .. "|" .. fieldColor2 .. "|" .. fieldColor2 .. "|" .. fieldColor)
- UI.setAttribute(attrId("Field/fieldColor/a"), "percentage", field.fieldColor.a * 100)
-
- UI.setAttribute(attrId("Field/counter"), "isOn", field.counter == "True")
- UI.setAttribute(attrId("Field/vsum"), "isOn", field.vsum == "True")
- UI.setAttribute(attrId("Field/locked"), "isOn", field.locked == "True")
-
- local role = 0
- if (field.role ~= nil) then
- if (field.role:find("name")) then
- role = 1
- elseif (field.role:find("desc")) then
- role = 2
- end
- end
- UI.setAttribute(attrId("Field/role"), "value", role)
-
- local tooltip = 0
- if (field.tooltip ~= nil) then
- if (field.tooltip:find("name")) then
- tooltip = 1
- elseif (field.tooltip:find("content")) then
- tooltip = 2
- end
- end
- UI.setAttribute(attrId("Field/tooltip"), "value", tooltip)
-
- local align = 0
- if (field.align == 3) then
- align = 1
- elseif (field.align == 4) then
- align = 2
- end
- UI.setAttribute(attrId("Field/align"), "value", align)
-
- UI.hide(attrId("CheckPanel"))
- UI.hide(attrId("DecalPanel"))
- UI.show(attrId("FieldPanel"))
- elseif (selectedType == "check") then
- local check = checks[selectedId]
- local name = ""
- if (check.name ~= "" and check.name ~= "") then
- name = " - " .. check.name
- end
- subpages = check.array.x * check.array.y
- local sub = ""
- if (subpages > 1) then
- sub = ";" .. selectedArrayId
- end
- UI.setAttribute(attrId("Check/ID"), "text", "Checkbox #" .. tostring(selectedId) .. sub .. name .. "")
- UI.setAttribute(attrId("Check/name"), "text", check.name)
- UI.setAttribute(attrId("Check/font"), "text", check.font)
- UI.setAttribute(attrId("Check/pos/x"), "text", check.pos.x)
- UI.setAttribute(attrId("Check/pos/y"), "text", check.pos.y)
- UI.setAttribute(attrId("Check/size/x"), "text", check.size.x)
- UI.setAttribute(attrId("Check/size/y"), "text", check.size.y)
- UI.setAttribute(attrId("Check/array/x"), "text", check.array.x)
- UI.setAttribute(attrId("Check/array/y"), "text", check.array.y)
- UI.setAttribute(attrId("Check/distance/x"), "text", check.distance.x)
- UI.setAttribute(attrId("Check/distance/y"), "text", check.distance.y)
-
- local tc = check.textColorOn or check.textColor
- local textColor = "rgba(" .. tc.r .. "," .. tc.g .. "," .. tc.b .. ",1)"
- local textColor2 = "rgba(" .. (tc.r * 0.5 + 0.2) .. "," .. (tc.g * 0.5 + 0.2) .. "," .. (tc.b * 0.5 + 0.2) ..
- ",1)"
- UI.setAttribute(attrId("Check/textColorOn"), "colors",
- textColor .. "|" .. textColor2 .. "|" .. textColor2 .. "|" .. textColor)
- UI.setAttribute(attrId("Check/textColorOn/a"), "percentage", tc.a * 100)
-
- local tc = check.textColorOff or check.textColor
- local textColor = "rgba(" .. tc.r .. "," .. tc.g .. "," .. tc.b .. ",1)"
- local textColor2 = "rgba(" .. (tc.r * 0.5 + 0.2) .. "," .. (tc.g * 0.5 + 0.2) .. "," .. (tc.b * 0.5 + 0.2) ..
- ",1)"
- UI.setAttribute(attrId("Check/textColorOff"), "colors",
- textColor .. "|" .. textColor2 .. "|" .. textColor2 .. "|" .. textColor)
- UI.setAttribute(attrId("Check/textColorOff/a"), "percentage", tc.a * 100)
-
- local tc = check.textColorDisabled or check.textColor
- local textColor = "rgba(" .. tc.r .. "," .. tc.g .. "," .. tc.b .. ",1)"
- local textColor2 = "rgba(" .. (tc.r * 0.5 + 0.2) .. "," .. (tc.g * 0.5 + 0.2) .. "," .. (tc.b * 0.5 + 0.2) ..
- ",1)"
- UI.setAttribute(attrId("Check/textColorDisabled"), "colors",
- textColor .. "|" .. textColor2 .. "|" .. textColor2 .. "|" .. textColor)
- UI.setAttribute(attrId("Check/textColorDisabled/a"), "percentage", tc.a * 100)
-
- local checkColor = "rgba(" .. check.checkColor.r .. "," .. check.checkColor.g .. "," .. check.checkColor.b ..
- ",1)"
- local checkColor2 = "rgba(" ..
- (check.checkColor.r * 0.5 + 0.2) .. "," .. (check.checkColor.g * 0.5 + 0.2) ..
- "," .. (check.checkColor.b * 0.5 + 0.2) .. ",1)"
- UI.setAttribute(attrId("Check/checkColor"), "colors",
- checkColor .. "|" .. checkColor2 .. "|" .. checkColor2 .. "|" .. checkColor)
- UI.setAttribute(attrId("Check/checkColor/a"), "percentage", check.checkColor.a * 100)
-
- UI.setAttribute(attrId("Check/characters/empty"), "text", check.characters.empty)
- UI.setAttribute(attrId("Check/characters/filled"), "text", check.characters.filled)
- UI.setAttribute(attrId("Check/characters/disabled"), "text", check.characters.disabled)
-
- if (check.separateColors == "True") then
- UI.setAttribute(attrId("CheckOnColorLabel"), "text", "On color")
- UI.setAttribute(attrId("CheckOffColorRow"), "active", "True")
- UI.setAttribute(attrId("CheckDisabledColorRow"), "active", "True")
- UI.setAttribute(attrId("CheckSeparateColorsSpacer1"), "active", "False")
- UI.setAttribute(attrId("CheckSeparateColorsSpacer2"), "active", "False")
- else
- UI.setAttribute(attrId("CheckOnColorLabel"), "text", "Color")
- UI.setAttribute(attrId("CheckOffColorRow"), "active", "False")
- UI.setAttribute(attrId("CheckDisabledColorRow"), "active", "False")
- UI.setAttribute(attrId("CheckSeparateColorsSpacer1"), "active", "True")
- UI.setAttribute(attrId("CheckSeparateColorsSpacer2"), "active", "True")
- end
- UI.setAttribute(attrId("Check/separateColors"), "isOn", check.separateColors == "True")
- UI.setAttribute(attrId("Check/fillFromDisabled"), "isOn", check.fillFromDisabled == "True")
-
- local option = 0
- if (check.value[selectedArrayId] == 0) then option = 2 end
- if (check.value[selectedArrayId] == 1) then option = 0 end
- if (check.value[selectedArrayId] == 2) then option = 1 end
- UI.setAttribute(attrId("Check/value"), "value", option)
-
- local tooltip = 0
- if (check.tooltip ~= nil) then
- if (check.tooltip:find("name")) then
- tooltip = 1
- elseif (check.tooltip:find("hint")) then
- tooltip = 2
- end
- end
- UI.setAttribute(attrId("Check/tooltip"), "value", tooltip)
- UI.setAttribute(attrId("Check/locked"), "isOn", check.locked == "True")
-
- UI.hide(attrId("DecalPanel"))
- UI.hide(attrId("FieldPanel"))
- UI.show(attrId("CheckPanel"))
-
- page = selectedId + #fields
- elseif (selectedType == "decal") then
- local decal = decals[selectedId]
- local slot = 1
- UI.setAttribute(attrId("Decal/ID"), "text", "Decal #" .. tostring(selectedId) .. "")
- UI.setAttribute(attrId("Decal/name"), "text", decal.name)
- UI.setAttribute(attrId("Decal/url"), "text", decal.url)
- UI.setAttribute(attrId("Decal/pos/x"), "text", decal.pos.x)
- UI.setAttribute(attrId("Decal/pos/y"), "text", decal.pos.y)
- UI.setAttribute(attrId("Decal/scale/x"), "text", decal.scale.x)
- UI.setAttribute(attrId("Decal/scale/y"), "text", decal.scale.y)
- UI.setAttribute(attrId("Decal/rotation"), "text", decal.rotation)
-
- UI.setAttribute(attrId("Decal/locked"), "isOn", decal.locked == "True")
-
- local tooltip = 0
- if (decal.tooltip ~= nil) then
- if (decal.tooltip:find("name")) then
- tooltip = 1
- elseif (decal.tooltip:find("hint")) then
- tooltip = 2
- end
- end
- UI.setAttribute(attrId("Decal/tooltip"), "value", tooltip)
-
- UI.hide(attrId("CheckPanel"))
- UI.hide(attrId("FieldPanel"))
- UI.show(attrId("DecalPanel"))
- page = selectedId + #fields + #checks
- else
- UI.show(attrId("EmptyPrompt"))
- UI.hide(attrId("SelectionPanel"))
- end
-
- -- Pages
- local pageCount = getPageCount()
- UI.setAttribute(attrId("LastPage"), "interactable", tostring(page < pageCount))
- UI.setAttribute(attrId("NextPage"), "interactable", tostring(page < pageCount))
- UI.setAttribute(attrId("PreviousPage"), "interactable", tostring(page > 1))
- UI.setAttribute(attrId("FirstPage"), "interactable", tostring(page > 1))
- if (subpages > 1) then
- UI.setAttribute(attrId("Pages"), "text", page .. " (" .. selectedArrayId .. "/" .. subpages .. ") / " .. pageCount)
- else
- UI.setAttribute(attrId("Pages"), "text", page .. " / " .. pageCount)
- end
-end
-
-function commit(ply)
- local codeSplit = split(self.script_code, "$")
- local uncutLines = get_line_count(codeSplit[1])
- local cutLines = get_line_count(codeSplit[2] .. codeSplit[3])
- broadcastToColor("Layout commited. Code reduced from " .. (uncutLines + cutLines + 1) .. " lines to " .. uncutLines,
- ply)
- if (Global.getVar("MarumEditableSheetGUID", self.guid)) then
- Global.setVar("MarumEditableSheetGUID", nil)
- end
- wasCommitted = true
- updateSave()
- self.script_code = codeSplit[1]
- self.reload()
-end
-
-function onToggleSheetLocked(obj, ply, value, selected)
- sheetLocked = not sheetLocked
- updateSave()
-end
-
-function closePanel(ply, value, id)
- if (editingSheet) then
- editingSheet = false
- refresh()
- end
- UI.setAttribute(getPanelId("main"), "active", "False")
-end
-
-function forceClosePanel()
- if (editingSheet) then
- editingSheet = false
- refresh()
- end
-end
-
-function getPageCount()
- return #fields + #checks + #decals
-end
-
-function getPanelId(panel)
- return "MarumEditableSheet/" .. panel
-end
-
-function showEditPanel(ply, value, id)
- createPanelIfNecessary(ply)
- waitForUiLoaded(function()
- UI.setAttribute(getPanelId("main"), "active", "True")
- UI.setAttribute(getPanelId("main"), "visibility", ply)
- if (selectedId == 0) then
- UI.show(attrId("EmptyPrompt"))
- UI.hide(attrId("SelectionPanel"))
- else
- UI.hide(attrId("EmptyPrompt"))
- UI.show(attrId("SelectionPanel"))
- end
- editingSheet = true
- local forcedSelectFirst = false
- if (selectedId == 0) then
- if (#fields > 0) then
- selectedId = 1
- selectedArrayId = 1
- selectedType = "field"
- forcedSelectFirst = true
- elseif (#checks > 0) then
- selectedId = 1
- selectedArrayId = 1
- selectedType = "check"
- forcedSelectFirst = true
- elseif (#decals > 0) then
- selectedId = 1
- selectedType = "decal"
- forcedSelectFirst = true
- end
- end
- refresh()
- if (forcedSelectFirst) then
- UI.hide(attrId("EmptyPrompt"))
- UI.show(attrId("SelectionPanel"))
- end
- refreshEditPanel()
- end)
-end
-
-function showCommitPanel(ply, value, id)
- local previousGUID = Global.getVar("MarumEditableSheetGUID")
- if (previousGUID) then
- local obj = getObjectFromGUID(previousGUID)
- if (obj ~= nil) then
- getObjectFromGUID(previousGUID).call("closePanel")
- end
- end
- Player[ply].showConfirmDialog("Do you want to lock the current layout and remove editing related code? " ..
- "You will still be able to change the contents of unlocked fields.", commit)
-end
-
-function removeMESPanel()
- local tbl = UI.getXmlTable()
- local removing = false
- local newTable = {}
- for k, v in pairs(tbl) do
- local isTag = false
- if (v.attributes ~= nil) then
- if (v.attributes.id == "MESStart") then
- removing = true
- isTag = true
- elseif (v.attributes.id == "MESEnd") then
- removing = false
- isTag = true
- end
- end
- if (not isTag and not removing) then
- table.insert(newTable, v)
- end
- end
- UI.setXmlTable({ newTable })
-end
-
-function createPanelIfNecessary(color)
- local guid = self.getGUID()
- local previousGUID = Global.getVar("MarumEditableSheetGUID")
- if (guid ~= previousGUID) then
- if (previousGUID ~= nil) then
- local obj = getObjectFromGUID(previousGUID)
- if (obj) then
- getObjectFromGUID(previousGUID).call("forceClosePanel")
- end
- removeMESPanel()
- end
- waitForUiLoaded(createMainPanel)
- end
-end
-
-function createMainPanel()
- local guid = self.getGUID()
- Global.setVar("MarumEditableSheetGUID", guid)
- local xml = [[
-
-
- Editable Sheet - by Marum
-
-
-
-
-
-
-
- Document settings: |
- Height |
- ]] ..
- height .. [[ |
- Scale |
- ]] ..
- scale.x .. [[ |
- ]] ..
- scale.y .. [[ |
- |
- |
- Lock everything |
- Flip |
-
-
-
-
-
-
-
-
-
-
-
-
- ]] .. selectedId ..
- " / " .. getPageCount() .. [[
-
-
-
-
- Add a new element using the buttons above. You can then select elements by clicking on them on the sheet, or with the navigation buttons above.
-
-
- ]] .. getFieldPanel() .. [[
- ]] .. getCheckPanel() .. [[
- ]] .. getDecalPanel() .. [[
-
-
-
-
- Loading...
-
-
-
- ]]
- UI.setXml(UI.getXml() .. xml)
-end
-
-function onScaleReset()
- scale = { x = math.floor(100 / self.getScale().x) / 100, y = math.floor(100 / self.getScale().z) / 100 }
- UI.setAttribute(attrId("ScaleX"), "text", scale.x)
- UI.setAttribute(attrId("ScaleY"), "text", scale.y)
- refreshAllPositionsAndSize()
- refreshEditPanel()
-end
-
-function firstPage()
- if (#fields > 0) then
- selectField({ id = 1, arrayId = 1 })
- elseif (#checks > 0) then
- selectCheck({ id = 1, arrayId = 1 })
- elseif (#decals > 0) then
- selectDecal(1)
- end
-end
-
-function previousPage()
- if (selectedType == "decal") then
- if (selectedId > 1) then
- selectedId = selectedId - 1
- selectDecal(selectedId)
- else
- if (#checks > 0) then
- selectedType = "check"
- selectedId = #checks
- selectCheck({ id = selectedId, arrayId = checks[selectedId].array.x * checks[selectedId].array.y })
- elseif (#fields > 0) then
- selectedType = "field"
- selectedId = #fields
- selectField({ id = selectedId, arrayId = fields[selectedId].array.x * fields[selectedId].array.y })
- end
- end
- elseif (selectedType == "check") then
- if (selectedArrayId > 1) then
- selectedArrayId = selectedArrayId - 1
- selectCheck({ id = selectedId, arrayId = selectedArrayId })
- elseif (selectedId > 1) then
- selectedId = selectedId - 1
- selectCheck({ id = selectedId, arrayId = checks[selectedId].array.x * checks[selectedId].array.y })
- else
- if (#fields > 0) then
- selectedType = "field"
- selectedId = #fields
- selectField({ id = selectedId, arrayId = fields[selectedId].array.x * fields[selectedId].array.y })
- end
- end
- elseif (selectedType == "field") then
- if (selectedArrayId > 1) then
- selectedArrayId = selectedArrayId - 1
- selectField({ id = selectedId, arrayId = selectedArrayId })
- elseif (selectedId > 1) then
- selectedId = selectedId - 1
- selectField({ id = selectedId, arrayId = fields[selectedId].array.x * fields[selectedId].array.y })
- end
- end
-end
-
-function nextPage()
- if (selectedType == "field") then
- if (fields[selectedId].array.x * fields[selectedId].array.y > selectedArrayId) then
- selectedArrayId = selectedArrayId + 1
- selectField({ id = selectedId, arrayId = selectedArrayId })
- elseif (#fields > selectedId) then
- selectedId = selectedId + 1
- selectField({ id = selectedId, arrayId = 1 })
- else
- if (#checks > 0) then
- selectedType = "check"
- selectedId = 1
- selectCheck({ id = selectedId, arrayId = 1 })
- elseif (#decals > 0) then
- selectedType = "decal"
- selectedId = 1
- selectDecal(1)
- end
- end
- elseif (selectedType == "check") then
- if (checks[selectedId].array.x * checks[selectedId].array.y > selectedArrayId) then
- selectedArrayId = selectedArrayId + 1
- selectCheck({ id = selectedId, arrayId = selectedArrayId })
- elseif (#checks > selectedId) then
- selectedId = selectedId + 1
- selectCheck({ id = selectedId, arrayId = 1 })
- else
- if (#decals > 0) then
- selectedType = "decal"
- selectedId = 1
- selectDecal(1)
- end
- end
- elseif (selectedType == "decal") then
- if (#decals > selectedId) then
- selectedId = selectedId + 1
- selectDecal(selectedId)
- end
- end
-end
-
-function lastPage()
- if (#decals > 0) then
- selectDecal(#decals)
- elseif (#checks > 0) then
- local last = checks[#checks]
- selectCheck({ id = #checks, arrayId = last.array.x * last.array.y })
- elseif (#fields > 0) then
- local last = fields[#fields]
- selectField({ id = #fields, arrayId = last.array.x * last.array.y })
- end
-end
-
-function onNudgeChanged(ply, value, id)
- nudgeDistance = value
- UI.setAttribute(attrId("Field_nudge"), "text", nudgeDistance)
- UI.setAttribute(attrId("Check_nudge"), "text", nudgeDistance)
- UI.setAttribute(attrId("Decal_nudge"), "text", nudgeDistance)
- updateSave()
-end
-
-function compareString(str, list)
- for k, v in pairs(list) do
- if (str == v) then return true end
- end
-end
-
-function onValueEdited(ply, value, id)
- local spl = split(id, "/")
- local parameter = spl[2]
- local tbl = nil
- if (selectedType == "field") then tbl = fields end
- if (selectedType == "check") then tbl = checks end
- if (selectedType == "decal") then tbl = decals end
- if (parameter == "content") then
- tbl[selectedId].value[selectedArrayId] = value
- else
- if (#spl > 2) then
- tbl[selectedId][parameter][spl[3]] = value
- else
- tbl[selectedId][parameter] = value
- end
- end
- updateSave()
-
- if (selectedType == "field") then
- if (compareString(parameter, { "pos", "distance", "size" })) then
- updateFieldPositionAndSize(selectedId)
- elseif (compareString(parameter, { "name", "content", "tooltip" })) then
- updateFieldNameContentAndTooltip(selectedId)
- elseif (parameter == "font") then
- updateFieldFontAndColor(selectedId)
- else
- refresh()
- end
- elseif (selectedType == "check") then
- if (compareString(parameter, { "pos", "distance", "size" })) then
- updateCheckPositionAndSize(selectedId)
- elseif (parameter == "name") then
- updateCheckNameContentAndTooltip(selectedId)
- elseif (parameter == "font") then
- updateCheckFontAndColor(selectedId)
- else
- refresh()
- end
- elseif (selectedType == "decal") then
- if (compareString(parameter, { "pos", "scale", "rotation" })) then
- updateDecalPositionAndSize(selectedId)
- elseif (parameter == "url") then
- createDecals()
- else
- refresh()
- end
- end
-end
-
-function updateFieldPositionAndSize(fieldID)
- local field = fields[fieldID]
- local lookup = lookupFieldIndices[fieldID]
- local fieldScale = { x = -scale.x, y = 1, z = scale.y }
- local flipped = 1
- local rotation = { x = 0, y = 0, z = 180 }
- if (flip == "True") then
- rotation.y = 180
- flipped = -1
- end
- local fontSize = math.min(field.size.y - 24, field.font)
- for k, v in pairs(lookup.inputs) do
- local pos = getFieldPosition(fieldID, v.x, v.y)
- self.editInput({
- index = v.index - 1,
- position = pos,
- scale = fieldScale,
- width = field.size.x,
- height = field.size.y,
- font_size = fontSize,
- rotation = rotation
- })
- end
- for k, v in pairs(lookup.totals) do
- local pos = getFieldPosition(fieldID, v.x, field.array.y + 1)
- self.editInput({
- index = v.index - 1,
- position = pos,
- scale = fieldScale,
- width = field.size.x,
- height = field.size.y,
- rotation = rotation,
- font_size = fontSize
- })
- end
- for k, v in pairs(lookup.counterButtons) do
- local pos = getFieldPosition(fieldID, v.x, v.y)
- local offset = (field.size.x + fontSize * 0.75) / 1000 * scale.x
- self.editButton({
- index = v.index - 1,
- position = { x = pos.x + offset * v.side * flipped, y = pos.y, z = pos.z },
- scale = fieldScale,
- rotation = rotation
- })
- end
- for k, v in pairs(lookup.selectionButtons) do
- local pos = getFieldPosition(fieldID, v.x, v.y)
- self.editButton({
- index = v.index - 1,
- position = pos,
- scale = { x = scale.x * 0.25, y = 1, z = scale.y * 0.25 },
- width = field.size.x * 4 + 200,
- height = field.size.y * 4 + 200
- })
- end
- createSelectionHighlight(true)
-end
-
-function updateFieldFontAndColor(fieldID)
- local field = fields[fieldID]
- local fontColor = getFieldTextColor(fieldID)
- local fontSize = math.min(field.size.y - 24, field.font)
- local lookup = lookupFieldIndices[fieldID]
- for k, v in pairs(lookup.inputs) do
- -- Do not question the ways of the tabletop, as if it requests for font_color to be assigned twice, then it shall be so
- self.editInput({
- index = v.index - 1,
- font_color = fontColor
- })
- self.editInput({
- index = v.index - 1,
- font_size = fontSize,
- color = field.fieldColor,
- font_color = fontColor
- })
- self.editInput({
- index = v.index - 1
- })
- end
- for k, v in pairs(lookup.counterButtons) do
- self.editButton({
- index = v.index - 1,
- color = field.fieldColor,
- font_color = fontColor,
- font_size = fontSize / 2
- })
- end
- for k, v in pairs(lookup.totals) do
- self.editInput({
- index = v.index - 1,
- font_size = fontSize,
- color = field.fieldColor,
- font_color = fontColor
- })
- end
-end
-
-function updateCheckNameContentAndTooltip(checkID)
- local check = checks[checkID]
- for k, v in pairs(lookupCheckIndices[checkID].buttons) do
- local label = getCheckLabelAndColor(checkID, v.arrayID)
- self.editButton({ index = v.index - 1, label = label, tooltip = getCheckTooltip(checkID) })
- end
- local name = "C" .. checkID
- local tooltip = "Select " .. (check.name or name)
- for k, v in pairs(lookupCheckIndices[checkID].selectionButtons) do
- self.editButton({ index = v.index - 1, tooltip = tooltip })
- end
-end
-
-function updateCheckPositionAndSize(checkID)
- local check = checks[checkID]
- local lookup = lookupCheckIndices[checkID]
- local rotation = { x = 0, y = 0, z = 0 }
- if (flip == "True") then
- rotation.y = 180
- end
- for k, v in pairs(lookup.buttons) do
- local pos = getCheckPosition(checkID, v.x, v.y)
- local checkScale = { x = scale.x * check.size.x, y = 1, z = scale.y * check.size.y }
- self.editButton({ index = v.index - 1, position = pos, scale = checkScale, rotation = rotation })
- end
- for k, v in pairs(lookup.selectionButtons) do
- local pos = getCheckPosition(checkID, v.x, v.y)
- local checkScale = { x = scale.x * check.size.x * 0.25, y = 1, z = scale.y * check.size.y * 0.25 }
- self.editButton({ index = v.index - 1, position = pos, scale = checkScale })
- end
- createSelectionHighlight(true)
-end
-
-function updateCheckFontAndColor(checkID)
- local check = checks[checkID]
- for k, v in pairs(lookupCheckIndices[checkID].buttons) do
- local label, color, alphaCorrectedColor = getCheckLabelAndColor(checkID, v.arrayID)
- -- Do not question the ways of the tabletop, as if it requests for font_color to be assigned twice, then it shall be so
- self.editButton({
- index = v.index - 1,
- font_size = check.font,
- color = check.checkColor,
- font_color = alphaCorrectedColor
- })
- end
-end
-
-function updateDecalPositionAndSize(decalID)
- local decal = decals[decalID]
- local lookup = lookupDecalIndices[decalID]
- local decalScale = {
- x = decal.scale.x * scale.x * 0.25,
- y = decal.scale.y * scale.y * 0.25,
- z = decal.scale.y *
- scale.y * 0.25
- }
- for k, v in pairs(lookup.inputs) do
- local pos = getDecalPosition(decalID, v.x, v.y)
- self.editInput({ index = v.index - 1, position = pos, scale = decalScale, rotation = decal.rotation })
- end
- for k, v in pairs(lookup.selectionButtons) do
- local pos = getDecalPosition(decalID, v.x, v.y)
- self.editButton({ index = v.index - 1, position = pos, scale = decalScale })
- end
- createSelectionHighlight(true)
- createDecals()
-end
-
-function onCheckValueEdited(ply, value, id)
- local spl = split(id, "/")
- local checkParameter = spl[2]
- if (#spl > 2) then
- checks[selectedId][checkParameter][spl[3]] = value
- else
- checks[selectedId][checkParameter] = value
- end
-
- if (compareString(checkParameter, { "pos", "size" })) then
- updateCheckPositionAndSize(selectedId)
- elseif (checkParameter == "characters") then
- updateCheckNameContentAndTooltip(selectedId)
- else
- refresh()
- end
-
- updateSave()
-end
-
-function onDecalValueEdited(ply, value, id)
- local spl = split(id, "/")
- local decalID = tonumber(spl[1])
- local decalParameter = spl[2]
- if (#spl > 2) then
- decals[decalID][decalParameter][spl[3]] = value
- else
- decals[decalID][decalParameter] = value
- end
-
- updateSave()
- refresh()
-end
-
-function onToggleChanged(ply, value, id)
- local spl = split(id, "/")
- local tbl = nil
- if (selectedType == "field") then tbl = fields end
- if (selectedType == "check") then tbl = checks end
- if (selectedType == "decal") then tbl = decals end
- tbl[selectedId][spl[2]] = value
- if (spl[2] == "separateColors") then
- updateCheckFontAndColor(selectedId)
- refreshEditPanel()
- else
- if (not compareString(spl[2], { "locked", "fillFromDisabled" })) then
- refresh()
- end
- end
- updateSave()
-end
-
-function onFieldDropdownSelected(ply, option, id)
- local spl = split(id, "/")
- local parameterID = spl[2]
- local shouldRefresh = false
- if (parameterID == "align") then
- shouldRefresh = true
- if (option == "Auto") then
- option = 1
- elseif (option == "Left") then
- option = 2
- elseif (option == "Center") then
- option = 3
- elseif (option == "Right") then
- option = 4
- elseif (option == "Justified") then
- option = 5
- end
- end
- fields[selectedId][parameterID] = option
- updateFieldFontAndColor(selectedId)
- updateSave()
- if (shouldRefresh) then
- -- I did my best to not refresh here, but it seems like editInput doesn't care about alignment
- refresh()
- end
-end
-
-function onCheckDropdownSelected(ply, option, id)
- local spl = split(id, "/")
- local parameterID = spl[2]
- if (parameterID == "value") then
- local value = 0
- if (option == "Off") then value = 1 elseif (option == "On") then value = 2 end
- local check = checks[selectedId]
- check.value[selectedArrayId] = value
- updateCheckNameContentAndTooltip(selectedId)
- updateCheckFontAndColor(selectedId)
- updateSave()
- elseif (parameterID == "tooltip") then
- checks[selectedId].tooltip = option
- updateSave()
- else
- checks[selectedId][parameterID] = option
- updateSave()
- refresh()
- end
-end
-
-function onDecalDropdownSelected(ply, option, id)
- local spl = split(id, "/")
- local parameterID = spl[2]
- if (parameterID == "tooltip") then
- decals[selectedId].tooltip = option
- updateSave()
- else
- decals[selectedId][parameterID] = option
- updateSave()
- refresh()
- end
-end
-
-function onColorButtonPressed(ply, value, id)
- local spl = split(id, "/")
- local parameterID = spl[2]
- local tbl = nil
- if (selectedType == "field") then tbl = fields end
- if (selectedType == "check") then tbl = checks end
- local startingColor = tbl[selectedId][parameterID]
- if (startingColor == nil) then
- if (parameterID:find("textColor")) then
- startingColor = tbl[selectedId].textColor
- end
- end
-
- ply.showColorDialog(startingColor,
- function(color, player_color)
- tbl[selectedId][parameterID] = color
- if (selectedType == "field") then
- updateFieldFontAndColor(selectedId)
- elseif (selectedType == "check") then
- updateCheckFontAndColor(selectedId)
- end
- local c = "rgba(" .. color.r .. "," .. color.g .. "," .. color.b .. ",1)"
- local c2 = "rgba(" .. (color.r * 0.5 + 0.2) .. "," .. (color.g * 0.5 + 0.2) .. "," ..
- (color.b * 0.5 + 0.2) .. ",1)"
- UI.setAttribute(id, "colors", c .. "|" .. c2 .. "|" .. c2 .. "|" .. c)
- UI.setAttribute(id .. "/a", "percentage", color.a * 100)
- updateSave()
- end
- )
-end
-
-function refreshAllPositionsAndSize()
- for k, v in pairs(fields) do
- updateFieldPositionAndSize(k)
- end
- for k, v in pairs(checks) do
- updateCheckPositionAndSize(k)
- end
- for k, v in pairs(decals) do
- updateDecalPositionAndSize(k)
- end
-end
-
-function onScaleChangedX(ply, value)
- scale.x = value
- updateSave()
- refreshAllPositionsAndSize()
-end
-
-function onScaleChangedY(ply, value)
- scale.y = value
- updateSave()
- refreshAllPositionsAndSize()
-end
-
-function onHeightChanged(ply, value)
- height = value
- updateSave()
- refreshAllPositionsAndSize()
-end
-
-function onFlip(ply, value)
- flip = value
- updateSave()
- refreshAllPositionsAndSize()
- local label = "┗"
- if (flip == "True") then label = "┓" end
- self.editButton({ index = 0, label = label })
- label = "┏"
- if (flip == "True") then label = "┛" end
- self.editButton({ index = 1, label = label })
- label = "┛"
- if (flip == "True") then label = "┏" end
- self.editButton({ index = 2, label = label })
- label = "┓"
- if (flip == "True") then label = "┗" end
- self.editButton({ index = 3, label = label })
-end
-
-function onCheckToggleChanged(ply, value, id)
- local spl = split(id, "/")
- local checkID = tonumber(spl[1])
- checks[checkID][spl[2]] = value
-
- updateSave()
- refresh()
-end
-
-function onDecalToggleChanged(ply, value, id)
- local spl = split(id, "/")
- local decalID = tonumber(spl[1])
- decals[decalID][spl[2]] = value
-
- updateSave()
- refresh()
-end
-
-function getDeselectButton(panelID)
- if (selectedId > 0) then
- return [[
]]
- end
- return ""
-end
-
-function deselect()
- selectedId = 0
- selectedType = ""
- refresh()
-end
-
-function correctCheckboxesAndDecals()
- for decalID, decal in pairs(decals) do
- decal.pos.x = decal.pos.x / scale.x
- decal.pos.y = decal.pos.y / scale.y
- end
- for checkID, check in pairs(checks) do
- check.pos.x = check.pos.x / scale.x
- check.pos.y = check.pos.y / scale.y
- check.distance.x = check.distance.x / scale.x
- check.distance.y = check.distance.y / scale.y
- end
- refresh()
-end
-
-function attrId(str)
- return "MarumEditorSheetAttribute_" .. str
-end
-
-function getFieldPanel()
- local guid = self.getGUID()
- return [[
-
-
-
-
-
- Text ?
- |
-
-
- |
-
-
- |
-
-
-
-
-
-
-
- Text
- |
-
-
-
- Name
- |
-
-
- |
-
-
-
-
- Content
- |
-
-
- |
-
-
-
-
- Tooltip
- |
-
-
-
-
-
-
- |
-
-
-
-
- On edit
- |
-
-
-
-
-
-
- |
-
-
-
-
-
- Font and color
- |
-
-
-
- Font size
- |
-
-
- |
-
-
-
-
- Align
- |
-
-
-
-
-
-
- |
-
-
-
-
- Text color
- |
-
-
-
-
-
- |
-
-
-
-
- Background Color
- |
-
-
-
-
-
- |
-
-
-
-
-
-
- Position and Size
- |
-
-
-
-
-
-
-
- Nudge
- |
-
-
-
- ]] ..
- nudgeDistance .. [[
- |
-
-
-
-
- |
-
-
- |
-
-
- |
-
-
- |
-
-
-
-
- |
- |
- |
-
-
- |
- |
- |
- |
-
-
- |
- |
- |
-
-
-
- |
-
-
-
- Pos
- |
-
-
- |
-
-
- |
-
-
-
- Size
- |
-
-
- |
-
-
- |
-
-
-
-
-
- Array
- |
-
-
-
- Columns/Rows
- |
-
-
- |
-
-
- |
-
-
-
- Spacing
- |
-
-
- |
-
-
- |
-
-
-
-
-
- Toggles
- |
-
-
-
- Counter
- |
-
- Total sum
- |
-
- Lock
- |
-
-
-
-
-
- ]]
-end
-
-function getCheckPanel()
- local guid = self.getGUID()
- return [[
-
-
-
-
-
- Checkbox ?
- |
-
-
- |
-
-
- |
-
-
-
-
-
-
-
- Checkbox
- |
-
-
-
- Name
- |
-
-
- |
-
-
-
-
- State
- |
-
-
-
-
-
-
- |
-
-
-
-
- Tooltip
- |
-
-
-
-
-
-
- |
-
-
-
-
-
-
-
- Off
- |
-
-
- |
-
- On
- |
-
-
- |
-
- Disabled
- |
-
-
- |
-
-
- |
-
-
-
-
-
-
- Font size
- |
-
-
- |
-
-
-
- Separate colors
- |
-
-
-
- On color
- |
-
-
-
-
-
- |
-
-
-
- Off color
- |
-
-
-
-
-
- |
-
-
-
- Disabled color
- |
-
-
-
-
-
- |
-
-
-
- Background Color
- |
-
-
-
-
-
- |
-
-
-
-
-
-
-
-
- Position and Scale
- |
-
-
-
-
-
-
-
- Nudge
- |
-
-
-
- ]] ..
- nudgeDistance .. [[
- |
-
-
-
-
- |
-
-
- |
-
-
- |
-
-
- |
-
-
-
-
- |
- |
- |
-
-
- |
- |
- |
- |
-
-
- |
- |
- |
-
-
-
- |
-
-
-
- Pos
- |
-
-
- |
-
-
- |
-
-
-
- Scale
- |
-
-
- |
-
-
- |
-
-
-
-
-
- Array
- |
-
-
-
- Columns/Rows
- |
-
-
- |
-
-
- |
-
-
-
- Spacing
- |
-
-
- |
-
-
- |
-
-
-
-
-
- Toggles
- |
-
-
-
- Can fill even if disabled
- |
-
- Lock
- |
-
-
-
-
-
- ]]
-end
-
-function getDecalPanel()
- local guid = self.getGUID()
- return [[
-
-
-
-
-
- Image ?
- |
-
-
- |
-
-
- |
-
-
-
-
-
-
-
- Image
- |
-
-
-
-
- Name
- |
-
-
- |
-
-
-
-
- URL
- |
-
-
- |
-
-
-
-
- Tooltip
- |
-
-
-
-
-
-
- |
-
-
-
-
-
-
-
-
- Position and Scale
- |
-
-
-
-
-
-
-
- Nudge
- |
-
-
-
- ]] ..
- nudgeDistance .. [[
- |
-
-
-
-
- |
-
-
- |
-
-
- |
-
-
- |
-
-
-
-
- |
- |
- |
-
-
- |
- |
- |
- |
-
-
- |
- |
- |
-
-
-
- |
-
-
-
- Pos
- |
-
-
- |
-
-
- |
-
-
-
- Scale
- |
-
-
- |
-
-
- |
-
-
-
- Rotation
- |
-
-
- |
-
-
-
-
-
- Toggles
- |
-
-
-
- Lock
- |
-
-
-
-
-
-
- ]]
-end
-
-function onCheckPresetButton(ply, value, id)
- local pres = { "◌ ○ ●", " ◇ ◆", " □ ■", "/ △ ▴", " ◎ ◉", "- x", " ◾ ✦", " x ♥" }
- ply.showOptionsDialog("Select checkbox preset", pres, 1,
- function(text, index, player_color)
- local disabled = pres[index]:sub(1, 1)
- local empty = pres[index]:sub(3, 3)
- local filled = pres[index]:sub(5, 5)
- checks[selectedId].characters.disabled = disabled
- checks[selectedId].characters.empty = empty
- checks[selectedId].characters.filled = filled
- updateCheckNameContentAndTooltip(selectedId)
- refreshEditPanel()
- updateSave()
- end)
-end
-
-function nudgeSet1() updateNudgeDistance(1) end
-
-function nudgeSet01() updateNudgeDistance(0.1) end
-
-function nudgeSet001() updateNudgeDistance(0.01) end
-
-function nudgeSet0001() updateNudgeDistance(0.001) end
-
-function updateNudgeDistance(value)
- nudgeDistance = value
- UI.setAttribute(attrId("Field_nudge"), "text", nudgeDistance)
- UI.setAttribute(attrId("Check_nudge"), "text", nudgeDistance)
- UI.setAttribute(attrId("Decal_nudge"), "text", nudgeDistance)
- updateSave()
-end
-
-function nudgeLeft(obj, value, id)
- local newX = fields[selectedId].pos.x - tonumber(nudgeDistance)
- UI.setAttribute(attrId("Field/pos/x"), "text", newX)
- fields[selectedId].pos.x = newX
- updateFieldPositionAndSize(selectedId)
- updateSave()
-end
-
-function nudgeUp(obj, value, id)
- local newY = fields[selectedId].pos.y - tonumber(nudgeDistance)
- UI.setAttribute(attrId("Field/pos/y"), "text", newY)
- fields[selectedId].pos.y = newY
- updateFieldPositionAndSize(selectedId)
- updateSave()
-end
-
-function nudgeRight(obj, value, id)
- local newX = fields[selectedId].pos.x + tonumber(nudgeDistance)
- UI.setAttribute(attrId("Field/pos/x"), "text", newX)
- fields[selectedId].pos.x = newX
- updateFieldPositionAndSize(selectedId)
- updateSave()
-end
-
-function nudgeDown(obj, value, id)
- local newY = fields[selectedId].pos.y + tonumber(nudgeDistance)
- UI.setAttribute(attrId("Field/pos/y"), "text", newY)
- fields[selectedId].pos.y = newY
- updateFieldPositionAndSize(selectedId)
- updateSave()
-end
-
-function nudgeDecalLeft(obj, value, id)
- local newX = decals[selectedId].pos.x - tonumber(nudgeDistance)
- UI.setAttribute(attrId("Decal/pos/x"), "text", newX)
- decals[selectedId].pos.x = newX
- updateDecalPositionAndSize(selectedId)
- updateSave()
-end
-
-function nudgeDecalUp(obj, value, id)
- local newY = decals[tonumber(selectedId)].pos.y - tonumber(nudgeDistance)
- UI.setAttribute(attrId("Decal/pos/y"), "text", newY)
- decals[tonumber(selectedId)].pos.y = newY
- updateDecalPositionAndSize(selectedId)
- updateSave()
-end
-
-function nudgeDecalRight(obj, value, id)
- local newX = decals[tonumber(selectedId)].pos.x + tonumber(nudgeDistance)
- UI.setAttribute(attrId("Decal/pos/x"), "text", newX)
- decals[tonumber(selectedId)].pos.x = newX
- updateDecalPositionAndSize(selectedId)
- updateSave()
-end
-
-function nudgeDecalDown(obj, value, id)
- local newY = decals[tonumber(selectedId)].pos.y + tonumber(nudgeDistance)
- UI.setAttribute(attrId("Decal/pos/y"), "text", newY)
- decals[tonumber(selectedId)].pos.y = newY
- updateDecalPositionAndSize(selectedId)
- updateSave()
-end
-
-function nudgeCheckLeft(obj, value, id)
- local newX = checks[tonumber(selectedId)].pos.x - tonumber(nudgeDistance)
- UI.setAttribute(attrId("Check/pos/x"), "text", newX)
- checks[tonumber(selectedId)].pos.x = newX
- updateCheckPositionAndSize(selectedId)
- updateSave()
-end
-
-function nudgeCheckUp(obj, value, id)
- local newY = checks[tonumber(selectedId)].pos.y - tonumber(nudgeDistance)
- UI.setAttribute(attrId("Check/pos/y"), "text", newY)
- checks[tonumber(selectedId)].pos.y = newY
- updateCheckPositionAndSize(selectedId)
- updateSave()
-end
-
-function nudgeCheckRight(obj, value, id)
- local newX = checks[tonumber(selectedId)].pos.x + tonumber(nudgeDistance)
- UI.setAttribute(attrId("Check/pos/x"), "text", newX)
- checks[tonumber(selectedId)].pos.x = newX
- updateCheckPositionAndSize(selectedId)
- updateSave()
-end
-
-function nudgeCheckDown(obj, value, id)
- local newY = checks[tonumber(selectedId)].pos.y + tonumber(nudgeDistance)
- UI.setAttribute(attrId("Check/pos/y"), "text", newY)
- checks[tonumber(selectedId)].pos.y = newY
- updateCheckPositionAndSize(selectedId)
- updateSave()
-end
-
-function showEmptyPrompt()
- selectedId = 0
- selectedType = ""
- refreshEditPanel()
-end
-
-function duplicateField(ply, value, id)
- broadcastToColor("Text duplicated", ply.color)
- local newField = JSON.decode(JSON.encode(fields[tonumber(selectedId)]))
- table.insert(fields, newField)
- updateSave()
- selectField({ id = #fields, arrayId = 1 })
- refresh()
-end
-
-function deleteField(ply, value, id)
- broadcastToColor("Text deleted", ply.color)
- table.remove(fields, tonumber(selectedId))
- updateSave()
- if (#fields > 0) then
- selectField({ id = math.max(selectedId - 1, 1), arrayId = 1 })
- else
- if (#checks > 0) then
- selectCheck({ id = 1, arrayId = 1 })
- elseif (#decals > 0) then
- selectDecal(1)
- else
- showEmptyPrompt()
- end
- end
- refresh()
-end
-
-function duplicateCheck(ply, value, id)
- broadcastToColor("Check duplicated", ply.color)
- local newCheck = JSON.decode(JSON.encode(checks[tonumber(selectedId)]))
- table.insert(checks, newCheck)
- updateSave()
- selectCheck({ id = #checks, arrayId = 1 })
- refresh()
-end
-
-function deleteCheck(ply, value, id)
- broadcastToColor("Check deleted", ply.color)
- table.remove(checks, tonumber(selectedId))
- updateSave()
- if (#checks > 0) then
- selectCheck({ id = math.max(selectedId - 1, 1), arrayId = 1 })
- else
- if (#fields > 0) then
- selectField({ id = 1, arrayId = 1 })
- elseif (#decals > 0) then
- selectDecal(1)
- else
- showEmptyPrompt()
- end
- end
- refresh()
-end
-
-function duplicateDecal(ply, value, id)
- broadcastToColor("Image duplicated", ply.color)
- local newDecal = JSON.decode(JSON.encode(decals[tonumber(selectedId)]))
- table.insert(decals, newDecal)
- updateSave()
- selectDecal(#decals)
- refresh()
-end
-
-function deleteDecal(ply, value, id)
- broadcastToColor("Image deleted", ply.color)
- table.remove(decals, tonumber(selectedId))
- updateSave()
- if (#decals > 0) then
- selectDecal(math.max(selectedId - 1, 1))
- else
- if (#fields > 0) then
- selectField({ id = 1, arrayId = 1 })
- elseif (#checks > 0) then
- selectCheck({ id = 1, arrayId = 1 })
- else
- showEmptyPrompt()
- end
- end
- refresh()
-end
-
-function addField(obj, player_clicker_color, alt_click)
- local newField = {
- value = { "?" },
- name = "",
- tooltip = "name",
- role = "Normal Field",
- textColor = { r = 0, g = 0, b = 0, a = 1 },
- fieldColor = { r = 1, g = 1, b = 1, a = 1 },
- font = 150,
- align = 3,
- pos = { x = 0, y = 0 },
- size = { x = 250, y = 250 },
- array = { x = 1, y = 1 },
- distance = { x = 1, y = 1 },
- locked = false
- }
- table.insert(fields, newField)
- selectField({ id = #fields, arrayId = 1 })
- updateSave()
- refresh()
-end
-
-function addCheck(obj, player_clicker_color, alt_click)
- local newCheck = {
- name = "",
- tooltip = "hint",
- value = { 1 },
- characters = { disabled = "◌", empty = "○", filled = "●" },
- textColor = { r = 0, g = 0, b = 0, a = 1 },
- textColorOff = { r = 0, g = 0, b = 0, a = 1 },
- textColorDisabled = { r = 0.5, g = 0.5, b = 0.5, a = 1 },
- separateColors = false,
- fillFromDisabled = false,
- checkColor = { r = 1, g = 1, b = 1, a = 1 },
- pos = { x = 0, y = 0 },
- size = { x = 1, y = 1 },
- array = { x = 1, y = 1 },
- distance = { x = 1, y = 1 },
- font = 500,
- locked = false
- }
- table.insert(checks, newCheck)
- selectCheck({ id = #checks, arrayId = 1 })
- updateSave()
- refresh()
-end
-
-function addDecal(obj, player_clicker_color, alt_click)
- local newDecal = {
- name = "",
- url = "https://api.tabletopsimulator.com/img/TSIcon.png",
- tooltip = "name",
- pos = { x = 0, y = 0 },
- rotation = 0,
- scale = { x = 1, y = 1 },
- locked = false
- }
- table.insert(decals, newDecal)
- selectDecal(#decals)
- updateSave()
- refresh()
-end
-
-function onDestroy()
- closePanel()
-end
-
-function cutAtWord(inputStr, delimiter)
- local t = {}
- local pattern = "(.-)" .. delimiter
- for str in inputStr:gmatch(pattern) do
- table.insert(t, str)
- end
- if (#t > 0) then
- return t[1]
- else
- return false
- end
-end
-
-function waitForUiLoaded(callback)
- if UI.loading == false then
- callback()
- return nil
- end
- return Wait.condition(callback, function() return UI.loading == false end)
-end