Merge branch 'main' into release-0.26

This commit is contained in:
MihailRis 2025-01-23 20:39:02 +03:00
commit 981b4a22b5
11 changed files with 189 additions and 101 deletions

View File

@ -2,6 +2,13 @@
To work with the command interpreter, use the **console** library. To work with the command interpreter, use the **console** library.
When sending a command via the standard console (core:console layout):
1. the `allow-cheats` rule is checked
2. the `player`, `pos.x|y|z`, `entity.id`, `entity.selected` variables are automatically set.
3. the command handler is called - console.submit or the default one.
The default handler calls console.execute, passing the result to the console.log call.
## Commands creation ## Commands creation
To create a console command, use the following function: To create a console command, use the following function:

View File

@ -2,6 +2,13 @@
Для работы с командным интерпретатором предоставляется библиотека **console**. Для работы с командным интерпретатором предоставляется библиотека **console**.
При отправке команды через стандартную консоль (макет core:console):
1. проверяется правило `allow-cheats`
2. автоматически устанавливаются переменные `player`, `pos.x|y|z`, `entity.id`, `entity.selected`.
3. вызывается обработчик команд - console.submit или по-умолчанию.
Обработчик по-умолчанию вызывает console.execute, передавая результат в вызов console.log.
## Создание команд ## Создание команд
Для создания команды консоли используется следующая функция: Для создания команды консоли используется следующая функция:

View File

@ -97,11 +97,12 @@ end)
function setup_variables() function setup_variables()
local pid = hud.get_player() local pid = hud.get_player()
local x,y,z = player.get_pos(pid) local x,y,z = player.get_pos(pid)
console.set("player", pid)
console.set('pos.x', x) console.set('pos.x', x)
console.set('pos.y', y) console.set('pos.y', y)
console.set('pos.z', z) console.set('pos.z', z)
local pentity = player.get_entity(pid) local pentity = player.get_entity(pid)
if pentity ~= 0 then if pentity > 0 then
console.set('entity.id', pentity) console.set('entity.id', pentity)
end end
local sentity = player.get_selected_entity(pid) local sentity = player.get_selected_entity(pid)
@ -148,8 +149,6 @@ function submit(text)
text = text:sub(2) text = text:sub(2)
end end
end end
setup_variables()
local name local name
for s in text:gmatch("%S+") do for s in text:gmatch("%S+") do
@ -167,12 +166,19 @@ function submit(text)
end end
document.log.caret = -1 document.log.caret = -1
local status, result = pcall(console.execute, text)
if result then
console.log(result)
end
document.prompt.text = "" document.prompt.text = ""
document.prompt.focused = true document.prompt.focused = true
setup_variables()
if console.submit then
console.submit(text)
else
local status, result = pcall(console.execute, text)
if result then
console.log(result)
end
end
end end
function set_mode(mode) function set_mode(mode)

View File

