Compare commits
10 commits
0b6096afd5
...
6903c2d3ca
Author | SHA1 | Date | |
---|---|---|---|
6903c2d3ca | |||
3a40e5697d | |||
38496209c0 | |||
|
bdf80f37e6 | ||
572ba4feb0 | |||
f2f4889161 | |||
1248defb9b | |||
5391c47b88 | |||
629f1075a0 | |||
|
93b8864834 |
37 changed files with 3454 additions and 331 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -5,3 +5,5 @@ build
|
||||||
NVL/.vs
|
NVL/.vs
|
||||||
NVL/out
|
NVL/out
|
||||||
.cache
|
.cache
|
||||||
|
vs
|
||||||
|
**/.DS_STORE
|
||||||
|
|
|
@ -2,18 +2,22 @@
|
||||||
#include "Environment.h"
|
#include "Environment.h"
|
||||||
#include "Graphics.h"
|
#include "Graphics.h"
|
||||||
#include "Track.h"
|
#include "Track.h"
|
||||||
|
#include "Compiler.h"
|
||||||
|
#include "Director.h"
|
||||||
|
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL.h>
|
||||||
#include <SDL2/SDL_main.h>
|
#include <SDL_main.h>
|
||||||
#include <SDL2/SDL_timer.h>
|
#include <SDL_timer.h>
|
||||||
#include <bx/math.h>
|
#include <bx/math.h>
|
||||||
#include <SDL2/SDL_syswm.h>
|
#include <SDL_syswm.h>
|
||||||
#include <bgfx/bgfx.h>
|
#include <bgfx/bgfx.h>
|
||||||
#include <bgfx/platform.h>
|
#include <bgfx/platform.h>
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -22,20 +26,18 @@ namespace {
|
||||||
u16 window_height = 720;
|
u16 window_height = 720;
|
||||||
|
|
||||||
u64 init_time, last_time, current_time, delta_t;
|
u64 init_time, last_time, current_time, delta_t;
|
||||||
bool running = false;
|
bool running = false, rolling = true;
|
||||||
|
|
||||||
bool draw_ui = true;
|
bool draw_ui = true;
|
||||||
|
|
||||||
bool m_keys[65536]{}; // terrible
|
bool m_keys[65536]{}; // terrible
|
||||||
bool mouse[256]{ true }; // terrible
|
bool mouse[256]{ true }; // terrible
|
||||||
|
|
||||||
std::vector<NVL::Parse::Scene> scenes;
|
std::unique_ptr<NVL::Director::Director> director;
|
||||||
u32 current_scene = 0;
|
|
||||||
u32 scene_pos = 0;
|
|
||||||
|
|
||||||
ADVect::MarkupTextTransitionTrack m_text{
|
ADVect::MarkupTextTransitionTrack m_text{
|
||||||
.current{},
|
.current{},
|
||||||
.pos_x = 280, .pos_y = 90, .w = 900, .h = 500,
|
.pos_x = 280, .pos_y = 90, .w = 800, .h = 500,
|
||||||
.opacity = 1.0f, .fill = 0xFFFFFFFF
|
.opacity = 1.0f, .fill = 0xFFFFFFFF
|
||||||
};
|
};
|
||||||
ADVect::TextTrack speaker = {
|
ADVect::TextTrack speaker = {
|
||||||
|
@ -58,33 +60,12 @@ namespace {
|
||||||
.pos_x = 0, .pos_y = 0,
|
.pos_x = 0, .pos_y = 0,
|
||||||
.w = 500, .h = 500
|
.w = 500, .h = 500
|
||||||
};
|
};
|
||||||
/*
|
std::vector<std::function<void(u64)>> track_updaters;
|
||||||
std::list<NamedImageTrack> tracks_img{}; // instead of vector because we need pointers to members; prevent use after free
|
|
||||||
NamedImageTrack* find_image_track(const std::string& s) {
|
|
||||||
for (auto& t : tracks_img)
|
|
||||||
if (t.name == s) {
|
|
||||||
return &t;
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
bool add_image_track(const std::string& s) {
|
|
||||||
if (find_image_track(s) == nullptr) {
|
|
||||||
NamedImageTrack t;
|
|
||||||
t.name = s;
|
|
||||||
tracks_img.push_back(std::move(t));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
std::cerr << "ADV: Redefinition of ImageTrack " << s << std::endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace ADVect {
|
namespace ADVect {
|
||||||
bool Init(std::string name, const std::vector<NVL::Parse::Scene>& sc) {
|
bool Init(std::string name, const NVL::Compiler::NVLGraph& g) {
|
||||||
scenes = sc; // sure make a copy whatever
|
director = std::make_unique<NVL::Director::Director>(g);
|
||||||
|
|
||||||
if (SDL_Init(SDL_INIT_VIDEO)) {
|
if (SDL_Init(SDL_INIT_VIDEO)) {
|
||||||
std::cerr << "ADV: Failed to init SDL: " << SDL_GetError() << std::endl;
|
std::cerr << "ADV: Failed to init SDL: " << SDL_GetError() << std::endl;
|
||||||
|
@ -114,6 +95,7 @@ namespace ADVect {
|
||||||
bgfxInit.platformData.nwh = wmi.info.win.window;
|
bgfxInit.platformData.nwh = wmi.info.win.window;
|
||||||
#elif BX_PLATFORM_OSX
|
#elif BX_PLATFORM_OSX
|
||||||
bgfxInit.platformData.nwh = wmi.info.cocoa.window;
|
bgfxInit.platformData.nwh = wmi.info.cocoa.window;
|
||||||
|
bgfx::renderFrame();
|
||||||
#elif BX_PLATFORM_LINUX
|
#elif BX_PLATFORM_LINUX
|
||||||
bgfxInit.platformData.ndt = wmi.info.x11.display;
|
bgfxInit.platformData.ndt = wmi.info.x11.display;
|
||||||
bgfxInit.platformData.nwh = (void*)(uintptr_t)wmi.info.x11.window;
|
bgfxInit.platformData.nwh = (void*)(uintptr_t)wmi.info.x11.window;
|
||||||
|
@ -140,6 +122,10 @@ namespace ADVect {
|
||||||
return false;
|
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();
|
Advance();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -153,21 +139,15 @@ namespace ADVect {
|
||||||
|
|
||||||
void Advance() {
|
void Advance() {
|
||||||
if (!m_text.transition.done) m_text.transition.done = true;
|
if (!m_text.transition.done) m_text.transition.done = true;
|
||||||
else {
|
else if (director->active) {
|
||||||
size_t curr_size = scenes[current_scene].get().size();
|
rolling = true;
|
||||||
while (scene_pos < curr_size && std::get<NVL::String>(scenes[current_scene].get()[scene_pos][0].value) != u"Say") {
|
director->Advance();
|
||||||
NVL::Environment::Apply(scenes[current_scene].get()[scene_pos]);
|
|
||||||
scene_pos++;
|
|
||||||
}
|
}
|
||||||
if (curr_size == scene_pos) {
|
else
|
||||||
running = false;
|
running = false;
|
||||||
return;
|
|
||||||
}
|
if (running && rolling)
|
||||||
if (std::get<NVL::String>(scenes[current_scene].get()[scene_pos][0].value) == u"Say") {
|
Advance();
|
||||||
NVL::Environment::Apply(scenes[current_scene].get()[scene_pos]);
|
|
||||||
scene_pos++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Update() {
|
void Update() {
|
||||||
|
@ -195,28 +175,23 @@ namespace ADVect {
|
||||||
Advance();
|
Advance();
|
||||||
}
|
}
|
||||||
|
|
||||||
bg.check(current_time);
|
for (const auto& x : track_updaters) {
|
||||||
avatar.check(current_time);
|
x(current_time);
|
||||||
m_text.check(current_time);
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Render() {
|
void Render() {
|
||||||
bgfx::touch(0);
|
bgfx::touch(0);
|
||||||
|
|
||||||
/*
|
draw_image_transition_crossfade(current_time, bg);
|
||||||
for (auto& t : tracks_img) {
|
|
||||||
if (t.current != nullptr)
|
|
||||||
ADVect::Graphics::DrawTextureImage(*t.current, t.pos_x, t.pos_y);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
draw_image_transition_fade(current_time, bg);
|
|
||||||
|
|
||||||
if (draw_ui) {
|
if (draw_ui) {
|
||||||
if (dialogue_bg.current != nullptr)
|
if (dialogue_bg.current != nullptr)
|
||||||
ADVect::Graphics::DrawTextureImage(*dialogue_bg.current, dialogue_bg.pos_x, dialogue_bg.pos_y);
|
ADVect::Graphics::DrawTextureImageAlpha(*dialogue_bg.current, dialogue_bg.pos_x, dialogue_bg.pos_y, 1.0f);
|
||||||
draw_image_transition_crossfade(current_time, avatar);
|
draw_image_transition_crossfade(current_time, avatar);
|
||||||
|
|
||||||
ADVect::Graphics::RenderString(speaker.current, speaker.pos_x, speaker.pos_y, speaker.fill, ADVect::Graphics::TEXT_BOLD);
|
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);
|
draw_typewriter(current_time, m_text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,8 +200,7 @@ namespace ADVect {
|
||||||
bgfx::dbgTextPrintf(0, 0, 0xf8, " %u FPS", stat->cpuTimerFreq / stat->cpuTimeFrame);
|
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, 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, 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, 3, 0xf8, " NVL Director State: %s", NVL::to_std_string(director->description).c_str());
|
||||||
bgfx::dbgTextPrintf(0, 4, 0xf8, " Current Scene: %s", NVL::to_std_string(scenes[current_scene].name).c_str());
|
|
||||||
|
|
||||||
bgfx::frame();
|
bgfx::frame();
|
||||||
}
|
}
|
||||||
|
@ -271,66 +245,79 @@ namespace ADVect {
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
std::filesystem::current_path("E:\\Archive\\Projects\\NouVeL\\ADVect\\runtime");
|
std::filesystem::current_path("E:\\Archive\\Projects\\NouVeL\\ADVect\\runtime");
|
||||||
|
//std::filesystem::current_path("/Users/lachrymal/Projects/NouVeL/ADVect/runtime/");
|
||||||
NVL::Environment::ENVIRONMENT.enter({
|
NVL::Environment::ENVIRONMENT.enter({
|
||||||
{
|
{
|
||||||
u"Say",
|
u"Say",
|
||||||
NVL::Environment::Variable([](std::vector<NVL::Environment::Variable> args) {
|
NVL::Environment::Variable([](std::vector<NVL::Environment::Variable> args) {
|
||||||
NVL::Environment::MarkupString str = NVL::Environment::UnpackMarkupVariable(std::get<std::vector<NVL::Environment::Variable>>(NVL::Environment::Variable(args[0]).value));
|
NVL::Environment::MarkupString str = NVL::Environment::UnpackMarkupVariable(std::get<std::vector<NVL::Environment::Variable>>(args[0].value));
|
||||||
size_t len = str.length();
|
size_t len = str.length();
|
||||||
m_text.change(current_time, str, len * 10, [len](NVL::Number x) { return static_cast<size_t>(x * len); });
|
m_text.change(current_time, str, len * 10, [len](NVL::Number x) { return static_cast<size_t>(x * len); });
|
||||||
|
rolling = false;
|
||||||
return NVL::Environment::Type::Nil;
|
return NVL::Environment::Type::Nil;
|
||||||
}, 2)
|
}, 1)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
u"SwitchSpeaker",
|
u"SwitchSpeaker",
|
||||||
NVL::Environment::Variable([](std::vector<NVL::Environment::Variable> args) {
|
NVL::Environment::Variable([](std::vector<NVL::Environment::Variable> args) {
|
||||||
speaker.current = std::get<NVL::String>(NVL::Environment::Variable(args[0]).value);
|
speaker.current = std::get<NVL::String>(args[0].value);
|
||||||
return NVL::Environment::Type::Nil;
|
return NVL::Environment::Type::Nil;
|
||||||
}, 1)
|
}, 1)
|
||||||
},
|
},
|
||||||
/* {
|
{
|
||||||
u"ImageTrack",
|
u"BG",
|
||||||
NVL::Environment::Variable([](std::vector<NVL::Environment::Variable> args) {
|
NVL::Environment::Variable([](std::vector<NVL::Environment::Variable> args) {
|
||||||
add_image_track(NVL::to_std_string(std::get<NVL::String>(NVL::Environment::Variable(args[0]).value)));
|
bg.change(current_time, ADVect::Graphics::GetImageTextureFromFile(NVL::to_std_string(std::get<NVL::String>(args[0].value))), 200);
|
||||||
return NVL::Environment::Type::Nil;
|
return NVL::Environment::Type::Nil;
|
||||||
}, 1)
|
}, 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",
|
u"Show",
|
||||||
NVL::Environment::Variable([](std::vector<NVL::Environment::Variable> args) {
|
NVL::Environment::Variable([](std::vector<NVL::Environment::Variable> args) {
|
||||||
std::string name = NVL::to_std_string(std::get<NVL::String>(NVL::Environment::Variable(args[0]).value));
|
std::get<std::function<NVL::Environment::Variable(std::vector<NVL::Environment::Variable>)>>(args[0].value)({args[1]});
|
||||||
/* NamedImageTrack* t = find_image_track(name);
|
|
||||||
if (t == nullptr) {
|
|
||||||
std::cerr << "ADV: Cannot find ImageTrack " << name << std::endl;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
auto s = std::get<NVL::String>(NVL::Environment::Variable(args[1]).value);
|
|
||||||
auto s2 = NVL::to_std_string(s);
|
|
||||||
t->current = ADVect::Graphics::GetImageTextureFromFile(s2);
|
|
||||||
}*/
|
|
||||||
if (name == "BG")
|
|
||||||
bg.change(current_time, ADVect::Graphics::GetImageTextureFromFile(NVL::to_std_string(std::get<NVL::String>(NVL::Environment::Variable(args[1]).value))), 200);
|
|
||||||
else if (name == "Avatar")
|
|
||||||
avatar.change(current_time, ADVect::Graphics::GetImageTextureFromFile(NVL::to_std_string(std::get<NVL::String>(NVL::Environment::Variable(args[1]).value))), 200);
|
|
||||||
else if (name == "BGDialogue")
|
|
||||||
dialogue_bg.current = ADVect::Graphics::GetImageTextureFromFile(NVL::to_std_string(std::get<NVL::String>(NVL::Environment::Variable(args[1]).value)));
|
|
||||||
else
|
|
||||||
std::cerr << "ADV: Cannot find ImageTrack " << name << std::endl;
|
|
||||||
return NVL::Environment::Type::Nil;
|
return NVL::Environment::Type::Nil;
|
||||||
}, 2)
|
}, 2)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
std::vector<NVL::Parse::Scene> SCENES = NVL::Parse::ParseFile("dialogue.nvl");
|
//std::vector<NVL::Parse::Scene> scenes = NVL::Parse::ParseFile("dialogue.nvl");
|
||||||
if (SCENES.empty()) {
|
//if (scenes.empty()) {
|
||||||
std::cerr << "Main: Empty NVL parse, check file" << std::endl;
|
// std::cerr << "Main: Empty NVL parse, check file" << std::endl;
|
||||||
return EXIT_FAILURE;
|
// return EXIT_FAILURE;
|
||||||
}
|
//}
|
||||||
|
|
||||||
if (!ADVect::Init("ADV Test", SCENES)) return EXIT_FAILURE;
|
//auto a = NVL::Compiler::Compile(scenes, 0);
|
||||||
|
//auto b = NVL::Compiler::Serialize(a);
|
||||||
|
|
||||||
|
std::ifstream f;
|
||||||
|
f.open("mmoker.nvlb", std::ios::binary);
|
||||||
|
|
||||||
|
std::stringstream c;
|
||||||
|
c << f.rdbuf();
|
||||||
|
f.close();
|
||||||
|
|
||||||
|
std::istringstream d(c.str());
|
||||||
|
|
||||||
|
auto e = NVL::Compiler::Deserialize(d);
|
||||||
|
|
||||||
|
if (!ADVect::Init("ADV Test", e)) return EXIT_FAILURE;
|
||||||
ADVect::Run();
|
ADVect::Run();
|
||||||
|
|
||||||
ADVect::Shutdown();
|
ADVect::Shutdown();
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
0
ADVect/Audio.cpp
Normal file
0
ADVect/Audio.cpp
Normal file
2
ADVect/Audio.h
Normal file
2
ADVect/Audio.h
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
#pragma once
|
||||||
|
#include "SDL_mixer.h"
|
|
@ -5,15 +5,19 @@ cmake_minimum_required (VERSION 3.8)
|
||||||
|
|
||||||
project (ADVect)
|
project (ADVect)
|
||||||
|
|
||||||
add_executable (Game "ADVect.cpp" "Graphics.cpp" "Track.h")
|
add_executable (Game "ADVect.cpp" "Graphics.cpp" "Track.h" "Audio.cpp" "Audio.h")
|
||||||
|
|
||||||
# TODO: Add tests and install targets if needed.
|
# TODO: Add tests and install targets if needed.
|
||||||
include_directories ("include" "../NVL/")
|
include_directories ("include" "../NVL/")
|
||||||
add_subdirectory("ext/freetype")
|
add_subdirectory("ext/freetype")
|
||||||
add_subdirectory("ext/bgfx")
|
add_subdirectory("ext/bgfx")
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
include_directories("include_windows")
|
include_directories("include_windows" "include_windows/SDL2")
|
||||||
target_link_libraries (Game PRIVATE ${PROJECT_SOURCE_DIR}/lib/SDL2.lib ${PROJECT_SOURCE_DIR}/lib/SDL2main.lib NVL freetype bgfx bx)
|
target_link_libraries (Game PRIVATE ${PROJECT_SOURCE_DIR}/lib/SDL2.lib ${PROJECT_SOURCE_DIR}/lib/SDL2main.lib NVL freetype bgfx bx)
|
||||||
|
elseif (APPLE)
|
||||||
|
set_target_properties(Game PROPERTIES XCODE_ATTRIBUTE_ENABLE_BITCODE "NO")
|
||||||
|
find_package(SDL2 REQUIRED)
|
||||||
|
target_link_libraries (Game PRIVATE NVL freetype bgfx bx SDL2::SDL2)
|
||||||
else ()
|
else ()
|
||||||
find_package(SDL2 REQUIRED)
|
find_package(SDL2 REQUIRED)
|
||||||
target_link_libraries (Game PRIVATE NVL freetype bgfx bx SDL2::SDL2 SDL2::SDL2main)
|
target_link_libraries (Game PRIVATE NVL freetype bgfx bx SDL2::SDL2 SDL2::SDL2main)
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#include "Graphics.h"
|
#include "Graphics.h"
|
||||||
#include "Environment.h"
|
|
||||||
#include <ft2build.h>
|
#include <ft2build.h>
|
||||||
#include FT_FREETYPE_H
|
#include FT_FREETYPE_H
|
||||||
|
|
||||||
|
@ -7,6 +6,7 @@
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#define STB_IMAGE_IMPLEMENTATION
|
#define STB_IMAGE_IMPLEMENTATION
|
||||||
#include <stb_image.h>
|
#include <stb_image.h>
|
||||||
|
@ -73,9 +73,10 @@ namespace {
|
||||||
|
|
||||||
struct Font {
|
struct Font {
|
||||||
FT_Face face = nullptr;
|
FT_Face face = nullptr;
|
||||||
std::unordered_map<NVL::Char, bgfx::TextureHandle> cache{};
|
std::unordered_map<NVL::Char, std::tuple<std::optional<bgfx::TextureHandle>, u32, u32, i32, i32, i32, i32>> cache{};
|
||||||
|
|
||||||
void cache_char(NVL::Char c) {
|
std::tuple<std::optional<bgfx::TextureHandle>, u32, u32, i32, i32, i32, i32>& get_char(NVL::Char c) {
|
||||||
|
if (cache.find(c) == cache.end()) {
|
||||||
FT_GlyphSlot slot = face->glyph;
|
FT_GlyphSlot slot = face->glyph;
|
||||||
|
|
||||||
error = FT_Load_Char(face, c, FT_LOAD_RENDER);
|
error = FT_Load_Char(face, c, FT_LOAD_RENDER);
|
||||||
|
@ -83,10 +84,11 @@ namespace {
|
||||||
std::cerr << "ADV: Failed to load character" << std::endl;
|
std::cerr << "ADV: Failed to load character" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cache.find(c) == cache.end() && slot->bitmap.width != 0) {
|
if (slot->bitmap.width != 0) {
|
||||||
const bgfx::Memory* buf = bgfx::copy(slot->bitmap.buffer, slot->bitmap.pitch * slot->bitmap.rows);
|
const bgfx::Memory* buf = bgfx::copy(slot->bitmap.buffer, slot->bitmap.pitch * slot->bitmap.rows);
|
||||||
|
|
||||||
cache.emplace(c, bgfx::createTexture2D(
|
cache.emplace(c, std::make_tuple(
|
||||||
|
bgfx::createTexture2D(
|
||||||
slot->bitmap.width,
|
slot->bitmap.width,
|
||||||
slot->bitmap.rows,
|
slot->bitmap.rows,
|
||||||
false,
|
false,
|
||||||
|
@ -94,8 +96,25 @@ namespace {
|
||||||
bgfx::TextureFormat::A8,
|
bgfx::TextureFormat::A8,
|
||||||
BGFX_TEXTURE_NONE | BGFX_SAMPLER_UVW_CLAMP,
|
BGFX_TEXTURE_NONE | BGFX_SAMPLER_UVW_CLAMP,
|
||||||
buf
|
buf
|
||||||
|
),
|
||||||
|
slot->bitmap.width,
|
||||||
|
slot->bitmap.rows,
|
||||||
|
slot->bitmap_left,
|
||||||
|
slot->bitmap_top,
|
||||||
|
slot->advance.x,
|
||||||
|
slot->advance.y
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
else cache.emplace(c, std::make_tuple(
|
||||||
|
std::nullopt,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
slot->advance.x,
|
||||||
|
slot->advance.y));
|
||||||
|
}
|
||||||
|
return cache[c];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -124,12 +143,13 @@ namespace {
|
||||||
void destroy_font(Font& f) {
|
void destroy_font(Font& f) {
|
||||||
FT_Done_Face(f.face);
|
FT_Done_Face(f.face);
|
||||||
for (auto it = f.cache.begin(); it != f.cache.end(); it++) {
|
for (auto it = f.cache.begin(); it != f.cache.end(); it++) {
|
||||||
bgfx::destroy(it->second);
|
if(auto& tx = std::get<0>(it->second))
|
||||||
|
bgfx::destroy(*tx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bgfx::ProgramHandle load_shader_program(const std::string& shader) {
|
inline bgfx::ProgramHandle load_shader_program(const std::string& shader) {
|
||||||
return bgfx::createProgram(loadShader(shader + ".vert.bin"), loadShader(shader + ".frag.bin"), true);
|
return bgfx::createProgram(loadShader(shader + ".vert.bin"), loadShader(shader + ".frag.bin"), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<ImageTexture> get_image_texture(const std::string& file) {
|
std::optional<ImageTexture> get_image_texture(const std::string& file) {
|
||||||
|
@ -180,6 +200,19 @@ namespace {
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void HandleMarkupFlags(const NVL::Environment::MarkupSegment& s, u32& style_flags, const NVL::String*& ruby) {
|
||||||
|
for (const auto& e : s.efs) {
|
||||||
|
if (e.first == u"b") { style_flags |= TEXT_BOLD; }
|
||||||
|
else if (e.first == u"i") { style_flags |= TEXT_ITALIC; }
|
||||||
|
else if (e.first == u"u") { style_flags |= TEXT_UNDERLINE; }
|
||||||
|
else if (e.first == u"s") { style_flags |= TEXT_STRIKETHROUGH; }
|
||||||
|
else if (e.first == u"o") { style_flags |= TEXT_OVERLINE; }
|
||||||
|
else if (e.first == u"rb") { ruby = &e.second[0]; }
|
||||||
|
else {
|
||||||
|
std::cerr << "ADV: Unrecognized text markup: " << NVL::to_std_string(e.first) << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace ADVect::Graphics {
|
namespace ADVect::Graphics {
|
||||||
|
@ -200,7 +233,7 @@ namespace ADVect::Graphics {
|
||||||
ibh = bgfx::createIndexBuffer(bgfx::makeRef(quad_indices, sizeof(quad_indices)));
|
ibh = bgfx::createIndexBuffer(bgfx::makeRef(quad_indices, sizeof(quad_indices)));
|
||||||
vbh = bgfx::createVertexBuffer(bgfx::makeRef(quad_vert, sizeof(quad_vert)), pcvDecl);
|
vbh = bgfx::createVertexBuffer(bgfx::makeRef(quad_vert, sizeof(quad_vert)), pcvDecl);
|
||||||
|
|
||||||
img_program = load_shader_program("test"); // RGBA
|
// img_program = load_shader_program("test"); // RGBA
|
||||||
imga_program = load_shader_program("ImageAlpha"); // RGBA + Opacity
|
imga_program = load_shader_program("ImageAlpha"); // RGBA + Opacity
|
||||||
a_program = load_shader_program("AlphaStencil"); // A -> FFFA
|
a_program = load_shader_program("AlphaStencil"); // A -> FFFA
|
||||||
|
|
||||||
|
@ -220,7 +253,7 @@ namespace ADVect::Graphics {
|
||||||
}
|
}
|
||||||
|
|
||||||
bgfx::destroy(a_program);
|
bgfx::destroy(a_program);
|
||||||
bgfx::destroy(img_program);
|
//bgfx::destroy(img_program);
|
||||||
bgfx::destroy(imga_program);
|
bgfx::destroy(imga_program);
|
||||||
|
|
||||||
bgfx::destroy(ibh);
|
bgfx::destroy(ibh);
|
||||||
|
@ -279,113 +312,119 @@ namespace ADVect::Graphics {
|
||||||
DrawTexture(tex, pos_x, pos_y, w, h, (BGFX_STATE_DEFAULT | BGFX_STATE_BLEND_ALPHA) & ~(BGFX_STATE_WRITE_Z | BGFX_STATE_DEPTH_TEST_LESS), a_program);
|
DrawTexture(tex, pos_x, pos_y, w, h, (BGFX_STATE_DEFAULT | BGFX_STATE_BLEND_ALPHA) & ~(BGFX_STATE_WRITE_Z | BGFX_STATE_DEPTH_TEST_LESS), a_program);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderStringWalk(const NVL::String& s, i32& pos_x, i32& pos_y, u32 col, u32 style_flags = TEXT_NONE) {
|
template <bool DoRender, bool Walk>
|
||||||
|
void RenderGlyph(NVL::Char c, std::conditional_t<Walk, i32&, i32> pos_x, std::conditional_t<Walk, i32&, i32> pos_y, u32 col, u32 style_flags) {
|
||||||
Font* f = ResolveStyleFlags(style_flags);
|
Font* f = ResolveStyleFlags(style_flags);
|
||||||
|
|
||||||
FT_GlyphSlot& slot = f->face->glyph;
|
auto& [tx, w, h, l, t, x, y] = f->get_char(c);
|
||||||
|
|
||||||
|
pos_x += l;
|
||||||
|
|
||||||
|
if (auto& buf = tx; DoRender && tx && w != 0) {
|
||||||
|
DrawTextureStencilAlpha(*buf, pos_x, pos_y - (h - t), w, h);
|
||||||
|
}
|
||||||
|
|
||||||
|
pos_x += x >> 6;
|
||||||
|
pos_y += y >> 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <bool DoRender, bool Walk>
|
||||||
|
void RenderString(const NVL::String& s, std::conditional_t<Walk, i32&, i32> pos_x, std::conditional_t<Walk, i32&, i32> pos_y, u32 col, u32 style_flags) {
|
||||||
for (const auto& c : s) {
|
for (const auto& c : s) {
|
||||||
f->cache_char(c);
|
RenderGlyph<DoRender>(c, pos_x, pos_y, col, style_flags);
|
||||||
|
|
||||||
pos_x += slot->bitmap_left;
|
|
||||||
f32 ypos = pos_y - (slot->bitmap.rows - slot->bitmap_top);
|
|
||||||
|
|
||||||
if (slot->bitmap.width != 0) {
|
|
||||||
DrawTextureStencilAlpha((f->cache)[c], pos_x, ypos, slot->bitmap.width, slot->bitmap.rows);
|
|
||||||
}
|
|
||||||
|
|
||||||
pos_x += slot->advance.x >> 6;
|
|
||||||
pos_y += slot->advance.y >> 6;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void StringWalk(const NVL::String& s, i32& pos_x, u32 style_flags = TEXT_NONE) {
|
template <bool DoRender, bool Walk>
|
||||||
|
void RenderString(NVL::String::const_iterator cbegin, NVL::String::const_iterator cend, std::conditional_t<Walk, i32&, i32> pos_x, std::conditional_t<Walk, i32&, i32> pos_y, u32 col, u32 style_flags) {
|
||||||
|
while (cbegin < cend) {
|
||||||
|
RenderGlyph<DoRender>(*cbegin++, pos_x, pos_y, col, style_flags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderStringCentered(const NVL::String& s, i32 pos_x, i32 pos_y, u32 col, u32 style_flags = TEXT_NONE) {
|
||||||
|
i32 copy_x = 0, copy_y = 0;
|
||||||
|
RenderString<false, true>(s, copy_x, copy_y, col, style_flags);
|
||||||
|
RenderString<true, false>(s, pos_x - copy_x / 2, pos_y, col, style_flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
// I cannot reason this function, returns where the string would end if it was not halted
|
||||||
|
i32 RenderSubstringBox(const NVL::String& s, i32& pos_x, i32& pos_y, i32 reset_x, u32 w, u32 col, u32 style_flags, size_t s_end) {
|
||||||
Font* f = ResolveStyleFlags(style_flags);
|
Font* f = ResolveStyleFlags(style_flags);
|
||||||
|
|
||||||
FT_GlyphSlot& slot = f->face->glyph;
|
NVL::String::const_iterator last = s.cbegin(), end = s.cend(), pos = std::find(last, end, u' '),
|
||||||
for (const auto& c : s) {
|
halt = s_end > s.length() ? end : last + s_end;
|
||||||
f->cache_char(c);
|
if (pos == end) { // Render the entire thing with hard break if we don't split at all
|
||||||
pos_x += slot->bitmap_left;
|
NVL::String::const_iterator last_copy = last;
|
||||||
pos_x += slot->advance.x >> 6;
|
i32 copy_x = pos_x, copy_y = pos_y;
|
||||||
}
|
while (last != std::min(pos, halt)) {
|
||||||
}
|
RenderGlyph(*last++, pos_x, pos_y, col, style_flags);
|
||||||
|
if (pos_x - reset_x > w) {
|
||||||
void RenderString(const NVL::String& s, i32 pos_x, i32 pos_y, u32 col, u32 style_flags = TEXT_NONE) {
|
pos_x = reset_x;
|
||||||
RenderStringWalk(s, pos_x, pos_y, col, style_flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RenderStringWrapWalk(const NVL::String& s, i32& pos_x, i32& pos_y, u32 w, u32 col, u32 style_flags = TEXT_NONE) {
|
|
||||||
Font* f = ResolveStyleFlags(style_flags);
|
|
||||||
|
|
||||||
i32 init_x = pos_x;
|
|
||||||
size_t last = 0, pos = s.find(u' ');
|
|
||||||
if (pos == NVL::String::npos)
|
|
||||||
RenderStringWalk(s, pos_x, pos_y, col, style_flags);
|
|
||||||
else {
|
|
||||||
while (last != NVL::String::npos) {
|
|
||||||
NVL::String sub = s.substr(last, pos - last);
|
|
||||||
i32 copy_x = pos_x;
|
|
||||||
StringWalk(sub, copy_x, style_flags);
|
|
||||||
if (copy_x - init_x > w) {
|
|
||||||
pos_x = init_x;
|
|
||||||
pos_y -= f->face->size->metrics.height / 64;
|
pos_y -= f->face->size->metrics.height / 64;
|
||||||
sub.erase(sub.begin());
|
|
||||||
}
|
}
|
||||||
RenderStringWalk(sub, pos_x, pos_y, col, style_flags);
|
if (last >= halt) {
|
||||||
|
RenderString<false>(last_copy, pos, copy_x, copy_y, col, style_flags);
|
||||||
|
return copy_x;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else while (last != end) { // Loop through all segments
|
||||||
|
i32 copy_x = pos_x, old_x = pos_x, copy_y = pos_y;
|
||||||
|
RenderString<false>(last, pos, copy_x, copy_y, col, style_flags);
|
||||||
|
if (copy_x - reset_x > w) { // if walk exceeded max w
|
||||||
|
copy_x = reset_x, copy_y = pos_y; // try walk again from leftmost of box, see if a soft break works; reset y from last walk
|
||||||
|
RenderString<false>(last, pos, copy_x, copy_y, col, style_flags);
|
||||||
|
if (copy_x - reset_x > w) { // soft break won't work, go back to old x and hard break
|
||||||
|
pos_x = old_x;
|
||||||
|
while (last != pos) {
|
||||||
|
RenderGlyph(*last++, pos_x, pos_y, col, style_flags);
|
||||||
|
if (pos_x - reset_x > w) {
|
||||||
|
pos_x = reset_x;
|
||||||
|
pos_y -= f->face->size->metrics.height / 64;
|
||||||
|
}
|
||||||
|
if (last >= halt) return copy_x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else { // soft break and kill beginning space
|
||||||
|
pos_x = reset_x;
|
||||||
|
pos_y -= f->face->size->metrics.height / 64;
|
||||||
|
last++;
|
||||||
|
RenderString(last, std::min(pos, halt), pos_x, pos_y, col, style_flags);
|
||||||
|
if (last >= halt) return copy_x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
RenderString(last, std::min(pos, halt), pos_x, pos_y, col, style_flags);
|
||||||
|
if (last >= halt) return copy_x;
|
||||||
|
}
|
||||||
|
|
||||||
last = pos;
|
last = pos;
|
||||||
pos = s.find(u' ', pos + 1);
|
if (pos != end)
|
||||||
}
|
pos = std::find(std::next(pos), end, u' ');
|
||||||
}
|
}
|
||||||
|
return pos_x;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderStringMarkup(const NVL::Environment::MarkupString& ms, i32 pos_x, i32 pos_y, u32 col) {
|
void RenderSubstringMarkupBox(const NVL::Environment::MarkupString& ms, i32 pos_x, i32 pos_y, u32 w, u32 col, size_t end) {
|
||||||
|
i32 init_x = pos_x;
|
||||||
|
size_t acc_length = 0;
|
||||||
// We assume markups are already sorted
|
// We assume markups are already sorted
|
||||||
for (const NVL::Environment::MarkupSegment& s : ms.segments) {
|
for (const NVL::Environment::MarkupSegment& s : ms.segments) {
|
||||||
u32 style_flags = TEXT_NONE;
|
u32 style_flags = TEXT_NONE;
|
||||||
const NVL::String* ruby = nullptr;
|
const NVL::String* ruby = nullptr;
|
||||||
|
HandleMarkupFlags(s, style_flags, ruby);
|
||||||
|
|
||||||
for (const auto& e : s.efs) {
|
i32 last_x = pos_x,
|
||||||
if (e.first == u"b") { style_flags |= TEXT_BOLD; }
|
|
||||||
else if (e.first == u"i") { style_flags |= TEXT_ITALIC; }
|
segment_end = RenderSubstringBox(s.str, pos_x, pos_y, init_x, w, col, style_flags, end - acc_length);
|
||||||
else if (e.first == u"u") { style_flags |= TEXT_UNDERLINE; }
|
|
||||||
else if (e.first == u"s") { style_flags |= TEXT_STRIKETHROUGH; }
|
if (ruby != nullptr && segment_end != last_x) {
|
||||||
else if (e.first == u"o") { style_flags |= TEXT_OVERLINE; }
|
RenderStringCentered(*ruby, segment_end / 2 + last_x / 2, i32(pos_y + 20), col);
|
||||||
else if (e.first == u"rb") { ruby = &e.second[0]; }
|
|
||||||
else {
|
|
||||||
std::cerr << "ADV: Unrecognized text markup: " << NVL::to_std_string(e.first) << std::endl;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ruby != nullptr) {
|
acc_length += s.str.length();
|
||||||
RenderString(*ruby, pos_x, pos_y + 20, col);
|
if (acc_length > end) return;
|
||||||
}
|
|
||||||
|
|
||||||
RenderStringWalk(s.str, pos_x, pos_y, col, style_flags);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RenderStringMarkupWrap(const NVL::Environment::MarkupString& ms, i32 pos_x, i32 pos_y, u32 w, u32 col) {
|
|
||||||
// We assume markups are already sorted
|
|
||||||
for (const NVL::Environment::MarkupSegment& s : ms.segments) {
|
|
||||||
u32 style_flags = TEXT_NONE;
|
|
||||||
const NVL::String* ruby = nullptr;
|
|
||||||
|
|
||||||
for (const auto& e : s.efs) {
|
|
||||||
if (e.first == u"b") { style_flags |= TEXT_BOLD; }
|
|
||||||
else if (e.first == u"i") { style_flags |= TEXT_ITALIC; }
|
|
||||||
else if (e.first == u"u") { style_flags |= TEXT_UNDERLINE; }
|
|
||||||
else if (e.first == u"s") { style_flags |= TEXT_STRIKETHROUGH; }
|
|
||||||
else if (e.first == u"o") { style_flags |= TEXT_OVERLINE; }
|
|
||||||
else if (e.first == u"rb") { ruby = &e.second[0]; }
|
|
||||||
else {
|
|
||||||
std::cerr << "ADV: Unrecognized text markup: " << NVL::to_std_string(e.first) << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ruby != nullptr) {
|
|
||||||
RenderString(*ruby, pos_x, pos_y + 20, col);
|
|
||||||
}
|
|
||||||
|
|
||||||
RenderStringWrapWalk(s.str, pos_x, pos_y, w, col, style_flags);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL.h>
|
||||||
|
|
||||||
#include <bgfx/bgfx.h>
|
#include <bgfx/bgfx.h>
|
||||||
|
|
||||||
|
@ -33,9 +33,13 @@ namespace ADVect::Graphics {
|
||||||
void DrawTextureImageAlpha(const ImageTexture& img, i32 pos_x, i32 pos_y, f32 alpha);
|
void DrawTextureImageAlpha(const ImageTexture& img, i32 pos_x, i32 pos_y, f32 alpha);
|
||||||
void DrawTextureStencilAlpha(const bgfx::TextureHandle& tex, i32 pos_x, i32 pos_y, u32 w, u32 h);
|
void DrawTextureStencilAlpha(const bgfx::TextureHandle& tex, i32 pos_x, i32 pos_y, u32 w, u32 h);
|
||||||
|
|
||||||
void RenderStringWalk(const NVL::String& s, i32& pos_x, i32& pos_y, u32 col, u32 style_flags);
|
template <bool DoRender = true, bool Walk = true>
|
||||||
void RenderStringWrapWalk(const NVL::String& s, i32& pos_x, i32& pos_y, u32 w, u32 col, u32 style_flags);
|
void RenderGlyph(NVL::Char c, std::conditional_t<Walk, i32&, i32> pos_x, std::conditional_t<Walk, i32&, i32> pos_y, u32 col, u32 style_flags = TEXT_NONE);
|
||||||
void RenderString(const NVL::String& s, i32 pos_x, i32 pos_y, u32 col, u32 style_flags);
|
template <bool DoRender = true, bool Walk = true>
|
||||||
void RenderStringMarkup(const NVL::Environment::MarkupString& s, i32 pos_x, i32 pos_y, u32 col);
|
void RenderString(const NVL::String& s, std::conditional_t<Walk, i32&, i32> pos_x, std::conditional_t<Walk, i32&, i32> pos_y, u32 col, u32 style_flags = TEXT_NONE);
|
||||||
void RenderStringMarkupWrap(const NVL::Environment::MarkupString& ms, i32 pos_x, i32 pos_y, u32 w, u32 col);
|
template <bool DoRender = true, bool Walk = true>
|
||||||
|
void RenderString(NVL::String::const_iterator cbegin, NVL::String::const_iterator cend, std::conditional_t<Walk, i32&, i32> pos_x, std::conditional_t<Walk, i32&, i32> pos_y, u32 col, u32 style_flags = TEXT_NONE);
|
||||||
|
|
||||||
|
i32 RenderSubstringBox(const NVL::String& s, i32& pos_x, i32& pos_y, i32 reset_x, u32 w, u32 col, u32 style_flags = TEXT_NONE, size_t s_end = NVL::String::npos);
|
||||||
|
void RenderSubstringMarkupBox(const NVL::Environment::MarkupString& ms, i32 pos_x, i32 pos_y, u32 w, u32 col, size_t end = NVL::String::npos);
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,25 +32,31 @@ namespace ADVect {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO maybe make this cleaner (packing?)
|
|
||||||
template <typename T, bool UsePointer, bool IsNamed, bool IsVisual, bool IsVisualFill, bool HasTransition>
|
template <typename T, bool UsePointer, bool IsNamed, bool IsVisual, bool IsVisualFill, bool HasTransition>
|
||||||
struct Track {
|
struct Track {
|
||||||
std::conditional_t<UsePointer, T*, T> current{};
|
std::conditional_t<UsePointer, T*, T> current{};
|
||||||
[[no_unique_address]] std::conditional_t<IsNamed, std::string, std::monostate> name{};
|
// [[no_unique_address]] std::conditional_t<IsNamed, std::string, std::monostate> name{};
|
||||||
|
std::conditional_t<IsNamed, std::string, std::monostate> name{};
|
||||||
|
|
||||||
// Visual
|
// Visual
|
||||||
[[no_unique_address]] std::conditional_t<IsVisual, i32, std::monostate> pos_x{}, pos_y{};
|
// [[no_unique_address]] std::conditional_t<IsVisual, i32, std::monostate> pos_x{}, pos_y{};
|
||||||
[[no_unique_address]] std::conditional_t<IsVisual, u32, std::monostate> w{}, h{};
|
// [[no_unique_address]] std::conditional_t<IsVisual, u32, std::monostate> w{}, h{};
|
||||||
[[no_unique_address]] std::conditional_t<IsVisual, f32, std::monostate> opacity{};
|
// [[no_unique_address]] std::conditional_t<IsVisual, f32, std::monostate> opacity{};
|
||||||
|
std::conditional_t<IsVisual, i32, std::monostate> pos_x{}, pos_y{};
|
||||||
|
std::conditional_t<IsVisual, u32, std::monostate> w{}, h{};
|
||||||
|
std::conditional_t<IsVisual, f32, std::monostate> opacity{};
|
||||||
// TODO other transforms
|
// TODO other transforms
|
||||||
|
|
||||||
// Fill
|
// Fill
|
||||||
static_assert(IsVisual || !IsVisualFill, "Track cannot have fill unless visual");
|
static_assert(IsVisual || !IsVisualFill, "Track cannot have fill unless visual");
|
||||||
[[no_unique_address]] std::conditional_t<IsVisualFill, u32, std::monostate> fill{};
|
// [[no_unique_address]] std::conditional_t<IsVisualFill, u32, std::monostate> fill{};
|
||||||
|
std::conditional_t<IsVisualFill, u32, std::monostate> fill{};
|
||||||
|
|
||||||
// Transition, with assumption that we need to access the original when transition is underway
|
// Transition, with assumption that we need to access the original when transition is underway
|
||||||
[[no_unique_address]] std::conditional_t<HasTransition, std::conditional_t<UsePointer, T*, T>, std::monostate> next{};
|
// [[no_unique_address]] std::conditional_t<HasTransition, std::conditional_t<UsePointer, T*, T>, std::monostate> next{};
|
||||||
[[no_unique_address]] std::conditional_t<HasTransition, Varying<f32>, std::monostate> transition{};
|
// [[no_unique_address]] std::conditional_t<HasTransition, Varying<f32>, std::monostate> transition{};
|
||||||
|
std::conditional_t<HasTransition, std::conditional_t<UsePointer, T*, T>, std::monostate> next{};
|
||||||
|
std::conditional_t<HasTransition, Varying<f32>, std::monostate> transition{};
|
||||||
void check(u64 current_time) requires HasTransition {
|
void check(u64 current_time) requires HasTransition {
|
||||||
if constexpr (UsePointer) {
|
if constexpr (UsePointer) {
|
||||||
if (next != nullptr && transition.check(current_time)) {
|
if (next != nullptr && transition.check(current_time)) {
|
||||||
|
@ -103,9 +109,9 @@ namespace ADVect {
|
||||||
|
|
||||||
void draw_typewriter(u64 current_time, const MarkupTextTransitionTrack& t) {
|
void draw_typewriter(u64 current_time, const MarkupTextTransitionTrack& t) {
|
||||||
if (t.transition.done)
|
if (t.transition.done)
|
||||||
ADVect::Graphics::RenderStringMarkupWrap(t.current, t.pos_x, t.pos_y, t.w, t.fill);
|
ADVect::Graphics::RenderSubstringMarkupBox(t.current, t.pos_x, t.pos_y, t.w, t.fill);
|
||||||
else
|
else
|
||||||
ADVect::Graphics::RenderStringMarkupWrap(t.next.substr(t.transition.get(current_time)), t.pos_x, t.pos_y, t.w, t.fill);
|
ADVect::Graphics::RenderSubstringMarkupBox(t.next, t.pos_x, t.pos_y, t.w, t.fill, t.transition.get(current_time));
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_image_transition_fade(u64 current_time, const ImageTransitionTrack& t) {
|
void draw_image_transition_fade(u64 current_time, const ImageTransitionTrack& t) {
|
||||||
|
@ -126,7 +132,7 @@ namespace ADVect {
|
||||||
ADVect::Graphics::DrawTextureImageAlpha(*t.next, t.pos_x, t.pos_y, t.transition.get(current_time));
|
ADVect::Graphics::DrawTextureImageAlpha(*t.next, t.pos_x, t.pos_y, t.transition.get(current_time));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ADVect::Graphics::DrawTextureImage(*t.current, t.pos_x, t.pos_y);
|
ADVect::Graphics::DrawTextureImageAlpha(*t.current, t.pos_x, t.pos_y, 1.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
2784
ADVect/include_windows/SDL_mixer.h
Normal file
2784
ADVect/include_windows/SDL_mixer.h
Normal file
File diff suppressed because it is too large
Load diff
BIN
ADVect/lib/SDL2_mixer.dll
Normal file
BIN
ADVect/lib/SDL2_mixer.dll
Normal file
Binary file not shown.
BIN
ADVect/lib/SDL2_mixer.lib
Normal file
BIN
ADVect/lib/SDL2_mixer.lib
Normal file
Binary file not shown.
BIN
ADVect/lib/libmodplug-1.dll
Normal file
BIN
ADVect/lib/libmodplug-1.dll
Normal file
Binary file not shown.
BIN
ADVect/lib/libogg-0.dll
Normal file
BIN
ADVect/lib/libogg-0.dll
Normal file
Binary file not shown.
BIN
ADVect/lib/libopus-0.dll
Normal file
BIN
ADVect/lib/libopus-0.dll
Normal file
Binary file not shown.
BIN
ADVect/lib/libopusfile-0.dll
Normal file
BIN
ADVect/lib/libopusfile-0.dll
Normal file
Binary file not shown.
|
@ -1,6 +1,6 @@
|
||||||
BEGIN Inferno
|
BEGIN Inferno
|
||||||
ImageTrack BG
|
|
||||||
Show BG "image.png"
|
Show BG "image.png"
|
||||||
|
Show BGDialogue "grad.png"
|
||||||
<<-
|
<<-
|
||||||
[]
|
[]
|
||||||
由我这里,直通[b]{悲惨之城}。
|
由我这里,直通[b]{悲惨之城}。
|
||||||
|
@ -11,7 +11,6 @@ Show BG "image.png"
|
||||||
我永远不朽;在我之前,万象 未形,只有永恒的事物存在。
|
我永远不朽;在我之前,万象 未形,只有永恒的事物存在。
|
||||||
来者呀,快把一切希望弃扬。
|
来者呀,快把一切希望弃扬。
|
||||||
我所见到的文字,毫无光彩, 用暗色刻在地狱之门的高处。
|
我所见到的文字,毫无光彩, 用暗色刻在地狱之门的高处。
|
||||||
老师呀,讲得真可骇。
|
|
||||||
[维吉尔]
|
[维吉尔]
|
||||||
一切疑虑,必须在这里摆脱。
|
一切疑虑,必须在这里摆脱。
|
||||||
一切怯懦,必须在这里结束。
|
一切怯懦,必须在这里结束。
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
BEGIN Inferno
|
BEGIN Inferno
|
||||||
|
|
||||||
ImageTrack BG
|
// ImageTrack BG
|
||||||
Show BG "image.png"
|
Show BG "image.png"
|
||||||
|
|
||||||
<<-
|
<<-
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
BEGIN Scene1
|
BEGIN Scene1
|
||||||
|
|
||||||
Show BG "image.png"
|
Show BG "image.png"
|
||||||
Show BGDialogue "grad.png"
|
Show BGDialogue "grad.png"
|
||||||
|
@ -23,8 +23,7 @@ After the login screen comes up, type in the password "G00gle."
|
||||||
When the system reboots, you will see a prompt asking you to install a new program.
|
When the system reboots, you will see a prompt asking you to install a new program.
|
||||||
Type "Y" and press ENTER.
|
Type "Y" and press ENTER.
|
||||||
The Google search engine will come up. Type in "www.yahoo.com" and hit ENTER.
|
The Google search engine will come up. Type in "www.yahoo.com" and hit ENTER.
|
||||||
A window will appear saying "You have successfully installed Google Chrome." Click OK.
|
A window will appear saying "You have successfully installed Google Chrome." Click OK. A new browser will open. Log in to your Yahoo mail account.
|
||||||
A new browser will open. Log in to your Yahoo mail account.
|
|
||||||
Go to your inbox and click on the link to download the latest version of Google Chrome.
|
Go to your inbox and click on the link to download the latest version of Google Chrome.
|
||||||
Install the update.
|
Install the update.
|
||||||
|
|
||||||
|
|
BIN
ADVect/runtime/mmoker.nvlb
Normal file
BIN
ADVect/runtime/mmoker.nvlb
Normal file
Binary file not shown.
BIN
ADVect/runtime/shaders/metal/AlphaStencil.frag.bin
Normal file
BIN
ADVect/runtime/shaders/metal/AlphaStencil.frag.bin
Normal file
Binary file not shown.
BIN
ADVect/runtime/shaders/metal/AlphaStencil.vert.bin
Normal file
BIN
ADVect/runtime/shaders/metal/AlphaStencil.vert.bin
Normal file
Binary file not shown.
BIN
ADVect/runtime/shaders/metal/ImageAlpha.frag.bin
Normal file
BIN
ADVect/runtime/shaders/metal/ImageAlpha.frag.bin
Normal file
Binary file not shown.
BIN
ADVect/runtime/shaders/metal/ImageAlpha.vert.bin
Normal file
BIN
ADVect/runtime/shaders/metal/ImageAlpha.vert.bin
Normal file
Binary file not shown.
BIN
ADVect/runtime/times.ttf
Normal file
BIN
ADVect/runtime/times.ttf
Normal file
Binary file not shown.
BIN
ADVect/runtime/unifont-11.0.03.ttf
Normal file
BIN
ADVect/runtime/unifont-11.0.03.ttf
Normal file
Binary file not shown.
|
@ -1,33 +1,36 @@
|
||||||
import subprocess, os
|
import subprocess, os
|
||||||
|
|
||||||
SHADERC = "..\\out\\install\\x64-Debug\\bin\\shaderc"
|
#SHADERC = "..\\out\\install\\x64-Debug\\bin\\shaderc"
|
||||||
OUT = "..\\out\\build\\x64-Debug\\ADVect\\shaders\\"
|
SHADERC = "/Users/lachrymal/Projects/NouVeL/build/ADVect/ext/bgfx/Debug/shaderc"
|
||||||
|
#OUT = "..\\out\\build\\x64-Debug\\ADVect\\shaders\\"
|
||||||
# OUT = "..\\build\\ADVect\\shaders\\"
|
# OUT = "..\\build\\ADVect\\shaders\\"
|
||||||
|
OUT = "/Users/lachrymal/Projects/NouVeL/ADVect/runtime/shaders/"
|
||||||
|
|
||||||
P = lambda location, frag, vert: { 'location': location, 'frag': frag, 'vert': vert }
|
P = lambda location, platform, frag, vert: { 'location': location, 'platform': platform, 'frag': frag, 'vert': vert }
|
||||||
plats = [
|
plats = [
|
||||||
P('glsl', '140', '140'),
|
# P('glsl', 'windows', '140', '140'),
|
||||||
P('dx11', 'ps_5_0', 'vs_5_0'),
|
# P('dx11', 'windows', 'ps_5_0', 'vs_5_0'),
|
||||||
P('spirv', 'spirv', 'spirv')
|
# P('spirv', 'windows', 'spirv', 'spirv'),
|
||||||
|
P('metal', 'osx', 'metal', 'metal')
|
||||||
]
|
]
|
||||||
|
|
||||||
for root, dirs, _ in os.walk('shaders'):
|
for root, dirs, _ in os.walk('shaders'):
|
||||||
for name in dirs:
|
for name in dirs:
|
||||||
for config in plats:
|
for config in plats:
|
||||||
subprocess.run([SHADERC, "-f", os.path.join(root, name, name + '.frag'),
|
subprocess.run([SHADERC, "-f", os.path.join(root, name, name + '.frag'),
|
||||||
"--type", "fragment"
|
"--type", "fragment",
|
||||||
"--platform", "windows",
|
"--platform", config['platform'],
|
||||||
"--profile", config['frag'],
|
"--profile", config['frag'],
|
||||||
"--varyingdef", os.path.join(root, name, "varying.def.sc"),
|
"--varyingdef", os.path.join(root, name, "varying.def.sc"),
|
||||||
"-i", "ext\\bgfx\\bgfx\\examples\\common",
|
"-i", "/Users/lachrymal/Projects/NouVeL/ADVect/ext/bgfx/bgfx/examples/common",
|
||||||
"-i", "ext\\bgfx\\bgfx\\src",
|
"-i", "/Users/lachrymal/Projects/NouVeL/ADVect/ext/bgfx/bgfx/src",
|
||||||
"-o", OUT + config['location'] + "\\" + name + ".frag.bin"])
|
"-o", OUT + config['location'] + "\\" + name + ".frag.bin"])
|
||||||
subprocess.run([SHADERC, "-f", os.path.join(root, name, name + '.vert'),
|
subprocess.run([SHADERC, "-f", os.path.join(root, name, name + '.vert'),
|
||||||
"--type", "vertex"
|
"--type", "vertex",
|
||||||
"--platform", "windows",
|
"--platform", config['platform'],
|
||||||
"--profile", config['vert'],
|
"--profile", config['vert'],
|
||||||
"--varyingdef", os.path.join(root, name, "varying.def.sc"),
|
"--varyingdef", os.path.join(root, name, "varying.def.sc"),
|
||||||
"-i", "ext\\bgfx\\bgfx\\examples\\common",
|
"-i", "/Users/lachrymal/Projects/NouVeL/ADVect/ext/bgfx/bgfx/examples/common",
|
||||||
"-i", "ext\\bgfx\\bgfx\\src",
|
"-i", "/Users/lachrymal/Projects/NouVeL/ADVect/ext/bgfx/bgfx/src",
|
||||||
"-o", OUT + config['location'] + "\\" + name + ".vert.bin"])
|
"-o", OUT + config['location'] + "\\" + name + ".vert.bin"])
|
||||||
|
|
|
@ -17,7 +17,9 @@
|
||||||
},
|
},
|
||||||
"vendor": {
|
"vendor": {
|
||||||
"microsoft.com/VisualStudioSettings/CMake/1.0": {
|
"microsoft.com/VisualStudioSettings/CMake/1.0": {
|
||||||
"hostOS": [ "Windows" ]
|
"hostOS": [
|
||||||
|
"Windows"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -33,12 +35,23 @@
|
||||||
},
|
},
|
||||||
"vendor": {
|
"vendor": {
|
||||||
"microsoft.com/VisualStudioSettings/CMake/1.0": {
|
"microsoft.com/VisualStudioSettings/CMake/1.0": {
|
||||||
"hostOS": [ "Linux" ]
|
"hostOS": [
|
||||||
|
"Linux"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"microsoft.com/VisualStudioRemoteSettings/CMake/1.0": {
|
"microsoft.com/VisualStudioRemoteSettings/CMake/1.0": {
|
||||||
"sourceDir": "$env{HOME}/.vs/$ms{projectDirName}"
|
"sourceDir": "$env{HOME}/.vs/$ms{projectDirName}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "x64-release",
|
||||||
|
"displayName": "x64 Release",
|
||||||
|
"inherits": "windows-default",
|
||||||
|
"cacheVariables": {
|
||||||
|
"CMAKE_BUILD_TYPE": "Release",
|
||||||
|
"CMAKE_MSVC_RUNTIME_LIBRARY": "MultiThreaded"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
|
@ -5,7 +5,7 @@ cmake_minimum_required (VERSION 3.8)
|
||||||
|
|
||||||
project (NVL)
|
project (NVL)
|
||||||
include_directories("include")
|
include_directories("include")
|
||||||
add_library (NVL STATIC "Parser.cpp" "Environment.cpp" "Environment.h" "Common.h")
|
add_library (NVL STATIC "Parser.cpp" "Environment.cpp" "Environment.h" "Common.h" "Compiler.cpp" "Compiler.h" "Director.h" "Director.cpp")
|
||||||
# add_executable (NVL "NouVeL.cpp" "Parser.cpp" "Environment.cpp" "Environment.h" "Common.h" )
|
# add_executable (NVL "NouVeL.cpp" "Parser.cpp" "Environment.cpp" "Environment.h" "Common.h" )
|
||||||
|
|
||||||
# TODO: Add tests and install targets if needed.
|
# TODO: Add tests and install targets if needed.
|
||||||
|
|
|
@ -15,6 +15,7 @@ typedef int64_t i64;
|
||||||
typedef uint64_t u64;
|
typedef uint64_t u64;
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <locale>
|
#include <locale>
|
||||||
#include <codecvt>
|
#include <codecvt>
|
||||||
|
@ -24,6 +25,8 @@ namespace NVL {
|
||||||
using Number = f32;
|
using Number = f32;
|
||||||
using Char = char16_t;
|
using Char = char16_t;
|
||||||
using String = std::u16string;
|
using String = std::u16string;
|
||||||
|
template <typename T>
|
||||||
|
using Vector = std::vector<T>;
|
||||||
|
|
||||||
static std::wstring_convert<std::codecvt_utf8_utf16<Char>, Char> str_converter;
|
static std::wstring_convert<std::codecvt_utf8_utf16<Char>, Char> str_converter;
|
||||||
|
|
||||||
|
|
177
NVL/Compiler.cpp
Normal file
177
NVL/Compiler.cpp
Normal file
|
@ -0,0 +1,177 @@
|
||||||
|
#include "Compiler.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
template <typename T>
|
||||||
|
void SerializeDirect(std::ostringstream& s, const T& v) {
|
||||||
|
s.write(reinterpret_cast<const char*>(&v), sizeof v);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SerializeString(std::ostringstream& s, const NVL::String& st) {
|
||||||
|
u16 v = st.size() * sizeof NVL::Char;
|
||||||
|
s.write(reinterpret_cast<const char*>(&v), sizeof v);
|
||||||
|
s.write(reinterpret_cast<const char*>(st.c_str()), v);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SerializeVariable(std::ostringstream& s, const NVL::Environment::Variable& v) {
|
||||||
|
using NVL::Environment::Type;
|
||||||
|
SerializeDirect(s, v.type);
|
||||||
|
switch (v.type) {
|
||||||
|
case Type::Array:
|
||||||
|
{
|
||||||
|
const auto& e = std::get<NVL::Vector<NVL::Environment::Variable>>(v.value);
|
||||||
|
SerializeDirect(s, static_cast<u16>(e.size()));
|
||||||
|
for (const auto& x : e) {
|
||||||
|
SerializeVariable(s, x);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case Type::Nil:
|
||||||
|
return;
|
||||||
|
case Type::Number:
|
||||||
|
case Type::StaticReference:
|
||||||
|
SerializeDirect(s, std::get<NVL::Number>(v.value));
|
||||||
|
return;
|
||||||
|
case Type::String:
|
||||||
|
SerializeString(s, std::get<NVL::String>(v.value));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void DeserializeDirect(std::istringstream& s, T& v) {
|
||||||
|
s.read(reinterpret_cast<char*>(&v), sizeof v);
|
||||||
|
}
|
||||||
|
|
||||||
|
NVL::String DeserializeString(std::istringstream& s) {
|
||||||
|
u16 size{};
|
||||||
|
DeserializeDirect(s, size);
|
||||||
|
u8* str = new u8[size + sizeof NVL::Char];
|
||||||
|
s.read(reinterpret_cast<char*>(str), size);
|
||||||
|
reinterpret_cast<NVL::Char*>(str)[size / sizeof NVL::Char] = u'\0';
|
||||||
|
NVL::String st = NVL::String(reinterpret_cast<NVL::Char*>(str));
|
||||||
|
delete[] str;
|
||||||
|
return st;
|
||||||
|
}
|
||||||
|
|
||||||
|
NVL::Environment::Variable DeserializeVariable(std::istringstream& s) {
|
||||||
|
using NVL::Environment::Type;
|
||||||
|
NVL::Environment::Type t{};
|
||||||
|
DeserializeDirect(s, t);
|
||||||
|
switch (t) {
|
||||||
|
case Type::Array:
|
||||||
|
{
|
||||||
|
u16 size{};
|
||||||
|
NVL::Vector<NVL::Environment::Variable> vs{};
|
||||||
|
DeserializeDirect(s, size);
|
||||||
|
for (u16 i = 0; i < size; i++) {
|
||||||
|
vs.push_back(DeserializeVariable(s));
|
||||||
|
}
|
||||||
|
return vs;
|
||||||
|
}
|
||||||
|
case Type::Nil:
|
||||||
|
return {Type::Nil};
|
||||||
|
case Type::Number:
|
||||||
|
case Type::StaticReference:
|
||||||
|
{
|
||||||
|
NVL::Number n{};
|
||||||
|
DeserializeDirect(s, n);
|
||||||
|
return { n, t == Type::StaticReference };
|
||||||
|
}
|
||||||
|
case Type::String:
|
||||||
|
return DeserializeString(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace NVL::Compiler {
|
||||||
|
Environment::Variable StaticEval(Vector<String>& refs, const Parse::Object& obj) {
|
||||||
|
Environment::Variable actual = Environment::Eval(obj);
|
||||||
|
if (actual.type == Environment::Type::Procedure) {
|
||||||
|
u32 proc_index = -1; // lol
|
||||||
|
const String& proc = std::get<String>(obj.value);
|
||||||
|
for (u32 i = 0; i < refs.size(); i++) {
|
||||||
|
if (refs[i] == proc) {
|
||||||
|
proc_index = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (proc_index == -1) {
|
||||||
|
proc_index = refs.size();
|
||||||
|
refs.push_back(proc);
|
||||||
|
}
|
||||||
|
return Environment::Variable(proc_index, true);
|
||||||
|
}
|
||||||
|
return actual;
|
||||||
|
}
|
||||||
|
|
||||||
|
NVLGraph Compile(const Vector<Parse::Scene>& scenes, i32 entry_scene_index) {
|
||||||
|
std::vector<_DirectedGraphNode> nodes{};
|
||||||
|
Vector<String> procedure_names;
|
||||||
|
|
||||||
|
_DirectedGraphNode n{};
|
||||||
|
for (auto& c : scenes[entry_scene_index].get()) {
|
||||||
|
Vector<Environment::Variable> s{};
|
||||||
|
|
||||||
|
for (auto& v : c) {
|
||||||
|
s.push_back(StaticEval(procedure_names, v));
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO route nodes when JUMP
|
||||||
|
|
||||||
|
n.sequence.push_back(s);
|
||||||
|
n.description = scenes[entry_scene_index].name;
|
||||||
|
}
|
||||||
|
nodes.push_back(n);
|
||||||
|
return NVLGraph{ nodes, procedure_names };
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostringstream Serialize(const NVLGraph& g) {
|
||||||
|
std::ostringstream s;
|
||||||
|
|
||||||
|
SerializeDirect(s, static_cast<u16>(g.static_refs.size()));
|
||||||
|
for (const String& r : g.static_refs) {
|
||||||
|
SerializeString(s, r);
|
||||||
|
}
|
||||||
|
SerializeDirect(s, static_cast<u16>(g.nodes.size()));
|
||||||
|
for (const _DirectedGraphNode& n : g.nodes) {
|
||||||
|
SerializeString(s, n.description);
|
||||||
|
SerializeDirect(s, static_cast<u16>(n.sequence.size()));
|
||||||
|
for (const Vector<Environment::Variable>& c : n.sequence) {
|
||||||
|
SerializeDirect(s, static_cast<u16>(c.size()));
|
||||||
|
for (const Environment::Variable& v : c) {
|
||||||
|
SerializeVariable(s, v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
NVLGraph Deserialize(std::istringstream& buf) {
|
||||||
|
NVLGraph g{};
|
||||||
|
|
||||||
|
u16 size{};
|
||||||
|
DeserializeDirect(buf, size);
|
||||||
|
for (u16 i = 0; i < size; i++) {
|
||||||
|
g.static_refs.push_back(DeserializeString(buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
DeserializeDirect(buf, size);
|
||||||
|
for (u16 i = 0; i < size; i++) {
|
||||||
|
_DirectedGraphNode n{};
|
||||||
|
n.description = DeserializeString(buf);
|
||||||
|
u16 size2{};
|
||||||
|
DeserializeDirect(buf, size2);
|
||||||
|
for (u16 j = 0; j < size2; j++) {
|
||||||
|
Vector<Environment::Variable> cmd{};
|
||||||
|
u16 size3{};
|
||||||
|
DeserializeDirect(buf, size3);
|
||||||
|
for (u16 k = 0; k < size3; k++) {
|
||||||
|
cmd.push_back(DeserializeVariable(buf));
|
||||||
|
}
|
||||||
|
n.sequence.push_back(cmd);
|
||||||
|
}
|
||||||
|
g.nodes.push_back(n);
|
||||||
|
}
|
||||||
|
return g;
|
||||||
|
}
|
||||||
|
}
|
26
NVL/Compiler.h
Normal file
26
NVL/Compiler.h
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
#pragma once
|
||||||
|
#include "Common.h"
|
||||||
|
|
||||||
|
#include "Parser.h"
|
||||||
|
#include "Environment.h"
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
namespace NVL::Compiler {
|
||||||
|
struct _DirectedGraphNode {
|
||||||
|
String description;
|
||||||
|
Vector<Vector<Environment::Variable>> sequence;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct NVLGraph {
|
||||||
|
Vector<_DirectedGraphNode> nodes;
|
||||||
|
Vector<String> static_refs;
|
||||||
|
};
|
||||||
|
|
||||||
|
Environment::Variable StaticEval(const Environment::Environment& env, Vector<String>& refs, const Parse::Object& obj);
|
||||||
|
|
||||||
|
NVLGraph Compile(const Vector<Parse::Scene>& scenes, i32 entry_scene_index);
|
||||||
|
|
||||||
|
std::ostringstream Serialize(const NVLGraph& g);
|
||||||
|
NVLGraph Deserialize(std::istringstream& buf);
|
||||||
|
}
|
46
NVL/Director.cpp
Normal file
46
NVL/Director.cpp
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
#include "Director.h"
|
||||||
|
|
||||||
|
namespace NVL::Director {
|
||||||
|
Director::Director(const Compiler::NVLGraph& g) :
|
||||||
|
g(g), current_position(0), active(true), description(g.nodes[0].description), current_node(g.nodes[0]) {
|
||||||
|
for (const String& s : g.static_refs)
|
||||||
|
resolve.push_back(Environment::ENVIRONMENT.get(s));
|
||||||
|
}
|
||||||
|
Environment::Variable Director::CollectVariable(const Environment::Variable& v) {
|
||||||
|
if (v.type == Environment::Type::StaticReference)
|
||||||
|
return this->resolve[static_cast<u16>(std::get<Number>(v.value))];
|
||||||
|
else if (v.type == Environment::Type::Array) {
|
||||||
|
Vector<Environment::Variable> a{};
|
||||||
|
for (const auto& x : std::get<Vector<Environment::Variable>>(v.value))
|
||||||
|
a.push_back(CollectVariable(x));
|
||||||
|
return Environment::Variable(a);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
void Director::Advance() {
|
||||||
|
if (current_position >= current_node.sequence.size()) {
|
||||||
|
this->active = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto& cmd = this->current_node.sequence[current_position];
|
||||||
|
Vector<Environment::Variable> args{};
|
||||||
|
for (u32 i = 1; i < cmd.size(); i++) {
|
||||||
|
args.push_back(CollectVariable(cmd[i]));
|
||||||
|
}
|
||||||
|
std::get<std::function<Environment::Variable(Vector<Environment::Variable>)>>(CollectVariable(cmd[0]).value)(args);
|
||||||
|
this->current_position++;
|
||||||
|
}
|
||||||
|
void Director::GetBacklog() {
|
||||||
|
|
||||||
|
}
|
||||||
|
void Director::Save() {
|
||||||
|
|
||||||
|
}
|
||||||
|
void Director::Load() {
|
||||||
|
|
||||||
|
}
|
||||||
|
void Director::Jump() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
25
NVL/Director.h
Normal file
25
NVL/Director.h
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
#pragma once
|
||||||
|
#include "Common.h"
|
||||||
|
#include "Compiler.h"
|
||||||
|
#include "Environment.h"
|
||||||
|
|
||||||
|
namespace NVL::Director {
|
||||||
|
class Director {
|
||||||
|
private:
|
||||||
|
u64 current_position{};
|
||||||
|
const Compiler::_DirectedGraphNode& current_node{};
|
||||||
|
const Compiler::NVLGraph& g{};
|
||||||
|
Vector<Environment::Variable> resolve{};
|
||||||
|
Environment::Variable CollectVariable(const Environment::Variable& v);
|
||||||
|
public:
|
||||||
|
const String& description;
|
||||||
|
bool active = false;
|
||||||
|
Director() = delete;
|
||||||
|
Director(const Compiler::NVLGraph& g);
|
||||||
|
void Advance();
|
||||||
|
void GetBacklog();
|
||||||
|
void Save();
|
||||||
|
void Load();
|
||||||
|
void Jump();
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,25 +1,26 @@
|
||||||
#include "Environment.h"
|
#include "Environment.h"
|
||||||
#include "Parser.h"
|
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
namespace NVL::Environment {
|
namespace NVL::Environment {
|
||||||
Environment ENVIRONMENT;
|
Environment ENVIRONMENT;
|
||||||
|
|
||||||
Variable::Variable() : type(Type::Nil), length(0) { }
|
Variable::Variable() : type(Type::Nil), length(0) { }
|
||||||
Variable::Variable(Type t) : type(t), length(0) {
|
Variable::Variable(Type t) : type(t), length(0) {
|
||||||
if (t != Type::Nil)
|
if (t != Type::Nil)
|
||||||
throw std::runtime_error("Cannot create non-nil object with type alone");
|
throw std::runtime_error("Cannot create non-nil object with type alone");
|
||||||
}
|
}
|
||||||
Variable::Variable(const Number& v) : type(Type::Number), value(v), length(1) {}
|
Variable::Variable(const Number& v, bool is_ref) : type(is_ref ? Type::StaticReference : Type::Number), value(v), length(1) {}
|
||||||
Variable::Variable(const String& v) : type(Type::String), value(v), length(1) {}
|
Variable::Variable(const String& v) : type(Type::String), value(v), length(1) {}
|
||||||
Variable::Variable(const std::vector<Variable>& v) : type(Type::Array), value(v), length(v.size()) {}
|
Variable::Variable(const Vector<Variable>& v) : type(Type::Array), value(v), length(v.size()) {}
|
||||||
Variable::Variable(const std::function < Variable(std::vector<Variable>)>& v, u32 l) : type(Type::Procedure), value(v), length(l) {}
|
Variable::Variable(const std::function < Variable(Vector<Variable>)>& v, u32 l) : type(Type::Procedure), value(v), length(l) {}
|
||||||
|
|
||||||
bool Variable::operator==(const Variable& other) const {
|
bool Variable::operator==(const Variable& other) const {
|
||||||
if (other.type != type)
|
if (other.type != type)
|
||||||
return false;
|
return false;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case Type::Number:
|
case Type::Number:
|
||||||
|
case Type::StaticReference: // Only used with serialization
|
||||||
return std::get<Number>(other.value) == std::get<Number>(value);
|
return std::get<Number>(other.value) == std::get<Number>(value);
|
||||||
case Type::String:
|
case Type::String:
|
||||||
return std::get<String>(other.value) == std::get<String>(value);
|
return std::get<String>(other.value) == std::get<String>(value);
|
||||||
|
@ -44,7 +45,7 @@ namespace NVL::Environment {
|
||||||
env[name] = p;
|
env[name] = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
Variable& Environment::get(const String& name) {
|
const Variable& Environment::get(const String& name) const {
|
||||||
return env.at(name);
|
return env.at(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,30 +56,34 @@ namespace NVL::Environment {
|
||||||
Variable Eval(const Parse::Object& obj) {
|
Variable Eval(const Parse::Object& obj) {
|
||||||
switch (obj.type) {
|
switch (obj.type) {
|
||||||
case Parse::Type::Symbol:
|
case Parse::Type::Symbol:
|
||||||
return std::get<String>(obj.value);
|
return ENVIRONMENT.get(std::get<String>(obj.value));
|
||||||
case Parse::Type::Number:
|
case Parse::Type::Number:
|
||||||
return Variable(std::get<Number>(obj.value));
|
return Variable(std::get<Number>(obj.value));
|
||||||
case Parse::Type::String:
|
case Parse::Type::String:
|
||||||
return Variable(std::get<String>(obj.value));
|
return Variable(std::get<String>(obj.value));
|
||||||
case Parse::Type::Array:
|
case Parse::Type::Array:
|
||||||
{
|
{
|
||||||
std::vector<Variable> v{};
|
Vector<Variable> v{};
|
||||||
for (const auto& x : std::get<std::vector<Parse::Object>>(obj.value))
|
for (const auto& x : std::get<Vector<Parse::Object>>(obj.value))
|
||||||
v.push_back(Eval(x));
|
v.push_back(Eval(x));
|
||||||
return Variable(v);
|
return Variable(v);
|
||||||
}
|
}
|
||||||
case Parse::Type::Subexpression:
|
case Parse::Type::Subexpression:
|
||||||
{
|
{
|
||||||
return Apply(std::get<std::vector<Parse::Object>>(obj.value));
|
return Apply(std::get<Vector<Parse::Object>>(obj.value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Variable Apply(const Parse::Command& c) {
|
Variable Apply(const Parse::Command& c) {
|
||||||
std::vector<Variable> args{};
|
Vector<Variable> args{};
|
||||||
for (u32 i = 1; i < c.size(); i++)
|
|
||||||
|
Variable f = Eval(c[0]);
|
||||||
|
for (u32 i = 1; i < c.size(); i++) {
|
||||||
args.push_back(Eval(c[i]));
|
args.push_back(Eval(c[i]));
|
||||||
return std::get<std::function<Variable(std::vector<Variable>)>>(ENVIRONMENT.get(std::get<String>(c[0].value)).value)(args);
|
}
|
||||||
|
if (f.length != -1 && f.length != c.size() - 1) throw std::runtime_error("Function arity mismatch");
|
||||||
|
return std::get<std::function<Variable(Vector<Variable>)>>(f.value)(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EvalScene(const Parse::Scene& s) {
|
void EvalScene(const Parse::Scene& s) {
|
||||||
|
@ -87,23 +92,23 @@ namespace NVL::Environment {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check MatchMarkup for more information
|
// Check MatchMarkup for more information
|
||||||
MarkupString UnpackMarkupVariable(const std::vector<Variable>& v) {
|
MarkupString UnpackMarkupVariable(const Vector<Variable>& v) {
|
||||||
MarkupString ms{};
|
MarkupString ms{};
|
||||||
for (const Variable& segment : v) {
|
for (const Variable& segment : v) {
|
||||||
const auto& pair = std::get<std::vector<Variable>>(segment.value);
|
const auto& pair = std::get<Vector<Variable>>(segment.value);
|
||||||
const String s = std::get<String>(pair[0].value);
|
const String s = std::get<String>(pair[0].value);
|
||||||
|
|
||||||
std::vector<std::pair<String, std::vector<String>>> efs;
|
Vector<std::pair<String, Vector<String>>> efs;
|
||||||
for (const Variable& combination : std::get<std::vector<Variable>>(pair[1].value)) {
|
for (const Variable& combination : std::get<Vector<Variable>>(pair[1].value)) {
|
||||||
if (combination.type == Type::String) {
|
if (combination.type == Type::String) {
|
||||||
const String ef = std::get<String>(combination.value);
|
const String ef = std::get<String>(combination.value);
|
||||||
efs.push_back({ ef, {} });
|
efs.push_back({ ef, {} });
|
||||||
}
|
}
|
||||||
else if (combination.type == Type::Array) {
|
else if (combination.type == Type::Array) {
|
||||||
const std::vector<Variable>& ef_t = std::get<std::vector<Variable>>(combination.value);
|
const Vector<Variable>& ef_t = std::get<Vector<Variable>>(combination.value);
|
||||||
const String& ef = std::get<String>(ef_t[0].value);
|
const String& ef = std::get<String>(ef_t[0].value);
|
||||||
const std::vector<Variable>& args = std::get<std::vector<Variable>>(ef_t[1].value);
|
const Vector<Variable>& args = std::get<Vector<Variable>>(ef_t[1].value);
|
||||||
std::vector<String> ss{};
|
Vector<String> ss{};
|
||||||
for (const auto& s : args) { ss.push_back(std::get<String>(s.value)); }
|
for (const auto& s : args) { ss.push_back(std::get<String>(s.value)); }
|
||||||
efs.push_back({ ef, ss });
|
efs.push_back({ ef, ss });
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,20 +6,20 @@
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
|
|
||||||
namespace NVL::Environment {
|
namespace NVL::Environment {
|
||||||
enum class Type { Procedure, Number, String, Array, Nil };
|
enum class Type { Nil, StaticReference, Procedure, Number, String, Array };
|
||||||
|
|
||||||
struct Variable {
|
struct Variable {
|
||||||
Type type;
|
Type type;
|
||||||
std::variant<Number, String, std::vector<Variable>, std::function<Variable(std::vector<Variable>)>> value;
|
std::variant<Number, String, Vector<Variable>, std::function<Variable(Vector<Variable>)>> value;
|
||||||
// Most things will have length 1 (including string); this is mostly for function arity and array length
|
// Most things will have length 1 (including string); this is mostly for function arity and array length
|
||||||
u32 length;
|
u32 length;
|
||||||
bool operator==(const Variable& other) const;
|
bool operator==(const Variable& other) const;
|
||||||
Variable(); // Makes Nil, length 0
|
Variable(); // Makes Nil, length 0
|
||||||
Variable(Type t); // Reserved for Nil
|
Variable(Type t); // Reserved for Nil
|
||||||
Variable(const Number& v);
|
Variable(const Number& v, bool is_ref = false);
|
||||||
Variable(const String& v);
|
Variable(const String& v);
|
||||||
Variable(const std::vector<Variable>& v);
|
Variable(const Vector<Variable>& v);
|
||||||
Variable(const std::function<Variable(std::vector<Variable>)>& v, u32 l);
|
Variable(const std::function<Variable(Vector<Variable>)>& v, u32 l);
|
||||||
};
|
};
|
||||||
|
|
||||||
class Environment {
|
class Environment {
|
||||||
|
@ -29,7 +29,7 @@ namespace NVL::Environment {
|
||||||
void enter(const String& name, Variable p);
|
void enter(const String& name, Variable p);
|
||||||
void enter(std::initializer_list<std::pair<String, Variable>> p);
|
void enter(std::initializer_list<std::pair<String, Variable>> p);
|
||||||
void set(const String& name, Variable p);
|
void set(const String& name, Variable p);
|
||||||
Variable& get(const String& name);
|
const Variable& get(const String& name) const;
|
||||||
bool exists(const String& name);
|
bool exists(const String& name);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -41,15 +41,15 @@ namespace NVL::Environment {
|
||||||
|
|
||||||
struct MarkupSegment {
|
struct MarkupSegment {
|
||||||
String str;
|
String str;
|
||||||
std::vector<std::pair<String, std::vector<String>>> efs;
|
Vector<std::pair<String, Vector<String>>> efs;
|
||||||
};
|
};
|
||||||
struct MarkupString {
|
struct MarkupString {
|
||||||
private:
|
private:
|
||||||
mutable i32 mem_length = -1;
|
mutable i32 mem_length = -1;
|
||||||
public:
|
public:
|
||||||
std::vector<MarkupSegment> segments{};
|
Vector<MarkupSegment> segments{};
|
||||||
size_t length() const;
|
size_t length() const;
|
||||||
MarkupString substr(size_t idx) const;
|
MarkupString substr(size_t idx) const;
|
||||||
};
|
};
|
||||||
MarkupString UnpackMarkupVariable(const std::vector<Variable>& v);
|
MarkupString UnpackMarkupVariable(const Vector<Variable>& v);
|
||||||
}
|
}
|
||||||
|
|
|
@ -125,8 +125,8 @@ namespace {
|
||||||
return to_NVL_string(buffer.str());
|
return to_NVL_string(buffer.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<String> split_string_by_lines(const String& str) {
|
Vector<String> split_string_by_lines(const String& str) {
|
||||||
std::vector<String> lines;
|
Vector<String> lines;
|
||||||
size_t pos = 0;
|
size_t pos = 0;
|
||||||
size_t prev = 0;
|
size_t prev = 0;
|
||||||
while ((pos = str.find(NEWLINE, prev)) != String::npos) {
|
while ((pos = str.find(NEWLINE, prev)) != String::npos) {
|
||||||
|
@ -230,7 +230,7 @@ namespace {
|
||||||
Parse::Object ParseArray(const String& f, size_t& pos, u32 layer) {
|
Parse::Object ParseArray(const String& f, size_t& pos, u32 layer) {
|
||||||
SkipComments(f, pos);
|
SkipComments(f, pos);
|
||||||
|
|
||||||
std::vector<Parse::Object> array{};
|
Vector<Parse::Object> array{};
|
||||||
|
|
||||||
array.push_back(ParseExpression(f, pos));
|
array.push_back(ParseExpression(f, pos));
|
||||||
while (PeekToken(f, pos)[0] != ARRAY_CLOSE) {
|
while (PeekToken(f, pos)[0] != ARRAY_CLOSE) {
|
||||||
|
@ -246,7 +246,7 @@ namespace {
|
||||||
|
|
||||||
String ParseString(const String& f, size_t& pos) {
|
String ParseString(const String& f, size_t& pos) {
|
||||||
SkipComments(f, pos);
|
SkipComments(f, pos);
|
||||||
std::vector<size_t> discards{};
|
Vector<size_t> discards{};
|
||||||
auto start = ++pos; // skip opening quote
|
auto start = ++pos; // skip opening quote
|
||||||
do {
|
do {
|
||||||
if (f[pos] == QUOTE) {
|
if (f[pos] == QUOTE) {
|
||||||
|
@ -352,7 +352,7 @@ namespace {
|
||||||
bool has_markup = false;
|
bool has_markup = false;
|
||||||
|
|
||||||
// Match tags
|
// Match tags
|
||||||
std::vector<Parse::Object> segments;
|
Vector<Parse::Object> segments;
|
||||||
String::const_iterator tags_start(s.cbegin());
|
String::const_iterator tags_start(s.cbegin());
|
||||||
while (srell::regex_search(tags_start, s.cend(), tags_match, typer)) {
|
while (srell::regex_search(tags_start, s.cend(), tags_match, typer)) {
|
||||||
has_markup = true;
|
has_markup = true;
|
||||||
|
@ -361,13 +361,13 @@ namespace {
|
||||||
if (!before.empty())
|
if (!before.empty())
|
||||||
segments.push_back({ Parse::Type::Array, {
|
segments.push_back({ Parse::Type::Array, {
|
||||||
{ Parse::Type::String, before },
|
{ Parse::Type::String, before },
|
||||||
{ Parse::Type::Array, std::vector<Parse::Object>{} }
|
{ Parse::Type::Array, Vector<Parse::Object>{} }
|
||||||
}});
|
}});
|
||||||
|
|
||||||
String inner = tags_match[2].str(); // markupped
|
String inner = tags_match[2].str(); // markupped
|
||||||
|
|
||||||
// Match markup options
|
// Match markup options
|
||||||
std::vector<Parse::Object> effects{};
|
Vector<Parse::Object> effects{};
|
||||||
String::const_iterator effects_start(tags_match[1].first);
|
String::const_iterator effects_start(tags_match[1].first);
|
||||||
while (srell::regex_search(effects_start, tags_match[1].second, effects_match, effect)) {
|
while (srell::regex_search(effects_start, tags_match[1].second, effects_match, effect)) {
|
||||||
if (effects_match[3].matched) { // no params
|
if (effects_match[3].matched) { // no params
|
||||||
|
@ -376,19 +376,19 @@ namespace {
|
||||||
else { // no params
|
else { // no params
|
||||||
|
|
||||||
// Comma split
|
// Comma split
|
||||||
std::vector<Parse::Object> args;
|
Vector<Parse::Object> args;
|
||||||
String::const_iterator params_start(effects_match[2].first);
|
String::const_iterator params_start(effects_match[2].first);
|
||||||
while (srell::regex_search(params_start, effects_match[2].second, params_match, param)) {
|
while (srell::regex_search(params_start, effects_match[2].second, params_match, param)) {
|
||||||
size_t temp = 0;
|
size_t temp = 0;
|
||||||
args.push_back(ParseExpression(params_match[1].str() + SEPARATOR.accept[0], temp)); // PeekToken will freak out if I don't do this
|
args.push_back(ParseExpression(params_match[1].str() + SEPARATOR.accept[0], temp)); // PeekToken will freak out if I don't do this
|
||||||
params_start = params_match.suffix().first;
|
params_start = params_match.suffix().first;
|
||||||
}
|
}
|
||||||
effects.push_back({ Parse::Type::Array, std::vector<Parse::Object>{ { Parse::Type::String, effects_match[1].str() }, { Parse::Type::Array, args } } });
|
effects.push_back({ Parse::Type::Array, Vector<Parse::Object>{ { Parse::Type::String, effects_match[1].str() }, { Parse::Type::Array, args } } });
|
||||||
}
|
}
|
||||||
effects_start = effects_match.suffix().first;
|
effects_start = effects_match.suffix().first;
|
||||||
}
|
}
|
||||||
tags_start = tags_match.suffix().first;
|
tags_start = tags_match.suffix().first;
|
||||||
segments.push_back({ Parse::Type::Array, std::vector<Parse::Object>{ { Parse::Type::String, inner }, { Parse::Type::Array, effects } } });
|
segments.push_back({ Parse::Type::Array, Vector<Parse::Object>{ { Parse::Type::String, inner }, { Parse::Type::Array, effects } } });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (has_markup) {
|
if (has_markup) {
|
||||||
|
@ -396,15 +396,15 @@ namespace {
|
||||||
if (!end.empty())
|
if (!end.empty())
|
||||||
segments.push_back({ Parse::Type::Array, {
|
segments.push_back({ Parse::Type::Array, {
|
||||||
{ Parse::Type::String, end },
|
{ Parse::Type::String, end },
|
||||||
{ Parse::Type::Array, std::vector<Parse::Object>{} }
|
{ Parse::Type::Array, Vector<Parse::Object>{} }
|
||||||
}});
|
}});
|
||||||
|
|
||||||
return { Parse::Type::Array, segments };
|
return { Parse::Type::Array, segments };
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return { Parse::Type::Array, std::vector<Parse::Object>{
|
return { Parse::Type::Array, Vector<Parse::Object>{
|
||||||
{ Parse::Type::Array, {
|
{ Parse::Type::Array, {
|
||||||
{ Parse::Type::String, s} , { Parse::Type::Array, std::vector<Parse::Object>{} }
|
{ Parse::Type::String, s} , { Parse::Type::Array, Vector<Parse::Object>{} }
|
||||||
} } }
|
} } }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -489,7 +489,7 @@ namespace NVL::Parse {
|
||||||
if (t != Type::String && t != Type::Symbol) throw std::runtime_error("Bad type when constructing object!");
|
if (t != Type::String && t != Type::Symbol) throw std::runtime_error("Bad type when constructing object!");
|
||||||
}
|
}
|
||||||
|
|
||||||
Object::Object(Type t, const std::vector<Object>& v) : type(t), value(v) {
|
Object::Object(Type t, const Vector<Object>& v) : type(t), value(v) {
|
||||||
if (t != Type::Array && t != Type::Subexpression) throw std::runtime_error("Bad type when constructing object!");
|
if (t != Type::Array && t != Type::Subexpression) throw std::runtime_error("Bad type when constructing object!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -500,14 +500,14 @@ namespace NVL::Parse {
|
||||||
if (t != Type::String && t != Type::Symbol) throw std::runtime_error("Bad type when constructing object!");
|
if (t != Type::String && t != Type::Symbol) throw std::runtime_error("Bad type when constructing object!");
|
||||||
}
|
}
|
||||||
|
|
||||||
Object::Object(Type t, std::vector<Object>&& v) : type(t), value(std::move(v)) {
|
Object::Object(Type t, Vector<Object>&& v) : type(t), value(std::move(v)) {
|
||||||
if (t != Type::Array && t != Type::Subexpression) throw std::runtime_error("Bad type when constructing object!");
|
if (t != Type::Array && t != Type::Subexpression) throw std::runtime_error("Bad type when constructing object!");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Scene> ParseFile(const std::string& path) {
|
Vector<Scene> ParseFile(const std::string& path) {
|
||||||
String f = read_file_to_string(path);
|
String f = read_file_to_string(path);
|
||||||
|
|
||||||
std::vector<Scene> list {}; // Vector of scenes which each contain a vector of Parses
|
Vector<Scene> list {}; // Vector of scenes which each contain a vector of Parses
|
||||||
for (size_t i = 0; i < f.length(); i++) {
|
for (size_t i = 0; i < f.length(); i++) {
|
||||||
list.push_back(ParseScene(f, i));
|
list.push_back(ParseScene(f, i));
|
||||||
}
|
}
|
||||||
|
|
13
NVL/Parser.h
13
NVL/Parser.h
|
@ -1,5 +1,4 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <vector>
|
|
||||||
#include <variant>
|
#include <variant>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
@ -13,22 +12,22 @@ namespace NVL::Parse {
|
||||||
Object() = delete;
|
Object() = delete;
|
||||||
Object(const Number& v);
|
Object(const Number& v);
|
||||||
Object(Type t, const String& v);
|
Object(Type t, const String& v);
|
||||||
Object(Type t, const std::vector<Object>& v);
|
Object(Type t, const Vector<Object>& v);
|
||||||
Object(Number&& v);
|
Object(Number&& v);
|
||||||
Object(Type t, String&& v);
|
Object(Type t, String&& v);
|
||||||
Object(Type t, std::vector<Object>&& v);
|
Object(Type t, Vector<Object>&& v);
|
||||||
Type type;
|
Type type;
|
||||||
std::variant<
|
std::variant<
|
||||||
Number,
|
Number,
|
||||||
String,
|
String,
|
||||||
std::vector<Object>
|
Vector<Object>
|
||||||
> value;
|
> value;
|
||||||
};
|
};
|
||||||
|
|
||||||
using Command = std::vector<Object>;
|
using Command = Vector<Object>;
|
||||||
|
|
||||||
class Scene {
|
class Scene {
|
||||||
std::vector<Command> commands{};
|
Vector<Command> commands{};
|
||||||
public:
|
public:
|
||||||
String name;
|
String name;
|
||||||
Scene(const String& name) : name(name) {}
|
Scene(const String& name) : name(name) {}
|
||||||
|
@ -43,5 +42,5 @@ namespace NVL::Parse {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<Scene> ParseFile(const std::string& path);
|
Vector<Scene> ParseFile(const std::string& path);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue