Skip to content

Commit

Permalink
Merge pull request #443 from MihailRis/notifications
Browse files Browse the repository at this point in the history
Notifications
  • Loading branch information
MihailRis authored Jan 18, 2025
2 parents 88ed15c + 432dc38 commit ce63b1b
Show file tree
Hide file tree
Showing 19 changed files with 208 additions and 64 deletions.
1 change: 1 addition & 0 deletions doc/en/scripting/ui.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ Common element methods:
| ------------------- | ----------------------------------------------------------------------------------- |
| moveInto(container) | moves the element to the specified container (the element is specified, not the id) |
| destruct() | removes element |
| reposition() | updates the element position based on the `positionfunc` |

## Containers

Expand Down
2 changes: 2 additions & 0 deletions doc/en/xml-ui-layouts.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ Examples:
- `margin` - element margin. Type: 4D vector
*left, top, right, bottom*
- `visible` - element visibility. Type: boolean (true/false)
- `min-size` - minimal element size. Type: 2D vector.
- `position-func` - position supplier for an element (two numbers), called on every parent container size update or on element adding on a container. May be called before *on_hud_open*
- `size-func` - element size provider (two numbers), called when the size of the container in which the element is located changes, or when an element is added to the container. Can be called before on_hud_open is called.
- `onclick` - lua function called when an element is clicked.
Expand Down Expand Up @@ -65,6 +66,7 @@ Buttons and panels are also containers.
Buttons are also panels.

- `max-length` - maximal length of panel stretching before scrolling (if scrollable = true). Type: number
- `min-length` - minimal length of panel. Type: number
- `orientation` - panel orientation: horizontal/vertical.

# Common elements
Expand Down
1 change: 1 addition & 0 deletions doc/ru/scripting/ui.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ document["worlds-panel"]:clear()
| ------------------- | ----------------------------------------------------------------------- |
| moveInto(container) | перемещает элемент в указанный контейнер (указывается элемент, а не id) |
| destruct() | удаляет элемент |
| reposition() | обновляет позицию элемента на основе функции позиционирования |

## Контейнеры

Expand Down
2 changes: 2 additions & 0 deletions doc/ru/xml-ui-layouts.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
- `margin` - внешний отступ элемента. Тип: 4D вектор.
Порядок: `"left,top,right,bottom"`
- `visible` - видимость элемента. Тип: логический ("true"/"false").
- `min-size` - минимальный размер элемента. Тип: 2D вектор.
- `position-func` - поставщик позиции элемента (два числа), вызываемый при изменении размера контейнера, в котором находится элемент, либо при добавлении элемента в контейнер. Может быть вызван до вызова on_hud_open.
- `size-func` - поставщик размера элемента (два числа), вызываемый при изменении размера контейнера, в котором находится элемент, либо при добавлении элемента в контейнер. Может быть вызван до вызова on_hud_open.
- `onclick` - lua функция вызываемая при нажатии на элемент.
Expand Down Expand Up @@ -67,6 +68,7 @@

В число панелей также входят кнопки.
- `max-length` - максимальная длина, на которую растягивается панель до начала скроллинга (если scrollable = true). Тип: число
- `min-length` - минимальная длина панели. Тип: число
- `orientation` - ориентация панели: horizontal/vertical.

# Основные элементы
Expand Down
11 changes: 11 additions & 0 deletions res/layouts/console.xml.lua
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,10 @@ function add_to_history(text)
end

function submit(text)
if #text == 0 then
document.prompt.focused = true
return
end
text = text:trim()
add_to_history(text)

Expand Down Expand Up @@ -204,4 +208,11 @@ function on_open(mode)
elseif mode then
modes:set(mode)
end
hud.close("core:ingame_chat")
end

function on_close()
time.post_runnable(function()
hud.open_permanent("core:ingame_chat")
end)
end
8 changes: 8 additions & 0 deletions res/layouts/ingame_chat.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<panel size="300,0" margin="0,0,0,70" max-length='300' min-length='0'
size-func="gui.get_viewport()[1]/2,-1"
padding="0"
min-size="0"
color="0"
interval="0"
gravity="bottom-left" interactive="false">
</panel>
59 changes: 59 additions & 0 deletions res/layouts/ingame_chat.xml.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
local lines = {}
local dead_lines = {}
local nextid = 0
local timeout = 7
local fadeout = 1
local initialized = false
local max_lines = 15
local animation_fps = 30

