refactor
This commit is contained in:
parent
5fe5c6b27a
commit
5ffc054d75
@ -1,3 +0,0 @@
|
||||
print("Hello from the example test!")
|
||||
test.sleep(1)
|
||||
print("2")
|
||||
30
src/Mainloop.cpp
Normal file
30
src/Mainloop.cpp
Normal file
@ -0,0 +1,30 @@
|
||||
#include "Mainloop.hpp"
|
||||
|
||||
#include "debug/Logger.hpp"
|
||||
#include "engine.hpp"
|
||||
#include "frontend/screens/MenuScreen.hpp"
|
||||
#include "window/Window.hpp"
|
||||
|
||||
static debug::Logger logger("mainloop");
|
||||
|
||||
Mainloop::Mainloop(Engine& engine) : engine(engine) {
|
||||
}
|
||||
|
||||
void Mainloop::run() {
|
||||
auto& time = engine.getTime();
|
||||
|
||||
logger.info() << "starting menu screen";
|
||||
engine.setScreen(std::make_shared<MenuScreen>(&engine));
|
||||
|
||||
logger.info() << "main loop started";
|
||||
while (!Window::isShouldClose()){
|
||||
time.update(Window::time());
|
||||
engine.updateFrontend();
|
||||
if (!Window::isIconified()) {
|
||||
engine.renderFrame();
|
||||
}
|
||||
engine.postUpdate();
|
||||
engine.nextFrame();
|
||||
}
|
||||
logger.info() << "main loop stopped";
|
||||
}
|
||||
11
src/Mainloop.hpp
Normal file
11
src/Mainloop.hpp
Normal file
@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
class Engine;
|
||||
|
||||
class Mainloop {
|
||||
Engine& engine;
|
||||
public:
|
||||
Mainloop(Engine& engine);
|
||||
|
||||
void run();
|
||||
};
|
||||
31
src/TestMainloop.cpp
Normal file
31
src/TestMainloop.cpp
Normal file
@ -0,0 +1,31 @@
|
||||
#include "TestMainloop.hpp"
|
||||
|
||||
#include "logic/scripting/scripting.hpp"
|
||||
#include "interfaces/Process.hpp"
|
||||
#include "debug/Logger.hpp"
|
||||
#include "engine.hpp"
|
||||
|
||||
static debug::Logger logger("mainloop");
|
||||
|
||||
inline constexpr int TPS = 20;
|
||||
|
||||
TestMainloop::TestMainloop(Engine& engine) : engine(engine) {
|
||||
}
|
||||
|
||||
void TestMainloop::run() {
|
||||
const auto& coreParams = engine.getCoreParameters();
|
||||
auto& time = engine.getTime();
|
||||
|
||||
if (coreParams.testFile.empty()) {
|
||||
logger.info() << "nothing to do";
|
||||
return;
|
||||
}
|
||||
|
||||
logger.info() << "starting test " << coreParams.testFile;
|
||||
auto process = scripting::start_coroutine(coreParams.testFile);
|
||||
while (process->isActive()) {
|
||||
time.step(1.0f / static_cast<float>(TPS));
|
||||
process->update();
|
||||
}
|
||||
logger.info() << "test finished";
|
||||
}
|
||||
11
src/TestMainloop.hpp
Normal file
11
src/TestMainloop.hpp
Normal file
@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
class Engine;
|
||||
|
||||
class TestMainloop {
|
||||
Engine& engine;
|
||||
public:
|
||||
TestMainloop(Engine& engine);
|
||||
|
||||
void run();
|
||||
};
|
||||
34
src/Time.hpp
Normal file
34
src/Time.hpp
Normal file
@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
class Time {
|
||||
uint64_t frame = 0;
|
||||
double lastTime = 0.0;
|
||||
double delta = 0.0;
|
||||
public:
|
||||
Time() {}
|
||||
|
||||
void update(double currentTime) {
|
||||
frame++;
|
||||
delta = currentTime - lastTime;
|
||||
lastTime = currentTime;
|
||||
}
|
||||
|
||||
void step(double delta) {
|
||||
frame++;
|
||||
lastTime += delta;
|
||||
}
|
||||
|
||||
void set(double currentTime) {
|
||||
lastTime = currentTime;
|
||||
}
|
||||
|
||||
double getDelta() const {
|
||||
return delta;
|
||||
}
|
||||
|
||||
double getTime() const {
|
||||
return lastTime;
|
||||
}
|
||||
};
|
||||
@ -146,9 +146,7 @@ void ContentPack::scanFolder(
|
||||
std::vector<std::string> ContentPack::worldPacksList(const fs::path& folder) {
|
||||
fs::path listfile = folder / fs::path("packs.list");
|
||||
if (!fs::is_regular_file(listfile)) {
|
||||
std::cerr << "warning: packs.list not found (will be created)";
|
||||
std::cerr << std::endl;
|
||||
files::write_string(listfile, "# autogenerated, do not modify\nbase\n");
|
||||
throw std::runtime_error("missing file 'packs.list'");
|
||||
}
|
||||
return files::read_list(listfile);
|
||||
}
|
||||
|
||||
143
src/engine.cpp
143
src/engine.cpp
@ -20,7 +20,6 @@
|
||||
#include "frontend/screens/Screen.hpp"
|
||||
#include "frontend/screens/MenuScreen.hpp"
|
||||
#include "graphics/render/ModelsGenerator.hpp"
|
||||
#include "graphics/core/Batch2D.hpp"
|
||||
#include "graphics/core/DrawContext.hpp"
|
||||
#include "graphics/core/ImageData.hpp"
|
||||
#include "graphics/core/Shader.hpp"
|
||||
@ -36,7 +35,8 @@
|
||||
#include "window/Events.hpp"
|
||||
#include "window/input.hpp"
|
||||
#include "window/Window.hpp"
|
||||
#include "interfaces/Process.hpp"
|
||||
#include "Mainloop.hpp"
|
||||
#include "TestMainloop.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <assert.h>
|
||||
@ -92,6 +92,7 @@ Engine::Engine(CoreParameters coreParameters)
|
||||
if (Window::initialize(&settings.display)){
|
||||
throw initialize_error("could not initialize window");
|
||||
}
|
||||
time.set(Window::time());
|
||||
if (auto icon = load_icon(resdir)) {
|
||||
icon->flipY();
|
||||
Window::setIcon(icon.get());
|
||||
@ -153,13 +154,6 @@ void Engine::onAssetsLoaded() {
|
||||
gui->onAssetsLoad(assets.get());
|
||||
}
|
||||
|
||||
void Engine::updateTimers() {
|
||||
frame++;
|
||||
double currentTime = Window::time();
|
||||
delta = currentTime - lastTime;
|
||||
lastTime = currentTime;
|
||||
}
|
||||
|
||||
void Engine::updateHotkeys() {
|
||||
if (Events::jpressed(keycode::F2)) {
|
||||
saveScreenshot();
|
||||
@ -179,70 +173,40 @@ void Engine::saveScreenshot() {
|
||||
|
||||
void Engine::run() {
|
||||
if (params.headless) {
|
||||
runTest();
|
||||
TestMainloop(*this).run();
|
||||
} else {
|
||||
mainloop();
|
||||
Mainloop(*this).run();
|
||||
}
|
||||
}
|
||||
|
||||
void Engine::runTest() {
|
||||
if (params.testFile.empty()) {
|
||||
logger.info() << "nothing to do";
|
||||
return;
|
||||
}
|
||||
int tps = 20;
|
||||
|
||||
logger.info() << "starting test " << params.testFile;
|
||||
auto process = scripting::start_coroutine(params.testFile);
|
||||
while (process->isActive()) {
|
||||
frame++;
|
||||
delta = 1.0f / static_cast<float>(tps);
|
||||
lastTime += delta;
|
||||
|
||||
process->update();
|
||||
}
|
||||
logger.info() << "test finished";
|
||||
void Engine::postUpdate() {
|
||||
network->update();
|
||||
processPostRunnables();
|
||||
}
|
||||
|
||||
void Engine::mainloop() {
|
||||
logger.info() << "starting menu screen";
|
||||
setScreen(std::make_shared<MenuScreen>(this));
|
||||
|
||||
Batch2D batch(1024);
|
||||
lastTime = Window::time();
|
||||
|
||||
logger.info() << "engine started";
|
||||
while (!Window::isShouldClose()){
|
||||
assert(screen != nullptr);
|
||||
updateTimers();
|
||||
updateHotkeys();
|
||||
audio::update(delta);
|
||||
|
||||
gui->act(delta, Viewport(Window::width, Window::height));
|
||||
screen->update(delta);
|
||||
|
||||
if (!Window::isIconified()) {
|
||||
renderFrame(batch);
|
||||
}
|
||||
Window::setFramerate(
|
||||
Window::isIconified() && settings.display.limitFpsIconified.get()
|
||||
? 20
|
||||
: settings.display.framerate.get()
|
||||
);
|
||||
|
||||
network->update();
|
||||
processPostRunnables();
|
||||
|
||||
Window::swapBuffers();
|
||||
Events::pollEvents();
|
||||
}
|
||||
void Engine::updateFrontend() {
|
||||
double delta = time.getDelta();
|
||||
updateHotkeys();
|
||||
audio::update(delta);
|
||||
gui->act(delta, Viewport(Window::width, Window::height));
|
||||
screen->update(delta);
|
||||
}
|
||||
|
||||
void Engine::renderFrame(Batch2D& batch) {
|
||||
screen->draw(delta);
|
||||
void Engine::nextFrame() {
|
||||
Window::setFramerate(
|
||||
Window::isIconified() && settings.display.limitFpsIconified.get()
|
||||
? 20
|
||||
: settings.display.framerate.get()
|
||||
);
|
||||
Window::swapBuffers();
|
||||
Events::pollEvents();
|
||||
}
|
||||
|
||||
void Engine::renderFrame() {
|
||||
screen->draw(time.getDelta());
|
||||
|
||||
Viewport viewport(Window::width, Window::height);
|
||||
DrawContext ctx(nullptr, viewport, &batch);
|
||||
DrawContext ctx(nullptr, viewport, nullptr);
|
||||
gui->draw(ctx, *assets);
|
||||
}
|
||||
|
||||
@ -333,32 +297,31 @@ void Engine::loadAssets() {
|
||||
}
|
||||
}
|
||||
assets = std::move(new_assets);
|
||||
|
||||
if (content) {
|
||||
for (auto& [name, def] : content->blocks.getDefs()) {
|
||||
if (def->model == BlockModel::custom) {
|
||||
if (def->modelName.empty()) {
|
||||
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()) {
|
||||
|
||||
if (content == nullptr) {
|
||||
return;
|
||||
}
|
||||
for (auto& [name, def] : content->blocks.getDefs()) {
|
||||
if (def->model == BlockModel::custom && def->modelName.empty()) {
|
||||
assets->store(
|
||||
std::make_unique<model::Model>(
|
||||
ModelsGenerator::generate(*def, *content, *assets)
|
||||
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 fs::path& root) {
|
||||
@ -468,14 +431,6 @@ void Engine::loadAllPacks() {
|
||||
contentPacks = manager.getAll(manager.assembly(allnames));
|
||||
}
|
||||
|
||||
double Engine::getDelta() const {
|
||||
return delta;
|
||||
}
|
||||
|
||||
double Engine::getUptime() const {
|
||||
return lastTime;
|
||||
}
|
||||
|
||||
void Engine::setScreen(std::shared_ptr<Screen> screen) {
|
||||
// reset audio channels (stop all sources)
|
||||
audio::reset_channel(audio::get_channel_index("regular"));
|
||||
@ -545,6 +500,14 @@ network::Network& Engine::getNetwork() {
|
||||
return *network;
|
||||
}
|
||||
|
||||
Time& Engine::getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
const CoreParameters& Engine::getCoreParameters() const {
|
||||
return params;
|
||||
}
|
||||
|
||||
bool Engine::isHeadless() const {
|
||||
return params.headless;
|
||||
}
|
||||
|
||||
@ -11,6 +11,7 @@
|
||||
#include "files/engine_paths.hpp"
|
||||
#include "files/settings_io.hpp"
|
||||
#include "util/ObjectsKeeper.hpp"
|
||||
#include "Time.hpp"
|
||||
|
||||
#include <filesystem>
|
||||
#include <memory>
|
||||
@ -23,7 +24,6 @@
|
||||
class Screen;
|
||||
class EnginePaths;
|
||||
class ResPaths;
|
||||
class Batch2D;
|
||||
class EngineController;
|
||||
class SettingsHandler;
|
||||
struct EngineSettings;
|
||||
@ -70,17 +70,12 @@ class Engine : public util::ObjectsKeeper {
|
||||
std::unique_ptr<network::Network> network;
|
||||
std::vector<std::string> basePacks;
|
||||
std::unique_ptr<gui::GUI> gui;
|
||||
|
||||
uint64_t frame = 0;
|
||||
double lastTime = 0.0;
|
||||
double delta = 0.0;
|
||||
Time time;
|
||||
|
||||
void loadControls();
|
||||
void loadSettings();
|
||||
void saveSettings();
|
||||
void updateTimers();
|
||||
void updateHotkeys();
|
||||
void renderFrame(Batch2D& batch);
|
||||
void processPostRunnables();
|
||||
void loadAssets();
|
||||
public:
|
||||
@ -90,11 +85,11 @@ public:
|
||||
/// @brief Start the engine
|
||||
void run();
|
||||
|
||||
/// @brief Start main engine input/update/render loop.
|
||||
/// Automatically sets MenuScreen
|
||||
void mainloop();
|
||||
void postUpdate();
|
||||
|
||||
void runTest();
|
||||
void updateFrontend();
|
||||
void renderFrame();
|
||||
void nextFrame();
|
||||
|
||||
/// @brief Called after assets loading when all engine systems are initialized
|
||||
void onAssetsLoaded();
|
||||
@ -122,11 +117,6 @@ public:
|
||||
/// @brief Collect all available content-packs from res/content
|
||||
void loadAllPacks();
|
||||
|
||||
/// @brief Get current frame delta-time
|
||||
double getDelta() const;
|
||||
|
||||
double getUptime() const;
|
||||
|
||||
/// @brief Get active assets storage instance
|
||||
Assets* getAssets();
|
||||
|
||||
@ -169,5 +159,9 @@ public:
|
||||
|
||||
network::Network& getNetwork();
|
||||
|
||||
Time& getTime();
|
||||
|
||||
const CoreParameters& getCoreParameters() const;
|
||||
|
||||
bool isHeadless() const;
|
||||
};
|
||||
|
||||
@ -56,7 +56,7 @@ std::shared_ptr<UINode> create_debug_panel(
|
||||
static std::wstring fpsString = L"";
|
||||
|
||||
panel->listenInterval(0.016f, [engine]() {
|
||||
fps = 1.0f / engine->getDelta();
|
||||
fps = 1.0f / engine->getTime().getDelta();
|
||||
fpsMin = std::min(fps, fpsMin);
|
||||
fpsMax = std::max(fps, fpsMax);
|
||||
});
|
||||
|
||||
@ -92,6 +92,9 @@ DrawContext DrawContext::sub(Flushable* flushable) const {
|
||||
ctx.parent = this;
|
||||
ctx.flushable = flushable;
|
||||
ctx.scissorsCount = 0;
|
||||
if (auto batch2D = dynamic_cast<Batch2D*>(flushable)) {
|
||||
ctx.g2d = batch2D;
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
|
||||
|
||||
@ -10,7 +10,7 @@ class Framebuffer;
|
||||
class DrawContext {
|
||||
const DrawContext* parent;
|
||||
Viewport viewport;
|
||||
Batch2D* const g2d;
|
||||
Batch2D* g2d;
|
||||
Flushable* flushable = nullptr;
|
||||
Framebuffer* fbo = nullptr;
|
||||
bool depthMask = true;
|
||||
|
||||
@ -23,7 +23,7 @@
|
||||
|
||||
using namespace gui;
|
||||
|
||||
GUI::GUI() {
|
||||
GUI::GUI() : batch2D(std::make_unique<Batch2D>(1024)) {
|
||||
container = std::make_shared<Container>(glm::vec2(1000));
|
||||
uicamera = std::make_unique<Camera>(glm::vec3(), Window::height);
|
||||
uicamera->perspective = false;
|
||||
@ -198,7 +198,9 @@ void GUI::act(float delta, const Viewport& vp) {
|
||||
}
|
||||
|
||||
void GUI::draw(const DrawContext& pctx, const Assets& assets) {
|
||||
auto& viewport = pctx.getViewport();
|
||||
auto ctx = pctx.sub(batch2D.get());
|
||||
|
||||
auto& viewport = ctx.getViewport();
|
||||
glm::vec2 wsize = viewport.size();
|
||||
|
||||
menu->setPos((wsize - menu->getSize()) / 2.0f);
|
||||
@ -208,8 +210,8 @@ void GUI::draw(const DrawContext& pctx, const Assets& assets) {
|
||||
uishader->use();
|
||||
uishader->uniformMatrix("u_projview", uicamera->getProjView());
|
||||
|
||||
pctx.getBatch2D()->begin();
|
||||
container->draw(pctx, assets);
|
||||
batch2D->begin();
|
||||
container->draw(ctx, assets);
|
||||
}
|
||||
|
||||
std::shared_ptr<UINode> GUI::getFocused() const {
|
||||
|
||||
@ -13,6 +13,7 @@ class Viewport;
|
||||
class DrawContext;
|
||||
class Assets;
|
||||
class Camera;
|
||||
class Batch2D;
|
||||
|
||||
/*
|
||||
Some info about padding and margin.
|
||||
@ -52,6 +53,7 @@ namespace gui {
|
||||
|
||||
/// @brief The main UI controller
|
||||
class GUI {
|
||||
std::unique_ptr<Batch2D> batch2D;
|
||||
std::shared_ptr<Container> container;
|
||||
std::shared_ptr<UINode> hover;
|
||||
std::shared_ptr<UINode> pressed;
|
||||
|
||||
@ -132,13 +132,18 @@ static void show_content_missing(
|
||||
menus::show(engine, "reports/missing_content", {std::move(root)});
|
||||
}
|
||||
|
||||
static bool loadWorldContent(Engine* engine, const fs::path& folder) {
|
||||
return menus::call(engine, [engine, folder]() {
|
||||
static bool load_world_content(Engine* engine, const fs::path& folder) {
|
||||
if (engine->isHeadless()) {
|
||||
engine->loadWorldContent(folder);
|
||||
});
|
||||
return true;
|
||||
} else {
|
||||
return menus::call(engine, [engine, folder]() {
|
||||
engine->loadWorldContent(folder);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
static void loadWorld(Engine* engine, const std::shared_ptr<WorldFiles>& worldFiles) {
|
||||
static void load_world(Engine* engine, const std::shared_ptr<WorldFiles>& worldFiles) {
|
||||
try {
|
||||
auto content = engine->getContent();
|
||||
auto& packs = engine->getContentPacks();
|
||||
@ -160,7 +165,12 @@ static void loadWorld(Engine* engine, const std::shared_ptr<WorldFiles>& worldFi
|
||||
void EngineController::openWorld(const std::string& name, bool confirmConvert) {
|
||||
auto paths = engine->getPaths();
|
||||
auto folder = paths->getWorldsFolder() / fs::u8path(name);
|
||||
if (!loadWorldContent(engine, folder)) {
|
||||
auto worldFile = folder / fs::u8path("world.json");
|
||||
if (!fs::exists(worldFile)) {
|
||||
throw std::runtime_error(worldFile.u8string() + " does not exists");
|
||||
}
|
||||
|
||||
if (!load_world_content(engine, folder)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -192,7 +202,7 @@ void EngineController::openWorld(const std::string& name, bool confirmConvert) {
|
||||
}
|
||||
return;
|
||||
}
|
||||
loadWorld(engine, std::move(worldFiles));
|
||||
load_world(engine, std::move(worldFiles));
|
||||
}
|
||||
|
||||
inline uint64_t str2seed(const std::string& seedstr) {
|
||||
|
||||
@ -5,11 +5,11 @@
|
||||
using namespace scripting;
|
||||
|
||||
static int l_uptime(lua::State* L) {
|
||||
return lua::pushnumber(L, engine->getUptime());
|
||||
return lua::pushnumber(L, engine->getTime().getTime());
|
||||
}
|
||||
|
||||
static int l_delta(lua::State* L) {
|
||||
return lua::pushnumber(L, engine->getDelta());
|
||||
return lua::pushnumber(L, engine->getTime().getDelta());
|
||||
}
|
||||
|
||||
const luaL_Reg timelib[] = {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user