revamped window with tabs

This commit is contained in:
Chr1Z93 2023-10-13 13:01:43 +02:00
parent 2cee7df57f
commit 04f337482a
4 changed files with 237 additions and 181 deletions

View File

@ -44,6 +44,8 @@ local hideTitleSplashWaitFunctionId = nil
local MOD_VERSION = "3.3.0" local MOD_VERSION = "3.3.0"
local SOURCE_REPO = 'https://raw.githubusercontent.com/chr1z93/loadable-objects/main' local SOURCE_REPO = 'https://raw.githubusercontent.com/chr1z93/loadable-objects/main'
local library, requestObj, modMeta, notificationVisible local library, requestObj, modMeta, notificationVisible
local downloadWindowVisible = false
local optionPanelVisible = false
local acknowledgedUpgradeVersions = {} local acknowledgedUpgradeVersions = {}
-- optionPanel data -- optionPanel data
@ -141,8 +143,10 @@ function onLoad(savedData)
resetChaosTokenStatTracker() resetChaosTokenStatTracker()
getModVersion() getModVersion()
onClick_refreshList()
math.randomseed(os.time()) math.randomseed(os.time())
-- initialization of loadable objects library
requestObj = WebRequest.get(SOURCE_REPO .. '/library.json', completed_list_update)
end end
-- Event hook for any object search. When chaos tokens are manipulated while the chaos bag -- Event hook for any object search. When chaos tokens are manipulated while the chaos bag
@ -620,66 +624,110 @@ end
-- Content Importing and XML functions -- Content Importing and XML functions
--------------------------------------------------------- ---------------------------------------------------------
function onClick_refreshList() -- forwards the requested content type to the update function
local request = WebRequest.get(SOURCE_REPO .. '/library.json', completed_list_update) ---@param player LuaPlayer Player that triggered this
requestObj = request ---@param contentToShow String Name of the content type to show
startLuaCoroutine(Global, 'downloadCoroutine') function onClick_tab(player, contentToShow)
update_list(contentToShow)
end end
-- click function for the items in the download window
function onClick_select(player, params) function onClick_select(player, params)
params = JSON.decode(urldecode(params)) params = JSON.decode(urldecode(params))
local url = SOURCE_REPO .. '/' .. params.url local url = SOURCE_REPO .. '/' .. params.url
local request = WebRequest.get(url, function (request) complete_obj_download(request, params) end ) requestObj = WebRequest.get(url, function (request) complete_obj_download(request, params) end )
requestObj = request
startLuaCoroutine(Global, 'downloadCoroutine') startLuaCoroutine(Global, 'downloadCoroutine')
end end
function onClick_load()
UI.show('progress_display')
UI.hide('load_button')
end
function onClick_toggleUi(player, title)
if title == "Navigation Overlay" then
navigationOverlayApi.cycleVisibility(player.color)
return
end
UI.hide('optionPanel')
UI.hide('load_ui')
-- when same button is clicked or close window button is pressed, don't open UI
if UI.getValue('title') ~= title and title ~= 'Hidden' then
UI.setValue('title', title)
if title == "Options" then
UI.show('optionPanel')
else
update_window_content(title)
UI.show('load_ui')
end
else
UI.setValue('title', "Hidden")
end
end
function downloadCoroutine() function downloadCoroutine()
while requestObj do while requestObj do
UI.setAttribute('download_progress', 'percentage', requestObj.download_progress * 100) UI.setAttribute('download_progress', 'percentage', requestObj.download_progress * 100)
coroutine.yield(0) coroutine.yield(0)
end end
UI.setAttribute('download_progress', 'percentage', 100)
return 1 return 1
end end
function update_list(objects) -- toggles the visibility of the respective UI
---@param player LuaPlayer Player that triggered this
---@param title String Name of the UI to toggle
function onClick_toggleUi(player, title)
if title == "Navigation Overlay" then
navigationOverlayApi.cycleVisibility(player.color)
elseif title == "Downloadable Content" then
if downloadWindowVisible then
UI.hide('downloadWindow')
else
UI.show('downloadWindow')
end
downloadWindowVisible = not downloadWindowVisible
elseif title == "Options" then
if optionPanelVisible then
UI.hide('optionPanel')
else
UI.show('optionPanel')
end
optionPanelVisible = not optionPanelVisible
end
end
-- formats the json response from the webrequest into a key-value lua table
-- strips the prefix from the community content items
function formatLibrary(json_response)
library = {}
library["campaigns"] = json_response.campaigns
library["scenarios"] = json_response.scenarios
library["extras"] = json_response.extras
library["fanmadeCampaigns"] = {}
library["fanmadeScenarios"] = {}
library["fanmadePlayerCards"] = {}
for _, item in ipairs(json_response.community) do
local identifier = nil
for str in string.gmatch(item.name, "([^:]+)") do
if not identifier then
-- grab the first part to know the content type
identifier = str
else
-- update the name without the content type
item.name = str
break
end
end
if identifier == "Fan Investigators" then
table.insert(library["fanmadePlayerCards"], item)
elseif identifier == "Fan Campaign" then
table.insert(library["fanmadeCampaigns"], item)
elseif identifier == "Fan Scenario" then
table.insert(library["fanmadeScenarios"], item)
end
end
end
-- updates the window content to the requested content
---@param contentToShow String Type of content to show
function update_list(contentToShow)
if not library then return end
local ui = UI.getXmlTable() local ui = UI.getXmlTable()
-- set title according to type
local cleanName = {
campaigns = "Campaigns",
scenarios = "Scenarios",
fanmadeCampaigns = "Fan-Made Campaigns",
fanmadePlayerCards = "Fan-Made Player Cards",
fanmadeScenarios = "Fan-Made Scenarios"
}
local titleText = find_tag_with_id(ui, "title")
titleText.value = "Downloable Content: " .. cleanName[contentToShow]
local update_height = find_tag_with_id(ui, 'ui_update_height') local update_height = find_tag_with_id(ui, 'ui_update_height')
local update_children = find_tag_with_id(update_height.children, 'ui_update_point') local update_children = find_tag_with_id(update_height.children, 'ui_update_point')
update_children.children = {} update_children.children = {}
for _, v in ipairs(objects) do for _, v in ipairs(library[contentToShow]) do
local s = JSON.encode(v);
table.insert(update_children.children, table.insert(update_children.children,
{ tag = 'Text', { tag = 'Text',
value = v.name, value = v.name,
@ -691,47 +739,35 @@ function update_list(objects)
UI.setXmlTable(ui) UI.setXmlTable(ui)
end end
function update_window_content(new_title) -- called after the webrequest of downloading an item
if not library then return end -- deletes the placeholder and spawns the downloaded item
if new_title == 'Campaigns' then
update_list(library.campaigns)
elseif new_title == 'Standalone Scenarios' then
update_list(library.scenarios)
elseif new_title == 'Investigators' then
update_list(library.investigators)
elseif new_title == 'Community Content' then
update_list(library.community)
elseif new_title == 'Extras' then
update_list(library.extras)
else
update_list({})
end
end
function complete_obj_download(request, params) function complete_obj_download(request, params)
assert(request.is_done) assert(request.is_done)
if request.is_error or request.response_code ~= 200 then if request.is_error or request.response_code ~= 200 then
print('error: ' .. request.error) print('error: ' .. request.error)
else else
if pcall(function() if pcall(function()
local replaced_object local replacedObject
pcall(function() pcall(function()
if params.replace then if params.replace then
replaced_object = getObjectFromGUID(params.replace) replacedObject = getObjectFromGUID(params.replace)
end end
end) end)
local json = request.text if replacedObject then
if replaced_object then local pos = replacedObject.getPosition()
local pos = replaced_object.getPosition() local rot = replacedObject.getRotation()
local rot = replaced_object.getRotation() local scale = replacedObject.getScale()
local scale = replaced_object.getScale() destroyObject(replacedObject)
destroyObject(replaced_object)
Wait.frames(function() Wait.frames(function()
spawnObjectJSON({ json = json, position = pos, rotation = rot, scale = scale }) spawnObjectJSON({
json = request.text,
position = pos,
rotation = rot,
scale = scale
})
end, 1) end, 1)
else else
spawnObjectJSON({json = json}) spawnObjectJSON({ json = request.text })
end end
end) then end) then
print('Object loaded.') print('Object loaded.')
@ -739,17 +775,16 @@ function complete_obj_download(request, params)
print('Error loading object.') print('Error loading object.')
end end
end end
requestObj = nil requestObj = nil
UI.setAttribute('download_progress', 'percentage', 100)
end end
-- the download button on the placeholder objects calls this to directly initiate a download -- the download button on the placeholder objects calls this to directly initiate a download
-- params is a table with url and guid of replacement object, which happens to match what onClick_select wants ---@param params Table contains url and guid of replacement object, which happens to match what onClick_select wants
function placeholder_download(params) function placeholder_download(params)
onClick_select(nil, JSON.encode(params)) onClick_select(nil, JSON.encode(params))
end end
-- downloading of the library file
function completed_list_update(request) function completed_list_update(request)
assert(request.is_done) assert(request.is_done)
if request.is_error or request.response_code ~= 200 then if request.is_error or request.response_code ~= 200 then
@ -757,17 +792,18 @@ function completed_list_update(request)
else else
local json_response = nil local json_response = nil
if pcall(function () json_response = JSON.decode(request.text) end) then if pcall(function () json_response = JSON.decode(request.text) end) then
library = json_response formatLibrary(json_response)
update_window_content(UI.getValue('title')) update_list("campaigns")
else else
print('error parsing downloaded library') print('error parsing downloaded library')
end end
end end
requestObj = nil requestObj = nil
UI.setAttribute('download_progress', 'percentage', 100)
end end
-- loops through an XML table and returns the specified object
---@param ui Table XmlTable (get this via getXmlTable)
---@param id String Id of the object to return
function find_tag_with_id(ui, id) function find_tag_with_id(ui, id)
for _, obj in ipairs(ui) do for _, obj in ipairs(ui) do
if obj.attributes and obj.attributes.id and obj.attributes.id == id then return obj end if obj.attributes and obj.attributes.id and obj.attributes.id == id then return obj end

41
xml/BottomBar.xml Normal file
View File

@ -0,0 +1,41 @@
<Defaults>
<Button class="navbar"
tooltipPosition="Left"
tooltipBackgroundColor="rgba(0,0,0,1)"
color="clear"/>
</Defaults>
<!-- Buttons at the bottom right (height: n * 37 - 2) -->
<VerticalLayout visibility="Admin"
color="#000000"
outlineSize="1 1"
outline="#303030"
rectAlignment="LowerRight"
width="35"
height="72"
offsetXY="-1 120"
spacing="2">
<Button class="navbar"
icon="devourer"
tooltip="Downloadable Content"
onClick="onClick_toggleUi(Downloadable Content)"/>
<Button class="navbar"
icon="option-gear"
tooltip="Options"
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 85">
<Button class="navbar"
icon="NavigationOverlayIcon"
tooltip="Navigation Overlay"
onClick="onClick_toggleUi(Navigation Overlay)"/>
</Panel>

83
xml/DownloadWindow.xml Normal file
View File

@ -0,0 +1,83 @@
<Defaults>
<!-- download tab buttons -->
<Button class="downloadTab"
hoverClass="hover"
pressClass="press"
color="#888888"
fontSize="24"
font="font_teutonic-arkham"/>
<Button class="hover"
color="grey"/>
<Button class="press"
color="white"/>
</Defaults>
<!-- window to select downloadable content -->
<VerticalLayout id="downloadWindow"
visibility="Admin"
color="black"
active="false"
width="700"
height="780"
outlineSize="1 1"
outline="#303030">
<!-- header -->
<Panel preferredHeight="60"
padding="10 10 5 0">
<Panel preferredWidth="500">
<Text id="title"
fontSize="32"
font="font_teutonic-arkham"
alignment="MiddleLeft">Downloadable Content</Text>
</Panel>
<Panel>
<Button rectAlignment="MiddleRight"
width="50"
color="clear"
icon="close"
tooltip="Close"
onClick="onClick_toggleUi(Downloadable Content)"/>
</Panel>
</Panel>
<!-- tab selection -->
<HorizontalLayout preferredHeight="60"
padding="5"
spacing="5">
<Button class="downloadTab"
onClick="onClick_tab(campaigns)">Official Campaigns</Button>
<Button class="downloadTab"
onClick="onClick_tab(scenarios)">Official Scenarios</Button>
<Button class="downloadTab"
onClick="onClick_tab(fanmadeCampaigns)">Fan-Made Campaigns</Button>
<Button class="downloadTab"
onClick="onClick_tab(fanmadeScenarios)">Fan-Made Scenarios</Button>
<Button class="downloadTab"
onClick="onClick_tab(fanmadePlayerCards)">Fan-Made Player Cards</Button>
</HorizontalLayout>
<!-- content list -->
<VerticalScrollView color="transparent"
minHeight="100"
flexibleHeight="100">
<Panel id="ui_update_height"
height="24">
<VerticalLayout id="ui_update_point"
padding="10">
<Text>Please refresh to see available items.</Text>
</VerticalLayout>
</Panel>
</VerticalScrollView>
<!-- download progress bar -->
<Panel preferredHeight="50"
padding="5">
<ProgressBar id="download_progress"
height="40"
percentage="0"
color="#111111"
textColor="#aaaaaa"
fillImageColor="#333333"/>
</Panel>
</VerticalLayout>

View File

@ -3,114 +3,10 @@
<!-- general Stuff --> <!-- general Stuff -->
<Text color="white" <Text color="white"
fontSize="18"/> fontSize="18"/>
<Button tooltipPosition="Left"
color="clear"/>
<!-- Window -->
<HorizontalLayout class="headerLayout"
height="75"
padding="5"/>
<Button class="headerButton"
minWidth="50"
preferredWidth="50"
flexibleWidth="0"
color="clear"/>
<Text class="headerText"
minWidth="200"
flexibleWidth="100"
fontSize="32"
font="font_teutonic-arkham"/>
</Defaults> </Defaults>
<!-- Buttons at the bottom right (height: n * 35 + (n-1) * 2) --> <Include src="BottomBar.xml"/>
<VerticalLayout visibility="Admin" <Include src="DownloadWindow.xml"/>
color="#000000"
outlineSize="1 1"
outline="#303030"
rectAlignment="LowerRight"
width="35"
height="146"
offsetXY="-1 120"
spacing="2">
<Button icon="cthulhu"
tooltip="Campaigns"
onClick="onClick_toggleUi(Campaigns)"/>
<Button icon="dark-cult"
tooltip="Standalone Scenarios"
onClick="onClick_toggleUi(Standalone Scenarios)"/>
<Button icon="devourer"
tooltip="Community Content"
onClick="onClick_toggleUi(Community Content)"/>
<Button icon="option-gear"
tooltip="Options"
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"
color="black"
active="false"
width="700"
height="780"
outlineSize="1 1"
outline="#303030">
<HorizontalLayout class="headerLayout">
<Button class="headerButton"
icon="refresh"
tooltip="Refresh List"
tooltipPosition="Right"
onClick="onClick_refreshList"/>
<Text id="title"
class="headerText">Loadable Items</Text>
<Button class="headerButton"
icon="close"
tooltip="Close"
onClick="onClick_toggleUi(Hidden)"/>
</HorizontalLayout>
<VerticalScrollView color="transparent"
minHeight="100"
flexibleHeight="100">
<Panel id="ui_update_height"
height="24">
<VerticalLayout id="ui_update_point"
padding="10">
<Text>Please refresh to see available items.</Text>
</VerticalLayout>
</Panel>
</VerticalScrollView>
<Panel color="rgb(0,0,0)"
minHeight="50"
preferredHeight="50"
flexibleHeight="0">
<Button id="load_button"
active="false"
onClick="onClick_load">Load:</Button>
<HorizontalLayout id="progress_display">
<ProgressBar id="download_progress"
percentage="0"
color="#000000"
fillImageColor="#333333"/>
<Button onClick="onClick_cancel"
active="false">Cancel</Button>
</HorizontalLayout>
</Panel>
</VerticalLayout>
<Include src="TitleSplash.xml"/> <Include src="TitleSplash.xml"/>
<Include src="NavigationOverlay.xml"/> <Include src="NavigationOverlay.xml"/>
<Include src="OptionPanel.xml"/> <Include src="OptionPanel.xml"/>