Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add mission dialogue rmlui widget #4233

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 86 additions & 0 deletions luaui/Widgets/gui_mission_dialogue.lua
RebelNode marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
-- todo: disable widget if we are not playing a mission

-- Usage example in other widgets / mission api: WG['mission_dialogue'].SendDialogue("Some Dude","Hello World!", "somedude.png", "left", "dialogue1.wav", 5)
-- somedude.png must be in "/luaui/images/character_portraits/" and dialogue1.wav must be in "/luaui/sounds/mission_dialogue/".

function widget:GetInfo()
return {
name = "Mission Dialogue",
desc = "Draws dialogue popups with character portraits",
author = "RebelNode",
date = "2025",
license = "GNU GPL, v2 or later",
layer = 1,
handler = true,
enabled = true
}
end
local datamodelHandle
local popupTimer = 0
local popupTimeout = 5
local spPlaySoundFile = Spring.PlaySoundFile

local function SendDialogue(characterName, message, characterPortrait, side, soundfile, popupTimeoutIn)
datamodelHandle.characterName = characterName
datamodelHandle.message = message

if popupTimeoutIn then
popupTimeout = popupTimeoutIn
else
popupTimeout = 5
end

characterPortraitElement:SetAttribute("src", "/luaui/images/character_portraits/" .. characterPortrait)

-- For whatever reason using `characterPortraitElement.style.marginleft = "auto"` doesn't work so we use SetAttribute instead
if side == "left" then
characterPortraitElement:SetAttribute("style", "display: block; margin-left: 0px;")
end
if side == "right" then
characterPortraitElement:SetAttribute("style", "display: block; margin-left: auto;")
end

document:Show()
popupTimer = 0

if soundfile then
spPlaySoundFile("luaui/sounds/mission_dialogue/" .. soundfile, 10, nil, "sfx")
end
end

function widget:Initialize()
widget.rmlContext = RmlUi.CreateContext(widget.whInfo.name)

-- only keys declared at the DataModel's creation can be used
datamodelHandle = widget.rmlContext:OpenDataModel("mission_dialogue", {
characterName = "Some dude",
message = "Hello world!"
});
document = widget.rmlContext:LoadDocument("LuaUi/Widgets/rml/gui_dialogue.rml", widget)
document:ReloadStyleSheet()

characterPortraitElement = document:GetElementById("characterPortrait")

WG['mission_dialogue'] = {}
WG['mission_dialogue'].SendDialogue = SendDialogue

end

function widget:Update(dt)

--hide dialogue popup after a while
popupTimer = popupTimer + dt
if popupTimer > popupTimeout then
Copy link
Contributor

@badosu badosu Jan 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After the first time the document is hidden won't it be spamming calls to document:Hide() again? Even then, would be good to not even have the update callin when the dialogue is unused.

I'd suggest registering the :Update callin once the dialog is shown, and deregistering when it's hidden. Deregistering on initialization.

See

widgetHandler:UpdateCallIn('GameFrame');
else
widgetHandler:RemoveCallIn('GameFrame');
as an example of dynamic callin registration.

document:Hide()
popupTimer = 0
end
end

function widget:Shutdown()
if document then
document:Close()
end
if widget.rmlContext then
RebelNode marked this conversation as resolved.
Show resolved Hide resolved
RmlUi.RemoveContext(widget.whInfo.name)
end
end
10 changes: 10 additions & 0 deletions luaui/Widgets/rcss/bar_ui.rcss
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
.element {
padding: 4px;
/*border-radius: 8px;*/
border: 2px black;
background-color: rgba(0%, 0%, 0%, 60%);
image-color: rgba(100%, 100%, 100%, 1%);
/*backdrop-filter is not working :( */
backdrop-filter: blur(5px);
}

97 changes: 97 additions & 0 deletions luaui/Widgets/rcss/default_styles.rcss
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/*
* Default styles for all the basic elements.
*/

* {
box-sizing: border-box;
font-family: "Exo 2";
font-size: 20px;
}

body, div, p, hr, pre,
h1, h2, h3, h4, h5, h6,
tabset tabs {
display: block;
}

h1 {
font-size: 2em;
margin: .5em 0;
}

h2 {
font-size: 1.5em;
margin: .5em 0;
}

h3 {
font-size: 1.17em;
margin: .5em 0;
}

h4 {
margin: .5em 0;
}

h5 {
font-size: .83em;
margin: .25em 0;
}

h6 {
font-size: .75em;
margin: .25em 0;
}

h1, h2, h3, h4,
h5, h6, strong {
font-weight: bold;
}

em {
font-style: italic;
}

pre {
white-space: pre;
}

hr {
border-width: 1px;
}

table {
box-sizing: border-box;
display: table;
}

tr {
box-sizing: border-box;
display: table-row;
}

td {
box-sizing: border-box;
display: table-cell;
}

col {
box-sizing: border-box;
display: table-column;
}

colgroup {
display: table-column-group;
}

thead, tbody, tfoot {
display: table-row-group;
}

handle[size_target] {
cursor: nwse-resize;
}

handle[move_target] {
cursor: move;
}
26 changes: 26 additions & 0 deletions luaui/Widgets/rml/gui_dialogue.rml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<rml style="border: 0">
<head style="border: 0">
<link type="text/rcss" href="/LuaUI/Widgets/rcss/default_styles.rcss"/>
<link type="text/rcss" href="/LuaUI/Widgets/rcss/bar_ui.rcss"/>
</head>
<body
data-model="mission_dialogue"
style="top: 55%; left: 21%; width: 600px; height: 70%; border: 0"
>

<div style="background-color: transparent; border: 0; min-width: 600px;">
<!-- "margin-left: auto" puts the image on the right side of the dialogue, leaving it out puts it on the left side -->
<!-- todo: make the actual image area smaller so player can click through the transparent part-->
<!-- todo: make it possible to mirror images so that all art can be drawn "left side" and then flipped when needed to be displayed on the right side-->
<!-- todo: style the widget more into BAR UI graphical style-->
<img width="300" height="250" id="characterPortrait" style="display: block; margin-left: 0px" src="";/> <!--&gt-->
</div>
<div class="element">
<h3 class="element" style="margin: 0.1em">{{characterName}}</h3>
<div style="height: 150px">{{message}}

</div>

</div>
</body>
</rml>