local function remove_line(line)
document[line[1]]:destruct()
time.post_runnable(function() document.root:reposition() end)
end

local function update_line(line, uptime)
local diff = uptime - line[2]
if diff > timeout then
remove_line(line)
table.insert(dead_lines, i)
elseif diff > timeout-fadeout then
local opacity = (timeout - diff) / fadeout
document[line[1]].color = {0, 0, 0, opacity * 80}
document[line[1].."L"].color = {255, 255, 255, opacity * 255}
end
end

events.on("core:chat", function(message)
local current_time = time.uptime()
local id = 'l'..tostring(nextid)
document.root:add(gui.template("chat_line", {id=id}))
document.root:reposition()
document[id.."L"].text = message
nextid = nextid + 1
if #lines == max_lines then
remove_line(lines[1])
table.remove(lines, 1)
end
table.insert(lines, {id, current_time})
end)

function on_open()
if not initialized then
initialized = true

document.root:setInterval(1/animation_fps, function ()
local uptime = time.uptime()
for _, line in ipairs(lines) do
update_line(line, uptime)
end
if #dead_lines > 0 then
for i = #dead_lines, 1, -1 do
local index = dead_lines[i]
table.remove(lines, i)
end
dead_lines = {}
end
end)
end
end
3 changes: 3 additions & 0 deletions res/layouts/templates/chat_line.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<container id='%{id}' color="#00000050" size="-1,20">
<label pos='5' id='%{id}L' markup='md'/>
</container>
53 changes: 53 additions & 0 deletions res/modules/gui_util.lua → res/modules/internal/gui_util.lua
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,57 @@ function gui_util.reset_local()
gui_util.local_dispatchers = {}
end

-- class designed for simple UI-nodes access via properties syntax
local Element = {}
function Element.new(docname, name)
return setmetatable({docname=docname, name=name}, {
__index=function(self, k)
return gui.getattr(self.docname, self.name, k)
end,
__newindex=function(self, k, v)
gui.setattr(self.docname, self.name, k, v)
end
})
end

-- the engine automatically creates an instance for every ui document (layout)
local Document = {}
function Document.new(docname)
return setmetatable({name=docname}, {
__index=function(self, k)
local elem = Element.new(self.name, k)
rawset(self, k, elem)
return elem
end
})
end

local RadioGroup = {}
function RadioGroup:set(key)
if type(self) ~= 'table' then
error("called as non-OOP via '.', use radiogroup:set")
end
if self.current then
self.elements[self.current].enabled = true
end
self.elements[key].enabled = false
self.current = key
if self.callback then
self.callback(key)
end
end
function RadioGroup:__call(elements, onset, default)
local group = setmetatable({
elements=elements,
callback=onset,
current=nil
}, {__index=self})
group:set(default)
return group
end
setmetatable(RadioGroup, RadioGroup)

gui_util.Document = Document
gui_util.RadioGroup = RadioGroup

return gui_util
2 changes: 1 addition & 1 deletion res/scripts/stdcmd.lua
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ console.add_command(
"chat text:str",
"Send chat message",
function (args, kwargs)
console.log("[you] "..args[1])
console.chat("[you] "..args[1])
end
)

Expand Down
62 changes: 10 additions & 52 deletions res/scripts/stdlib.lua
Original file line number Diff line number Diff line change
Expand Up @@ -146,64 +146,16 @@ function events.emit(event, ...)
return result
end

-- class designed for simple UI-nodes access via properties syntax
local Element = {}
function Element.new(docname, name)
return setmetatable({docname=docname, name=name}, {
__index=function(self, k)
return gui.getattr(self.docname, self.name, k)
end,
__newindex=function(self, k, v)
gui.setattr(self.docname, self.name, k, v)
end
})
end

-- the engine automatically creates an instance for every ui document (layout)
Document = {}
function Document.new(docname)
return setmetatable({name=docname}, {
__index=function(self, k)
local elem = Element.new(self.name, k)
rawset(self, k, elem)
return elem
end
})
end
gui_util = require "core:internal/gui_util"