@ -9,19 +9,21 @@
#include "AL/ALAudio.hpp" #include "AL/ALAudio.hpp"
#include "NoAudio.hpp" #include "NoAudio.hpp"
#include "debug/Logger.hpp" #include "debug/Logger.hpp"
#include "util/ObjectsKeeper.hpp"
static debug::Logger logger("audio"); static debug::Logger logger("audio");
namespace audio { using namespace audio;
namespace {
static speakerid_t nextId = 1; static speakerid_t nextId = 1;
static Backend* backend; static Backend* backend;
static std::unordered_map<speakerid_t, std::unique_ptr<Speaker>> speakers; static std::unordered_map<speakerid_t, std::unique_ptr<Speaker>> speakers;
static std::unordered_map<speakerid_t, std::shared_ptr<Stream>> streams; static std::unordered_map<speakerid_t, std::shared_ptr<Stream>> streams;
static std::vector<std::unique_ptr<Channel>> channels; static std::vector<std::unique_ptr<Channel>> channels;
static util::ObjectsKeeper objects_keeper {};
} }
using namespace audio;
Channel::Channel(std::string name) : name(std::move(name)) { Channel::Channel(std::string name) : name(std::move(name)) {
} }
@ -148,7 +150,8 @@ public:
} }
}; };
void audio::initialize(bool enabled) { void audio::initialize(bool enabled, AudioSettings& settings) {
enabled = enabled && settings.enabled.get();
if (enabled) { if (enabled) {
logger.info() << "initializing ALAudio backend"; logger.info() << "initializing ALAudio backend";
backend = ALAudio::create().release(); backend = ALAudio::create().release();
@ -160,7 +163,22 @@ void audio::initialize(bool enabled) {
logger.info() << "initializing NoAudio backend"; logger.info() << "initializing NoAudio backend";
backend = NoAudio::create().release(); backend = NoAudio::create().release();
} }
create_channel("master"); struct {
std::string name;
NumberSetting* setting;
} builtin_channels[] {
{"master", &settings.volumeMaster},
{"regular", &settings.volumeRegular},
{"music", &settings.volumeMusic},
{"ambient", &settings.volumeAmbient},
{"ui", &settings.volumeUI}
};
for (auto& channel : builtin_channels) {
create_channel(channel.name);
objects_keeper.keepAlive(channel.setting->observe([=](auto value) {
audio::get_channel(channel.name)->setVolume(value * value);
}, true));
}
} }
std::unique_ptr<PCM> audio::load_PCM(const fs::path& file, bool headerOnly) { std::unique_ptr<PCM> audio::load_PCM(const fs::path& file, bool headerOnly) {
@ -442,4 +460,5 @@ void audio::close() {
speakers.clear(); speakers.clear();
delete backend; delete backend;
backend = nullptr; backend = nullptr;
objects_keeper.clearKeepedObjects();
} }

View File

@ -6,6 +6,7 @@
#include <vector> #include <vector>
#include "typedefs.hpp" #include "typedefs.hpp"
#include "settings.hpp"
namespace fs = std::filesystem; namespace fs = std::filesystem;
@ -357,7 +358,7 @@ namespace audio {
/// @brief Initialize audio system or use no audio mode /// @brief Initialize audio system or use no audio mode
/// @param enabled try to initialize actual audio /// @param enabled try to initialize actual audio
void initialize(bool enabled); void initialize(bool enabled, AudioSettings& settings);
/// @brief Load audio file info and PCM data /// @brief Load audio file info and PCM data
/// @param file audio file /// @param file audio file

View File

@ -52,15 +52,6 @@ static debug::Logger logger("engine");
namespace fs = std::filesystem; namespace fs = std::filesystem;
static void create_channel(Engine* engine, std::string name, NumberSetting& setting) {
if (name != "master") {
audio::create_channel(name);
}
engine->keepAlive(setting.observe([=](auto value) {
audio::get_channel(name)->setVolume(value*value);
}, true));
}
static std::unique_ptr<ImageData> load_icon(const fs::path& resdir) { static std::unique_ptr<ImageData> load_icon(const fs::path& resdir) {
try { try {
auto file = resdir / fs::u8path("textures/misc/icon.png"); auto file = resdir / fs::u8path("textures/misc/icon.png");
@ -73,12 +64,23 @@ static std::unique_ptr<ImageData> load_icon(const fs::path& resdir) {
return nullptr; return nullptr;
} }
Engine::Engine(CoreParameters coreParameters) Engine::Engine() = default;
: params(std::move(coreParameters)),
settings(), static std::unique_ptr<Engine> engine;
settingsHandler({settings}),
interpreter(std::make_unique<cmd::CommandsInterpreter>()), Engine& Engine::getInstance() {
network(network::Network::create(settings.network)) { if (!engine) {
engine = std::make_unique<Engine>();
}
return *engine;
}
void Engine::initialize(CoreParameters coreParameters) {
params = std::move(coreParameters);
settingsHandler = std::make_unique<SettingsHandler>(settings);
interpreter = std::make_unique<cmd::CommandsInterpreter>();
network = network::Network::create(settings.network);
logger.info() << "engine version: " << ENGINE_VERSION_STRING; logger.info() << "engine version: " << ENGINE_VERSION_STRING;
if (params.headless) { if (params.headless) {
logger.info() << "headless mode is enabled"; logger.info() << "headless mode is enabled";
@ -110,12 +112,7 @@ Engine::Engine(CoreParameters coreParameters)
menus::create_version_label(*this); menus::create_version_label(*this);
} }
} }
audio::initialize(settings.audio.enabled.get() && !params.headless); audio::initialize(!params.headless, settings.audio);
create_channel(this, "master", settings.audio.volumeMaster);
create_channel(this, "regular", settings.audio.volumeRegular);
create_channel(this, "music", settings.audio.volumeMusic);
create_channel(this, "ambient", settings.audio.volumeAmbient);
create_channel(this, "ui", settings.audio.volumeUI);
bool langNotSet = settings.ui.language.get() == "auto"; bool langNotSet = settings.ui.language.get() == "auto";
if (langNotSet) { if (langNotSet) {
@ -140,7 +137,7 @@ void Engine::loadSettings() {
logger.info() << "loading settings"; logger.info() << "loading settings";
std::string text = files::read_string(settings_file); std::string text = files::read_string(settings_file);
try { try {
toml::parse(settingsHandler, settings_file.string(), text); toml::parse(*settingsHandler, settings_file.string(), text);
} catch (const parsing_error& err) { } catch (const parsing_error& err) {
logger.error() << err.errorLog(); logger.error() << err.errorLog();
throw; throw;
@ -222,7 +219,7 @@ void Engine::renderFrame() {
void Engine::saveSettings() { void Engine::saveSettings() {
logger.info() << "saving settings"; logger.info() << "saving settings";
files::write_string(paths.getSettingsFile(), toml::stringify(settingsHandler)); files::write_string(paths.getSettingsFile(), toml::stringify(*settingsHandler));
if (!params.headless) { if (!params.headless) {
logger.info() << "saving bindings"; logger.info() << "saving bindings";
files::write_string(paths.getControlsFile(), Events::writeBindings()); files::write_string(paths.getControlsFile(), Events::writeBindings());
@ -255,6 +252,10 @@ Engine::~Engine() {
logger.info() << "engine finished"; logger.info() << "engine finished";
} }
void Engine::terminate() {
engine.reset();
}
EngineController* Engine::getController() { EngineController* Engine::getController() {
return controller.get(); return controller.get();
} }
@ -511,7 +512,7 @@ std::shared_ptr<Screen> Engine::getScreen() {
} }
SettingsHandler& Engine::getSettingsHandler() { SettingsHandler& Engine::getSettingsHandler() {
return settingsHandler; return *settingsHandler;
} }
network::Network& Engine::getNetwork() { network::Network& Engine::getNetwork() {

View File

@ -58,9 +58,9 @@ using OnWorldOpen = std::function<void(std::unique_ptr<Level>, int64_t)>;
class Engine : public util::ObjectsKeeper { class Engine : public util::ObjectsKeeper {
CoreParameters params; CoreParameters params;
EngineSettings settings; EngineSettings settings;
SettingsHandler settingsHandler;
EnginePaths paths; EnginePaths paths;
std::unique_ptr<SettingsHandler> settingsHandler;
std::unique_ptr<Assets> assets; std::unique_ptr<Assets> assets;
std::shared_ptr<Screen> screen; std::shared_ptr<Screen> screen;
std::vector<ContentPack> contentPacks; std::vector<ContentPack> contentPacks;
@ -82,9 +82,15 @@ class Engine : public util::ObjectsKeeper {
void updateHotkeys(); void updateHotkeys();
void loadAssets(); void loadAssets();
public: public:
Engine(CoreParameters coreParameters); Engine();
~Engine(); ~Engine();
static Engine& getInstance();
void initialize(CoreParameters coreParameters);
static void terminate();
/// @brief Start the engine /// @brief Start the engine
void run(); void run();

View File

@ -82,8 +82,8 @@ static onaction create_action(
return [callback](GUI*) {callback();}; return [callback](GUI*) {callback();};
} }
/* Read basic UINode properties */ /// @brief Read basic UINode properties
static void _readUINode( static void read_uinode(
const UiXmlReader& reader, const xml::xmlelement& element, UINode& node const UiXmlReader& reader, const xml::xmlelement& element, UINode& node
) { ) {
if (element.has("id")) { if (element.has("id")) {
@ -177,8 +177,8 @@ static void _readUINode(
} }
} }
static void _readContainer(UiXmlReader& reader, const xml::xmlelement& element, Container& container) { static void read_container_impl(UiXmlReader& reader, const xml::xmlelement& element, Container& container) {
_readUINode(reader, element, container); read_uinode(reader, element, container);
if (element.has("scrollable")) { if (element.has("scrollable")) {
container.setScrollable(element.attr("scrollable").asBool()); container.setScrollable(element.attr("scrollable").asBool());
@ -197,17 +197,22 @@ static void _readContainer(UiXmlReader& reader, const xml::xmlelement& element,
} }
void UiXmlReader::readUINode(UiXmlReader& reader, const xml::xmlelement& element, Container& container) { void UiXmlReader::readUINode(UiXmlReader& reader, const xml::xmlelement& element, Container& container) {
_readContainer(reader, element, container); read_container_impl(reader, element, container);
} }
void UiXmlReader::readUINode( void UiXmlReader::readUINode(
const UiXmlReader& reader, const xml::xmlelement& element, UINode& node const UiXmlReader& reader, const xml::xmlelement& element, UINode& node
) { ) {
_readUINode(reader, element, node); read_uinode(reader, element, node);
} }
static void _readPanel(UiXmlReader& reader, const xml::xmlelement& element, Panel& panel, bool subnodes=true) { static void read_panel_impl(
_readUINode(reader, element, panel); UiXmlReader& reader,
const xml::xmlelement& element,
Panel& panel,
bool subnodes = true
) {
read_uinode(reader, element, panel);
if (element.has("padding")) { if (element.has("padding")) {
glm::vec4 padding = element.attr("padding").asVec4(); glm::vec4 padding = element.attr("padding").asVec4();
@ -245,7 +250,9 @@ static void _readPanel(UiXmlReader& reader, const xml::xmlelement& element, Pane
} }
} }
static std::wstring readAndProcessInnerText(const xml::xmlelement& element, const std::string& context) { static std::wstring parse_inner_text(
const xml::xmlelement& element, const std::string& context
) {
std::wstring text = L""; std::wstring text = L"";
if (element.size() == 1) { if (element.size() == 1) {
std::string source = element.sub(0).attr("#").getText(); std::string source = element.sub(0).attr("#").getText();
@ -265,9 +272,9 @@ static std::wstring readAndProcessInnerText(const xml::xmlelement& element, cons
static std::shared_ptr<UINode> readLabel( static std::shared_ptr<UINode> readLabel(
const UiXmlReader& reader, const xml::xmlelement& element const UiXmlReader& reader, const xml::xmlelement& element
) { ) {
std::wstring text = readAndProcessInnerText(element, reader.getContext()); std::wstring text = parse_inner_text(element, reader.getContext());
auto label = std::make_shared<Label>(text); auto label = std::make_shared<Label>(text);
_readUINode(reader, element, *label); read_uinode(reader, element, *label);
if (element.has("valign")) { if (element.has("valign")) {
label->setVerticalAlign( label->setVerticalAlign(
align_from_string(element.attr("valign").getText(), label->getVerticalAlign()) align_from_string(element.attr("valign").getText(), label->getVerticalAlign())
@ -298,20 +305,26 @@ static std::shared_ptr<UINode> readLabel(
return label; return label;
} }
static std::shared_ptr<UINode> readContainer(UiXmlReader& reader, const xml::xmlelement& element) { static std::shared_ptr<UINode> read_container(
UiXmlReader& reader, const xml::xmlelement& element
) {
auto container = std::make_shared<Container>(glm::vec2()); auto container = std::make_shared<Container>(glm::vec2());
_readContainer(reader, element, *container); read_container_impl(reader, element, *container);
return container; return container;
} }
static std::shared_ptr<UINode> readPanel(UiXmlReader& reader, const xml::xmlelement& element) { static std::shared_ptr<UINode> read_panel(
UiXmlReader& reader, const xml::xmlelement& element
) {
float interval = element.attr("interval", "2").asFloat(); float interval = element.attr("interval", "2").asFloat();
auto panel = std::make_shared<Panel>(glm::vec2(), glm::vec4(), interval); auto panel = std::make_shared<Panel>(glm::vec2(), glm::vec4(), interval);
_readPanel(reader, element, *panel); read_panel_impl(reader, element, *panel);
return panel; return panel;
} }
static std::shared_ptr<UINode> readButton(UiXmlReader& reader, const xml::xmlelement& element) { static std::shared_ptr<UINode> read_button(
UiXmlReader& reader, const xml::xmlelement& element
) {
glm::vec4 padding = element.attr("padding", "10").asVec4(); glm::vec4 padding = element.attr("padding", "10").asVec4();
std::shared_ptr<Button> button; std::shared_ptr<Button> button;
@ -323,11 +336,11 @@ static std::shared_ptr<UINode> readButton(UiXmlReader& reader, const xml::xmlele
} else { } else {
button = std::make_shared<Button>(L"", padding, nullptr); button = std::make_shared<Button>(L"", padding, nullptr);
} }
_readPanel(reader, element, *button, false); read_panel_impl(reader, element, *button, false);
} else { } else {
std::wstring text = readAndProcessInnerText(element, reader.getContext()); std::wstring text = parse_inner_text(element, reader.getContext());
button = std::make_shared<Button>(text, padding, nullptr); button = std::make_shared<Button>(text, padding, nullptr);
_readPanel(reader, element, *button, true); read_panel_impl(reader, element, *button, true);
} }
if (element.has("text-align")) { if (element.has("text-align")) {
button->setTextAlign(align_from_string( button->setTextAlign(align_from_string(
@ -337,11 +350,13 @@ static std::shared_ptr<UINode> readButton(UiXmlReader& reader, const xml::xmlele
return button; return button;
} }
static std::shared_ptr<UINode> readCheckBox(UiXmlReader& reader, const xml::xmlelement& element) { static std::shared_ptr<UINode> read_check_box(
auto text = readAndProcessInnerText(element, reader.getContext()); UiXmlReader& reader, const xml::xmlelement& element
) {
auto text = parse_inner_text(element, reader.getContext());
bool checked = element.attr("checked", "false").asBool(); bool checked = element.attr("checked", "false").asBool();
auto checkbox = std::make_shared<FullCheckBox>(text, glm::vec2(32), checked); auto checkbox = std::make_shared<FullCheckBox>(text, glm::vec2(32), checked);
_readPanel(reader, element, *checkbox); read_panel_impl(reader, element, *checkbox);
if (element.has("consumer")) { if (element.has("consumer")) {
checkbox->setConsumer(scripting::create_bool_consumer( checkbox->setConsumer(scripting::create_bool_consumer(
@ -361,14 +376,16 @@ static std::shared_ptr<UINode> readCheckBox(UiXmlReader& reader, const xml::xmle
return checkbox; return checkbox;
} }
static std::shared_ptr<UINode> readTextBox(UiXmlReader& reader, const xml::xmlelement& element) { static std::shared_ptr<UINode> read_text_box(
UiXmlReader& reader, const xml::xmlelement& element
) {
auto placeholder = util::str2wstr_utf8(element.attr("placeholder", "").getText()); auto placeholder = util::str2wstr_utf8(element.attr("placeholder", "").getText());
auto hint = util::str2wstr_utf8(element.attr("hint", "").getText()); auto hint = util::str2wstr_utf8(element.attr("hint", "").getText());
auto text = readAndProcessInnerText(element, reader.getContext()); auto text = parse_inner_text(element, reader.getContext());
auto textbox = std::make_shared<TextBox>(placeholder, glm::vec4(0.0f)); auto textbox = std::make_shared<TextBox>(placeholder, glm::vec4(0.0f));
textbox->setHint(hint); textbox->setHint(hint);
_readContainer(reader, element, *textbox); read_container_impl(reader, element, *textbox);
if (element.has("padding")) { if (element.has("padding")) {
glm::vec4 padding = element.attr("padding").asVec4(); glm::vec4 padding = element.attr("padding").asVec4();
textbox->setPadding(padding); textbox->setPadding(padding);
@ -447,16 +464,16 @@ static std::shared_ptr<UINode> readTextBox(UiXmlReader& reader, const xml::xmlel
return textbox; return textbox;
} }
static std::shared_ptr<UINode> readImage( static std::shared_ptr<UINode> read_image(
const UiXmlReader& reader, const xml::xmlelement& element const UiXmlReader& reader, const xml::xmlelement& element
) { ) {
std::string src = element.attr("src", "").getText(); std::string src = element.attr("src", "").getText();
auto image = std::make_shared<Image>(src); auto image = std::make_shared<Image>(src);
_readUINode(reader, element, *image); read_uinode(reader, element, *image);
return image; return image;
} }
static std::shared_ptr<UINode> readCanvas( static std::shared_ptr<UINode> read_canvas(
const UiXmlReader& reader, const xml::xmlelement& element const UiXmlReader& reader, const xml::xmlelement& element
) { ) {
auto size = glm::uvec2{32, 32}; auto size = glm::uvec2{32, 32};
@ -464,11 +481,11 @@ static std::shared_ptr<UINode> readCanvas(
size = element.attr("size").asVec2(); size = element.attr("size").asVec2();
} }
auto image = std::make_shared<Canvas>(ImageFormat::rgba8888, size); auto image = std::make_shared<Canvas>(ImageFormat::rgba8888, size);
_readUINode(reader, element, *image); read_uinode(reader, element, *image);
return image; return image;
} }
static std::shared_ptr<UINode> readTrackBar( static std::shared_ptr<UINode> read_track_bar(
const UiXmlReader& reader, const xml::xmlelement& element const UiXmlReader& reader, const xml::xmlelement& element
) { ) {
const auto& env = reader.getEnvironment(); const auto& env = reader.getEnvironment();
@ -479,7 +496,7 @@ static std::shared_ptr<UINode> readTrackBar(
float step = element.attr("step", "1.0").asFloat(); float step = element.attr("step", "1.0").asFloat();
int trackWidth = element.attr("track-width", "12").asInt(); int trackWidth = element.attr("track-width", "12").asInt();
auto bar = std::make_shared<TrackBar>(minv, maxv, def, step, trackWidth); auto bar = std::make_shared<TrackBar>(minv, maxv, def, step, trackWidth);
_readUINode(reader, element, *bar); read_uinode(reader, element, *bar);
if (element.has("consumer")) { if (element.has("consumer")) {
bar->setConsumer(scripting::create_number_consumer( bar->setConsumer(scripting::create_number_consumer(
env, element.attr("consumer").getText(), file)); env, element.attr("consumer").getText(), file));
@ -501,7 +518,9 @@ static std::shared_ptr<UINode> readTrackBar(
return bar; return bar;
} }
static std::shared_ptr<UINode> readInputBindBox(UiXmlReader& reader, const xml::xmlelement& element) { static std::shared_ptr<UINode> read_input_bind_box(
UiXmlReader& reader, const xml::xmlelement& element
) {
auto bindname = element.attr("binding").getText(); auto bindname = element.attr("binding").getText();
auto found = Events::bindings.find(bindname); auto found = Events::bindings.find(bindname);
if (found == Events::bindings.end()) { if (found == Events::bindings.end()) {
@ -509,12 +528,12 @@ static std::shared_ptr<UINode> readInputBindBox(UiXmlReader& reader, const xml::
} }
glm::vec4 padding = element.attr("padding", "6").asVec4(); glm::vec4 padding = element.attr("padding", "6").asVec4();
auto bindbox = std::make_shared<InputBindBox>(found->second, padding); auto bindbox = std::make_shared<InputBindBox>(found->second, padding);
_readPanel(reader, element, *bindbox); read_panel_impl(reader, element, *bindbox);
return bindbox; return bindbox;
} }
static slotcallback readSlotFunc( static slotcallback read_slot_func(
InventoryView* view, InventoryView* view,
const UiXmlReader& reader, const UiXmlReader& reader,
const xml::xmlelement& element, const xml::xmlelement& element,
@ -542,13 +561,13 @@ static void readSlot(
layout.position = element.attr("pos").asVec2(); layout.position = element.attr("pos").asVec2();
} }
if (element.has("updatefunc")) { if (element.has("updatefunc")) {
layout.updateFunc = readSlotFunc(view, reader, element, "updatefunc"); layout.updateFunc = read_slot_func(view, reader, element, "updatefunc");
} }
if (element.has("sharefunc")) { if (element.has("sharefunc")) {
layout.shareFunc = readSlotFunc(view, reader, element, "sharefunc"); layout.shareFunc = read_slot_func(view, reader, element, "sharefunc");
} }
if (element.has("onrightclick")) { if (element.has("onrightclick")) {
layout.rightClick = readSlotFunc(view, reader, element, "onrightclick"); layout.rightClick = read_slot_func(view, reader, element, "onrightclick");
} }
layout.taking = taking; layout.taking = taking;
layout.placing = placing; layout.placing = placing;
@ -588,13 +607,13 @@ static void readSlotsGrid(
layout.position = element.attr("pos").asVec2(); layout.position = element.attr("pos").asVec2();
} }
if (element.has("updatefunc")) { if (element.has("updatefunc")) {
layout.updateFunc = readSlotFunc(view, reader, element, "updatefunc"); layout.updateFunc = read_slot_func(view, reader, element, "updatefunc");
} }
if (element.has("sharefunc")) { if (element.has("sharefunc")) {
layout.shareFunc = readSlotFunc(view, reader, element, "sharefunc"); layout.shareFunc = read_slot_func(view, reader, element, "sharefunc");
} }
if (element.has("onrightclick")) { if (element.has("onrightclick")) {
layout.rightClick = readSlotFunc(view, reader, element, "onrightclick"); layout.rightClick = read_slot_func(view, reader, element, "onrightclick");
} }
layout.padding = padding; layout.padding = padding;
layout.taking = taking; layout.taking = taking;
@ -618,7 +637,9 @@ static void readSlotsGrid(
} }
} }
static std::shared_ptr<UINode> readInventory(UiXmlReader& reader, const xml::xmlelement& element) { static std::shared_ptr<UINode> read_inventory(
UiXmlReader& reader, const xml::xmlelement& element
) {
auto view = std::make_shared<InventoryView>(); auto view = std::make_shared<InventoryView>();
view->setColor(glm::vec4(0.122f, 0.122f, 0.122f, 0.878f)); // todo: fixme view->setColor(glm::vec4(0.122f, 0.122f, 0.122f, 0.878f)); // todo: fixme
reader.addIgnore("slot"); reader.addIgnore("slot");
@ -633,31 +654,34 @@ static std::shared_ptr<UINode> readInventory(UiXmlReader& reader, const xml::xml
} }
} }
return view; return view;
} }
static std::shared_ptr<UINode> readPageBox(UiXmlReader& reader, const xml::xmlelement& element) { static std::shared_ptr<UINode> read_page_box(
UiXmlReader& reader, const xml::xmlelement& element
) {
auto menu = std::make_shared<Menu>(); auto menu = std::make_shared<Menu>();
// FIXME menu->setPageLoader(
menu->setPageLoader(scripting::engine->getGUI()->getMenu()->getPageLoader()); Engine::getInstance().getGUI()->getMenu()->getPageLoader()
_readContainer(reader, element, *menu); );
read_container_impl(reader, element, *menu);
return menu; return menu;
} }
UiXmlReader::UiXmlReader(const scriptenv& env) : env(env) { UiXmlReader::UiXmlReader(const scriptenv& env) : env(env) {
contextStack.emplace(""); contextStack.emplace("");
add("image", readImage); add("image", read_image);
add("canvas", readCanvas); add("canvas", read_canvas);
add("label", readLabel); add("label", readLabel);
add("panel", readPanel); add("panel", read_panel);
add("button", readButton); add("button", read_button);
add("textbox", readTextBox); add("textbox", read_text_box);
add("pagebox", readPageBox); add("pagebox", read_page_box);
add("checkbox", readCheckBox); add("checkbox", read_check_box);
add("trackbar", readTrackBar); add("trackbar", read_track_bar);
add("container", readContainer); add("container", read_container);
add("bindbox", readInputBindBox); add("bindbox", read_input_bind_box);
add("inventory", readInventory); add("inventory", read_inventory);
} }
void UiXmlReader::add(const std::string& tag, uinode_reader reader) { void UiXmlReader::add(const std::string& tag, uinode_reader reader) {

View File

@ -46,9 +46,10 @@ static glm::vec4 parse_color(const std::basic_string_view<CharT>& color_code) {
template <typename CharT> template <typename CharT>
static inline void apply_color( static inline void apply_color(
const std::basic_string_view<CharT>& color_code, FontStylesScheme& styles const std::basic_string_view<CharT>& color_code,
FontStylesScheme& styles,
FontStyle& style
) { ) {
FontStyle style = styles.palette.back();
style.color = parse_color(color_code); style.color = parse_color(color_code);
styles.palette.push_back(style); styles.palette.push_back(style);
} }
@ -116,7 +117,7 @@ Result<CharT> process_markdown(
} }
} else if (first == '[' && pos + 9 <= source.size() && source[pos + 1] == '#' && source[pos + 8] == ']') { } else if (first == '[' && pos + 9 <= source.size() && source[pos + 1] == '#' && source[pos + 8] == ']') {
std::basic_string_view<CharT> color_code = source.substr(pos + 1, 8); std::basic_string_view<CharT> color_code = source.substr(pos + 1, 8);
apply_color(color_code, styles); apply_color(color_code, styles, style);
if (!eraseMarkdown) { if (!eraseMarkdown) {
for (int i = 0; i < 9; ++i) { for (int i = 0; i < 9; ++i) {
emit_md(source[pos + i], styles, ss); emit_md(source[pos + i], styles, ss);

View File

@ -43,6 +43,11 @@ static int l_execute(lua::State* L) {
} }
} }
static int l_get(lua::State* L) {
auto name = lua::require_string(L, 1);
return lua::pushvalue(L, (*engine->getCommandsInterpreter())[name]);
}
static int l_set(lua::State* L) { static int l_set(lua::State* L) {
auto name = lua::require_string(L, 1); auto name = lua::require_string(L, 1);
auto value = lua::tovalue(L, 2); auto value = lua::tovalue(L, 2);
@ -119,6 +124,7 @@ static int l_get_command_info(lua::State* L) {
const luaL_Reg consolelib[] = { const luaL_Reg consolelib[] = {
{"add_command", lua::wrap<l_add_command>}, {"add_command", lua::wrap<l_add_command>},
{"execute", lua::wrap<l_execute>}, {"execute", lua::wrap<l_execute>},
{"get", lua::wrap<l_get>},
{"set", lua::wrap<l_set>}, {"set", lua::wrap<l_set>},
{"get_commands_list", lua::wrap<l_get_commands_list>}, {"get_commands_list", lua::wrap<l_get_commands_list>},
{"get_command_info", lua::wrap<l_get_command_info>}, {"get_command_info", lua::wrap<l_get_command_info>},

View File

@ -3,11 +3,16 @@
#include "util/command_line.hpp" #include "util/command_line.hpp"
#include "debug/Logger.hpp" #include "debug/Logger.hpp"
#include <csignal>
#include <iostream> #include <iostream>
#include <stdexcept> #include <stdexcept>
static debug::Logger logger("main"); static debug::Logger logger("main");
static void sigterm_handler(int signum) {
Engine::getInstance().quit();
}
int main(int argc, char** argv) { int main(int argc, char** argv) {
CoreParameters coreParameters; CoreParameters coreParameters;
try { try {
@ -18,11 +23,15 @@ int main(int argc, char** argv) {
std::cerr << err.what() << std::endl; std::cerr << err.what() << std::endl;
return EXIT_FAILURE; return EXIT_FAILURE;
} }
std::signal(SIGTERM, sigterm_handler);
debug::Logger::init(coreParameters.userFolder.string()+"/latest.log"); debug::Logger::init(coreParameters.userFolder.string()+"/latest.log");
platform::configure_encoding(); platform::configure_encoding();
auto& engine = Engine::getInstance();
try { try {
Engine(std::move(coreParameters)).run(); engine.initialize(std::move(coreParameters));
engine.run();
} catch (const initialize_error& err) { } catch (const initialize_error& err) {
logger.error() << "could not to initialize engine\n" << err.what(); logger.error() << "could not to initialize engine\n" << err.what();
} }
@ -33,5 +42,6 @@ int main(int argc, char** argv) {
throw; throw;
} }
#endif #endif
Engine::terminate();
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }