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/out
|
||||
.cache
|
||||
vs
|
||||
**/.DS_STORE
|
||||
|
|
|
@ -2,18 +2,22 @@
|
|||
#include "Environment.h"
|
||||
#include "Graphics.h"
|
||||
#include "Track.h"
|
||||
#include "Compiler.h"
|
||||
#include "Director.h"
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL2/SDL_main.h>
|
||||
#include <SDL2/SDL_timer.h>
|
||||
#include <SDL.h>
|
||||
#include <SDL_main.h>
|
||||
#include <SDL_timer.h>
|
||||
#include <bx/math.h>
|
||||
#include <SDL2/SDL_syswm.h>
|
||||
#include <SDL_syswm.h>
|
||||
#include <bgfx/bgfx.h>
|
||||
#include <bgfx/platform.h>
|
||||
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
|
||||
#include <fstream>
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
namespace {
|
||||
|
@ -22,20 +26,18 @@ namespace {
|
|||
u16 window_height = 720;
|
||||
|
||||
u64 init_time, last_time, current_time, delta_t;
|
||||
bool running = false;
|
||||
bool running = false, rolling = true;
|
||||
|
||||
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;
|
||||
std::unique_ptr<NVL::Director::Director> director;
|
||||
|
||||
ADVect::MarkupTextTransitionTrack m_text{
|
||||
.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
|
||||
};
|
||||
ADVect::TextTrack speaker = {
|
||||
|
@ -58,33 +60,12 @@ namespace {
|
|||
.pos_x = 0, .pos_y = 0,
|
||||
.w = 500, .h = 500
|
||||
};
|
||||
/*
|
||||
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;
|
||||
}
|
||||
*/
|
||||
|
||||
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
|
||||
bool Init(std::string name, const NVL::Compiler::NVLGraph& g) {
|
||||
director = std::make_unique<NVL::Director::Director>(g);
|
||||
|
||||
if (SDL_Init(SDL_INIT_VIDEO)) {
|
||||
std::cerr << "ADV: Failed to init SDL: " << SDL_GetError() << std::endl;
|
||||
|
@ -114,6 +95,7 @@ namespace ADVect {
|
|||
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;
|
||||
|
@ -140,6 +122,10 @@ namespace ADVect {
|
|||
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;
|
||||
}
|
||||
|
@ -153,21 +139,15 @@ namespace ADVect {
|
|||
|
||||
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++;
|
||||
else if (director->active) {
|
||||
rolling = true;
|
||||
director->Advance();
|
||||
}
|
||||
if (curr_size == scene_pos) {
|
||||
else
|
||||
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++;
|
||||
}
|
||||
}
|
||||
|
||||
if (running && rolling)
|
||||
Advance();
|
||||
}
|
||||
|
||||
void Update() {
|
||||
|
@ -195,28 +175,23 @@ namespace ADVect {
|
|||
Advance();
|
||||
}
|
||||
|
||||
bg.check(current_time);
|
||||
avatar.check(current_time);
|
||||
m_text.check(current_time);
|
||||
for (const auto& x : track_updaters) {
|
||||
x(current_time);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Render() {
|
||||
bgfx::touch(0);
|
||||
|
||||
/*
|
||||
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);
|
||||
draw_image_transition_crossfade(current_time, bg);
|
||||
|
||||
if (draw_ui) {
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -225,8 +200,7 @@ namespace ADVect {
|
|||
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::dbgTextPrintf(0, 3, 0xf8, " NVL Director State: %s", NVL::to_std_string(director->description).c_str());
|
||||
|
||||
bgfx::frame();
|
||||
}
|
||||
|
@ -271,66 +245,79 @@ namespace ADVect {
|
|||
|
||||
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>>(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();
|
||||
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;
|
||||
}, 2)
|
||||
}, 1)
|
||||
},
|
||||
{
|
||||
u"SwitchSpeaker",
|
||||
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;
|
||||
}, 1)
|
||||
},
|
||||
/* {
|
||||
u"ImageTrack",
|
||||
{
|
||||
u"BG",
|
||||
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;
|
||||
}, 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::string name = NVL::to_std_string(std::get<NVL::String>(NVL::Environment::Variable(args[0]).value));
|
||||
/* 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;
|
||||
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;
|
||||
}
|
||||
//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;
|
||||
//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::Shutdown();
|
||||
|
||||
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)
|
||||
|
||||
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.
|
||||
include_directories ("include" "../NVL/")
|
||||
add_subdirectory("ext/freetype")
|
||||
add_subdirectory("ext/bgfx")
|
||||
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)
|
||||
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 ()
|
||||
find_package(SDL2 REQUIRED)
|
||||
target_link_libraries (Game PRIVATE NVL freetype bgfx bx SDL2::SDL2 SDL2::SDL2main)
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#include "Graphics.h"
|
||||
#include "Environment.h"
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
|
||||
|
@ -7,6 +6,7 @@
|
|||
|
||||
#include <iostream>
|
||||
#include <optional>
|
||||
#include <algorithm>
|
||||
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include <stb_image.h>
|
||||
|
@ -73,9 +73,10 @@ namespace {
|
|||
|
||||
struct Font {
|
||||
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;
|
||||
|
||||
error = FT_Load_Char(face, c, FT_LOAD_RENDER);
|
||||
|
@ -83,10 +84,11 @@ namespace {
|
|||
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);
|
||||
|
||||
cache.emplace(c, bgfx::createTexture2D(
|
||||
cache.emplace(c, std::make_tuple(
|
||||
bgfx::createTexture2D(
|
||||
slot->bitmap.width,
|
||||
slot->bitmap.rows,
|
||||
false,
|
||||
|
@ -94,8 +96,25 @@ namespace {
|
|||
bgfx::TextureFormat::A8,
|
||||
BGFX_TEXTURE_NONE | BGFX_SAMPLER_UVW_CLAMP,
|
||||
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) {
|
||||
FT_Done_Face(f.face);
|
||||
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) {
|
||||
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) {
|
||||
|
@ -180,6 +200,19 @@ namespace {
|
|||
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 {
|
||||
|
@ -200,7 +233,7 @@ namespace ADVect::Graphics {
|
|||
ibh = bgfx::createIndexBuffer(bgfx::makeRef(quad_indices, sizeof(quad_indices)));
|
||||
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
|
||||
a_program = load_shader_program("AlphaStencil"); // A -> FFFA
|
||||
|
||||
|
@ -220,7 +253,7 @@ namespace ADVect::Graphics {
|
|||
}
|
||||
|
||||
bgfx::destroy(a_program);
|
||||
bgfx::destroy(img_program);
|
||||
//bgfx::destroy(img_program);
|
||||
bgfx::destroy(imga_program);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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) {
|
||||
f->cache_char(c);
|
||||
|
||||
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;
|
||||
RenderGlyph<DoRender>(c, pos_x, pos_y, col, style_flags);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
FT_GlyphSlot& slot = f->face->glyph;
|
||||
for (const auto& c : s) {
|
||||
f->cache_char(c);
|
||||
pos_x += slot->bitmap_left;
|
||||
pos_x += slot->advance.x >> 6;
|
||||
}
|
||||
}
|
||||
|
||||
void RenderString(const NVL::String& s, i32 pos_x, i32 pos_y, u32 col, u32 style_flags = TEXT_NONE) {
|
||||
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;
|
||||
NVL::String::const_iterator last = s.cbegin(), end = s.cend(), pos = std::find(last, end, u' '),
|
||||
halt = s_end > s.length() ? end : last + s_end;
|
||||
if (pos == end) { // Render the entire thing with hard break if we don't split at all
|
||||
NVL::String::const_iterator last_copy = last;
|
||||
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) {
|
||||
pos_x = reset_x;
|
||||
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;
|
||||
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
|
||||
for (const NVL::Environment::MarkupSegment& s : ms.segments) {
|
||||
u32 style_flags = TEXT_NONE;
|
||||
const NVL::String* ruby = nullptr;
|
||||
HandleMarkupFlags(s, style_flags, 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;
|
||||
}
|
||||
i32 last_x = pos_x,
|
||||
|
||||
segment_end = RenderSubstringBox(s.str, pos_x, pos_y, init_x, w, col, style_flags, end - acc_length);
|
||||
|
||||
if (ruby != nullptr && segment_end != last_x) {
|
||||
RenderStringCentered(*ruby, segment_end / 2 + last_x / 2, i32(pos_y + 20), col);
|
||||
}
|
||||
|
||||
if (ruby != nullptr) {
|
||||
RenderString(*ruby, pos_x, pos_y + 20, col);
|
||||
}
|
||||
|
||||
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);
|
||||
acc_length += s.str.length();
|
||||
if (acc_length > end) return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL.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 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);
|
||||
void RenderStringWrapWalk(const NVL::String& s, i32& pos_x, i32& pos_y, u32 w, u32 col, u32 style_flags);
|
||||
void RenderString(const NVL::String& s, i32 pos_x, i32 pos_y, u32 col, u32 style_flags);
|
||||
void RenderStringMarkup(const NVL::Environment::MarkupString& s, i32 pos_x, i32 pos_y, u32 col);
|
||||
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 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);
|
||||
template <bool DoRender = true, bool Walk = true>
|
||||
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);
|
||||
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>
|
||||
struct Track {
|
||||
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
|
||||
[[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, f32, std::monostate> opacity{};
|
||||
// [[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, 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
|
||||
|
||||
// Fill
|
||||
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
|
||||
[[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, std::conditional_t<UsePointer, T*, T>, std::monostate> next{};
|
||||
// [[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 {
|
||||
if constexpr (UsePointer) {
|
||||
if (next != nullptr && transition.check(current_time)) {
|
||||
|
@ -103,9 +109,9 @@ namespace ADVect {
|
|||
|
||||
void draw_typewriter(u64 current_time, const MarkupTextTransitionTrack& t) {
|
||||
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
|
||||
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) {
|
||||
|
@ -126,7 +132,7 @@ namespace ADVect {
|
|||
ADVect::Graphics::DrawTextureImageAlpha(*t.next, t.pos_x, t.pos_y, t.transition.get(current_time));
|
||||
}
|
||||
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,17 +1,16 @@
|
|||
BEGIN Inferno
|
||||
ImageTrack BG
|
||||
BEGIN Inferno
|
||||
Show BG "image.png"
|
||||
Show BGDialogue "grad.png"
|
||||
<<-
|
||||
[]
|
||||
由我这里,直通[b]{悲惨之城}。
|
||||
由我这里,直通[b]{无尽之苦}。
|
||||
由我这里,直通[b]{堕落众生}。
|
||||
圣裁于高天激发造我的君主;
|
||||
造我的大能是[b, rb("C")]{神}的力量,是无上的[b, rb(" L L V M")]{智慧与众爱}所自出。
|
||||
造我的大能是[b, rb("C")]{神}的力量,是无上的[b, rb("L L V M")]{智慧与众爱}所自出。
|
||||
我永远不朽;在我之前,万象 未形,只有永恒的事物存在。
|
||||
来者呀,快把一切希望弃扬。
|
||||
我所见到的文字,毫无光彩, 用暗色刻在地狱之门的高处。
|
||||
老师呀,讲得真可骇。
|
||||
[维吉尔]
|
||||
一切疑虑,必须在这里摆脱。
|
||||
一切怯懦,必须在这里结束。
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
BEGIN Inferno
|
||||
BEGIN Inferno
|
||||
|
||||
ImageTrack BG
|
||||
// ImageTrack BG
|
||||
Show BG "image.png"
|
||||
|
||||
<<-
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
BEGIN Scene1
|
||||
BEGIN Scene1
|
||||
|
||||
Show BG "image.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.
|
||||
Type "Y" and press 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 new browser will open. Log in to your Yahoo mail account.
|
||||
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.
|
||||
Go to your inbox and click on the link to download the latest version of Google Chrome.
|
||||
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
|
||||
|
||||
SHADERC = "..\\out\\install\\x64-Debug\\bin\\shaderc"
|
||||
OUT = "..\\out\\build\\x64-Debug\\ADVect\\shaders\\"
|
||||
#SHADERC = "..\\out\\install\\x64-Debug\\bin\\shaderc"
|
||||
SHADERC = "/Users/lachrymal/Projects/NouVeL/build/ADVect/ext/bgfx/Debug/shaderc"
|
||||
#OUT = "..\\out\\build\\x64-Debug\\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 = [
|
||||
P('glsl', '140', '140'),
|
||||
P('dx11', 'ps_5_0', 'vs_5_0'),
|
||||
P('spirv', 'spirv', 'spirv')
|
||||
# P('glsl', 'windows', '140', '140'),
|
||||
# P('dx11', 'windows', 'ps_5_0', 'vs_5_0'),
|
||||
# P('spirv', 'windows', 'spirv', 'spirv'),
|
||||
P('metal', 'osx', 'metal', 'metal')
|
||||
]
|
||||
|
||||
for root, dirs, _ in os.walk('shaders'):
|
||||
for name in dirs:
|
||||
for config in plats:
|
||||
subprocess.run([SHADERC, "-f", os.path.join(root, name, name + '.frag'),
|
||||
"--type", "fragment"
|
||||
"--platform", "windows",
|
||||
"--type", "fragment",
|
||||
"--platform", config['platform'],
|
||||
"--profile", config['frag'],
|
||||
"--varyingdef", os.path.join(root, name, "varying.def.sc"),
|
||||
"-i", "ext\\bgfx\\bgfx\\examples\\common",
|
||||
"-i", "ext\\bgfx\\bgfx\\src",
|
||||
"-i", "/Users/lachrymal/Projects/NouVeL/ADVect/ext/bgfx/bgfx/examples/common",
|
||||
"-i", "/Users/lachrymal/Projects/NouVeL/ADVect/ext/bgfx/bgfx/src",
|
||||
"-o", OUT + config['location'] + "\\" + name + ".frag.bin"])
|
||||
subprocess.run([SHADERC, "-f", os.path.join(root, name, name + '.vert'),
|
||||
"--type", "vertex"
|
||||
"--platform", "windows",
|
||||
"--type", "vertex",
|
||||
"--platform", config['platform'],
|
||||
"--profile", config['vert'],
|
||||
"--varyingdef", os.path.join(root, name, "varying.def.sc"),
|
||||
"-i", "ext\\bgfx\\bgfx\\examples\\common",
|
||||
"-i", "ext\\bgfx\\bgfx\\src",
|
||||
"-i", "/Users/lachrymal/Projects/NouVeL/ADVect/ext/bgfx/bgfx/examples/common",
|
||||
"-i", "/Users/lachrymal/Projects/NouVeL/ADVect/ext/bgfx/bgfx/src",
|
||||
"-o", OUT + config['location'] + "\\" + name + ".vert.bin"])
|
||||
|
|
@ -17,7 +17,9 @@
|
|||
},
|
||||
"vendor": {
|
||||
"microsoft.com/VisualStudioSettings/CMake/1.0": {
|
||||
"hostOS": [ "Windows" ]
|
||||
"hostOS": [
|
||||
"Windows"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -33,12 +35,23 @@
|
|||
},
|
||||
"vendor": {
|
||||
"microsoft.com/VisualStudioSettings/CMake/1.0": {
|
||||
"hostOS": [ "Linux" ]
|
||||
"hostOS": [
|
||||
"Linux"
|
||||
]
|
||||
},
|
||||
"microsoft.com/VisualStudioRemoteSettings/CMake/1.0": {
|
||||
"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)
|
||||
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" )
|
||||
|
||||
# TODO: Add tests and install targets if needed.
|
||||
|
|
|
@ -15,6 +15,7 @@ typedef int64_t i64;
|
|||
typedef uint64_t u64;
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <locale>
|
||||
#include <codecvt>
|
||||
|
@ -24,6 +25,8 @@ namespace NVL {
|
|||
using Number = f32;
|
||||
using Char = char16_t;
|
||||
using String = std::u16string;
|
||||
template <typename T>
|
||||
using Vector = std::vector<T>;
|
||||
|
||||
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 "Parser.h"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
namespace NVL::Environment {
|
||||
Environment ENVIRONMENT;
|
||||
|
||||
Variable::Variable() : type(Type::Nil), length(0) { }
|
||||
Variable::Variable(Type t) : type(t), length(0) {
|
||||
if (t != Type::Nil)
|
||||
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 std::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 Vector<Variable>& v) : type(Type::Array), value(v), length(v.size()) {}
|
||||
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 {
|
||||
if (other.type != type)
|
||||
return false;
|
||||
switch (type) {
|
||||
case Type::Number:
|
||||
case Type::StaticReference: // Only used with serialization
|
||||
return std::get<Number>(other.value) == std::get<Number>(value);
|
||||
case Type::String:
|
||||
return std::get<String>(other.value) == std::get<String>(value);
|
||||
|
@ -44,7 +45,7 @@ namespace NVL::Environment {
|
|||
env[name] = p;
|
||||
}
|
||||
|
||||
Variable& Environment::get(const String& name) {
|
||||
const Variable& Environment::get(const String& name) const {
|
||||
return env.at(name);
|
||||
}
|
||||
|
||||
|
@ -55,30 +56,34 @@ namespace NVL::Environment {
|
|||
Variable Eval(const Parse::Object& obj) {
|
||||
switch (obj.type) {
|
||||
case Parse::Type::Symbol:
|
||||
return std::get<String>(obj.value);
|
||||
return ENVIRONMENT.get(std::get<String>(obj.value));
|
||||
case Parse::Type::Number:
|
||||
return Variable(std::get<Number>(obj.value));
|
||||
case Parse::Type::String:
|
||||
return Variable(std::get<String>(obj.value));
|
||||
case Parse::Type::Array:
|
||||
{
|
||||
std::vector<Variable> v{};
|
||||
for (const auto& x : std::get<std::vector<Parse::Object>>(obj.value))
|
||||
Vector<Variable> v{};
|
||||
for (const auto& x : std::get<Vector<Parse::Object>>(obj.value))
|
||||
v.push_back(Eval(x));
|
||||
return Variable(v);
|
||||
}
|
||||
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) {
|
||||
std::vector<Variable> args{};
|
||||
for (u32 i = 1; i < c.size(); i++)
|
||||
Vector<Variable> args{};
|
||||
|
||||
Variable f = Eval(c[0]);
|
||||
for (u32 i = 1; i < c.size(); 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) {
|
||||
|
@ -87,23 +92,23 @@ namespace NVL::Environment {
|
|||
}
|
||||
|
||||
// Check MatchMarkup for more information
|
||||
MarkupString UnpackMarkupVariable(const std::vector<Variable>& v) {
|
||||
MarkupString UnpackMarkupVariable(const Vector<Variable>& v) {
|
||||
MarkupString ms{};
|
||||
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);
|
||||
|
||||
std::vector<std::pair<String, std::vector<String>>> efs;
|
||||
for (const Variable& combination : std::get<std::vector<Variable>>(pair[1].value)) {
|
||||
Vector<std::pair<String, Vector<String>>> efs;
|
||||
for (const Variable& combination : std::get<Vector<Variable>>(pair[1].value)) {
|
||||
if (combination.type == Type::String) {
|
||||
const String ef = std::get<String>(combination.value);
|
||||
efs.push_back({ ef, {} });
|
||||
}
|
||||
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 std::vector<Variable>& args = std::get<std::vector<Variable>>(ef_t[1].value);
|
||||
std::vector<String> ss{};
|
||||
const Vector<Variable>& args = std::get<Vector<Variable>>(ef_t[1].value);
|
||||
Vector<String> ss{};
|
||||
for (const auto& s : args) { ss.push_back(std::get<String>(s.value)); }
|
||||
efs.push_back({ ef, ss });
|
||||
}
|
||||
|
|
|
@ -6,20 +6,20 @@
|
|||
#include "Common.h"
|
||||
|
||||
namespace NVL::Environment {
|
||||
enum class Type { Procedure, Number, String, Array, Nil };
|
||||
enum class Type { Nil, StaticReference, Procedure, Number, String, Array };
|
||||
|
||||
struct Variable {
|
||||
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
|
||||
u32 length;
|
||||
bool operator==(const Variable& other) const;
|
||||
Variable(); // Makes Nil, length 0
|
||||
Variable(Type t); // Reserved for Nil
|
||||
Variable(const Number& v);
|
||||
Variable(const Number& v, bool is_ref = false);
|
||||
Variable(const String& v);
|
||||
Variable(const std::vector<Variable>& v);
|
||||
Variable(const std::function<Variable(std::vector<Variable>)>& v, u32 l);
|
||||
Variable(const Vector<Variable>& v);
|
||||
Variable(const std::function<Variable(Vector<Variable>)>& v, u32 l);
|
||||
};
|
||||
|
||||
class Environment {
|
||||
|
@ -29,7 +29,7 @@ namespace NVL::Environment {
|
|||
void enter(const String& name, Variable p);
|
||||
void enter(std::initializer_list<std::pair<String, 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);
|
||||
};
|
||||
|
||||
|
@ -41,15 +41,15 @@ namespace NVL::Environment {
|
|||
|
||||
struct MarkupSegment {
|
||||
String str;
|
||||
std::vector<std::pair<String, std::vector<String>>> efs;
|
||||
Vector<std::pair<String, Vector<String>>> efs;
|
||||
};
|
||||
struct MarkupString {
|
||||
private:
|
||||
mutable i32 mem_length = -1;
|
||||
public:
|
||||
std::vector<MarkupSegment> segments{};
|
||||
Vector<MarkupSegment> segments{};
|
||||
size_t length() 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());
|
||||
}
|
||||
|
||||
std::vector<String> split_string_by_lines(const String& str) {
|
||||
std::vector<String> lines;
|
||||
Vector<String> split_string_by_lines(const String& str) {
|
||||
Vector<String> lines;
|
||||
size_t pos = 0;
|
||||
size_t prev = 0;
|
||||
while ((pos = str.find(NEWLINE, prev)) != String::npos) {
|
||||
|
@ -230,7 +230,7 @@ namespace {
|
|||
Parse::Object ParseArray(const String& f, size_t& pos, u32 layer) {
|
||||
SkipComments(f, pos);
|
||||
|
||||
std::vector<Parse::Object> array{};
|
||||
Vector<Parse::Object> array{};
|
||||
|
||||
array.push_back(ParseExpression(f, pos));
|
||||
while (PeekToken(f, pos)[0] != ARRAY_CLOSE) {
|
||||
|
@ -246,7 +246,7 @@ namespace {
|
|||
|
||||
String ParseString(const String& f, size_t& pos) {
|
||||
SkipComments(f, pos);
|
||||
std::vector<size_t> discards{};
|
||||
Vector<size_t> discards{};
|
||||
auto start = ++pos; // skip opening quote
|
||||
do {
|
||||
if (f[pos] == QUOTE) {
|
||||
|
@ -352,7 +352,7 @@ namespace {
|
|||
bool has_markup = false;
|
||||
|
||||
// Match tags
|
||||
std::vector<Parse::Object> segments;
|
||||
Vector<Parse::Object> segments;
|
||||
String::const_iterator tags_start(s.cbegin());
|
||||
while (srell::regex_search(tags_start, s.cend(), tags_match, typer)) {
|
||||
has_markup = true;
|
||||
|
@ -361,13 +361,13 @@ namespace {
|
|||
if (!before.empty())
|
||||
segments.push_back({ Parse::Type::Array, {
|
||||
{ Parse::Type::String, before },
|
||||
{ Parse::Type::Array, std::vector<Parse::Object>{} }
|
||||
{ Parse::Type::Array, Vector<Parse::Object>{} }
|
||||
}});
|
||||
|
||||
String inner = tags_match[2].str(); // markupped
|
||||
|
||||
// Match markup options
|
||||
std::vector<Parse::Object> effects{};
|
||||
Vector<Parse::Object> effects{};
|
||||
String::const_iterator effects_start(tags_match[1].first);
|
||||
while (srell::regex_search(effects_start, tags_match[1].second, effects_match, effect)) {
|
||||
if (effects_match[3].matched) { // no params
|
||||
|
@ -376,19 +376,19 @@ namespace {
|
|||
else { // no params
|
||||
|
||||
// Comma split
|
||||
std::vector<Parse::Object> args;
|
||||
Vector<Parse::Object> args;
|
||||
String::const_iterator params_start(effects_match[2].first);
|
||||
while (srell::regex_search(params_start, effects_match[2].second, params_match, param)) {
|
||||
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
|
||||
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;
|
||||
}
|
||||
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) {
|
||||
|
@ -396,15 +396,15 @@ namespace {
|
|||
if (!end.empty())
|
||||
segments.push_back({ Parse::Type::Array, {
|
||||
{ Parse::Type::String, end },
|
||||
{ Parse::Type::Array, std::vector<Parse::Object>{} }
|
||||
{ Parse::Type::Array, Vector<Parse::Object>{} }
|
||||
}});
|
||||
|
||||
return { Parse::Type::Array, segments };
|
||||
}
|
||||
else {
|
||||
return { Parse::Type::Array, std::vector<Parse::Object>{
|
||||
return { Parse::Type::Array, Vector<Parse::Object>{
|
||||
{ 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!");
|
||||
}
|
||||
|
||||
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!");
|
||||
}
|
||||
|
||||
|
@ -500,14 +500,14 @@ namespace NVL::Parse {
|
|||
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!");
|
||||
}
|
||||
|
||||
std::vector<Scene> ParseFile(const std::string& path) {
|
||||
Vector<Scene> ParseFile(const std::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++) {
|
||||
list.push_back(ParseScene(f, i));
|
||||
}
|
||||
|
|
13
NVL/Parser.h
13
NVL/Parser.h
|
@ -1,5 +1,4 @@
|
|||
#pragma once
|
||||
#include <vector>
|
||||
#include <variant>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
@ -13,22 +12,22 @@ namespace NVL::Parse {
|
|||
Object() = delete;
|
||||
Object(const Number& 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(Type t, String&& v);
|
||||
Object(Type t, std::vector<Object>&& v);
|
||||
Object(Type t, Vector<Object>&& v);
|
||||
Type type;
|
||||
std::variant<
|
||||
Number,
|
||||
String,
|
||||
std::vector<Object>
|
||||
Vector<Object>
|
||||
> value;
|
||||
};
|
||||
|
||||
using Command = std::vector<Object>;
|
||||
using Command = Vector<Object>;
|
||||
|
||||
class Scene {
|
||||
std::vector<Command> commands{};
|
||||
Vector<Command> commands{};
|
||||
public:
|
||||
String 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