local _RadioGroup = {}
function _RadioGroup:set(key)
if type(self) ~= 'table' then
error("called as non-OOP via '.', use radiogroup:set")
end
if self.current then
self.elements[self.current].enabled = true
end
self.elements[key].enabled = false
self.current = key
if self.callback then
self.callback(key)
end
end
function _RadioGroup:__call(elements, onset, default)
local group = setmetatable({
elements=elements,
callback=onset,
current=nil
}, {__index=_RadioGroup})
group:set(default)
return group
end
setmetatable(_RadioGroup, _RadioGroup)
RadioGroup = _RadioGroup
Document = gui_util.Document
RadioGroup = gui_util.RadioGroup
__vc_page_loader = gui_util.load_page

_GUI_ROOT = Document.new("core:root")
_MENU = _GUI_ROOT.menu
menu = _MENU

gui_util = require "core:gui_util"
__vc_page_loader = gui_util.load_page

--- Console library extension ---
console.cheats = {}

Expand All @@ -225,6 +177,11 @@ function console.log(...)
log_element:paste(text)
end

function console.chat(...)
console.log(...)
events.emit("core:chat", ...)
end

function gui.template(name, params)
local text = file.read(file.find("layouts/templates/"..name..".xml"))
for k,v in pairs(params) do
Expand Down Expand Up @@ -394,6 +351,7 @@ function __vc_on_hud_open()
hud.pause()
end
end)
hud.open_permanent("core:ingame_chat")
end

local RULES_FILE = "world:rules.toml"
Expand Down
1 change: 1 addition & 0 deletions src/engine/Engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ void Engine::renderFrame() {
Viewport viewport(Window::width, Window::height);
DrawContext ctx(nullptr, viewport, nullptr);
gui->draw(ctx, *assets);
gui->postAct();
}

void Engine::saveSettings() {
Expand Down
14 changes: 8 additions & 6 deletions src/graphics/ui/GUI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -178,12 +178,6 @@ void GUI::actFocused() {
}

void GUI::act(float delta, const Viewport& vp) {
while (!postRunnables.empty()) {
runnable callback = postRunnables.back();
postRunnables.pop();
callback();
}

container->setSize(vp.size());
container->act(delta);
auto prevfocus = focus;
Expand All @@ -206,6 +200,14 @@ void GUI::act(float delta, const Viewport& vp) {
}
}

void GUI::postAct() {
while (!postRunnables.empty()) {
runnable callback = postRunnables.back();
postRunnables.pop();
callback();
}
}

void GUI::draw(const DrawContext& pctx, const Assets& assets) {
auto ctx = pctx.sub(batch2D.get());

Expand Down
2 changes: 2 additions & 0 deletions src/graphics/ui/GUI.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ namespace gui {
/// @param assets active assets storage
void draw(const DrawContext& pctx, const Assets& assets);

void postAct();

/// @brief Add element to the main container
/// @param node UI element
void add(std::shared_ptr<UINode> node);
Expand Down
19 changes: 17 additions & 2 deletions src/graphics/ui/elements/Panel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@ int Panel::getMaxLength() const {
return maxLength;
}

void Panel::setMinLength(int value) {
minLength = value;
}

int Panel::getMinLength() const {
return minLength;
}

void Panel::setPadding(glm::vec4 padding) {
this->padding = padding;
refresh();
Expand All @@ -34,9 +42,11 @@ glm::vec4 Panel::getPadding() const {

void Panel::cropToContent() {
if (maxLength > 0.0f) {
setSize(glm::vec2(getSize().x, glm::min(maxLength, actualLength)));
setSize(glm::vec2(
getSize().x, glm::max(minLength, glm::min(maxLength, actualLength))
));
} else {
setSize(glm::vec2(getSize().x, actualLength));
setSize(glm::vec2(getSize().x, glm::max(minLength, actualLength)));
}
}

Expand All @@ -52,6 +62,11 @@ void Panel::add(const std::shared_ptr<UINode> &node) {
fullRefresh();
}

void Panel::remove(const std::shared_ptr<UINode> &node) {
Container::remove(node);
fullRefresh();
}

void Panel::refresh() {
UINode::refresh();
std::stable_sort(nodes.begin(), nodes.end(), [](auto a, auto b) {
Expand Down
Loading

0 comments on commit ce63b1b

Please sign in to comment.