Merge pull request #282 from argonui/navigation-overlay

improved implementation of Navigation Overlay
This commit is contained in:
Tikatoy 2023-05-23 16:03:38 -07:00 committed by GitHub
commit e49c8751ff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 752 additions and 1477 deletions

View File

@ -198,6 +198,7 @@
"GameKeyHandler.fce69c",
"ArkhamSCE310-4202023-Page1.e1b8df",
"3DText.d628cc",
"NavigationOverlayHandler.797ede",
"TheColourOutofOz.be7d21",
"Bloodborne-CityoftheUnseen0175.81651b"
],

View File

@ -37,12 +37,17 @@
{
"Name": "OverlayLarge",
"Type": 0,
"URL": "http://cloud-3.steamusercontent.com/ugc/1745699502804112656/A34D1F30E0DA0E283F300AE6D6B63F59FFC97730/"
"URL": "http://cloud-3.steamusercontent.com/ugc/2038486957000838167/1EF958D11A228817099C310F97817F61F84DDD91/"
},
{
"Name": "OverlaySmall",
"Type": 0,
"URL": "http://cloud-3.steamusercontent.com/ugc/1745699502804112719/CFFC89BF9FB8439204EE19CF94180EC99450CD38/"
"URL": "http://cloud-3.steamusercontent.com/ugc/2038486957000850722/37F0D4848BA08788F79DB2D3FB6D11429CB1F861/"
},
{
"Name": "NavigationOverlayIcon",
"Type": 0,
"URL": "http://cloud-3.steamusercontent.com/ugc/2038485431576357223/9B834B6C40D02D2796C4027D52FFFDF2F1DFBAA5/"
},
{
"Name": "option-gear",

View File

@ -40,6 +40,11 @@
"Nickname": "Investigator Count",
"Snap": true,
"Sticky": true,
"Tags": [
"CameraZoom_ignore",
"CleanUpHelper_ignore",
"displacement_excluded"
],
"Tooltip": true,
"Transform": {
"posX": -12.03,

View File

@ -41,7 +41,9 @@
"Snap": true,
"Sticky": true,
"Tags": [
"CleanUpHelper_ignore"
"CameraZoom_ignore",
"CleanUpHelper_ignore",
"displacement_excluded"
],
"Tooltip": true,
"Transform": {

View File

@ -1 +1 @@
{"acknowledgedUpgradeVersions":[],"optionPanel":{"playAreaSnapTags":true,"showAttachmentHelper":false,"showChaosBagManager":false,"showCleanUpHelper":false,"showCustomPlaymatImages":false,"showCYOA":false,"showDisplacementTool":false,"showDrawButton":false,"showHandHelper":[],"showNavigationOverlay":false,"showSearchAssistant":[],"showTitleSplash":true,"showTokenArranger":false,"useClueClickers":false,"useSnapTags":true}}
{"acknowledgedUpgradeVersions":[],"optionPanel":{"playAreaSnapTags":true,"showAttachmentHelper":false,"showChaosBagManager":false,"showCleanUpHelper":false,"showCustomPlaymatImages":false,"showCYOA":false,"showDisplacementTool":false,"showDrawButton":false,"showHandHelper":[],"showSearchAssistant":[],"showTitleSplash":true,"showTokenArranger":false,"useClueClickers":false,"useSnapTags":true}}

View File

@ -0,0 +1,45 @@
{
"AltLookAngle": {
"x": 0,
"y": 0,
"z": 0
},
"Autoraise": true,
"ColorDiffuse": {
"b": 0,
"g": 0,
"r": 0
},
"Description": "This object contains the code for the \"Navigation Overlay\".",
"DragSelectable": true,
"GMNotes": "",
"GUID": "797ede",
"Grid": true,
"GridProjection": false,
"Hands": false,
"HideWhenFaceDown": false,
"IgnoreFoW": false,
"LayoutGroupSortIndex": 0,
"Locked": true,
"LuaScript": "require(\"core/NavigationOverlayHandler\")",
"LuaScriptState": "",
"MeasureMovement": false,
"Name": "go_game_piece_black",
"Nickname": "Navigation Overlay Handler",
"Snap": true,
"Sticky": true,
"Tooltip": true,
"Transform": {
"posX": 78,
"posY": 1.328,
"posZ": -12,
"rotX": 0,
"rotY": 0,
"rotZ": 0,
"scaleX": 1,
"scaleY": 1,
"scaleZ": 1
},
"Value": 0,
"XmlUI": ""
}

View File

@ -18,7 +18,6 @@
"TokenArranger.022907",
"CYOACampaignGuides.e87ea2",
"AttachmentHelper.7f4976",
"jaqenZannsNavigationOverlay.a8affa",
"SearchAssistant.17aed0",
"HandHelper.450688",
"DisplacementTool.0f1374",

View File

@ -1,56 +0,0 @@
{
"AltLookAngle": {
"x": 0,
"y": 0,
"z": 0
},
"Autoraise": true,
"Bag": {
"Order": 0
},
"ColorDiffuse": {
"b": 0,
"g": 0.36652,
"r": 0.70588
},
"ContainedObjects_order": [
"NavigationOverlay.e5803c",
"CameraPlacementHelper.cecc3e",
"jaqenZannsNavigationOverlayTile.9f2481"
],
"ContainedObjects_path": "jaqenZannsNavigationOverlay.a8affa",
"Description": "",
"DragSelectable": true,
"GMNotes": "",
"GUID": "a8affa",
"Grid": true,
"GridProjection": false,
"Hands": false,
"HideWhenFaceDown": false,
"IgnoreFoW": false,
"LayoutGroupSortIndex": 0,
"Locked": false,
"LuaScript": "",
"LuaScriptState": "",
"MaterialIndex": -1,
"MeasureMovement": false,
"MeshIndex": -1,
"Name": "Bag",
"Nickname": "jaqenZann's Navigation Overlay",
"Snap": true,
"Sticky": true,
"Tooltip": true,
"Transform": {
"posX": 76.955,
"posY": 36.39,
"posZ": 4.123,
"rotX": 0,
"rotY": 180,
"rotZ": 0,
"scaleX": 1,
"scaleY": 1,
"scaleZ": 1
},
"Value": 0,
"XmlUI": ""
}

View File

@ -1,52 +0,0 @@
{
"AltLookAngle": {
"x": 0,
"y": 0,
"z": 0
},
"Autoraise": true,
"ColorDiffuse": {
"b": 0.18382,
"g": 0.18382,
"r": 0.18382
},
"CustomAssetbundle": {
"AssetbundleSecondaryURL": "",
"AssetbundleURL": "http://cloud-3.steamusercontent.com/ugc/880873968289806692/67F62868DF65CD9CC43F3CDCDED7BACA0F075422/",
"LoopingEffectIndex": 0,
"MaterialIndex": 2,
"TypeIndex": 4
},
"Description": "[b]Camera Placement Helper[/b]\n\nIf you want to use another object as the focus for the camera, you may do so by enter its GUID into this object's NAME field.\n\nIf you put a space and a number, the camera rotation will be offset by that amount. POSITIVE NUMBERS ONLY.\n\n[i]Example:[/i]\ncecc3e 90\n",
"DragSelectable": true,
"GMNotes": "",
"GUID": "cecc3e",
"Grid": false,
"GridProjection": false,
"Hands": false,
"HideWhenFaceDown": false,
"IgnoreFoW": false,
"LayoutGroupSortIndex": 0,
"Locked": false,
"LuaScriptState": "",
"LuaScript_path": "OptionPanelSource.830bd0/jaqenZannsNavigationOverlay.a8affa/CameraPlacementHelper.cecc3e.ttslua",
"MeasureMovement": false,
"Name": "Custom_Assetbundle",
"Nickname": "Camera Placement Helper",
"Snap": false,
"Sticky": true,
"Tooltip": true,
"Transform": {
"posX": -12.658,
"posY": 3.538,
"posZ": 28.573,
"rotX": 0,
"rotY": 270,
"rotZ": 0,
"scaleX": 0.58,
"scaleY": 0.58,
"scaleZ": 0.58
},
"Value": 0,
"XmlUI": ""
}

View File

@ -1,174 +0,0 @@
--Data tables used in button creation
ref_modifyPitchButtons = {
{ offset = -0.37, func = function() click_modify(-1, 0) end },
{ offset = -1.11, func = function() click_modify(-5, 0) end },
{ offset = 0.37, func = function() click_modify(1, 0) end },
{ offset = 1.11, func = function() click_modify(5, 0) end },
}
ref_modifyDistanceButtons = {
{ offset = -0.37, func = function() click_modify(-1, 1) end },
{ offset = -1.11, func = function() click_modify(-5, 1) end },
{ offset = 0.37, func = function() click_modify(1, 1) end },
{ offset = 1.11, func = function() click_modify(5, 1) end },
}
--On-demand save function, remembers pitch and distance values
function updateSave()
self.script_state = JSON.encode({ pitch = pitch, distance = distance })
end
--Startup, loading memory
function onload(saved_data)
--Loads the tracking for if the game has started yet
if saved_data ~= "" then
local loaded_data = JSON.decode(saved_data)
pitch = loaded_data.pitch
distance = loaded_data.distance
else
pitch = 45
distance = 30
end
createInputs()
createButtons()
end
--Activated by finishing writing in the input box, updates save info
function input_entered(inputString, stillEditing, typeIndex)
if stillEditing == false then
--Check to avoid empty input strings
if tonumber(inputString) == nil then inputString = 0 end
--Update save data
if typeIndex == 0 then
pitch = inputString
else
distance = inputString
end
updateSave()
end
end
--Activated by button, the -5 -1 +1 +5 buttons
function click_modify(amount, typeIndex)
if typeIndex == 0 then
pitch = pitch + amount
self.editInput({ index = typeIndex, value = pitch })
else
distance = distance + amount
self.editInput({ index = typeIndex, value = distance })
end
updateSave()
end
--Activated by button, uses the data to move the camera
function click_setCamera(_, color)
--Check if there is another object to use instead of self
local targetObj = self
local nameGUID = string.sub(self.getName(), 1, 6)
if getObjectFromGUID(nameGUID) ~= nil then
targetObj = getObjectFromGUID(nameGUID)
end
--Check if there is an offset to use instead of 180
local offsetY = 180
local offsetString = string.sub(self.getName(), 7)
if tonumber(string.match(offsetString, "%d+")) ~= nil then
offsetY = tonumber(string.match(offsetString, "%d+"))
end
--Move camera into position around object
local pos = targetObj.getPosition()
local rot = targetObj.getRotation()
rot.y = rot.y + offsetY
Player[color].lookAt({ position = pos, pitch = pitch, yaw = rot.y, distance = distance })
--Send values to main tile
for _, v in ipairs(getObjects()) do
if v.getName() == "jaqenZann's Navigation Overlay Tile" then
v.call('updateEditCamera', { { pos.x, pos.y, pos.z }, tonumber(pitch), rot.y, tonumber(distance) })
break
end
end
end
--Button/Input creation
--Text boxes for number input
function createInputs()
local funcName = "inputFuncNamePitch"
local func = function(_, _, x, z) input_entered(x, z, 0) end
self.setVar(funcName, func)
self.createInput({
input_function = funcName,
function_owner = self,
label = "input",
alignment = 2,
position = { -3.4, 0.35, -0.21 },
rotation = { 0, 0, 0 },
height = 420,
width = 1400,
font_size = 400,
color = { 57 / 255, 46 / 255, 40 / 255 },
font_color = { 1, 1, 1 },
value = pitch,
validation = 3
})
local funcName = "inputFuncNameDistance"
local func = function(_, _, x, z) input_entered(x, z, 1) end
self.setVar(funcName, func)
self.createInput({
input_function = funcName,
function_owner = self,
label = "input",
alignment = 4,
position = { 3.4, 0.35, -0.21 },
rotation = { 0, 0, 0 },
height = 420,
width = 1400,
font_size = 400,
color = { 57 / 255, 46 / 255, 40 / 255 },
font_color = { 1, 1, 1 },
value = distance,
validation = 3
})
end
--Center button and -5 - +5 buttons
function createButtons()
self.createButton({
click_function = "click_setCamera",
function_owner = self,
position = { 0, 0.4, 0 },
height = 900,
width = 900,
color = { 1, 1, 1, 0 },
tooltip = "Set camera to this angle"
})
for i, ref in ipairs(ref_modifyPitchButtons) do
local funcName = "pitchModifyFunction_" .. i
self.setVar(funcName, ref.func)
local pos = { -3.4 + ref.offset, 0.3, 0.6 }
self.createButton({
click_function = funcName,
function_owner = self,
position = pos,
height = 240,
width = 320,
color = { 1, 1, 1, 0 }
})
end
for i, ref in ipairs(ref_modifyDistanceButtons) do
local funcName = "distanceModifyFunction_" .. i
self.setVar(funcName, ref.func)
local pos = { 3.4 + ref.offset, 0.3, 0.6 }
self.createButton({
click_function = funcName,
function_owner = self,
position = pos,
height = 240,
width = 320,
color = { 1, 1, 1, 0 }
})
end
end

View File

@ -1,227 +0,0 @@
{
"AltLookAngle": {
"x": 0,
"y": 0,
"z": 0
},
"Autoraise": true,
"ColorDiffuse": {
"b": 1,
"g": 1,
"r": 1
},
"Description": "Controls a movable overlay allowing for quick movement to various parts of the table. There should only be one tile per table.\n\nFull Table: Displays a larger overlay corresponding to the whole table.\n\nPlay Area: Displays a much smaller overlay only covering the play area.",
"DragSelectable": true,
"GMNotes": "",
"GUID": "e5803c",
"Grid": true,
"GridProjection": false,
"Hands": false,
"HideWhenFaceDown": false,
"IgnoreFoW": false,
"LayoutGroupSortIndex": 0,
"Locked": false,
"LuaScript": "",
"LuaScriptState": "",
"MeasureMovement": false,
"Name": "Notecard",
"Nickname": "Navigation Overlay",
"Snap": true,
"States": {
"2": {
"AltLookAngle": {
"x": 0,
"y": 0,
"z": 0
},
"Autoraise": true,
"ColorDiffuse": {
"b": 1,
"g": 1,
"r": 1
},
"Description": "If there is only 1 player, clicking a button to move to a playmat will change the player's color to that playmat's color. Changes to camera settings will apply to all colors.\n\nIf there is more than 1 player, displaying the overlay or editing a camera setting will only apply to your color.",
"DragSelectable": true,
"GMNotes": "",
"GUID": "3051f2",
"Grid": true,
"GridProjection": false,
"Hands": false,
"HideWhenFaceDown": false,
"IgnoreFoW": false,
"LayoutGroupSortIndex": 0,
"Locked": false,
"LuaScript": "",
"LuaScriptState": "",
"MeasureMovement": false,
"Name": "Notecard",
"Nickname": "Navigation Overlay",
"Snap": true,
"Sticky": true,
"Tooltip": true,
"Transform": {
"posX": -69.47138,
"posY": 1.551499,
"posZ": -50.97995,
"rotX": -6.706855e-8,
"rotY": 90.00628,
"rotZ": 3.98763333e-9,
"scaleX": 0.7,
"scaleY": 1,
"scaleZ": 0.7
},
"Value": 0,
"XmlUI": ""
},
"3": {
"AltLookAngle": {
"x": 0,
"y": 0,
"z": 0
},
"Autoraise": true,
"ColorDiffuse": {
"b": 1,
"g": 1,
"r": 1
},
"Description": "Edit Camera: TTS does not make accessing camera settings easy, so this is done using a modified version of MrStump's Camera Placement Helper.\n\nTo use the Helper, place it in the position you want the camera to look, with the desired rotation. Set the Pitch and Distance values. Click \"Set camera to this angle\".",
"DragSelectable": true,
"GMNotes": "",
"GUID": "579a11",
"Grid": true,
"GridProjection": false,
"Hands": false,
"HideWhenFaceDown": false,
"IgnoreFoW": false,
"LayoutGroupSortIndex": 0,
"Locked": false,
"LuaScript": "",
"LuaScriptState": "",
"MeasureMovement": false,
"Name": "Notecard",
"Nickname": "Navigation Overlay: Edit Camera (1/2)",
"Snap": true,
"Sticky": true,
"Tooltip": true,
"Transform": {
"posX": -69.47138,
"posY": 1.55149889,
"posZ": -50.97995,
"rotX": -4.66551136e-8,
"rotY": 90.00628,
"rotZ": 9.637148e-9,
"scaleX": 0.7,
"scaleY": 1,
"scaleZ": 0.7
},
"Value": 0,
"XmlUI": ""
},
"4": {
"AltLookAngle": {
"x": 0,
"y": 0,
"z": 0
},
"Autoraise": true,
"ColorDiffuse": {
"b": 1,
"g": 1,
"r": 1
},
"Description": "1. Click \"Edit Camera\"\n2. Click a button in the overlay, it will turn green.\n3. Use the Camera Placement Helper to set the camera view.\n4. When clicking \"Set camera to this angle\" produces the correct camera view, click the green button in the overlay again to set the camera. Click a red button to cancel.",
"DragSelectable": true,
"GMNotes": "",
"GUID": "045a3e",
"Grid": true,
"GridProjection": false,
"Hands": false,
"HideWhenFaceDown": false,
"IgnoreFoW": false,
"LayoutGroupSortIndex": 0,
"Locked": false,
"LuaScript": "",
"LuaScriptState": "",
"MeasureMovement": false,
"Name": "Notecard",
"Nickname": "Navigation Overlay: Edit Camera (2/2)",
"Snap": true,
"Sticky": true,
"Tooltip": true,
"Transform": {
"posX": -69.47138,
"posY": 1.55149889,
"posZ": -50.97995,
"rotX": -1.21061817e-7,
"rotY": 90.00628,
"rotZ": 9.462388e-8,
"scaleX": 0.7,
"scaleY": 1,
"scaleZ": 0.7
},
"Value": 0,
"XmlUI": ""
},
"5": {
"AltLookAngle": {
"x": 0,
"y": 0,
"z": 0
},
"Autoraise": true,
"ColorDiffuse": {
"b": 1,
"g": 1,
"r": 1
},
"Description": "Claim Color: This is useful if you are running a game where one person controls 2 colors, and one controls the other two, and you wish to have your player color switch when you click White or Red, but not if you click Green or Orange.\n\nWhen you click Claim Color, the playmat areas of the overlay will turn white. Clicking one will allow you to switch to that color with the overlay. ",
"DragSelectable": true,
"GMNotes": "",
"GUID": "516664",
"Grid": true,
"GridProjection": false,
"Hands": false,
"HideWhenFaceDown": false,
"IgnoreFoW": false,
"LayoutGroupSortIndex": 0,
"Locked": false,
"LuaScript": "",
"LuaScriptState": "",
"MeasureMovement": false,
"Name": "Notecard",
"Nickname": "Navigation Overlay: Claim Colors",
"Snap": true,
"Sticky": true,
"Tooltip": true,
"Transform": {
"posX": -38.4611664,
"posY": 1.59,
"posZ": -1.54776835,
"rotX": 5.3783765e-8,
"rotY": 90.00012,
"rotZ": 8.552772e-8,
"scaleX": 0.7,
"scaleY": 1,
"scaleZ": 0.7
},
"Value": 0,
"XmlUI": ""
}
},
"Sticky": true,
"Tooltip": true,
"Transform": {
"posX": -37.692,
"posY": 3.67,
"posZ": 9.23,
"rotX": 0,
"rotY": 90,
"rotZ": 0,
"scaleX": 0.7,
"scaleY": 1,
"scaleZ": 0.7
},
"Value": 0,
"XmlUI": ""
}

View File

@ -1,57 +0,0 @@
{
"AltLookAngle": {
"x": 0,
"y": 0,
"z": 0
},
"Autoraise": true,
"ColorDiffuse": {
"b": 1,
"g": 1,
"r": 1
},
"CustomImage": {
"CustomTile": {
"Stackable": false,
"Stretch": true,
"Thickness": 0.1,
"Type": 0
},
"ImageScalar": 1,
"ImageSecondaryURL": "http://cloud-3.steamusercontent.com/ugc/2021591230456185506/15AF790F0622B57C1F629DB3A8C38F2A99D0EB1B/",
"ImageURL": "http://cloud-3.steamusercontent.com/ugc/2021591230456185506/15AF790F0622B57C1F629DB3A8C38F2A99D0EB1B/",
"WidthScale": 0
},
"Description": "",
"DragSelectable": true,
"GMNotes": "",
"GUID": "9f2481",
"Grid": false,
"GridProjection": false,
"Hands": false,
"HideWhenFaceDown": false,
"IgnoreFoW": false,
"LayoutGroupSortIndex": 0,
"Locked": false,
"LuaScriptState": "",
"LuaScript_path": "OptionPanelSource.830bd0/jaqenZannsNavigationOverlay.a8affa/jaqenZannsNavigationOverlayTile.9f2481.ttslua",
"MeasureMovement": false,
"Name": "Custom_Tile",
"Nickname": "jaqenZann's Navigation Overlay Tile",
"Snap": false,
"Sticky": true,
"Tooltip": true,
"Transform": {
"posX": -12.93,
"posY": 3.562,
"posZ": 28.568,
"rotX": 0,
"rotY": 270,
"rotZ": 1,
"scaleX": 3,
"scaleY": 1,
"scaleZ": 3
},
"Value": 0,
"XmlUI": ""
}

View File

@ -1,845 +0,0 @@
local buttonCount = 20
local cameraCount = 18
function onLoad(saved_data)
self.createButton({
label = "",
tooltip = "Display full overlay",
click_function = "displayFull",
function_owner = self,
position = { 0.0, 0.1, -0.63 },
height = 70,
width = 700,
scale = { x = 1, y = 1, z = 1 },
color = { 1, 0, 0, 0 }
})
self.createButton({
label = "",
tooltip = "Display only play area",
click_function = "displayPlayArea",
function_owner = self,
position = { 0.0, 0.1, -0.39 },
height = 70,
width = 700,
scale = { x = 1, y = 1, z = 1 },
color = { 1, 0, 0, 0 }
})
self.createButton({
label = "",
tooltip = "Close overlay",
click_function = "closeOverlay",
function_owner = self,
position = { 0.0, 0.1, -0.16 },
height = 70,
width = 700,
scale = { x = 1, y = 1, z = 1 },
color = { 1, 0, 0, 0 }
})
self.createButton({
label = "",
tooltip = "Modify a camera position",
click_function = "beginSetCamera",
function_owner = self,
position = { 0.0, 0.1, 0.19 },
height = 70,
width = 700,
scale = { x = 1, y = 1, z = 1 },
color = { 1, 0, 0, 0 }
})
self.createButton({
label = "",
tooltip = "Claim a color (you will switch to this color when clicking in the overlay)",
click_function = "beginClaimColor",
function_owner = self,
position = { -0.22, 0.1, 0.42 },
height = 70,
width = 475,
scale = { x = 1, y = 1, z = 1 },
color = { 1, 0, 0, 0 }
})
self.createButton({
label = "",
tooltip = "Reset all color claims",
click_function = "resetClaimColors",
function_owner = self,
position = { 0.48, 0.1, 0.42 },
height = 70,
width = 230,
scale = { x = 1, y = 1, z = 1 },
color = { 1, 0, 0, 0 }
})
self.createButton({
label = "",
tooltip = "Reset camera positions to default",
click_function = "resetCameras",
function_owner = self,
position = { 0.0, 0.1, 0.78 },
height = 70,
width = 700,
scale = { x = 1, y = 1, z = 1 },
color = { 1, 0, 0, 0 }
})
defaultCameraParams = {
{ position = { -1.626, -2.5, 0 }, pitch = 74, yaw = 90, distance = 17.844 }, -- 1. ActAgenda
{ position = { -27.822, -2.5, 0.424 }, pitch = 74, yaw = 90, distance = -1 }, -- 2. Map
{ position = { -31.592, -2.5, 26.392 }, pitch = 74, yaw = 180, distance = -1 }, -- 3. Green playmat
{ position = { -55.026, -2.5, 12.052 }, pitch = 74, yaw = 90, distance = -1 }, -- 4. White playmat
{ position = { -55.026, -2.5, -11.479 }, pitch = 74, yaw = 90, distance = -1 }, -- 5. Orange playmat
{ position = { -31.592, -2.5, -26.392 }, pitch = 74, yaw = 0, distance = -1 }, -- 6. Red playmat
{ position = { -3.029, 1.652, 24.296 }, pitch = 74, yaw = 90, distance = 16 }, -- 7. Victory / SetAside
{ position = { -2.936, 1.552, -26.757 }, pitch = 74, yaw = 90, distance = 16 }, -- 8. Guide
{ position = { -11.833, 1.491, -0.145 }, pitch = 74, yaw = 90, distance = 10 }, -- 9. Player count
{ position = { -48.352, 1.552, -0.055 }, pitch = 74, yaw = 90, distance = 10 }, -- 10. Bless/Curse
{ position = { 12.560, 1.912, 0.458 }, pitch = 74, yaw = 90, distance = 35 }, -- 11. Scenarios
{ position = { 57.835, 1.552, 75.385 }, pitch = 74, yaw = 90, distance = 22 }, -- 12. Player card panel
{ position = { 60.377, 1.552, 55.941 }, pitch = 74, yaw = 90, distance = 10 }, -- 13. Card search panel
{ position = { 27.482, 1.480, 71.057 }, pitch = 74, yaw = 90, distance = 35 }, -- 14. Player card area
{ position = { -19.481, 1.552, 70.880 }, pitch = 74, yaw = 90, distance = 22 }, -- 15. Deck builder
{ position = { -52.918, 1.478, 70.899 }, pitch = 74, yaw = 90, distance = 42 }, -- 16. Rules area
{ position = { 24.551, 2.222, -71.284 }, pitch = 60, yaw = 90, distance = 60 }, -- 17. Cycle area
{ position = { -59.077, 1.462, -85.472 }, pitch = 74, yaw = 90, distance = 27 } -- 18. Additions
}
fullButtonData = {
{ id = "1", width = "84", height = "33", offsetX = "1", offsetY = "2" }, -- Act/Agenda
{ id = "2", width = "78", height = "69", offsetX = "1", offsetY = "-62" }, -- Map
{ id = "3", width = "36", height = "70", offsetX = "-62", offsetY = "-66" }, -- Green
{ id = "4", width = "70", height = "36", offsetX = "-36", offsetY = "-126" }, -- White
{ id = "5", width = "70", height = "36", offsetX = "39", offsetY = "-126" }, -- Orange
{ id = "6", width = "36", height = "70", offsetX = "64", offsetY = "-66" }, -- Red
{ id = "7", width = "38", height = "38", offsetX = "-64", offsetY = "-3" }, -- Victory
{ id = "8", width = "40", height = "40", offsetX = "66", offsetY = "-3" }, -- Guide
{ id = "9", width = "56", height = "16", offsetX = "1", offsetY = "-20" }, -- Player count
{ id = "10", width = "36", height = "16", offsetX = "1", offsetY = "-102" }, -- Bless/Curse
{ id = "11", width = "168", height = "56", offsetX = "1", offsetY = "47" }, -- Scenarios
{ id = "12", width = "52", height = "53", offsetX = "-154", offsetY = "134" }, -- Player card panel
{ id = "13", width = "22", height = "22", offsetX = "-116", offsetY = "132" }, -- Search card panel
{ id = "14", width = "120", height = "75", offsetX = "-152", offsetY = "70" }, -- Player card display
{ id = "15", width = "40", height = "54", offsetX = "-150", offsetY = "-38" }, -- Deck builder
{ id = "16", width = "104", height = "84", offsetX = "-154", offsetY = "-114" }, -- Rules area
{ id = "17", width = "100", height = "170", offsetX = "152", offsetY = "72" }, -- Cycle area
{ id = "18", width = "56", height = "60", offsetX = "182", offsetY = "-124" }, -- Additions
{ id = "19", width = "20", height = "20", offsetX = "-8", offsetY = "150" }, -- Shrink
{ id = "20", width = "20", height = "20", offsetX = "12", offsetY = "150" } -- Close
}
playButtonData = {
{ id = "1", width = "80", height = "33", offsetX = "0", offsetY = "55" },
{ id = "2", width = "78", height = "70", offsetX = "0", offsetY = "-8" },
{ id = "3", width = "35", height = "66", offsetX = "-65", offsetY = "-10" },
{ id = "4", width = "68", height = "32", offsetX = "-36", offsetY = "-71" },
{ id = "5", width = "68", height = "32", offsetX = "36", offsetY = "-71" },
{ id = "6", width = "35", height = "66", offsetX = "65", offsetY = "-10" },
{ id = "7", width = "38", height = "38", offsetX = "-66", offsetY = "52" },
{ id = "8", width = "38", height = "38", offsetX = "66", offsetY = "52" },
{ id = "9", width = "50", height = "12", offsetX = "0", offsetY = "33" },
{ id = "10", width = "32", height = "12", offsetX = "0", offsetY = "-48" },
{ id = "19", width = "20", height = "20", offsetX = "-10", offsetY = "80" },
{ id = "20", width = "20", height = "20", offsetX = "10", offsetY = "80" }
}
playermatData = {
{
guid = '383d8b',
origin = { x = -25.00, y = 0, z = 26.20 },
scale = { x = 31.5, y = 5.10, z = 14.59 },
orientation = { x = 0, y = 0, z = 0 },
minX = -44.43,
maxX = -17.44,
minZ = 20.17,
maxZ = 32.97,
xOffset = -0.07,
zOffset = 0.00,
claims = { true, false, false, false }
},
{
guid = '8b081b',
origin = { x = -54.42, y = 0, z = 20.96 },
scale = { x = 36.63, y = 5.10, z = 14.59 },
orientation = { x = 0, y = 270, z = 0 },
minX = -61.4,
maxX = -48.6,
minZ = -2.39,
maxZ = 24.53,
xOffset = 0.07,
zOffset = 0.03,
claims = { false, true, false, false }
},
{
guid = 'bd0ff4',
origin = { x = -54.42, y = 0, z = -20.96 },
scale = { x = 36.63, y = 5.10, z = 14.59 },
orientation = { x = 0, y = 270, z = 0 },
minX = -61.4,
maxX = -48.6,
minZ = -24.53,
maxZ = 2.39,
xOffset = 0.07,
zOffset = 0.02,
claims = { false, false, true, false }
},
{
guid = '0840d5',
origin = { x = -25.00, y = 0, z = -26.60 },
scale = { x = 31.5, y = 5.10, z = 14.59 },
orientation = { x = 0, y = 180, z = 0 },
minX = -44.43,
maxX = -17.44,
minZ = -32.97,
maxZ = -20.17,
xOffset = 0.07,
zOffset = -0.06,
claims = { false, false, false, true }
}
}
editing = false
claiming = false
selectedEditButton = -1
editPos = { 0, 0, 0 }
editPitch = 0
editYaw = 0
editDistance = 0
if saved_data ~= "" then
local loaded_data = JSON.decode(saved_data)
cameraParams = loaded_data.cameras
fullVisibility = loaded_data.fullVis
playVisibility = loaded_data.playVis
for i = 1, 4 do
playermatData[i].claims = loaded_data.claims[i]
end
else
cameraParams = { {}, {}, {}, {} }
for cam = 1, 4 do
cameraParams[cam] = {}
for i = 1, cameraCount do
cameraParams[cam][i] = {}
cameraParams[cam][i].position = defaultCameraParams[i].position
cameraParams[cam][i].pitch = defaultCameraParams[i].pitch
cameraParams[cam][i].yaw = defaultCameraParams[i].yaw
cameraParams[cam][i].distance = defaultCameraParams[i].distance
end
end
fullVisibility = { false, false, false, false }
playVisibility = { false, false, false, false }
end
resetOverlay()
end
function onSave()
local allclaims = {}
for i = 1, 4 do
table.insert(allclaims, playermatData[i].claims)
end
return JSON.encode({
cameras = cameraParams,
fullVis = fullVisibility,
playVis = playVisibility,
claims = allclaims
})
end
function displayFull(object, color)
local playerCount = getPlayerCount()
local colors
if playerCount == 0 then
return
elseif playerCount == 1 then
colors = { 1, 2, 3, 4 }
else
colors = { getIndexForPlayerColor(color) }
end
for i, v in ipairs(colors) do
if v > 0 then
fullVisibility[v] = true
playVisibility[v] = false
end
end
resetOverlay()
end
function displayPlayArea(object, color)
local playerCount = getPlayerCount()
local colors
if playerCount == 0 then
return
elseif playerCount == 1 then
colors = { 1, 2, 3, 4 }
else
colors = { getIndexForPlayerColor(color) }
end
for _, v in ipairs(colors) do
if v > 0 then
fullVisibility[v] = false
playVisibility[v] = true
end
end
resetOverlay()
end
function resetCameras(object, color)
local playerCount = getPlayerCount()
local colors
if playerCount == 0 then
return
elseif playerCount == 1 then
colors = { 1, 2, 3, 4 }
else
colors = { getIndexForPlayerColor(color) }
end
for iv, v in ipairs(colors) do
if v > 0 then
for i = 1, cameraCount do
cameraParams[v][i].position = defaultCameraParams[i].position
cameraParams[v][i].pitch = defaultCameraParams[i].pitch
cameraParams[v][i].yaw = defaultCameraParams[i].yaw
cameraParams[v][i].distance = defaultCameraParams[i].distance
end
end
end
end
function closeOverlay(object, color)
local playerCount = getPlayerCount()
local colors
editing = false
claiming = false
if playerCount == 0 then
return
elseif playerCount == 1 then
colors = { 1, 2, 3, 4 }
else
colors = { getIndexForPlayerColor(color) }
end
for _, v in ipairs(colors) do
if v > 0 then
fullVisibility[v] = false
playVisibility[v] = false
end
end
resetOverlay()
end
function resizeOverlay(object, color)
local playerCount = getPlayerCount()
local colors
if playerCount == 0 then
return
elseif playerCount == 1 then
colors = { 1, 2, 3, 4 }
else
colors = { getIndexForPlayerColor(color) }
end
for _, v in ipairs(colors) do
if v > 0 then
local full = fullVisibility[v]
fullVisibility[v] = not full
playVisibility[v] = full
end
end
resetOverlay()
end
function resetOverlay()
local guid = self.getGUID()
local color
local panel
local existingXml = UI.getXml()
local openingXml = ''
-- try to only remove our panels
for p = 1, 2 do
i, j = string.find(existingXml, '<Panel id="navPanel')
if i and i > 1 and string.len(openingXml) == 0 then
openingXml = string.sub(existingXml, 1, i - 1)
end
if i then
local panelXml = string.sub(existingXml, i)
k, m = string.find(panelXml, '</Panel>')
existingXml = string.sub(panelXml, m + 1)
else
break
end
end
local xml = openingXml .. [[
]] .. existingXml
local fullColors = ''
local playColors = ''
for i, v in pairs(fullVisibility) do
if v == true then
local matColor = getPlayerColorForIndex(i)
if string.len(fullColors) > 0 and matColor ~= nil then
fullColors = fullColors .. '|' .. matColor
elseif matColor ~= nil then
fullColors = matColor
end
end
end
for i, v in pairs(playVisibility) do
if v == true then
local matColor = getPlayerColorForIndex(i)
if string.len(playColors) > 0 and matColor ~= nil then
playColors = playColors .. '|' .. matColor
elseif matColor ~= nil then
playColors = matColor
end
end
end
if string.len(fullColors) > 0 then
data = fullButtonData
xml = xml ..
[[<Panel id="navPanelFull" height="358" width="455" visibility="]] ..
fullColors ..
[[" allowDragging="true" returnToOriginalPositionWhenReleased="false" rectAlignment="LowerRight" offsetXY="-40 0">
<image id="backgroundImage" image="OverlayLarge" />]]
for _, d in ipairs(data) do
local buttonID = tonumber(d.id)
if editing and buttonID < 19 then
if selectedEditButton < 0 then
color = "rgba(1,1,1,1)"
elseif buttonID == selectedEditButton then
color = "rgba(0,1,0,1)"
else
color = "rgba(1,0,0,1)"
end
elseif claiming and buttonID < 19 then
if buttonID >= 3 and buttonID <= 6 then
color = "rgba(1,1,1,1)"
else
color = "rgba(1,0,0,1)"
end
else
color = "rgba(0,1,0,0)"
end
xml = xml .. [[<button
onClick="]] .. guid .. [[/buttonClicked"
id="]] .. d.id .. [["
height="]] .. d.height .. [["
width="]] .. d.width .. [["
offsetXY="]] .. d.offsetX .. " " .. d.offsetY .. [["
color="]] .. color .. [["
>
</button>
]]
end
xml = xml .. [[ </Panel>]]
end
if string.len(playColors) > 0 then
data = playButtonData
xml = xml .. [[
<Panel id="navPanelPlay" height="208" width="205" visibility="]] ..
playColors ..
[[" allowDragging="true" returnToOriginalPositionWhenReleased="false" rectAlignment="LowerRight" offsetXY="-40 0">
<image id="backgroundImage" image="OverlaySmall" />]]
for _, d in ipairs(data) do
local buttonID = tonumber(d.id)
if editing and buttonID < 19 then
if selectedEditButton < 0 then
color = "rgba(1,1,1,1)"
elseif buttonID == selectedEditButton then
color = "rgba(0,1,0,1)"
else
color = "rgba(1,0,0,1)"
end
elseif claiming and buttonID < 19 then
if buttonID >= 3 and buttonID <= 6 then
color = "rgba(1,1,1,1)"
else
color = "rgba(1,0,0,1)"
end
else
color = "rgba(0,1,0,0)"
end
xml = xml .. [[<button
onClick="]] .. guid .. [[/buttonClicked"
id="]] .. d.id .. [["
height="]] .. d.height .. [["
width="]] .. d.width .. [["
offsetXY="]] .. d.offsetX .. " " .. d.offsetY .. [["
color="]] .. color .. [["
>
</button>
]]
end
xml = xml .. [[ </Panel>]]
end
local existingAssets = UI.getCustomAssets()
local largeOverlay = nil
local smallOverlay = nil
for _, v in pairs(existingAssets) do
for _, vv in pairs(v) do
if vv == 'OverlayLarge' then
largeOverlay = v
end
if vv == 'OverlaySmall' then
smallOverlay = v
end
end
end
local largeURL = 'http://cloud-3.steamusercontent.com/ugc/2021591230441678995/7B413A821136969D8723687A2AD66773B3F8FEED/'
local smallURL = 'http://cloud-3.steamusercontent.com/ugc/2021591230447630077/18C86248B9BDAF1DE01B67791439A39EE4F97B60/'
if largeOverlay == nil then
largeOverlay = { name = 'OverlayLarge', url = largeURL }
table.insert(existingAssets, largeOverlay)
else
largeOverlay.url = largeURL
end
if smallOverlay == nil then
smallOverlay = { name = 'OverlaySmall', url = smallURL }
table.insert(existingAssets, smallOverlay)
else
smallOverlay.url = smallURL
end
UI.setXml(xml, existingAssets)
end
function buttonClicked(player, _, idValue)
local buttonID = tonumber(idValue)
if buttonID == 19 then
resizeOverlay(nil, player.color)
return
elseif buttonID == 20 then
closeOverlay(nil, player.color)
return
end
if editing then
if selectedEditButton < 0 then
selectedEditButton = buttonID
else
if buttonID == selectedEditButton and editDistance > 0 then
local playerCount = getPlayerCount()
local colors
if playerCount == 1 then
colors = { 1, 2, 3, 4 }
else
colors = { getIndexForPlayerColor(player.color) }
end
for i, v in ipairs(colors) do
cameraParams[v][selectedEditButton].position = editPos
cameraParams[v][selectedEditButton].pitch = editPitch
cameraParams[v][selectedEditButton].yaw = editYaw
cameraParams[v][selectedEditButton].distance = editDistance
end
end
editing = false
selectedEditButton = -1
end
resetOverlay()
elseif claiming then
if buttonID >= 3 and buttonID <= 6 then
local colorID = buttonID - 2
local playerIndex = getIndexForPlayerColor(player.color)
-- if we haven't claimed it, break all earlier claims
if playermatData[playerIndex].claims[colorID] == false then
for i = 1, 4 do
if i ~= colorID then
playermatData[i].claims[colorID] = false
playermatData[colorID].claims[i] = false
end
end
end
for i = 1, 4 do
if playermatData[playerIndex].claims[i] then
playermatData[i].claims[colorID] = true
playermatData[colorID].claims[i] = true
end
end
fullVisibility[colorID] = fullVisibility[playerIndex]
playVisibility[colorID] = playVisibility[playerIndex]
end
claiming = false
resetOverlay()
else
loadCamera(player, _, idValue)
end
end
function loadCamera(player, _, idValue)
local index = tonumber(idValue)
local playerColor = player.color
local playerIndex = getIndexForPlayerColor(playerColor)
-- only do map zooming if the camera hasn't been specially set by user
if index == 2 and cameraParams[playerIndex][index].distance <= 0.0 then
local mapObjects = Physics.cast({
origin = { x = -29.2, y = 0, z = 0.0 },
direction = { x = 0, y = 1, z = 0 },
type = 3,
size = { x = 36, y = 5, z = 31.4 },
orientation = { x = 0, y = 90, z = 0 }
})
local minX = 100
local maxX = -100
local minZ = 100
local maxZ = -100
for _, v in pairs(mapObjects) do
local obj = v.hit_object
if obj.type == 'Card' or obj.type == 'Infinite' then
local bounds = obj.getBounds()
local x1 = bounds['center'][1] - bounds['size'][1] / 2
local x2 = bounds['center'][1] + bounds['size'][1] / 2
local z1 = bounds['center'][3] - bounds['size'][3] / 2
local z2 = bounds['center'][3] + bounds['size'][3] / 2
minX = math.min(x1, minX)
maxX = math.max(x2, maxX)
minZ = math.min(z1, minZ)
maxZ = math.max(z2, maxZ)
end
end
if minX < 100 then
local dx = maxX - minX
local dz = (maxZ - minZ) / (1.6) -- screen ratio * 1.2 (for my macbook pro, no idea how to generalize this)
local centerX = (minX + maxX) / 2 -- offset is to move it a bit up, so the cards don't block anything
local centerZ = (minZ + maxZ) / 2
local scale = math.max(dx, dz)
-- regression line from the following data points, seems linear
-- rows 1 scale 4.5 d 12
-- rows 2 scale 11 d 16
-- rows 3 scale 14.5 d 19.6
-- rows 4 scale 19.6 d 25
-- rows 5 scale 23.25 d 28
-- rows 6 scale 30.8 d 34
-- modified by testing
local d = 0.96 * scale + 5
player.lookAt({ position = { centerX, 0, centerZ }, pitch = 74, yaw = 90, distance = d })
else
player.lookAt({ position = { -30.667, 0, 0 }, pitch = 74, yaw = 90, distance = 32 })
end
elseif index >= 3 and index <= 6 then
local newMatIndex = index - 2 -- mat index 1 - 4
local newMatColor = getPlayerColorForIndex(newMatIndex)
if newMatColor ~= nil then
local playerCount = getPlayerCount()
if playerCount <= 1 or playermatData[playerIndex].claims[newMatIndex] then
player.changeColor(newMatColor)
end
end
if cameraParams[newMatIndex][index].distance <= 0.0 then
local matObjects = Physics.cast({
origin = playermatData[newMatIndex].origin,
direction = { x = 0, y = 1, z = 0 },
type = 3,
size = playermatData[newMatIndex].scale,
orientation = playermatData[newMatIndex].orientation
})
local minX = playermatData[newMatIndex].minX
local maxX = playermatData[newMatIndex].maxX
local minZ = playermatData[newMatIndex].minZ
local maxZ = playermatData[newMatIndex].maxZ
for _, v in pairs(matObjects) do
local obj = v.hit_object
if obj.type == 'Card' or obj.type == 'Infinite' then
local bounds = obj.getBounds()
local x1 = bounds['center'][1] - bounds['size'][1] / 2
local x2 = bounds['center'][1] + bounds['size'][1] / 2
local z1 = bounds['center'][3] - bounds['size'][3] / 2
local z2 = bounds['center'][3] + bounds['size'][3] / 2
minX = math.min(x1, minX)
maxX = math.max(x2, maxX)
minZ = math.min(z1, minZ)
maxZ = math.max(z2, maxZ)
end
end
local dx, dz, centerX, centerZ, yaw
-- White/Orange
if index > 3 and index < 6 then
dx = maxX - minX
dz = (maxZ - minZ) / 1.6 -- screen ratio * 1.2 (for my macbook pro, no idea how to generalize this)
yaw = 90
-- offset is to move it a bit up and right, so the cards/toolbar don't block anything
centerX = (minX + maxX) / 2 - dx * playermatData[newMatIndex].xOffset
centerZ = (minZ + maxZ) / 2 + dz * playermatData[newMatIndex].zOffset
-- Green/Red
else
dx = (maxX - minX) / 1.6
dz = maxZ - minZ
yaw = playermatData[newMatIndex].orientation.y + 180
centerX = (minX + maxX) / 2 + dx * playermatData[newMatIndex].zOffset
centerZ = (minZ + maxZ) / 2 - dz * playermatData[newMatIndex].xOffset
end
local scale = math.max(dx, dz)
local d = 0.64 * scale + 7
-- need to wait if the player color changed
Wait.frames(function()
player.lookAt({ position = { centerX, 0, centerZ }, pitch = 75.823, yaw = yaw, distance = d })
end, 2)
else
Wait.frames(function()
player.lookAt(cameraParams[newMatIndex][index])
end, 2)
end
else
player.lookAt(cameraParams[playerIndex][index])
end
end
function beginSetCamera(object, color)
if getPlayerCount() == 0 then
return
elseif getIndexForPlayerColor(color) < 0 then
return
end
editing = true
resetOverlay()
end
function updateEditCamera(params)
editPos = params[1]
editPitch = params[2]
editYaw = params[3]
editDistance = params[4]
end
function beginClaimColor(object, color)
if getPlayerCount() == 0 then
return
elseif getIndexForPlayerColor(color) < 0 then
return
end
claiming = true
resetOverlay()
end
function resetClaimColors(object, color)
if getPlayerCount() == 0 then
return
elseif getIndexForPlayerColor(color) < 0 then
return
end
for c1 = 1, 4 do
for c2 = 1, 4 do
if c1 == c2 then
playermatData[c1].claims[c2] = true
else
playermatData[c1].claims[c2] = false
end
end
end
end
function getPlayerCount()
local playerCount = 0
local playerColors = {}
for i = 1, 4 do
local guid = playermatData[i].guid
local mat = getObjectFromGUID(guid)
local color = mat.getVar('playerColor')
playerColors[i] = color
end
for _, v in ipairs(getSeatedPlayers()) do
for _, vv in ipairs(playerColors) do
if v == vv then
playerCount = playerCount + 1
end
end
end
return playerCount
end
function getPlayerColorForIndex(index)
if index < 0 or index > 4 then
return nil
end
local guid = playermatData[index]['guid']
if guid ~= nil then
local mat = getObjectFromGUID(guid)
return mat.getVar("playerColor")
end
end
function getIndexForPlayerColor(color)
for i = 1, 4 do
local mat = getObjectFromGUID(playermatData[i].guid)
if mat ~= nil then
if mat.getVar('playerColor') == color then
return i
end
end
end
return -1
end

View File

@ -42,6 +42,7 @@
"Sticky": true,
"Tags": [
"LinkedPhaseTracker",
"CameraZoom_ignore",
"CleanUpHelper_ignore",
"displacement_excluded"
],

View File

@ -977,6 +977,11 @@
"Nickname": "Playarea",
"Snap": true,
"Sticky": true,
"Tags": [
"CameraZoom_ignore",
"CleanUpHelper_ignore",
"displacement_excluded"
],
"Tooltip": false,
"Transform": {
"posX": -27.94,

View File

@ -40,6 +40,11 @@
"Nickname": "Playmat Image Swapper",
"Snap": true,
"Sticky": true,
"Tags": [
"CameraZoom_ignore",
"CleanUpHelper_ignore",
"displacement_excluded"
],
"Tooltip": true,
"Transform": {
"posX": -10.36,

View File

@ -31,7 +31,7 @@
"Sticky": true,
"Tooltip": true,
"Transform": {
"posX": -27.873,
"posX": -27.94,
"posY": 3.5,
"posZ": 0,
"rotX": 0,

View File

@ -48,6 +48,11 @@
"Nickname": "TableSurface",
"Snap": true,
"Sticky": true,
"Tags": [
"CameraZoom_ignore",
"CleanUpHelper_ignore",
"displacement_excluded"
],
"Tooltip": false,
"Transform": {
"posX": 0,

View File

@ -38,6 +38,7 @@ local soundCubeApi = require("core/SoundCubeApi")
local mythosAreaApi = require("core/MythosAreaApi")
local tokenArrangerApi = require("accessories/TokenArrangerApi")
local blessCurseManagerApi = require("chaosbag/BlessCurseManagerApi")
local navigationOverlayApi = require("core/NavigationOverlayApi")
-- online functionality related variables
local MOD_VERSION = "3.1.0"
@ -641,7 +642,12 @@ function onClick_load()
UI.hide('load_button')
end
function onClick_toggleUi(_, title)
function onClick_toggleUi(player, title)
if title == "Navigation Overlay" then
navigationOverlayApi.cycleVisibility(player.color)
return
end
UI.hide('optionPanel')
UI.hide('load_ui')
@ -886,10 +892,6 @@ function applyOptionPanelChange(id, state)
elseif id == "showAttachmentHelper" then
optionPanel[id] = spawnOrRemoveHelper(state, "Attachment Helper", {-62, 1.4, 0})
-- option: Show navigation overlay
elseif id == "showNavigationOverlay" then
optionPanel[id] = spawnOrRemoveHelper(state, "jaqenZann's Navigation Overlay", {-68, 1.4, -70})
-- option: Show CYOA campaign guides
elseif id == "showCYOA" then
optionPanel[id] = spawnOrRemoveHelper(state, "CYOA Campaign Guides", {65, 1.6, -11})
@ -959,7 +961,6 @@ function removeHelperObject(name)
["Hand Helper"] = "showHandHelper",
["Search Assistant"] = "showSearchAssistant",
["Chaos Bag Manager"] = "showChaosBagManager",
["jaqenZann's Navigation Overlay"] = "showNavigationOverlay",
["Displacement Tool"] = "showDisplacementTool",
["Custom Playmat Images"] = "showCustomPlaymatImages",
["Attachment Helper"] = "showAttachmentHelper",
@ -1004,7 +1005,6 @@ function onClick_defaultSettings()
showDisplacementTool = false,
showDrawButton = false,
showHandHelper = {},
showNavigationOverlay = false,
showSearchAssistant = {},
showTitleSplash = true,
showTokenArranger = false,

View File

@ -0,0 +1,22 @@
do
local NavigationOverlayApi = {}
local HANDLER_GUID = "797ede"
-- Copies the visibility for the Navigation overlay
---@param startColor String Color of the player to copy from
---@param targetColor String Color of the targeted player
NavigationOverlayApi.copyVisibility = function(startColor, targetColor)
getObjectFromGUID(HANDLER_GUID).call("copyVisibility", {
startColor = startColor,
targetColor = targetColor
})
end
-- Changes the Navigation Overlay view ("Full View" --> "Play Areas" --> "Closed" etc.)
---@param playerColor String Color of the player to update the visibility for
NavigationOverlayApi.cycleVisibility = function(playerColor)
getObjectFromGUID(HANDLER_GUID).call("cycleVisibility", playerColor)
end
return NavigationOverlayApi
end

View File

@ -0,0 +1,407 @@
local playmatApi = require("playermat/PlaymatApi")
fullButtonData = {
{ id = "1", width = "84", height = "33", offset = "1 2" }, -- 1. Act/Agenda
{ id = "2", width = "78", height = "69", offset = "1 -62" }, -- 2. Map
{ id = "3", width = "70", height = "36", offset = "-38 -126" }, -- 3. White
{ id = "4", width = "70", height = "36", offset = "38 -126" }, -- 4. Orange
{ id = "5", width = "36", height = "70", offset = "-63 -66" }, -- 5. Green
{ id = "6", width = "36", height = "70", offset = "63 -66" }, -- 6. Red
{ id = "7", width = "38", height = "38", offset = "-65 -3" }, -- 7. Victory
{ id = "8", width = "40", height = "40", offset = "65 -3" }, -- 8. Guide
{ id = "9", width = "56", height = "16", offset = "1 -20" }, -- 9. Player count
{ id = "10", width = "36", height = "16", offset = "1 -102" }, -- 10. Bless/Curse
{ id = "11", width = "168", height = "56", offset = "1 47" }, -- 11. Scenarios
{ id = "12", width = "52", height = "53", offset = "-154 134" }, -- 12. Player card panel
{ id = "13", width = "22", height = "22", offset = "-116 132" }, -- 13. Search card panel
{ id = "14", width = "120", height = "75", offset = "-152 70" }, -- 14. Player card display
{ id = "15", width = "40", height = "54", offset = "-150 -38" }, -- 15. Deck builder
{ id = "16", width = "104", height = "84", offset = "-154 -114" }, -- 16. Rules area
{ id = "17", width = "100", height = "170", offset = "152 72" }, -- 17. Cycle area
{ id = "18", width = "56", height = "60", offset = "182 -124" }, -- 18. Additions
{ id = "19", width = "20", height = "20", offset = "0 150" }, -- 19. Shrink
{ id = "20", width = "20", height = "20", offset = "20 150" }, -- 20. Close
{ id = "21", width = "20", height = "20", offset = "-20 150" } -- 21. Settings
}
playButtonData = {
{ id = "1", width = "80", height = "33", offset = "0 55" },
{ id = "2", width = "78", height = "70", offset = "0 -8" },
{ id = "3", width = "68", height = "32", offset = "-36 -71" },
{ id = "4", width = "68", height = "32", offset = "36 -71" },
{ id = "5", width = "35", height = "66", offset = "-65 -10" },
{ id = "6", width = "35", height = "66", offset = "65 -10" },
{ id = "7", width = "38", height = "38", offset = "-66 52" },
{ id = "8", width = "38", height = "38", offset = "66 52" },
{ id = "9", width = "50", height = "12", offset = "0 33" },
{ id = "10", width = "32", height = "12", offset = "0 -48" },
{ id = "19", width = "20", height = "20", offset = "0 80" },
{ id = "20", width = "20", height = "20", offset = "20 80" },
{ id = "21", width = "20", height = "20", offset = "-20 80" }
}
-- To-Do: dynamically get positions by linking to objects
cameraData = {
{ position = { -1.6, 1.55, 0 }, distance = 18 }, -- 1. Act/Agenda
{ position = { -28, 1.55, 0 }, distance = -1 }, -- 2. Map
{ position = { -31.6, 1.55, 26.4 }, distance = -1 }, -- 3. Green playmat
{ position = { -55, 1.55, 12.05 }, distance = -1 }, -- 4. White playmat
{ position = { -55, 1.55, -11.48 }, distance = -1 }, -- 5. Orange playmat
{ position = { -31.6, 1.55, -26.4 }, distance = -1 }, -- 6. Red playmat
{ position = { -3, 1.55, 30 }, distance = 16 }, -- 7. Victory / SetAside
{ position = { -3, 1.55, -26.76 }, distance = 16 }, -- 8. Guide
{ position = { -11.83, 1.55, 0 }, distance = 10 }, -- 9. Player count
{ position = { -48.35, 1.55, 0 }, distance = 10 }, -- 10. Bless/Curse
{ position = { 12.56, 1.55, 0 }, distance = 45 }, -- 11. Scenarios
{ position = { 57.8, 1.55, 71 }, distance = 22 }, -- 12. Player card panel
{ position = { 60.38, 1.55, 56 }, distance = 10 }, -- 13. Card search panel
{ position = { 27.48, 1.55, 71 }, distance = 35 }, -- 14. Player card area
{ position = { -19.48, 1.55, 71 }, distance = 22 }, -- 15. Deck builder
{ position = { -52.92, 1.55, 71 }, distance = 42 }, -- 16. Rules area
{ position = { 26, 1.55, -71 }, distance = 65 }, -- 17. Cycle area
{ position = { -59.08, 1.55, -83 }, distance = 27 } -- 18. Additions
}
local settingsOpenForColor
local visibility = {}
local claims = {}
local pitch = {}
---------------------------------------------------------
-- save/load functionality
---------------------------------------------------------
function onSave()
return JSON.encode({
visibility = visibility,
claims = claims,
pitch = pitch
})
end
function onLoad(savedData)
if savedData ~= "" then
local loadedData = JSON.decode(savedData)
visibility = loadedData.visibility
claims = loadedData.claims
pitch = loadedData.pitch
else
local allColors = Player.getColors()
for _, color in ipairs(allColors) do
-- default state for claims
claims[color] = {}
-- default state for visibility
visibility[color] = { full = false, play = false }
end
end
createXmlButtons()
updateVisibility()
end
---------------------------------------------------------
-- visibility related functions
---------------------------------------------------------
function cycleVisibility(color)
setVisibility("next", color)
end
function copyVisibility(params)
visibility[params.targetColor] = {
full = visibility[params.startColor].full,
play = visibility[params.startColor].play
}
updateVisibility()
end
function setVisibility(type, color)
if type == "next" then
if visibility[color].full then
visibility[color] = { full = false, play = true }
elseif visibility[color].play then
visibility[color] = { full = false, play = false }
else
visibility[color] = { full = true, play = false }
end
elseif type == "toggle" then
visibility[color] = {
full = not visibility[color].full,
play = not visibility[color].play
}
else
visibility[color] = { full = false, play = false }
end
updateVisibility()
end
-- update XML visibility
function updateVisibility()
local colorString = { full = "", play = "" }
for color, v in pairs(visibility) do
if v.full then
if colorString.full == "" then
colorString.full = color
else
colorString.full = colorString.full .. '|' .. color
end
elseif v.play then
if colorString.play == "" then
colorString.play = color
else
colorString.play = colorString.play .. '|' .. color
end
end
end
-- update the visibility on the XML
UI.setAttribute("navPanelFull", "visibility", colorString.full)
UI.setAttribute("navPanelPlay", "visibility", colorString.play)
UI.setAttribute("navPanelFull", "active", colorString.full ~= "")
UI.setAttribute("navPanelPlay", "active", colorString.play ~= "")
end
---------------------------------------------------------
-- XML button creation
---------------------------------------------------------
function createXmlButtons()
local ui = UI.getXmlTable()
ui = createXmlButtonHelper(ui, {
data = fullButtonData,
id = "navPanelFull",
overlay = "OverlayLarge"
})
ui = createXmlButtonHelper(ui, {
data = playButtonData,
id = "navPanelPlay",
overlay = "OverlaySmall"
})
UI.setXmlTable(ui)
end
-- XML button creation
function createXmlButtonHelper(ui, params)
local color
local guid = self.getGUID()
local xml = findTagWithId(ui, params.id)
-- add basic image
xml.children = { {
tag = "image",
attributes = {
id = "backgroundImage",
image = params.overlay
}
} }
-- add all buttons
for _, d in ipairs(params.data) do
table.insert(xml.children, {
tag = "button",
attributes = {
onClick = guid .. "/buttonClicked",
id = d.id,
height = d.height,
width = d.width,
offsetXY = d.offset,
color = "rgba(0,1,0,0)"
}
})
end
return ui
end
function findTagWithId(ui, id)
for _, obj in ipairs(ui) do
if obj.attributes and obj.attributes.id and obj.attributes.id == id then return obj end
if obj.children then
local result = findTagWithId(obj.children, id)
if result then return result end
end
end
return nil
end
---------------------------------------------------------
-- core functionality
---------------------------------------------------------
-- handles all button clicks
function buttonClicked(player, _, id)
local index = tonumber(id)
if index == 19 then
setVisibility("toggle", player.color)
elseif index == 20 then
setVisibility("close", player.color)
elseif index == 21 then
toggleSettings(player)
else
loadCamera(player, index)
end
end
-- generates a table with rectangular bounds for provided objects
function getDynamicViewBounds(objList)
local count = 0
local totalBounds = {
minX = 0,
maxX = -70,
minZ = 60,
maxZ = -60
}
for _, obj in pairs(objList) do
-- handling for Physics.cast() results
if not obj.type then obj = obj.hit_object end
if not obj.hasTag("CameraZoom_ignore") then
count = count + 1
local bounds = obj.getBounds()
local x1 = bounds['center'][1] - bounds['size'][1] / 2
local x2 = bounds['center'][1] + bounds['size'][1] / 2
local z1 = bounds['center'][3] - bounds['size'][3] / 2
local z2 = bounds['center'][3] + bounds['size'][3] / 2
totalBounds.minX = math.min(x1, totalBounds.minX)
totalBounds.maxX = math.max(x2, totalBounds.maxX)
totalBounds.minZ = math.min(z1, totalBounds.minZ)
totalBounds.maxZ = math.max(z2, totalBounds.maxZ)
end
end
-- default values (mainly for play area if nothing is found)
if count == 0 then
totalBounds.minX = -10
totalBounds.maxX = -50
totalBounds.minZ = -20
totalBounds.maxZ = 20
end
totalBounds.middleX = (totalBounds.maxX + totalBounds.minX) / 2
totalBounds.middleZ = (totalBounds.maxZ + totalBounds.minZ) / 2
totalBounds.diffX = totalBounds.maxX - totalBounds.minX
totalBounds.diffZ = totalBounds.maxZ - totalBounds.minZ
return totalBounds
end
-- loads the specified camera for a player
function loadCamera(player, index)
local lookHere
-- dynamic view of the play area
if index == 2 then
-- search the scripting zone on the play area for objects
local bounds = getDynamicViewBounds(getObjectFromGUID("a2f932").getObjects())
lookHere = {
position = { bounds.middleX, 1.55, bounds.middleZ },
yaw = 90,
distance = 0.8 * math.max(bounds.diffX, bounds.diffZ) + 7
}
-- dynamic view of the clicked play mat
elseif index >= 3 and index <= 6 then
local matColorList = { "White", "Orange", "Green", "Red" }
local matColor = matColorList[index - 2] -- mat index 1 - 4
-- check if anyone (except for yourself) has claimed this color
local isClaimed = false
for playerColor, playerTable in pairs(claims) do
if playerColor ~= player.color and playerTable[matColor] then
isClaimed = true
break
end
end
-- swap to that color if it isn't claimed by someone else
if #getSeatedPlayers() == 1 or not isClaimed then
local newPlayerColor = playmatApi.getPlayerColor(matColor)
copyVisibility({ startColor = player.color, targetColor = newPlayerColor })
player.changeColor(newPlayerColor)
end
-- search on the playmat for objects
local bounds = getDynamicViewBounds(playmatApi.searchPlaymat(matColor))
lookHere = {
position = { bounds.middleX, 0, bounds.middleZ },
yaw = playmatApi.returnRotation(matColor).y + 180,
distance = 0.42 * math.max(bounds.diffX, bounds.diffZ) + 7
}
end
-- get default data if no dynamic view (play area or play mat) was loaded
if not lookHere then
lookHere = cameraData[index]
lookHere.yaw = 90
end
-- set pitch to default if not edited
lookHere.pitch = pitch[player.color] or 75
-- delay is to account for colorswap
Wait.frames(function() player.lookAt(lookHere) end, 2)
end
---------------------------------------------------------
-- settings related functionality
---------------------------------------------------------
-- claims a color for a player
function claimColor(player, color)
local currentState = claims[player.color][color]
claims[player.color][color] = not currentState
end
function loadDefaultSettings(player)
-- reset claims for that player
for _, color in ipairs(Player.getColors()) do
claims[player.color][color] = (player.color == color)
end
-- reset pitch for that player
pitch[player.color] = nil
-- update the UI accordingly
updateSettingsUI(player)
end
-- called by clicking a toggle
function toggleSettings(player)
if settingsOpenForColor == player.color then
settingsOpenForColor = nil
UI.setAttribute("navPanelSettings", "active", false)
elseif settingsOpenForColor then
broadcastToColor("Someone else is currently using the settings. Please wait and try again.", player.color, "Yellow")
else
settingsOpenForColor = player.color
updateSettingsUI(player)
UI.setAttribute("navPanelSettings", "visibility", player.color)
UI.setAttribute("navPanelSettings", "active", true)
end
end
-- called by the slider
function updatePitch(player, number)
pitch[player.color] = number
end
-- updates the settings UI for the provided player
function updateSettingsUI(player)
-- update the slider
UI.setAttribute("sliderPitch", "value", pitch[player.color] or 75)
-- update the claims
local matColorList = { "White", "Orange", "Green", "Red" }
for _, matColor in pairs(matColorList) do
UI.setAttribute("claim" .. matColor, "isOn", claims[player.color][matColor] or false)
end
end

View File

@ -1,5 +1,6 @@
local tokenManager = require("core/token/TokenManager")
local tokenChecker = require("core/token/TokenChecker")
local navigationOverlayApi = require("core/NavigationOverlayApi")
-- set true to enable debug logging and show Physics.cast()
local DEBUG = false
@ -154,6 +155,10 @@ function searchArea(origin, size)
})
end
function searchAroundSelf()
return searchArea(PLAY_ZONE_POSITION, PLAY_ZONE_SCALE)
end
function doNotReady(card)
return card.getVar("do_not_ready") or false
end
@ -240,7 +245,7 @@ function doUpkeep(_, clickedByColor, isRightClick)
-- unexhaust cards in play zone, flip action tokens and find forcedLearning
local forcedLearning = false
for _, v in ipairs(searchArea(PLAY_ZONE_POSITION, PLAY_ZONE_SCALE)) do
for _, v in ipairs(searchAroundSelf()) do
local obj = v.hit_object
if obj.getDescription() == "Action Token" and obj.is_face_down then
obj.flip()
@ -500,6 +505,7 @@ function changeColor(clickedByColor)
-- if the seated player clicked this, reseat him to the new color
if clickedByColor == playerColor then
navigationOverlayApi.copyVisibility(playerColor, color)
Player[playerColor].changeColor(color)
end
@ -538,7 +544,7 @@ function replenishTokens(card, count, replenish)
-- handling Runic Axe upgrade sheet for additional replenish
if card.getName() == "Runic Axe" then
for _, v in ipairs(searchArea(PLAY_ZONE_POSITION, PLAY_ZONE_SCALE)) do
for _, v in ipairs(searchAroundSelf()) do
local obj = v.hit_object
if obj.tag == "Card" then
local notes = JSON.decode(obj.getGMNotes()) or {}
@ -572,7 +578,7 @@ end
function syncCustomizableMetadata(card)
local cardMetadata = JSON.decode(card.getGMNotes()) or { }
if cardMetadata ~= nil and cardMetadata.customizations ~= nil then
for _, collision in ipairs(searchArea(PLAY_ZONE_POSITION, PLAY_ZONE_SCALE)) do
for _, collision in ipairs(searchAroundSelf()) do
local obj = collision.hit_object
if obj.name == "Card" or obj.name == "CardCustom" then
local notes = JSON.decode(obj.getGMNotes()) or { }

View File

@ -59,6 +59,13 @@ do
return "NOT_FOUND"
end
-- Returns the result of a cast in the specificed playermat's area
---@param matColor String Color of the playermat
PlaymatApi.searchPlaymat = function(matColor)
local mat = getObjectFromGUID(MAT_IDS[matColor])
return mat.call("searchAroundSelf")
end
-- Returns if there is the card "Dream-Enhancing Serum" on the requested playermat
---@param matColor String Color of the playermat
PlaymatApi.isDES = function(matColor)

View File

@ -30,7 +30,7 @@
rectAlignment="LowerRight"
width="35"
height="146"
offsetXY="-1 80"
offsetXY="-1 120"
spacing="2">
<Button icon="cthulhu"
tooltip="Campaigns"
@ -46,6 +46,20 @@
onClick="onClick_toggleUi(Options)"/>
</VerticalLayout>
<!-- Navigation Overlay button (not visibly to Grey and Black) -->
<Panel visibility="White|Brown|Red|Orange|Yellow|Green|Teal|Blue|Purple|Pink"
color="#000000"
outlineSize="1 1"
outline="#303030"
rectAlignment="LowerRight"
width="35"
height="35"
offsetXY="-1 65">
<Button icon="NavigationOverlayIcon"
tooltip="Navigation Overlay"
onClick="onClick_toggleUi(Navigation Overlay)"/>
</Panel>
<!-- Basic UI that will be replaced based on title -->
<VerticalLayout id="load_ui"
visibility="Admin"
@ -97,29 +111,7 @@
</Panel>
</VerticalLayout>
<!-- Title Splash when starting a scenario -->
<Panel id="title_splash"
height="220"
position="0 250 0"
showAnimation="FadeIn"
hideAnimation="FadeOut"
active="false"
animationDuration="2">
<Image id="title_gradient"
height="220"
image="TitleGradient" />
<Text id="title_splash_text"
width="95%"
height="180"
resizeTextForBestFit="true"
resizeTextMinSize="100"
resizeTextMaxSize="150"
font="font_teutonic-arkham"
outline="black"
outlineSize="3 -3"
horizontalOverflow="Overflow">
</Text>
</Panel>
<Include src="TitleSplash.xml"/>
<Include src="NavigationOverlay.xml"/>
<Include src="OptionPanel.xml"/>
<Include src="UpdateNotification.xml"/>

172
xml/NavigationOverlay.xml Normal file
View File

@ -0,0 +1,172 @@
<!-- Default formatting -->
<Defaults>
<Text color="#FFFFFF"
alignment="MiddleLeft" />
<Toggle isOn="False"
rectAlignment="MiddleRight" />
<Cell dontUseTableCellBackground="true"
outlineSize="0 1"
outline="grey" />
<!-- options -->
<Row class="nav_option-text"
preferredHeight="45"/>
<Cell class="nav_option-text"
color="#333333"/>
<Cell class="nav_option-button"
color="#333333"/>
<Text class="nav_option-header"
fontSize="20"
font="font_teutonic-arkham"/>
<Cell class="claim"
tooltip="Clicking this seat in the navigation overlay will now only swap the playercolor for you."
tooltipPosition="Right" />
<!-- buttons at the bottom -->
<Button class="bottomButtons"
hoverClass="hover"
pressClass="press"
selectClass="select"
color="#888888"
minHeight="35"
fontSize="24"
font="font_teutonic-arkham"/>
<Button class="hover"
color="grey"/>
<Button class="press"
color="white"/>
<Button class="select"
color="white"/>
<!-- Navigation Panels -->
<Panel class="navPanel"
active="false"
allowDragging="true"
rectAlignment="LowerRight"
returnToOriginalPositionWhenReleased="false"
offsetXY="-40 0">
</Panel>
</Defaults>
<!-- full Panel -->
<Panel id="navPanelFull"
height="358"
width="455"
class="navPanel">
</Panel>
<!-- Play Area only -->
<Panel id="navPanelPlay"
height="208"
width="205"
class="navPanel">
</Panel>
<!-- Settings -->
<TableLayout id="navPanelSettings"
active="false"
width="300"
height="335"
color="#000000"
outlineSize="2 2"
outline="grey"
rectAlignment="MiddleCenter">
<!-- Header -->
<Row preferredHeight="60">
<Cell>
<Panel padding="10 0 0 0">
<Text font="font_teutonic-arkham"
fontSize="35">Navigation Overlay</Text>
</Panel>
</Cell>
</Row>
<!-- Options -->
<Row>
<Cell>
<TableLayout columnWidths="0 125"
autoCalculateHeight="1"
cellPadding="10 0 5 5">
<!-- Option: Custom pitch -->
<Row class="nav_option-text">
<Cell class="nav_option-text">
<Text class="nav_option-header">Viewing angle in degrees:</Text>
</Cell>
<Cell class="nav_option-button">
<Slider id="sliderPitch"
onValueChanged="797ede/updatePitch"
wholeNumbers="true"
minValue="0"
maxValue="90"
value="75"
tooltip="This controls the camera pitch ('nodding your head')."
tooltipPosition="Right"/>
</Cell>
</Row>
<!-- Option: Claim White -->
<Row class="nav_option-text">
<Cell class="nav_option-text">
<Text class="nav_option-header">Claim "White" seat</Text>
</Cell>
<Cell class="nav_option-button claim">
<Toggle id="claimWhite"
onValueChanged="797ede/claimColor(White)"/>
</Cell>
</Row>
<!-- Option: Claim Orange -->
<Row class="nav_option-text">
<Cell class="nav_option-text">
<Text class="nav_option-header">Claim "Orange" seat</Text>
</Cell>
<Cell class="nav_option-button claim">
<Toggle id="claimOrange"
onValueChanged="797ede/claimColor(Orange)"/>
</Cell>
</Row>
<!-- Option: Claim Green -->
<Row class="nav_option-text">
<Cell class="nav_option-text">
<Text class="nav_option-header">Claim "Green" seat</Text>
</Cell>
<Cell class="nav_option-button claim">
<Toggle id="claimGreen"
onValueChanged="797ede/claimColor(Green)"/>
</Cell>
</Row>
<!-- Option: Claim Red -->
<Row class="nav_option-text">
<Cell class="nav_option-text">
<Text class="nav_option-header">Claim "Red" seat</Text>
</Cell>
<Cell class="nav_option-button claim">
<Toggle id="claimRed"
onValueChanged="797ede/claimColor(Red)"/>
</Cell>
</Row>
</TableLayout>
</Cell>
</Row>
<!-- Buttons: Defaults and Close -->
<Row preferredHeight="50">
<Cell>
<HorizontalLayout minHeight="55"
flexibleHeight="0"
padding="10 10 5 10"
spacing="35">
<Button class="bottomButtons"
onClick="797ede/loadDefaultSettings">Load defaults</Button>
<Button class="bottomButtons"
onClick="797ede/toggleSettings">Close</Button>
</HorizontalLayout>
</Cell>
</Row>
</TableLayout>

View File

@ -303,22 +303,6 @@
</Cell>
</Row>
<!-- Option: show navigation overlay -->
<Row class="option-text">
<Cell class="option-text">
<VerticalLayout class="text-column">
<Text class="option-header">Navigation Overlay</Text>
<Text class="description">This enables an overlay for quickly moving the camera to various points on the table.</Text>
</VerticalLayout>
</Cell>
<Cell class="option-button">
<Toggle id="showNavigationOverlay"
onValueChanged="onClick_toggleOption(showNavigationOverlay)"/>
</Cell>
</Row>
<!-- Option: show search assistant -->
<Row class="option-text">
<Cell class="option-text">

23
xml/TitleSplash.xml Normal file
View File

@ -0,0 +1,23 @@
<!-- Title Splash when starting a scenario -->
<Panel id="title_splash"
height="220"
position="0 250 0"
showAnimation="FadeIn"
hideAnimation="FadeOut"
active="false"
animationDuration="2">
<Image id="title_gradient"
height="220"
image="TitleGradient" />
<Text id="title_splash_text"
width="95%"
height="180"
resizeTextForBestFit="true"
resizeTextMinSize="100"
resizeTextMaxSize="150"
font="font_teutonic-arkham"
outline="black"
outlineSize="3 -3"
horizontalOverflow="Overflow">
</Text>
</Panel>