313 lines
9.1 KiB
C++
313 lines
9.1 KiB
C++
#include "ADVect.h"
|
|
#include "Environment.h"
|
|
#include "Graphics.h"
|
|
#include "Track.h"
|
|
|
|
#include <SDL.h>
|
|
#include <SDL_main.h>
|
|
#include <SDL_timer.h>
|
|
#include <bx/math.h>
|
|
#include <SDL_syswm.h>
|
|
#include <bgfx/bgfx.h>
|
|
#include <bgfx/platform.h>
|
|
|
|
#include <functional>
|
|
#include <iostream>
|
|
|
|
#include <filesystem>
|
|
|
|
namespace {
|
|
SDL_Window* window;
|
|
u16 window_width = 1280;
|
|
u16 window_height = 720;
|
|
|
|
u64 init_time, last_time, current_time, delta_t;
|
|
bool running = false;
|
|
|
|
bool draw_ui = true;
|
|
|
|
bool m_keys[65536]{}; // terrible
|
|
bool mouse[256]{ true }; // terrible
|
|
|
|
std::vector<NVL::Parse::Scene> scenes;
|
|
u32 current_scene = 0;
|
|
u32 scene_pos = 0;
|
|
|
|
ADVect::MarkupTextTransitionTrack m_text{
|
|
.current{},
|
|
.pos_x = 280, .pos_y = 90, .w = 800, .h = 500,
|
|
.opacity = 1.0f, .fill = 0xFFFFFFFF
|
|
};
|
|
ADVect::TextTrack speaker = {
|
|
.current{},
|
|
.pos_x = 250, .pos_y = 150,
|
|
.w = 500, .h = 500,
|
|
.opacity = 1.0f, .fill = 0xFFFFFFFF
|
|
};
|
|
ADVect::ImageTransitionTrack bg = {
|
|
.current{},
|
|
.pos_x = 0, .pos_y = 0,
|
|
.w = 500, .h = 500
|
|
}, avatar = {
|
|
.current{},
|
|
.pos_x = 10, .pos_y = 0,
|
|
.w = 500, .h = 500
|
|
};
|
|
ADVect::ImageTrack dialogue_bg = {
|
|
.current{},
|
|
.pos_x = 0, .pos_y = 0,
|
|
.w = 500, .h = 500
|
|
};
|
|
std::vector<std::function<void(u64)>> track_updaters;
|
|
}
|
|
|
|
namespace ADVect {
|
|
bool Init(std::string name, const std::vector<NVL::Parse::Scene>& sc) {
|
|
scenes = sc; // sure make a copy whatever
|
|
|
|
if (SDL_Init(SDL_INIT_VIDEO)) {
|
|
std::cerr << "ADV: Failed to init SDL: " << SDL_GetError() << std::endl;
|
|
return false;
|
|
}
|
|
|
|
window = SDL_CreateWindow(name.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, window_width, window_height, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
|
|
if (window == NULL) {
|
|
std::cerr << "ADV: Failed to create window: " << SDL_GetError() << std::endl;
|
|
return false;
|
|
}
|
|
|
|
bgfx::Init bgfxInit;
|
|
bgfxInit.type = bgfx::RendererType::Count; // Automatically choose a renderer.
|
|
bgfxInit.resolution.width = window_width;
|
|
bgfxInit.resolution.height = window_height;
|
|
bgfxInit.resolution.reset = BGFX_RESET_VSYNC;
|
|
|
|
#if !BX_PLATFORM_EMSCRIPTEN
|
|
SDL_SysWMinfo wmi;
|
|
SDL_VERSION(&wmi.version);
|
|
if (!SDL_GetWindowWMInfo(window, &wmi)) {
|
|
std::cerr << "ADV: SDL_SysWMinfo could not be retrieved: " << SDL_GetError() << std::endl;
|
|
}
|
|
#endif
|
|
#if BX_PLATFORM_WINDOWS
|
|
bgfxInit.platformData.nwh = wmi.info.win.window;
|
|
#elif BX_PLATFORM_OSX
|
|
bgfxInit.platformData.nwh = wmi.info.cocoa.window;
|
|
bgfx::renderFrame();
|
|
#elif BX_PLATFORM_LINUX
|
|
bgfxInit.platformData.ndt = wmi.info.x11.display;
|
|
bgfxInit.platformData.nwh = (void*)(uintptr_t)wmi.info.x11.window;
|
|
#elif BX_PLATFORM_EMSCRIPTEN
|
|
bgfxInit.platformData.nwh = (void*)"#canvas";
|
|
#endif
|
|
|
|
if (!bgfx::init(bgfxInit)) {
|
|
std::cerr << "ADV: Failed bgfx initialization" << std::endl;
|
|
return false;
|
|
};
|
|
bgfx::setDebug(BGFX_DEBUG_TEXT);
|
|
bgfx::setViewClear(0, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH, 0x443322ff, 1.0f, 0);
|
|
bgfx::setViewRect(0, 0, 0, window_width, window_height);
|
|
bgfx::setViewMode(0, bgfx::ViewMode::Sequential);
|
|
float view[16];
|
|
bx::mtxTranslate(view, 0.f, 0.f, 1.0f);
|
|
float proj[16];
|
|
bx::mtxOrtho(proj, 0.0f, window_width, 0.0f, window_height, 0.1f, 100.0f, 0.f, bgfx::getCaps()->homogeneousDepth);
|
|
bgfx::setViewTransform(0, view, proj);
|
|
|
|
if (!ADVect::Graphics::Init(window_width, window_height)) {
|
|
std::cerr << "ADV: Graphics init failed" << std::endl;
|
|
return false;
|
|
}
|
|
|
|
track_updaters.push_back(std::bind(&decltype(bg)::check, &bg, std::placeholders::_1));
|
|
track_updaters.push_back(std::bind(&decltype(avatar)::check, &avatar, std::placeholders::_1));
|
|
track_updaters.push_back(std::bind(&decltype(m_text)::check, &m_text, std::placeholders::_1));
|
|
|
|
Advance();
|
|
return true;
|
|
}
|
|
|
|
void Shutdown() {
|
|
Graphics::Shutdown();
|
|
bgfx::shutdown();
|
|
SDL_DestroyWindow(window);
|
|
SDL_Quit();
|
|
}
|
|
|
|
void Advance() {
|
|
if (!m_text.transition.done) m_text.transition.done = true;
|
|
else {
|
|
size_t curr_size = scenes[current_scene].get().size();
|
|
while (scene_pos < curr_size && std::get<NVL::String>(scenes[current_scene].get()[scene_pos][0].value) != u"Say") {
|
|
NVL::Environment::Apply(scenes[current_scene].get()[scene_pos]);
|
|
scene_pos++;
|
|
}
|
|
if (curr_size == scene_pos) {
|
|
running = false;
|
|
return;
|
|
}
|
|
if (std::get<NVL::String>(scenes[current_scene].get()[scene_pos][0].value) == u"Say") {
|
|
NVL::Environment::Apply(scenes[current_scene].get()[scene_pos]);
|
|
scene_pos++;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Update() {
|
|
if (m_keys[SDL_SCANCODE_RETURN]) {
|
|
if (draw_ui)
|
|
Advance();
|
|
else
|
|
draw_ui ^= true;
|
|
m_keys[SDL_SCANCODE_RETURN] = false;
|
|
}
|
|
if (m_keys[SDL_SCANCODE_SPACE]) {
|
|
draw_ui ^= true;
|
|
m_keys[SDL_SCANCODE_SPACE] = false;
|
|
}
|
|
if (!mouse[SDL_BUTTON_LEFT]) {
|
|
if (draw_ui)
|
|
Advance();
|
|
else
|
|
draw_ui ^= true;
|
|
|
|
mouse[SDL_BUTTON_LEFT] = true;
|
|
}
|
|
if (m_keys[SDL_SCANCODE_LCTRL]) {
|
|
if (draw_ui)
|
|
Advance();
|
|
}
|
|
|
|
for (const auto& x : track_updaters) {
|
|
x(current_time);
|
|
}
|
|
|
|
}
|
|
|
|
void Render() {
|
|
bgfx::touch(0);
|
|
|
|
draw_image_transition_crossfade(current_time, bg);
|
|
|
|
if (draw_ui) {
|
|
if (dialogue_bg.current != nullptr)
|
|
ADVect::Graphics::DrawTextureImageAlpha(*dialogue_bg.current, dialogue_bg.pos_x, dialogue_bg.pos_y, 1.0f);
|
|
draw_image_transition_crossfade(current_time, avatar);
|
|
|
|
ADVect::Graphics::RenderString<true, false>(speaker.current, speaker.pos_x, speaker.pos_y, speaker.fill, ADVect::Graphics::TEXT_BOLD);
|
|
draw_typewriter(current_time, m_text);
|
|
}
|
|
|
|
const bgfx::Stats* stat = bgfx::getStats();
|
|
bgfx::dbgTextClear();
|
|
bgfx::dbgTextPrintf(0, 0, 0xf8, " %u FPS", stat->cpuTimerFreq / stat->cpuTimeFrame);
|
|
bgfx::dbgTextPrintf(0, 1, 0xf8, " NouVeL x ADVect :: %s :: Build %s %s", BX_COMPILER_NAME, __DATE__, __TIME__);
|
|
bgfx::dbgTextPrintf(0, 2, 0xf8, " SDL %i.%i.%2i :: bgfx 1.%i :: %s", SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL, BGFX_API_VERSION, bgfx::getRendererName(bgfx::getRendererType()));
|
|
bgfx::dbgTextPrintf(0, 3, 0xf8, " Current Position: %u", scene_pos);
|
|
bgfx::dbgTextPrintf(0, 4, 0xf8, " Current Scene: %s", NVL::to_std_string(scenes[current_scene].name).c_str());
|
|
|
|
bgfx::frame();
|
|
}
|
|
|
|
void Run() {
|
|
last_time = init_time = SDL_GetTicks64();
|
|
|
|
running = true;
|
|
while (running) {
|
|
current_time = SDL_GetTicks64();
|
|
delta_t = current_time - last_time;
|
|
|
|
for (SDL_Event event; SDL_PollEvent(&event);) {
|
|
switch (event.type) {
|
|
case SDL_QUIT:
|
|
running = false;
|
|
break;
|
|
case SDL_KEYDOWN:
|
|
if (!event.key.repeat)
|
|
m_keys[event.key.keysym.scancode] = true;
|
|
break;
|
|
case SDL_KEYUP:
|
|
if (!event.key.repeat)
|
|
m_keys[event.key.keysym.scancode] = false;
|
|
break;
|
|
case SDL_MOUSEBUTTONDOWN:
|
|
mouse[event.button.button] = true;
|
|
break;
|
|
case SDL_MOUSEBUTTONUP:
|
|
mouse[event.button.button] = false;
|
|
break;
|
|
}
|
|
|
|
}
|
|
Update();
|
|
Render();
|
|
|
|
last_time = current_time;
|
|
}
|
|
}
|
|
}
|
|
|
|
int main(int argc, char* argv[]) {
|
|
std::filesystem::current_path("E:\\Archive\\Projects\\NouVeL\\ADVect\\runtime");
|
|
//std::filesystem::current_path("/Users/lachrymal/Projects/NouVeL/ADVect/runtime/");
|
|
|
|
NVL::Environment::ENVIRONMENT.enter({
|
|
{
|
|
u"Say",
|
|
NVL::Environment::Variable([](std::vector<NVL::Environment::Variable> args) {
|
|
NVL::Environment::MarkupString str = NVL::Environment::UnpackMarkupVariable(std::get<std::vector<NVL::Environment::Variable>>(args[0].value));
|
|
size_t len = str.length();
|
|
m_text.change(current_time, str, len * 10, [len](NVL::Number x) { return static_cast<size_t>(x * len); });
|
|
return NVL::Environment::Type::Nil;
|
|
}, 1)
|
|
},
|
|
{
|
|
u"SwitchSpeaker",
|
|
NVL::Environment::Variable([](std::vector<NVL::Environment::Variable> args) {
|
|
speaker.current = std::get<NVL::String>(args[0].value);
|
|
return NVL::Environment::Type::Nil;
|
|
}, 1)
|
|
},
|
|
{
|
|
u"BG",
|
|
NVL::Environment::Variable([](std::vector<NVL::Environment::Variable> args) {
|
|
bg.change(current_time, ADVect::Graphics::GetImageTextureFromFile(NVL::to_std_string(std::get<NVL::String>(args[0].value))), 200);
|
|
return NVL::Environment::Type::Nil;
|
|
}, 1)
|
|
},
|
|
{
|
|
u"Avatar",
|
|
NVL::Environment::Variable([](std::vector<NVL::Environment::Variable> args) {
|
|
avatar.change(current_time, ADVect::Graphics::GetImageTextureFromFile(NVL::to_std_string(std::get<NVL::String>(args[0].value))), 200);
|
|
return NVL::Environment::Type::Nil;
|
|
}, 1)
|
|
},
|
|
{
|
|
u"BGDialogue",
|
|
NVL::Environment::Variable([](std::vector<NVL::Environment::Variable> args) {
|
|
dialogue_bg.current = ADVect::Graphics::GetImageTextureFromFile(NVL::to_std_string(std::get<NVL::String>(args[0].value)));
|
|
return NVL::Environment::Type::Nil;
|
|
}, 1)
|
|
},
|
|
{
|
|
u"Show",
|
|
NVL::Environment::Variable([](std::vector<NVL::Environment::Variable> args) {
|
|
std::get<std::function<NVL::Environment::Variable(std::vector<NVL::Environment::Variable>)>>(args[0].value)({args[1]});
|
|
return NVL::Environment::Type::Nil;
|
|
}, 2)
|
|
}
|
|
});
|
|
|
|
std::vector<NVL::Parse::Scene> SCENES = NVL::Parse::ParseFile("dialogue.nvl");
|
|
if (SCENES.empty()) {
|
|
std::cerr << "Main: Empty NVL parse, check file" << std::endl;
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
if (!ADVect::Init("ADV Test", SCENES)) return EXIT_FAILURE;
|
|
ADVect::Run();
|
|
|
|
ADVect::Shutdown();
|
|
return EXIT_SUCCESS;
|
|
}
|