commit
531334f059
@ -1,6 +1,6 @@
|
|||||||
# Documentation
|
# Documentation
|
||||||
|
|
||||||
Documentation for release 0.27.
|
Documentation for release 0.28.
|
||||||
|
|
||||||
## Sections
|
## Sections
|
||||||
|
|
||||||
|
|||||||
@ -11,7 +11,7 @@ Subsections:
|
|||||||
- [Libraries](#)
|
- [Libraries](#)
|
||||||
- [app](scripting/builtins/libapp.md)
|
- [app](scripting/builtins/libapp.md)
|
||||||
- [base64](scripting/builtins/libbase64.md)
|
- [base64](scripting/builtins/libbase64.md)
|
||||||
- [bjson, json, toml](scripting/filesystem.md)
|
- [bjson, json, toml, yaml](scripting/filesystem.md)
|
||||||
- [block](scripting/builtins/libblock.md)
|
- [block](scripting/builtins/libblock.md)
|
||||||
- [byteutil](scripting/builtins/libbyteutil.md)
|
- [byteutil](scripting/builtins/libbyteutil.md)
|
||||||
- [cameras](scripting/builtins/libcameras.md)
|
- [cameras](scripting/builtins/libcameras.md)
|
||||||
|
|||||||
@ -36,6 +36,22 @@ toml.parse(code: str) -> table
|
|||||||
|
|
||||||
Parses a TOML string into a table.
|
Parses a TOML string into a table.
|
||||||
|
|
||||||
|
## *yaml* library
|
||||||
|
|
||||||
|
The library contains functions for serializing and deserializing tables:
|
||||||
|
|
||||||
|
```python
|
||||||
|
yaml.tostring(object: table) -> str
|
||||||
|
```
|
||||||
|
|
||||||
|
Serializes an object into a YAML string.
|
||||||
|
|
||||||
|
```python
|
||||||
|
yaml.parse(code: str) -> table
|
||||||
|
```
|
||||||
|
|
||||||
|
Parses a YAML string into a table.
|
||||||
|
|
||||||
## *bjson* library
|
## *bjson* library
|
||||||
|
|
||||||
The library contains functions for working with the binary data exchange format [vcbjson](../../specs/binary_json_spec.md).
|
The library contains functions for working with the binary data exchange format [vcbjson](../../specs/binary_json_spec.md).
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
# Документация
|
# Документация
|
||||||
|
|
||||||
Документация версии 0.27.
|
Документация версии 0.28.
|
||||||
|
|
||||||
## Разделы
|
## Разделы
|
||||||
|
|
||||||
|
|||||||
@ -11,7 +11,7 @@
|
|||||||
- [Библиотеки](#)
|
- [Библиотеки](#)
|
||||||
- [app](scripting/builtins/libapp.md)
|
- [app](scripting/builtins/libapp.md)
|
||||||
- [base64](scripting/builtins/libbase64.md)
|
- [base64](scripting/builtins/libbase64.md)
|
||||||
- [bjson, json, toml](scripting/filesystem.md)
|
- [bjson, json, toml, yaml](scripting/filesystem.md)
|
||||||
- [block](scripting/builtins/libblock.md)
|
- [block](scripting/builtins/libblock.md)
|
||||||
- [byteutil](scripting/builtins/libbyteutil.md)
|
- [byteutil](scripting/builtins/libbyteutil.md)
|
||||||
- [cameras](scripting/builtins/libcameras.md)
|
- [cameras](scripting/builtins/libcameras.md)
|
||||||
|
|||||||
@ -36,6 +36,22 @@ toml.parse(code: str) -> table
|
|||||||
|
|
||||||
Парсит TOML строку в таблицу.
|
Парсит TOML строку в таблицу.
|
||||||
|
|
||||||
|
## Библиотека yaml
|
||||||
|
|
||||||
|
Библиотека содержит функции для сериализации и десериализации таблиц:
|
||||||
|
|
||||||
|
```python
|
||||||
|
yaml.tostring(object: table) -> str
|
||||||
|
```
|
||||||
|
|
||||||
|
Сериализует объект в YAML строку.
|
||||||
|
|
||||||
|
```python
|
||||||
|
yaml.parse(code: str) -> table
|
||||||
|
```
|
||||||
|
|
||||||
|
Парсит YAML строку в таблицу.
|
||||||
|
|
||||||
## Библиотека bjson
|
## Библиотека bjson
|
||||||
|
|
||||||
Библиотека содержит функции для работы с двоичным форматом обмена данными [vcbjson](../../specs/binary_json_spec.md).
|
Библиотека содержит функции для работы с двоичным форматом обмена данными [vcbjson](../../specs/binary_json_spec.md).
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"id": "base",
|
"id": "base",
|
||||||
"title": "Base",
|
"title": "Base",
|
||||||
"version": "0.27",
|
"version": "0.28",
|
||||||
"description": "basic content package"
|
"description": "basic content package"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,13 +19,14 @@
|
|||||||
#include "items/ItemDef.hpp"
|
#include "items/ItemDef.hpp"
|
||||||
#include "Assets.hpp"
|
#include "Assets.hpp"
|
||||||
#include "assetload_funcs.hpp"
|
#include "assetload_funcs.hpp"
|
||||||
|
#include "engine/Engine.hpp"
|
||||||
|
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
static debug::Logger logger("assets-loader");
|
static debug::Logger logger("assets-loader");
|
||||||
|
|
||||||
AssetsLoader::AssetsLoader(Assets* assets, const ResPaths* paths)
|
AssetsLoader::AssetsLoader(Engine& engine, Assets& assets, const ResPaths& paths)
|
||||||
: assets(assets), paths(paths) {
|
: engine(engine), assets(assets), paths(paths) {
|
||||||
addLoader(AssetType::SHADER, assetload::shader);
|
addLoader(AssetType::SHADER, assetload::shader);
|
||||||
addLoader(AssetType::TEXTURE, assetload::texture);
|
addLoader(AssetType::TEXTURE, assetload::texture);
|
||||||
addLoader(AssetType::FONT, assetload::font);
|
addLoader(AssetType::FONT, assetload::font);
|
||||||
@ -73,7 +74,7 @@ void AssetsLoader::loadNext() {
|
|||||||
aloader_func loader = getLoader(entry.tag);
|
aloader_func loader = getLoader(entry.tag);
|
||||||
auto postfunc =
|
auto postfunc =
|
||||||
loader(this, paths, entry.filename, entry.alias, entry.config);
|
loader(this, paths, entry.filename, entry.alias, entry.config);
|
||||||
postfunc(assets);
|
postfunc(&assets);
|
||||||
entries.pop();
|
entries.pop();
|
||||||
} catch (std::runtime_error& err) {
|
} catch (std::runtime_error& err) {
|
||||||
logger.error() << err.what();
|
logger.error() << err.what();
|
||||||
@ -101,7 +102,7 @@ static void add_layouts(
|
|||||||
AssetType::LAYOUT,
|
AssetType::LAYOUT,
|
||||||
file.string(),
|
file.string(),
|
||||||
name,
|
name,
|
||||||
std::make_shared<LayoutCfg>(env)
|
std::make_shared<LayoutCfg>(&loader.getEngine().getGUI(), env)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -199,7 +200,7 @@ void AssetsLoader::processPreloadConfig(const io::path& file) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AssetsLoader::processPreloadConfigs(const Content* content) {
|
void AssetsLoader::processPreloadConfigs(const Content* content) {
|
||||||
auto preloadFile = paths->getMainRoot() / "preload.json";
|
io::path preloadFile = "res:preload.json";
|
||||||
if (io::exists(preloadFile)) {
|
if (io::exists(preloadFile)) {
|
||||||
processPreloadConfig(preloadFile);
|
processPreloadConfig(preloadFile);
|
||||||
}
|
}
|
||||||
@ -211,7 +212,7 @@ void AssetsLoader::processPreloadConfigs(const Content* content) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const auto& pack = entry.second;
|
const auto& pack = entry.second;
|
||||||
auto preloadFile = pack->getInfo().folder / "preload.json";
|
preloadFile = pack->getInfo().folder / "preload.json";
|
||||||
if (io::exists(preloadFile)) {
|
if (io::exists(preloadFile)) {
|
||||||
processPreloadConfig(preloadFile);
|
processPreloadConfig(preloadFile);
|
||||||
}
|
}
|
||||||
@ -296,7 +297,11 @@ bool AssetsLoader::loadExternalTexture(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ResPaths* AssetsLoader::getPaths() const {
|
Engine& AssetsLoader::getEngine() {
|
||||||
|
return engine;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ResPaths& AssetsLoader::getPaths() const {
|
||||||
return paths;
|
return paths;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -324,7 +329,7 @@ std::shared_ptr<Task> AssetsLoader::startTask(runnable onDone) {
|
|||||||
std::make_shared<util::ThreadPool<aloader_entry, assetload::postfunc>>(
|
std::make_shared<util::ThreadPool<aloader_entry, assetload::postfunc>>(
|
||||||
"assets-loader-pool",
|
"assets-loader-pool",
|
||||||
[=]() { return std::make_shared<LoaderWorker>(this); },
|
[=]() { return std::make_shared<LoaderWorker>(this); },
|
||||||
[=](const assetload::postfunc& func) { func(assets); }
|
[this](const assetload::postfunc& func) { func(&assets); }
|
||||||
);
|
);
|
||||||
pool->setOnComplete(std::move(onDone));
|
pool->setOnComplete(std::move(onDone));
|
||||||
while (!entries.empty()) {
|
while (!entries.empty()) {
|
||||||
|
|||||||
@ -18,6 +18,11 @@
|
|||||||
class ResPaths;
|
class ResPaths;
|
||||||
class AssetsLoader;
|
class AssetsLoader;
|
||||||
class Content;
|
class Content;
|
||||||
|
class Engine;
|
||||||
|
|
||||||
|
namespace gui {
|
||||||
|
class GUI;
|
||||||
|
}
|
||||||
|
|
||||||
struct AssetCfg {
|
struct AssetCfg {
|
||||||
virtual ~AssetCfg() {
|
virtual ~AssetCfg() {
|
||||||
@ -25,9 +30,10 @@ struct AssetCfg {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct LayoutCfg : AssetCfg {
|
struct LayoutCfg : AssetCfg {
|
||||||
|
gui::GUI* gui;
|
||||||
scriptenv env;
|
scriptenv env;
|
||||||
|
|
||||||
LayoutCfg(scriptenv env) : env(std::move(env)) {
|
LayoutCfg(gui::GUI* gui, scriptenv env) : gui(gui), env(std::move(env)) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -51,7 +57,7 @@ struct AtlasCfg : AssetCfg {
|
|||||||
|
|
||||||
using aloader_func = std::function<
|
using aloader_func = std::function<
|
||||||
assetload::
|
assetload::
|
||||||
postfunc(AssetsLoader*, const ResPaths*, const std::string&, const std::string&, std::shared_ptr<AssetCfg>)>;
|
postfunc(AssetsLoader*, const ResPaths&, const std::string&, const std::string&, std::shared_ptr<AssetCfg>)>;
|
||||||
|
|
||||||
struct aloader_entry {
|
struct aloader_entry {
|
||||||
AssetType tag;
|
AssetType tag;
|
||||||
@ -61,11 +67,12 @@ struct aloader_entry {
|
|||||||
};
|
};
|
||||||
|
|
||||||
class AssetsLoader {
|
class AssetsLoader {
|
||||||
Assets* assets;
|
Engine& engine;
|
||||||
|
Assets& assets;
|
||||||
std::map<AssetType, aloader_func> loaders;
|
std::map<AssetType, aloader_func> loaders;
|
||||||
std::queue<aloader_entry> entries;
|
std::queue<aloader_entry> entries;
|
||||||
std::set<std::pair<AssetType, std::string>> enqueued;
|
std::set<std::pair<AssetType, std::string>> enqueued;
|
||||||
const ResPaths* paths;
|
const ResPaths& paths;
|
||||||
|
|
||||||
void tryAddSound(const std::string& name);
|
void tryAddSound(const std::string& name);
|
||||||
|
|
||||||
@ -76,7 +83,7 @@ class AssetsLoader {
|
|||||||
void processPreloadConfig(const io::path& file);
|
void processPreloadConfig(const io::path& file);
|
||||||
void processPreloadConfigs(const Content* content);
|
void processPreloadConfigs(const Content* content);
|
||||||
public:
|
public:
|
||||||
AssetsLoader(Assets* assets, const ResPaths* paths);
|
AssetsLoader(Engine& engine, Assets& assets, const ResPaths& paths);
|
||||||
void addLoader(AssetType tag, aloader_func func);
|
void addLoader(AssetType tag, aloader_func func);
|
||||||
|
|
||||||
/// @brief Enqueue asset load
|
/// @brief Enqueue asset load
|
||||||
@ -98,7 +105,7 @@ public:
|
|||||||
|
|
||||||
std::shared_ptr<Task> startTask(runnable onDone);
|
std::shared_ptr<Task> startTask(runnable onDone);
|
||||||
|
|
||||||
const ResPaths* getPaths() const;
|
const ResPaths& getPaths() const;
|
||||||
aloader_func getLoader(AssetType tag);
|
aloader_func getLoader(AssetType tag);
|
||||||
|
|
||||||
/// @brief Enqueue core and content assets
|
/// @brief Enqueue core and content assets
|
||||||
@ -111,4 +118,6 @@ public:
|
|||||||
const std::string& name,
|
const std::string& name,
|
||||||
const std::vector<io::path>& alternatives
|
const std::vector<io::path>& alternatives
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Engine& getEngine();
|
||||||
};
|
};
|
||||||
|
|||||||
@ -34,7 +34,7 @@ namespace fs = std::filesystem;
|
|||||||
|
|
||||||
static bool load_animation(
|
static bool load_animation(
|
||||||
Assets* assets,
|
Assets* assets,
|
||||||
const ResPaths* paths,
|
const ResPaths& paths,
|
||||||
const std::string& atlasName,
|
const std::string& atlasName,
|
||||||
const std::string& directory,
|
const std::string& directory,
|
||||||
const std::string& name,
|
const std::string& name,
|
||||||
@ -43,14 +43,14 @@ static bool load_animation(
|
|||||||
|
|
||||||
assetload::postfunc assetload::texture(
|
assetload::postfunc assetload::texture(
|
||||||
AssetsLoader*,
|
AssetsLoader*,
|
||||||
const ResPaths* paths,
|
const ResPaths& paths,
|
||||||
const std::string& filename,
|
const std::string& filename,
|
||||||
const std::string& name,
|
const std::string& name,
|
||||||
const std::shared_ptr<AssetCfg>&
|
const std::shared_ptr<AssetCfg>&
|
||||||
) {
|
) {
|
||||||
auto actualFile = paths->find(filename + ".png");
|
auto actualFile = paths.find(filename + ".png");
|
||||||
try {
|
try {
|
||||||
std::shared_ptr<ImageData> image(imageio::read(actualFile).release());
|
std::shared_ptr<ImageData> image(imageio::read(actualFile));
|
||||||
return [name, image, actualFile](auto assets) {
|
return [name, image, actualFile](auto assets) {
|
||||||
assets->store(Texture::from(image.get()), name);
|
assets->store(Texture::from(image.get()), name);
|
||||||
};
|
};
|
||||||
@ -62,13 +62,13 @@ assetload::postfunc assetload::texture(
|
|||||||
|
|
||||||
assetload::postfunc assetload::shader(
|
assetload::postfunc assetload::shader(
|
||||||
AssetsLoader*,
|
AssetsLoader*,
|
||||||
const ResPaths* paths,
|
const ResPaths& paths,
|
||||||
const std::string& filename,
|
const std::string& filename,
|
||||||
const std::string& name,
|
const std::string& name,
|
||||||
const std::shared_ptr<AssetCfg>&
|
const std::shared_ptr<AssetCfg>&
|
||||||
) {
|
) {
|
||||||
io::path vertexFile = paths->find(filename + ".glslv");
|
io::path vertexFile = paths.find(filename + ".glslv");
|
||||||
io::path fragmentFile = paths->find(filename + ".glslf");
|
io::path fragmentFile = paths.find(filename + ".glslf");
|
||||||
|
|
||||||
std::string vertexSource = io::read_string(vertexFile);
|
std::string vertexSource = io::read_string(vertexFile);
|
||||||
std::string fragmentSource = io::read_string(fragmentFile);
|
std::string fragmentSource = io::read_string(fragmentFile);
|
||||||
@ -104,14 +104,14 @@ static bool append_atlas(AtlasBuilder& atlas, const io::path& file) {
|
|||||||
|
|
||||||
assetload::postfunc assetload::atlas(
|
assetload::postfunc assetload::atlas(
|
||||||
AssetsLoader* loader,
|
AssetsLoader* loader,
|
||||||
const ResPaths* paths,
|
const ResPaths& paths,
|
||||||
const std::string& directory,
|
const std::string& directory,
|
||||||
const std::string& name,
|
const std::string& name,
|
||||||
const std::shared_ptr<AssetCfg>& config
|
const std::shared_ptr<AssetCfg>& config
|
||||||
) {
|
) {
|
||||||
auto atlasConfig = std::dynamic_pointer_cast<AtlasCfg>(config);
|
auto atlasConfig = std::dynamic_pointer_cast<AtlasCfg>(config);
|
||||||
if (atlasConfig && atlasConfig->type == AtlasType::SEPARATE) {
|
if (atlasConfig && atlasConfig->type == AtlasType::SEPARATE) {
|
||||||
for (const auto& file : paths->listdir(directory)) {
|
for (const auto& file : paths.listdir(directory)) {
|
||||||
if (!imageio::is_read_supported(file.extension()))
|
if (!imageio::is_read_supported(file.extension()))
|
||||||
continue;
|
continue;
|
||||||
loader->add(
|
loader->add(
|
||||||
@ -123,7 +123,7 @@ assetload::postfunc assetload::atlas(
|
|||||||
return [](auto){};
|
return [](auto){};
|
||||||
}
|
}
|
||||||
AtlasBuilder builder;
|
AtlasBuilder builder;
|
||||||
for (const auto& file : paths->listdir(directory)) {
|
for (const auto& file : paths.listdir(directory)) {
|
||||||
if (!imageio::is_read_supported(file.extension())) continue;
|
if (!imageio::is_read_supported(file.extension())) continue;
|
||||||
if (!append_atlas(builder, file)) continue;
|
if (!append_atlas(builder, file)) continue;
|
||||||
}
|
}
|
||||||
@ -140,7 +140,7 @@ assetload::postfunc assetload::atlas(
|
|||||||
|
|
||||||
assetload::postfunc assetload::font(
|
assetload::postfunc assetload::font(
|
||||||
AssetsLoader*,
|
AssetsLoader*,
|
||||||
const ResPaths* paths,
|
const ResPaths& paths,
|
||||||
const std::string& filename,
|
const std::string& filename,
|
||||||
const std::string& name,
|
const std::string& name,
|
||||||
const std::shared_ptr<AssetCfg>&
|
const std::shared_ptr<AssetCfg>&
|
||||||
@ -148,7 +148,7 @@ assetload::postfunc assetload::font(
|
|||||||
auto pages = std::make_shared<std::vector<std::unique_ptr<ImageData>>>();
|
auto pages = std::make_shared<std::vector<std::unique_ptr<ImageData>>>();
|
||||||
for (size_t i = 0; i <= 1024; i++) {
|
for (size_t i = 0; i <= 1024; i++) {
|
||||||
std::string pagefile = filename + "_" + std::to_string(i) + ".png";
|
std::string pagefile = filename + "_" + std::to_string(i) + ".png";
|
||||||
auto file = paths->find(pagefile);
|
auto file = paths.find(pagefile);
|
||||||
if (io::exists(file)) {
|
if (io::exists(file)) {
|
||||||
pages->push_back(imageio::read(file));
|
pages->push_back(imageio::read(file));
|
||||||
} else if (i == 0) {
|
} else if (i == 0) {
|
||||||
@ -177,7 +177,7 @@ assetload::postfunc assetload::font(
|
|||||||
|
|
||||||
assetload::postfunc assetload::layout(
|
assetload::postfunc assetload::layout(
|
||||||
AssetsLoader*,
|
AssetsLoader*,
|
||||||
const ResPaths* paths,
|
const ResPaths&,
|
||||||
const std::string& file,
|
const std::string& file,
|
||||||
const std::string& name,
|
const std::string& name,
|
||||||
const std::shared_ptr<AssetCfg>& config
|
const std::shared_ptr<AssetCfg>& config
|
||||||
@ -189,6 +189,7 @@ assetload::postfunc assetload::layout(
|
|||||||
auto prefix = name.substr(0, pos);
|
auto prefix = name.substr(0, pos);
|
||||||
assets->store(
|
assets->store(
|
||||||
UiDocument::read(
|
UiDocument::read(
|
||||||
|
*cfg->gui,
|
||||||
cfg->env,
|
cfg->env,
|
||||||
name,
|
name,
|
||||||
file,
|
file,
|
||||||
@ -205,7 +206,7 @@ assetload::postfunc assetload::layout(
|
|||||||
}
|
}
|
||||||
assetload::postfunc assetload::sound(
|
assetload::postfunc assetload::sound(
|
||||||
AssetsLoader*,
|
AssetsLoader*,
|
||||||
const ResPaths* paths,
|
const ResPaths& paths,
|
||||||
const std::string& file,
|
const std::string& file,
|
||||||
const std::string& name,
|
const std::string& name,
|
||||||
const std::shared_ptr<AssetCfg>& config
|
const std::shared_ptr<AssetCfg>& config
|
||||||
@ -219,13 +220,13 @@ assetload::postfunc assetload::sound(
|
|||||||
for (size_t i = 0; i < extensions.size(); i++) {
|
for (size_t i = 0; i < extensions.size(); i++) {
|
||||||
extension = extensions[i];
|
extension = extensions[i];
|
||||||
// looking for 'sound_name' as base sound
|
// looking for 'sound_name' as base sound
|
||||||
auto soundFile = paths->find(file + extension);
|
auto soundFile = paths.find(file + extension);
|
||||||
if (io::exists(soundFile)) {
|
if (io::exists(soundFile)) {
|
||||||
baseSound = audio::load_sound(soundFile, keepPCM);
|
baseSound = audio::load_sound(soundFile, keepPCM);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// looking for 'sound_name_0' as base sound
|
// looking for 'sound_name_0' as base sound
|
||||||
auto variantFile = paths->find(file + "_0" + extension);
|
auto variantFile = paths.find(file + "_0" + extension);
|
||||||
if (io::exists(variantFile)) {
|
if (io::exists(variantFile)) {
|
||||||
baseSound = audio::load_sound(variantFile, keepPCM);
|
baseSound = audio::load_sound(variantFile, keepPCM);
|
||||||
break;
|
break;
|
||||||
@ -238,7 +239,7 @@ assetload::postfunc assetload::sound(
|
|||||||
// loading sound variants
|
// loading sound variants
|
||||||
for (uint i = 1;; i++) {
|
for (uint i = 1;; i++) {
|
||||||
auto variantFile =
|
auto variantFile =
|
||||||
paths->find(file + "_" + std::to_string(i) + extension);
|
paths.find(file + "_" + std::to_string(i) + extension);
|
||||||
if (!io::exists(variantFile)) {
|
if (!io::exists(variantFile)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -264,12 +265,12 @@ static void request_textures(AssetsLoader* loader, const model::Model& model) {
|
|||||||
|
|
||||||
assetload::postfunc assetload::model(
|
assetload::postfunc assetload::model(
|
||||||
AssetsLoader* loader,
|
AssetsLoader* loader,
|
||||||
const ResPaths* paths,
|
const ResPaths& paths,
|
||||||
const std::string& file,
|
const std::string& file,
|
||||||
const std::string& name,
|
const std::string& name,
|
||||||
const std::shared_ptr<AssetCfg>&
|
const std::shared_ptr<AssetCfg>&
|
||||||
) {
|
) {
|
||||||
auto path = paths->find(file + ".vec3");
|
auto path = paths.find(file + ".vec3");
|
||||||
if (io::exists(path)) {
|
if (io::exists(path)) {
|
||||||
auto bytes = io::read_bytes_buffer(path);
|
auto bytes = io::read_bytes_buffer(path);
|
||||||
auto modelVEC3 = std::make_shared<vec3::File>(vec3::load(path.string(), bytes));
|
auto modelVEC3 = std::make_shared<vec3::File>(vec3::load(path.string(), bytes));
|
||||||
@ -289,7 +290,7 @@ assetload::postfunc assetload::model(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
path = paths->find(file + ".obj");
|
path = paths.find(file + ".obj");
|
||||||
auto text = io::read_string(path);
|
auto text = io::read_string(path);
|
||||||
try {
|
try {
|
||||||
auto model = obj::parse(path.string(), text).release();
|
auto model = obj::parse(path.string(), text).release();
|
||||||
@ -383,7 +384,7 @@ inline bool contains(
|
|||||||
|
|
||||||
static bool load_animation(
|
static bool load_animation(
|
||||||
Assets* assets,
|
Assets* assets,
|
||||||
const ResPaths* paths,
|
const ResPaths& paths,
|
||||||
const std::string& atlasName,
|
const std::string& atlasName,
|
||||||
const std::string& directory,
|
const std::string& directory,
|
||||||
const std::string& name,
|
const std::string& name,
|
||||||
@ -391,20 +392,20 @@ static bool load_animation(
|
|||||||
) {
|
) {
|
||||||
std::string animsDir = directory + "/animation";
|
std::string animsDir = directory + "/animation";
|
||||||
|
|
||||||
for (const auto& folder : paths->listdir(animsDir)) {
|
for (const auto& folder : paths.listdir(animsDir)) {
|
||||||
if (!io::is_directory(folder)) continue;
|
if (!io::is_directory(folder)) continue;
|
||||||
if (folder.name() != name) continue;
|
if (folder.name() != name) continue;
|
||||||
//FIXME: if (fs::is_empty(folder)) continue;
|
//FIXME: if (fs::is_empty(folder)) continue;
|
||||||
|
|
||||||
AtlasBuilder builder;
|
AtlasBuilder builder;
|
||||||
append_atlas(builder, paths->find(directory + "/" + name + ".png"));
|
append_atlas(builder, paths.find(directory + "/" + name + ".png"));
|
||||||
|
|
||||||
std::vector<std::pair<std::string, int>> frameList;
|
std::vector<std::pair<std::string, int>> frameList;
|
||||||
std::string animFile = folder.string() + "/animation.json";
|
std::string animFile = folder.string() + "/animation.json";
|
||||||
if (io::exists(animFile)) {
|
if (io::exists(animFile)) {
|
||||||
read_anim_file(animFile, frameList);
|
read_anim_file(animFile, frameList);
|
||||||
}
|
}
|
||||||
for (const auto& file : paths->listdir(animsDir + "/" + name)) {
|
for (const auto& file : paths.listdir(animsDir + "/" + name)) {
|
||||||
if (!frameList.empty() &&
|
if (!frameList.empty() &&
|
||||||
!contains(frameList, file.stem())) {
|
!contains(frameList, file.stem())) {
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@ -15,49 +15,49 @@ struct AssetCfg;
|
|||||||
namespace assetload {
|
namespace assetload {
|
||||||
postfunc texture(
|
postfunc texture(
|
||||||
AssetsLoader*,
|
AssetsLoader*,
|
||||||
const ResPaths* paths,
|
const ResPaths& paths,
|
||||||
const std::string& filename,
|
const std::string& filename,
|
||||||
const std::string& name,
|
const std::string& name,
|
||||||
const std::shared_ptr<AssetCfg>& settings
|
const std::shared_ptr<AssetCfg>& settings
|
||||||
);
|
);
|
||||||
postfunc shader(
|
postfunc shader(
|
||||||
AssetsLoader*,
|
AssetsLoader*,
|
||||||
const ResPaths* paths,
|
const ResPaths& paths,
|
||||||
const std::string& filename,
|
const std::string& filename,
|
||||||
const std::string& name,
|
const std::string& name,
|
||||||
const std::shared_ptr<AssetCfg>& settings
|
const std::shared_ptr<AssetCfg>& settings
|
||||||
);
|
);
|
||||||
postfunc atlas(
|
postfunc atlas(
|
||||||
AssetsLoader*,
|
AssetsLoader*,
|
||||||
const ResPaths* paths,
|
const ResPaths& paths,
|
||||||
const std::string& directory,
|
const std::string& directory,
|
||||||
const std::string& name,
|
const std::string& name,
|
||||||
const std::shared_ptr<AssetCfg>& settings
|
const std::shared_ptr<AssetCfg>& settings
|
||||||
);
|
);
|
||||||
postfunc font(
|
postfunc font(
|
||||||
AssetsLoader*,
|
AssetsLoader*,
|
||||||
const ResPaths* paths,
|
const ResPaths& paths,
|
||||||
const std::string& filename,
|
const std::string& filename,
|
||||||
const std::string& name,
|
const std::string& name,
|
||||||
const std::shared_ptr<AssetCfg>& settings
|
const std::shared_ptr<AssetCfg>& settings
|
||||||
);
|
);
|
||||||
postfunc layout(
|
postfunc layout(
|
||||||
AssetsLoader*,
|
AssetsLoader*,
|
||||||
const ResPaths* paths,
|
const ResPaths& paths,
|
||||||
const std::string& file,
|
const std::string& file,
|
||||||
const std::string& name,
|
const std::string& name,
|
||||||
const std::shared_ptr<AssetCfg>& settings
|
const std::shared_ptr<AssetCfg>& settings
|
||||||
);
|
);
|
||||||
postfunc sound(
|
postfunc sound(
|
||||||
AssetsLoader*,
|
AssetsLoader*,
|
||||||
const ResPaths* paths,
|
const ResPaths& paths,
|
||||||
const std::string& file,
|
const std::string& file,
|
||||||
const std::string& name,
|
const std::string& name,
|
||||||
const std::shared_ptr<AssetCfg>& settings
|
const std::shared_ptr<AssetCfg>& settings
|
||||||
);
|
);
|
||||||
postfunc model(
|
postfunc model(
|
||||||
AssetsLoader*,
|
AssetsLoader*,
|
||||||
const ResPaths* paths,
|
const ResPaths& paths,
|
||||||
const std::string& file,
|
const std::string& file,
|
||||||
const std::string& name,
|
const std::string& name,
|
||||||
const std::shared_ptr<AssetCfg>& settings
|
const std::shared_ptr<AssetCfg>& settings
|
||||||
|
|||||||
@ -17,12 +17,12 @@ static debug::Logger logger("audio");
|
|||||||
using namespace audio;
|
using namespace audio;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
static speakerid_t nextId = 1;
|
speakerid_t nextId = 1;
|
||||||
static Backend* backend;
|
Backend* backend;
|
||||||
static std::unordered_map<speakerid_t, std::unique_ptr<Speaker>> speakers;
|
std::unordered_map<speakerid_t, std::unique_ptr<Speaker>> speakers;
|
||||||
static std::unordered_map<speakerid_t, std::shared_ptr<Stream>> streams;
|
std::unordered_map<speakerid_t, std::shared_ptr<Stream>> streams;
|
||||||
static std::vector<std::unique_ptr<Channel>> channels;
|
std::vector<std::unique_ptr<Channel>> channels;
|
||||||
static util::ObjectsKeeper objects_keeper {};
|
util::ObjectsKeeper objects_keeper {};
|
||||||
}
|
}
|
||||||
|
|
||||||
Channel::Channel(std::string name) : name(std::move(name)) {
|
Channel::Channel(std::string name) : name(std::move(name)) {
|
||||||
|
|||||||
@ -7,16 +7,20 @@ template <typename CharT>
|
|||||||
class BasicParser {
|
class BasicParser {
|
||||||
using StringT = std::basic_string<CharT>;
|
using StringT = std::basic_string<CharT>;
|
||||||
using StringViewT = std::basic_string_view<CharT>;
|
using StringViewT = std::basic_string_view<CharT>;
|
||||||
|
|
||||||
|
void skipWhitespaceHashComment(bool newline = true);
|
||||||
protected:
|
protected:
|
||||||
std::string_view filename;
|
std::string_view filename;
|
||||||
StringViewT source;
|
StringViewT source;
|
||||||
uint pos = 0;
|
uint pos = 0;
|
||||||
uint line = 1;
|
uint line = 1;
|
||||||
uint linestart = 0;
|
uint linestart = 0;
|
||||||
|
bool hashComment = false;
|
||||||
|
|
||||||
virtual void skipWhitespace();
|
void skipWhitespace(bool newline = true);
|
||||||
void skip(size_t n);
|
void skip(size_t n);
|
||||||
void skipLine();
|
void skipLine();
|
||||||
|
void skipEmptyLines();
|
||||||
bool skipTo(const StringT& substring);
|
bool skipTo(const StringT& substring);
|
||||||
void expect(CharT expected);
|
void expect(CharT expected);
|
||||||
void expect(const StringT& substring);
|
void expect(const StringT& substring);
|
||||||
|
|||||||
@ -31,10 +31,17 @@ namespace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename CharT>
|
template<typename CharT>
|
||||||
void BasicParser<CharT>::skipWhitespace() {
|
void BasicParser<CharT>::skipWhitespace(bool newline) {
|
||||||
|
if (hashComment) {
|
||||||
|
skipWhitespaceHashComment(newline);
|
||||||
|
return;
|
||||||
|
}
|
||||||
while (hasNext()) {
|
while (hasNext()) {
|
||||||
char next = source[pos];
|
char next = source[pos];
|
||||||
if (next == '\n') {
|
if (next == '\n') {
|
||||||
|
if (!newline) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
line++;
|
line++;
|
||||||
linestart = ++pos;
|
linestart = ++pos;
|
||||||
continue;
|
continue;
|
||||||
@ -47,6 +54,36 @@ void BasicParser<CharT>::skipWhitespace() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename CharT>
|
||||||
|
void BasicParser<CharT>::skipWhitespaceHashComment(bool newline) {
|
||||||
|
while (hasNext()) {
|
||||||
|
char next = source[pos];
|
||||||
|
if (next == '\n') {
|
||||||
|
if (!newline) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
line++;
|
||||||
|
linestart = ++pos;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (is_whitespace(next)) {
|
||||||
|
pos++;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (hasNext() && source[pos] == '#') {
|
||||||
|
if (!newline) {
|
||||||
|
readUntilEOL();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
skipLine();
|
||||||
|
if (hasNext() && (is_whitespace(source[pos]) || source[pos] == '#')) {
|
||||||
|
skipWhitespaceHashComment(newline);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template<typename CharT>
|
template<typename CharT>
|
||||||
void BasicParser<CharT>::skip(size_t n) {
|
void BasicParser<CharT>::skip(size_t n) {
|
||||||
n = std::min(n, source.length() - pos);
|
n = std::min(n, source.length() - pos);
|
||||||
@ -73,6 +110,12 @@ void BasicParser<CharT>::skipLine() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename CharT>
|
||||||
|
void BasicParser<CharT>::skipEmptyLines() {
|
||||||
|
skipWhitespace();
|
||||||
|
pos = linestart;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename CharT>
|
template<typename CharT>
|
||||||
bool BasicParser<CharT>::skipTo(const std::basic_string<CharT>& substring) {
|
bool BasicParser<CharT>::skipTo(const std::basic_string<CharT>& substring) {
|
||||||
size_t idx = source.find(substring, pos);
|
size_t idx = source.find(substring, pos);
|
||||||
@ -240,9 +283,12 @@ std::basic_string_view<CharT> BasicParser<CharT>::readUntilWhitespace() {
|
|||||||
template <typename CharT>
|
template <typename CharT>
|
||||||
std::basic_string_view<CharT> BasicParser<CharT>::readUntilEOL() {
|
std::basic_string_view<CharT> BasicParser<CharT>::readUntilEOL() {
|
||||||
int start = pos;
|
int start = pos;
|
||||||
while (hasNext() && source[pos] != '\r' && source[pos] != '\n') {
|
while (hasNext() && source[pos] != '\n') {
|
||||||
pos++;
|
pos++;
|
||||||
}
|
}
|
||||||
|
if (pos > start && source[pos - 1] == '\r') {
|
||||||
|
return source.substr(start, pos - start - 1);
|
||||||
|
}
|
||||||
return source.substr(start, pos - start);
|
return source.substr(start, pos - start);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -13,13 +13,14 @@ using namespace json;
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
class Parser : BasicParser<char> {
|
class Parser : BasicParser<char> {
|
||||||
dv::value parseList();
|
|
||||||
dv::value parseObject();
|
|
||||||
dv::value parseValue();
|
|
||||||
public:
|
public:
|
||||||
Parser(std::string_view filename, std::string_view source);
|
Parser(std::string_view filename, std::string_view source);
|
||||||
|
|
||||||
dv::value parse();
|
dv::value parse();
|
||||||
|
private:
|
||||||
|
dv::value parseList();
|
||||||
|
dv::value parseObject();
|
||||||
|
dv::value parseValue();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -16,16 +16,6 @@ using namespace toml;
|
|||||||
class TomlReader : BasicParser<char> {
|
class TomlReader : BasicParser<char> {
|
||||||
dv::value root;
|
dv::value root;
|
||||||
|
|
||||||
void skipWhitespace() override {
|
|
||||||
BasicParser::skipWhitespace();
|
|
||||||
if (hasNext() && source[pos] == '#') {
|
|
||||||
skipLine();
|
|
||||||
if (hasNext() && is_whitespace(peek())) {
|
|
||||||
skipWhitespace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// modified version of BaseParser.parseString
|
// modified version of BaseParser.parseString
|
||||||
// todo: extract common part
|
// todo: extract common part
|
||||||
std::string parseMultilineString() {
|
std::string parseMultilineString() {
|
||||||
@ -214,6 +204,7 @@ class TomlReader : BasicParser<char> {
|
|||||||
public:
|
public:
|
||||||
TomlReader(std::string_view file, std::string_view source)
|
TomlReader(std::string_view file, std::string_view source)
|
||||||
: BasicParser(file, source), root(dv::object()) {
|
: BasicParser(file, source), root(dv::object()) {
|
||||||
|
hashComment = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
dv::value read() {
|
dv::value read() {
|
||||||
|
|||||||
459
src/coders/yaml.cpp
Normal file
459
src/coders/yaml.cpp
Normal file
@ -0,0 +1,459 @@
|
|||||||
|
#include "yaml.hpp"
|
||||||
|
#include "BasicParser.hpp"
|
||||||
|
|
||||||
|
#include <iomanip>
|
||||||
|
|
||||||
|
using namespace yaml;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
enum Chomping {
|
||||||
|
CLIP, STRIP, KEEP
|
||||||
|
};
|
||||||
|
|
||||||
|
class Parser : BasicParser<char> {
|
||||||
|
public:
|
||||||
|
Parser(std::string_view filename, std::string_view source);
|
||||||
|
|
||||||
|
dv::value parseValue();
|
||||||
|
dv::value parseFullValue(int indent);
|
||||||
|
dv::value parseArray(int indent = 0);
|
||||||
|
dv::value parseObject(dv::value&& object, int indent = 0);
|
||||||
|
dv::value parseInlineArray();
|
||||||
|
dv::value parseInlineObject();
|
||||||
|
private:
|
||||||
|
int countIndent();
|
||||||
|
bool expectIndent(int indent);
|
||||||
|
std::string_view readYamlIdentifier();
|
||||||
|
std::string readMultilineString(int indent, bool eols, Chomping chomp);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool is_yaml_identifier_char(int c) {
|
||||||
|
return c > 20 && c != ':' && c != ' ' && c != '\n' && c != '\r' &&
|
||||||
|
c != '\t' && c != '\f' && c != '\v';
|
||||||
|
}
|
||||||
|
|
||||||
|
static dv::value perform_literal(std::string_view literal) {
|
||||||
|
if (literal == "true" || literal == "True" ||
|
||||||
|
literal == "false" || literal == "False") {
|
||||||
|
return literal[0] == 't';
|
||||||
|
}
|
||||||
|
if (literal == "null" || literal == "Null") {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return std::string(literal);
|
||||||
|
}
|
||||||
|
|
||||||
|
Parser::Parser(std::string_view filename, std::string_view source)
|
||||||
|
: BasicParser(filename, source) {
|
||||||
|
hashComment = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Parser::expectIndent(int required) {
|
||||||
|
int indent = 0;
|
||||||
|
while (hasNext() && source[pos] == ' ' && indent < required) {
|
||||||
|
indent++;
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
return indent >= required;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Parser::readMultilineString(int indent, bool eols, Chomping chomp) {
|
||||||
|
int next_indent = countIndent();
|
||||||
|
if (next_indent <= indent) {
|
||||||
|
throw error("indentation error");
|
||||||
|
}
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << readUntilEOL();
|
||||||
|
if (hasNext()) {
|
||||||
|
skip(1);
|
||||||
|
}
|
||||||
|
int trailingEmpties = 0;
|
||||||
|
while (true) {
|
||||||
|
while (expectIndent(next_indent)) {
|
||||||
|
trailingEmpties = 0;
|
||||||
|
ss << (eols ? '\n' : ' ');
|
||||||
|
ss << readUntilEOL();
|
||||||
|
if (hasNext()) {
|
||||||
|
skip(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (true) {
|
||||||
|
skipWhitespace(false);
|
||||||
|
if (!hasNext() || source[pos] != '\n') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
skip(1);
|
||||||
|
trailingEmpties++;
|
||||||
|
}
|
||||||
|
if (!expectIndent(next_indent)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pos = linestart;
|
||||||
|
}
|
||||||
|
if (chomp == KEEP) {
|
||||||
|
for (int i = 0; i < trailingEmpties - 1; i++) {
|
||||||
|
ss << (eols ? '\n' : ' ');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ss << '\n';
|
||||||
|
|
||||||
|
pos = linestart;
|
||||||
|
|
||||||
|
auto string = ss.str();
|
||||||
|
if (chomp == STRIP) {
|
||||||
|
util::trim(string);
|
||||||
|
}
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string_view Parser::readYamlIdentifier() {
|
||||||
|
char c = peek();
|
||||||
|
if (!is_yaml_identifier_char(c)) {
|
||||||
|
throw error("identifier expected");
|
||||||
|
}
|
||||||
|
int start = pos;
|
||||||
|
while (hasNext() && is_yaml_identifier_char(source[pos])) {
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
return source.substr(start, pos - start);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Parser::countIndent() {
|
||||||
|
int indent = 0;
|
||||||
|
while (hasNext() && source[pos] == ' ') {
|
||||||
|
indent++;
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
return indent;
|
||||||
|
}
|
||||||
|
|
||||||
|
dv::value Parser::parseValue() {
|
||||||
|
char c = peek();
|
||||||
|
if (is_digit(c)) {
|
||||||
|
return parseNumber(1);
|
||||||
|
} else if (c == '-' || c == '+') {
|
||||||
|
skip(1);
|
||||||
|
return parseNumber(c == '-' ? -1 : 1);
|
||||||
|
} else if (c == '"' || c == '\'') {
|
||||||
|
skip(1);
|
||||||
|
return parseString(c, true);
|
||||||
|
} else if (c == '[') {
|
||||||
|
return parseInlineArray();
|
||||||
|
} else if (c == '{') {
|
||||||
|
return parseInlineObject();
|
||||||
|
} else {
|
||||||
|
return perform_literal(readUntilEOL());
|
||||||
|
}
|
||||||
|
throw error("unexpected character");
|
||||||
|
}
|
||||||
|
|
||||||
|
dv::value Parser::parseInlineArray() {
|
||||||
|
expect('[');
|
||||||
|
auto list = dv::list();
|
||||||
|
while (peek() != ']') {
|
||||||
|
if (peek() == '#') {
|
||||||
|
skipLine();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
list.add(parseValue());
|
||||||
|
|
||||||
|
char next = peek();
|
||||||
|
if (next == ',') {
|
||||||
|
pos++;
|
||||||
|
} else if (next == ']') {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
throw error("',' expected");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pos++;
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
dv::value Parser::parseInlineObject() {
|
||||||
|
expect('{');
|
||||||
|
dv::value object = dv::object();
|
||||||
|
while (peek() != '}') {
|
||||||
|
if (peek() == '#') {
|
||||||
|
skipLine();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
auto name = readYamlIdentifier();
|
||||||
|
expect(':');
|
||||||
|
object[std::string(name)] = parseValue();
|
||||||
|
|
||||||
|
char next = peek();
|
||||||
|
if (next == ',') {
|
||||||
|
pos++;
|
||||||
|
} else if (next == '}') {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
throw error("',' expected");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pos++;
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
dv::value Parser::parseFullValue(int indent) {
|
||||||
|
dv::value value;
|
||||||
|
char c = source[pos];
|
||||||
|
if (c == '\n') {
|
||||||
|
skip(1);
|
||||||
|
skipEmptyLines();
|
||||||
|
int init_pos = pos;
|
||||||
|
int next_indent = countIndent();
|
||||||
|
if (next_indent < indent) {
|
||||||
|
throw error("indentation error");
|
||||||
|
}
|
||||||
|
if (source[pos] == '-') {
|
||||||
|
pos = init_pos;
|
||||||
|
return parseArray(next_indent);
|
||||||
|
} else {
|
||||||
|
pos = init_pos;
|
||||||
|
return parseObject(dv::object(), next_indent);
|
||||||
|
}
|
||||||
|
} else if (is_digit(c)) {
|
||||||
|
return parseNumber(1);
|
||||||
|
} else if (c == '-' || c == '+') {
|
||||||
|
skip(1);
|
||||||
|
return parseNumber(c == '-' ? -1 : 1);
|
||||||
|
} else if (c == '"' || c == '\'') {
|
||||||
|
skip(1);
|
||||||
|
return parseString(c, true);
|
||||||
|
} else if (c == '[') {
|
||||||
|
return parseInlineArray();
|
||||||
|
} else if (c == '{') {
|
||||||
|
return parseInlineObject();
|
||||||
|
} else if (c == '|' || c == '>') {
|
||||||
|
skip(1);
|
||||||
|
Chomping chomp = CLIP;
|
||||||
|
if (source[pos] == '-' || source[pos] == '+') {
|
||||||
|
chomp = source[pos] == '-' ? STRIP : KEEP;
|
||||||
|
skip(1);
|
||||||
|
}
|
||||||
|
skipWhitespace(false);
|
||||||
|
expectNewLine();
|
||||||
|
return readMultilineString(indent, c == '|', chomp);
|
||||||
|
} else {
|
||||||
|
return perform_literal(readUntilEOL());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dv::value Parser::parseArray(int indent) {
|
||||||
|
dv::value list = dv::list();
|
||||||
|
|
||||||
|
while (hasNext()) {
|
||||||
|
skipEmptyLines();
|
||||||
|
int next_indent = countIndent();
|
||||||
|
if (next_indent < indent) {
|
||||||
|
pos = linestart;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
expect('-');
|
||||||
|
skipWhitespace();
|
||||||
|
size_t nlpos = source.find('\n', pos);
|
||||||
|
size_t colonpos = source.find(':', pos);
|
||||||
|
if (nlpos == std::string::npos && colonpos == std::string::npos) {
|
||||||
|
list.add(perform_literal(readUntilEOL()));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (nlpos < colonpos) {
|
||||||
|
list.add(parseFullValue(next_indent));
|
||||||
|
skipLine();
|
||||||
|
} else {
|
||||||
|
auto name = readYamlIdentifier();
|
||||||
|
expect(':');
|
||||||
|
skipWhitespace(false);
|
||||||
|
dv::value object = dv::object();
|
||||||
|
object[std::string(name)] = parseFullValue(next_indent);
|
||||||
|
skipEmptyLines();
|
||||||
|
next_indent = countIndent();
|
||||||
|
if (next_indent > indent) {
|
||||||
|
pos = linestart;
|
||||||
|
object = parseObject(std::move(object), next_indent);
|
||||||
|
} else {
|
||||||
|
pos = linestart;
|
||||||
|
}
|
||||||
|
list.add(std::move(object));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
dv::value Parser::parseObject(dv::value&& object, int indent) {
|
||||||
|
skipEmptyLines();
|
||||||
|
while (hasNext()) {
|
||||||
|
size_t prev_pos = pos;
|
||||||
|
int next_indent = countIndent();
|
||||||
|
if (source[pos] == '\n') {
|
||||||
|
skip(1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (next_indent < indent) {
|
||||||
|
pos = prev_pos;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
char c = peek();
|
||||||
|
if (!is_yaml_identifier_char(c)) {
|
||||||
|
if (!is_whitespace(c)) {
|
||||||
|
throw error("invalid character");
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
auto name = readYamlIdentifier();
|
||||||
|
expect(':');
|
||||||
|
skipWhitespace(false);
|
||||||
|
object[std::string(name)] = parseFullValue(indent);
|
||||||
|
skipEmptyLines();
|
||||||
|
}
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
dv::value yaml::parse(std::string_view filename, std::string_view source) {
|
||||||
|
return Parser(filename, source).parseObject(dv::object());
|
||||||
|
}
|
||||||
|
|
||||||
|
dv::value yaml::parse(std::string_view source) {
|
||||||
|
return parse("[string]", source);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void add_indent(std::stringstream& ss, int indent) {
|
||||||
|
for (int i = 0; i < indent; i++) {
|
||||||
|
ss << " ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void insert_string(
|
||||||
|
std::stringstream& ss, const std::string& string, int indent
|
||||||
|
) {
|
||||||
|
bool has_spec_chars = false;
|
||||||
|
bool multiline = false;
|
||||||
|
for (char c : string) {
|
||||||
|
if (c < ' ' || c == '"' || c == '\'') {
|
||||||
|
has_spec_chars = true;
|
||||||
|
if (multiline) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (c == '\n') {
|
||||||
|
multiline = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (multiline) {
|
||||||
|
ss << "|-\n";
|
||||||
|
size_t offset = 0;
|
||||||
|
size_t newoffset = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
offset = newoffset;
|
||||||
|
if (offset == string.length() - 1 && string[offset] == '\n') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
add_indent(ss, indent);
|
||||||
|
newoffset = string.find('\n', offset + 1);
|
||||||
|
if (newoffset == std::string::npos) {
|
||||||
|
ss << string.substr(offset);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
ss << string.substr(offset + 1, newoffset - offset - 1);
|
||||||
|
}
|
||||||
|
ss << '\n';
|
||||||
|
} while (true);
|
||||||
|
} else {
|
||||||
|
if (has_spec_chars || string.empty()) {
|
||||||
|
ss << util::escape(string, false);
|
||||||
|
} else {
|
||||||
|
ss << string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void to_string(
|
||||||
|
std::stringstream& ss,
|
||||||
|
const dv::value& value,
|
||||||
|
int indent,
|
||||||
|
bool eliminateIndent = false
|
||||||
|
) {
|
||||||
|
using dv::value_type;
|
||||||
|
|
||||||
|
switch (value.getType()) {
|
||||||
|
case value_type::string:
|
||||||
|
insert_string(ss, value.asString(), indent);
|
||||||
|
break;
|
||||||
|
case value_type::number:
|
||||||
|
ss << std::setprecision(15) << value.asNumber();
|
||||||
|
break;
|
||||||
|
case value_type::integer:
|
||||||
|
ss << value.asInteger();
|
||||||
|
break;
|
||||||
|
case value_type::boolean:
|
||||||
|
ss << (value.asBoolean() ? "true" : "false");
|
||||||
|
break;
|
||||||
|
case value_type::none:
|
||||||
|
ss << "null";
|
||||||
|
break;
|
||||||
|
case value_type::object: {
|
||||||
|
if (value.empty()) {
|
||||||
|
ss << "{}";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
bool first = true;
|
||||||
|
for (const auto& [key, elem] : value.asObject()) {
|
||||||
|
if (!first) {
|
||||||
|
ss << '\n';
|
||||||
|
}
|
||||||
|
if (!eliminateIndent) {
|
||||||
|
add_indent(ss, indent);
|
||||||
|
} else {
|
||||||
|
eliminateIndent = false;
|
||||||
|
}
|
||||||
|
ss << key << ": ";
|
||||||
|
if ((elem.isObject() || elem.isList()) && !elem.empty()) {
|
||||||
|
ss << "\n";
|
||||||
|
to_string(ss, elem, indent + 1);
|
||||||
|
} else {
|
||||||
|
to_string(ss, elem, indent + 1);
|
||||||
|
}
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case value_type::list: {
|
||||||
|
if (value.empty()) {
|
||||||
|
ss << "[]";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
bool first = true;
|
||||||
|
for (const auto& elem : value) {
|
||||||
|
if (!first) {
|
||||||
|
ss << '\n';
|
||||||
|
}
|
||||||
|
if (!eliminateIndent) {
|
||||||
|
add_indent(ss, indent);
|
||||||
|
} else {
|
||||||
|
eliminateIndent = false;
|
||||||
|
}
|
||||||
|
ss << "- ";
|
||||||
|
to_string(ss, elem, indent + 1, true);
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case value_type::bytes: {
|
||||||
|
const auto& bytes = value.asBytes();
|
||||||
|
auto b64 = util::base64_encode(bytes.data(), bytes.size());
|
||||||
|
b64 = util::join(util::split_by_n(b64, 64), '\n');
|
||||||
|
insert_string(ss, b64, indent);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string yaml::stringify(const dv::value& value) {
|
||||||
|
std::stringstream ss;
|
||||||
|
to_string(ss, value, 0);
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
12
src/coders/yaml.hpp
Normal file
12
src/coders/yaml.hpp
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "data/dv.hpp"
|
||||||
|
|
||||||
|
namespace yaml {
|
||||||
|
dv::value parse(std::string_view filename, std::string_view source);
|
||||||
|
dv::value parse(std::string_view source);
|
||||||
|
|
||||||
|
std::string stringify(const dv::value& value);
|
||||||
|
}
|
||||||
@ -6,7 +6,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
inline constexpr int ENGINE_VERSION_MAJOR = 0;
|
inline constexpr int ENGINE_VERSION_MAJOR = 0;
|
||||||
inline constexpr int ENGINE_VERSION_MINOR = 27;
|
inline constexpr int ENGINE_VERSION_MINOR = 28;
|
||||||
|
|
||||||
#ifdef NDEBUG
|
#ifdef NDEBUG
|
||||||
inline constexpr bool ENGINE_DEBUG_BUILD = false;
|
inline constexpr bool ENGINE_DEBUG_BUILD = false;
|
||||||
@ -14,7 +14,7 @@ inline constexpr bool ENGINE_DEBUG_BUILD = false;
|
|||||||
inline constexpr bool ENGINE_DEBUG_BUILD = true;
|
inline constexpr bool ENGINE_DEBUG_BUILD = true;
|
||||||
#endif // NDEBUG
|
#endif // NDEBUG
|
||||||
|
|
||||||
inline const std::string ENGINE_VERSION_STRING = "0.27";
|
inline const std::string ENGINE_VERSION_STRING = "0.28";
|
||||||
|
|
||||||
/// @brief world regions format version
|
/// @brief world regions format version
|
||||||
inline constexpr uint REGION_FORMAT_VERSION = 3;
|
inline constexpr uint REGION_FORMAT_VERSION = 3;
|
||||||
|
|||||||
133
src/content/ContentControl.cpp
Normal file
133
src/content/ContentControl.cpp
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
#include "ContentControl.hpp"
|
||||||
|
|
||||||
|
#include "io/io.hpp"
|
||||||
|
#include "io/engine_paths.hpp"
|
||||||
|
#include "Content.hpp"
|
||||||
|
#include "ContentPack.hpp"
|
||||||
|
#include "ContentBuilder.hpp"
|
||||||
|
#include "ContentLoader.hpp"
|
||||||
|
#include "PacksManager.hpp"
|
||||||
|
#include "objects/rigging.hpp"
|
||||||
|
#include "logic/scripting/scripting.hpp"
|
||||||
|
#include "core_defs.hpp"
|
||||||
|
|
||||||
|
static void load_configs(Input& input, const io::path& root) {
|
||||||
|
auto configFolder = root / "config";
|
||||||
|
}
|
||||||
|
|
||||||
|
ContentControl::ContentControl(
|
||||||
|
EnginePaths& paths, Input& input, std::function<void()> postContent
|
||||||
|
)
|
||||||
|
: paths(paths),
|
||||||
|
input(input),
|
||||||
|
postContent(std::move(postContent)),
|
||||||
|
basePacks(io::read_list("res:config/builtins.list")),
|
||||||
|
manager(std::make_unique<PacksManager>()) {
|
||||||
|
manager->setSources({
|
||||||
|
"world:content",
|
||||||
|
"user:content",
|
||||||
|
"res:content",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ContentControl::~ContentControl() = default;
|
||||||
|
|
||||||
|
Content* ContentControl::get() {
|
||||||
|
return content.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
const Content* ContentControl::get() const {
|
||||||
|
return content.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string>& ContentControl::getBasePacks() {
|
||||||
|
return basePacks;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ContentControl::resetContent() {
|
||||||
|
paths.setCurrentWorldFolder("");
|
||||||
|
|
||||||
|
scripting::cleanup();
|
||||||
|
std::vector<PathsRoot> resRoots;
|
||||||
|
{
|
||||||
|
auto pack = ContentPack::createCore(paths);
|
||||||
|
resRoots.push_back({"core", pack.folder});
|
||||||
|
load_configs(input, pack.folder);
|
||||||
|
}
|
||||||
|
manager->scan();
|
||||||
|
for (const auto& pack : manager->getAll(basePacks)) {
|
||||||
|
resRoots.push_back({pack.id, pack.folder});
|
||||||
|
}
|
||||||
|
paths.resPaths = ResPaths(resRoots);
|
||||||
|
content.reset();
|
||||||
|
|
||||||
|
contentPacks.clear();
|
||||||
|
contentPacks = manager->getAll(basePacks);
|
||||||
|
|
||||||
|
postContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ContentControl::loadContent(const std::vector<std::string>& names) {
|
||||||
|
manager->scan();
|
||||||
|
contentPacks = manager->getAll(manager->assemble(names));
|
||||||
|
loadContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ContentControl::loadContent() {
|
||||||
|
scripting::cleanup();
|
||||||
|
|
||||||
|
std::vector<std::string> names;
|
||||||
|
for (auto& pack : contentPacks) {
|
||||||
|
names.push_back(pack.id);
|
||||||
|
}
|
||||||
|
manager->scan();
|
||||||
|
names = manager->assemble(names);
|
||||||
|
contentPacks = manager->getAll(names);
|
||||||
|
|
||||||
|
std::vector<PathsRoot> entryPoints;
|
||||||
|
for (auto& pack : contentPacks) {
|
||||||
|
entryPoints.emplace_back(pack.id, pack.folder);
|
||||||
|
}
|
||||||
|
paths.setEntryPoints(std::move(entryPoints));
|
||||||
|
|
||||||
|
ContentBuilder contentBuilder;
|
||||||
|
corecontent::setup(input, contentBuilder);
|
||||||
|
|
||||||
|
auto corePack = ContentPack::createCore(paths);
|
||||||
|
|
||||||
|
auto allPacks = contentPacks;
|
||||||
|
allPacks.insert(allPacks.begin(), corePack);
|
||||||
|
|
||||||
|
// Setup filesystem entry points
|
||||||
|
std::vector<PathsRoot> resRoots;
|
||||||
|
for (auto& pack : allPacks) {
|
||||||
|
resRoots.push_back({pack.id, pack.folder});
|
||||||
|
}
|
||||||
|
paths.resPaths = ResPaths(resRoots);
|
||||||
|
// Load content
|
||||||
|
for (auto& pack : allPacks) {
|
||||||
|
ContentLoader(&pack, contentBuilder, paths.resPaths).load();
|
||||||
|
load_configs(input, pack.folder);
|
||||||
|
}
|
||||||
|
content = contentBuilder.build();
|
||||||
|
scripting::on_content_load(content.get());
|
||||||
|
|
||||||
|
ContentLoader::loadScripts(*content);
|
||||||
|
|
||||||
|
postContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<ContentPack>& ContentControl::getContentPacks() {
|
||||||
|
return contentPacks;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<ContentPack> ContentControl::getAllContentPacks() {
|
||||||
|
auto packs = contentPacks;
|
||||||
|
packs.insert(packs.begin(), ContentPack::createCore(paths));
|
||||||
|
return packs;
|
||||||
|
}
|
||||||
|
|
||||||
|
PacksManager& ContentControl::scan() {
|
||||||
|
manager->scan();
|
||||||
|
return *manager;
|
||||||
|
}
|
||||||
51
src/content/ContentControl.hpp
Normal file
51
src/content/ContentControl.hpp
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
#include "ContentPack.hpp"
|
||||||
|
|
||||||
|
class Content;
|
||||||
|
class PacksManager;
|
||||||
|
class EnginePaths;
|
||||||
|
class Input;
|
||||||
|
|
||||||
|
namespace io {
|
||||||
|
class path;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ContentControl {
|
||||||
|
public:
|
||||||
|
ContentControl(
|
||||||
|
EnginePaths& paths, Input& input, std::function<void()> postContent
|
||||||
|
);
|
||||||
|
~ContentControl();
|
||||||
|
|
||||||
|
Content* get();
|
||||||
|
|
||||||
|
const Content* get() const;
|
||||||
|
|
||||||
|
std::vector<std::string>& getBasePacks();
|
||||||
|
|
||||||
|
/// @brief Reset content to base packs list
|
||||||
|
void resetContent();
|
||||||
|
|
||||||
|
void loadContent(const std::vector<std::string>& names);
|
||||||
|
|
||||||
|
void loadContent();
|
||||||
|
|
||||||
|
std::vector<ContentPack>& getContentPacks();
|
||||||
|
std::vector<ContentPack> getAllContentPacks();
|
||||||
|
|
||||||
|
PacksManager& scan();
|
||||||
|
private:
|
||||||
|
EnginePaths& paths;
|
||||||
|
Input& input;
|
||||||
|
std::unique_ptr<Content> content;
|
||||||
|
std::function<void()> postContent;
|
||||||
|
std::vector<std::string> basePacks;
|
||||||
|
std::unique_ptr<PacksManager> manager;
|
||||||
|
std::vector<ContentPack> contentPacks;
|
||||||
|
};
|
||||||
@ -15,12 +15,13 @@ namespace fs = std::filesystem;
|
|||||||
|
|
||||||
ContentPack ContentPack::createCore(const EnginePaths& paths) {
|
ContentPack ContentPack::createCore(const EnginePaths& paths) {
|
||||||
return ContentPack {
|
return ContentPack {
|
||||||
"core", "Core", ENGINE_VERSION_STRING, "", "", "res:", "res:", {}
|
"core", "Core", ENGINE_VERSION_STRING, "", "", "res:", {}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<std::string> ContentPack::RESERVED_NAMES = {
|
const std::vector<std::string> ContentPack::RESERVED_NAMES = {
|
||||||
"res", "abs", "local", "core", "user", "world", "none", "null"};
|
"res", "abs", "local", "core", "user", "world", "none", "null"
|
||||||
|
};
|
||||||
|
|
||||||
contentpack_error::contentpack_error(
|
contentpack_error::contentpack_error(
|
||||||
std::string packId, io::path folder, const std::string& message
|
std::string packId, io::path folder, const std::string& message
|
||||||
@ -70,7 +71,7 @@ static void checkContentPackId(const std::string& id, const io::path& folder) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ContentPack ContentPack::read(const std::string& path, const io::path& folder) {
|
ContentPack ContentPack::read(const io::path& folder) {
|
||||||
auto root = io::read_json(folder / PACKAGE_FILENAME);
|
auto root = io::read_json(folder / PACKAGE_FILENAME);
|
||||||
ContentPack pack;
|
ContentPack pack;
|
||||||
root.at("id").get(pack.id);
|
root.at("id").get(pack.id);
|
||||||
@ -90,7 +91,6 @@ ContentPack ContentPack::read(const std::string& path, const io::path& folder) {
|
|||||||
root.at("description").get(pack.description);
|
root.at("description").get(pack.description);
|
||||||
root.at("source").get(pack.source);
|
root.at("source").get(pack.source);
|
||||||
pack.folder = folder;
|
pack.folder = folder;
|
||||||
pack.path = path;
|
|
||||||
|
|
||||||
if (auto found = root.at("dependencies")) {
|
if (auto found = root.at("dependencies")) {
|
||||||
const auto& dependencies = *found;
|
const auto& dependencies = *found;
|
||||||
@ -124,7 +124,7 @@ ContentPack ContentPack::read(const std::string& path, const io::path& folder) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ContentPack::scanFolder(
|
void ContentPack::scanFolder(
|
||||||
const std::string& path, const io::path& folder, std::vector<ContentPack>& packs
|
const io::path& folder, std::vector<ContentPack>& packs
|
||||||
) {
|
) {
|
||||||
if (!io::is_directory(folder)) {
|
if (!io::is_directory(folder)) {
|
||||||
return;
|
return;
|
||||||
@ -133,9 +133,7 @@ void ContentPack::scanFolder(
|
|||||||
if (!io::is_directory(packFolder)) continue;
|
if (!io::is_directory(packFolder)) continue;
|
||||||
if (!is_pack(packFolder)) continue;
|
if (!is_pack(packFolder)) continue;
|
||||||
try {
|
try {
|
||||||
packs.push_back(
|
packs.push_back(read(packFolder));
|
||||||
read(path + "/" + packFolder.name(), packFolder)
|
|
||||||
);
|
|
||||||
} catch (const contentpack_error& err) {
|
} catch (const contentpack_error& err) {
|
||||||
std::cerr << "package.json error at " << err.getFolder().string();
|
std::cerr << "package.json error at " << err.getFolder().string();
|
||||||
std::cerr << ": " << err.what() << std::endl;
|
std::cerr << ": " << err.what() << std::endl;
|
||||||
|
|||||||
@ -43,7 +43,6 @@ struct ContentPack {
|
|||||||
std::string creator = "";
|
std::string creator = "";
|
||||||
std::string description = "no description";
|
std::string description = "no description";
|
||||||
io::path folder;
|
io::path folder;
|
||||||
std::string path;
|
|
||||||
std::vector<DependencyPack> dependencies;
|
std::vector<DependencyPack> dependencies;
|
||||||
std::string source = "";
|
std::string source = "";
|
||||||
|
|
||||||
@ -58,14 +57,10 @@ struct ContentPack {
|
|||||||
static const std::vector<std::string> RESERVED_NAMES;
|
static const std::vector<std::string> RESERVED_NAMES;
|
||||||
|
|
||||||
static bool is_pack(const io::path& folder);
|
static bool is_pack(const io::path& folder);
|
||||||
static ContentPack read(
|
static ContentPack read(const io::path& folder);
|
||||||
const std::string& path, const io::path& folder
|
|
||||||
);
|
|
||||||
|
|
||||||
static void scanFolder(
|
static void scanFolder(
|
||||||
const std::string& path,
|
const io::path& folder, std::vector<ContentPack>& packs
|
||||||
const io::path& folder,
|
|
||||||
std::vector<ContentPack>& packs
|
|
||||||
);
|
);
|
||||||
|
|
||||||
static std::vector<std::string> worldPacksList(
|
static std::vector<std::string> worldPacksList(
|
||||||
|
|||||||
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
PacksManager::PacksManager() = default;
|
PacksManager::PacksManager() = default;
|
||||||
|
|
||||||
void PacksManager::setSources(std::vector<std::pair<std::string, io::path>> sources) {
|
void PacksManager::setSources(std::vector<io::path> sources) {
|
||||||
this->sources = std::move(sources);
|
this->sources = std::move(sources);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -15,8 +15,8 @@ void PacksManager::scan() {
|
|||||||
packs.clear();
|
packs.clear();
|
||||||
|
|
||||||
std::vector<ContentPack> packsList;
|
std::vector<ContentPack> packsList;
|
||||||
for (auto& [path, folder] : sources) {
|
for (auto& folder : sources) {
|
||||||
ContentPack::scanFolder(path, folder, packsList);
|
ContentPack::scanFolder(folder, packsList);
|
||||||
for (auto& pack : packsList) {
|
for (auto& pack : packsList) {
|
||||||
packs.try_emplace(pack.id, pack);
|
packs.try_emplace(pack.id, pack);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,12 +8,12 @@
|
|||||||
|
|
||||||
class PacksManager {
|
class PacksManager {
|
||||||
std::unordered_map<std::string, ContentPack> packs;
|
std::unordered_map<std::string, ContentPack> packs;
|
||||||
std::vector<std::pair<std::string, io::path>> sources;
|
std::vector<io::path> sources;
|
||||||
public:
|
public:
|
||||||
PacksManager();
|
PacksManager();
|
||||||
|
|
||||||
/// @brief Set content packs sources (search folders)
|
/// @brief Set content packs sources (search folders)
|
||||||
void setSources(std::vector<std::pair<std::string, io::path>> sources);
|
void setSources(std::vector<io::path> sources);
|
||||||
|
|
||||||
/// @brief Scan sources and collect all found packs excluding duplication.
|
/// @brief Scan sources and collect all found packs excluding duplication.
|
||||||
/// Scanning order depends on sources order
|
/// Scanning order depends on sources order
|
||||||
|
|||||||
@ -5,13 +5,12 @@
|
|||||||
#include "content/ContentBuilder.hpp"
|
#include "content/ContentBuilder.hpp"
|
||||||
#include "io/io.hpp"
|
#include "io/io.hpp"
|
||||||
#include "io/engine_paths.hpp"
|
#include "io/engine_paths.hpp"
|
||||||
#include "window/Window.hpp"
|
|
||||||
#include "window/Events.hpp"
|
|
||||||
#include "window/input.hpp"
|
#include "window/input.hpp"
|
||||||
#include "voxels/Block.hpp"
|
#include "voxels/Block.hpp"
|
||||||
|
#include "coders/toml.hpp"
|
||||||
|
|
||||||
// All in-game definitions (blocks, items, etc..)
|
// All in-game definitions (blocks, items, etc..)
|
||||||
void corecontent::setup(ContentBuilder& builder) {
|
void corecontent::setup(Input& input, ContentBuilder& builder) {
|
||||||
{
|
{
|
||||||
Block& block = builder.blocks.create(CORE_AIR);
|
Block& block = builder.blocks.create(CORE_AIR);
|
||||||
block.replaceable = true;
|
block.replaceable = true;
|
||||||
@ -30,8 +29,8 @@ void corecontent::setup(ContentBuilder& builder) {
|
|||||||
|
|
||||||
auto bindsFile = "res:bindings.toml";
|
auto bindsFile = "res:bindings.toml";
|
||||||
if (io::is_regular_file(bindsFile)) {
|
if (io::is_regular_file(bindsFile)) {
|
||||||
Events::loadBindings(
|
input.getBindings().read(
|
||||||
bindsFile, io::read_string(bindsFile), BindType::BIND
|
toml::parse(bindsFile, io::read_string(bindsFile)), BindType::BIND
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -28,8 +28,9 @@ inline const std::string BIND_PLAYER_FAST_INTERACTOIN =
|
|||||||
"player.fast_interaction";
|
"player.fast_interaction";
|
||||||
inline const std::string BIND_HUD_INVENTORY = "hud.inventory";
|
inline const std::string BIND_HUD_INVENTORY = "hud.inventory";
|
||||||
|
|
||||||
|
class Input;
|
||||||
class ContentBuilder;
|
class ContentBuilder;
|
||||||
|
|
||||||
namespace corecontent {
|
namespace corecontent {
|
||||||
void setup(ContentBuilder& builder);
|
void setup(Input& input, ContentBuilder& builder);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,6 +6,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include "data/dv.hpp"
|
||||||
#include "util/data_io.hpp"
|
#include "util/data_io.hpp"
|
||||||
#include "util/stringutil.hpp"
|
#include "util/stringutil.hpp"
|
||||||
|
|
||||||
|
|||||||
6
src/data/dv_fwd.hpp
Normal file
6
src/data/dv_fwd.hpp
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace dv {
|
||||||
|
class value;
|
||||||
|
struct optionalvalue;
|
||||||
|
}
|
||||||
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#include "delegates.hpp"
|
#include "delegates.hpp"
|
||||||
#include "typedefs.hpp"
|
#include "typedefs.hpp"
|
||||||
|
#include "util/observer_handler.hpp"
|
||||||
|
|
||||||
enum class setting_format { simple, percent };
|
enum class setting_format { simple, percent };
|
||||||
|
|
||||||
@ -41,15 +42,14 @@ public:
|
|||||||
: Setting(format), initial(value), value(value) {
|
: Setting(format), initial(value), value(value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
observer_handler observe(consumer<T> callback, bool callOnStart = false) {
|
ObserverHandler observe(consumer<T> callback, bool callOnStart = false) {
|
||||||
const int id = nextid++;
|
const int id = nextid++;
|
||||||
observers.emplace(id, callback);
|
observers.emplace(id, callback);
|
||||||
if (callOnStart) {
|
if (callOnStart) {
|
||||||
callback(value);
|
callback(value);
|
||||||
}
|
}
|
||||||
return std::shared_ptr<int>(new int(id), [this](int* id) { //-V508
|
return ObserverHandler([this, id]() {
|
||||||
observers.erase(*id);
|
observers.erase(id);
|
||||||
delete id;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -12,9 +12,7 @@
|
|||||||
#include "coders/json.hpp"
|
#include "coders/json.hpp"
|
||||||
#include "coders/toml.hpp"
|
#include "coders/toml.hpp"
|
||||||
#include "coders/commons.hpp"
|
#include "coders/commons.hpp"
|
||||||
#include "content/Content.hpp"
|
#include "content/ContentControl.hpp"
|
||||||
#include "content/ContentBuilder.hpp"
|
|
||||||
#include "content/ContentLoader.hpp"
|
|
||||||
#include "core_defs.hpp"
|
#include "core_defs.hpp"
|
||||||
#include "io/io.hpp"
|
#include "io/io.hpp"
|
||||||
#include "frontend/locale.hpp"
|
#include "frontend/locale.hpp"
|
||||||
@ -31,10 +29,8 @@
|
|||||||
#include "logic/scripting/scripting.hpp"
|
#include "logic/scripting/scripting.hpp"
|
||||||
#include "logic/scripting/scripting_hud.hpp"
|
#include "logic/scripting/scripting_hud.hpp"
|
||||||
#include "network/Network.hpp"
|
#include "network/Network.hpp"
|
||||||
#include "util/listutil.hpp"
|
|
||||||
#include "util/platform.hpp"
|
#include "util/platform.hpp"
|
||||||
#include "window/Camera.hpp"
|
#include "window/Camera.hpp"
|
||||||
#include "window/Events.hpp"
|
|
||||||
#include "window/input.hpp"
|
#include "window/input.hpp"
|
||||||
#include "window/Window.hpp"
|
#include "window/Window.hpp"
|
||||||
#include "world/Level.hpp"
|
#include "world/Level.hpp"
|
||||||
@ -50,8 +46,6 @@
|
|||||||
|
|
||||||
static debug::Logger logger("engine");
|
static debug::Logger logger("engine");
|
||||||
|
|
||||||
namespace fs = std::filesystem;
|
|
||||||
|
|
||||||
static std::unique_ptr<ImageData> load_icon() {
|
static std::unique_ptr<ImageData> load_icon() {
|
||||||
try {
|
try {
|
||||||
auto file = "res:textures/misc/icon.png";
|
auto file = "res:textures/misc/icon.png";
|
||||||
@ -65,20 +59,21 @@ static std::unique_ptr<ImageData> load_icon() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Engine::Engine() = default;
|
Engine::Engine() = default;
|
||||||
|
Engine::~Engine() = default;
|
||||||
|
|
||||||
static std::unique_ptr<Engine> engine;
|
static std::unique_ptr<Engine> instance = nullptr;
|
||||||
|
|
||||||
Engine& Engine::getInstance() {
|
Engine& Engine::getInstance() {
|
||||||
if (!engine) {
|
if (!instance) {
|
||||||
engine = std::make_unique<Engine>();
|
instance = std::make_unique<Engine>();
|
||||||
}
|
}
|
||||||
return *engine;
|
return *instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Engine::initialize(CoreParameters coreParameters) {
|
void Engine::initialize(CoreParameters coreParameters) {
|
||||||
params = std::move(coreParameters);
|
params = std::move(coreParameters);
|
||||||
settingsHandler = std::make_unique<SettingsHandler>(settings);
|
settingsHandler = std::make_unique<SettingsHandler>(settings);
|
||||||
interpreter = std::make_unique<cmd::CommandsInterpreter>();
|
cmd = std::make_unique<cmd::CommandsInterpreter>();
|
||||||
network = network::Network::create(settings.network);
|
network = network::Network::create(settings.network);
|
||||||
|
|
||||||
logger.info() << "engine version: " << ENGINE_VERSION_STRING;
|
logger.info() << "engine version: " << ENGINE_VERSION_STRING;
|
||||||
@ -93,46 +88,80 @@ void Engine::initialize(CoreParameters coreParameters) {
|
|||||||
}
|
}
|
||||||
loadSettings();
|
loadSettings();
|
||||||
|
|
||||||
auto resdir = paths.getResourcesFolder();
|
|
||||||
|
|
||||||
controller = std::make_unique<EngineController>(*this);
|
controller = std::make_unique<EngineController>(*this);
|
||||||
if (!params.headless) {
|
if (!params.headless) {
|
||||||
if (Window::initialize(&settings.display)){
|
std::string title = "VoxelCore v" +
|
||||||
|
std::to_string(ENGINE_VERSION_MAJOR) + "." +
|
||||||
|
std::to_string(ENGINE_VERSION_MINOR);
|
||||||
|
if (ENGINE_DEBUG_BUILD) {
|
||||||
|
title += " [debug]";
|
||||||
|
}
|
||||||
|
auto [window, input] = Window::initialize(&settings.display, title);
|
||||||
|
if (!window || !input){
|
||||||
throw initialize_error("could not initialize window");
|
throw initialize_error("could not initialize window");
|
||||||
}
|
}
|
||||||
time.set(Window::time());
|
window->setFramerate(settings.display.framerate.get());
|
||||||
|
|
||||||
|
time.set(window->time());
|
||||||
if (auto icon = load_icon()) {
|
if (auto icon = load_icon()) {
|
||||||
icon->flipY();
|
icon->flipY();
|
||||||
Window::setIcon(icon.get());
|
window->setIcon(icon.get());
|
||||||
}
|
}
|
||||||
|
this->window = std::move(window);
|
||||||
|
this->input = std::move(input);
|
||||||
|
|
||||||
loadControls();
|
loadControls();
|
||||||
|
|
||||||
gui = std::make_unique<gui::GUI>();
|
gui = std::make_unique<gui::GUI>(*this);
|
||||||
if (ENGINE_DEBUG_BUILD) {
|
if (ENGINE_DEBUG_BUILD) {
|
||||||
menus::create_version_label(*this);
|
menus::create_version_label(*gui);
|
||||||
}
|
}
|
||||||
|
keepAlive(settings.display.fullscreen.observe(
|
||||||
|
[this](bool value) {
|
||||||
|
if (value != this->window->isFullscreen()) {
|
||||||
|
this->window->toggleFullscreen();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
true
|
||||||
|
));
|
||||||
}
|
}
|
||||||
audio::initialize(!params.headless, settings.audio);
|
audio::initialize(!params.headless, settings.audio);
|
||||||
|
|
||||||
bool langNotSet = settings.ui.language.get() == "auto";
|
bool langNotSet = settings.ui.language.get() == "auto";
|
||||||
if (langNotSet) {
|
if (langNotSet) {
|
||||||
settings.ui.language.set(langs::locale_by_envlocale(
|
settings.ui.language.set(
|
||||||
platform::detect_locale(),
|
langs::locale_by_envlocale(platform::detect_locale())
|
||||||
"res:"
|
);
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
content = std::make_unique<ContentControl>(paths, *input, [this]() {
|
||||||
|
langs::setup(langs::get_current(), paths.resPaths.collectRoots());
|
||||||
|
if (!isHeadless()) {
|
||||||
|
for (auto& pack : content->getAllContentPacks()) {
|
||||||
|
auto configFolder = pack.folder / "config";
|
||||||
|
auto bindsFile = configFolder / "bindings.toml";
|
||||||
|
if (io::is_regular_file(bindsFile)) {
|
||||||
|
input->getBindings().read(
|
||||||
|
toml::parse(
|
||||||
|
bindsFile.string(), io::read_string(bindsFile)
|
||||||
|
),
|
||||||
|
BindType::BIND
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
loadAssets();
|
||||||
|
}
|
||||||
|
});
|
||||||
scripting::initialize(this);
|
scripting::initialize(this);
|
||||||
if (!isHeadless()) {
|
if (!isHeadless()) {
|
||||||
gui->setPageLoader(scripting::create_page_loader());
|
gui->setPageLoader(scripting::create_page_loader());
|
||||||
}
|
}
|
||||||
keepAlive(settings.ui.language.observe([this](auto lang) {
|
keepAlive(settings.ui.language.observe([this](auto lang) {
|
||||||
setLanguage(lang);
|
langs::setup(lang, paths.resPaths.collectRoots());
|
||||||
}, true));
|
}, true));
|
||||||
basePacks = io::read_list("res:config/builtins.list");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Engine::loadSettings() {
|
void Engine::loadSettings() {
|
||||||
io::path settings_file = paths.getSettingsFile();
|
io::path settings_file = EnginePaths::SETTINGS_FILE;
|
||||||
if (io::is_regular_file(settings_file)) {
|
if (io::is_regular_file(settings_file)) {
|
||||||
logger.info() << "loading settings";
|
logger.info() << "loading settings";
|
||||||
std::string text = io::read_string(settings_file);
|
std::string text = io::read_string(settings_file);
|
||||||
@ -146,33 +175,30 @@ void Engine::loadSettings() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Engine::loadControls() {
|
void Engine::loadControls() {
|
||||||
io::path controls_file = paths.getControlsFile();
|
io::path controls_file = EnginePaths::CONTROLS_FILE;
|
||||||
if (io::is_regular_file(controls_file)) {
|
if (io::is_regular_file(controls_file)) {
|
||||||
logger.info() << "loading controls";
|
logger.info() << "loading controls";
|
||||||
std::string text = io::read_string(controls_file);
|
std::string text = io::read_string(controls_file);
|
||||||
Events::loadBindings(controls_file.string(), text, BindType::BIND);
|
input->getBindings().read(
|
||||||
|
toml::parse(controls_file.string(), text), BindType::BIND
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Engine::onAssetsLoaded() {
|
|
||||||
assets->setup();
|
|
||||||
gui->onAssetsLoad(assets.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
void Engine::updateHotkeys() {
|
void Engine::updateHotkeys() {
|
||||||
if (Events::jpressed(keycode::F2)) {
|
if (input->jpressed(Keycode::F2)) {
|
||||||
saveScreenshot();
|
saveScreenshot();
|
||||||
}
|
}
|
||||||
if (Events::jpressed(keycode::F8)) {
|
if (input->jpressed(Keycode::F8)) {
|
||||||
gui->toggleDebug();
|
gui->toggleDebug();
|
||||||
}
|
}
|
||||||
if (Events::jpressed(keycode::F11)) {
|
if (input->jpressed(Keycode::F11)) {
|
||||||
settings.display.fullscreen.toggle();
|
settings.display.fullscreen.toggle();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Engine::saveScreenshot() {
|
void Engine::saveScreenshot() {
|
||||||
auto image = Window::takeScreenshot();
|
auto image = window->takeScreenshot();
|
||||||
image->flipY();
|
image->flipY();
|
||||||
io::path filename = paths.getNewScreenshotFile("png");
|
io::path filename = paths.getNewScreenshotFile("png");
|
||||||
imageio::write(filename.string(), image.get());
|
imageio::write(filename.string(), image.get());
|
||||||
@ -197,39 +223,38 @@ void Engine::updateFrontend() {
|
|||||||
double delta = time.getDelta();
|
double delta = time.getDelta();
|
||||||
updateHotkeys();
|
updateHotkeys();
|
||||||
audio::update(delta);
|
audio::update(delta);
|
||||||
gui->act(delta, Viewport(Window::width, Window::height));
|
gui->act(delta, window->getSize());
|
||||||
screen->update(delta);
|
screen->update(delta);
|
||||||
gui->postAct();
|
gui->postAct();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Engine::nextFrame() {
|
void Engine::nextFrame() {
|
||||||
Window::setFramerate(
|
window->setFramerate(
|
||||||
Window::isIconified() && settings.display.limitFpsIconified.get()
|
window->isIconified() && settings.display.limitFpsIconified.get()
|
||||||
? 20
|
? 20
|
||||||
: settings.display.framerate.get()
|
: settings.display.framerate.get()
|
||||||
);
|
);
|
||||||
Window::swapBuffers();
|
window->swapBuffers();
|
||||||
Events::pollEvents();
|
input->pollEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Engine::renderFrame() {
|
void Engine::renderFrame() {
|
||||||
screen->draw(time.getDelta());
|
screen->draw(time.getDelta());
|
||||||
|
|
||||||
Viewport viewport(Window::width, Window::height);
|
DrawContext ctx(nullptr, *window, nullptr);
|
||||||
DrawContext ctx(nullptr, viewport, nullptr);
|
|
||||||
gui->draw(ctx, *assets);
|
gui->draw(ctx, *assets);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Engine::saveSettings() {
|
void Engine::saveSettings() {
|
||||||
logger.info() << "saving settings";
|
logger.info() << "saving settings";
|
||||||
io::write_string(paths.getSettingsFile(), toml::stringify(*settingsHandler));
|
io::write_string(EnginePaths::SETTINGS_FILE, toml::stringify(*settingsHandler));
|
||||||
if (!params.headless) {
|
if (!params.headless) {
|
||||||
logger.info() << "saving bindings";
|
logger.info() << "saving bindings";
|
||||||
io::write_string(paths.getControlsFile(), Events::writeBindings());
|
io::write_string(EnginePaths::CONTROLS_FILE, input->getBindings().write());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Engine::~Engine() {
|
void Engine::close() {
|
||||||
saveSettings();
|
saveSettings();
|
||||||
logger.info() << "shutting down";
|
logger.info() << "shutting down";
|
||||||
if (screen) {
|
if (screen) {
|
||||||
@ -238,7 +263,7 @@ Engine::~Engine() {
|
|||||||
}
|
}
|
||||||
content.reset();
|
content.reset();
|
||||||
assets.reset();
|
assets.reset();
|
||||||
interpreter.reset();
|
cmd.reset();
|
||||||
if (gui) {
|
if (gui) {
|
||||||
gui.reset();
|
gui.reset();
|
||||||
logger.info() << "gui finished";
|
logger.info() << "gui finished";
|
||||||
@ -249,45 +274,34 @@ Engine::~Engine() {
|
|||||||
scripting::close();
|
scripting::close();
|
||||||
logger.info() << "scripting finished";
|
logger.info() << "scripting finished";
|
||||||
if (!params.headless) {
|
if (!params.headless) {
|
||||||
Window::terminate();
|
window.reset();
|
||||||
logger.info() << "window closed";
|
logger.info() << "window closed";
|
||||||
}
|
}
|
||||||
logger.info() << "engine finished";
|
logger.info() << "engine finished";
|
||||||
}
|
}
|
||||||
|
|
||||||
void Engine::terminate() {
|
void Engine::terminate() {
|
||||||
engine.reset();
|
instance->close();
|
||||||
|
instance.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
EngineController* Engine::getController() {
|
EngineController* Engine::getController() {
|
||||||
return controller.get();
|
return controller.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd::CommandsInterpreter* Engine::getCommandsInterpreter() {
|
|
||||||
return interpreter.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
PacksManager Engine::createPacksManager(const io::path& worldFolder) {
|
|
||||||
PacksManager manager;
|
|
||||||
manager.setSources({
|
|
||||||
{"world:content", worldFolder.empty() ? worldFolder : worldFolder / "content"},
|
|
||||||
{"user:content", "user:content"},
|
|
||||||
{"res:content", "res:content"}
|
|
||||||
});
|
|
||||||
return manager;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Engine::setLevelConsumer(OnWorldOpen levelConsumer) {
|
void Engine::setLevelConsumer(OnWorldOpen levelConsumer) {
|
||||||
this->levelConsumer = std::move(levelConsumer);
|
this->levelConsumer = std::move(levelConsumer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Engine::loadAssets() {
|
void Engine::loadAssets() {
|
||||||
logger.info() << "loading assets";
|
logger.info() << "loading assets";
|
||||||
Shader::preprocessor->setPaths(resPaths.get());
|
Shader::preprocessor->setPaths(&paths.resPaths);
|
||||||
|
|
||||||
|
auto content = this->content->get();
|
||||||
|
|
||||||
auto new_assets = std::make_unique<Assets>();
|
auto new_assets = std::make_unique<Assets>();
|
||||||
AssetsLoader loader(new_assets.get(), resPaths.get());
|
AssetsLoader loader(*this, *new_assets, paths.resPaths);
|
||||||
AssetsLoader::addDefaults(loader, content.get());
|
AssetsLoader::addDefaults(loader, content);
|
||||||
|
|
||||||
// no need
|
// no need
|
||||||
// correct log messages order is more useful
|
// correct log messages order is more useful
|
||||||
@ -301,139 +315,11 @@ void Engine::loadAssets() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
assets = std::move(new_assets);
|
assets = std::move(new_assets);
|
||||||
|
if (content) {
|
||||||
if (content == nullptr) {
|
ModelsGenerator::prepare(*content, *assets);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
for (auto& [name, def] : content->blocks.getDefs()) {
|
assets->setup();
|
||||||
if (def->model == BlockModel::custom && def->modelName.empty()) {
|
gui->onAssetsLoad(assets.get());
|
||||||
assets->store(
|
|
||||||
std::make_unique<model::Model>(
|
|
||||||
ModelsGenerator::loadCustomBlockModel(
|
|
||||||
def->customModelRaw, *assets, !def->shadeless
|
|
||||||
)
|
|
||||||
),
|
|
||||||
name + ".model"
|
|
||||||
);
|
|
||||||
def->modelName = def->name + ".model";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (auto& [name, def] : content->items.getDefs()) {
|
|
||||||
assets->store(
|
|
||||||
std::make_unique<model::Model>(
|
|
||||||
ModelsGenerator::generate(*def, *content, *assets)
|
|
||||||
),
|
|
||||||
name + ".model"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void load_configs(const io::path& root) {
|
|
||||||
auto configFolder = root / "config";
|
|
||||||
auto bindsFile = configFolder / "bindings.toml";
|
|
||||||
if (io::is_regular_file(bindsFile)) {
|
|
||||||
Events::loadBindings(
|
|
||||||
bindsFile.string(), io::read_string(bindsFile), BindType::BIND
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Engine::loadContent() {
|
|
||||||
scripting::cleanup();
|
|
||||||
|
|
||||||
std::vector<std::string> names;
|
|
||||||
for (auto& pack : contentPacks) {
|
|
||||||
names.push_back(pack.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
ContentBuilder contentBuilder;
|
|
||||||
corecontent::setup(contentBuilder);
|
|
||||||
|
|
||||||
paths.setContentPacks(&contentPacks);
|
|
||||||
PacksManager manager = createPacksManager(paths.getCurrentWorldFolder());
|
|
||||||
manager.scan();
|
|
||||||
names = manager.assemble(names);
|
|
||||||
contentPacks = manager.getAll(names);
|
|
||||||
|
|
||||||
auto corePack = ContentPack::createCore(paths);
|
|
||||||
|
|
||||||
// Setup filesystem entry points
|
|
||||||
std::vector<PathsRoot> resRoots {
|
|
||||||
{"core", corePack.folder}
|
|
||||||
};
|
|
||||||
for (auto& pack : contentPacks) {
|
|
||||||
resRoots.push_back({pack.id, pack.folder});
|
|
||||||
}
|
|
||||||
resPaths = std::make_unique<ResPaths>("res:", resRoots);
|
|
||||||
|
|
||||||
// Load content
|
|
||||||
{
|
|
||||||
ContentLoader(&corePack, contentBuilder, *resPaths).load();
|
|
||||||
load_configs(corePack.folder);
|
|
||||||
}
|
|
||||||
for (auto& pack : contentPacks) {
|
|
||||||
ContentLoader(&pack, contentBuilder, *resPaths).load();
|
|
||||||
load_configs(pack.folder);
|
|
||||||
}
|
|
||||||
content = contentBuilder.build();
|
|
||||||
interpreter->reset();
|
|
||||||
scripting::on_content_load(content.get());
|
|
||||||
|
|
||||||
ContentLoader::loadScripts(*content);
|
|
||||||
|
|
||||||
langs::setup("res:", langs::current->getId(), contentPacks);
|
|
||||||
if (!isHeadless()) {
|
|
||||||
loadAssets();
|
|
||||||
onAssetsLoaded();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Engine::resetContent() {
|
|
||||||
scripting::cleanup();
|
|
||||||
std::vector<PathsRoot> resRoots;
|
|
||||||
{
|
|
||||||
auto pack = ContentPack::createCore(paths);
|
|
||||||
resRoots.push_back({"core", pack.folder});
|
|
||||||
load_configs(pack.folder);
|
|
||||||
}
|
|
||||||
auto manager = createPacksManager(io::path());
|
|
||||||
manager.scan();
|
|
||||||
for (const auto& pack : manager.getAll(basePacks)) {
|
|
||||||
resRoots.push_back({pack.id, pack.folder});
|
|
||||||
}
|
|
||||||
resPaths = std::make_unique<ResPaths>("res:", resRoots);
|
|
||||||
contentPacks.clear();
|
|
||||||
content.reset();
|
|
||||||
|
|
||||||
langs::setup("res:", langs::current->getId(), contentPacks);
|
|
||||||
if (!isHeadless()) {
|
|
||||||
loadAssets();
|
|
||||||
onAssetsLoaded();
|
|
||||||
}
|
|
||||||
|
|
||||||
contentPacks = manager.getAll(basePacks);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Engine::loadWorldContent(const io::path& folder) {
|
|
||||||
contentPacks.clear();
|
|
||||||
auto packNames = ContentPack::worldPacksList(folder);
|
|
||||||
PacksManager manager;
|
|
||||||
manager.setSources(
|
|
||||||
{{"world:content", folder.empty() ? folder : folder / "content"},
|
|
||||||
{"user:content", "user:content"},
|
|
||||||
{"res:content", "res:content"}}
|
|
||||||
);
|
|
||||||
manager.scan();
|
|
||||||
contentPacks = manager.getAll(manager.assemble(packNames));
|
|
||||||
paths.setCurrentWorldFolder(folder);
|
|
||||||
loadContent();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Engine::loadAllPacks() {
|
|
||||||
PacksManager manager = createPacksManager(paths.getCurrentWorldFolder());
|
|
||||||
manager.scan();
|
|
||||||
auto allnames = manager.getAllNames();
|
|
||||||
contentPacks = manager.getAll(manager.assemble(allnames));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Engine::setScreen(std::shared_ptr<Screen> screen) {
|
void Engine::setScreen(std::shared_ptr<Screen> screen) {
|
||||||
@ -443,10 +329,6 @@ void Engine::setScreen(std::shared_ptr<Screen> screen) {
|
|||||||
this->screen = std::move(screen);
|
this->screen = std::move(screen);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Engine::setLanguage(std::string locale) {
|
|
||||||
langs::setup("res:", std::move(locale), contentPacks);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Engine::onWorldOpen(std::unique_ptr<Level> level, int64_t localPlayer) {
|
void Engine::onWorldOpen(std::unique_ptr<Level> level, int64_t localPlayer) {
|
||||||
logger.info() << "world open";
|
logger.info() << "world open";
|
||||||
levelConsumer(std::move(level), localPlayer);
|
levelConsumer(std::move(level), localPlayer);
|
||||||
@ -460,7 +342,7 @@ void Engine::onWorldClosed() {
|
|||||||
void Engine::quit() {
|
void Engine::quit() {
|
||||||
quitSignal = true;
|
quitSignal = true;
|
||||||
if (!isHeadless()) {
|
if (!isHeadless()) {
|
||||||
Window::setShouldClose(true);
|
window->setShouldClose(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -468,10 +350,6 @@ bool Engine::isQuitSignal() const {
|
|||||||
return quitSignal;
|
return quitSignal;
|
||||||
}
|
}
|
||||||
|
|
||||||
gui::GUI* Engine::getGUI() {
|
|
||||||
return gui.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
EngineSettings& Engine::getSettings() {
|
EngineSettings& Engine::getSettings() {
|
||||||
return settings;
|
return settings;
|
||||||
}
|
}
|
||||||
@ -480,34 +358,12 @@ Assets* Engine::getAssets() {
|
|||||||
return assets.get();
|
return assets.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
const Content* Engine::getContent() const {
|
|
||||||
return content.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
Content* Engine::getWriteableContent() {
|
|
||||||
return content.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<ContentPack> Engine::getAllContentPacks() {
|
|
||||||
auto packs = getContentPacks();
|
|
||||||
packs.insert(packs.begin(), ContentPack::createCore(paths));
|
|
||||||
return packs;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<ContentPack>& Engine::getContentPacks() {
|
|
||||||
return contentPacks;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::string>& Engine::getBasePacks() {
|
|
||||||
return basePacks;
|
|
||||||
}
|
|
||||||
|
|
||||||
EnginePaths& Engine::getPaths() {
|
EnginePaths& Engine::getPaths() {
|
||||||
return paths;
|
return paths;
|
||||||
}
|
}
|
||||||
|
|
||||||
ResPaths* Engine::getResPaths() {
|
ResPaths& Engine::getResPaths() {
|
||||||
return resPaths.get();
|
return paths.resPaths;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Screen> Engine::getScreen() {
|
std::shared_ptr<Screen> Engine::getScreen() {
|
||||||
@ -518,10 +374,6 @@ SettingsHandler& Engine::getSettingsHandler() {
|
|||||||
return *settingsHandler;
|
return *settingsHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
network::Network& Engine::getNetwork() {
|
|
||||||
return *network;
|
|
||||||
}
|
|
||||||
|
|
||||||
Time& Engine::getTime() {
|
Time& Engine::getTime() {
|
||||||
return time;
|
return time;
|
||||||
}
|
}
|
||||||
@ -533,3 +385,7 @@ const CoreParameters& Engine::getCoreParameters() const {
|
|||||||
bool Engine::isHeadless() const {
|
bool Engine::isHeadless() const {
|
||||||
return params.headless;
|
return params.headless;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ContentControl& Engine::getContentControl() {
|
||||||
|
return *content;
|
||||||
|
}
|
||||||
|
|||||||
@ -4,10 +4,6 @@
|
|||||||
#include "typedefs.hpp"
|
#include "typedefs.hpp"
|
||||||
#include "settings.hpp"
|
#include "settings.hpp"
|
||||||
|
|
||||||
#include "assets/Assets.hpp"
|
|
||||||
#include "content/content_fwd.hpp"
|
|
||||||
#include "content/ContentPack.hpp"
|
|
||||||
#include "content/PacksManager.hpp"
|
|
||||||
#include "io/engine_paths.hpp"
|
#include "io/engine_paths.hpp"
|
||||||
#include "io/settings_io.hpp"
|
#include "io/settings_io.hpp"
|
||||||
#include "util/ObjectsKeeper.hpp"
|
#include "util/ObjectsKeeper.hpp"
|
||||||
@ -15,17 +11,15 @@
|
|||||||
#include "Time.hpp"
|
#include "Time.hpp"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <stdexcept>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
|
class Window;
|
||||||
|
class Assets;
|
||||||
class Level;
|
class Level;
|
||||||
class Screen;
|
class Screen;
|
||||||
class EnginePaths;
|
class ContentControl;
|
||||||
class ResPaths;
|
|
||||||
class EngineController;
|
class EngineController;
|
||||||
class SettingsHandler;
|
class Input;
|
||||||
struct EngineSettings;
|
|
||||||
|
|
||||||
namespace gui {
|
namespace gui {
|
||||||
class GUI;
|
class GUI;
|
||||||
@ -62,13 +56,12 @@ class Engine : public util::ObjectsKeeper {
|
|||||||
std::unique_ptr<SettingsHandler> settingsHandler;
|
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::unique_ptr<ContentControl> content;
|
||||||
std::unique_ptr<Content> content;
|
|
||||||
std::unique_ptr<ResPaths> resPaths;
|
|
||||||
std::unique_ptr<EngineController> controller;
|
std::unique_ptr<EngineController> controller;
|
||||||
std::unique_ptr<cmd::CommandsInterpreter> interpreter;
|
std::unique_ptr<cmd::CommandsInterpreter> cmd;
|
||||||
std::unique_ptr<network::Network> network;
|
std::unique_ptr<network::Network> network;
|
||||||
std::vector<std::string> basePacks;
|
std::unique_ptr<Window> window;
|
||||||
|
std::unique_ptr<Input> input;
|
||||||
std::unique_ptr<gui::GUI> gui;
|
std::unique_ptr<gui::GUI> gui;
|
||||||
PostRunnables postRunnables;
|
PostRunnables postRunnables;
|
||||||
Time time;
|
Time time;
|
||||||
@ -87,6 +80,7 @@ public:
|
|||||||
static Engine& getInstance();
|
static Engine& getInstance();
|
||||||
|
|
||||||
void initialize(CoreParameters coreParameters);
|
void initialize(CoreParameters coreParameters);
|
||||||
|
void close();
|
||||||
|
|
||||||
static void terminate();
|
static void terminate();
|
||||||
|
|
||||||
@ -99,39 +93,15 @@ public:
|
|||||||
void renderFrame();
|
void renderFrame();
|
||||||
void nextFrame();
|
void nextFrame();
|
||||||
|
|
||||||
/// @brief Called after assets loading when all engine systems are initialized
|
|
||||||
void onAssetsLoaded();
|
|
||||||
|
|
||||||
/// @brief Set screen (scene).
|
/// @brief Set screen (scene).
|
||||||
/// nullptr may be used to delete previous screen before creating new one,
|
/// nullptr may be used to delete previous screen before creating new one,
|
||||||
/// not-null value must be set before next frame
|
/// not-null value must be set before next frame
|
||||||
/// @param screen nullable screen
|
/// @param screen nullable screen
|
||||||
void setScreen(std::shared_ptr<Screen> screen);
|
void setScreen(std::shared_ptr<Screen> screen);
|
||||||
|
|
||||||
/// @brief Change locale to specified
|
|
||||||
/// @param locale isolanguage_ISOCOUNTRY (example: en_US)
|
|
||||||
void setLanguage(std::string locale);
|
|
||||||
|
|
||||||
/// @brief Load all selected content-packs and reload assets
|
|
||||||
void loadContent();
|
|
||||||
|
|
||||||
/// @brief Reset content to base packs list
|
|
||||||
void resetContent();
|
|
||||||
|
|
||||||
/// @brief Collect world content-packs and load content
|
|
||||||
/// @see loadContent
|
|
||||||
/// @param folder world folder
|
|
||||||
void loadWorldContent(const io::path& folder);
|
|
||||||
|
|
||||||
/// @brief Collect all available content-packs from res/content
|
|
||||||
void loadAllPacks();
|
|
||||||
|
|
||||||
/// @brief Get active assets storage instance
|
/// @brief Get active assets storage instance
|
||||||
Assets* getAssets();
|
Assets* getAssets();
|
||||||
|
|
||||||
/// @brief Get main UI controller
|
|
||||||
gui::GUI* getGUI();
|
|
||||||
|
|
||||||
/// @brief Get writeable engine settings structure instance
|
/// @brief Get writeable engine settings structure instance
|
||||||
EngineSettings& getSettings();
|
EngineSettings& getSettings();
|
||||||
|
|
||||||
@ -139,7 +109,7 @@ public:
|
|||||||
EnginePaths& getPaths();
|
EnginePaths& getPaths();
|
||||||
|
|
||||||
/// @brief Get engine resource paths controller
|
/// @brief Get engine resource paths controller
|
||||||
ResPaths* getResPaths();
|
ResPaths& getResPaths();
|
||||||
|
|
||||||
void onWorldOpen(std::unique_ptr<Level> level, int64_t localPlayer);
|
void onWorldOpen(std::unique_ptr<Level> level, int64_t localPlayer);
|
||||||
void onWorldClosed();
|
void onWorldClosed();
|
||||||
@ -148,18 +118,6 @@ public:
|
|||||||
|
|
||||||
bool isQuitSignal() const;
|
bool isQuitSignal() const;
|
||||||
|
|
||||||
/// @brief Get current Content instance
|
|
||||||
const Content* getContent() const;
|
|
||||||
|
|
||||||
Content* getWriteableContent();
|
|
||||||
|
|
||||||
/// @brief Get selected content packs
|
|
||||||
std::vector<ContentPack>& getContentPacks();
|
|
||||||
|
|
||||||
std::vector<ContentPack> getAllContentPacks();
|
|
||||||
|
|
||||||
std::vector<std::string>& getBasePacks();
|
|
||||||
|
|
||||||
/// @brief Get current screen
|
/// @brief Get current screen
|
||||||
std::shared_ptr<Screen> getScreen();
|
std::shared_ptr<Screen> getScreen();
|
||||||
|
|
||||||
@ -171,19 +129,36 @@ public:
|
|||||||
void saveScreenshot();
|
void saveScreenshot();
|
||||||
|
|
||||||
EngineController* getController();
|
EngineController* getController();
|
||||||
cmd::CommandsInterpreter* getCommandsInterpreter();
|
|
||||||
|
|
||||||
PacksManager createPacksManager(const io::path& worldFolder);
|
|
||||||
|
|
||||||
void setLevelConsumer(OnWorldOpen levelConsumer);
|
void setLevelConsumer(OnWorldOpen levelConsumer);
|
||||||
|
|
||||||
SettingsHandler& getSettingsHandler();
|
SettingsHandler& getSettingsHandler();
|
||||||
|
|
||||||
network::Network& getNetwork();
|
|
||||||
|
|
||||||
Time& getTime();
|
Time& getTime();
|
||||||
|
|
||||||
const CoreParameters& getCoreParameters() const;
|
const CoreParameters& getCoreParameters() const;
|
||||||
|
|
||||||
bool isHeadless() const;
|
bool isHeadless() const;
|
||||||
|
|
||||||
|
ContentControl& getContentControl();
|
||||||
|
|
||||||
|
gui::GUI& getGUI() {
|
||||||
|
return *gui;
|
||||||
|
}
|
||||||
|
|
||||||
|
Input& getInput() {
|
||||||
|
return *input;
|
||||||
|
}
|
||||||
|
|
||||||
|
Window& getWindow() {
|
||||||
|
return *window;
|
||||||
|
}
|
||||||
|
|
||||||
|
network::Network& getNetwork() {
|
||||||
|
return *network;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd::CommandsInterpreter& getCmd() {
|
||||||
|
return *cmd;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -14,6 +14,7 @@ Mainloop::Mainloop(Engine& engine) : engine(engine) {
|
|||||||
|
|
||||||
void Mainloop::run() {
|
void Mainloop::run() {
|
||||||
auto& time = engine.getTime();
|
auto& time = engine.getTime();
|
||||||
|
auto& window = engine.getWindow();
|
||||||
|
|
||||||
engine.setLevelConsumer([this](auto level, int64_t localPlayer) {
|
engine.setLevelConsumer([this](auto level, int64_t localPlayer) {
|
||||||
if (level == nullptr) {
|
if (level == nullptr) {
|
||||||
@ -32,10 +33,10 @@ void Mainloop::run() {
|
|||||||
engine.setScreen(std::make_shared<MenuScreen>(engine));
|
engine.setScreen(std::make_shared<MenuScreen>(engine));
|
||||||
|
|
||||||
logger.info() << "main loop started";
|
logger.info() << "main loop started";
|
||||||
while (!Window::isShouldClose()){
|
while (!window.isShouldClose()){
|
||||||
time.update(Window::time());
|
time.update(window.time());
|
||||||
engine.updateFrontend();
|
engine.updateFrontend();
|
||||||
if (!Window::isIconified()) {
|
if (!window.isIconified()) {
|
||||||
engine.renderFrame();
|
engine.renderFrame();
|
||||||
}
|
}
|
||||||
engine.postUpdate();
|
engine.postUpdate();
|
||||||
|
|||||||
@ -69,10 +69,6 @@ void ContentGfxCache::refresh() {
|
|||||||
|
|
||||||
ContentGfxCache::~ContentGfxCache() = default;
|
ContentGfxCache::~ContentGfxCache() = default;
|
||||||
|
|
||||||
const Content* ContentGfxCache::getContent() const {
|
|
||||||
return &content;
|
|
||||||
}
|
|
||||||
|
|
||||||
const model::Model& ContentGfxCache::getModel(blockid_t id) const {
|
const model::Model& ContentGfxCache::getModel(blockid_t id) const {
|
||||||
const auto& found = models.find(id);
|
const auto& found = models.find(id);
|
||||||
if (found == models.end()) {
|
if (found == models.end()) {
|
||||||
|
|||||||
@ -6,6 +6,7 @@
|
|||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
|
#include "maths/UVRegion.hpp"
|
||||||
#include "graphics/commons/Model.hpp"
|
#include "graphics/commons/Model.hpp"
|
||||||
|
|
||||||
class Content;
|
class Content;
|
||||||
@ -15,10 +16,6 @@ class Block;
|
|||||||
struct UVRegion;
|
struct UVRegion;
|
||||||
struct GraphicsSettings;
|
struct GraphicsSettings;
|
||||||
|
|
||||||
namespace model {
|
|
||||||
struct Model;
|
|
||||||
}
|
|
||||||
|
|
||||||
class ContentGfxCache {
|
class ContentGfxCache {
|
||||||
const Content& content;
|
const Content& content;
|
||||||
const Assets& assets;
|
const Assets& assets;
|
||||||
@ -41,8 +38,6 @@ public:
|
|||||||
|
|
||||||
const model::Model& getModel(blockid_t id) const;
|
const model::Model& getModel(blockid_t id) const;
|
||||||
|
|
||||||
const Content* getContent() const;
|
|
||||||
|
|
||||||
void refresh(const Block& block, const Atlas& atlas);
|
void refresh(const Block& block, const Atlas& atlas);
|
||||||
|
|
||||||
void refresh();
|
void refresh();
|
||||||
|
|||||||
@ -12,27 +12,33 @@
|
|||||||
#include "objects/Player.hpp"
|
#include "objects/Player.hpp"
|
||||||
#include "voxels/Block.hpp"
|
#include "voxels/Block.hpp"
|
||||||
#include "world/Level.hpp"
|
#include "world/Level.hpp"
|
||||||
|
#include "engine/Engine.hpp"
|
||||||
|
|
||||||
LevelFrontend::LevelFrontend(
|
LevelFrontend::LevelFrontend(
|
||||||
|
Engine& engine,
|
||||||
Player* currentPlayer,
|
Player* currentPlayer,
|
||||||
LevelController* controller,
|
LevelController* controller,
|
||||||
Assets& assets,
|
|
||||||
const EngineSettings& settings
|
const EngineSettings& settings
|
||||||
)
|
)
|
||||||
: level(*controller->getLevel()),
|
: level(*controller->getLevel()),
|
||||||
controller(controller),
|
controller(controller),
|
||||||
assets(assets),
|
assets(*engine.getAssets()),
|
||||||
contentCache(std::make_unique<ContentGfxCache>(
|
contentCache(std::make_unique<ContentGfxCache>(
|
||||||
level.content, assets, settings.graphics
|
level.content, assets, settings.graphics
|
||||||
)) {
|
)) {
|
||||||
assets.store(
|
assets.store(
|
||||||
BlocksPreview::build(
|
BlocksPreview::build(
|
||||||
*contentCache, assets, *level.content.getIndices()
|
engine.getWindow(),
|
||||||
|
*contentCache,
|
||||||
|
*engine.getAssets(),
|
||||||
|
*level.content.getIndices()
|
||||||
),
|
),
|
||||||
"block-previews"
|
"block-previews"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
auto& rassets = assets;
|
||||||
controller->getBlocksController()->listenBlockInteraction(
|
controller->getBlocksController()->listenBlockInteraction(
|
||||||
[currentPlayer, controller, &assets](auto player, const auto& pos, const auto& def, BlockInteraction type) {
|
[currentPlayer, controller, &rassets](auto player, const auto& pos, const auto& def, BlockInteraction type) {
|
||||||
const auto& level = *controller->getLevel();
|
const auto& level = *controller->getLevel();
|
||||||
auto material = level.content.findBlockMaterial(def.material);
|
auto material = level.content.findBlockMaterial(def.material);
|
||||||
if (material == nullptr) {
|
if (material == nullptr) {
|
||||||
@ -40,7 +46,7 @@ LevelFrontend::LevelFrontend(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (type == BlockInteraction::step) {
|
if (type == BlockInteraction::step) {
|
||||||
auto sound = assets.get<audio::Sound>(material->stepsSound);
|
auto sound = rassets.get<audio::Sound>(material->stepsSound);
|
||||||
glm::vec3 pos {};
|
glm::vec3 pos {};
|
||||||
auto soundsCamera = currentPlayer->currentCamera.get();
|
auto soundsCamera = currentPlayer->currentCamera.get();
|
||||||
if (soundsCamera == currentPlayer->spCamera.get() ||
|
if (soundsCamera == currentPlayer->spCamera.get() ||
|
||||||
@ -66,10 +72,10 @@ LevelFrontend::LevelFrontend(
|
|||||||
audio::Sound* sound = nullptr;
|
audio::Sound* sound = nullptr;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case BlockInteraction::placing:
|
case BlockInteraction::placing:
|
||||||
sound = assets.get<audio::Sound>(material->placeSound);
|
sound = rassets.get<audio::Sound>(material->placeSound);
|
||||||
break;
|
break;
|
||||||
case BlockInteraction::destruction:
|
case BlockInteraction::destruction:
|
||||||
sound = assets.get<audio::Sound>(material->breakSound);
|
sound = rassets.get<audio::Sound>(material->breakSound);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -95,14 +101,6 @@ Level& LevelFrontend::getLevel() {
|
|||||||
return level;
|
return level;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Level& LevelFrontend::getLevel() const {
|
|
||||||
return level;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Assets& LevelFrontend::getAssets() const {
|
|
||||||
return assets;
|
|
||||||
}
|
|
||||||
|
|
||||||
ContentGfxCache& LevelFrontend::getContentGfxCache() {
|
ContentGfxCache& LevelFrontend::getContentGfxCache() {
|
||||||
return *contentCache;
|
return *contentCache;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,6 +5,7 @@
|
|||||||
class Level;
|
class Level;
|
||||||
class Assets;
|
class Assets;
|
||||||
class Player;
|
class Player;
|
||||||
|
class Engine;
|
||||||
class ContentGfxCache;
|
class ContentGfxCache;
|
||||||
class LevelController;
|
class LevelController;
|
||||||
struct EngineSettings;
|
struct EngineSettings;
|
||||||
@ -12,20 +13,18 @@ struct EngineSettings;
|
|||||||
class LevelFrontend {
|
class LevelFrontend {
|
||||||
Level& level;
|
Level& level;
|
||||||
LevelController* controller;
|
LevelController* controller;
|
||||||
const Assets& assets;
|
Assets& assets;
|
||||||
std::unique_ptr<ContentGfxCache> contentCache;
|
std::unique_ptr<ContentGfxCache> contentCache;
|
||||||
public:
|
public:
|
||||||
LevelFrontend(
|
LevelFrontend(
|
||||||
|
Engine& engine,
|
||||||
Player* currentPlayer,
|
Player* currentPlayer,
|
||||||
LevelController* controller,
|
LevelController* controller,
|
||||||
Assets& assets,
|
|
||||||
const EngineSettings& settings
|
const EngineSettings& settings
|
||||||
);
|
);
|
||||||
~LevelFrontend();
|
~LevelFrontend();
|
||||||
|
|
||||||
Level& getLevel();
|
Level& getLevel();
|
||||||
const Level& getLevel() const;
|
|
||||||
const Assets& getAssets() const;
|
|
||||||
const ContentGfxCache& getContentGfxCache() const;
|
const ContentGfxCache& getContentGfxCache() const;
|
||||||
ContentGfxCache& getContentGfxCache();
|
ContentGfxCache& getContentGfxCache();
|
||||||
LevelController* getController() const;
|
LevelController* getController() const;
|
||||||
|
|||||||
@ -21,11 +21,11 @@ void UiDocument::rebuildIndices() {
|
|||||||
gui::UINode::getIndices(root, map);
|
gui::UINode::getIndices(root, map);
|
||||||
}
|
}
|
||||||
|
|
||||||
const uinodes_map& UiDocument::getMap() const {
|
const UINodesMap& UiDocument::getMap() const {
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
uinodes_map& UiDocument::getMapWriteable() {
|
UINodesMap& UiDocument::getMapWriteable() {
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,6 +54,7 @@ scriptenv UiDocument::getEnvironment() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<UiDocument> UiDocument::read(
|
std::unique_ptr<UiDocument> UiDocument::read(
|
||||||
|
gui::GUI& gui,
|
||||||
const scriptenv& penv,
|
const scriptenv& penv,
|
||||||
const std::string& name,
|
const std::string& name,
|
||||||
const io::path& file,
|
const io::path& file,
|
||||||
@ -66,7 +67,7 @@ std::unique_ptr<UiDocument> UiDocument::read(
|
|||||||
? scripting::create_doc_environment(scripting::get_root_environment(), name)
|
? scripting::create_doc_environment(scripting::get_root_environment(), name)
|
||||||
: scripting::create_doc_environment(penv, name);
|
: scripting::create_doc_environment(penv, name);
|
||||||
|
|
||||||
gui::UiXmlReader reader(env);
|
gui::UiXmlReader reader(gui, env);
|
||||||
auto view = reader.readXML(file.string(), *xmldoc->getRoot());
|
auto view = reader.readXML(file.string(), *xmldoc->getRoot());
|
||||||
view->setId("root");
|
view->setId("root");
|
||||||
uidocscript script {};
|
uidocscript script {};
|
||||||
@ -80,8 +81,7 @@ std::unique_ptr<UiDocument> UiDocument::read(
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<gui::UINode> UiDocument::readElement(
|
std::shared_ptr<gui::UINode> UiDocument::readElement(
|
||||||
const io::path& file, const std::string& fileName
|
gui::GUI& gui, const io::path& file, const std::string& fileName
|
||||||
) {
|
) {
|
||||||
auto document = read(nullptr, file.name(), file, fileName);
|
return read(gui, nullptr, file.name(), file, fileName)->getRoot();
|
||||||
return document->getRoot();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,6 +9,7 @@
|
|||||||
#include "io/fwd.hpp"
|
#include "io/fwd.hpp"
|
||||||
|
|
||||||
namespace gui {
|
namespace gui {
|
||||||
|
class GUI;
|
||||||
class UINode;
|
class UINode;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -18,12 +19,12 @@ struct uidocscript {
|
|||||||
bool onclose : 1;
|
bool onclose : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
using uinodes_map = std::unordered_map<std::string, std::shared_ptr<gui::UINode>>;
|
using UINodesMap = std::unordered_map<std::string, std::shared_ptr<gui::UINode>>;
|
||||||
|
|
||||||
class UiDocument {
|
class UiDocument {
|
||||||
std::string id;
|
std::string id;
|
||||||
uidocscript script;
|
uidocscript script;
|
||||||
uinodes_map map;
|
UINodesMap map;
|
||||||
std::shared_ptr<gui::UINode> root;
|
std::shared_ptr<gui::UINode> root;
|
||||||
scriptenv env;
|
scriptenv env;
|
||||||
public:
|
public:
|
||||||
@ -37,20 +38,21 @@ public:
|
|||||||
void rebuildIndices();
|
void rebuildIndices();
|
||||||
|
|
||||||
const std::string& getId() const;
|
const std::string& getId() const;
|
||||||
const uinodes_map& getMap() const;
|
const UINodesMap& getMap() const;
|
||||||
uinodes_map& getMapWriteable();
|
UINodesMap& getMapWriteable();
|
||||||
std::shared_ptr<gui::UINode> getRoot() const;
|
std::shared_ptr<gui::UINode> getRoot() const;
|
||||||
std::shared_ptr<gui::UINode> get(const std::string& id) const;
|
std::shared_ptr<gui::UINode> get(const std::string& id) const;
|
||||||
const uidocscript& getScript() const;
|
const uidocscript& getScript() const;
|
||||||
scriptenv getEnvironment() const;
|
scriptenv getEnvironment() const;
|
||||||
|
|
||||||
static std::unique_ptr<UiDocument> read(
|
static std::unique_ptr<UiDocument> read(
|
||||||
|
gui::GUI&,
|
||||||
const scriptenv& parent_env,
|
const scriptenv& parent_env,
|
||||||
const std::string& name,
|
const std::string& name,
|
||||||
const io::path& file,
|
const io::path& file,
|
||||||
const std::string& fileName
|
const std::string& fileName
|
||||||
);
|
);
|
||||||
static std::shared_ptr<gui::UINode> readElement(
|
static std::shared_ptr<gui::UINode> readElement(
|
||||||
const io::path& file, const std::string& fileName
|
gui::GUI&, const io::path& file, const std::string& fileName
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -35,8 +35,8 @@
|
|||||||
|
|
||||||
using namespace gui;
|
using namespace gui;
|
||||||
|
|
||||||
static std::shared_ptr<Label> create_label(wstringsupplier supplier) {
|
static std::shared_ptr<Label> create_label(GUI& gui, wstringsupplier supplier) {
|
||||||
auto label = std::make_shared<Label>(L"-");
|
auto label = std::make_shared<Label>(gui, L"-");
|
||||||
label->textSupplier(std::move(supplier));
|
label->textSupplier(std::move(supplier));
|
||||||
return label;
|
return label;
|
||||||
}
|
}
|
||||||
@ -50,7 +50,10 @@ std::shared_ptr<UINode> create_debug_panel(
|
|||||||
Player& player,
|
Player& player,
|
||||||
bool allowDebugCheats
|
bool allowDebugCheats
|
||||||
) {
|
) {
|
||||||
auto panel = std::make_shared<Panel>(glm::vec2(300, 200), glm::vec4(5.0f), 2.0f);
|
auto& gui = engine.getGUI();
|
||||||
|
auto panel = std::make_shared<Panel>(
|
||||||
|
gui, glm::vec2(300, 200), glm::vec4(5.0f), 2.0f
|
||||||
|
);
|
||||||
panel->setId("hud.debug-panel");
|
panel->setId("hud.debug-panel");
|
||||||
panel->setPos(glm::vec2(10, 10));
|
panel->setPos(glm::vec2(10, 10));
|
||||||
|
|
||||||
@ -87,48 +90,48 @@ std::shared_ptr<UINode> create_debug_panel(
|
|||||||
lastTotalUpload = totalUpload;
|
lastTotalUpload = totalUpload;
|
||||||
});
|
});
|
||||||
|
|
||||||
panel->add(create_label([]() { return L"fps: "+fpsString;}));
|
panel->add(create_label(gui, []() { return L"fps: "+fpsString;}));
|
||||||
|
|
||||||
panel->add(create_label([]() {
|
panel->add(create_label(gui, []() {
|
||||||
return L"meshes: " + std::to_wstring(Mesh::meshesCount);
|
return L"meshes: " + std::to_wstring(Mesh::meshesCount);
|
||||||
}));
|
}));
|
||||||
panel->add(create_label([]() {
|
panel->add(create_label(gui, []() {
|
||||||
int drawCalls = Mesh::drawCalls;
|
int drawCalls = Mesh::drawCalls;
|
||||||
Mesh::drawCalls = 0;
|
Mesh::drawCalls = 0;
|
||||||
return L"draw-calls: " + std::to_wstring(drawCalls);
|
return L"draw-calls: " + std::to_wstring(drawCalls);
|
||||||
}));
|
}));
|
||||||
panel->add(create_label([]() {
|
panel->add(create_label(gui, []() {
|
||||||
return L"speakers: " + std::to_wstring(audio::count_speakers())+
|
return L"speakers: " + std::to_wstring(audio::count_speakers())+
|
||||||
L" streams: " + std::to_wstring(audio::count_streams());
|
L" streams: " + std::to_wstring(audio::count_streams());
|
||||||
}));
|
}));
|
||||||
panel->add(create_label([]() {
|
panel->add(create_label(gui, []() {
|
||||||
return L"lua-stack: " + std::to_wstring(scripting::get_values_on_stack());
|
return L"lua-stack: " + std::to_wstring(scripting::get_values_on_stack());
|
||||||
}));
|
}));
|
||||||
panel->add(create_label([]() { return netSpeedString; }));
|
panel->add(create_label(gui, []() { return netSpeedString; }));
|
||||||
panel->add(create_label([&engine]() {
|
panel->add(create_label(gui, [&engine]() {
|
||||||
auto& settings = engine.getSettings();
|
auto& settings = engine.getSettings();
|
||||||
bool culling = settings.graphics.frustumCulling.get();
|
bool culling = settings.graphics.frustumCulling.get();
|
||||||
return L"frustum-culling: "+std::wstring(culling ? L"on" : L"off");
|
return L"frustum-culling: "+std::wstring(culling ? L"on" : L"off");
|
||||||
}));
|
}));
|
||||||
panel->add(create_label([=]() {
|
panel->add(create_label(gui, [=]() {
|
||||||
return L"particles: " +
|
return L"particles: " +
|
||||||
std::to_wstring(ParticlesRenderer::visibleParticles) +
|
std::to_wstring(ParticlesRenderer::visibleParticles) +
|
||||||
L" emitters: " +
|
L" emitters: " +
|
||||||
std::to_wstring(ParticlesRenderer::aliveEmitters);
|
std::to_wstring(ParticlesRenderer::aliveEmitters);
|
||||||
}));
|
}));
|
||||||
panel->add(create_label([&]() {
|
panel->add(create_label(gui, [&]() {
|
||||||
return L"chunks: "+std::to_wstring(level.chunks->size())+
|
return L"chunks: "+std::to_wstring(level.chunks->size())+
|
||||||
L" visible: "+std::to_wstring(ChunksRenderer::visibleChunks);
|
L" visible: "+std::to_wstring(ChunksRenderer::visibleChunks);
|
||||||
}));
|
}));
|
||||||
panel->add(create_label([&]() {
|
panel->add(create_label(gui, [&]() {
|
||||||
return L"entities: "+std::to_wstring(level.entities->size())+L" next: "+
|
return L"entities: "+std::to_wstring(level.entities->size())+L" next: "+
|
||||||
std::to_wstring(level.entities->peekNextID());
|
std::to_wstring(level.entities->peekNextID());
|
||||||
}));
|
}));
|
||||||
panel->add(create_label([&]() {
|
panel->add(create_label(gui, [&]() {
|
||||||
return L"players: "+std::to_wstring(level.players->size())+L" local: "+
|
return L"players: "+std::to_wstring(level.players->size())+L" local: "+
|
||||||
std::to_wstring(player.getId());
|
std::to_wstring(player.getId());
|
||||||
}));
|
}));
|
||||||
panel->add(create_label([&]() -> std::wstring {
|
panel->add(create_label(gui, [&]() -> std::wstring {
|
||||||
const auto& vox = player.selection.vox;
|
const auto& vox = player.selection.vox;
|
||||||
std::wstringstream stream;
|
std::wstringstream stream;
|
||||||
stream << "r:" << vox.state.rotation << " s:"
|
stream << "r:" << vox.state.rotation << " s:"
|
||||||
@ -141,7 +144,7 @@ std::shared_ptr<UINode> create_debug_panel(
|
|||||||
L" "+stream.str();
|
L" "+stream.str();
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
panel->add(create_label([&]() -> std::wstring {
|
panel->add(create_label(gui, [&]() -> std::wstring {
|
||||||
const auto& selection = player.selection;
|
const auto& selection = player.selection;
|
||||||
const auto& vox = selection.vox;
|
const auto& vox = selection.vox;
|
||||||
if (vox.id == BLOCK_VOID) {
|
if (vox.id == BLOCK_VOID) {
|
||||||
@ -151,7 +154,7 @@ std::shared_ptr<UINode> create_debug_panel(
|
|||||||
L" y: " + std::to_wstring(selection.actualPosition.y) +
|
L" y: " + std::to_wstring(selection.actualPosition.y) +
|
||||||
L" z: " + std::to_wstring(selection.actualPosition.z);
|
L" z: " + std::to_wstring(selection.actualPosition.z);
|
||||||
}));
|
}));
|
||||||
panel->add(create_label([&]() {
|
panel->add(create_label(gui, [&]() {
|
||||||
auto eid = player.getSelectedEntity();
|
auto eid = player.getSelectedEntity();
|
||||||
if (eid == ENTITY_NONE) {
|
if (eid == ENTITY_NONE) {
|
||||||
return std::wstring {L"entity: -"};
|
return std::wstring {L"entity: -"};
|
||||||
@ -162,7 +165,7 @@ std::shared_ptr<UINode> create_debug_panel(
|
|||||||
return std::wstring {L"entity: error (invalid UID)"};
|
return std::wstring {L"entity: error (invalid UID)"};
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
panel->add(create_label([&](){
|
panel->add(create_label(gui, [&](){
|
||||||
auto indices = level.content.getIndices();
|
auto indices = level.content.getIndices();
|
||||||
if (auto def = indices->blocks.get(player.selection.vox.id)) {
|
if (auto def = indices->blocks.get(player.selection.vox.id)) {
|
||||||
return L"name: " + util::str2wstr_utf8(def->name);
|
return L"name: " + util::str2wstr_utf8(def->name);
|
||||||
@ -170,23 +173,23 @@ std::shared_ptr<UINode> create_debug_panel(
|
|||||||
return std::wstring {L"name: void"};
|
return std::wstring {L"name: void"};
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
panel->add(create_label([&](){
|
panel->add(create_label(gui, [&](){
|
||||||
return L"seed: "+std::to_wstring(level.getWorld()->getSeed());
|
return L"seed: "+std::to_wstring(level.getWorld()->getSeed());
|
||||||
}));
|
}));
|
||||||
|
|
||||||
for (int ax = 0; ax < 3; ax++) {
|
for (int ax = 0; ax < 3; ax++) {
|
||||||
auto sub = std::make_shared<Container>(glm::vec2(250, 27));
|
auto sub = std::make_shared<Container>(gui, glm::vec2(250, 27));
|
||||||
|
|
||||||
std::wstring str = L"x: ";
|
std::wstring str = L"x: ";
|
||||||
str[0] += ax;
|
str[0] += ax;
|
||||||
auto label = std::make_shared<Label>(str);
|
auto label = std::make_shared<Label>(gui, str);
|
||||||
label->setMargin(glm::vec4(2, 3, 2, 3));
|
label->setMargin(glm::vec4(2, 3, 2, 3));
|
||||||
label->setSize(glm::vec2(20, 27));
|
label->setSize(glm::vec2(20, 27));
|
||||||
sub->add(label);
|
sub->add(label);
|
||||||
sub->setColor(glm::vec4(0.0f));
|
sub->setColor(glm::vec4(0.0f));
|
||||||
|
|
||||||
// Coord input
|
// Coord input
|
||||||
auto box = std::make_shared<TextBox>(L"");
|
auto box = std::make_shared<TextBox>(gui, L"");
|
||||||
auto boxRef = box.get();
|
auto boxRef = box.get();
|
||||||
box->setTextSupplier([&player, ax]() {
|
box->setTextSupplier([&player, ax]() {
|
||||||
return util::to_wstring(player.getPosition()[ax], 2);
|
return util::to_wstring(player.getPosition()[ax], 2);
|
||||||
@ -212,7 +215,7 @@ std::shared_ptr<UINode> create_debug_panel(
|
|||||||
panel->add(sub);
|
panel->add(sub);
|
||||||
}
|
}
|
||||||
auto& worldInfo = level.getWorld()->getInfo();
|
auto& worldInfo = level.getWorld()->getInfo();
|
||||||
panel->add(create_label([&](){
|
panel->add(create_label(gui, [&](){
|
||||||
int hour, minute, second;
|
int hour, minute, second;
|
||||||
timeutil::from_value(worldInfo.daytime, hour, minute, second);
|
timeutil::from_value(worldInfo.daytime, hour, minute, second);
|
||||||
|
|
||||||
@ -222,20 +225,20 @@ std::shared_ptr<UINode> create_debug_panel(
|
|||||||
return L"time: "+timeString;
|
return L"time: "+timeString;
|
||||||
}));
|
}));
|
||||||
if (allowDebugCheats) {
|
if (allowDebugCheats) {
|
||||||
auto bar = std::make_shared<TrackBar>(0.0f, 1.0f, 1.0f, 0.005f, 8);
|
auto bar = std::make_shared<TrackBar>(gui, 0.0f, 1.0f, 1.0f, 0.005f, 8);
|
||||||
bar->setSupplier([&]() {return worldInfo.daytime;});
|
bar->setSupplier([&]() {return worldInfo.daytime;});
|
||||||
bar->setConsumer([&](double val) {worldInfo.daytime = val;});
|
bar->setConsumer([&](double val) {worldInfo.daytime = val;});
|
||||||
panel->add(bar);
|
panel->add(bar);
|
||||||
}
|
}
|
||||||
if (allowDebugCheats) {
|
if (allowDebugCheats) {
|
||||||
auto bar = std::make_shared<TrackBar>(0.0f, 1.0f, 0.0f, 0.005f, 8);
|
auto bar = std::make_shared<TrackBar>(gui, 0.0f, 1.0f, 0.0f, 0.005f, 8);
|
||||||
bar->setSupplier([&]() {return worldInfo.fog;});
|
bar->setSupplier([&]() {return worldInfo.fog;});
|
||||||
bar->setConsumer([&](double val) {worldInfo.fog = val;});
|
bar->setConsumer([&](double val) {worldInfo.fog = val;});
|
||||||
panel->add(bar);
|
panel->add(bar);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
auto checkbox = std::make_shared<FullCheckBox>(
|
auto checkbox = std::make_shared<FullCheckBox>(
|
||||||
L"Show Chunk Borders", glm::vec2(400, 24)
|
gui, L"Show Chunk Borders", glm::vec2(400, 24)
|
||||||
);
|
);
|
||||||
checkbox->setSupplier([=]() {
|
checkbox->setSupplier([=]() {
|
||||||
return WorldRenderer::showChunkBorders;
|
return WorldRenderer::showChunkBorders;
|
||||||
@ -247,7 +250,7 @@ std::shared_ptr<UINode> create_debug_panel(
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
auto checkbox = std::make_shared<FullCheckBox>(
|
auto checkbox = std::make_shared<FullCheckBox>(
|
||||||
L"Show Hitboxes", glm::vec2(400, 24)
|
gui, L"Show Hitboxes", glm::vec2(400, 24)
|
||||||
);
|
);
|
||||||
checkbox->setSupplier([=]() {
|
checkbox->setSupplier([=]() {
|
||||||
return WorldRenderer::showEntitiesDebug;
|
return WorldRenderer::showEntitiesDebug;
|
||||||
@ -259,7 +262,7 @@ std::shared_ptr<UINode> create_debug_panel(
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
auto checkbox = std::make_shared<FullCheckBox>(
|
auto checkbox = std::make_shared<FullCheckBox>(
|
||||||
L"Show Generator Minimap", glm::vec2(400, 24)
|
gui, L"Show Generator Minimap", glm::vec2(400, 24)
|
||||||
);
|
);
|
||||||
checkbox->setSupplier([=]() {
|
checkbox->setSupplier([=]() {
|
||||||
return Hud::showGeneratorMinimap;
|
return Hud::showGeneratorMinimap;
|
||||||
|
|||||||
@ -13,8 +13,6 @@
|
|||||||
#include "graphics/core/Batch2D.hpp"
|
#include "graphics/core/Batch2D.hpp"
|
||||||
#include "graphics/core/Batch3D.hpp"
|
#include "graphics/core/Batch3D.hpp"
|
||||||
#include "graphics/core/DrawContext.hpp"
|
#include "graphics/core/DrawContext.hpp"
|
||||||
#include "graphics/core/Font.hpp"
|
|
||||||
#include "graphics/core/Mesh.hpp"
|
|
||||||
#include "graphics/core/Shader.hpp"
|
#include "graphics/core/Shader.hpp"
|
||||||
#include "graphics/core/Texture.hpp"
|
#include "graphics/core/Texture.hpp"
|
||||||
#include "graphics/core/ImageData.hpp"
|
#include "graphics/core/ImageData.hpp"
|
||||||
@ -42,7 +40,6 @@
|
|||||||
#include "voxels/Chunks.hpp"
|
#include "voxels/Chunks.hpp"
|
||||||
#include "voxels/GlobalChunks.hpp"
|
#include "voxels/GlobalChunks.hpp"
|
||||||
#include "window/Camera.hpp"
|
#include "window/Camera.hpp"
|
||||||
#include "window/Events.hpp"
|
|
||||||
#include "window/input.hpp"
|
#include "window/input.hpp"
|
||||||
#include "window/Window.hpp"
|
#include "window/Window.hpp"
|
||||||
#include "world/Level.hpp"
|
#include "world/Level.hpp"
|
||||||
@ -126,7 +123,7 @@ std::shared_ptr<InventoryView> Hud::createContentAccess() {
|
|||||||
inventory->getSlot(player.getChosenSlot()).set(item);
|
inventory->getSlot(player.getChosenSlot()).set(item);
|
||||||
});
|
});
|
||||||
|
|
||||||
InventoryBuilder builder;
|
InventoryBuilder builder(gui);
|
||||||
builder.addGrid(8, itemsCount-1, glm::vec2(), glm::vec4(8, 8, 12, 8), true, slotLayout);
|
builder.addGrid(8, itemsCount-1, glm::vec2(), glm::vec4(8, 8, 12, 8), true, slotLayout);
|
||||||
auto view = builder.build();
|
auto view = builder.build();
|
||||||
view->bind(accessInventory, &content);
|
view->bind(accessInventory, &content);
|
||||||
@ -139,7 +136,7 @@ std::shared_ptr<InventoryView> Hud::createHotbar() {
|
|||||||
auto& content = frontend.getLevel().content;
|
auto& content = frontend.getLevel().content;
|
||||||
|
|
||||||
SlotLayout slotLayout(-1, glm::vec2(), false, false, nullptr, nullptr, nullptr);
|
SlotLayout slotLayout(-1, glm::vec2(), false, false, nullptr, nullptr, nullptr);
|
||||||
InventoryBuilder builder;
|
InventoryBuilder builder(gui);
|
||||||
builder.addGrid(10, 10, glm::vec2(), glm::vec4(4), true, slotLayout);
|
builder.addGrid(10, 10, glm::vec2(), glm::vec4(4), true, slotLayout);
|
||||||
auto view = builder.build();
|
auto view = builder.build();
|
||||||
view->setId("hud.hotbar");
|
view->setId("hud.hotbar");
|
||||||
@ -153,8 +150,10 @@ static constexpr uint WORLDGEN_IMG_SIZE = 128U;
|
|||||||
|
|
||||||
Hud::Hud(Engine& engine, LevelFrontend& frontend, Player& player)
|
Hud::Hud(Engine& engine, LevelFrontend& frontend, Player& player)
|
||||||
: engine(engine),
|
: engine(engine),
|
||||||
|
input(engine.getInput()),
|
||||||
assets(*engine.getAssets()),
|
assets(*engine.getAssets()),
|
||||||
gui(*engine.getGUI()),
|
gui(engine.getGUI()),
|
||||||
|
menu(*engine.getGUI().getMenu()),
|
||||||
frontend(frontend),
|
frontend(frontend),
|
||||||
player(player),
|
player(player),
|
||||||
debugImgWorldGen(std::make_unique<ImageData>(
|
debugImgWorldGen(std::make_unique<ImageData>(
|
||||||
@ -163,7 +162,7 @@ Hud::Hud(Engine& engine, LevelFrontend& frontend, Player& player)
|
|||||||
contentAccess = createContentAccess();
|
contentAccess = createContentAccess();
|
||||||
contentAccess->setId("hud.content-access");
|
contentAccess->setId("hud.content-access");
|
||||||
contentAccessPanel = std::make_shared<Panel>(
|
contentAccessPanel = std::make_shared<Panel>(
|
||||||
contentAccess->getSize(), glm::vec4(0.0f), 0.0f
|
gui, contentAccess->getSize(), glm::vec4(0.0f), 0.0f
|
||||||
);
|
);
|
||||||
contentAccessPanel->setColor(glm::vec4());
|
contentAccessPanel->setColor(glm::vec4());
|
||||||
contentAccessPanel->add(contentAccess);
|
contentAccessPanel->add(contentAccess);
|
||||||
@ -172,6 +171,7 @@ Hud::Hud(Engine& engine, LevelFrontend& frontend, Player& player)
|
|||||||
|
|
||||||
hotbarView = createHotbar();
|
hotbarView = createHotbar();
|
||||||
darkOverlay = guiutil::create(
|
darkOverlay = guiutil::create(
|
||||||
|
gui,
|
||||||
"<container size='4000' color='#00000080' z-index='-1' visible='false'/>"
|
"<container size='4000' color='#00000080' z-index='-1' visible='false'/>"
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -183,13 +183,13 @@ Hud::Hud(Engine& engine, LevelFrontend& frontend, Player& player)
|
|||||||
engine, frontend.getLevel(), player, allowDebugCheats
|
engine, frontend.getLevel(), player, allowDebugCheats
|
||||||
);
|
);
|
||||||
debugPanel->setZIndex(2);
|
debugPanel->setZIndex(2);
|
||||||
gui.add(debugPanel);
|
|
||||||
|
|
||||||
|
gui.add(debugPanel);
|
||||||
gui.add(darkOverlay);
|
gui.add(darkOverlay);
|
||||||
gui.add(hotbarView);
|
gui.add(hotbarView);
|
||||||
gui.add(contentAccessPanel);
|
gui.add(contentAccessPanel);
|
||||||
|
|
||||||
auto dplotter = std::make_shared<Plotter>(350, 250, 2000, 16);
|
auto dplotter = std::make_shared<Plotter>(gui, 350, 250, 2000, 16);
|
||||||
dplotter->setGravity(Gravity::bottom_right);
|
dplotter->setGravity(Gravity::bottom_right);
|
||||||
dplotter->setInteractive(false);
|
dplotter->setInteractive(false);
|
||||||
add(HudElement(HudElementMode::PERMANENT, nullptr, dplotter, true));
|
add(HudElement(HudElementMode::PERMANENT, nullptr, dplotter, true));
|
||||||
@ -197,7 +197,8 @@ Hud::Hud(Engine& engine, LevelFrontend& frontend, Player& player)
|
|||||||
assets.store(Texture::from(debugImgWorldGen.get()), DEBUG_WORLDGEN_IMAGE);
|
assets.store(Texture::from(debugImgWorldGen.get()), DEBUG_WORLDGEN_IMAGE);
|
||||||
|
|
||||||
debugMinimap = guiutil::create(
|
debugMinimap = guiutil::create(
|
||||||
"<image src='"+DEBUG_WORLDGEN_IMAGE+
|
gui,
|
||||||
|
"<image src='" + DEBUG_WORLDGEN_IMAGE +
|
||||||
"' pos='0' size='256' gravity='top-right' margin='0,20,0,0'/>"
|
"' pos='0' size='256' gravity='top-right' margin='0,20,0,0'/>"
|
||||||
);
|
);
|
||||||
add(HudElement(HudElementMode::PERMANENT, nullptr, debugMinimap, true));
|
add(HudElement(HudElementMode::PERMANENT, nullptr, debugMinimap, true));
|
||||||
@ -223,11 +224,12 @@ void Hud::cleanup() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Hud::processInput(bool visible) {
|
void Hud::processInput(bool visible) {
|
||||||
auto menu = gui.getMenu();
|
const auto& window = engine.getWindow();
|
||||||
if (!Window::isFocused() && !menu->hasOpenPage() && !isInventoryOpen()) {
|
if (!window.isFocused() && !menu.hasOpenPage() && !isInventoryOpen()) {
|
||||||
setPause(true);
|
setPause(true);
|
||||||
}
|
}
|
||||||
if (!pause && visible && Events::jactive(BIND_HUD_INVENTORY)) {
|
const auto& bindings = input.getBindings();
|
||||||
|
if (!pause && visible && bindings.jactive(BIND_HUD_INVENTORY)) {
|
||||||
if (inventoryOpen) {
|
if (inventoryOpen) {
|
||||||
closeInventory();
|
closeInventory();
|
||||||
} else {
|
} else {
|
||||||
@ -240,24 +242,25 @@ void Hud::processInput(bool visible) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Hud::updateHotbarControl() {
|
void Hud::updateHotbarControl() {
|
||||||
if (!inventoryOpen && Events::scroll) {
|
int scroll = input.getScroll();
|
||||||
|
if (!inventoryOpen && scroll) {
|
||||||
int slot = player.getChosenSlot();
|
int slot = player.getChosenSlot();
|
||||||
slot = (slot - Events::scroll) % 10;
|
slot = (slot - scroll) % 10;
|
||||||
if (slot < 0) {
|
if (slot < 0) {
|
||||||
slot += 10;
|
slot += 10;
|
||||||
}
|
}
|
||||||
player.setChosenSlot(slot);
|
player.setChosenSlot(slot);
|
||||||
}
|
}
|
||||||
for (
|
for (
|
||||||
int i = static_cast<int>(keycode::NUM_1);
|
int i = static_cast<int>(Keycode::NUM_1);
|
||||||
i <= static_cast<int>(keycode::NUM_9);
|
i <= static_cast<int>(Keycode::NUM_9);
|
||||||
i++
|
i++
|
||||||
) {
|
) {
|
||||||
if (Events::jpressed(i)) {
|
if (input.jpressed(static_cast<Keycode>(i))) {
|
||||||
player.setChosenSlot(i - static_cast<int>(keycode::NUM_1));
|
player.setChosenSlot(i - static_cast<int>(Keycode::NUM_1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Events::jpressed(keycode::NUM_0)) {
|
if (input.jpressed(Keycode::NUM_0)) {
|
||||||
player.setChosenSlot(9);
|
player.setChosenSlot(9);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -311,7 +314,6 @@ void Hud::updateWorldGenDebug() {
|
|||||||
|
|
||||||
void Hud::update(bool visible) {
|
void Hud::update(bool visible) {
|
||||||
const auto& chunks = *player.chunks;
|
const auto& chunks = *player.chunks;
|
||||||
const auto& menu = gui.getMenu();
|
|
||||||
|
|
||||||
debugPanel->setVisible(
|
debugPanel->setVisible(
|
||||||
debug && visible && !(inventoryOpen && inventoryView == nullptr)
|
debug && visible && !(inventoryOpen && inventoryView == nullptr)
|
||||||
@ -320,14 +322,14 @@ void Hud::update(bool visible) {
|
|||||||
if (!visible && inventoryOpen) {
|
if (!visible && inventoryOpen) {
|
||||||
closeInventory();
|
closeInventory();
|
||||||
}
|
}
|
||||||
if (pause && !menu->hasOpenPage()) {
|
if (pause && !menu.hasOpenPage()) {
|
||||||
setPause(false);
|
setPause(false);
|
||||||
}
|
}
|
||||||
if (!gui.isFocusCaught()) {
|
if (!gui.isFocusCaught()) {
|
||||||
processInput(visible);
|
processInput(visible);
|
||||||
}
|
}
|
||||||
if ((menu->hasOpenPage() || inventoryOpen) == Events::isCursorLocked()) {
|
if ((menu.hasOpenPage() || inventoryOpen) == input.getCursor().locked) {
|
||||||
Events::toggleCursor();
|
input.toggleCursor();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (blockUI) {
|
if (blockUI) {
|
||||||
@ -341,10 +343,11 @@ void Hud::update(bool visible) {
|
|||||||
element.getNode()->setVisible(visible);
|
element.getNode()->setVisible(visible);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto& windowSize = engine.getWindow().getSize();
|
||||||
glm::vec2 caSize = contentAccessPanel->getSize();
|
glm::vec2 caSize = contentAccessPanel->getSize();
|
||||||
contentAccessPanel->setVisible(inventoryView != nullptr && showContentPanel);
|
contentAccessPanel->setVisible(inventoryView != nullptr && showContentPanel);
|
||||||
contentAccessPanel->setSize(glm::vec2(caSize.x, Window::height));
|
contentAccessPanel->setSize(glm::vec2(caSize.x, windowSize.y));
|
||||||
contentAccess->setMinSize(glm::vec2(1, Window::height));
|
contentAccess->setMinSize(glm::vec2(1, windowSize.y));
|
||||||
hotbarView->setVisible(visible && !(secondUI && !inventoryView));
|
hotbarView->setVisible(visible && !(secondUI && !inventoryView));
|
||||||
|
|
||||||
if (visible) {
|
if (visible) {
|
||||||
@ -447,6 +450,7 @@ void Hud::showExchangeSlot() {
|
|||||||
auto& content = level.content;
|
auto& content = level.content;
|
||||||
exchangeSlotInv = level.inventories->createVirtual(1);
|
exchangeSlotInv = level.inventories->createVirtual(1);
|
||||||
exchangeSlot = std::make_shared<SlotView>(
|
exchangeSlot = std::make_shared<SlotView>(
|
||||||
|
gui,
|
||||||
SlotLayout(-1, glm::vec2(), false, false, nullptr, nullptr, nullptr)
|
SlotLayout(-1, glm::vec2(), false, false, nullptr, nullptr, nullptr)
|
||||||
);
|
);
|
||||||
exchangeSlot->bind(exchangeSlotInv->getId(), exchangeSlotInv->getSlot(0), &content);
|
exchangeSlot->bind(exchangeSlotInv->getId(), exchangeSlotInv->getSlot(0), &content);
|
||||||
@ -587,18 +591,16 @@ void Hud::setDebug(bool flag) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Hud::draw(const DrawContext& ctx){
|
void Hud::draw(const DrawContext& ctx){
|
||||||
const Viewport& viewport = ctx.getViewport();
|
const auto& viewport = ctx.getViewport();
|
||||||
const uint width = viewport.getWidth();
|
|
||||||
const uint height = viewport.getHeight();
|
|
||||||
auto menu = gui.getMenu();
|
|
||||||
|
|
||||||
bool is_menu_open = menu->hasOpenPage();
|
bool is_menu_open = menu.hasOpenPage();
|
||||||
darkOverlay->setVisible(is_menu_open);
|
darkOverlay->setVisible(is_menu_open);
|
||||||
menu->setVisible(is_menu_open);
|
menu.setVisible(is_menu_open);
|
||||||
|
|
||||||
updateElementsPosition(viewport);
|
updateElementsPosition(viewport);
|
||||||
|
|
||||||
uicamera->setFov(height);
|
uicamera->setFov(viewport.y);
|
||||||
|
uicamera->setAspectRatio(viewport.x / static_cast<float>(viewport.y));
|
||||||
|
|
||||||
auto batch = ctx.getBatch2D();
|
auto batch = ctx.getBatch2D();
|
||||||
batch->begin();
|
batch->begin();
|
||||||
@ -616,28 +618,28 @@ void Hud::draw(const DrawContext& ctx){
|
|||||||
int chsizex = texture != nullptr ? texture->getWidth() : 16;
|
int chsizex = texture != nullptr ? texture->getWidth() : 16;
|
||||||
int chsizey = texture != nullptr ? texture->getHeight() : 16;
|
int chsizey = texture != nullptr ? texture->getHeight() : 16;
|
||||||
batch->rect(
|
batch->rect(
|
||||||
(width-chsizex)/2, (height-chsizey)/2,
|
(viewport.x - chsizex) / 2, (viewport.y - chsizey) / 2,
|
||||||
chsizex, chsizey, 0,0, 1,1, 1,1,1,1
|
chsizex, chsizey, 0, 0, 1, 1, 1, 1, 1, 1
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Hud::updateElementsPosition(const Viewport& viewport) {
|
void Hud::updateElementsPosition(const glm::uvec2& viewport) {
|
||||||
const uint width = viewport.getWidth();
|
|
||||||
const uint height = viewport.getHeight();
|
|
||||||
|
|
||||||
if (inventoryOpen) {
|
if (inventoryOpen) {
|
||||||
float caWidth = inventoryView && showContentPanel
|
float caWidth = inventoryView && showContentPanel
|
||||||
? contentAccess->getSize().x
|
? contentAccess->getSize().x
|
||||||
: 0.0f;
|
: 0.0f;
|
||||||
contentAccessPanel->setPos(glm::vec2(width-caWidth, 0));
|
contentAccessPanel->setPos(glm::vec2(viewport.x - caWidth, 0));
|
||||||
|
|
||||||
glm::vec2 invSize = inventoryView ? inventoryView->getSize() : glm::vec2();
|
glm::vec2 invSize = inventoryView ? inventoryView->getSize() : glm::vec2();
|
||||||
if (secondUI == nullptr) {
|
if (secondUI == nullptr) {
|
||||||
if (inventoryView) {
|
if (inventoryView) {
|
||||||
inventoryView->setPos(glm::vec2(
|
inventoryView->setPos(glm::vec2(
|
||||||
glm::min(width/2-invSize.x/2, width-caWidth-10-invSize.x),
|
glm::min(
|
||||||
height/2-invSize.y/2
|
viewport.x / 2 - invSize.x / 2,
|
||||||
|
viewport.x - caWidth - 10 - invSize.x
|
||||||
|
),
|
||||||
|
viewport.y / 2 - invSize.y / 2
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -647,25 +649,29 @@ void Hud::updateElementsPosition(const Viewport& viewport) {
|
|||||||
float totalHeight = invSize.y + secondUISize.y + interval;
|
float totalHeight = invSize.y + secondUISize.y + interval;
|
||||||
if (inventoryView) {
|
if (inventoryView) {
|
||||||
inventoryView->setPos(glm::vec2(
|
inventoryView->setPos(glm::vec2(
|
||||||
glm::min(width/2-invwidth/2, width-caWidth-10-invwidth),
|
glm::min(
|
||||||
height/2+totalHeight/2-invSize.y
|
viewport.x / 2 - invwidth / 2,
|
||||||
|
viewport.x - caWidth - 10 - invwidth
|
||||||
|
),
|
||||||
|
viewport.y / 2 + totalHeight / 2 - invSize.y
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
if (secondUI->getPositionFunc() == nullptr) {
|
if (secondUI->getPositionFunc() == nullptr) {
|
||||||
secondUI->setPos(glm::vec2(
|
secondUI->setPos(glm::vec2(
|
||||||
glm::min(
|
glm::min(
|
||||||
width / 2.f - invwidth / 2.f,
|
viewport.x / 2.f - invwidth / 2.f,
|
||||||
width - caWidth - (inventoryView ? 10 : 0) - invwidth
|
viewport.x - caWidth - (inventoryView ? 10 : 0) -
|
||||||
|
invwidth
|
||||||
),
|
),
|
||||||
height / 2.f - totalHeight / 2.f
|
viewport.y / 2.f - totalHeight / 2.f
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (exchangeSlot != nullptr) {
|
if (exchangeSlot != nullptr) {
|
||||||
exchangeSlot->setPos(glm::vec2(Events::cursor));
|
exchangeSlot->setPos(input.getCursor().pos);
|
||||||
}
|
}
|
||||||
hotbarView->setPos(glm::vec2(width/2, height-65));
|
hotbarView->setPos(glm::vec2(viewport.x / 2, viewport.y - 65));
|
||||||
hotbarView->setSelected(player.getChosenSlot());
|
hotbarView->setSelected(player.getChosenSlot());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -689,12 +695,11 @@ void Hud::setPause(bool pause) {
|
|||||||
closeInventory();
|
closeInventory();
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& menu = gui.getMenu();
|
if (!pause && menu.hasOpenPage()) {
|
||||||
if (!pause && menu->hasOpenPage()) {
|
menu.reset();
|
||||||
menu->reset();
|
|
||||||
}
|
}
|
||||||
if (pause && !menu->hasOpenPage()) {
|
if (pause && !menu.hasOpenPage()) {
|
||||||
menu->setPage("pause");
|
menu.setPage("pause");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -730,9 +735,8 @@ void Hud::setDebugCheats(bool flag) {
|
|||||||
|
|
||||||
void Hud::setAllowPause(bool flag) {
|
void Hud::setAllowPause(bool flag) {
|
||||||
if (pause) {
|
if (pause) {
|
||||||
auto menu = gui.getMenu();
|
|
||||||
setPause(false);
|
setPause(false);
|
||||||
menu->setPage("pause", true);
|
menu.setPage("pause", true);
|
||||||
}
|
}
|
||||||
allowPause = flag;
|
allowPause = flag;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,11 +18,12 @@ class Inventory;
|
|||||||
class LevelFrontend;
|
class LevelFrontend;
|
||||||
class UiDocument;
|
class UiDocument;
|
||||||
class DrawContext;
|
class DrawContext;
|
||||||
class Viewport;
|
|
||||||
class ImageData;
|
class ImageData;
|
||||||
|
class Input;
|
||||||
|
|
||||||
namespace gui {
|
namespace gui {
|
||||||
class GUI;
|
class GUI;
|
||||||
|
class Menu;
|
||||||
class UINode;
|
class UINode;
|
||||||
class Panel;
|
class Panel;
|
||||||
class Container;
|
class Container;
|
||||||
@ -71,9 +72,11 @@ public:
|
|||||||
|
|
||||||
class Hud : public util::ObjectsKeeper {
|
class Hud : public util::ObjectsKeeper {
|
||||||
Engine& engine;
|
Engine& engine;
|
||||||
|
Input& input;
|
||||||
Assets& assets;
|
Assets& assets;
|
||||||
std::unique_ptr<Camera> uicamera;
|
|
||||||
gui::GUI& gui;
|
gui::GUI& gui;
|
||||||
|
gui::Menu& menu;
|
||||||
|
std::unique_ptr<Camera> uicamera;
|
||||||
LevelFrontend& frontend;
|
LevelFrontend& frontend;
|
||||||
Player& player;
|
Player& player;
|
||||||
|
|
||||||
@ -127,7 +130,7 @@ class Hud : public util::ObjectsKeeper {
|
|||||||
std::shared_ptr<gui::InventoryView> createHotbar();
|
std::shared_ptr<gui::InventoryView> createHotbar();
|
||||||
|
|
||||||
void processInput(bool visible);
|
void processInput(bool visible);
|
||||||
void updateElementsPosition(const Viewport& viewport);
|
void updateElementsPosition(const glm::uvec2& viewport);
|
||||||
void updateHotbarControl();
|
void updateHotbarControl();
|
||||||
void cleanup();
|
void cleanup();
|
||||||
|
|
||||||
|
|||||||
@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
#include "coders/json.hpp"
|
#include "coders/json.hpp"
|
||||||
#include "coders/BasicParser.hpp"
|
#include "coders/BasicParser.hpp"
|
||||||
#include "content/ContentPack.hpp"
|
|
||||||
#include "io/io.hpp"
|
#include "io/io.hpp"
|
||||||
#include "util/stringutil.hpp"
|
#include "util/stringutil.hpp"
|
||||||
#include "data/dv.hpp"
|
#include "data/dv.hpp"
|
||||||
@ -14,9 +13,12 @@ static debug::Logger logger("locale");
|
|||||||
|
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
using namespace std::literals;
|
using namespace std::literals;
|
||||||
|
using namespace langs;
|
||||||
|
|
||||||
std::unique_ptr<langs::Lang> langs::current;
|
namespace {
|
||||||
std::unordered_map<std::string, langs::LocaleInfo> langs::locales_info;
|
std::unique_ptr<langs::Lang> current;
|
||||||
|
std::unordered_map<std::string, LocaleInfo> locales_info;
|
||||||
|
}
|
||||||
|
|
||||||
langs::Lang::Lang(std::string locale) : locale(std::move(locale)) {
|
langs::Lang::Lang(std::string locale) : locale(std::move(locale)) {
|
||||||
}
|
}
|
||||||
@ -40,18 +42,10 @@ const std::string& langs::Lang::getId() const {
|
|||||||
/// @brief Language key-value txt files parser
|
/// @brief Language key-value txt files parser
|
||||||
namespace {
|
namespace {
|
||||||
class Reader : BasicParser<char> {
|
class Reader : BasicParser<char> {
|
||||||
void skipWhitespace() override {
|
|
||||||
BasicParser::skipWhitespace();
|
|
||||||
if (hasNext() && source[pos] == '#') {
|
|
||||||
skipLine();
|
|
||||||
if (hasNext() && is_whitespace(peek())) {
|
|
||||||
skipWhitespace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public:
|
public:
|
||||||
Reader(std::string_view file, std::string_view source)
|
Reader(std::string_view file, std::string_view source)
|
||||||
: BasicParser(file, source) {
|
: BasicParser(file, source) {
|
||||||
|
hashComment = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void read(langs::Lang& lang, const std::string &prefix) {
|
void read(langs::Lang& lang, const std::string &prefix) {
|
||||||
@ -69,11 +63,11 @@ namespace {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void langs::loadLocalesInfo(const io::path& resdir, std::string& fallback) {
|
static void load_locales_info(std::string& fallback) {
|
||||||
auto file = resdir / langs::TEXTS_FOLDER / "langs.json";
|
auto file = io::path("res:") / langs::TEXTS_FOLDER / "langs.json";
|
||||||
auto root = io::read_json(file);
|
auto root = io::read_json(file);
|
||||||
|
|
||||||
langs::locales_info.clear();
|
::locales_info.clear();
|
||||||
root.at("fallback").get(fallback);
|
root.at("fallback").get(fallback);
|
||||||
|
|
||||||
if (auto found = root.at("langs")) {
|
if (auto found = root.at("langs")) {
|
||||||
@ -88,16 +82,62 @@ void langs::loadLocalesInfo(const io::path& resdir, std::string& fallback) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
logline << key << " ";
|
logline << key << " ";
|
||||||
langs::locales_info[key] = LocaleInfo {key, name};
|
::locales_info[key] = LocaleInfo {key, name};
|
||||||
}
|
}
|
||||||
logline << "added";
|
logline << "added";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string langs::locale_by_envlocale(const std::string& envlocale, const io::path& resdir){
|
static void load(
|
||||||
|
const std::string& locale,
|
||||||
|
const std::vector<io::path>& roots,
|
||||||
|
Lang& lang
|
||||||
|
) {
|
||||||
|
io::path filename = io::path(TEXTS_FOLDER) / (locale + LANG_FILE_EXT);
|
||||||
|
io::path core_file = io::path("res:") / filename;
|
||||||
|
|
||||||
|
if (io::is_regular_file(core_file)) {
|
||||||
|
std::string text = io::read_string(core_file);
|
||||||
|
Reader reader(core_file.string(), text);
|
||||||
|
reader.read(lang, "");
|
||||||
|
}
|
||||||
|
for (auto root : roots) {
|
||||||
|
io::path file = root / filename;
|
||||||
|
if (io::is_regular_file(file)) {
|
||||||
|
std::string text = io::read_string(file);
|
||||||
|
Reader reader(file.string(), text);
|
||||||
|
reader.read(lang, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static void load(
|
||||||
|
const std::string& locale,
|
||||||
|
const std::string& fallback,
|
||||||
|
const std::vector<io::path>& roots
|
||||||
|
) {
|
||||||
|
auto lang = std::make_unique<Lang>(locale);
|
||||||
|
load(fallback, roots, *lang.get());
|
||||||
|
if (locale != fallback) {
|
||||||
|
load(locale, roots, *lang.get());
|
||||||
|
}
|
||||||
|
current = std::move(lang);
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& langs::get_current() {
|
||||||
|
if (current == nullptr) {
|
||||||
|
throw std::runtime_error("localization is not initialized");
|
||||||
|
}
|
||||||
|
return current->getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::unordered_map<std::string, LocaleInfo>& langs::get_locales_info() {
|
||||||
|
return ::locales_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string langs::locale_by_envlocale(const std::string& envlocale){
|
||||||
std::string fallback = FALLBACK_DEFAULT;
|
std::string fallback = FALLBACK_DEFAULT;
|
||||||
if (locales_info.size() == 0) {
|
if (locales_info.size() == 0) {
|
||||||
loadLocalesInfo(resdir, fallback);
|
load_locales_info(fallback);
|
||||||
}
|
}
|
||||||
if (locales_info.find(envlocale) != locales_info.end()) {
|
if (locales_info.find(envlocale) != locales_info.end()) {
|
||||||
logger.info() << "locale " << envlocale << " is automatically selected";
|
logger.info() << "locale " << envlocale << " is automatically selected";
|
||||||
@ -115,49 +155,16 @@ std::string langs::locale_by_envlocale(const std::string& envlocale, const io::p
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void langs::load(const io::path& resdir,
|
void langs::setup(
|
||||||
const std::string& locale,
|
|
||||||
const std::vector<ContentPack>& packs,
|
|
||||||
Lang& lang) {
|
|
||||||
io::path filename = io::path(TEXTS_FOLDER) / (locale + LANG_FILE_EXT);
|
|
||||||
io::path core_file = resdir / filename;
|
|
||||||
|
|
||||||
if (io::is_regular_file(core_file)) {
|
|
||||||
std::string text = io::read_string(core_file);
|
|
||||||
Reader reader(core_file.string(), text);
|
|
||||||
reader.read(lang, "");
|
|
||||||
}
|
|
||||||
for (auto pack : packs) {
|
|
||||||
io::path file = pack.folder / filename;
|
|
||||||
if (io::is_regular_file(file)) {
|
|
||||||
std::string text = io::read_string(file);
|
|
||||||
Reader reader(file.string(), text);
|
|
||||||
reader.read(lang, "");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void langs::load(const io::path& resdir,
|
|
||||||
const std::string& locale,
|
|
||||||
const std::string& fallback,
|
|
||||||
const std::vector<ContentPack>& packs) {
|
|
||||||
auto lang = std::make_unique<Lang>(locale);
|
|
||||||
load(resdir, fallback, packs, *lang.get());
|
|
||||||
if (locale != fallback) {
|
|
||||||
load(resdir, locale, packs, *lang.get());
|
|
||||||
}
|
|
||||||
current = std::move(lang);
|
|
||||||
}
|
|
||||||
|
|
||||||
void langs::setup(const io::path& resdir,
|
|
||||||
std::string locale,
|
std::string locale,
|
||||||
const std::vector<ContentPack>& packs) {
|
const std::vector<io::path>& roots
|
||||||
|
) {
|
||||||
std::string fallback = langs::FALLBACK_DEFAULT;
|
std::string fallback = langs::FALLBACK_DEFAULT;
|
||||||
langs::loadLocalesInfo(resdir, fallback);
|
load_locales_info(fallback);
|
||||||
if (langs::locales_info.find(locale) == langs::locales_info.end()) {
|
if (locales_info.find(locale) == locales_info.end()) {
|
||||||
locale = fallback;
|
locale = fallback;
|
||||||
}
|
}
|
||||||
langs::load(resdir, locale, fallback, packs);
|
load(locale, fallback, roots);
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::wstring& langs::get(const std::wstring& key) {
|
const std::wstring& langs::get(const std::wstring& key) {
|
||||||
|
|||||||
@ -7,8 +7,6 @@
|
|||||||
|
|
||||||
#include "io/fwd.hpp"
|
#include "io/fwd.hpp"
|
||||||
|
|
||||||
struct ContentPack;
|
|
||||||
|
|
||||||
namespace langs {
|
namespace langs {
|
||||||
const char LANG_FILE_EXT[] = ".txt";
|
const char LANG_FILE_EXT[] = ".txt";
|
||||||
const char TEXTS_FOLDER[] = "texts";
|
const char TEXTS_FOLDER[] = "texts";
|
||||||
@ -41,30 +39,17 @@ namespace langs {
|
|||||||
std::string name;
|
std::string name;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern std::unique_ptr<Lang> current;
|
std::string locale_by_envlocale(const std::string& envlocale);
|
||||||
extern std::unordered_map<std::string, LocaleInfo> locales_info;
|
|
||||||
|
|
||||||
extern void loadLocalesInfo(
|
const std::string& get_current();
|
||||||
const io::path& resdir,
|
const std::unordered_map<std::string, LocaleInfo>& get_locales_info();
|
||||||
std::string& fallback);
|
|
||||||
|
|
||||||
extern std::string locale_by_envlocale(const std::string& envlocale,
|
const std::wstring& get(const std::wstring& key);
|
||||||
const io::path& resdir);
|
const std::wstring& get(
|
||||||
|
const std::wstring& key, const std::wstring& context
|
||||||
|
);
|
||||||
|
|
||||||
extern void load(const io::path& resdir,
|
/// @brief Change locale to specified
|
||||||
const std::string& locale,
|
/// @param locale isolanguage_ISOCOUNTRY (example: en_US)
|
||||||
const std::vector<ContentPack>& packs,
|
void setup(std::string locale, const std::vector<io::path>& roots);
|
||||||
Lang& lang);
|
|
||||||
extern void load(const io::path& resdir,
|
|
||||||
const std::string& locale,
|
|
||||||
const std::string& fallback,
|
|
||||||
const std::vector<ContentPack>& packs);
|
|
||||||
|
|
||||||
extern const std::wstring& get(const std::wstring& key);
|
|
||||||
extern const std::wstring& get(const std::wstring& key,
|
|
||||||
const std::wstring& context);
|
|
||||||
|
|
||||||
extern void setup(const io::path& resdir,
|
|
||||||
std::string locale,
|
|
||||||
const std::vector<ContentPack>& packs);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,82 +1,88 @@
|
|||||||
#include "menu.hpp"
|
#include "menu.hpp"
|
||||||
|
|
||||||
#include "locale.hpp"
|
|
||||||
#include "UiDocument.hpp"
|
|
||||||
#include "screens/MenuScreen.hpp"
|
|
||||||
|
|
||||||
#include "delegates.hpp"
|
|
||||||
#include "engine/Engine.hpp"
|
|
||||||
#include "data/dv.hpp"
|
|
||||||
#include "interfaces/Task.hpp"
|
|
||||||
#include "io/engine_paths.hpp"
|
|
||||||
#include "graphics/ui/elements/Menu.hpp"
|
|
||||||
#include "graphics/ui/gui_util.hpp"
|
|
||||||
#include "graphics/ui/GUI.hpp"
|
|
||||||
#include "logic/scripting/scripting.hpp"
|
|
||||||
#include "settings.hpp"
|
|
||||||
#include "coders/commons.hpp"
|
|
||||||
#include "util/stringutil.hpp"
|
|
||||||
#include "window/Window.hpp"
|
|
||||||
|
|
||||||
#include <filesystem>
|
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
namespace fs = std::filesystem;
|
#include "UiDocument.hpp"
|
||||||
|
#include "coders/commons.hpp"
|
||||||
|
#include "data/dv.hpp"
|
||||||
|
#include "delegates.hpp"
|
||||||
|
#include "engine/Engine.hpp"
|
||||||
|
#include "graphics/ui/GUI.hpp"
|
||||||
|
#include "graphics/ui/elements/Menu.hpp"
|
||||||
|
#include "graphics/ui/gui_util.hpp"
|
||||||
|
#include "interfaces/Task.hpp"
|
||||||
|
#include "io/engine_paths.hpp"
|
||||||
|
#include "locale.hpp"
|
||||||
|
#include "logic/scripting/scripting.hpp"
|
||||||
|
#include "screens/MenuScreen.hpp"
|
||||||
|
#include "settings.hpp"
|
||||||
|
#include "util/stringutil.hpp"
|
||||||
|
#include "assets/assetload_funcs.hpp"
|
||||||
|
#include "content/ContentPack.hpp"
|
||||||
|
|
||||||
using namespace gui;
|
using namespace gui;
|
||||||
|
|
||||||
void menus::create_version_label(Engine& engine) {
|
void menus::create_version_label(gui::GUI& gui) {
|
||||||
auto gui = engine.getGUI();
|
auto text = ENGINE_VERSION_STRING + " debug build";
|
||||||
auto text = ENGINE_VERSION_STRING+" debug build";
|
gui.add(guiutil::create(
|
||||||
gui->add(guiutil::create(
|
gui,
|
||||||
"<label z-index='1000' color='#FFFFFF80' gravity='top-right' margin='4'>"
|
"<label z-index='1000' color='#FFFFFF80' gravity='top-right' "
|
||||||
+text+
|
"margin='4'>" +
|
||||||
"</label>"
|
text + "</label>"
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool menus::call(Engine& engine, runnable func) {
|
void menus::call(Engine& engine, runnable func) {
|
||||||
if (engine.isHeadless()) {
|
if (engine.isHeadless()) {
|
||||||
throw std::runtime_error("menus::call(...) in headless mode");
|
throw std::runtime_error("menus::call(...) in headless mode");
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
func();
|
func();
|
||||||
return true;
|
|
||||||
} catch (const contentpack_error& error) {
|
} catch (const contentpack_error& error) {
|
||||||
engine.setScreen(std::make_shared<MenuScreen>(engine));
|
engine.setScreen(std::make_shared<MenuScreen>(engine));
|
||||||
// could not to find or read pack
|
// could not to find or read pack
|
||||||
guiutil::alert(
|
guiutil::alert(
|
||||||
engine, langs::get(L"error.pack-not-found")+L": "+
|
engine,
|
||||||
|
langs::get(L"error.pack-not-found") + L": " +
|
||||||
util::str2wstr_utf8(error.getPackId())
|
util::str2wstr_utf8(error.getPackId())
|
||||||
);
|
);
|
||||||
return false;
|
throw std::runtime_error(error);
|
||||||
} catch (const assetload::error& error) {
|
} catch (const assetload::error& error) {
|
||||||
engine.setScreen(std::make_shared<MenuScreen>(engine));
|
engine.setScreen(std::make_shared<MenuScreen>(engine));
|
||||||
guiutil::alert(
|
guiutil::alert(
|
||||||
engine, langs::get(L"Assets Load Error", L"menu")+L":\n"+
|
engine,
|
||||||
|
langs::get(L"Assets Load Error", L"menu") + L":\n" +
|
||||||
util::str2wstr_utf8(error.what())
|
util::str2wstr_utf8(error.what())
|
||||||
);
|
);
|
||||||
return false;
|
throw std::runtime_error(error);
|
||||||
} catch (const parsing_error& error) {
|
} catch (const parsing_error& error) {
|
||||||
engine.setScreen(std::make_shared<MenuScreen>(engine));
|
engine.setScreen(std::make_shared<MenuScreen>(engine));
|
||||||
guiutil::alert(engine, util::str2wstr_utf8(error.errorLog()));
|
guiutil::alert(engine, util::str2wstr_utf8(error.errorLog()));
|
||||||
return false;
|
throw std::runtime_error(error);
|
||||||
} catch (const std::runtime_error& error) {
|
} catch (const std::runtime_error& error) {
|
||||||
engine.setScreen(std::make_shared<MenuScreen>(engine));
|
engine.setScreen(std::make_shared<MenuScreen>(engine));
|
||||||
guiutil::alert(
|
guiutil::alert(
|
||||||
engine, langs::get(L"Content Error", L"menu")+L":\n"+
|
engine,
|
||||||
|
langs::get(L"Content Error", L"menu") + L":\n" +
|
||||||
util::str2wstr_utf8(error.what())
|
util::str2wstr_utf8(error.what())
|
||||||
);
|
);
|
||||||
return false;
|
throw std::runtime_error(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UiDocument* menus::show(Engine& engine, const std::string& name, std::vector<dv::value> args) {
|
UiDocument* menus::show(
|
||||||
auto menu = engine.getGUI()->getMenu();
|
Engine& engine, const std::string& name, std::vector<dv::value> args
|
||||||
auto file = engine.getResPaths()->find("layouts/"+name+".xml");
|
) {
|
||||||
auto fullname = "core:layouts/"+name;
|
auto menu = engine.getGUI().getMenu();
|
||||||
|
auto file = engine.getResPaths().find("layouts/" + name + ".xml");
|
||||||
|
auto fullname = "core:layouts/" + name;
|
||||||
|
|
||||||
auto documentPtr = UiDocument::read(
|
auto documentPtr = UiDocument::read(
|
||||||
scripting::get_root_environment(), fullname, file, "core:layouts/"+name
|
engine.getGUI(),
|
||||||
|
scripting::get_root_environment(),
|
||||||
|
fullname,
|
||||||
|
file,
|
||||||
|
"core:layouts/" + name
|
||||||
);
|
);
|
||||||
auto document = documentPtr.get();
|
auto document = documentPtr.get();
|
||||||
engine.getAssets()->store(std::move(documentPtr), fullname);
|
engine.getAssets()->store(std::move(documentPtr), fullname);
|
||||||
@ -86,15 +92,17 @@ UiDocument* menus::show(Engine& engine, const std::string& name, std::vector<dv:
|
|||||||
return document;
|
return document;
|
||||||
}
|
}
|
||||||
|
|
||||||
void menus::show_process_panel(Engine& engine, const std::shared_ptr<Task>& task, const std::wstring& text) {
|
void menus::show_process_panel(
|
||||||
|
Engine& engine, const std::shared_ptr<Task>& task, const std::wstring& text
|
||||||
|
) {
|
||||||
uint initialWork = task->getWorkTotal();
|
uint initialWork = task->getWorkTotal();
|
||||||
|
|
||||||
auto menu = engine.getGUI()->getMenu();
|
auto menu = engine.getGUI().getMenu();
|
||||||
menu->reset();
|
menu->reset();
|
||||||
auto doc = menus::show(engine, "process", {
|
auto doc =
|
||||||
util::wstr2str_utf8(langs::get(text))
|
menus::show(engine, "process", {util::wstr2str_utf8(langs::get(text))});
|
||||||
});
|
std::dynamic_pointer_cast<Container>(doc->getRoot())
|
||||||
std::dynamic_pointer_cast<Container>(doc->getRoot())->listenInterval(0.01f, [=]() {
|
->listenInterval(0.01f, [=]() {
|
||||||
task->update();
|
task->update();
|
||||||
|
|
||||||
uint tasksDone = task->getWorkDone();
|
uint tasksDone = task->getWorkDone();
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "data/dv.hpp"
|
#include "data/dv.hpp"
|
||||||
#include "graphics/ui/elements/Menu.hpp"
|
#include "delegates.hpp"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -12,9 +12,13 @@ class Engine;
|
|||||||
|
|
||||||
class UiDocument;
|
class UiDocument;
|
||||||
|
|
||||||
|
namespace gui {
|
||||||
|
class GUI;
|
||||||
|
}
|
||||||
|
|
||||||
namespace menus {
|
namespace menus {
|
||||||
/// @brief Create development version label at the top-right screen corner
|
/// @brief Create development version label at the top-right screen corner
|
||||||
void create_version_label(Engine& engine);
|
void create_version_label(gui::GUI& gui);
|
||||||
|
|
||||||
UiDocument* show(
|
UiDocument* show(
|
||||||
Engine& engine,
|
Engine& engine,
|
||||||
@ -22,7 +26,11 @@ namespace menus {
|
|||||||
std::vector<dv::value> args
|
std::vector<dv::value> args
|
||||||
);
|
);
|
||||||
|
|
||||||
void show_process_panel(Engine& engine, const std::shared_ptr<Task>& task, const std::wstring& text=L"");
|
void show_process_panel(
|
||||||
|
Engine& engine,
|
||||||
|
const std::shared_ptr<Task>& task,
|
||||||
|
const std::wstring& text = L""
|
||||||
|
);
|
||||||
|
|
||||||
bool call(Engine& engine, runnable func);
|
void call(Engine& engine, runnable func);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,19 +6,19 @@
|
|||||||
#include "core_defs.hpp"
|
#include "core_defs.hpp"
|
||||||
#include "debug/Logger.hpp"
|
#include "debug/Logger.hpp"
|
||||||
#include "engine/Engine.hpp"
|
#include "engine/Engine.hpp"
|
||||||
#include "io/io.hpp"
|
#include "assets/Assets.hpp"
|
||||||
|
#include "frontend/ContentGfxCache.hpp"
|
||||||
#include "frontend/LevelFrontend.hpp"
|
#include "frontend/LevelFrontend.hpp"
|
||||||
#include "frontend/hud.hpp"
|
#include "frontend/hud.hpp"
|
||||||
#include "graphics/core/DrawContext.hpp"
|
#include "graphics/core/DrawContext.hpp"
|
||||||
#include "graphics/core/ImageData.hpp"
|
#include "graphics/core/ImageData.hpp"
|
||||||
#include "graphics/core/PostProcessing.hpp"
|
#include "graphics/core/PostProcessing.hpp"
|
||||||
#include "graphics/core/Viewport.hpp"
|
|
||||||
#include "graphics/render/Decorator.hpp"
|
#include "graphics/render/Decorator.hpp"
|
||||||
#include "graphics/render/WorldRenderer.hpp"
|
#include "graphics/render/WorldRenderer.hpp"
|
||||||
#include "graphics/ui/GUI.hpp"
|
#include "graphics/ui/GUI.hpp"
|
||||||
#include "graphics/ui/elements/Menu.hpp"
|
#include "graphics/ui/elements/Menu.hpp"
|
||||||
#include "graphics/ui/GUI.hpp"
|
#include "graphics/core/TextureAnimation.hpp"
|
||||||
#include "frontend/ContentGfxCache.hpp"
|
#include "io/io.hpp"
|
||||||
#include "logic/LevelController.hpp"
|
#include "logic/LevelController.hpp"
|
||||||
#include "logic/PlayerController.hpp"
|
#include "logic/PlayerController.hpp"
|
||||||
#include "logic/scripting/scripting.hpp"
|
#include "logic/scripting/scripting.hpp"
|
||||||
@ -29,7 +29,6 @@
|
|||||||
#include "util/stringutil.hpp"
|
#include "util/stringutil.hpp"
|
||||||
#include "voxels/Chunks.hpp"
|
#include "voxels/Chunks.hpp"
|
||||||
#include "window/Camera.hpp"
|
#include "window/Camera.hpp"
|
||||||
#include "window/Events.hpp"
|
|
||||||
#include "window/Window.hpp"
|
#include "window/Window.hpp"
|
||||||
#include "world/Level.hpp"
|
#include "world/Level.hpp"
|
||||||
#include "world/World.hpp"
|
#include "world/World.hpp"
|
||||||
@ -43,12 +42,14 @@ LevelScreen::LevelScreen(
|
|||||||
)
|
)
|
||||||
: Screen(engine),
|
: Screen(engine),
|
||||||
world(*levelPtr->getWorld()),
|
world(*levelPtr->getWorld()),
|
||||||
postProcessing(std::make_unique<PostProcessing>()) {
|
postProcessing(std::make_unique<PostProcessing>()),
|
||||||
|
gui(engine.getGUI()),
|
||||||
|
input(engine.getInput()) {
|
||||||
Level* level = levelPtr.get();
|
Level* level = levelPtr.get();
|
||||||
|
|
||||||
auto& settings = engine.getSettings();
|
auto& settings = engine.getSettings();
|
||||||
auto& assets = *engine.getAssets();
|
auto& assets = *engine.getAssets();
|
||||||
auto menu = engine.getGUI()->getMenu();
|
auto menu = engine.getGUI().getMenu();
|
||||||
menu->reset();
|
menu->reset();
|
||||||
|
|
||||||
auto player = level->players->get(localPlayer);
|
auto player = level->players->get(localPlayer);
|
||||||
@ -57,14 +58,11 @@ LevelScreen::LevelScreen(
|
|||||||
controller =
|
controller =
|
||||||
std::make_unique<LevelController>(&engine, std::move(levelPtr), player);
|
std::make_unique<LevelController>(&engine, std::move(levelPtr), player);
|
||||||
playerController = std::make_unique<PlayerController>(
|
playerController = std::make_unique<PlayerController>(
|
||||||
settings,
|
settings, *level, *player, *controller->getBlocksController()
|
||||||
*level,
|
|
||||||
*player,
|
|
||||||
*controller->getBlocksController()
|
|
||||||
);
|
);
|
||||||
|
|
||||||
frontend = std::make_unique<LevelFrontend>(
|
frontend = std::make_unique<LevelFrontend>(
|
||||||
player, controller.get(), assets, settings
|
engine, player, controller.get(), settings
|
||||||
);
|
);
|
||||||
renderer = std::make_unique<WorldRenderer>(
|
renderer = std::make_unique<WorldRenderer>(
|
||||||
engine, *frontend, *player
|
engine, *frontend, *player
|
||||||
@ -87,7 +85,7 @@ LevelScreen::LevelScreen(
|
|||||||
keepAlive(settings.camera.fov.observe([=](double value) {
|
keepAlive(settings.camera.fov.observe([=](double value) {
|
||||||
player->fpCamera->setFov(glm::radians(value));
|
player->fpCamera->setFov(glm::radians(value));
|
||||||
}));
|
}));
|
||||||
keepAlive(Events::getBinding(BIND_CHUNKS_RELOAD).onactived.add([=](){
|
keepAlive(input.addCallback(BIND_CHUNKS_RELOAD, [=]() {
|
||||||
player->chunks->saveAndClear();
|
player->chunks->saveAndClear();
|
||||||
renderer->clear();
|
renderer->clear();
|
||||||
return false;
|
return false;
|
||||||
@ -107,7 +105,7 @@ LevelScreen::~LevelScreen() {
|
|||||||
}
|
}
|
||||||
scripting::on_frontend_close();
|
scripting::on_frontend_close();
|
||||||
// unblock all bindings
|
// unblock all bindings
|
||||||
Events::enableBindings();
|
input.getBindings().enableAll();
|
||||||
controller->onWorldQuit();
|
controller->onWorldQuit();
|
||||||
engine.getPaths().setCurrentWorldFolder("");
|
engine.getPaths().setCurrentWorldFolder("");
|
||||||
}
|
}
|
||||||
@ -162,10 +160,13 @@ void LevelScreen::saveWorldPreview() {
|
|||||||
Camera camera = *player->fpCamera;
|
Camera camera = *player->fpCamera;
|
||||||
camera.setFov(glm::radians(70.0f));
|
camera.setFov(glm::radians(70.0f));
|
||||||
|
|
||||||
DrawContext pctx(nullptr, {Window::width, Window::height}, batch.get());
|
DrawContext pctx(nullptr, engine.getWindow(), batch.get());
|
||||||
|
|
||||||
Viewport viewport(previewSize * 1.5, previewSize);
|
DrawContext ctx(&pctx, engine.getWindow(), batch.get());
|
||||||
DrawContext ctx(&pctx, viewport, batch.get());
|
ctx.setViewport(
|
||||||
|
{static_cast<uint>(previewSize * 1.5),
|
||||||
|
static_cast<uint>(previewSize)}
|
||||||
|
);
|
||||||
|
|
||||||
renderer->draw(ctx, camera, false, true, 0.0f, *postProcessing);
|
renderer->draw(ctx, camera, false, true, 0.0f, *postProcessing);
|
||||||
auto image = postProcessing->toImage();
|
auto image = postProcessing->toImage();
|
||||||
@ -178,13 +179,14 @@ void LevelScreen::saveWorldPreview() {
|
|||||||
|
|
||||||
void LevelScreen::updateHotkeys() {
|
void LevelScreen::updateHotkeys() {
|
||||||
auto& settings = engine.getSettings();
|
auto& settings = engine.getSettings();
|
||||||
if (Events::jpressed(keycode::O)) {
|
|
||||||
|
if (input.jpressed(Keycode::O)) {
|
||||||
settings.graphics.frustumCulling.toggle();
|
settings.graphics.frustumCulling.toggle();
|
||||||
}
|
}
|
||||||
if (Events::jpressed(keycode::F1)) {
|
if (input.jpressed(Keycode::F1)) {
|
||||||
hudVisible = !hudVisible;
|
hudVisible = !hudVisible;
|
||||||
}
|
}
|
||||||
if (Events::jpressed(keycode::F3)) {
|
if (input.jpressed(Keycode::F3)) {
|
||||||
debug = !debug;
|
debug = !debug;
|
||||||
hud->setDebug(debug);
|
hud->setDebug(debug);
|
||||||
renderer->setDebug(debug);
|
renderer->setDebug(debug);
|
||||||
@ -203,15 +205,12 @@ void LevelScreen::updateAudio() {
|
|||||||
velocity = hitbox->velocity;
|
velocity = hitbox->velocity;
|
||||||
}
|
}
|
||||||
audio::set_listener(
|
audio::set_listener(
|
||||||
camera->position,
|
camera->position, velocity, camera->dir, glm::vec3(0, 1, 0)
|
||||||
velocity,
|
|
||||||
camera->dir,
|
|
||||||
glm::vec3(0, 1, 0)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LevelScreen::update(float delta) {
|
void LevelScreen::update(float delta) {
|
||||||
auto& gui = *engine.getGUI();
|
auto& gui = engine.getGUI();
|
||||||
|
|
||||||
if (!gui.isFocusCaught()) {
|
if (!gui.isFocusCaught()) {
|
||||||
updateHotkeys();
|
updateHotkeys();
|
||||||
@ -225,10 +224,15 @@ void LevelScreen::update(float delta) {
|
|||||||
if (!paused) {
|
if (!paused) {
|
||||||
world.updateTimers(delta);
|
world.updateTimers(delta);
|
||||||
animator->update(delta);
|
animator->update(delta);
|
||||||
playerController->update(delta, !inputLocked);
|
playerController->update(delta, inputLocked ? nullptr : &engine.getInput());
|
||||||
}
|
}
|
||||||
controller->update(glm::min(delta, 0.2f), paused);
|
controller->update(glm::min(delta, 0.2f), paused);
|
||||||
playerController->postUpdate(delta, !inputLocked, paused);
|
playerController->postUpdate(
|
||||||
|
delta,
|
||||||
|
engine.getWindow().getSize().y,
|
||||||
|
inputLocked ? nullptr : &engine.getInput(),
|
||||||
|
paused
|
||||||
|
);
|
||||||
|
|
||||||
hud->update(hudVisible);
|
hud->update(hudVisible);
|
||||||
|
|
||||||
@ -241,8 +245,7 @@ void LevelScreen::update(float delta) {
|
|||||||
void LevelScreen::draw(float delta) {
|
void LevelScreen::draw(float delta) {
|
||||||
auto camera = playerController->getPlayer()->currentCamera;
|
auto camera = playerController->getPlayer()->currentCamera;
|
||||||
|
|
||||||
Viewport viewport(Window::width, Window::height);
|
DrawContext ctx(nullptr, engine.getWindow(), batch.get());
|
||||||
DrawContext ctx(nullptr, viewport, batch.get());
|
|
||||||
|
|
||||||
if (!hud->isPause()) {
|
if (!hud->isPause()) {
|
||||||
scripting::on_entities_render(engine.getTime().getDelta());
|
scripting::on_entities_render(engine.getTime().getDelta());
|
||||||
|
|||||||
@ -16,6 +16,11 @@ class ContentPackRuntime;
|
|||||||
class Decorator;
|
class Decorator;
|
||||||
class Level;
|
class Level;
|
||||||
class World;
|
class World;
|
||||||
|
class Input;
|
||||||
|
|
||||||
|
namespace gui {
|
||||||
|
class GUI;
|
||||||
|
}
|
||||||
|
|
||||||
class LevelScreen : public Screen {
|
class LevelScreen : public Screen {
|
||||||
World& world;
|
World& world;
|
||||||
@ -27,6 +32,8 @@ class LevelScreen : public Screen {
|
|||||||
std::unique_ptr<PostProcessing> postProcessing;
|
std::unique_ptr<PostProcessing> postProcessing;
|
||||||
std::unique_ptr<Decorator> decorator;
|
std::unique_ptr<Decorator> decorator;
|
||||||
std::unique_ptr<Hud> hud;
|
std::unique_ptr<Hud> hud;
|
||||||
|
gui::GUI& gui;
|
||||||
|
Input& input;
|
||||||
|
|
||||||
void saveWorldPreview();
|
void saveWorldPreview();
|
||||||
|
|
||||||
|
|||||||
@ -1,29 +1,31 @@
|
|||||||
#include "MenuScreen.hpp"
|
#include "MenuScreen.hpp"
|
||||||
|
|
||||||
|
#include "content/ContentControl.hpp"
|
||||||
#include "graphics/ui/GUI.hpp"
|
#include "graphics/ui/GUI.hpp"
|
||||||
#include "graphics/ui/elements/Menu.hpp"
|
#include "graphics/ui/elements/Menu.hpp"
|
||||||
#include "graphics/core/Batch2D.hpp"
|
#include "graphics/core/Batch2D.hpp"
|
||||||
#include "graphics/core/Shader.hpp"
|
#include "graphics/core/Shader.hpp"
|
||||||
#include "graphics/core/Texture.hpp"
|
#include "graphics/core/Texture.hpp"
|
||||||
|
#include "assets/Assets.hpp"
|
||||||
#include "maths/UVRegion.hpp"
|
#include "maths/UVRegion.hpp"
|
||||||
#include "window/Window.hpp"
|
#include "window/Window.hpp"
|
||||||
#include "window/Camera.hpp"
|
#include "window/Camera.hpp"
|
||||||
#include "engine/Engine.hpp"
|
#include "engine/Engine.hpp"
|
||||||
|
|
||||||
MenuScreen::MenuScreen(Engine& engine) : Screen(engine) {
|
MenuScreen::MenuScreen(Engine& engine) : Screen(engine) {
|
||||||
engine.resetContent();
|
engine.getContentControl().resetContent();
|
||||||
|
|
||||||
auto menu = engine.getGUI()->getMenu();
|
auto menu = engine.getGUI().getMenu();
|
||||||
menu->reset();
|
menu->reset();
|
||||||
menu->setPage("main");
|
menu->setPage("main");
|
||||||
|
|
||||||
uicamera = std::make_unique<Camera>(glm::vec3(), Window::height);
|
uicamera =
|
||||||
|
std::make_unique<Camera>(glm::vec3(), engine.getWindow().getSize().y);
|
||||||
uicamera->perspective = false;
|
uicamera->perspective = false;
|
||||||
uicamera->flipped = true;
|
uicamera->flipped = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
MenuScreen::~MenuScreen() {
|
MenuScreen::~MenuScreen() = default;
|
||||||
}
|
|
||||||
|
|
||||||
void MenuScreen::update(float delta) {
|
void MenuScreen::update(float delta) {
|
||||||
}
|
}
|
||||||
@ -31,24 +33,26 @@ void MenuScreen::update(float delta) {
|
|||||||
void MenuScreen::draw(float delta) {
|
void MenuScreen::draw(float delta) {
|
||||||
auto assets = engine.getAssets();
|
auto assets = engine.getAssets();
|
||||||
|
|
||||||
Window::clear();
|
display::clear();
|
||||||
Window::setBgColor(glm::vec3(0.2f));
|
display::setBgColor(glm::vec3(0.2f));
|
||||||
|
|
||||||
uicamera->setFov(Window::height);
|
const auto& size = engine.getWindow().getSize();
|
||||||
|
uint width = size.x;
|
||||||
|
uint height = size.y;
|
||||||
|
|
||||||
|
uicamera->setFov(height);
|
||||||
|
uicamera->setAspectRatio(width / static_cast<float>(height));
|
||||||
auto uishader = assets->get<Shader>("ui");
|
auto uishader = assets->get<Shader>("ui");
|
||||||
uishader->use();
|
uishader->use();
|
||||||
uishader->uniformMatrix("u_projview", uicamera->getProjView());
|
uishader->uniformMatrix("u_projview", uicamera->getProjView());
|
||||||
|
|
||||||
uint width = Window::width;
|
|
||||||
uint height = Window::height;
|
|
||||||
|
|
||||||
auto bg = assets->get<Texture>("gui/menubg");
|
auto bg = assets->get<Texture>("gui/menubg");
|
||||||
batch->begin();
|
batch->begin();
|
||||||
batch->texture(bg);
|
batch->texture(bg);
|
||||||
batch->rect(
|
batch->rect(
|
||||||
0, 0,
|
0, 0,
|
||||||
width, height, 0, 0, 0,
|
width, height, 0, 0, 0,
|
||||||
UVRegion(0, 0, width/bg->getWidth(), height/bg->getHeight()),
|
UVRegion(0, 0, width / bg->getWidth(), height / bg->getHeight()),
|
||||||
false, false, glm::vec4(1.0f)
|
false, false, glm::vec4(1.0f)
|
||||||
);
|
);
|
||||||
batch->flush();
|
batch->flush();
|
||||||
|
|||||||
@ -25,10 +25,11 @@ static void set_blend_mode(BlendMode mode) {
|
|||||||
|
|
||||||
DrawContext::DrawContext(
|
DrawContext::DrawContext(
|
||||||
const DrawContext* parent,
|
const DrawContext* parent,
|
||||||
Viewport viewport,
|
Window& window,
|
||||||
Batch2D* g2d
|
Batch2D* g2d
|
||||||
) : parent(parent),
|
) : window(window),
|
||||||
viewport(std::move(viewport)),
|
parent(parent),
|
||||||
|
viewport(window.getSize()),
|
||||||
g2d(g2d),
|
g2d(g2d),
|
||||||
flushable(g2d)
|
flushable(g2d)
|
||||||
{}
|
{}
|
||||||
@ -39,7 +40,7 @@ DrawContext::~DrawContext() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
while (scissorsCount--) {
|
while (scissorsCount--) {
|
||||||
Window::popScissor();
|
window.popScissor();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parent == nullptr)
|
if (parent == nullptr)
|
||||||
@ -54,11 +55,7 @@ DrawContext::~DrawContext() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Window::viewport(
|
glViewport(0, 0, parent->viewport.x, parent->viewport.y);
|
||||||
0, 0,
|
|
||||||
parent->viewport.getWidth(),
|
|
||||||
parent->viewport.getHeight()
|
|
||||||
);
|
|
||||||
|
|
||||||
if (depthMask != parent->depthMask) {
|
if (depthMask != parent->depthMask) {
|
||||||
glDepthMask(parent->depthMask);
|
glDepthMask(parent->depthMask);
|
||||||
@ -79,7 +76,7 @@ DrawContext::~DrawContext() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const Viewport& DrawContext::getViewport() const {
|
const glm::uvec2& DrawContext::getViewport() const {
|
||||||
return viewport;
|
return viewport;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,13 +95,9 @@ DrawContext DrawContext::sub(Flushable* flushable) const {
|
|||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawContext::setViewport(const Viewport& viewport) {
|
void DrawContext::setViewport(const glm::uvec2& viewport) {
|
||||||
this->viewport = viewport;
|
this->viewport = viewport;
|
||||||
Window::viewport(
|
glViewport(0, 0, viewport.x, viewport.y);
|
||||||
0, 0,
|
|
||||||
viewport.getWidth(),
|
|
||||||
viewport.getHeight()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawContext::setFramebuffer(Framebuffer* fbo) {
|
void DrawContext::setFramebuffer(Framebuffer* fbo) {
|
||||||
@ -153,7 +146,7 @@ void DrawContext::setBlendMode(BlendMode mode) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DrawContext::setScissors(const glm::vec4& area) {
|
void DrawContext::setScissors(const glm::vec4& area) {
|
||||||
Window::pushScissor(area);
|
window.pushScissor(area);
|
||||||
scissorsCount++;
|
scissorsCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,15 +1,19 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <glm/vec2.hpp>
|
||||||
|
#include <glm/vec4.hpp>
|
||||||
|
|
||||||
#include "commons.hpp"
|
#include "commons.hpp"
|
||||||
#include "Viewport.hpp"
|
|
||||||
#include "typedefs.hpp"
|
#include "typedefs.hpp"
|
||||||
|
|
||||||
|
class Window;
|
||||||
class Batch2D;
|
class Batch2D;
|
||||||
class Framebuffer;
|
class Framebuffer;
|
||||||
|
|
||||||
class DrawContext {
|
class DrawContext {
|
||||||
|
Window& window;
|
||||||
const DrawContext* parent;
|
const DrawContext* parent;
|
||||||
Viewport viewport;
|
glm::uvec2 viewport;
|
||||||
Batch2D* g2d;
|
Batch2D* g2d;
|
||||||
Flushable* flushable = nullptr;
|
Flushable* flushable = nullptr;
|
||||||
Framebuffer* fbo = nullptr;
|
Framebuffer* fbo = nullptr;
|
||||||
@ -20,15 +24,19 @@ class DrawContext {
|
|||||||
int scissorsCount = 0;
|
int scissorsCount = 0;
|
||||||
float lineWidth = 1.0f;
|
float lineWidth = 1.0f;
|
||||||
public:
|
public:
|
||||||
DrawContext(const DrawContext* parent, Viewport viewport, Batch2D* g2d);
|
DrawContext(
|
||||||
|
const DrawContext* parent,
|
||||||
|
Window& window,
|
||||||
|
Batch2D* g2d
|
||||||
|
);
|
||||||
~DrawContext();
|
~DrawContext();
|
||||||
|
|
||||||
Batch2D* getBatch2D() const;
|
Batch2D* getBatch2D() const;
|
||||||
|
|
||||||
const Viewport& getViewport() const;
|
const glm::uvec2& getViewport() const;
|
||||||
DrawContext sub(Flushable* flushable=nullptr) const;
|
DrawContext sub(Flushable* flushable=nullptr) const;
|
||||||
|
|
||||||
void setViewport(const Viewport& viewport);
|
void setViewport(const glm::uvec2& viewport);
|
||||||
void setFramebuffer(Framebuffer* fbo);
|
void setFramebuffer(Framebuffer* fbo);
|
||||||
void setDepthMask(bool flag);
|
void setDepthMask(bool flag);
|
||||||
void setDepthTest(bool flag);
|
void setDepthTest(bool flag);
|
||||||
|
|||||||
@ -3,7 +3,6 @@
|
|||||||
#include "Shader.hpp"
|
#include "Shader.hpp"
|
||||||
#include "Texture.hpp"
|
#include "Texture.hpp"
|
||||||
#include "Framebuffer.hpp"
|
#include "Framebuffer.hpp"
|
||||||
#include "Viewport.hpp"
|
|
||||||
#include "DrawContext.hpp"
|
#include "DrawContext.hpp"
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
@ -23,9 +22,9 @@ PostProcessing::~PostProcessing() = default;
|
|||||||
void PostProcessing::use(DrawContext& context) {
|
void PostProcessing::use(DrawContext& context) {
|
||||||
const auto& vp = context.getViewport();
|
const auto& vp = context.getViewport();
|
||||||
if (fbo) {
|
if (fbo) {
|
||||||
fbo->resize(vp.getWidth(), vp.getHeight());
|
fbo->resize(vp.x, vp.y);
|
||||||
} else {
|
} else {
|
||||||
fbo = std::make_unique<Framebuffer>(vp.getWidth(), vp.getHeight());
|
fbo = std::make_unique<Framebuffer>(vp.x, vp.y);
|
||||||
}
|
}
|
||||||
context.setFramebuffer(fbo.get());
|
context.setFramebuffer(fbo.get());
|
||||||
}
|
}
|
||||||
@ -37,7 +36,7 @@ void PostProcessing::render(const DrawContext& context, Shader* screenShader) {
|
|||||||
|
|
||||||
const auto& viewport = context.getViewport();
|
const auto& viewport = context.getViewport();
|
||||||
screenShader->use();
|
screenShader->use();
|
||||||
screenShader->uniform2i("u_screenSize", viewport.size());
|
screenShader->uniform2i("u_screenSize", viewport);
|
||||||
fbo->getTexture()->bind();
|
fbo->getTexture()->bind();
|
||||||
quadMesh->draw();
|
quadMesh->draw();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,13 +0,0 @@
|
|||||||
#include "Viewport.hpp"
|
|
||||||
|
|
||||||
Viewport::Viewport(uint width, uint height)
|
|
||||||
: width(width), height(height) {
|
|
||||||
}
|
|
||||||
|
|
||||||
uint Viewport::getWidth() const {
|
|
||||||
return width;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint Viewport::getHeight() const {
|
|
||||||
return height;
|
|
||||||
}
|
|
||||||
@ -1,19 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
|
||||||
|
|
||||||
#include "typedefs.hpp"
|
|
||||||
|
|
||||||
class Viewport {
|
|
||||||
uint width;
|
|
||||||
uint height;
|
|
||||||
public:
|
|
||||||
Viewport(uint width, uint height);
|
|
||||||
|
|
||||||
virtual uint getWidth() const;
|
|
||||||
virtual uint getHeight() const;
|
|
||||||
|
|
||||||
glm::ivec2 size() const {
|
|
||||||
return glm::ivec2(width, height);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@ -11,7 +11,6 @@
|
|||||||
#include "objects/Player.hpp"
|
#include "objects/Player.hpp"
|
||||||
#include "voxels/Block.hpp"
|
#include "voxels/Block.hpp"
|
||||||
#include "voxels/Chunks.hpp"
|
#include "voxels/Chunks.hpp"
|
||||||
#include "window/Window.hpp"
|
|
||||||
#include "world/Level.hpp"
|
#include "world/Level.hpp"
|
||||||
|
|
||||||
BlockWrapsRenderer::BlockWrapsRenderer(
|
BlockWrapsRenderer::BlockWrapsRenderer(
|
||||||
|
|||||||
@ -13,7 +13,7 @@
|
|||||||
#include "graphics/core/DrawContext.hpp"
|
#include "graphics/core/DrawContext.hpp"
|
||||||
#include "graphics/core/Shader.hpp"
|
#include "graphics/core/Shader.hpp"
|
||||||
#include "graphics/core/Texture.hpp"
|
#include "graphics/core/Texture.hpp"
|
||||||
#include "graphics/core/Viewport.hpp"
|
#include "graphics/commons/Model.hpp"
|
||||||
|
|
||||||
#include <glm/ext.hpp>
|
#include <glm/ext.hpp>
|
||||||
|
|
||||||
@ -25,7 +25,7 @@ std::unique_ptr<ImageData> BlocksPreview::draw(
|
|||||||
const Block& def,
|
const Block& def,
|
||||||
int size
|
int size
|
||||||
){
|
){
|
||||||
Window::clear();
|
display::clear();
|
||||||
blockid_t id = def.rt.id;
|
blockid_t id = def.rt.id;
|
||||||
const UVRegion texfaces[6]{cache.getRegion(id, 0), cache.getRegion(id, 1),
|
const UVRegion texfaces[6]{cache.getRegion(id, 0), cache.getRegion(id, 1),
|
||||||
cache.getRegion(id, 2), cache.getRegion(id, 3),
|
cache.getRegion(id, 2), cache.getRegion(id, 3),
|
||||||
@ -97,6 +97,7 @@ std::unique_ptr<ImageData> BlocksPreview::draw(
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Atlas> BlocksPreview::build(
|
std::unique_ptr<Atlas> BlocksPreview::build(
|
||||||
|
Window& window,
|
||||||
const ContentGfxCache& cache,
|
const ContentGfxCache& cache,
|
||||||
const Assets& assets,
|
const Assets& assets,
|
||||||
const ContentIndices& indices
|
const ContentIndices& indices
|
||||||
@ -107,8 +108,7 @@ std::unique_ptr<Atlas> BlocksPreview::build(
|
|||||||
auto& shader = assets.require<Shader>("ui3d");
|
auto& shader = assets.require<Shader>("ui3d");
|
||||||
const auto& atlas = assets.require<Atlas>("blocks");
|
const auto& atlas = assets.require<Atlas>("blocks");
|
||||||
|
|
||||||
Viewport viewport(iconSize, iconSize);
|
DrawContext pctx(nullptr, window, nullptr);
|
||||||
DrawContext pctx(nullptr, viewport, nullptr);
|
|
||||||
DrawContext ctx = pctx.sub();
|
DrawContext ctx = pctx.sub();
|
||||||
ctx.setCullFace(true);
|
ctx.setCullFace(true);
|
||||||
ctx.setDepthTest(true);
|
ctx.setDepthTest(true);
|
||||||
@ -126,8 +126,8 @@ std::unique_ptr<Atlas> BlocksPreview::build(
|
|||||||
glm::vec3(0, 1, 0)));
|
glm::vec3(0, 1, 0)));
|
||||||
|
|
||||||
AtlasBuilder builder;
|
AtlasBuilder builder;
|
||||||
Window::viewport(0, 0, iconSize, iconSize);
|
ctx.setViewport({iconSize, iconSize});
|
||||||
Window::setBgColor(glm::vec4(0.0f));
|
display::setBgColor(glm::vec4(0.0f));
|
||||||
|
|
||||||
fbo.bind();
|
fbo.bind();
|
||||||
for (size_t i = 0; i < count; i++) {
|
for (size_t i = 0; i < count; i++) {
|
||||||
@ -136,7 +136,5 @@ std::unique_ptr<Atlas> BlocksPreview::build(
|
|||||||
builder.add(def.name, draw(cache, shader, fbo, batch, def, iconSize));
|
builder.add(def.name, draw(cache, shader, fbo, batch, def, iconSize));
|
||||||
}
|
}
|
||||||
fbo.unbind();
|
fbo.unbind();
|
||||||
|
|
||||||
Window::viewport(0, 0, Window::width, Window::height);
|
|
||||||
return builder.build(2);
|
return builder.build(2);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,6 +13,7 @@ class Batch3D;
|
|||||||
class Block;
|
class Block;
|
||||||
class ContentIndices;
|
class ContentIndices;
|
||||||
class Shader;
|
class Shader;
|
||||||
|
class Window;
|
||||||
class ContentGfxCache;
|
class ContentGfxCache;
|
||||||
|
|
||||||
class BlocksPreview {
|
class BlocksPreview {
|
||||||
@ -26,6 +27,7 @@ class BlocksPreview {
|
|||||||
);
|
);
|
||||||
public:
|
public:
|
||||||
static std::unique_ptr<Atlas> build(
|
static std::unique_ptr<Atlas> build(
|
||||||
|
Window& window,
|
||||||
const ContentGfxCache& cache,
|
const ContentGfxCache& cache,
|
||||||
const Assets& assets,
|
const Assets& assets,
|
||||||
const ContentIndices& indices
|
const ContentIndices& indices
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
#include "WorldRenderer.hpp"
|
#include "WorldRenderer.hpp"
|
||||||
#include "TextsRenderer.hpp"
|
#include "TextsRenderer.hpp"
|
||||||
#include "TextNote.hpp"
|
#include "TextNote.hpp"
|
||||||
|
#include "assets/Assets.hpp"
|
||||||
#include "assets/assets_util.hpp"
|
#include "assets/assets_util.hpp"
|
||||||
#include "content/Content.hpp"
|
#include "content/Content.hpp"
|
||||||
#include "voxels/Chunks.hpp"
|
#include "voxels/Chunks.hpp"
|
||||||
@ -60,7 +61,7 @@ Decorator::Decorator(
|
|||||||
player->getPosition()
|
player->getPosition()
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
playerNamePreset.deserialize(engine.getResPaths()->readCombinedObject(
|
playerNamePreset.deserialize(engine.getResPaths().readCombinedObject(
|
||||||
"presets/text3d/player_name.toml"
|
"presets/text3d/player_name.toml"
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -64,8 +64,6 @@ void GuidesRenderer::renderDebugLines(
|
|||||||
) {
|
) {
|
||||||
DrawContext ctx = pctx.sub(&batch);
|
DrawContext ctx = pctx.sub(&batch);
|
||||||
const auto& viewport = ctx.getViewport();
|
const auto& viewport = ctx.getViewport();
|
||||||
uint displayWidth = viewport.getWidth();
|
|
||||||
uint displayHeight = viewport.getHeight();
|
|
||||||
|
|
||||||
ctx.setDepthTest(true);
|
ctx.setDepthTest(true);
|
||||||
|
|
||||||
@ -91,15 +89,15 @@ void GuidesRenderer::renderDebugLines(
|
|||||||
}
|
}
|
||||||
|
|
||||||
float length = 40.f;
|
float length = 40.f;
|
||||||
glm::vec3 tsl(displayWidth / 2, displayHeight / 2, 0.f);
|
glm::vec3 tsl(viewport.x / 2, viewport.y / 2, 0.f);
|
||||||
glm::mat4 model(glm::translate(glm::mat4(1.f), tsl));
|
glm::mat4 model(glm::translate(glm::mat4(1.f), tsl));
|
||||||
linesShader.uniformMatrix(
|
linesShader.uniformMatrix(
|
||||||
"u_projview",
|
"u_projview",
|
||||||
glm::ortho(
|
glm::ortho(
|
||||||
0.f,
|
0.f,
|
||||||
static_cast<float>(displayWidth),
|
static_cast<float>(viewport.x),
|
||||||
0.f,
|
0.f,
|
||||||
static_cast<float>(displayHeight),
|
static_cast<float>(viewport.y),
|
||||||
-length,
|
-length,
|
||||||
length
|
length
|
||||||
) * model *
|
) * model *
|
||||||
|
|||||||
@ -6,7 +6,6 @@
|
|||||||
#include "graphics/core/Atlas.hpp"
|
#include "graphics/core/Atlas.hpp"
|
||||||
#include "graphics/core/Texture.hpp"
|
#include "graphics/core/Texture.hpp"
|
||||||
#include "assets/Assets.hpp"
|
#include "assets/Assets.hpp"
|
||||||
#include "window/Window.hpp"
|
|
||||||
#include "voxels/Chunks.hpp"
|
#include "voxels/Chunks.hpp"
|
||||||
#include "lighting/Lightmap.hpp"
|
#include "lighting/Lightmap.hpp"
|
||||||
#include "settings.hpp"
|
#include "settings.hpp"
|
||||||
|
|||||||
@ -48,6 +48,30 @@ static inline UVRegion get_region_for(
|
|||||||
return texreg.region;
|
return texreg.region;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ModelsGenerator::prepare(Content& content, Assets& assets) {
|
||||||
|
for (auto& [name, def] : content.blocks.getDefs()) {
|
||||||
|
if (def->model == BlockModel::custom && def->modelName.empty()) {
|
||||||
|
assets.store(
|
||||||
|
std::make_unique<model::Model>(
|
||||||
|
loadCustomBlockModel(
|
||||||
|
def->customModelRaw, assets, !def->shadeless
|
||||||
|
)
|
||||||
|
),
|
||||||
|
name + ".model"
|
||||||
|
);
|
||||||
|
def->modelName = def->name + ".model";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (auto& [name, def] : content.items.getDefs()) {
|
||||||
|
assets.store(
|
||||||
|
std::make_unique<model::Model>(
|
||||||
|
generate(*def, content, assets)
|
||||||
|
),
|
||||||
|
name + ".model"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
model::Model ModelsGenerator::fromCustom(
|
model::Model ModelsGenerator::fromCustom(
|
||||||
const Assets& assets,
|
const Assets& assets,
|
||||||
const std::vector<BoxModel>& modelBoxes,
|
const std::vector<BoxModel>& modelBoxes,
|
||||||
|
|||||||
@ -11,6 +11,8 @@ class Block;
|
|||||||
|
|
||||||
class ModelsGenerator {
|
class ModelsGenerator {
|
||||||
public:
|
public:
|
||||||
|
static void prepare(Content& content, Assets& assets);
|
||||||
|
|
||||||
static model::Model generate(
|
static model::Model generate(
|
||||||
const ItemDef& def, const Content& content, const Assets& assets
|
const ItemDef& def, const Content& content, const Assets& assets
|
||||||
);
|
);
|
||||||
|
|||||||
@ -101,11 +101,9 @@ void Skybox::draw(
|
|||||||
float daytime,
|
float daytime,
|
||||||
float fog)
|
float fog)
|
||||||
{
|
{
|
||||||
const Viewport& viewport = pctx.getViewport();
|
const glm::uvec2& viewport = pctx.getViewport();
|
||||||
int width = viewport.getWidth();
|
|
||||||
int height = viewport.getHeight();
|
|
||||||
|
|
||||||
drawBackground(camera, assets, width, height);
|
drawBackground(camera, assets, viewport.x, viewport.y);
|
||||||
|
|
||||||
DrawContext ctx = pctx.sub();
|
DrawContext ctx = pctx.sub();
|
||||||
ctx.setBlendMode(BlendMode::addition);
|
ctx.setBlendMode(BlendMode::addition);
|
||||||
@ -145,7 +143,7 @@ void Skybox::refresh(const DrawContext& pctx, float t, float mie, uint quality)
|
|||||||
ctx.setDepthMask(false);
|
ctx.setDepthMask(false);
|
||||||
ctx.setDepthTest(false);
|
ctx.setDepthTest(false);
|
||||||
ctx.setFramebuffer(fbo.get());
|
ctx.setFramebuffer(fbo.get());
|
||||||
ctx.setViewport(Viewport(size, size));
|
ctx.setViewport({size, size});
|
||||||
|
|
||||||
auto cubemap = dynamic_cast<Cubemap*>(fbo->getTexture());
|
auto cubemap = dynamic_cast<Cubemap*>(fbo->getTexture());
|
||||||
assert(cubemap != nullptr);
|
assert(cubemap != nullptr);
|
||||||
|
|||||||
@ -4,11 +4,11 @@
|
|||||||
#include "maths/util.hpp"
|
#include "maths/util.hpp"
|
||||||
#include "assets/Assets.hpp"
|
#include "assets/Assets.hpp"
|
||||||
#include "window/Camera.hpp"
|
#include "window/Camera.hpp"
|
||||||
#include "window/Window.hpp"
|
|
||||||
#include "maths/FrustumCulling.hpp"
|
#include "maths/FrustumCulling.hpp"
|
||||||
#include "graphics/core/Font.hpp"
|
#include "graphics/core/Font.hpp"
|
||||||
#include "graphics/core/Batch3D.hpp"
|
#include "graphics/core/Batch3D.hpp"
|
||||||
#include "graphics/core/Shader.hpp"
|
#include "graphics/core/Shader.hpp"
|
||||||
|
#include "graphics/core/DrawContext.hpp"
|
||||||
#include "presets/NotePreset.hpp"
|
#include "presets/NotePreset.hpp"
|
||||||
#include "constants.hpp"
|
#include "constants.hpp"
|
||||||
|
|
||||||
@ -66,6 +66,7 @@ void TextsRenderer::renderNote(
|
|||||||
xvec *= 1.0f + scale;
|
xvec *= 1.0f + scale;
|
||||||
yvec *= 1.0f + scale;
|
yvec *= 1.0f + scale;
|
||||||
}
|
}
|
||||||
|
const auto& viewport = context.getViewport();
|
||||||
if (preset.displayMode == NoteDisplayMode::PROJECTED) {
|
if (preset.displayMode == NoteDisplayMode::PROJECTED) {
|
||||||
float scale = 1.0f;
|
float scale = 1.0f;
|
||||||
if (glm::abs(preset.perspective) > 0.0001f) {
|
if (glm::abs(preset.perspective) > 0.0001f) {
|
||||||
@ -84,14 +85,14 @@ void TextsRenderer::renderNote(
|
|||||||
}
|
}
|
||||||
pos /= projpos.w;
|
pos /= projpos.w;
|
||||||
pos.z = 0;
|
pos.z = 0;
|
||||||
xvec = {2.0f/Window::width*scale, 0, 0};
|
xvec = {2.0f / viewport.x * scale, 0, 0};
|
||||||
yvec = {0, 2.0f/Window::height*scale, 0};
|
yvec = {0, 2.0f / viewport.y * scale, 0};
|
||||||
} else {
|
} else {
|
||||||
auto matrix = camera.getProjView();
|
auto matrix = camera.getProjView();
|
||||||
auto screenPos = matrix * glm::vec4(pos, 1.0f);
|
auto screenPos = matrix * glm::vec4(pos, 1.0f);
|
||||||
|
|
||||||
xvec = glm::vec3(2.0f/Window::width*scale, 0, 0);
|
xvec = glm::vec3(2.0f / viewport.x * scale, 0, 0);
|
||||||
yvec = glm::vec3(0, 2.0f/Window::height*scale, 0);
|
yvec = glm::vec3(0, 2.0f / viewport.y * scale, 0);
|
||||||
|
|
||||||
pos = screenPos / screenPos.w;
|
pos = screenPos / screenPos.w;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -316,7 +316,7 @@ void WorldRenderer::renderHands(
|
|||||||
assets.get<model::Model>(def.modelName),
|
assets.get<model::Model>(def.modelName),
|
||||||
nullptr
|
nullptr
|
||||||
);
|
);
|
||||||
Window::clearDepth();
|
display::clearDepth();
|
||||||
setupWorldShader(entityShader, hudcam, engine.getSettings(), 0.0f);
|
setupWorldShader(entityShader, hudcam, engine.getSettings(), 0.0f);
|
||||||
skybox->bind();
|
skybox->bind();
|
||||||
modelBatch->render();
|
modelBatch->render();
|
||||||
@ -338,8 +338,8 @@ void WorldRenderer::draw(
|
|||||||
|
|
||||||
auto world = level.getWorld();
|
auto world = level.getWorld();
|
||||||
|
|
||||||
const Viewport& vp = pctx.getViewport();
|
const auto& vp = pctx.getViewport();
|
||||||
camera.aspect = vp.getWidth() / static_cast<float>(vp.getHeight());
|
camera.setAspectRatio(vp.x / static_cast<float>(vp.y));
|
||||||
|
|
||||||
const auto& settings = engine.getSettings();
|
const auto& settings = engine.getSettings();
|
||||||
const auto& worldInfo = world->getInfo();
|
const auto& worldInfo = world->getInfo();
|
||||||
@ -359,7 +359,7 @@ void WorldRenderer::draw(
|
|||||||
DrawContext wctx = pctx.sub();
|
DrawContext wctx = pctx.sub();
|
||||||
postProcessing.use(wctx);
|
postProcessing.use(wctx);
|
||||||
|
|
||||||
Window::clearDepth();
|
display::clearDepth();
|
||||||
|
|
||||||
// Drawing background sky plane
|
// Drawing background sky plane
|
||||||
skybox->draw(pctx, camera, assets, worldInfo.daytime, clouds);
|
skybox->draw(pctx, camera, assets, worldInfo.daytime, clouds);
|
||||||
|
|||||||
@ -1,13 +1,15 @@
|
|||||||
#include "GUI.hpp"
|
#include "GUI.hpp"
|
||||||
|
|
||||||
#include "gui_util.hpp"
|
#include <algorithm>
|
||||||
|
#include <iostream>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include "elements/UINode.hpp"
|
#include "assets/Assets.hpp"
|
||||||
#include "elements/Label.hpp"
|
#include "elements/Label.hpp"
|
||||||
#include "elements/Menu.hpp"
|
#include "elements/Menu.hpp"
|
||||||
#include "elements/Panel.hpp"
|
#include "elements/Panel.hpp"
|
||||||
|
#include "elements/UINode.hpp"
|
||||||
#include "assets/Assets.hpp"
|
#include "engine/Engine.hpp"
|
||||||
#include "frontend/UiDocument.hpp"
|
#include "frontend/UiDocument.hpp"
|
||||||
#include "frontend/locale.hpp"
|
#include "frontend/locale.hpp"
|
||||||
#include "graphics/core/Batch2D.hpp"
|
#include "graphics/core/Batch2D.hpp"
|
||||||
@ -15,31 +17,36 @@
|
|||||||
#include "graphics/core/Shader.hpp"
|
#include "graphics/core/Shader.hpp"
|
||||||
#include "graphics/core/Font.hpp"
|
#include "graphics/core/Font.hpp"
|
||||||
#include "graphics/core/DrawContext.hpp"
|
#include "graphics/core/DrawContext.hpp"
|
||||||
#include "window/Events.hpp"
|
#include "graphics/core/Shader.hpp"
|
||||||
|
#include "gui_util.hpp"
|
||||||
|
#include "window/Camera.hpp"
|
||||||
#include "window/Window.hpp"
|
#include "window/Window.hpp"
|
||||||
#include "window/input.hpp"
|
#include "window/input.hpp"
|
||||||
#include "window/Camera.hpp"
|
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
using namespace gui;
|
using namespace gui;
|
||||||
|
|
||||||
GUI::GUI()
|
GUI::GUI(Engine& engine)
|
||||||
: batch2D(std::make_unique<Batch2D>(1024)),
|
: engine(engine),
|
||||||
container(std::make_shared<Container>(glm::vec2(1000))) {
|
input(engine.getInput()),
|
||||||
|
batch2D(std::make_unique<Batch2D>(1024)),
|
||||||
|
container(std::make_shared<Container>(*this, glm::vec2(1000))) {
|
||||||
container->setId("root");
|
container->setId("root");
|
||||||
uicamera = std::make_unique<Camera>(glm::vec3(), Window::height);
|
uicamera =
|
||||||
|
std::make_unique<Camera>(glm::vec3(), engine.getWindow().getSize().y);
|
||||||
uicamera->perspective = false;
|
uicamera->perspective = false;
|
||||||
uicamera->flipped = true;
|
uicamera->flipped = true;
|
||||||
|
|
||||||
menu = std::make_shared<Menu>();
|
menu = std::make_shared<Menu>(*this);
|
||||||
menu->setId("menu");
|
menu->setId("menu");
|
||||||
menu->setZIndex(10);
|
menu->setZIndex(10);
|
||||||
container->add(menu);
|
container->add(menu);
|
||||||
container->setScrollable(false);
|
container->setScrollable(false);
|
||||||
|
|
||||||
tooltip = guiutil::create(
|
tooltip = guiutil::create(
|
||||||
|
*this,
|
||||||
"<container color='#000000A0' interactive='false' z-index='999'>"
|
"<container color='#000000A0' interactive='false' z-index='999'>"
|
||||||
"<label id='tooltip.label' pos='2' autoresize='true' multiline='true' text-wrap='false'></label>"
|
"<label id='tooltip.label' pos='2' autoresize='true' multiline='true' text-wrap='false'></label>"
|
||||||
"</container>"
|
"</container>"
|
||||||
@ -65,12 +72,15 @@ std::shared_ptr<Menu> GUI::getMenu() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void GUI::onAssetsLoad(Assets* assets) {
|
void GUI::onAssetsLoad(Assets* assets) {
|
||||||
assets->store(std::make_unique<UiDocument>(
|
assets->store(
|
||||||
|
std::make_unique<UiDocument>(
|
||||||
"core:root",
|
"core:root",
|
||||||
uidocscript {},
|
uidocscript {},
|
||||||
std::dynamic_pointer_cast<gui::UINode>(container),
|
std::dynamic_pointer_cast<gui::UINode>(container),
|
||||||
nullptr
|
nullptr
|
||||||
), "core:root");
|
),
|
||||||
|
"core:root"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GUI::resetTooltip() {
|
void GUI::resetTooltip() {
|
||||||
@ -79,11 +89,13 @@ void GUI::resetTooltip() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void GUI::updateTooltip(float delta) {
|
void GUI::updateTooltip(float delta) {
|
||||||
if (hover == nullptr || !hover->isInside(Events::cursor)) {
|
const auto& cursor = input.getCursor();
|
||||||
|
if (hover == nullptr || !hover->isInside(cursor.pos)) {
|
||||||
return resetTooltip();
|
return resetTooltip();
|
||||||
}
|
}
|
||||||
if (tooltipTimer + delta >= hover->getTooltipDelay()) {
|
if (tooltipTimer + delta >= hover->getTooltipDelay()) {
|
||||||
auto label = std::dynamic_pointer_cast<gui::Label>(get("tooltip.label"));
|
auto label =
|
||||||
|
std::dynamic_pointer_cast<gui::Label>(get("tooltip.label"));
|
||||||
const auto& text = hover->getTooltip();
|
const auto& text = hover->getTooltip();
|
||||||
if (text.empty() && tooltip->isVisible()) {
|
if (text.empty() && tooltip->isVisible()) {
|
||||||
return resetTooltip();
|
return resetTooltip();
|
||||||
@ -91,11 +103,11 @@ void GUI::updateTooltip(float delta) {
|
|||||||
if (label && !text.empty()) {
|
if (label && !text.empty()) {
|
||||||
tooltip->setVisible(true);
|
tooltip->setVisible(true);
|
||||||
label->setText(langs::get(text));
|
label->setText(langs::get(text));
|
||||||
auto size = label->getSize()+glm::vec2(4.0f);
|
auto size = label->getSize() + glm::vec2(4.0f);
|
||||||
auto pos = Events::cursor+glm::vec2(10.0f);
|
auto pos = cursor.pos + glm::vec2(10.0f);
|
||||||
auto rootSize = container->getSize();
|
auto rootSize = container->getSize();
|
||||||
pos.x = glm::min(pos.x, rootSize.x-size.x);
|
pos.x = glm::min(pos.x, rootSize.x - size.x);
|
||||||
pos.y = glm::min(pos.y, rootSize.y-size.y);
|
pos.y = glm::min(pos.y, rootSize.y - size.y);
|
||||||
tooltip->setSize(size);
|
tooltip->setSize(size);
|
||||||
tooltip->setPos(pos);
|
tooltip->setPos(pos);
|
||||||
}
|
}
|
||||||
@ -104,31 +116,33 @@ void GUI::updateTooltip(float delta) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Mouse related input and logic handling
|
/// @brief Mouse related input and logic handling
|
||||||
void GUI::actMouse(float delta) {
|
void GUI::actMouse(float delta, const CursorState& cursor) {
|
||||||
float mouseDelta = glm::length(Events::delta);
|
float mouseDelta = glm::length(cursor.delta);
|
||||||
doubleClicked = false;
|
doubleClicked = false;
|
||||||
doubleClickTimer += delta + mouseDelta * 0.1f;
|
doubleClickTimer += delta + mouseDelta * 0.1f;
|
||||||
|
|
||||||
auto hover = container->getAt(Events::cursor);
|
auto hover = container->getAt(cursor.pos);
|
||||||
if (this->hover && this->hover != hover) {
|
if (this->hover && this->hover != hover) {
|
||||||
this->hover->setHover(false);
|
this->hover->setHover(false);
|
||||||
}
|
}
|
||||||
if (hover) {
|
if (hover) {
|
||||||
hover->setHover(true);
|
hover->setHover(true);
|
||||||
if (Events::scroll) {
|
|
||||||
hover->scrolled(Events::scroll);
|
int scroll = input.getScroll();
|
||||||
|
if (scroll) {
|
||||||
|
hover->scrolled(scroll);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this->hover = hover;
|
this->hover = hover;
|
||||||
|
|
||||||
if (Events::jclicked(mousecode::BUTTON_1)) {
|
if (input.jclicked(Mousecode::BUTTON_1)) {
|
||||||
if (pressed == nullptr && this->hover) {
|
if (pressed == nullptr && this->hover) {
|
||||||
pressed = hover;
|
pressed = hover;
|
||||||
if (doubleClickTimer < doubleClickDelay) {
|
if (doubleClickTimer < doubleClickDelay) {
|
||||||
pressed->doubleClick(this, Events::cursor.x, Events::cursor.y);
|
pressed->doubleClick(cursor.pos.x, cursor.pos.y);
|
||||||
doubleClicked = true;
|
doubleClicked = true;
|
||||||
} else {
|
} else {
|
||||||
pressed->click(this, Events::cursor.x, Events::cursor.y);
|
pressed->click(cursor.pos.x, cursor.pos.y);
|
||||||
}
|
}
|
||||||
doubleClickTimer = 0.0f;
|
doubleClickTimer = 0.0f;
|
||||||
if (focus && focus != pressed) {
|
if (focus && focus != pressed) {
|
||||||
@ -136,7 +150,7 @@ void GUI::actMouse(float delta) {
|
|||||||
}
|
}
|
||||||
if (focus != pressed) {
|
if (focus != pressed) {
|
||||||
focus = pressed;
|
focus = pressed;
|
||||||
focus->onFocus(this);
|
focus->onFocus();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -144,59 +158,61 @@ void GUI::actMouse(float delta) {
|
|||||||
focus->defocus();
|
focus->defocus();
|
||||||
focus = nullptr;
|
focus = nullptr;
|
||||||
}
|
}
|
||||||
} else if (!Events::clicked(mousecode::BUTTON_1) && pressed) {
|
} else if (!input.clicked(Mousecode::BUTTON_1) && pressed) {
|
||||||
pressed->mouseRelease(this, Events::cursor.x, Events::cursor.y);
|
pressed->mouseRelease(cursor.pos.x, cursor.pos.y);
|
||||||
pressed = nullptr;
|
pressed = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hover) {
|
if (hover) {
|
||||||
for (mousecode code : MOUSECODES_ALL) {
|
for (Mousecode code : MOUSECODES_ALL) {
|
||||||
if (Events::jclicked(code)) {
|
if (input.jclicked(code)) {
|
||||||
hover->clicked(this, code);
|
hover->clicked(code);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GUI::actFocused() {
|
void GUI::actFocused() {
|
||||||
if (Events::jpressed(keycode::ESCAPE)) {
|
if (input.jpressed(Keycode::ESCAPE)) {
|
||||||
focus->defocus();
|
focus->defocus();
|
||||||
focus = nullptr;
|
focus = nullptr;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (auto codepoint : Events::codepoints) {
|
for (auto codepoint : input.getCodepoints()) {
|
||||||
focus->typed(codepoint);
|
focus->typed(codepoint);
|
||||||
}
|
}
|
||||||
for (auto key : Events::pressedKeys) {
|
for (auto key : input.getPressedKeys()) {
|
||||||
focus->keyPressed(key);
|
focus->keyPressed(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Events::isCursorLocked()) {
|
const auto& cursor = input.getCursor();
|
||||||
if (Events::clicked(mousecode::BUTTON_1) &&
|
if (!cursor.locked) {
|
||||||
(Events::jclicked(mousecode::BUTTON_1) || Events::delta.x || Events::delta.y))
|
if (input.clicked(Mousecode::BUTTON_1) &&
|
||||||
{
|
(input.jclicked(Mousecode::BUTTON_1) || cursor.delta.x ||
|
||||||
|
cursor.delta.y)) {
|
||||||
if (!doubleClicked) {
|
if (!doubleClicked) {
|
||||||
focus->mouseMove(this, Events::cursor.x, Events::cursor.y);
|
focus->mouseMove(cursor.pos.x, cursor.pos.y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GUI::act(float delta, const Viewport& vp) {
|
void GUI::act(float delta, const glm::uvec2& vp) {
|
||||||
container->setSize(vp.size());
|
container->setSize(vp);
|
||||||
container->act(delta);
|
container->act(delta);
|
||||||
auto prevfocus = focus;
|
auto prevfocus = focus;
|
||||||
|
|
||||||
updateTooltip(delta);
|
updateTooltip(delta);
|
||||||
if (!Events::isCursorLocked()) {
|
|
||||||
actMouse(delta);
|
const auto& cursor = input.getCursor();
|
||||||
|
if (!cursor.locked) {
|
||||||
|
actMouse(delta, cursor);
|
||||||
} else {
|
} else {
|
||||||
if (hover) {
|
if (hover) {
|
||||||
hover->setHover(false);
|
hover->setHover(false);
|
||||||
hover = nullptr;
|
hover = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (focus) {
|
if (focus) {
|
||||||
actFocused();
|
actFocused();
|
||||||
}
|
}
|
||||||
@ -217,7 +233,6 @@ void GUI::draw(const DrawContext& pctx, const Assets& assets) {
|
|||||||
auto ctx = pctx.sub(batch2D.get());
|
auto ctx = pctx.sub(batch2D.get());
|
||||||
|
|
||||||
auto& viewport = ctx.getViewport();
|
auto& viewport = ctx.getViewport();
|
||||||
glm::vec2 wsize = viewport.size();
|
|
||||||
|
|
||||||
auto& page = menu->getCurrent();
|
auto& page = menu->getCurrent();
|
||||||
if (page.panel) {
|
if (page.panel) {
|
||||||
@ -227,8 +242,9 @@ void GUI::draw(const DrawContext& pctx, const Assets& assets) {
|
|||||||
panel->cropToContent();
|
panel->cropToContent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
menu->setPos((wsize - menu->getSize()) / 2.0f);
|
menu->setPos((glm::vec2(viewport) - menu->getSize()) / 2.0f);
|
||||||
uicamera->setFov(wsize.y);
|
uicamera->setFov(viewport.y);
|
||||||
|
uicamera->setAspectRatio(viewport.x / static_cast<float>(viewport.y));
|
||||||
|
|
||||||
auto uishader = assets.get<Shader>("ui");
|
auto uishader = assets.get<Shader>("ui");
|
||||||
uishader->use();
|
uishader->use();
|
||||||
@ -238,7 +254,7 @@ void GUI::draw(const DrawContext& pctx, const Assets& assets) {
|
|||||||
container->draw(ctx, assets);
|
container->draw(ctx, assets);
|
||||||
|
|
||||||
if (hover) {
|
if (hover) {
|
||||||
Window::setCursor(hover->getCursor());
|
engine.getWindow().setCursor(hover->getCursor());
|
||||||
}
|
}
|
||||||
if (hover && debug) {
|
if (hover && debug) {
|
||||||
auto pos = hover->calcPos();
|
auto pos = hover->calcPos();
|
||||||
@ -260,11 +276,11 @@ void GUI::draw(const DrawContext& pctx, const Assets& assets) {
|
|||||||
batch2D->untexture();
|
batch2D->untexture();
|
||||||
auto node = hover->getParent();
|
auto node = hover->getParent();
|
||||||
while (node) {
|
while (node) {
|
||||||
auto pos = node->calcPos();
|
auto parentPos = node->calcPos();
|
||||||
auto size = node->getSize();
|
auto size = node->getSize();
|
||||||
|
|
||||||
batch2D->setColor(0, 255, 255);
|
batch2D->setColor(0, 255, 255);
|
||||||
batch2D->lineRect(pos.x, pos.y, size.x-1, size.y-1);
|
batch2D->lineRect(parentPos.x, parentPos.y, size.x-1, size.y-1);
|
||||||
|
|
||||||
node = node->getParent();
|
node = node->getParent();
|
||||||
}
|
}
|
||||||
@ -313,7 +329,7 @@ void GUI::setFocus(std::shared_ptr<UINode> node) {
|
|||||||
}
|
}
|
||||||
focus = std::move(node);
|
focus = std::move(node);
|
||||||
if (focus) {
|
if (focus) {
|
||||||
focus->onFocus(this);
|
focus->onFocus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -336,3 +352,15 @@ float GUI::getDoubleClickDelay() const {
|
|||||||
void GUI::toggleDebug() {
|
void GUI::toggleDebug() {
|
||||||
debug = !debug;
|
debug = !debug;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Input& GUI::getInput() const {
|
||||||
|
return engine.getInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
Input& GUI::getInput() {
|
||||||
|
return engine.getInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
Window& GUI::getWindow() {
|
||||||
|
return engine.getWindow();
|
||||||
|
}
|
||||||
|
|||||||
@ -9,12 +9,14 @@
|
|||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
class Viewport;
|
|
||||||
class DrawContext;
|
class DrawContext;
|
||||||
class Assets;
|
class Assets;
|
||||||
class Camera;
|
class Camera;
|
||||||
class Batch2D;
|
class Batch2D;
|
||||||
class LineBatch;
|
struct CursorState;
|
||||||
|
class Engine;
|
||||||
|
class Input;
|
||||||
|
class Window;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Some info about padding and margin.
|
Some info about padding and margin.
|
||||||
@ -56,6 +58,8 @@ namespace gui {
|
|||||||
|
|
||||||
/// @brief The main UI controller
|
/// @brief The main UI controller
|
||||||
class GUI {
|
class GUI {
|
||||||
|
Engine& engine;
|
||||||
|
Input& input;
|
||||||
std::unique_ptr<Batch2D> batch2D;
|
std::unique_ptr<Batch2D> batch2D;
|
||||||
std::shared_ptr<Container> container;
|
std::shared_ptr<Container> container;
|
||||||
std::shared_ptr<UINode> hover;
|
std::shared_ptr<UINode> hover;
|
||||||
@ -76,12 +80,12 @@ namespace gui {
|
|||||||
bool doubleClicked = false;
|
bool doubleClicked = false;
|
||||||
bool debug = false;
|
bool debug = false;
|
||||||
|
|
||||||
void actMouse(float delta);
|
void actMouse(float delta, const CursorState& cursor);
|
||||||
void actFocused();
|
void actFocused();
|
||||||
void updateTooltip(float delta);
|
void updateTooltip(float delta);
|
||||||
void resetTooltip();
|
void resetTooltip();
|
||||||
public:
|
public:
|
||||||
GUI();
|
GUI(Engine& engine);
|
||||||
~GUI();
|
~GUI();
|
||||||
|
|
||||||
void setPageLoader(PageLoaderFunc pageLoader);
|
void setPageLoader(PageLoaderFunc pageLoader);
|
||||||
@ -101,7 +105,7 @@ namespace gui {
|
|||||||
/// @brief Main input handling and logic update method
|
/// @brief Main input handling and logic update method
|
||||||
/// @param delta delta time
|
/// @param delta delta time
|
||||||
/// @param viewport window size
|
/// @param viewport window size
|
||||||
void act(float delta, const Viewport& viewport);
|
void act(float delta, const glm::uvec2& viewport);
|
||||||
|
|
||||||
/// @brief Draw all visible elements on main container
|
/// @brief Draw all visible elements on main container
|
||||||
/// @param pctx parent graphics context
|
/// @param pctx parent graphics context
|
||||||
@ -152,5 +156,8 @@ namespace gui {
|
|||||||
float getDoubleClickDelay() const;
|
float getDoubleClickDelay() const;
|
||||||
|
|
||||||
void toggleDebug();
|
void toggleDebug();
|
||||||
|
const Input& getInput() const;
|
||||||
|
Input& getInput();
|
||||||
|
Window& getWindow();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,12 +26,13 @@ namespace gui {
|
|||||||
}
|
}
|
||||||
protected:
|
protected:
|
||||||
BasePanel(
|
BasePanel(
|
||||||
|
GUI& gui,
|
||||||
glm::vec2 size,
|
glm::vec2 size,
|
||||||
glm::vec4 padding = glm::vec4(0.0f),
|
glm::vec4 padding = glm::vec4(0.0f),
|
||||||
float interval = 2.0f,
|
float interval = 2.0f,
|
||||||
Orientation orientation = Orientation::vertical
|
Orientation orientation = Orientation::vertical
|
||||||
)
|
)
|
||||||
: Container(std::move(size)),
|
: Container(gui, std::move(size)),
|
||||||
padding(std::move(padding)),
|
padding(std::move(padding)),
|
||||||
interval(interval) {
|
interval(interval) {
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,17 +3,23 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include "Label.hpp"
|
#include "Label.hpp"
|
||||||
#include "graphics/core/DrawContext.hpp"
|
|
||||||
#include "graphics/core/Batch2D.hpp"
|
#include "graphics/core/Batch2D.hpp"
|
||||||
|
#include "graphics/core/DrawContext.hpp"
|
||||||
|
|
||||||
using namespace gui;
|
using namespace gui;
|
||||||
|
|
||||||
Button::Button(const std::shared_ptr<UINode>& content, glm::vec4 padding)
|
Button::Button(
|
||||||
: Panel(glm::vec2(), padding, 0) {
|
GUI& gui, const std::shared_ptr<UINode>& content, glm::vec4 padding
|
||||||
|
)
|
||||||
|
: Panel(gui, glm::vec2(), padding, 0) {
|
||||||
glm::vec4 margin = getMargin();
|
glm::vec4 margin = getMargin();
|
||||||
setSize(content->getSize()+
|
setSize(
|
||||||
glm::vec2(padding[0]+padding[2]+margin[0]+margin[2],
|
content->getSize() +
|
||||||
padding[1]+padding[3]+margin[1]+margin[3]));
|
glm::vec2(
|
||||||
|
padding[0] + padding[2] + margin[0] + margin[2],
|
||||||
|
padding[1] + padding[3] + margin[1] + margin[3]
|
||||||
|
)
|
||||||
|
);
|
||||||
add(content);
|
add(content);
|
||||||
setScrollable(false);
|
setScrollable(false);
|
||||||
setHoverColor(glm::vec4(0.05f, 0.1f, 0.15f, 0.75f));
|
setHoverColor(glm::vec4(0.05f, 0.1f, 0.15f, 0.75f));
|
||||||
@ -22,15 +28,16 @@ Button::Button(const std::shared_ptr<UINode>& content, glm::vec4 padding)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Button::Button(
|
Button::Button(
|
||||||
|
GUI& gui,
|
||||||
const std::wstring& text,
|
const std::wstring& text,
|
||||||
glm::vec4 padding,
|
glm::vec4 padding,
|
||||||
const onaction& action,
|
const onaction& action,
|
||||||
glm::vec2 size
|
glm::vec2 size
|
||||||
) : Panel(size, padding, 0)
|
)
|
||||||
{
|
: Panel(gui, size, padding, 0) {
|
||||||
if (size.y < 0.0f) {
|
if (size.y < 0.0f) {
|
||||||
size = glm::vec2(
|
size = glm::vec2(
|
||||||
glm::max(padding.x + padding.z + text.length()*8, size.x),
|
glm::max(padding.x + padding.z + text.length() * 8, size.x),
|
||||||
glm::max(padding.y + padding.w + 16, size.y)
|
glm::max(padding.y + padding.w + 16, size.y)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -41,9 +48,11 @@ Button::Button(
|
|||||||
}
|
}
|
||||||
setScrollable(false);
|
setScrollable(false);
|
||||||
|
|
||||||
label = std::make_shared<Label>(text);
|
label = std::make_shared<Label>(gui, text);
|
||||||
label->setAlign(Align::center);
|
label->setAlign(Align::center);
|
||||||
label->setSize(size-glm::vec2(padding.z+padding.x, padding.w+padding.y));
|
label->setSize(
|
||||||
|
size - glm::vec2(padding.z + padding.x, padding.w + padding.y)
|
||||||
|
);
|
||||||
label->setInteractive(false);
|
label->setInteractive(false);
|
||||||
add(label);
|
add(label);
|
||||||
setHoverColor(glm::vec4(0.05f, 0.1f, 0.15f, 0.75f));
|
setHoverColor(glm::vec4(0.05f, 0.1f, 0.15f, 0.75f));
|
||||||
@ -73,7 +82,9 @@ Button* Button::textSupplier(wstringsupplier supplier) {
|
|||||||
void Button::refresh() {
|
void Button::refresh() {
|
||||||
Panel::refresh();
|
Panel::refresh();
|
||||||
if (label) {
|
if (label) {
|
||||||
label->setSize(size-glm::vec2(padding.z+padding.x, padding.w+padding.y));
|
label->setSize(
|
||||||
|
size - glm::vec2(padding.z + padding.x, padding.w + padding.y)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -9,13 +9,19 @@ namespace gui {
|
|||||||
protected:
|
protected:
|
||||||
std::shared_ptr<Label> label;
|
std::shared_ptr<Label> label;
|
||||||
public:
|
public:
|
||||||
Button(const std::shared_ptr<UINode>& content,
|
Button(
|
||||||
glm::vec4 padding=glm::vec4(2.0f));
|
GUI& gui,
|
||||||
|
const std::shared_ptr<UINode>& content,
|
||||||
|
glm::vec4 padding = glm::vec4(2.0f)
|
||||||
|
);
|
||||||
|
|
||||||
Button(const std::wstring& text,
|
Button(
|
||||||
|
GUI& gui,
|
||||||
|
const std::wstring& text,
|
||||||
glm::vec4 padding,
|
glm::vec4 padding,
|
||||||
const onaction& action,
|
const onaction& action,
|
||||||
glm::vec2 size=glm::vec2(-1));
|
glm::vec2 size = glm::vec2(-1)
|
||||||
|
);
|
||||||
|
|
||||||
virtual void drawBackground(
|
virtual void drawBackground(
|
||||||
const DrawContext& pctx, const Assets& assets
|
const DrawContext& pctx, const Assets& assets
|
||||||
|
|||||||
@ -4,7 +4,8 @@
|
|||||||
#include "graphics/core/DrawContext.hpp"
|
#include "graphics/core/DrawContext.hpp"
|
||||||
#include "graphics/core/Texture.hpp"
|
#include "graphics/core/Texture.hpp"
|
||||||
|
|
||||||
gui::Canvas::Canvas(ImageFormat inFormat, glm::uvec2 inSize) : UINode(inSize) {
|
gui::Canvas::Canvas(GUI& gui, ImageFormat inFormat, glm::uvec2 inSize)
|
||||||
|
: UINode(gui, inSize) {
|
||||||
auto data = std::make_shared<ImageData>(inFormat, inSize.x, inSize.y);
|
auto data = std::make_shared<ImageData>(inFormat, inSize.x, inSize.y);
|
||||||
mTexture = Texture::from(data.get());
|
mTexture = Texture::from(data.get());
|
||||||
mData = std::move(data);
|
mData = std::move(data);
|
||||||
|
|||||||
@ -9,7 +9,7 @@ class Texture;
|
|||||||
namespace gui {
|
namespace gui {
|
||||||
class Canvas final : public UINode {
|
class Canvas final : public UINode {
|
||||||
public:
|
public:
|
||||||
explicit Canvas(ImageFormat inFormat, glm::uvec2 inSize);
|
explicit Canvas(GUI& gui, ImageFormat inFormat, glm::uvec2 inSize);
|
||||||
|
|
||||||
~Canvas() override = default;
|
~Canvas() override = default;
|
||||||
|
|
||||||
|
|||||||
@ -2,13 +2,14 @@
|
|||||||
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include "graphics/core/DrawContext.hpp"
|
|
||||||
#include "graphics/core/Batch2D.hpp"
|
|
||||||
#include "Label.hpp"
|
#include "Label.hpp"
|
||||||
|
#include "graphics/core/Batch2D.hpp"
|
||||||
|
#include "graphics/core/DrawContext.hpp"
|
||||||
|
|
||||||
using namespace gui;
|
using namespace gui;
|
||||||
|
|
||||||
CheckBox::CheckBox(bool checked) : UINode(glm::vec2(32.0f)), checked(checked) {
|
CheckBox::CheckBox(GUI& gui, bool checked)
|
||||||
|
: UINode(gui, glm::vec2(32.0f)), checked(checked) {
|
||||||
setColor({0.0f, 0.0f, 0.0f, 0.5f});
|
setColor({0.0f, 0.0f, 0.0f, 0.5f});
|
||||||
setHoverColor({0.05f, 0.1f, 0.2f, 0.75f});
|
setHoverColor({0.05f, 0.1f, 0.2f, 0.75f});
|
||||||
}
|
}
|
||||||
@ -24,7 +25,7 @@ void CheckBox::draw(const DrawContext& pctx, const Assets&) {
|
|||||||
batch->rect(pos.x, pos.y, size.x, size.y);
|
batch->rect(pos.x, pos.y, size.x, size.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckBox::mouseRelease(GUI*, int, int) {
|
void CheckBox::mouseRelease(int, int) {
|
||||||
checked = !checked;
|
checked = !checked;
|
||||||
if (consumer) {
|
if (consumer) {
|
||||||
consumer(checked);
|
consumer(checked);
|
||||||
@ -44,10 +45,12 @@ CheckBox* CheckBox::setChecked(bool flag) {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
FullCheckBox::FullCheckBox(const std::wstring& text, glm::vec2 size, bool checked)
|
FullCheckBox::FullCheckBox(
|
||||||
: Panel(size),
|
GUI& gui, const std::wstring& text, glm::vec2 size, bool checked
|
||||||
checkbox(std::make_shared<CheckBox>(checked)),
|
)
|
||||||
label(std::make_shared<Label>(text)) {
|
: Panel(gui, size),
|
||||||
|
checkbox(std::make_shared<CheckBox>(gui, checked)),
|
||||||
|
label(std::make_shared<Label>(gui, text)) {
|
||||||
setColor(glm::vec4(0.0f));
|
setColor(glm::vec4(0.0f));
|
||||||
setOrientation(Orientation::horizontal);
|
setOrientation(Orientation::horizontal);
|
||||||
|
|
||||||
|
|||||||
@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include "Panel.hpp"
|
|
||||||
#include "Label.hpp"
|
#include "Label.hpp"
|
||||||
|
#include "Panel.hpp"
|
||||||
|
|
||||||
namespace gui {
|
namespace gui {
|
||||||
class CheckBox : public UINode {
|
class CheckBox : public UINode {
|
||||||
@ -13,11 +13,12 @@ namespace gui {
|
|||||||
boolconsumer consumer = nullptr;
|
boolconsumer consumer = nullptr;
|
||||||
bool checked = false;
|
bool checked = false;
|
||||||
public:
|
public:
|
||||||
CheckBox(bool checked=false);
|
explicit CheckBox(GUI& gui, bool checked = false);
|
||||||
|
|
||||||
virtual void draw(const DrawContext& pctx, const Assets& assets) override;
|
virtual void draw(const DrawContext& pctx, const Assets& assets)
|
||||||
|
override;
|
||||||
|
|
||||||
virtual void mouseRelease(GUI*, int x, int y) override;
|
virtual void mouseRelease(int x, int y) override;
|
||||||
|
|
||||||
virtual void setSupplier(boolsupplier supplier);
|
virtual void setSupplier(boolsupplier supplier);
|
||||||
virtual void setConsumer(boolconsumer consumer);
|
virtual void setConsumer(boolconsumer consumer);
|
||||||
@ -25,8 +26,7 @@ namespace gui {
|
|||||||
virtual CheckBox* setChecked(bool flag);
|
virtual CheckBox* setChecked(bool flag);
|
||||||
|
|
||||||
virtual bool isChecked() const {
|
virtual bool isChecked() const {
|
||||||
if (supplier)
|
if (supplier) return supplier();
|
||||||
return supplier();
|
|
||||||
return checked;
|
return checked;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -36,7 +36,12 @@ namespace gui {
|
|||||||
std::shared_ptr<CheckBox> checkbox;
|
std::shared_ptr<CheckBox> checkbox;
|
||||||
std::shared_ptr<Label> label;
|
std::shared_ptr<Label> label;
|
||||||
public:
|
public:
|
||||||
FullCheckBox(const std::wstring& text, glm::vec2 size, bool checked=false);
|
explicit FullCheckBox(
|
||||||
|
GUI& gui,
|
||||||
|
const std::wstring& text,
|
||||||
|
glm::vec2 size,
|
||||||
|
bool checked = false
|
||||||
|
);
|
||||||
|
|
||||||
virtual void setSupplier(boolsupplier supplier) {
|
virtual void setSupplier(boolsupplier supplier) {
|
||||||
checkbox->setSupplier(std::move(supplier));
|
checkbox->setSupplier(std::move(supplier));
|
||||||
|
|||||||
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
using namespace gui;
|
using namespace gui;
|
||||||
|
|
||||||
Container::Container(glm::vec2 size) : UINode(size) {
|
Container::Container(GUI& gui, glm::vec2 size) : UINode(gui, size) {
|
||||||
actualLength = size.y;
|
actualLength = size.y;
|
||||||
setColor(glm::vec4());
|
setColor(glm::vec4());
|
||||||
}
|
}
|
||||||
@ -41,8 +41,8 @@ std::shared_ptr<UINode> Container::getAt(const glm::vec2& pos) {
|
|||||||
return UINode::getAt(pos);
|
return UINode::getAt(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Container::mouseMove(GUI* gui, int x, int y) {
|
void Container::mouseMove(int x, int y) {
|
||||||
UINode::mouseMove(gui, x, y);
|
UINode::mouseMove(x, y);
|
||||||
if (!scrollable) {
|
if (!scrollable) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -65,8 +65,8 @@ void Container::mouseMove(GUI* gui, int x, int y) {
|
|||||||
prevScrollY = y;
|
prevScrollY = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Container::mouseRelease(GUI* gui, int x, int y) {
|
void Container::mouseRelease(int x, int y) {
|
||||||
UINode::mouseRelease(gui, x, y);
|
UINode::mouseRelease(x, y);
|
||||||
prevScrollY = -1;
|
prevScrollY = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -7,7 +7,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace gui {
|
namespace gui {
|
||||||
class Container : public UINode, public util::ObjectsKeeper {
|
class Container : public UINode, public ::util::ObjectsKeeper {
|
||||||
int prevScrollY = -1;
|
int prevScrollY = -1;
|
||||||
protected:
|
protected:
|
||||||
std::vector<std::shared_ptr<UINode>> nodes;
|
std::vector<std::shared_ptr<UINode>> nodes;
|
||||||
@ -22,7 +22,7 @@ namespace gui {
|
|||||||
return prevScrollY != -1;
|
return prevScrollY != -1;
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
Container(glm::vec2 size);
|
Container(GUI& gui, glm::vec2 size);
|
||||||
virtual ~Container();
|
virtual ~Container();
|
||||||
|
|
||||||
virtual void act(float delta) override;
|
virtual void act(float delta) override;
|
||||||
@ -44,8 +44,8 @@ namespace gui {
|
|||||||
virtual void refresh() override;
|
virtual void refresh() override;
|
||||||
void setScroll(int scroll);
|
void setScroll(int scroll);
|
||||||
|
|
||||||
virtual void mouseMove(GUI*, int x, int y) override;
|
virtual void mouseMove(int x, int y) override;
|
||||||
virtual void mouseRelease(GUI*, int x, int y) override;
|
virtual void mouseRelease(int x, int y) override;
|
||||||
|
|
||||||
const std::vector<std::shared_ptr<UINode>>& getNodes() const;
|
const std::vector<std::shared_ptr<UINode>>& getNodes() const;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -2,16 +2,17 @@
|
|||||||
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include "graphics/core/DrawContext.hpp"
|
|
||||||
#include "graphics/core/Batch2D.hpp"
|
|
||||||
#include "graphics/core/Texture.hpp"
|
|
||||||
#include "graphics/core/Atlas.hpp"
|
|
||||||
#include "assets/Assets.hpp"
|
#include "assets/Assets.hpp"
|
||||||
|
#include "graphics/core/Atlas.hpp"
|
||||||
|
#include "graphics/core/Batch2D.hpp"
|
||||||
|
#include "graphics/core/DrawContext.hpp"
|
||||||
|
#include "graphics/core/Texture.hpp"
|
||||||
#include "maths/UVRegion.hpp"
|
#include "maths/UVRegion.hpp"
|
||||||
|
|
||||||
using namespace gui;
|
using namespace gui;
|
||||||
|
|
||||||
Image::Image(std::string texture, glm::vec2 size) : UINode(size), texture(std::move(texture)) {
|
Image::Image(GUI& gui, std::string texture, glm::vec2 size)
|
||||||
|
: UINode(gui, size), texture(std::move(texture)) {
|
||||||
setInteractive(false);
|
setInteractive(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -30,14 +31,16 @@ void Image::draw(const DrawContext& pctx, const Assets& assets) {
|
|||||||
} else {
|
} else {
|
||||||
auto atlasName = this->texture.substr(0, separator);
|
auto atlasName = this->texture.substr(0, separator);
|
||||||
if (auto atlas = assets.get<Atlas>(atlasName)) {
|
if (auto atlas = assets.get<Atlas>(atlasName)) {
|
||||||
if (auto region = atlas->getIf(this->texture.substr(separator+1))) {
|
if (auto region =
|
||||||
|
atlas->getIf(this->texture.substr(separator + 1))) {
|
||||||
texture = atlas->getTexture();
|
texture = atlas->getTexture();
|
||||||
batch->texture(atlas->getTexture());
|
batch->texture(atlas->getTexture());
|
||||||
batch->setRegion(*region);
|
batch->setRegion(*region);
|
||||||
if (autoresize) {
|
if (autoresize) {
|
||||||
setSize(glm::vec2(
|
setSize(glm::vec2(
|
||||||
texture->getWidth()*region->getWidth(),
|
texture->getWidth() * region->getWidth(),
|
||||||
texture->getHeight()*region->getHeight()));
|
texture->getHeight() * region->getHeight()
|
||||||
|
));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
batch->texture(nullptr);
|
batch->texture(nullptr);
|
||||||
@ -45,8 +48,17 @@ void Image::draw(const DrawContext& pctx, const Assets& assets) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
batch->rect(
|
batch->rect(
|
||||||
pos.x, pos.y, size.x, size.y,
|
pos.x,
|
||||||
0, 0, 0, UVRegion(), false, true, calcColor()
|
pos.y,
|
||||||
|
size.x,
|
||||||
|
size.y,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
UVRegion(),
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
calcColor()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -8,7 +8,7 @@ namespace gui {
|
|||||||
std::string texture;
|
std::string texture;
|
||||||
bool autoresize = false;
|
bool autoresize = false;
|
||||||
public:
|
public:
|
||||||
Image(std::string texture, glm::vec2 size=glm::vec2(32,32));
|
Image(GUI& gui, std::string texture, glm::vec2 size=glm::vec2(32,32));
|
||||||
|
|
||||||
virtual void draw(const DrawContext& pctx, const Assets& assets) override;
|
virtual void draw(const DrawContext& pctx, const Assets& assets) override;
|
||||||
|
|
||||||
|
|||||||
@ -7,10 +7,10 @@
|
|||||||
|
|
||||||
using namespace gui;
|
using namespace gui;
|
||||||
|
|
||||||
InputBindBox::InputBindBox(Binding& binding, glm::vec4 padding)
|
InputBindBox::InputBindBox(GUI& gui, Binding& binding, glm::vec4 padding)
|
||||||
: Panel(glm::vec2(100,32), padding, 0),
|
: Panel(gui, glm::vec2(100,32), padding, 0),
|
||||||
binding(binding),
|
binding(binding),
|
||||||
label(std::make_shared<Label>(L"")) {
|
label(std::make_shared<Label>(gui, L"")) {
|
||||||
add(label);
|
add(label);
|
||||||
setScrollable(false);
|
setScrollable(false);
|
||||||
hoverColor = glm::vec4(0.05f, 0.1f, 0.2f, 0.75f);
|
hoverColor = glm::vec4(0.05f, 0.1f, 0.2f, 0.75f);
|
||||||
@ -25,15 +25,15 @@ void InputBindBox::drawBackground(const DrawContext& pctx, const Assets&) {
|
|||||||
label->setText(util::str2wstr_utf8(binding.text()));
|
label->setText(util::str2wstr_utf8(binding.text()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputBindBox::clicked(GUI*, mousecode button) {
|
void InputBindBox::clicked(Mousecode button) {
|
||||||
if (isFocused()) {
|
if (isFocused()) {
|
||||||
binding.reset(button);
|
binding.reset(button);
|
||||||
defocus();
|
defocus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputBindBox::keyPressed(keycode key) {
|
void InputBindBox::keyPressed(Keycode key) {
|
||||||
if (key != keycode::ESCAPE) {
|
if (key != Keycode::ESCAPE) {
|
||||||
binding.reset(key);
|
binding.reset(key);
|
||||||
}
|
}
|
||||||
defocus();
|
defocus();
|
||||||
|
|||||||
@ -11,14 +11,18 @@ namespace gui {
|
|||||||
glm::vec4 focusedColor {0.1f, 0.15f, 0.35f, 0.75f};
|
glm::vec4 focusedColor {0.1f, 0.15f, 0.35f, 0.75f};
|
||||||
std::shared_ptr<Label> label;
|
std::shared_ptr<Label> label;
|
||||||
public:
|
public:
|
||||||
InputBindBox(Binding& binding, glm::vec4 padding=glm::vec4(6.0f));
|
explicit InputBindBox(
|
||||||
|
GUI& gui, Binding& binding, glm::vec4 padding = glm::vec4(6.0f)
|
||||||
|
);
|
||||||
|
|
||||||
virtual void drawBackground(
|
virtual void drawBackground(
|
||||||
const DrawContext& pctx, const Assets& assets
|
const DrawContext& pctx, const Assets& assets
|
||||||
) override;
|
) override;
|
||||||
|
|
||||||
virtual void clicked(GUI*, mousecode button) override;
|
virtual void clicked(Mousecode button) override;
|
||||||
virtual void keyPressed(keycode key) override;
|
virtual void keyPressed(Keycode key) override;
|
||||||
virtual bool isFocuskeeper() const override {return true;}
|
virtual bool isFocuskeeper() const override {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,7 +13,6 @@
|
|||||||
#include "objects/Player.hpp"
|
#include "objects/Player.hpp"
|
||||||
#include "util/stringutil.hpp"
|
#include "util/stringutil.hpp"
|
||||||
#include "voxels/Block.hpp"
|
#include "voxels/Block.hpp"
|
||||||
#include "window/Events.hpp"
|
|
||||||
#include "window/input.hpp"
|
#include "window/input.hpp"
|
||||||
#include "world/Level.hpp"
|
#include "world/Level.hpp"
|
||||||
#include "graphics/core/Atlas.hpp"
|
#include "graphics/core/Atlas.hpp"
|
||||||
@ -46,8 +45,8 @@ SlotLayout::SlotLayout(
|
|||||||
shareFunc(std::move(shareFunc)),
|
shareFunc(std::move(shareFunc)),
|
||||||
rightClick(std::move(rightClick)) {}
|
rightClick(std::move(rightClick)) {}
|
||||||
|
|
||||||
InventoryBuilder::InventoryBuilder() {
|
InventoryBuilder::InventoryBuilder(GUI& gui) : gui(gui) {
|
||||||
view = std::make_shared<InventoryView>();
|
view = std::make_shared<InventoryView>(gui);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InventoryBuilder::addGrid(
|
void InventoryBuilder::addGrid(
|
||||||
@ -75,7 +74,8 @@ void InventoryBuilder::addGrid(
|
|||||||
view->setSize(vsize);
|
view->setSize(vsize);
|
||||||
|
|
||||||
if (addpanel) {
|
if (addpanel) {
|
||||||
auto panel = std::make_shared<gui::Container>(glm::vec2(width, height));
|
auto panel =
|
||||||
|
std::make_shared<gui::Container>(gui, glm::vec2(width, height));
|
||||||
view->setColor(glm::vec4(0.122f, 0.122f, 0.122f, 0.878f));
|
view->setColor(glm::vec4(0.122f, 0.122f, 0.122f, 0.878f));
|
||||||
view->add(panel, pos);
|
view->add(panel, pos);
|
||||||
}
|
}
|
||||||
@ -106,8 +106,8 @@ std::shared_ptr<InventoryView> InventoryBuilder::build() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SlotView::SlotView(
|
SlotView::SlotView(
|
||||||
SlotLayout layout
|
GUI& gui, SlotLayout layout
|
||||||
) : UINode(glm::vec2(InventoryView::SLOT_SIZE)),
|
) : UINode(gui, glm::vec2(InventoryView::SLOT_SIZE)),
|
||||||
layout(std::move(layout))
|
layout(std::move(layout))
|
||||||
{
|
{
|
||||||
setColor(glm::vec4(0, 0, 0, 0.2f));
|
setColor(glm::vec4(0, 0, 0, 0.2f));
|
||||||
@ -280,7 +280,8 @@ bool SlotView::isHighlighted() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SlotView::performLeftClick(ItemStack& stack, ItemStack& grabbed) {
|
void SlotView::performLeftClick(ItemStack& stack, ItemStack& grabbed) {
|
||||||
if (layout.taking && Events::pressed(keycode::LEFT_SHIFT)) {
|
const auto& input = gui.getInput();
|
||||||
|
if (layout.taking && input.pressed(Keycode::LEFT_SHIFT)) {
|
||||||
if (layout.shareFunc) {
|
if (layout.shareFunc) {
|
||||||
layout.shareFunc(layout.index, stack);
|
layout.shareFunc(layout.index, stack);
|
||||||
}
|
}
|
||||||
@ -347,20 +348,20 @@ void SlotView::performRightClick(ItemStack& stack, ItemStack& grabbed) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SlotView::clicked(gui::GUI* gui, mousecode button) {
|
void SlotView::clicked(Mousecode button) {
|
||||||
if (bound == nullptr)
|
if (bound == nullptr)
|
||||||
return;
|
return;
|
||||||
auto exchangeSlot =
|
auto exchangeSlot =
|
||||||
std::dynamic_pointer_cast<SlotView>(gui->get(EXCHANGE_SLOT_NAME));
|
std::dynamic_pointer_cast<SlotView>(gui.get(EXCHANGE_SLOT_NAME));
|
||||||
if (exchangeSlot == nullptr) {
|
if (exchangeSlot == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ItemStack& grabbed = exchangeSlot->getStack();
|
ItemStack& grabbed = exchangeSlot->getStack();
|
||||||
ItemStack& stack = *bound;
|
ItemStack& stack = *bound;
|
||||||
|
|
||||||
if (button == mousecode::BUTTON_1) {
|
if (button == Mousecode::BUTTON_1) {
|
||||||
performLeftClick(stack, grabbed);
|
performLeftClick(stack, grabbed);
|
||||||
} else if (button == mousecode::BUTTON_2) {
|
} else if (button == Mousecode::BUTTON_2) {
|
||||||
performRightClick(stack, grabbed);
|
performRightClick(stack, grabbed);
|
||||||
}
|
}
|
||||||
if (layout.updateFunc) {
|
if (layout.updateFunc) {
|
||||||
@ -368,8 +369,8 @@ void SlotView::clicked(gui::GUI* gui, mousecode button) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SlotView::onFocus(gui::GUI* gui) {
|
void SlotView::onFocus() {
|
||||||
clicked(gui, mousecode::BUTTON_1);
|
clicked(Mousecode::BUTTON_1);
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::wstring& SlotView::getTooltip() const {
|
const std::wstring& SlotView::getTooltip() const {
|
||||||
@ -398,7 +399,7 @@ ItemStack& SlotView::getStack() {
|
|||||||
return *bound;
|
return *bound;
|
||||||
}
|
}
|
||||||
|
|
||||||
InventoryView::InventoryView() : Container(glm::vec2()) {
|
InventoryView::InventoryView(GUI& gui) : Container(gui, glm::vec2()) {
|
||||||
setColor(glm::vec4(0, 0, 0, 0.0f));
|
setColor(glm::vec4(0, 0, 0, 0.0f));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -419,7 +420,7 @@ std::shared_ptr<SlotView> InventoryView::addSlot(const SlotLayout& layout) {
|
|||||||
}
|
}
|
||||||
setSize(vsize);
|
setSize(vsize);
|
||||||
|
|
||||||
auto slot = std::make_shared<SlotView>(layout);
|
auto slot = std::make_shared<SlotView>(gui, layout);
|
||||||
if (!layout.background) {
|
if (!layout.background) {
|
||||||
slot->setColor(glm::vec4());
|
slot->setColor(glm::vec4());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -86,15 +86,15 @@ namespace gui {
|
|||||||
|
|
||||||
void refreshTooltip(const ItemStack& stack, const ItemDef& item);
|
void refreshTooltip(const ItemStack& stack, const ItemDef& item);
|
||||||
public:
|
public:
|
||||||
SlotView(SlotLayout layout);
|
SlotView(GUI& gui, SlotLayout layout);
|
||||||
|
|
||||||
virtual void draw(const DrawContext& pctx, const Assets& assets) override;
|
virtual void draw(const DrawContext& pctx, const Assets& assets) override;
|
||||||
|
|
||||||
void setHighlighted(bool flag);
|
void setHighlighted(bool flag);
|
||||||
bool isHighlighted() const;
|
bool isHighlighted() const;
|
||||||
|
|
||||||
virtual void clicked(gui::GUI*, mousecode) override;
|
virtual void clicked(Mousecode) override;
|
||||||
virtual void onFocus(gui::GUI*) override;
|
virtual void onFocus() override;
|
||||||
virtual const std::wstring& getTooltip() const override;
|
virtual const std::wstring& getTooltip() const override;
|
||||||
|
|
||||||
void bind(
|
void bind(
|
||||||
@ -117,7 +117,7 @@ namespace gui {
|
|||||||
std::vector<SlotView*> slots;
|
std::vector<SlotView*> slots;
|
||||||
glm::vec2 origin {};
|
glm::vec2 origin {};
|
||||||
public:
|
public:
|
||||||
InventoryView();
|
InventoryView(GUI& gui);
|
||||||
virtual ~InventoryView();
|
virtual ~InventoryView();
|
||||||
|
|
||||||
virtual void setPos(glm::vec2 pos) override;
|
virtual void setPos(glm::vec2 pos) override;
|
||||||
@ -145,9 +145,10 @@ namespace gui {
|
|||||||
};
|
};
|
||||||
|
|
||||||
class InventoryBuilder {
|
class InventoryBuilder {
|
||||||
|
GUI& gui;
|
||||||
std::shared_ptr<InventoryView> view;
|
std::shared_ptr<InventoryView> view;
|
||||||
public:
|
public:
|
||||||
InventoryBuilder();
|
InventoryBuilder(GUI& gui);
|
||||||
|
|
||||||
/// @brief Add slots grid to inventory view
|
/// @brief Add slots grid to inventory view
|
||||||
/// @param cols grid columns
|
/// @param cols grid columns
|
||||||
|
|||||||
@ -83,8 +83,8 @@ void LabelCache::update(std::wstring_view text, bool multiline, bool wrap) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Label::Label(const std::string& text, std::string fontName)
|
Label::Label(GUI& gui, const std::string& text, std::string fontName)
|
||||||
: UINode(glm::vec2(text.length() * 8, 16)),
|
: UINode(gui, glm::vec2(text.length() * 8, 16)),
|
||||||
text(util::str2wstr_utf8(text)),
|
text(util::str2wstr_utf8(text)),
|
||||||
fontName(std::move(fontName))
|
fontName(std::move(fontName))
|
||||||
{
|
{
|
||||||
@ -93,8 +93,8 @@ Label::Label(const std::string& text, std::string fontName)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Label::Label(const std::wstring& text, std::string fontName)
|
Label::Label(GUI& gui, const std::wstring& text, std::string fontName)
|
||||||
: UINode(glm::vec2(text.length() * 8, 16)),
|
: UINode(gui, glm::vec2(text.length() * 8, 16)),
|
||||||
text(text),
|
text(text),
|
||||||
fontName(std::move(fontName))
|
fontName(std::move(fontName))
|
||||||
{
|
{
|
||||||
@ -237,8 +237,8 @@ void Label::draw(const DrawContext& pctx, const Assets& assets) {
|
|||||||
textYOffset = pos.y-calcPos().y;
|
textYOffset = pos.y-calcPos().y;
|
||||||
totalLineHeight = lineHeight;
|
totalLineHeight = lineHeight;
|
||||||
|
|
||||||
auto& viewport = pctx.getViewport();
|
const auto& viewport = pctx.getViewport();
|
||||||
glm::vec4 bounds {0, 0, viewport.getWidth(), viewport.getHeight()};
|
glm::vec4 bounds {0, 0, viewport.x, viewport.y};
|
||||||
if (parent) {
|
if (parent) {
|
||||||
auto ppos = parent->calcPos();
|
auto ppos = parent->calcPos();
|
||||||
auto psize = parent->getSize();
|
auto psize = parent->getSize();
|
||||||
|
|||||||
@ -63,8 +63,8 @@ namespace gui {
|
|||||||
|
|
||||||
std::unique_ptr<FontStylesScheme> styles;
|
std::unique_ptr<FontStylesScheme> styles;
|
||||||
public:
|
public:
|
||||||
Label(const std::string& text, std::string fontName=FONT_DEFAULT);
|
Label(GUI& gui, const std::string& text, std::string fontName="normal");
|
||||||
Label(const std::wstring& text, std::string fontName=FONT_DEFAULT);
|
Label(GUI& gui, const std::wstring& text, std::string fontName="normal");
|
||||||
|
|
||||||
virtual ~Label();
|
virtual ~Label();
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
using namespace gui;
|
using namespace gui;
|
||||||
|
|
||||||
Menu::Menu() : Container(glm::vec2(1)){
|
Menu::Menu(GUI& gui) : Container(gui, glm::vec2(1)){
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Menu::has(const std::string& name) {
|
bool Menu::has(const std::string& name) {
|
||||||
|
|||||||
@ -21,7 +21,7 @@ namespace gui {
|
|||||||
std::unordered_map<std::string, supplier<std::shared_ptr<UINode>>> pageSuppliers;
|
std::unordered_map<std::string, supplier<std::shared_ptr<UINode>>> pageSuppliers;
|
||||||
PageLoaderFunc pagesLoader = nullptr;
|
PageLoaderFunc pagesLoader = nullptr;
|
||||||
public:
|
public:
|
||||||
Menu();
|
explicit Menu(GUI& gui);
|
||||||
|
|
||||||
/// @brief Check menu have page or page supplier
|
/// @brief Check menu have page or page supplier
|
||||||
/// @param name page name
|
/// @param name page name
|
||||||
|
|||||||
@ -4,14 +4,12 @@
|
|||||||
|
|
||||||
using namespace gui;
|
using namespace gui;
|
||||||
|
|
||||||
Panel::Panel(glm::vec2 size, glm::vec4 padding, float interval)
|
Panel::Panel(GUI& gui, glm::vec2 size, glm::vec4 padding, float interval)
|
||||||
: BasePanel(size, padding, interval, Orientation::vertical)
|
: BasePanel(gui, size, padding, interval) {
|
||||||
{
|
|
||||||
setColor(glm::vec4(0.0f, 0.0f, 0.0f, 0.75f));
|
setColor(glm::vec4(0.0f, 0.0f, 0.0f, 0.75f));
|
||||||
}
|
}
|
||||||
|
|
||||||
Panel::~Panel() {
|
Panel::~Panel() = default;
|
||||||
}
|
|
||||||
|
|
||||||
void Panel::setMaxLength(int value) {
|
void Panel::setMaxLength(int value) {
|
||||||
maxLength = value;
|
maxLength = value;
|
||||||
@ -46,7 +44,7 @@ void Panel::fullRefresh() {
|
|||||||
Container::fullRefresh();
|
Container::fullRefresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Panel::add(const std::shared_ptr<UINode> &node) {
|
void Panel::add(const std::shared_ptr<UINode>& node) {
|
||||||
node->setResizing(true);
|
node->setResizing(true);
|
||||||
Container::add(node);
|
Container::add(node);
|
||||||
fullRefresh();
|
fullRefresh();
|
||||||
@ -80,7 +78,7 @@ void Panel::refresh() {
|
|||||||
node->refresh();
|
node->refresh();
|
||||||
glm::vec2 nodeSize = node->getSize();
|
glm::vec2 nodeSize = node->getSize();
|
||||||
y += nodeSize.y + margin.w + interval;
|
y += nodeSize.y + margin.w + interval;
|
||||||
maxw = fmax(maxw, ex+nodeSize.x+margin.z+padding.z);
|
maxw = fmax(maxw, ex + nodeSize.x + margin.z + padding.z);
|
||||||
}
|
}
|
||||||
actualLength = y + padding.w;
|
actualLength = y + padding.w;
|
||||||
} else {
|
} else {
|
||||||
@ -89,11 +87,13 @@ void Panel::refresh() {
|
|||||||
glm::vec2 nodesize = node->getSize();
|
glm::vec2 nodesize = node->getSize();
|
||||||
const glm::vec4 margin = node->getMargin();
|
const glm::vec4 margin = node->getMargin();
|
||||||
x += margin.x;
|
x += margin.x;
|
||||||
node->setPos(glm::vec2(x, y+margin.y));
|
node->setPos(glm::vec2(x, y + margin.y));
|
||||||
x += nodesize.x + margin.z + interval;
|
x += nodesize.x + margin.z + interval;
|
||||||
|
|
||||||
node->refresh();
|
node->refresh();
|
||||||
maxh = fmax(maxh, y+margin.y+node->getSize().y+margin.w+padding.w);
|
maxh = fmax(
|
||||||
|
maxh, y + margin.y + node->getSize().y + margin.w + padding.w
|
||||||
|
);
|
||||||
}
|
}
|
||||||
actualLength = size.y;
|
actualLength = size.y;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,15 +1,16 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "commons.hpp"
|
|
||||||
#include "BasePanel.hpp"
|
#include "BasePanel.hpp"
|
||||||
|
#include "commons.hpp"
|
||||||
|
|
||||||
namespace gui {
|
namespace gui {
|
||||||
class Panel : public BasePanel {
|
class Panel : public BasePanel {
|
||||||
public:
|
public:
|
||||||
Panel(
|
Panel(
|
||||||
|
GUI& gui,
|
||||||
glm::vec2 size,
|
glm::vec2 size,
|
||||||
glm::vec4 padding=glm::vec4(0.0f),
|
glm::vec4 padding = glm::vec4(2.0f),
|
||||||
float interval=2.0f
|
float interval = 2.0f
|
||||||
);
|
);
|
||||||
virtual ~Panel();
|
virtual ~Panel();
|
||||||
|
|
||||||
|
|||||||
@ -1,15 +1,16 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
#include "UINode.hpp"
|
#include "UINode.hpp"
|
||||||
#include "typedefs.hpp"
|
#include "typedefs.hpp"
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
class Assets;
|
class Assets;
|
||||||
class DrawContext;
|
class DrawContext;
|
||||||
|
|
||||||
namespace gui {
|
namespace gui {
|
||||||
class Plotter : public gui::UINode {
|
class Plotter : public UINode {
|
||||||
std::unique_ptr<int[]> points;
|
std::unique_ptr<int[]> points;
|
||||||
float multiplier;
|
float multiplier;
|
||||||
int index = 0;
|
int index = 0;
|
||||||
@ -17,13 +18,18 @@ namespace gui {
|
|||||||
int dmheight;
|
int dmheight;
|
||||||
int labelsInterval;
|
int labelsInterval;
|
||||||
public:
|
public:
|
||||||
Plotter(uint width, uint height, float multiplier, int labelsInterval)
|
Plotter(
|
||||||
: gui::UINode(glm::vec2(width, height)),
|
GUI& gui,
|
||||||
|
uint width,
|
||||||
|
uint height,
|
||||||
|
float multiplier,
|
||||||
|
int labelsInterval
|
||||||
|
)
|
||||||
|
: UINode(gui, glm::vec2(width, height)),
|
||||||
multiplier(multiplier),
|
multiplier(multiplier),
|
||||||
dmwidth(width-50),
|
dmwidth(width - 50),
|
||||||
dmheight(height),
|
dmheight(height),
|
||||||
labelsInterval(labelsInterval)
|
labelsInterval(labelsInterval) {
|
||||||
{
|
|
||||||
points = std::make_unique<int[]>(dmwidth);
|
points = std::make_unique<int[]>(dmwidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2,15 +2,15 @@
|
|||||||
|
|
||||||
using namespace gui;
|
using namespace gui;
|
||||||
|
|
||||||
SplitBox::SplitBox(const glm::vec2& size, float splitPos, Orientation orientation)
|
SplitBox::SplitBox(GUI& gui, const glm::vec2& size, float splitPos, Orientation orientation)
|
||||||
: BasePanel(size, glm::vec4(), 4.0f, orientation), splitPos(splitPos) {
|
: BasePanel(gui, size, glm::vec4(), 4.0f, orientation), splitPos(splitPos) {
|
||||||
setCursor(
|
setCursor(
|
||||||
orientation == Orientation::vertical ? CursorShape::NS_RESIZE
|
orientation == Orientation::vertical ? CursorShape::NS_RESIZE
|
||||||
: CursorShape::EW_RESIZE
|
: CursorShape::EW_RESIZE
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SplitBox::mouseMove(GUI*, int x, int y) {
|
void SplitBox::mouseMove(int x, int y) {
|
||||||
auto pos = calcPos();
|
auto pos = calcPos();
|
||||||
auto size = getSize();
|
auto size = getSize();
|
||||||
|
|
||||||
@ -59,7 +59,7 @@ void SplitBox::refresh() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SplitBox::doubleClick(GUI*, int x, int y) {
|
void SplitBox::doubleClick(int x, int y) {
|
||||||
if (nodes.size() < 2) {
|
if (nodes.size() < 2) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,12 +5,12 @@
|
|||||||
namespace gui {
|
namespace gui {
|
||||||
class SplitBox : public BasePanel {
|
class SplitBox : public BasePanel {
|
||||||
public:
|
public:
|
||||||
SplitBox(const glm::vec2& size, float splitPos, Orientation orientation);
|
SplitBox(GUI& gui, const glm::vec2& size, float splitPos, Orientation orientation);
|
||||||
|
|
||||||
virtual void mouseMove(GUI*, int x, int y) override;
|
virtual void mouseMove(int x, int y) override;
|
||||||
virtual void refresh() override;
|
virtual void refresh() override;
|
||||||
virtual void fullRefresh() override;
|
virtual void fullRefresh() override;
|
||||||
virtual void doubleClick(GUI*, int x, int y) override;
|
virtual void doubleClick(int x, int y) override;
|
||||||
private:
|
private:
|
||||||
float splitPos;
|
float splitPos;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -4,15 +4,17 @@
|
|||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
#include "../GUI.hpp"
|
||||||
|
#include "../markdown.hpp"
|
||||||
#include "Label.hpp"
|
#include "Label.hpp"
|
||||||
#include "assets/Assets.hpp"
|
#include "assets/Assets.hpp"
|
||||||
#include "devtools/syntax_highlighting.hpp"
|
#include "devtools/syntax_highlighting.hpp"
|
||||||
|
#include "engine/Engine.hpp"
|
||||||
#include "graphics/core/Batch2D.hpp"
|
#include "graphics/core/Batch2D.hpp"
|
||||||
#include "graphics/core/DrawContext.hpp"
|
#include "graphics/core/DrawContext.hpp"
|
||||||
#include "graphics/core/Font.hpp"
|
#include "graphics/core/Font.hpp"
|
||||||
#include "graphics/ui/markdown.hpp"
|
#include "graphics/ui/markdown.hpp"
|
||||||
#include "util/stringutil.hpp"
|
#include "util/stringutil.hpp"
|
||||||
#include "window/Events.hpp"
|
|
||||||
#include "window/Window.hpp"
|
#include "window/Window.hpp"
|
||||||
#include "devtools/actions.hpp"
|
#include "devtools/actions.hpp"
|
||||||
#include "../markdown.hpp"
|
#include "../markdown.hpp"
|
||||||
@ -186,8 +188,9 @@ namespace gui {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
TextBox::TextBox(std::wstring placeholder, glm::vec4 padding)
|
TextBox::TextBox(GUI& gui, std::wstring placeholder, glm::vec4 padding)
|
||||||
: Container(glm::vec2(200, 32)),
|
: Container(gui, glm::vec2(200, 32)),
|
||||||
|
inputEvents(gui.getInput()),
|
||||||
history(std::make_shared<ActionsHistory>()),
|
history(std::make_shared<ActionsHistory>()),
|
||||||
historian(std::make_unique<TextBoxHistorian>(*this, *history)),
|
historian(std::make_unique<TextBoxHistorian>(*this, *history)),
|
||||||
padding(padding),
|
padding(padding),
|
||||||
@ -197,16 +200,21 @@ TextBox::TextBox(std::wstring placeholder, glm::vec4 padding)
|
|||||||
setOnUpPressed(nullptr);
|
setOnUpPressed(nullptr);
|
||||||
setOnDownPressed(nullptr);
|
setOnDownPressed(nullptr);
|
||||||
setColor(glm::vec4(0.0f, 0.0f, 0.0f, 0.75f));
|
setColor(glm::vec4(0.0f, 0.0f, 0.0f, 0.75f));
|
||||||
label = std::make_shared<Label>(L"");
|
|
||||||
label->setSize(size-glm::vec2(padding.z+padding.x, padding.w+padding.y));
|
label = std::make_shared<Label>(gui, L"");
|
||||||
|
label->setSize(
|
||||||
|
size - glm::vec2(padding.z + padding.x, padding.w + padding.y)
|
||||||
|
);
|
||||||
label->setPos(glm::vec2(
|
label->setPos(glm::vec2(
|
||||||
padding.x + LINE_NUMBERS_PANE_WIDTH * showLineNumbers, padding.y
|
padding.x + LINE_NUMBERS_PANE_WIDTH * showLineNumbers, padding.y
|
||||||
));
|
));
|
||||||
add(label);
|
add(label);
|
||||||
|
|
||||||
lineNumbersLabel = std::make_shared<Label>(L"");
|
lineNumbersLabel = std::make_shared<Label>(gui, L"");
|
||||||
lineNumbersLabel->setMultiline(true);
|
lineNumbersLabel->setMultiline(true);
|
||||||
lineNumbersLabel->setSize(size-glm::vec2(padding.z+padding.x, padding.w+padding.y));
|
lineNumbersLabel->setSize(
|
||||||
|
size - glm::vec2(padding.z + padding.x, padding.w + padding.y)
|
||||||
|
);
|
||||||
lineNumbersLabel->setVerticalAlign(Align::top);
|
lineNumbersLabel->setVerticalAlign(Align::top);
|
||||||
add(lineNumbersLabel);
|
add(lineNumbersLabel);
|
||||||
|
|
||||||
@ -242,7 +250,9 @@ void TextBox::draw(const DrawContext& pctx, const Assets& assets) {
|
|||||||
batch->texture(nullptr);
|
batch->texture(nullptr);
|
||||||
batch->setColor(glm::vec4(1.0f));
|
batch->setColor(glm::vec4(1.0f));
|
||||||
|
|
||||||
if (editable && int((Window::time() - caretLastMove) * 2) % 2 == 0) {
|
float time = gui.getWindow().time();
|
||||||
|
|
||||||
|
if (editable && static_cast<int>((time - caretLastMove) * 2) % 2 == 0) {
|
||||||
uint line = rawTextCache.getLineByTextIndex(caret);
|
uint line = rawTextCache.getLineByTextIndex(caret);
|
||||||
uint lcaret = caret - rawTextCache.getTextLineOffset(line);
|
uint lcaret = caret - rawTextCache.getTextLineOffset(line);
|
||||||
int width = font->calcWidth(input, lcaret);
|
int width = font->calcWidth(input, lcaret);
|
||||||
@ -342,7 +352,7 @@ void TextBox::drawBackground(const DrawContext& pctx, const Assets&) {
|
|||||||
batch->texture(nullptr);
|
batch->texture(nullptr);
|
||||||
|
|
||||||
auto subctx = pctx.sub();
|
auto subctx = pctx.sub();
|
||||||
subctx.setScissors(glm::vec4(pos.x, pos.y-0.5, size.x, size.y+1));
|
subctx.setScissors(glm::vec4(pos.x, pos.y - 0.5, size.x, size.y + 1));
|
||||||
|
|
||||||
if (valid) {
|
if (valid) {
|
||||||
if (isFocused() && !multiline) {
|
if (isFocused() && !multiline) {
|
||||||
@ -371,7 +381,8 @@ void TextBox::refreshLabel() {
|
|||||||
|
|
||||||
const auto& displayText = input.empty() && !hint.empty() ? hint : getText();
|
const auto& displayText = input.empty() && !hint.empty() ? hint : getText();
|
||||||
if (markup == "md") {
|
if (markup == "md") {
|
||||||
auto [processedText, styles] = markdown::process(displayText, !focused || !editable);
|
auto [processedText, styles] =
|
||||||
|
markdown::process(displayText, !focused || !editable);
|
||||||
label->setText(std::move(processedText));
|
label->setText(std::move(processedText));
|
||||||
label->setStyles(std::move(styles));
|
label->setStyles(std::move(styles));
|
||||||
} else {
|
} else {
|
||||||
@ -386,7 +397,7 @@ void TextBox::refreshLabel() {
|
|||||||
std::wstringstream ss;
|
std::wstringstream ss;
|
||||||
int n = 1;
|
int n = 1;
|
||||||
for (int i = 1; i <= label->getLinesNumber(); i++) {
|
for (int i = 1; i <= label->getLinesNumber(); i++) {
|
||||||
if (!label->isFakeLine(i-1)) {
|
if (!label->isFakeLine(i - 1)) {
|
||||||
ss << n;
|
ss << n;
|
||||||
n++;
|
n++;
|
||||||
}
|
}
|
||||||
@ -402,11 +413,12 @@ void TextBox::refreshLabel() {
|
|||||||
|
|
||||||
if (autoresize && font) {
|
if (autoresize && font) {
|
||||||
auto size = getSize();
|
auto size = getSize();
|
||||||
int newy = glm::min(static_cast<int>(parent->getSize().y),
|
int newy = glm::min(
|
||||||
|
static_cast<int>(parent->getSize().y),
|
||||||
static_cast<int>(
|
static_cast<int>(
|
||||||
label->getLinesNumber() *
|
label->getLinesNumber() * label->getLineInterval() *
|
||||||
label->getLineInterval() *
|
font->getLineHeight()
|
||||||
font->getLineHeight()) + 1
|
) + 1
|
||||||
);
|
);
|
||||||
if (newy != static_cast<int>(size.y)) {
|
if (newy != static_cast<int>(size.y)) {
|
||||||
size.y = newy;
|
size.y = newy;
|
||||||
@ -475,7 +487,7 @@ bool TextBox::eraseSelected() {
|
|||||||
input.substr(selectionStart, selectionEnd - selectionStart),
|
input.substr(selectionStart, selectionEnd - selectionStart),
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
erase(selectionStart, selectionEnd-selectionStart);
|
erase(selectionStart, selectionEnd - selectionStart);
|
||||||
resetSelection();
|
resetSelection();
|
||||||
onInput();
|
onInput();
|
||||||
return true;
|
return true;
|
||||||
@ -495,7 +507,7 @@ void TextBox::extendSelection(int index) {
|
|||||||
|
|
||||||
size_t TextBox::getLineLength(uint line) const {
|
size_t TextBox::getLineLength(uint line) const {
|
||||||
size_t position = label->getTextLineOffset(line);
|
size_t position = label->getTextLineOffset(line);
|
||||||
size_t lineLength = label->getTextLineOffset(line+1)-position;
|
size_t lineLength = label->getTextLineOffset(line + 1) - position;
|
||||||
if (lineLength == 0) {
|
if (lineLength == 0) {
|
||||||
lineLength = label->getText().length() - position + 1;
|
lineLength = label->getText().length() - position + 1;
|
||||||
}
|
}
|
||||||
@ -593,9 +605,9 @@ bool TextBox::isAutoResize() const {
|
|||||||
return autoresize;
|
return autoresize;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextBox::onFocus(GUI* gui) {
|
void TextBox::onFocus() {
|
||||||
Container::onFocus(gui);
|
Container::onFocus();
|
||||||
if (onEditStart){
|
if (onEditStart) {
|
||||||
setCaret(input.size());
|
setCaret(input.size());
|
||||||
onEditStart();
|
onEditStart();
|
||||||
resetSelection();
|
resetSelection();
|
||||||
@ -609,7 +621,9 @@ void TextBox::reposition() {
|
|||||||
|
|
||||||
void TextBox::refresh() {
|
void TextBox::refresh() {
|
||||||
Container::refresh();
|
Container::refresh();
|
||||||
label->setSize(size-glm::vec2(padding.z+padding.x, padding.w+padding.y));
|
label->setSize(
|
||||||
|
size - glm::vec2(padding.z + padding.x, padding.w + padding.y)
|
||||||
|
);
|
||||||
label->setPos(glm::vec2(
|
label->setPos(glm::vec2(
|
||||||
padding.x + LINE_NUMBERS_PANE_WIDTH * showLineNumbers + textInitX -
|
padding.x + LINE_NUMBERS_PANE_WIDTH * showLineNumbers + textInitX -
|
||||||
static_cast<int>(textOffset),
|
static_cast<int>(textOffset),
|
||||||
@ -629,24 +643,27 @@ size_t TextBox::normalizeIndex(int index) {
|
|||||||
/// @param y screen Y position
|
/// @param y screen Y position
|
||||||
/// @return non-normalized character index
|
/// @return non-normalized character index
|
||||||
int TextBox::calcIndexAt(int x, int y) const {
|
int TextBox::calcIndexAt(int x, int y) const {
|
||||||
if (font == nullptr)
|
if (font == nullptr) return 0;
|
||||||
return 0;
|
|
||||||
const auto& labelText = label->getText();
|
const auto& labelText = label->getText();
|
||||||
glm::vec2 lcoord = label->calcPos();
|
glm::vec2 lcoord = label->calcPos();
|
||||||
uint line = label->getLineByYOffset(y-lcoord.y);
|
uint line = label->getLineByYOffset(y - lcoord.y);
|
||||||
line = std::min(line, label->getLinesNumber()-1);
|
line = std::min(line, label->getLinesNumber() - 1);
|
||||||
size_t lineLength = getLineLength(line);
|
size_t lineLength = getLineLength(line);
|
||||||
uint offset = 0;
|
uint offset = 0;
|
||||||
while (lcoord.x + font->calcWidth(labelText, offset) < x && offset < lineLength-1) {
|
while (lcoord.x + font->calcWidth(labelText, offset) < x &&
|
||||||
|
offset < lineLength - 1) {
|
||||||
offset++;
|
offset++;
|
||||||
}
|
}
|
||||||
return std::min(offset+label->getTextLineOffset(line), labelText.length());
|
return std::min(
|
||||||
|
offset + label->getTextLineOffset(line), labelText.length()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline std::wstring get_alphabet(wchar_t c) {
|
static inline std::wstring get_alphabet(wchar_t c) {
|
||||||
std::wstring alphabet {c};
|
std::wstring alphabet {c};
|
||||||
if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '_') {
|
if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '_') {
|
||||||
return L"abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
return L"abcdefghijklmnopqrstuvwxyz_"
|
||||||
|
L"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
||||||
} else if (c >= '0' && c <= '9') {
|
} else if (c >= '0' && c <= '9') {
|
||||||
return L"0123456789";
|
return L"0123456789";
|
||||||
}
|
}
|
||||||
@ -674,23 +691,23 @@ void TextBox::tokenSelectAt(int index) {
|
|||||||
}
|
}
|
||||||
right++;
|
right++;
|
||||||
}
|
}
|
||||||
select(left+1, right);
|
select(left + 1, right);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextBox::doubleClick(GUI* gui, int x, int y) {
|
void TextBox::doubleClick(int x, int y) {
|
||||||
UINode::doubleClick(gui, x, y);
|
UINode::doubleClick(x, y);
|
||||||
tokenSelectAt(normalizeIndex(calcIndexAt(x, y)-1));
|
tokenSelectAt(normalizeIndex(calcIndexAt(x, y) - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextBox::click(GUI*, int x, int y) {
|
void TextBox::click(int x, int y) {
|
||||||
int index = normalizeIndex(calcIndexAt(x, y));
|
int index = normalizeIndex(calcIndexAt(x, y));
|
||||||
selectionStart = index;
|
selectionStart = index;
|
||||||
selectionEnd = index;
|
selectionEnd = index;
|
||||||
selectionOrigin = index;
|
selectionOrigin = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextBox::mouseMove(GUI* gui, int x, int y) {
|
void TextBox::mouseMove(int x, int y) {
|
||||||
Container::mouseMove(gui, x, y);
|
Container::mouseMove(x, y);
|
||||||
if (isScrolling()) {
|
if (isScrolling()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -701,7 +718,8 @@ void TextBox::mouseMove(GUI* gui, int x, int y) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TextBox::resetMaxLocalCaret() {
|
void TextBox::resetMaxLocalCaret() {
|
||||||
maxLocalCaret = caret - label->getTextLineOffset(label->getLineByTextIndex(caret));
|
maxLocalCaret =
|
||||||
|
caret - label->getTextLineOffset(label->getLineByTextIndex(caret));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextBox::stepLeft(bool shiftPressed, bool breakSelection) {
|
void TextBox::stepLeft(bool shiftPressed, bool breakSelection) {
|
||||||
@ -709,9 +727,9 @@ void TextBox::stepLeft(bool shiftPressed, bool breakSelection) {
|
|||||||
size_t caret = breakSelection ? selectionStart : this->caret;
|
size_t caret = breakSelection ? selectionStart : this->caret;
|
||||||
if (caret > 0) {
|
if (caret > 0) {
|
||||||
if (caret > input.length()) {
|
if (caret > input.length()) {
|
||||||
setCaret(input.length()-1);
|
setCaret(input.length() - 1);
|
||||||
} else {
|
} else {
|
||||||
setCaret(caret-1);
|
setCaret(caret - 1);
|
||||||
}
|
}
|
||||||
if (shiftPressed) {
|
if (shiftPressed) {
|
||||||
if (selectionStart == selectionEnd) {
|
if (selectionStart == selectionEnd) {
|
||||||
@ -732,8 +750,8 @@ void TextBox::stepRight(bool shiftPressed, bool breakSelection) {
|
|||||||
uint previousCaret = this->caret;
|
uint previousCaret = this->caret;
|
||||||
size_t caret = breakSelection ? selectionEnd : this->caret;
|
size_t caret = breakSelection ? selectionEnd : this->caret;
|
||||||
if (caret < input.length()) {
|
if (caret < input.length()) {
|
||||||
setCaret(caret+1);
|
setCaret(caret + 1);
|
||||||
caretLastMove = Window::time();
|
caretLastMove = gui.getWindow().time();
|
||||||
if (shiftPressed) {
|
if (shiftPressed) {
|
||||||
if (selectionStart == selectionEnd) {
|
if (selectionStart == selectionEnd) {
|
||||||
selectionOrigin = previousCaret;
|
selectionOrigin = previousCaret;
|
||||||
@ -753,9 +771,10 @@ void TextBox::stepDefaultDown(bool shiftPressed, bool breakSelection) {
|
|||||||
uint previousCaret = this->caret;
|
uint previousCaret = this->caret;
|
||||||
uint caret = breakSelection ? selectionEnd : this->caret;
|
uint caret = breakSelection ? selectionEnd : this->caret;
|
||||||
uint caretLine = label->getLineByTextIndex(caret);
|
uint caretLine = label->getLineByTextIndex(caret);
|
||||||
if (caretLine < label->getLinesNumber()-1) {
|
if (caretLine < label->getLinesNumber() - 1) {
|
||||||
uint offset = std::min(size_t(maxLocalCaret), getLineLength(caretLine+1)-1);
|
uint offset =
|
||||||
setCaret(label->getTextLineOffset(caretLine+1) + offset);
|
std::min(size_t(maxLocalCaret), getLineLength(caretLine + 1) - 1);
|
||||||
|
setCaret(label->getTextLineOffset(caretLine + 1) + offset);
|
||||||
} else {
|
} else {
|
||||||
setCaret(input.length());
|
setCaret(input.length());
|
||||||
}
|
}
|
||||||
@ -774,8 +793,9 @@ void TextBox::stepDefaultUp(bool shiftPressed, bool breakSelection) {
|
|||||||
uint caret = breakSelection ? selectionStart : this->caret;
|
uint caret = breakSelection ? selectionStart : this->caret;
|
||||||
uint caretLine = label->getLineByTextIndex(caret);
|
uint caretLine = label->getLineByTextIndex(caret);
|
||||||
if (caretLine > 0) {
|
if (caretLine > 0) {
|
||||||
uint offset = std::min(size_t(maxLocalCaret), getLineLength(caretLine-1)-1);
|
uint offset =
|
||||||
setCaret(label->getTextLineOffset(caretLine-1) + offset);
|
std::min(size_t(maxLocalCaret), getLineLength(caretLine - 1) - 1);
|
||||||
|
setCaret(label->getTextLineOffset(caretLine - 1) + offset);
|
||||||
} else {
|
} else {
|
||||||
setCaret(static_cast<size_t>(0));
|
setCaret(static_cast<size_t>(0));
|
||||||
}
|
}
|
||||||
@ -804,22 +824,22 @@ void TextBox::onInput() {
|
|||||||
refreshSyntax();
|
refreshSyntax();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextBox::performEditingKeyboardEvents(keycode key) {
|
void TextBox::performEditingKeyboardEvents(Keycode key) {
|
||||||
bool shiftPressed = Events::pressed(keycode::LEFT_SHIFT);
|
bool shiftPressed = gui.getInput().pressed(Keycode::LEFT_SHIFT);
|
||||||
bool breakSelection = getSelectionLength() != 0 && !shiftPressed;
|
bool breakSelection = getSelectionLength() != 0 && !shiftPressed;
|
||||||
if (key == keycode::BACKSPACE) {
|
if (key == Keycode::BACKSPACE) {
|
||||||
if (!eraseSelected() && caret > 0 && input.length() > 0) {
|
if (!eraseSelected() && caret > 0 && input.length() > 0) {
|
||||||
if (caret > input.length()) {
|
if (caret > input.length()) {
|
||||||
caret = input.length();
|
caret = input.length();
|
||||||
}
|
}
|
||||||
historian->onErase(caret - 1, input.substr(caret - 1, 1));
|
historian->onErase(caret - 1, input.substr(caret - 1, 1));
|
||||||
input = input.substr(0, caret-1) + input.substr(caret);
|
input = input.substr(0, caret - 1) + input.substr(caret);
|
||||||
setCaret(caret-1);
|
setCaret(caret - 1);
|
||||||
if (validate()) {
|
if (validate()) {
|
||||||
onInput();
|
onInput();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (key == keycode::DELETE) {
|
} else if (key == Keycode::DELETE) {
|
||||||
if (!eraseSelected() && caret < input.length()) {
|
if (!eraseSelected() && caret < input.length()) {
|
||||||
historian->onErase(caret, input.substr(caret, 1));
|
historian->onErase(caret, input.substr(caret, 1));
|
||||||
input = input.substr(0, caret) + input.substr(caret + 1);
|
input = input.substr(0, caret) + input.substr(caret + 1);
|
||||||
@ -827,7 +847,7 @@ void TextBox::performEditingKeyboardEvents(keycode key) {
|
|||||||
onInput();
|
onInput();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (key == keycode::ENTER) {
|
} else if (key == Keycode::ENTER) {
|
||||||
if (multiline) {
|
if (multiline) {
|
||||||
paste(L"\n");
|
paste(L"\n");
|
||||||
} else {
|
} else {
|
||||||
@ -836,42 +856,43 @@ void TextBox::performEditingKeyboardEvents(keycode key) {
|
|||||||
consumer(getText());
|
consumer(getText());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (key == keycode::TAB) {
|
} else if (key == Keycode::TAB) {
|
||||||
paste(L" ");
|
paste(L" ");
|
||||||
} else if (key == keycode::LEFT) {
|
} else if (key == Keycode::LEFT) {
|
||||||
stepLeft(shiftPressed, breakSelection);
|
stepLeft(shiftPressed, breakSelection);
|
||||||
} else if (key == keycode::RIGHT) {
|
} else if (key == Keycode::RIGHT) {
|
||||||
stepRight(shiftPressed, breakSelection);
|
stepRight(shiftPressed, breakSelection);
|
||||||
} else if (key == keycode::UP && onUpPressed) {
|
} else if (key == Keycode::UP && onUpPressed) {
|
||||||
onUpPressed();
|
onUpPressed();
|
||||||
} else if (key == keycode::DOWN && onDownPressed) {
|
} else if (key == Keycode::DOWN && onDownPressed) {
|
||||||
onDownPressed();
|
onDownPressed();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextBox::keyPressed(keycode key) {
|
void TextBox::keyPressed(Keycode key) {
|
||||||
|
const auto& inputEvents = gui.getInput();
|
||||||
if (editable) {
|
if (editable) {
|
||||||
performEditingKeyboardEvents(key);
|
performEditingKeyboardEvents(key);
|
||||||
}
|
}
|
||||||
if (Events::pressed(keycode::LEFT_CONTROL) && key != keycode::LEFT_CONTROL) {
|
if (inputEvents.pressed(Keycode::LEFT_CONTROL) && key != Keycode::LEFT_CONTROL) {
|
||||||
if (controlCombinationsHandler) {
|
if (controlCombinationsHandler) {
|
||||||
if (controlCombinationsHandler(static_cast<int>(key))) {
|
if (controlCombinationsHandler(static_cast<int>(key))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Copy selected text to clipboard
|
// Copy selected text to clipboard
|
||||||
if (key == keycode::C || key == keycode::X) {
|
if (key == Keycode::C || key == Keycode::X) {
|
||||||
std::string text = util::wstr2str_utf8(getSelection());
|
std::string text = util::wstr2str_utf8(getSelection());
|
||||||
if (!text.empty()) {
|
if (!text.empty()) {
|
||||||
Window::setClipboardText(text.c_str());
|
gui.getInput().setClipboardText(text.c_str());
|
||||||
}
|
}
|
||||||
if (editable && key == keycode::X) {
|
if (editable && key == Keycode::X) {
|
||||||
eraseSelected();
|
eraseSelected();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Paste text from clipboard
|
// Paste text from clipboard
|
||||||
if (key == keycode::V && editable) {
|
if (key == Keycode::V && editable) {
|
||||||
const char* text = Window::getClipboardText();
|
const char* text = inputEvents.getClipboardText();
|
||||||
if (text) {
|
if (text) {
|
||||||
historian->sync(); // flush buffer before combination
|
historian->sync(); // flush buffer before combination
|
||||||
// Combine deleting selected text and pasing a clipboard content
|
// Combine deleting selected text and pasing a clipboard content
|
||||||
@ -881,18 +902,18 @@ void TextBox::keyPressed(keycode key) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Select/deselect all
|
// Select/deselect all
|
||||||
if (key == keycode::A) {
|
if (key == Keycode::A) {
|
||||||
if (selectionStart == selectionEnd) {
|
if (selectionStart == selectionEnd) {
|
||||||
select(0, input.length());
|
select(0, input.length());
|
||||||
} else {
|
} else {
|
||||||
resetSelection();
|
resetSelection();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (key == keycode::Z) {
|
if (key == Keycode::Z) {
|
||||||
historian->undo();
|
historian->undo();
|
||||||
refreshSyntax();
|
refreshSyntax();
|
||||||
}
|
}
|
||||||
if (key == keycode::Y) {
|
if (key == Keycode::Y) {
|
||||||
historian->redo();
|
historian->redo();
|
||||||
refreshSyntax();
|
refreshSyntax();
|
||||||
}
|
}
|
||||||
@ -924,14 +945,14 @@ std::shared_ptr<UINode> TextBox::getAt(const glm::vec2& pos) {
|
|||||||
return UINode::getAt(pos);
|
return UINode::getAt(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextBox::setOnUpPressed(const runnable &callback) {
|
void TextBox::setOnUpPressed(const runnable& callback) {
|
||||||
if (callback == nullptr) {
|
if (callback == nullptr) {
|
||||||
onUpPressed = [this]() {
|
onUpPressed = [this]() {
|
||||||
if (Events::pressed(keycode::LEFT_CONTROL)) {
|
if (inputEvents.pressed(Keycode::LEFT_CONTROL)) {
|
||||||
scrolled(1);
|
scrolled(1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
bool shiftPressed = Events::pressed(keycode::LEFT_SHIFT);
|
bool shiftPressed = inputEvents.pressed(Keycode::LEFT_SHIFT);
|
||||||
bool breakSelection = getSelectionLength() != 0 && !shiftPressed;
|
bool breakSelection = getSelectionLength() != 0 && !shiftPressed;
|
||||||
stepDefaultUp(shiftPressed, breakSelection);
|
stepDefaultUp(shiftPressed, breakSelection);
|
||||||
};
|
};
|
||||||
@ -940,14 +961,14 @@ void TextBox::setOnUpPressed(const runnable &callback) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextBox::setOnDownPressed(const runnable &callback) {
|
void TextBox::setOnDownPressed(const runnable& callback) {
|
||||||
if (callback == nullptr) {
|
if (callback == nullptr) {
|
||||||
onDownPressed = [this]() {
|
onDownPressed = [this]() {
|
||||||
if (Events::pressed(keycode::LEFT_CONTROL)) {
|
if (inputEvents.pressed(Keycode::LEFT_CONTROL)) {
|
||||||
scrolled(-1);
|
scrolled(-1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
bool shiftPressed = Events::pressed(keycode::LEFT_SHIFT);
|
bool shiftPressed = inputEvents.pressed(Keycode::LEFT_SHIFT);
|
||||||
bool breakSelection = getSelectionLength() != 0 && !shiftPressed;
|
bool breakSelection = getSelectionLength() != 0 && !shiftPressed;
|
||||||
stepDefaultDown(shiftPressed, breakSelection);
|
stepDefaultDown(shiftPressed, breakSelection);
|
||||||
};
|
};
|
||||||
@ -984,7 +1005,6 @@ glm::vec4 TextBox::getFocusedColor() const {
|
|||||||
return focusedColor;
|
return focusedColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TextBox::setTextColor(glm::vec4 color) {
|
void TextBox::setTextColor(glm::vec4 color) {
|
||||||
this->textColor = color;
|
this->textColor = color;
|
||||||
}
|
}
|
||||||
@ -1002,8 +1022,7 @@ glm::vec4 TextBox::getErrorColor() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const std::wstring& TextBox::getText() const {
|
const std::wstring& TextBox::getText() const {
|
||||||
if (input.empty())
|
if (input.empty()) return placeholder;
|
||||||
return placeholder;
|
|
||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1024,7 +1043,6 @@ void TextBox::setPlaceholder(const std::wstring& placeholder) {
|
|||||||
this->placeholder = placeholder;
|
this->placeholder = placeholder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const std::wstring& TextBox::getHint() const {
|
const std::wstring& TextBox::getHint() const {
|
||||||
return hint;
|
return hint;
|
||||||
}
|
}
|
||||||
@ -1035,7 +1053,7 @@ void TextBox::setHint(const std::wstring& text) {
|
|||||||
|
|
||||||
std::wstring TextBox::getSelection() const {
|
std::wstring TextBox::getSelection() const {
|
||||||
const auto& text = label->getText();
|
const auto& text = label->getText();
|
||||||
return text.substr(selectionStart, selectionEnd-selectionStart);
|
return text.substr(selectionStart, selectionEnd - selectionStart);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t TextBox::getCaret() const {
|
size_t TextBox::getCaret() const {
|
||||||
@ -1053,28 +1071,29 @@ void TextBox::setCaret(size_t position) {
|
|||||||
rawTextCache.prepare(font, width);
|
rawTextCache.prepare(font, width);
|
||||||
rawTextCache.update(input, multiline, label->isTextWrapping());
|
rawTextCache.update(input, multiline, label->isTextWrapping());
|
||||||
|
|
||||||
caretLastMove = Window::time();
|
caretLastMove = gui.getWindow().time();
|
||||||
|
|
||||||
uint line = rawTextCache.getLineByTextIndex(caret);
|
uint line = rawTextCache.getLineByTextIndex(caret);
|
||||||
int offset = label->getLineYOffset(line) + getContentOffset().y;
|
int offset = label->getLineYOffset(line) + getContentOffset().y;
|
||||||
uint lineHeight = font->getLineHeight()*label->getLineInterval();
|
uint lineHeight = font->getLineHeight() * label->getLineInterval();
|
||||||
if (scrollStep == 0) {
|
if (scrollStep == 0) {
|
||||||
scrollStep = lineHeight;
|
scrollStep = lineHeight;
|
||||||
}
|
}
|
||||||
if (offset < 0) {
|
if (offset < 0) {
|
||||||
scrolled(-glm::floor(offset / static_cast<double>(scrollStep)+0.5f));
|
scrolled(-glm::floor(offset / static_cast<double>(scrollStep) + 0.5f));
|
||||||
} else if (offset >= getSize().y) {
|
} else if (offset >= getSize().y) {
|
||||||
offset -= getSize().y;
|
offset -= getSize().y;
|
||||||
scrolled(-glm::ceil(offset / static_cast<double>(scrollStep)+0.5f));
|
scrolled(-glm::ceil(offset / static_cast<double>(scrollStep) + 0.5f));
|
||||||
}
|
}
|
||||||
int lcaret = caret - rawTextCache.getTextLineOffset(line);
|
int lcaret = caret - rawTextCache.getTextLineOffset(line);
|
||||||
int realoffset =
|
int realoffset =
|
||||||
font->calcWidth(labelText, lcaret) - static_cast<int>(textOffset) + 2;
|
font->calcWidth(labelText, lcaret) - static_cast<int>(textOffset) + 2;
|
||||||
|
|
||||||
if (realoffset-width > 0) {
|
if (realoffset - width > 0) {
|
||||||
setTextOffset(textOffset + realoffset-width);
|
setTextOffset(textOffset + realoffset - width);
|
||||||
} else if (realoffset < 0) {
|
} else if (realoffset < 0) {
|
||||||
setTextOffset(std::max(textOffset + realoffset, static_cast<size_t>(0)));
|
setTextOffset(std::max(textOffset + realoffset, static_cast<size_t>(0))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -9,6 +9,7 @@ class ActionsHistory;
|
|||||||
namespace gui {
|
namespace gui {
|
||||||
class TextBoxHistorian;
|
class TextBoxHistorian;
|
||||||
class TextBox : public Container {
|
class TextBox : public Container {
|
||||||
|
const Input& inputEvents;
|
||||||
LabelCache rawTextCache;
|
LabelCache rawTextCache;
|
||||||
std::shared_ptr<ActionsHistory> history;
|
std::shared_ptr<ActionsHistory> history;
|
||||||
std::unique_ptr<TextBoxHistorian> historian;
|
std::unique_ptr<TextBoxHistorian> historian;
|
||||||
@ -86,7 +87,7 @@ namespace gui {
|
|||||||
/// @brief Set maxLocalCaret to local (line) caret position
|
/// @brief Set maxLocalCaret to local (line) caret position
|
||||||
void resetMaxLocalCaret();
|
void resetMaxLocalCaret();
|
||||||
|
|
||||||
void performEditingKeyboardEvents(keycode key);
|
void performEditingKeyboardEvents(Keycode key);
|
||||||
|
|
||||||
void refreshLabel();
|
void refreshLabel();
|
||||||
|
|
||||||
@ -94,7 +95,8 @@ namespace gui {
|
|||||||
|
|
||||||
void refreshSyntax();
|
void refreshSyntax();
|
||||||
public:
|
public:
|
||||||
TextBox(
|
explicit TextBox(
|
||||||
|
GUI& gui,
|
||||||
std::wstring placeholder,
|
std::wstring placeholder,
|
||||||
glm::vec4 padding=glm::vec4(4.0f)
|
glm::vec4 padding=glm::vec4(4.0f)
|
||||||
);
|
);
|
||||||
@ -227,16 +229,16 @@ namespace gui {
|
|||||||
virtual bool isShowLineNumbers() const;
|
virtual bool isShowLineNumbers() const;
|
||||||
|
|
||||||
virtual void reposition() override;
|
virtual void reposition() override;
|
||||||
virtual void onFocus(GUI*) override;
|
virtual void onFocus() override;
|
||||||
virtual void refresh() override;
|
virtual void refresh() override;
|
||||||
virtual void doubleClick(GUI*, int x, int y) override;
|
virtual void doubleClick(int x, int y) override;
|
||||||
virtual void click(GUI*, int, int) override;
|
virtual void click(int, int) override;
|
||||||
virtual void mouseMove(GUI*, int x, int y) override;
|
virtual void mouseMove(int x, int y) override;
|
||||||
virtual bool isFocuskeeper() const override {return true;}
|
virtual bool isFocuskeeper() const override {return true;}
|
||||||
virtual void draw(const DrawContext& pctx, const Assets& assets) override;
|
virtual void draw(const DrawContext& pctx, const Assets& assets) override;
|
||||||
virtual void drawBackground(const DrawContext& pctx, const Assets& assets) override;
|
virtual void drawBackground(const DrawContext& pctx, const Assets& assets) override;
|
||||||
virtual void typed(unsigned int codepoint) override;
|
virtual void typed(unsigned int codepoint) override;
|
||||||
virtual void keyPressed(keycode key) override;
|
virtual void keyPressed(Keycode key) override;
|
||||||
virtual std::shared_ptr<UINode> getAt(const glm::vec2& pos) override;
|
virtual std::shared_ptr<UINode> getAt(const glm::vec2& pos) override;
|
||||||
virtual void setOnUpPressed(const runnable &callback);
|
virtual void setOnUpPressed(const runnable &callback);
|
||||||
virtual void setOnDownPressed(const runnable &callback);
|
virtual void setOnDownPressed(const runnable &callback);
|
||||||
|
|||||||
@ -9,12 +9,13 @@
|
|||||||
using namespace gui;
|
using namespace gui;
|
||||||
|
|
||||||
TrackBar::TrackBar(
|
TrackBar::TrackBar(
|
||||||
|
GUI& gui,
|
||||||
double min,
|
double min,
|
||||||
double max,
|
double max,
|
||||||
double value,
|
double value,
|
||||||
double step,
|
double step,
|
||||||
int trackWidth
|
int trackWidth
|
||||||
) : UINode(glm::vec2(26)),
|
) : UINode(gui, glm::vec2(26)),
|
||||||
min(min),
|
min(min),
|
||||||
max(max),
|
max(max),
|
||||||
value(value),
|
value(value),
|
||||||
@ -54,7 +55,7 @@ void TrackBar::setSubConsumer(doubleconsumer consumer) {
|
|||||||
this->subconsumer = std::move(consumer);
|
this->subconsumer = std::move(consumer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TrackBar::mouseMove(GUI*, int x, int) {
|
void TrackBar::mouseMove(int x, int) {
|
||||||
glm::vec2 pos = calcPos();
|
glm::vec2 pos = calcPos();
|
||||||
value = x - trackWidth/2;
|
value = x - trackWidth/2;
|
||||||
value -= pos.x;
|
value -= pos.x;
|
||||||
@ -62,7 +63,7 @@ void TrackBar::mouseMove(GUI*, int x, int) {
|
|||||||
value += min;
|
value += min;
|
||||||
value = (value > max) ? max : value;
|
value = (value > max) ? max : value;
|
||||||
value = (value < min) ? min : value;
|
value = (value < min) ? min : value;
|
||||||
value = (int64_t)round(value / step) * step;
|
value = static_cast<int64_t>(std::round(value / step)) * step;
|
||||||
|
|
||||||
if (consumer && !changeOnRelease) {
|
if (consumer && !changeOnRelease) {
|
||||||
consumer(value);
|
consumer(value);
|
||||||
@ -72,7 +73,7 @@ void TrackBar::mouseMove(GUI*, int x, int) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TrackBar::mouseRelease(GUI*, int, int) {
|
void TrackBar::mouseRelease(int, int) {
|
||||||
if (consumer && changeOnRelease) {
|
if (consumer && changeOnRelease) {
|
||||||
consumer(value);
|
consumer(value);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,19 +16,22 @@ namespace gui {
|
|||||||
int trackWidth;
|
int trackWidth;
|
||||||
bool changeOnRelease = false;
|
bool changeOnRelease = false;
|
||||||
public:
|
public:
|
||||||
TrackBar(double min,
|
TrackBar(
|
||||||
|
GUI& gui,
|
||||||
|
double min,
|
||||||
double max,
|
double max,
|
||||||
double value,
|
double value,
|
||||||
double step=1.0,
|
double step = 1.0,
|
||||||
int trackWidth=12);
|
int trackWidth = 12
|
||||||
|
);
|
||||||
virtual void draw(const DrawContext& pctx, const Assets& assets) override;
|
virtual void draw(const DrawContext& pctx, const Assets& assets) override;
|
||||||
|
|
||||||
virtual void setSupplier(doublesupplier);
|
virtual void setSupplier(doublesupplier);
|
||||||
virtual void setConsumer(doubleconsumer);
|
virtual void setConsumer(doubleconsumer);
|
||||||
virtual void setSubConsumer(doubleconsumer);
|
virtual void setSubConsumer(doubleconsumer);
|
||||||
|
|
||||||
virtual void mouseMove(GUI*, int x, int y) override;
|
virtual void mouseMove(int x, int y) override;
|
||||||
virtual void mouseRelease(GUI*, int x, int y) override;
|
virtual void mouseRelease(int x, int y) override;
|
||||||
|
|
||||||
virtual double getValue() const;
|
virtual double getValue() const;
|
||||||
virtual double getMin() const;
|
virtual double getMin() const;
|
||||||
|
|||||||
@ -8,7 +8,7 @@
|
|||||||
using gui::UINode;
|
using gui::UINode;
|
||||||
using gui::Align;
|
using gui::Align;
|
||||||
|
|
||||||
UINode::UINode(glm::vec2 size) : size(size) {
|
UINode::UINode(GUI& gui, glm::vec2 size) : gui(gui), size(size) {
|
||||||
}
|
}
|
||||||
|
|
||||||
UINode::~UINode() {
|
UINode::~UINode() {
|
||||||
@ -74,18 +74,18 @@ UINode* UINode::listenDoubleClick(const onaction& action) {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UINode::click(GUI*, int, int) {
|
void UINode::click(int, int) {
|
||||||
pressed = true;
|
pressed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UINode::doubleClick(GUI* gui, int x, int y) {
|
void UINode::doubleClick(int x, int y) {
|
||||||
pressed = true;
|
pressed = true;
|
||||||
if (isInside(glm::vec2(x, y))) {
|
if (isInside(glm::vec2(x, y))) {
|
||||||
doubleClickCallbacks.notify(gui);
|
doubleClickCallbacks.notify(gui);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UINode::mouseRelease(GUI* gui, int x, int y) {
|
void UINode::mouseRelease(int x, int y) {
|
||||||
pressed = false;
|
pressed = false;
|
||||||
if (isInside(glm::vec2(x, y))) {
|
if (isInside(glm::vec2(x, y))) {
|
||||||
actions.notify(gui);
|
actions.notify(gui);
|
||||||
|
|||||||
@ -19,8 +19,8 @@ namespace gui {
|
|||||||
class GUI;
|
class GUI;
|
||||||
class Container;
|
class Container;
|
||||||
|
|
||||||
using onaction = std::function<void(GUI*)>;
|
using onaction = std::function<void(GUI&)>;
|
||||||
using onnumberchange = std::function<void(GUI*, double)>;
|
using onnumberchange = std::function<void(GUI&, double)>;
|
||||||
|
|
||||||
class ActionsSet {
|
class ActionsSet {
|
||||||
std::unique_ptr<std::vector<onaction>> callbacks;
|
std::unique_ptr<std::vector<onaction>> callbacks;
|
||||||
@ -32,7 +32,7 @@ namespace gui {
|
|||||||
callbacks->push_back(callback);
|
callbacks->push_back(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
void notify(GUI* gui) {
|
void notify(GUI& gui) {
|
||||||
if (callbacks) {
|
if (callbacks) {
|
||||||
for (auto& callback : *callbacks) {
|
for (auto& callback : *callbacks) {
|
||||||
callback(gui);
|
callback(gui);
|
||||||
@ -64,6 +64,9 @@ namespace gui {
|
|||||||
|
|
||||||
/// @brief Base abstract class for all UI elements
|
/// @brief Base abstract class for all UI elements
|
||||||
class UINode : public std::enable_shared_from_this<UINode> {
|
class UINode : public std::enable_shared_from_this<UINode> {
|
||||||
|
protected:
|
||||||
|
GUI& gui;
|
||||||
|
private:
|
||||||
/// @brief element identifier used for direct access in UiDocument
|
/// @brief element identifier used for direct access in UiDocument
|
||||||
std::string id = "";
|
std::string id = "";
|
||||||
/// @brief element enabled state
|
/// @brief element enabled state
|
||||||
@ -118,7 +121,7 @@ namespace gui {
|
|||||||
/// @brief cursor shape when mouse is over the element
|
/// @brief cursor shape when mouse is over the element
|
||||||
CursorShape cursor = CursorShape::ARROW;
|
CursorShape cursor = CursorShape::ARROW;
|
||||||
|
|
||||||
UINode(glm::vec2 size);
|
UINode(GUI& gui, glm::vec2 size);
|
||||||
public:
|
public:
|
||||||
virtual ~UINode();
|
virtual ~UINode();
|
||||||
|
|
||||||
@ -169,12 +172,12 @@ namespace gui {
|
|||||||
virtual UINode* listenAction(const onaction &action);
|
virtual UINode* listenAction(const onaction &action);
|
||||||
virtual UINode* listenDoubleClick(const onaction &action);
|
virtual UINode* listenDoubleClick(const onaction &action);
|
||||||
|
|
||||||
virtual void onFocus(GUI*) {focused = true;}
|
virtual void onFocus() {focused = true;}
|
||||||
virtual void doubleClick(GUI*, int x, int y);
|
virtual void doubleClick(int x, int y);
|
||||||
virtual void click(GUI*, int x, int y);
|
virtual void click(int x, int y);
|
||||||
virtual void clicked(GUI*, mousecode button) {}
|
virtual void clicked(Mousecode button) {}
|
||||||
virtual void mouseMove(GUI*, int x, int y) {};
|
virtual void mouseMove(int x, int y) {};
|
||||||
virtual void mouseRelease(GUI*, int x, int y);
|
virtual void mouseRelease(int x, int y);
|
||||||
virtual void scrolled(int value);
|
virtual void scrolled(int value);
|
||||||
|
|
||||||
bool isPressed() const;
|
bool isPressed() const;
|
||||||
@ -185,7 +188,7 @@ namespace gui {
|
|||||||
virtual bool isFocuskeeper() const {return false;}
|
virtual bool isFocuskeeper() const {return false;}
|
||||||
|
|
||||||
virtual void typed(unsigned int codepoint) {};
|
virtual void typed(unsigned int codepoint) {};
|
||||||
virtual void keyPressed(keycode key) {};
|
virtual void keyPressed(Keycode key) {};
|
||||||
|
|
||||||
/// @brief Check if screen position is inside of the element
|
/// @brief Check if screen position is inside of the element
|
||||||
/// @param pos screen position
|
/// @param pos screen position
|
||||||
@ -222,11 +225,11 @@ namespace gui {
|
|||||||
virtual glm::vec2 calcPos() const;
|
virtual glm::vec2 calcPos() const;
|
||||||
virtual void setPos(glm::vec2 pos);
|
virtual void setPos(glm::vec2 pos);
|
||||||
virtual glm::vec2 getPos() const;
|
virtual glm::vec2 getPos() const;
|
||||||
virtual glm::vec2 getSize() const;
|
glm::vec2 getSize() const;
|
||||||
virtual void setSize(glm::vec2 size);
|
virtual void setSize(glm::vec2 size);
|
||||||
virtual glm::vec2 getMinSize() const;
|
glm::vec2 getMinSize() const;
|
||||||
virtual void setMinSize(glm::vec2 size);
|
virtual void setMinSize(glm::vec2 size);
|
||||||
virtual glm::vec2 getMaxSize() const;
|
glm::vec2 getMaxSize() const;
|
||||||
virtual void setMaxSize(glm::vec2 size);
|
virtual void setMaxSize(glm::vec2 size);
|
||||||
/// @brief Called in containers when new element added
|
/// @brief Called in containers when new element added
|
||||||
virtual void refresh() {};
|
virtual void refresh() {};
|
||||||
|
|||||||
@ -1,37 +1,36 @@
|
|||||||
#include "gui_util.hpp"
|
#include "gui_util.hpp"
|
||||||
|
|
||||||
#include "elements/Label.hpp"
|
|
||||||
#include "elements/Menu.hpp"
|
|
||||||
#include "elements/Button.hpp"
|
|
||||||
#include "elements/TextBox.hpp"
|
|
||||||
#include "gui_xml.hpp"
|
|
||||||
|
|
||||||
#include "logic/scripting/scripting.hpp"
|
|
||||||
#include "frontend/locale.hpp"
|
|
||||||
#include "util/stringutil.hpp"
|
|
||||||
#include "delegates.hpp"
|
|
||||||
|
|
||||||
#include "window/Events.hpp"
|
|
||||||
#include "engine/Engine.hpp"
|
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
|
#include "delegates.hpp"
|
||||||
|
#include "elements/Button.hpp"
|
||||||
|
#include "elements/Label.hpp"
|
||||||
|
#include "elements/Menu.hpp"
|
||||||
|
#include "elements/TextBox.hpp"
|
||||||
|
#include "engine/Engine.hpp"
|
||||||
|
#include "frontend/locale.hpp"
|
||||||
|
#include "gui_xml.hpp"
|
||||||
|
#include "logic/scripting/scripting.hpp"
|
||||||
|
#include "util/stringutil.hpp"
|
||||||
|
|
||||||
using namespace gui;
|
using namespace gui;
|
||||||
|
|
||||||
std::shared_ptr<gui::UINode> guiutil::create(const std::string& source, scriptenv env) {
|
std::shared_ptr<gui::UINode> guiutil::create(
|
||||||
|
GUI& gui, const std::string& source, scriptenv env
|
||||||
|
) {
|
||||||
if (env == nullptr) {
|
if (env == nullptr) {
|
||||||
env = scripting::get_root_environment();
|
env = scripting::get_root_environment();
|
||||||
}
|
}
|
||||||
UiXmlReader reader(env);
|
UiXmlReader reader(gui, env);
|
||||||
return reader.readXML("[string]", source);
|
return reader.readXML("[string]", source);
|
||||||
}
|
}
|
||||||
|
|
||||||
void guiutil::alert(
|
void guiutil::alert(
|
||||||
Engine& engine,
|
Engine& engine, const std::wstring& text, const runnable& on_hidden
|
||||||
const std::wstring& text,
|
|
||||||
const runnable& on_hidden
|
|
||||||
) {
|
) {
|
||||||
|
GUI& gui = engine.getGUI();
|
||||||
auto panel = std::make_shared<Panel>(
|
auto panel = std::make_shared<Panel>(
|
||||||
|
gui,
|
||||||
glm::vec2(
|
glm::vec2(
|
||||||
glm::min(
|
glm::min(
|
||||||
static_cast<size_t>(650),
|
static_cast<size_t>(650),
|
||||||
@ -44,7 +43,7 @@ void guiutil::alert(
|
|||||||
);
|
);
|
||||||
panel->setColor(glm::vec4(0.0f, 0.0f, 0.0f, 0.5f));
|
panel->setColor(glm::vec4(0.0f, 0.0f, 0.0f, 0.5f));
|
||||||
|
|
||||||
auto menuPtr = engine.getGUI()->getMenu();
|
auto menuPtr = gui.getMenu();
|
||||||
auto& menu = *menuPtr;
|
auto& menu = *menuPtr;
|
||||||
runnable on_hidden_final = [on_hidden, &menu]() {
|
runnable on_hidden_final = [on_hidden, &menu]() {
|
||||||
menu.removePage("<alert>");
|
menu.removePage("<alert>");
|
||||||
@ -55,24 +54,25 @@ void guiutil::alert(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
auto label = std::make_shared<Label>(text);
|
auto label = std::make_shared<Label>(gui, text);
|
||||||
label->setMultiline(true);
|
label->setMultiline(true);
|
||||||
label->setSize(glm::vec2(1, 24));
|
label->setSize(glm::vec2(1, 24));
|
||||||
label->setAutoResize(true);
|
label->setAutoResize(true);
|
||||||
panel->add(label);
|
panel->add(label);
|
||||||
panel->add(std::make_shared<Button>(
|
panel->add(std::make_shared<Button>(
|
||||||
langs::get(L"Ok"), glm::vec4(10.f),
|
gui,
|
||||||
[on_hidden_final](GUI*) {
|
langs::get(L"Ok"),
|
||||||
on_hidden_final();
|
glm::vec4(10.f),
|
||||||
}
|
[on_hidden_final](GUI&) { on_hidden_final(); }
|
||||||
));
|
));
|
||||||
panel->refresh();
|
panel->refresh();
|
||||||
|
|
||||||
panel->keepAlive(Events::keyCallbacks[keycode::ENTER].add([on_hidden_final](){
|
auto& input = engine.getInput();
|
||||||
|
panel->keepAlive(input.addKeyCallback(Keycode::ENTER, [on_hidden_final]() {
|
||||||
on_hidden_final();
|
on_hidden_final();
|
||||||
return true;
|
return true;
|
||||||
}));
|
}));
|
||||||
panel->keepAlive(Events::keyCallbacks[keycode::ESCAPE].add([on_hidden_final](){
|
panel->keepAlive(input.addKeyCallback(Keycode::ESCAPE, [on_hidden_final]() {
|
||||||
on_hidden_final();
|
on_hidden_final();
|
||||||
return true;
|
return true;
|
||||||
}));
|
}));
|
||||||
@ -91,17 +91,25 @@ void guiutil::confirm(
|
|||||||
if (yestext.empty()) yestext = langs::get(L"Yes");
|
if (yestext.empty()) yestext = langs::get(L"Yes");
|
||||||
if (notext.empty()) notext = langs::get(L"No");
|
if (notext.empty()) notext = langs::get(L"No");
|
||||||
|
|
||||||
auto container = std::make_shared<Container>(glm::vec2(5000, 5000));
|
auto& gui = engine.getGUI();
|
||||||
|
auto& input = engine.getInput();
|
||||||
|
|
||||||
|
auto container = std::make_shared<Container>(gui, glm::vec2(5000, 5000));
|
||||||
container->setColor(glm::vec4(0.05f, 0.05f, 0.05f, 0.7f));
|
container->setColor(glm::vec4(0.05f, 0.05f, 0.05f, 0.7f));
|
||||||
auto panel = std::make_shared<Panel>(glm::vec2(600, 200), glm::vec4(8.0f), 8.0f);
|
|
||||||
|
auto panel = std::make_shared<Panel>(
|
||||||
|
gui, glm::vec2(600, 200), glm::vec4(8.0f), 8.0f
|
||||||
|
);
|
||||||
|
|
||||||
panel->setGravity(Gravity::center_center);
|
panel->setGravity(Gravity::center_center);
|
||||||
container->add(panel);
|
container->add(panel);
|
||||||
|
|
||||||
panel->setColor(glm::vec4(0.0f, 0.0f, 0.0f, 0.5f));
|
panel->setColor(glm::vec4(0.0f, 0.0f, 0.0f, 0.5f));
|
||||||
panel->add(std::make_shared<Label>(text));
|
panel->add(std::make_shared<Label>(gui, text));
|
||||||
auto subpanel = std::make_shared<Panel>(glm::vec2(600, 53));
|
auto subpanel = std::make_shared<Panel>(gui, glm::vec2(600, 53));
|
||||||
subpanel->setColor(glm::vec4(0));
|
subpanel->setColor(glm::vec4(0));
|
||||||
|
|
||||||
auto menu = engine.getGUI()->getMenu();
|
auto menu = gui.getMenu();
|
||||||
|
|
||||||
runnable on_confirm_final = [on_confirm, menu]() {
|
runnable on_confirm_final = [on_confirm, menu]() {
|
||||||
menu->removePage("<confirm>");
|
menu->removePage("<confirm>");
|
||||||
@ -121,20 +129,20 @@ void guiutil::confirm(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
subpanel->add(std::make_shared<Button>(yestext, glm::vec4(8.f), [=](GUI*){
|
subpanel->add(std::make_shared<Button>(gui, yestext, glm::vec4(8.f), [=](GUI&) {
|
||||||
on_confirm_final();
|
on_confirm_final();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
subpanel->add(std::make_shared<Button>(notext, glm::vec4(8.f), [=](GUI*){
|
subpanel->add(std::make_shared<Button>(gui, notext, glm::vec4(8.f), [=](GUI&) {
|
||||||
on_deny_final();
|
on_deny_final();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
panel->add(subpanel);
|
panel->add(subpanel);
|
||||||
panel->keepAlive(Events::keyCallbacks[keycode::ENTER].add([=](){
|
panel->keepAlive(input.addKeyCallback(Keycode::ENTER, [=]() {
|
||||||
on_confirm_final();
|
on_confirm_final();
|
||||||
return true;
|
return true;
|
||||||
}));
|
}));
|
||||||
panel->keepAlive(Events::keyCallbacks[keycode::ESCAPE].add([=](){
|
panel->keepAlive(input.addKeyCallback(Keycode::ESCAPE, [=]() {
|
||||||
on_deny_final();
|
on_deny_final();
|
||||||
return true;
|
return true;
|
||||||
}));
|
}));
|
||||||
@ -145,21 +153,25 @@ void guiutil::confirm(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void guiutil::confirm_with_memo(
|
void guiutil::confirm_with_memo(
|
||||||
const std::shared_ptr<gui::Menu>& menu,
|
Engine& engine,
|
||||||
const std::wstring& text,
|
const std::wstring& text,
|
||||||
const std::wstring& memo,
|
const std::wstring& memo,
|
||||||
const runnable& on_confirm,
|
const runnable& on_confirm,
|
||||||
std::wstring yestext,
|
std::wstring yestext,
|
||||||
std::wstring notext) {
|
std::wstring notext
|
||||||
|
) {
|
||||||
|
auto& gui = engine.getGUI();
|
||||||
|
auto menu = gui.getMenu();
|
||||||
if (yestext.empty()) yestext = langs::get(L"Yes");
|
if (yestext.empty()) yestext = langs::get(L"Yes");
|
||||||
if (notext.empty()) notext = langs::get(L"No");
|
if (notext.empty()) notext = langs::get(L"No");
|
||||||
|
|
||||||
auto panel = std::make_shared<Panel>(glm::vec2(600, 500), glm::vec4(8.0f), 8.0f);
|
auto panel = std::make_shared<Panel>(
|
||||||
|
gui, glm::vec2(600, 500), glm::vec4(8.0f), 8.0f
|
||||||
|
);
|
||||||
panel->setColor(glm::vec4(0.0f, 0.0f, 0.0f, 0.5f));
|
panel->setColor(glm::vec4(0.0f, 0.0f, 0.0f, 0.5f));
|
||||||
panel->add(std::make_shared<Label>(text));
|
panel->add(std::make_shared<Label>(gui, text));
|
||||||
|
|
||||||
auto textbox = std::make_shared<TextBox>(L"");
|
auto textbox = std::make_shared<TextBox>(gui, L"");
|
||||||
textbox->setMultiline(true);
|
textbox->setMultiline(true);
|
||||||
textbox->setTextWrapping(true);
|
textbox->setTextWrapping(true);
|
||||||
textbox->setSize(glm::vec2(600, 300));
|
textbox->setSize(glm::vec2(600, 300));
|
||||||
@ -167,16 +179,15 @@ void guiutil::confirm_with_memo(
|
|||||||
textbox->setEditable(false);
|
textbox->setEditable(false);
|
||||||
panel->add(textbox);
|
panel->add(textbox);
|
||||||
|
|
||||||
auto subpanel = std::make_shared<Panel>(glm::vec2(600, 53));
|
auto subpanel = std::make_shared<Panel>(gui, glm::vec2(600, 53));
|
||||||
subpanel->setColor(glm::vec4(0));
|
subpanel->setColor(glm::vec4(0));
|
||||||
|
|
||||||
subpanel->add(std::make_shared<Button>(yestext, glm::vec4(8.f), [=](GUI*){
|
subpanel->add(std::make_shared<Button>(gui, yestext, glm::vec4(8.f), [=](GUI&) {
|
||||||
if (on_confirm)
|
if (on_confirm) on_confirm();
|
||||||
on_confirm();
|
|
||||||
menu->back();
|
menu->back();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
subpanel->add(std::make_shared<Button>(notext, glm::vec4(8.f), [=](GUI*){
|
subpanel->add(std::make_shared<Button>(gui, notext, glm::vec4(8.f), [=](GUI&) {
|
||||||
menu->back();
|
menu->back();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|||||||
@ -1,38 +1,46 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "GUI.hpp"
|
|
||||||
#include "typedefs.hpp"
|
|
||||||
#include "delegates.hpp"
|
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include "delegates.hpp"
|
||||||
|
#include "typedefs.hpp"
|
||||||
|
|
||||||
class Engine;
|
class Engine;
|
||||||
|
|
||||||
|
namespace gui {
|
||||||
|
class GUI;
|
||||||
|
class UINode;
|
||||||
|
}
|
||||||
|
|
||||||
namespace guiutil {
|
namespace guiutil {
|
||||||
/// @brief Create element from XML
|
/// @brief Create element from XML
|
||||||
/// @param source XML
|
/// @param source XML
|
||||||
std::shared_ptr<gui::UINode> create(const std::string& source, scriptenv env=0);
|
std::shared_ptr<gui::UINode> create(
|
||||||
|
gui::GUI& gui, const std::string& source, scriptenv env = 0
|
||||||
|
);
|
||||||
|
|
||||||
void alert(
|
void alert(
|
||||||
Engine& engine,
|
Engine& engine,
|
||||||
const std::wstring& text,
|
const std::wstring& text,
|
||||||
const runnable& on_hidden=nullptr
|
const runnable& on_hidden = nullptr
|
||||||
);
|
);
|
||||||
|
|
||||||
void confirm(
|
void confirm(
|
||||||
Engine& engine,
|
Engine& engine,
|
||||||
const std::wstring& text,
|
const std::wstring& text,
|
||||||
const runnable& on_confirm=nullptr,
|
const runnable& on_confirm = nullptr,
|
||||||
const runnable& on_deny=nullptr,
|
const runnable& on_deny = nullptr,
|
||||||
std::wstring yestext=L"",
|
std::wstring yestext = L"",
|
||||||
std::wstring notext=L"");
|
std::wstring notext = L""
|
||||||
|
);
|
||||||
|
|
||||||
void confirm_with_memo(
|
void confirm_with_memo(
|
||||||
const std::shared_ptr<gui::Menu>& menu,
|
Engine& engine,
|
||||||
const std::wstring& text,
|
const std::wstring& text,
|
||||||
const std::wstring& memo,
|
const std::wstring& memo,
|
||||||
const runnable& on_confirm=nullptr,
|
const runnable& on_confirm = nullptr,
|
||||||
std::wstring yestext=L"",
|
std::wstring yestext = L"",
|
||||||
std::wstring notext=L"");
|
std::wstring notext = L""
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,29 +1,29 @@
|
|||||||
#include "gui_xml.hpp"
|
#include "gui_xml.hpp"
|
||||||
|
|
||||||
#include "elements/Panel.hpp"
|
#include <stdexcept>
|
||||||
#include "elements/Image.hpp"
|
#include <utility>
|
||||||
#include "elements/Menu.hpp"
|
|
||||||
|
#include "GUI.hpp"
|
||||||
#include "elements/Button.hpp"
|
#include "elements/Button.hpp"
|
||||||
#include "elements/Canvas.hpp"
|
#include "elements/Canvas.hpp"
|
||||||
#include "elements/CheckBox.hpp"
|
#include "elements/CheckBox.hpp"
|
||||||
#include "elements/TextBox.hpp"
|
#include "elements/TextBox.hpp"
|
||||||
#include "elements/SplitBox.hpp"
|
#include "elements/SplitBox.hpp"
|
||||||
#include "elements/TrackBar.hpp"
|
#include "elements/TrackBar.hpp"
|
||||||
|
#include "elements/Image.hpp"
|
||||||
#include "elements/InputBindBox.hpp"
|
#include "elements/InputBindBox.hpp"
|
||||||
#include "elements/InventoryView.hpp"
|
#include "elements/InventoryView.hpp"
|
||||||
#include "GUI.hpp"
|
#include "elements/Menu.hpp"
|
||||||
|
#include "elements/Panel.hpp"
|
||||||
|
#include "elements/TextBox.hpp"
|
||||||
|
#include "elements/TrackBar.hpp"
|
||||||
#include "engine/Engine.hpp"
|
#include "engine/Engine.hpp"
|
||||||
|
|
||||||
#include "frontend/menu.hpp"
|
|
||||||
#include "frontend/locale.hpp"
|
#include "frontend/locale.hpp"
|
||||||
|
#include "frontend/menu.hpp"
|
||||||
#include "items/Inventory.hpp"
|
#include "items/Inventory.hpp"
|
||||||
#include "logic/scripting/scripting.hpp"
|
#include "logic/scripting/scripting.hpp"
|
||||||
#include "maths/voxmaths.hpp"
|
#include "maths/voxmaths.hpp"
|
||||||
#include "util/stringutil.hpp"
|
#include "util/stringutil.hpp"
|
||||||
#include "window/Events.hpp"
|
|
||||||
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
using namespace gui;
|
using namespace gui;
|
||||||
|
|
||||||
@ -80,7 +80,7 @@ static onaction create_action(
|
|||||||
if (callback == nullptr) {
|
if (callback == nullptr) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return [callback](GUI*) {callback();};
|
return [callback](GUI&) { callback(); };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Read basic UINode properties
|
/// @brief Read basic UINode properties
|
||||||
@ -152,9 +152,7 @@ static void read_uinode(
|
|||||||
node.setAlign(align_from_string(alignName, node.getAlign()));
|
node.setAlign(align_from_string(alignName, node.getAlign()));
|
||||||
|
|
||||||
if (element.has("gravity")) {
|
if (element.has("gravity")) {
|
||||||
node.setGravity(gravity_from_string(
|
node.setGravity(gravity_from_string(element.attr("gravity").getText()));
|
||||||
element.attr("gravity").getText()
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (element.has("tooltip")) {
|
if (element.has("tooltip")) {
|
||||||
@ -184,7 +182,9 @@ static void read_uinode(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void read_container_impl(UiXmlReader& reader, const xml::xmlelement& element, Container& container) {
|
static void read_container_impl(
|
||||||
|
UiXmlReader& reader, const xml::xmlelement& element, Container& container
|
||||||
|
) {
|
||||||
read_uinode(reader, element, container);
|
read_uinode(reader, element, container);
|
||||||
|
|
||||||
if (element.has("scrollable")) {
|
if (element.has("scrollable")) {
|
||||||
@ -194,8 +194,7 @@ static void read_container_impl(UiXmlReader& reader, const xml::xmlelement& elem
|
|||||||
container.setScrollStep(element.attr("scroll-step").asInt());
|
container.setScrollStep(element.attr("scroll-step").asInt());
|
||||||
}
|
}
|
||||||
for (auto& sub : element.getElements()) {
|
for (auto& sub : element.getElements()) {
|
||||||
if (sub->isText())
|
if (sub->isText()) continue;
|
||||||
continue;
|
|
||||||
auto subnode = reader.readUINode(*sub);
|
auto subnode = reader.readUINode(*sub);
|
||||||
if (subnode) {
|
if (subnode) {
|
||||||
container.add(subnode);
|
container.add(subnode);
|
||||||
@ -203,7 +202,9 @@ static void read_container_impl(UiXmlReader& reader, const xml::xmlelement& elem
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UiXmlReader::readUINode(UiXmlReader& reader, const xml::xmlelement& element, Container& container) {
|
void UiXmlReader::readUINode(
|
||||||
|
UiXmlReader& reader, const xml::xmlelement& element, Container& container
|
||||||
|
) {
|
||||||
read_container_impl(reader, element, container);
|
read_container_impl(reader, element, container);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -225,8 +226,7 @@ static void read_base_panel_impl(
|
|||||||
panel.setPadding(padding);
|
panel.setPadding(padding);
|
||||||
glm::vec2 size = panel.getSize();
|
glm::vec2 size = panel.getSize();
|
||||||
panel.setSize(glm::vec2(
|
panel.setSize(glm::vec2(
|
||||||
size.x + padding.x + padding.z,
|
size.x + padding.x + padding.z, size.y + padding.y + padding.w
|
||||||
size.y + padding.y + padding.w
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
if (element.has("orientation")) {
|
if (element.has("orientation")) {
|
||||||
@ -254,10 +254,15 @@ static void read_panel_impl(
|
|||||||
if (element.has("min-length")) {
|
if (element.has("min-length")) {
|
||||||
panel.setMinLength(element.attr("min-length").asInt());
|
panel.setMinLength(element.attr("min-length").asInt());
|
||||||
}
|
}
|
||||||
|
if (element.has("orientation")) {
|
||||||
|
auto& oname = element.attr("orientation").getText();
|
||||||
|
if (oname == "horizontal") {
|
||||||
|
panel.setOrientation(Orientation::horizontal);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (subnodes) {
|
if (subnodes) {
|
||||||
for (auto& sub : element.getElements()) {
|
for (auto& sub : element.getElements()) {
|
||||||
if (sub->isText())
|
if (sub->isText()) continue;
|
||||||
continue;
|
|
||||||
auto subnode = reader.readUINode(*sub);
|
auto subnode = reader.readUINode(*sub);
|
||||||
if (subnode) {
|
if (subnode) {
|
||||||
panel.add(subnode);
|
panel.add(subnode);
|
||||||
@ -289,12 +294,12 @@ static std::shared_ptr<UINode> readLabel(
|
|||||||
const UiXmlReader& reader, const xml::xmlelement& element
|
const UiXmlReader& reader, const xml::xmlelement& element
|
||||||
) {
|
) {
|
||||||
std::wstring text = parse_inner_text(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>(reader.getGUI(), text);
|
||||||
read_uinode(reader, element, *label);
|
read_uinode(reader, element, *label);
|
||||||
if (element.has("valign")) {
|
if (element.has("valign")) {
|
||||||
label->setVerticalAlign(
|
label->setVerticalAlign(align_from_string(
|
||||||
align_from_string(element.attr("valign").getText(), label->getVerticalAlign())
|
element.attr("valign").getText(), label->getVerticalAlign()
|
||||||
);
|
));
|
||||||
}
|
}
|
||||||
if (element.has("supplier")) {
|
if (element.has("supplier")) {
|
||||||
label->textSupplier(scripting::create_wstring_supplier(
|
label->textSupplier(scripting::create_wstring_supplier(
|
||||||
@ -324,7 +329,7 @@ static std::shared_ptr<UINode> readLabel(
|
|||||||
static std::shared_ptr<UINode> read_container(
|
static std::shared_ptr<UINode> read_container(
|
||||||
UiXmlReader& reader, const xml::xmlelement& element
|
UiXmlReader& reader, const xml::xmlelement& element
|
||||||
) {
|
) {
|
||||||
auto container = std::make_shared<Container>(glm::vec2());
|
auto container = std::make_shared<Container>(reader.getGUI(), glm::vec2());
|
||||||
read_container_impl(reader, element, *container);
|
read_container_impl(reader, element, *container);
|
||||||
return container;
|
return container;
|
||||||
}
|
}
|
||||||
@ -337,8 +342,9 @@ static std::shared_ptr<UINode> read_split_box(
|
|||||||
element.attr("orientation", "vertical").getText() == "horizontal"
|
element.attr("orientation", "vertical").getText() == "horizontal"
|
||||||
? Orientation::horizontal
|
? Orientation::horizontal
|
||||||
: Orientation::vertical;
|
: Orientation::vertical;
|
||||||
auto splitBox =
|
auto splitBox = std::make_shared<SplitBox>(
|
||||||
std::make_shared<SplitBox>(glm::vec2(), splitPos, orientation);
|
reader.getGUI(), glm::vec2(), splitPos, orientation
|
||||||
|
);
|
||||||
read_base_panel_impl(reader, element, *splitBox);
|
read_base_panel_impl(reader, element, *splitBox);
|
||||||
for (auto& sub : element.getElements()) {
|
for (auto& sub : element.getElements()) {
|
||||||
if (sub->isText())
|
if (sub->isText())
|
||||||
@ -355,7 +361,9 @@ static std::shared_ptr<UINode> read_panel(
|
|||||||
UiXmlReader& reader, const xml::xmlelement& element
|
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>(
|
||||||
|
reader.getGUI(), glm::vec2(), glm::vec4(), interval
|
||||||
|
);
|
||||||
read_panel_impl(reader, element, *panel);
|
read_panel_impl(reader, element, *panel);
|
||||||
return panel;
|
return panel;
|
||||||
}
|
}
|
||||||
@ -363,6 +371,7 @@ static std::shared_ptr<UINode> read_panel(
|
|||||||
static std::shared_ptr<UINode> read_button(
|
static std::shared_ptr<UINode> read_button(
|
||||||
UiXmlReader& reader, const xml::xmlelement& element
|
UiXmlReader& reader, const xml::xmlelement& element
|
||||||
) {
|
) {
|
||||||
|
auto& gui = reader.getGUI();
|
||||||
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;
|
||||||
@ -370,14 +379,14 @@ static std::shared_ptr<UINode> read_button(
|
|||||||
if (!elements.empty() && elements[0]->getTag() != "#") {
|
if (!elements.empty() && elements[0]->getTag() != "#") {
|
||||||
auto inner = reader.readUINode(*elements.at(0));
|
auto inner = reader.readUINode(*elements.at(0));
|
||||||
if (inner != nullptr) {
|
if (inner != nullptr) {
|
||||||
button = std::make_shared<Button>(inner, padding);
|
button = std::make_shared<Button>(gui, inner, padding);
|
||||||
} else {
|
} else {
|
||||||
button = std::make_shared<Button>(L"", padding, nullptr);
|
button = std::make_shared<Button>(gui, L"", padding, nullptr);
|
||||||
}
|
}
|
||||||
read_panel_impl(reader, element, *button, false);
|
read_panel_impl(reader, element, *button, false);
|
||||||
} else {
|
} else {
|
||||||
std::wstring text = parse_inner_text(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>(gui, text, padding, nullptr);
|
||||||
read_panel_impl(reader, element, *button, true);
|
read_panel_impl(reader, element, *button, true);
|
||||||
}
|
}
|
||||||
if (element.has("text-align")) {
|
if (element.has("text-align")) {
|
||||||
@ -393,7 +402,9 @@ static std::shared_ptr<UINode> read_check_box(
|
|||||||
) {
|
) {
|
||||||
auto text = parse_inner_text(element, reader.getContext());
|
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>(
|
||||||
|
reader.getGUI(), text, glm::vec2(32), checked
|
||||||
|
);
|
||||||
read_panel_impl(reader, element, *checkbox);
|
read_panel_impl(reader, element, *checkbox);
|
||||||
|
|
||||||
if (element.has("consumer")) {
|
if (element.has("consumer")) {
|
||||||
@ -417,10 +428,13 @@ static std::shared_ptr<UINode> read_check_box(
|
|||||||
static std::shared_ptr<UINode> read_text_box(
|
static std::shared_ptr<UINode> read_text_box(
|
||||||
UiXmlReader& reader, const xml::xmlelement& element
|
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 = parse_inner_text(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>(
|
||||||
|
reader.getGUI(), placeholder, glm::vec4(0.0f)
|
||||||
|
);
|
||||||
textbox->setHint(hint);
|
textbox->setHint(hint);
|
||||||
|
|
||||||
read_container_impl(reader, element, *textbox);
|
read_container_impl(reader, element, *textbox);
|
||||||
@ -429,8 +443,7 @@ static std::shared_ptr<UINode> read_text_box(
|
|||||||
textbox->setPadding(padding);
|
textbox->setPadding(padding);
|
||||||
glm::vec2 size = textbox->getSize();
|
glm::vec2 size = textbox->getSize();
|
||||||
textbox->setSize(glm::vec2(
|
textbox->setSize(glm::vec2(
|
||||||
size.x + padding.x + padding.z,
|
size.x + padding.x + padding.z, size.y + padding.y + padding.w
|
||||||
size.y + padding.y + padding.w
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
textbox->setText(text);
|
textbox->setText(text);
|
||||||
@ -513,7 +526,7 @@ 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>(reader.getGUI(), src);
|
||||||
read_uinode(reader, element, *image);
|
read_uinode(reader, element, *image);
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
@ -521,11 +534,12 @@ static std::shared_ptr<UINode> read_image(
|
|||||||
static std::shared_ptr<UINode> read_canvas(
|
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};
|
||||||
if (element.has("size")) {
|
if (element.has("size")) {
|
||||||
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>(reader.getGUI(), ImageFormat::rgba8888, size);
|
||||||
read_uinode(reader, element, *image);
|
read_uinode(reader, element, *image);
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
@ -540,19 +554,24 @@ static std::shared_ptr<UINode> read_track_bar(
|
|||||||
float def = element.attr("value", "0.0").asFloat();
|
float def = element.attr("value", "0.0").asFloat();
|
||||||
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>(
|
||||||
|
reader.getGUI(), minv, maxv, def, step, trackWidth
|
||||||
|
);
|
||||||
read_uinode(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
|
||||||
|
));
|
||||||
}
|
}
|
||||||
if (element.has("sub-consumer")) {
|
if (element.has("sub-consumer")) {
|
||||||
bar->setSubConsumer(scripting::create_number_consumer(
|
bar->setSubConsumer(scripting::create_number_consumer(
|
||||||
env, element.attr("sub-consumer").getText(), file));
|
env, element.attr("sub-consumer").getText(), file
|
||||||
|
));
|
||||||
}
|
}
|
||||||
if (element.has("supplier")) {
|
if (element.has("supplier")) {
|
||||||
bar->setSupplier(scripting::create_number_supplier(
|
bar->setSupplier(scripting::create_number_supplier(
|
||||||
env, element.attr("supplier").getText(), file));
|
env, element.attr("supplier").getText(), file
|
||||||
|
));
|
||||||
}
|
}
|
||||||
if (element.has("track-color")) {
|
if (element.has("track-color")) {
|
||||||
bar->setTrackColor(element.attr("track-color").asColor());
|
bar->setTrackColor(element.attr("track-color").asColor());
|
||||||
@ -567,14 +586,11 @@ static std::shared_ptr<UINode> read_input_bind_box(
|
|||||||
UiXmlReader& reader, const xml::xmlelement& element
|
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 = reader.getGUI().getInput().getBindings().require(bindname);
|
||||||
if (found == Events::bindings.end()) {
|
|
||||||
throw std::runtime_error("binding does not exists "+util::quote(bindname));
|
|
||||||
}
|
|
||||||
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>(reader.getGUI(), found, padding);
|
||||||
read_panel_impl(reader, element, *bindbox);
|
read_panel_impl(reader, element, *bindbox);
|
||||||
|
|
||||||
return bindbox;
|
return bindbox;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -585,11 +601,12 @@ static slotcallback read_slot_func(
|
|||||||
const std::string& attr
|
const std::string& attr
|
||||||
) {
|
) {
|
||||||
auto consumer = scripting::create_int_array_consumer(
|
auto consumer = scripting::create_int_array_consumer(
|
||||||
reader.getEnvironment(),
|
reader.getEnvironment(), element.attr(attr).getText()
|
||||||
element.attr(attr).getText()
|
|
||||||
);
|
);
|
||||||
return [=](uint slot, ItemStack&) {
|
return [=](uint slot, ItemStack&) {
|
||||||
int args[] {int(view->getInventory()->getId()), int(slot)};
|
int args[] {
|
||||||
|
static_cast<int>(view->getInventory()->getId()),
|
||||||
|
static_cast<int>(slot)};
|
||||||
consumer(args, 2);
|
consumer(args, 2);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -601,7 +618,9 @@ static void readSlot(
|
|||||||
bool itemSource = element.attr("item-source", "false").asBool();
|
bool itemSource = element.attr("item-source", "false").asBool();
|
||||||
bool taking = element.attr("taking", "true").asBool();
|
bool taking = element.attr("taking", "true").asBool();
|
||||||
bool placing = element.attr("placing", "true").asBool();
|
bool placing = element.attr("placing", "true").asBool();
|
||||||
SlotLayout layout(index, glm::vec2(), true, itemSource, nullptr, nullptr, nullptr);
|
SlotLayout layout(
|
||||||
|
index, glm::vec2(), true, itemSource, nullptr, nullptr, nullptr
|
||||||
|
);
|
||||||
if (element.has("pos")) {
|
if (element.has("pos")) {
|
||||||
layout.position = element.attr("pos").asVec2();
|
layout.position = element.attr("pos").asVec2();
|
||||||
}
|
}
|
||||||
@ -612,7 +631,8 @@ static void readSlot(
|
|||||||
layout.shareFunc = read_slot_func(view, reader, element, "sharefunc");
|
layout.shareFunc = read_slot_func(view, reader, element, "sharefunc");
|
||||||
}
|
}
|
||||||
if (element.has("onrightclick")) {
|
if (element.has("onrightclick")) {
|
||||||
layout.rightClick = read_slot_func(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;
|
||||||
@ -622,7 +642,9 @@ static void readSlot(
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void readSlotsGrid(
|
static void readSlotsGrid(
|
||||||
InventoryView* view, const UiXmlReader& reader, const xml::xmlelement& element
|
InventoryView* view,
|
||||||
|
const UiXmlReader& reader,
|
||||||
|
const xml::xmlelement& element
|
||||||
) {
|
) {
|
||||||
int startIndex = element.attr("start-index", "0").asInt();
|
int startIndex = element.attr("start-index", "0").asInt();
|
||||||
int rows = element.attr("rows", "0").asInt();
|
int rows = element.attr("rows", "0").asInt();
|
||||||
@ -647,7 +669,9 @@ static void readSlotsGrid(
|
|||||||
count = rows * cols;
|
count = rows * cols;
|
||||||
}
|
}
|
||||||
bool itemSource = element.attr("item-source", "false").asBool();
|
bool itemSource = element.attr("item-source", "false").asBool();
|
||||||
SlotLayout layout(-1, glm::vec2(), true, itemSource, nullptr, nullptr, nullptr);
|
SlotLayout layout(
|
||||||
|
-1, glm::vec2(), true, itemSource, nullptr, nullptr, nullptr
|
||||||
|
);
|
||||||
if (element.has("pos")) {
|
if (element.has("pos")) {
|
||||||
layout.position = element.attr("pos").asVec2();
|
layout.position = element.attr("pos").asVec2();
|
||||||
}
|
}
|
||||||
@ -658,7 +682,8 @@ static void readSlotsGrid(
|
|||||||
layout.shareFunc = read_slot_func(view, reader, element, "sharefunc");
|
layout.shareFunc = read_slot_func(view, reader, element, "sharefunc");
|
||||||
}
|
}
|
||||||
if (element.has("onrightclick")) {
|
if (element.has("onrightclick")) {
|
||||||
layout.rightClick = read_slot_func(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;
|
||||||
@ -674,7 +699,7 @@ static void readSlotsGrid(
|
|||||||
slotLayout.index = startIndex + idx;
|
slotLayout.index = startIndex + idx;
|
||||||
slotLayout.position += glm::vec2(
|
slotLayout.position += glm::vec2(
|
||||||
padding + col * (slotSize + interval),
|
padding + col * (slotSize + interval),
|
||||||
padding + (rows-row-1) * (slotSize + interval)
|
padding + (rows - row - 1) * (slotSize + interval)
|
||||||
);
|
);
|
||||||
auto slot = view->addSlot(slotLayout);
|
auto slot = view->addSlot(slotLayout);
|
||||||
view->add(slot, slotLayout.position);
|
view->add(slot, slotLayout.position);
|
||||||
@ -685,8 +710,8 @@ static void readSlotsGrid(
|
|||||||
static std::shared_ptr<UINode> read_inventory(
|
static std::shared_ptr<UINode> read_inventory(
|
||||||
UiXmlReader& reader, const xml::xmlelement& element
|
UiXmlReader& reader, const xml::xmlelement& element
|
||||||
) {
|
) {
|
||||||
auto view = std::make_shared<InventoryView>();
|
auto view = std::make_shared<InventoryView>(reader.getGUI());
|
||||||
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");
|
||||||
reader.addIgnore("slots-grid");
|
reader.addIgnore("slots-grid");
|
||||||
reader.readUINode(reader, element, *view);
|
reader.readUINode(reader, element, *view);
|
||||||
@ -704,16 +729,15 @@ static std::shared_ptr<UINode> read_inventory(
|
|||||||
static std::shared_ptr<UINode> read_page_box(
|
static std::shared_ptr<UINode> read_page_box(
|
||||||
UiXmlReader& reader, const xml::xmlelement& element
|
UiXmlReader& reader, const xml::xmlelement& element
|
||||||
) {
|
) {
|
||||||
auto menu = std::make_shared<Menu>();
|
auto& gui = reader.getGUI();
|
||||||
menu->setPageLoader(
|
auto menu = std::make_shared<Menu>(gui);
|
||||||
Engine::getInstance().getGUI()->getMenu()->getPageLoader()
|
menu->setPageLoader(gui.getMenu()->getPageLoader());
|
||||||
);
|
|
||||||
read_container_impl(reader, element, *menu);
|
read_container_impl(reader, element, *menu);
|
||||||
|
|
||||||
return menu;
|
return menu;
|
||||||
}
|
}
|
||||||
|
|
||||||
UiXmlReader::UiXmlReader(const scriptenv& env) : env(env) {
|
UiXmlReader::UiXmlReader(gui::GUI& gui, const scriptenv& env) : gui(gui), env(env) {
|
||||||
contextStack.emplace("");
|
contextStack.emplace("");
|
||||||
add("image", read_image);
|
add("image", read_image);
|
||||||
add("canvas", read_canvas);
|
add("canvas", read_canvas);
|
||||||
@ -742,16 +766,15 @@ void UiXmlReader::addIgnore(const std::string& tag) {
|
|||||||
ignored.insert(tag);
|
ignored.insert(tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<UINode> UiXmlReader::readUINode(const xml::xmlelement& element) {
|
std::shared_ptr<UINode> UiXmlReader::readUINode(const xml::xmlelement& element
|
||||||
|
) {
|
||||||
if (element.has("if")) {
|
if (element.has("if")) {
|
||||||
const auto& cond = element.attr("if").getText();
|
const auto& cond = element.attr("if").getText();
|
||||||
if (cond.empty() || cond == "false" || cond == "nil")
|
if (cond.empty() || cond == "false" || cond == "nil") return nullptr;
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
if (element.has("ifnot")) {
|
if (element.has("ifnot")) {
|
||||||
const auto& cond = element.attr("ifnot").getText();
|
const auto& cond = element.attr("ifnot").getText();
|
||||||
if (!(cond.empty() || cond == "false" || cond == "nil"))
|
if (!(cond.empty() || cond == "false" || cond == "nil")) return nullptr;
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& tag = element.getTag();
|
const std::string& tag = element.getTag();
|
||||||
@ -760,7 +783,7 @@ std::shared_ptr<UINode> UiXmlReader::readUINode(const xml::xmlelement& element)
|
|||||||
if (ignored.find(tag) != ignored.end()) {
|
if (ignored.find(tag) != ignored.end()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
throw std::runtime_error("unsupported element '"+tag+"'");
|
throw std::runtime_error("unsupported element '" + tag + "'");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hascontext = element.has("context");
|
bool hascontext = element.has("context");
|
||||||
@ -775,8 +798,7 @@ std::shared_ptr<UINode> UiXmlReader::readUINode(const xml::xmlelement& element)
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<UINode> UiXmlReader::readXML(
|
std::shared_ptr<UINode> UiXmlReader::readXML(
|
||||||
const std::string& filename,
|
const std::string& filename, const std::string& source
|
||||||
const std::string& source
|
|
||||||
) {
|
) {
|
||||||
this->filename = filename;
|
this->filename = filename;
|
||||||
auto document = xml::parse(filename, source);
|
auto document = xml::parse(filename, source);
|
||||||
@ -784,8 +806,7 @@ std::shared_ptr<UINode> UiXmlReader::readXML(
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<UINode> UiXmlReader::readXML(
|
std::shared_ptr<UINode> UiXmlReader::readXML(
|
||||||
const std::string& filename,
|
const std::string& filename, const xml::xmlelement& root
|
||||||
const xml::xmlelement& root
|
|
||||||
) {
|
) {
|
||||||
this->filename = filename;
|
this->filename = filename;
|
||||||
return readUINode(root);
|
return readUINode(root);
|
||||||
@ -802,3 +823,7 @@ const std::string& UiXmlReader::getFilename() const {
|
|||||||
const scriptenv& UiXmlReader::getEnvironment() const {
|
const scriptenv& UiXmlReader::getEnvironment() const {
|
||||||
return env;
|
return env;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gui::GUI& UiXmlReader::getGUI() const {
|
||||||
|
return gui;
|
||||||
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user