diff --git a/config.json b/config.json index de87caff..649972e6 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 8fd6b615..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.3 - 11/21/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": [ - "Changes from 4.0.3\n- added ability for 'number typing' to the chaos token draw button\n- added \"0 uses\" metadata for Charles Ross\n- added \"imprinting\" to Charisma / Relic Hunter (drop them on a playermat!)\n- turned \"randomize\" feature of action / ability tokens into a context menu entry\n- turned upgradesheets into XML and their boxes into crosses\n- fixed Clean Up Helper toggling the \"subtract doom\" feature\n- fixed DES scripting\n- fixed error with Navigation Overlay\n- fixed error with investigator placing on playermats\n- fixed error with Kohaku feedback messages\n- fixed issues with Campaign Importer / Exporter\n- fixed handling for cards with attachments (Deck Importer)\n\nHighlights from 4.0.0\n\nNew 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. Longest Night)\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