some parser bugs, srell supports lookbehind, imagetrack abstraction
This commit is contained in:
parent
19e7374ac4
commit
ee42a08fb8
13 changed files with 473 additions and 307 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1,4 +1,6 @@
|
||||||
.vs
|
.vs
|
||||||
out
|
out
|
||||||
|
build
|
||||||
NVL/.vs
|
NVL/.vs
|
||||||
NVL/out
|
NVL/out
|
||||||
|
.cache
|
||||||
|
|
|
@ -4,15 +4,16 @@
|
||||||
#include <SDL2/SDL_syswm.h>
|
#include <SDL2/SDL_syswm.h>
|
||||||
#include <bgfx/bgfx.h>
|
#include <bgfx/bgfx.h>
|
||||||
#include <bgfx/platform.h>
|
#include <bgfx/platform.h>
|
||||||
|
#include <bx/math.h>
|
||||||
|
|
||||||
#include <chrono>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
SDL_Window* window;
|
SDL_Window* window;
|
||||||
|
|
||||||
std::string m_name;
|
std::string m_name;
|
||||||
bool running = false;
|
volatile bool running = false;
|
||||||
|
|
||||||
u16 m_width = 1280;
|
u16 m_width = 1280;
|
||||||
u16 m_height = 720;
|
u16 m_height = 720;
|
||||||
|
@ -25,23 +26,49 @@ namespace {
|
||||||
NVL::String speaker;
|
NVL::String speaker;
|
||||||
u32 scene_pos = 0;
|
u32 scene_pos = 0;
|
||||||
|
|
||||||
|
struct ImageTrack {
|
||||||
|
std::string name;
|
||||||
|
ADVect::Graphics::ImageTexture* current = nullptr;
|
||||||
|
i32 pos_x = 0, pos_y = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<ImageTrack> tracks_img{};
|
||||||
|
ImageTrack* 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) {
|
||||||
|
ImageTrack 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 {
|
||||||
void Init(std::string name, const std::vector<NVL::Parse::Scene>& sc) {
|
bool Init(std::string name, const std::vector<NVL::Parse::Scene>& sc) {
|
||||||
m_name = name;
|
m_name = name;
|
||||||
scenes = sc; // sure make a copy whatever
|
scenes = sc; // sure make a copy whatever
|
||||||
|
|
||||||
if (SDL_Init(SDL_INIT_VIDEO)) {
|
if (SDL_Init(SDL_INIT_VIDEO)) {
|
||||||
std::cerr << "Failed to init SDL: " << SDL_GetError() << std::endl;
|
std::cerr << "ADV: Failed to init SDL: " << SDL_GetError() << std::endl;
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
window = SDL_CreateWindow(m_name.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, m_width, m_height, SDL_WINDOW_SHOWN);
|
|
||||||
|
|
||||||
|
window = SDL_CreateWindow(m_name.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, m_width, m_height, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
|
||||||
if (window == NULL) {
|
if (window == NULL) {
|
||||||
std::cerr << "ADV: Failed to create window: " << SDL_GetError() << std::endl;
|
std::cerr << "ADV: Failed to create window: " << SDL_GetError() << std::endl;
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bgfx::Init bgfxInit;
|
bgfx::Init bgfxInit;
|
||||||
bgfxInit.type = bgfx::RendererType::Count; // Automatically choose a renderer.
|
bgfxInit.type = bgfx::RendererType::Count; // Automatically choose a renderer.
|
||||||
bgfxInit.resolution.width = m_width;
|
bgfxInit.resolution.width = m_width;
|
||||||
|
@ -68,25 +95,25 @@ namespace ADVect {
|
||||||
|
|
||||||
if (!bgfx::init(bgfxInit)) {
|
if (!bgfx::init(bgfxInit)) {
|
||||||
std::cerr << "ADV: Failed bgfx initialization" << std::endl;
|
std::cerr << "ADV: Failed bgfx initialization" << std::endl;
|
||||||
return;
|
return false;
|
||||||
};
|
};
|
||||||
bgfx::setDebug(BGFX_DEBUG_TEXT);
|
bgfx::setDebug(BGFX_DEBUG_TEXT);
|
||||||
bgfx::setViewClear(0, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH, 0x443322ff, 1.0f, 0);
|
bgfx::setViewClear(0, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH, 0x443322ff, 1.0f, 0);
|
||||||
bgfx::setViewRect(0, 0, 0, m_width, m_height);
|
bgfx::setViewRect(0, 0, 0, m_width, m_height);
|
||||||
bgfx::setViewMode(0, bgfx::ViewMode::Sequential);
|
bgfx::setViewMode(0, bgfx::ViewMode::Sequential);
|
||||||
|
float view[16];
|
||||||
|
bx::mtxTranslate(view, 0.f, 0.f, 1.0f);
|
||||||
|
float proj[16];
|
||||||
|
bx::mtxOrtho(proj, 0.0f, m_width, 0.0f, m_height, 0.1f, 100.0f, 0.f, bgfx::getCaps()->homogeneousDepth);
|
||||||
|
bgfx::setViewTransform(0, view, proj);
|
||||||
|
|
||||||
ADVect::Graphics::Init(m_width, m_height);
|
if (!ADVect::Graphics::Init(m_width, m_height)) {
|
||||||
|
std::cerr << "ADV: Graphics init failed" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
NVL::Environment::ENVIRONMENT.enter(u"Say", NVL::Environment::Variable([&](std::vector<NVL::Environment::Variable> args) {
|
|
||||||
m_text = args;
|
|
||||||
return NVL::Environment::Type::Nil;
|
|
||||||
}, 2));
|
|
||||||
|
|
||||||
NVL::Environment::ENVIRONMENT.enter(u"SwitchSpeaker", NVL::Environment::Variable([&](std::vector<NVL::Environment::Variable> args) {
|
|
||||||
speaker = std::get<NVL::String>(NVL::Environment::Variable(args[0]).value);
|
|
||||||
return NVL::Environment::Type::Nil;
|
|
||||||
}, 1));
|
|
||||||
Advance();
|
Advance();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shutdown() {
|
void Shutdown() {
|
||||||
|
@ -98,39 +125,22 @@ namespace ADVect {
|
||||||
|
|
||||||
void Advance() {
|
void Advance() {
|
||||||
size_t curr_size = scenes[current_scene].get().size();
|
size_t curr_size = scenes[current_scene].get().size();
|
||||||
while (scene_pos < curr_size) {
|
while (scene_pos < curr_size && std::get<NVL::String>(scenes[current_scene].get()[scene_pos][0].value) != u"Say") {
|
||||||
|
NVL::Environment::Apply(scenes[current_scene].get()[scene_pos]);
|
||||||
|
scene_pos++;
|
||||||
|
}
|
||||||
|
if (curr_size == scene_pos) {
|
||||||
|
running = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (std::get<NVL::String>(scenes[current_scene].get()[scene_pos][0].value) == u"Say") {
|
if (std::get<NVL::String>(scenes[current_scene].get()[scene_pos][0].value) == u"Say") {
|
||||||
NVL::Environment::Apply(scenes[current_scene].get()[scene_pos]);
|
NVL::Environment::Apply(scenes[current_scene].get()[scene_pos]);
|
||||||
scene_pos++;
|
scene_pos++;
|
||||||
return;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
NVL::Environment::Apply(scenes[current_scene].get()[scene_pos]);
|
|
||||||
scene_pos++;
|
|
||||||
}
|
|
||||||
switch (curr_size - scene_pos) {
|
|
||||||
case 0:
|
|
||||||
current_scene = -1;
|
|
||||||
return;
|
|
||||||
case 1:
|
|
||||||
return;
|
|
||||||
default:
|
|
||||||
if (std::get<NVL::String>(scenes[current_scene].get()[scene_pos + 1][0].value) == u"Say") {
|
|
||||||
NVL::Environment::Apply(scenes[current_scene].get()[scene_pos]);
|
|
||||||
scene_pos++;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Update() {
|
void Update() {
|
||||||
if (m_keys[SDL_SCANCODE_SPACE]) {
|
if (m_keys[SDL_SCANCODE_SPACE]) {
|
||||||
if (current_scene == -1) {
|
|
||||||
running = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Advance();
|
Advance();
|
||||||
m_keys[SDL_SCANCODE_SPACE] = false;
|
m_keys[SDL_SCANCODE_SPACE] = false;
|
||||||
}
|
}
|
||||||
|
@ -139,18 +149,22 @@ namespace ADVect {
|
||||||
void Render() {
|
void Render() {
|
||||||
bgfx::touch(0);
|
bgfx::touch(0);
|
||||||
|
|
||||||
ADVect::Graphics::DrawRandomShit();
|
// ADVect::Graphics::DrawFunkyAhhShit();
|
||||||
|
for (auto& t : tracks_img) {
|
||||||
|
if (t.current != nullptr)
|
||||||
|
ADVect::Graphics::DrawTextureImage(*t.current, t.pos_x, t.pos_y);
|
||||||
|
}
|
||||||
ADVect::Graphics::RenderString(speaker, 100, 150, 0xFFFFFFFF, ADVect::Graphics::TEXT_BOLD);
|
ADVect::Graphics::RenderString(speaker, 100, 150, 0xFFFFFFFF, ADVect::Graphics::TEXT_BOLD);
|
||||||
ADVect::Graphics::RenderStringMarkup(m_text, 300, 90, 0xFFFFFFFF);
|
ADVect::Graphics::RenderStringMarkup(m_text, 300, 90, 0xFFFFFFFF);
|
||||||
|
|
||||||
|
|
||||||
bgfx::dbgTextClear();
|
bgfx::dbgTextClear();
|
||||||
bgfx::dbgTextPrintf(0, 44, 0xF0, "NouVeL x ADVect :: %s %s", __DATE__, __TIME__);
|
bgfx::dbgTextPrintf(0, 44, 0xF0, "NouVeL x ADVect :: %s :: %s %s", BX_COMPILER_NAME, __DATE__, __TIME__);
|
||||||
bgfx::dbgTextPrintf(0, 43, 0xF0, "Current Position: %u", scene_pos);
|
bgfx::dbgTextPrintf(0, 43, 0xF0, "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, 42, 0xF0, "Current Scene: %s", NVL::to_std_string(scenes[current_scene].name).c_str());
|
bgfx::dbgTextPrintf(0, 42, 0xF0, "Current Position: %u", scene_pos);
|
||||||
|
bgfx::dbgTextPrintf(0, 41, 0xF0, "Current Scene: %s", NVL::to_std_string(scenes[current_scene].name).c_str());
|
||||||
|
|
||||||
bgfx::frame();
|
bgfx::frame();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Run() {
|
void Run() {
|
||||||
|
@ -178,11 +192,40 @@ namespace ADVect {
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
const std::string PJ_DIR = "..\\..\\..\\..\\NVL\\";
|
const std::string PJ_DIR = "..\\..\\..\\..\\NVL\\";
|
||||||
std::vector<NVL::Parse::Scene> SCENES = NVL::Parse::ParseFile(PJ_DIR + "dialogue.nvl");
|
|
||||||
|
|
||||||
ADVect::Init("ADV", SCENES);
|
NVL::Environment::ENVIRONMENT.enter(u"Say", NVL::Environment::Variable([](std::vector<NVL::Environment::Variable> args) {
|
||||||
|
m_text = args;
|
||||||
|
return NVL::Environment::Type::Nil;
|
||||||
|
}, 2));
|
||||||
|
|
||||||
|
NVL::Environment::ENVIRONMENT.enter(u"SwitchSpeaker", NVL::Environment::Variable([](std::vector<NVL::Environment::Variable> args) {
|
||||||
|
speaker = std::get<NVL::String>(NVL::Environment::Variable(args[0]).value);
|
||||||
|
return NVL::Environment::Type::Nil;
|
||||||
|
}, 1));
|
||||||
|
|
||||||
|
NVL::Environment::ENVIRONMENT.enter(u"ImageTrack", 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)));
|
||||||
|
return NVL::Environment::Type::Nil;
|
||||||
|
}, 1));
|
||||||
|
|
||||||
|
NVL::Environment::ENVIRONMENT.enter(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));
|
||||||
|
ImageTrack* t = find_image_track(name);
|
||||||
|
if (t == nullptr) {
|
||||||
|
std::cerr << "ADV: Cannot find ImageTrack " << name << std::endl;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
t->current = ADVect::Graphics::GetImageTextureFromFile(NVL::to_std_string(std::get<NVL::String>(NVL::Environment::Variable(args[1]).value)));
|
||||||
|
}
|
||||||
|
return NVL::Environment::Type::Nil;
|
||||||
|
}, 2));
|
||||||
|
|
||||||
|
std::vector<NVL::Parse::Scene> SCENES = NVL::Parse::ParseFile(PJ_DIR + "dante_de.nvl");
|
||||||
|
if (SCENES.empty()) return EXIT_FAILURE;
|
||||||
|
|
||||||
|
if (!ADVect::Init("ADV", SCENES)) return EXIT_FAILURE;
|
||||||
ADVect::Run();
|
ADVect::Run();
|
||||||
|
|
||||||
ADVect::Shutdown();
|
ADVect::Shutdown();
|
||||||
return 0;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
#include <Common.h>
|
#include <Common.h>
|
||||||
|
|
||||||
namespace ADVect {
|
namespace ADVect {
|
||||||
void Init(std::string name, const std::vector<NVL::Parse::Scene>& sc);
|
bool Init(std::string name, const std::vector<NVL::Parse::Scene>& sc);
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
|
|
||||||
void Run();
|
void Run();
|
||||||
|
|
|
@ -5,37 +5,15 @@
|
||||||
#include <bx/math.h>
|
#include <bx/math.h>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
#define STB_IMAGE_IMPLEMENTATION
|
#define STB_IMAGE_IMPLEMENTATION
|
||||||
#include <stb_image.h>
|
#include <stb_image.h>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
FT_Library library;
|
using namespace ADVect::Graphics;
|
||||||
FT_Error error;
|
|
||||||
FT_Face face_regular, face_bold;
|
|
||||||
|
|
||||||
struct PosUVVertex {
|
bgfx::ShaderHandle loadShader(const std::string& FILENAME)
|
||||||
f32 x;
|
|
||||||
f32 y;
|
|
||||||
f32 z;
|
|
||||||
f32 u;
|
|
||||||
f32 v;
|
|
||||||
};
|
|
||||||
static PosUVVertex quad_vert[] =
|
|
||||||
{
|
|
||||||
{ 0.f, 0.f, 0.0f, 0.0f, 0.0f },
|
|
||||||
{ 0.f, 1.f, 0.0f, 0.0f, 1.0f },
|
|
||||||
{ 1.f, 0.f, 0.0f, 1.0f, 0.0f },
|
|
||||||
{ 1.f, 1.f, 0.0f, 1.0f, 1.0f }
|
|
||||||
};
|
|
||||||
|
|
||||||
static const uint16_t quad_indices[] =
|
|
||||||
{
|
|
||||||
0, 2, 1,
|
|
||||||
1, 2, 3
|
|
||||||
};
|
|
||||||
|
|
||||||
bgfx::ShaderHandle loadShader(const char* FILENAME)
|
|
||||||
{
|
{
|
||||||
std::string shaderPath{};
|
std::string shaderPath{};
|
||||||
|
|
||||||
|
@ -67,171 +45,47 @@ namespace {
|
||||||
return bgfx::createShader(mem);
|
return bgfx::createShader(mem);
|
||||||
}
|
}
|
||||||
|
|
||||||
bgfx::ShaderHandle a_vsh, img_vsh;
|
struct PosUVVertex {
|
||||||
bgfx::ShaderHandle a_fsh, img_fsh;
|
f32 x;
|
||||||
bgfx::ProgramHandle a_program, img_program;
|
f32 y;
|
||||||
bgfx::IndexBufferHandle ibh;
|
f32 z;
|
||||||
bgfx::VertexBufferHandle vbh;
|
f32 u;
|
||||||
bgfx::UniformHandle s_texColor;
|
f32 v;
|
||||||
bgfx::VertexLayout pcvDecl;
|
};
|
||||||
|
|
||||||
std::unordered_map<NVL::Char, bgfx::TextureHandle> cache_regular {};
|
static PosUVVertex quad_vert[] =
|
||||||
std::unordered_map<NVL::Char, bgfx::TextureHandle> cache_bold {};
|
{
|
||||||
|
{ 0.f, 0.f, 0.0f, 0.0f, 0.0f },
|
||||||
|
{ 0.f, 1.f, 0.0f, 0.0f, 1.0f },
|
||||||
|
{ 1.f, 0.f, 0.0f, 1.0f, 0.0f },
|
||||||
|
{ 1.f, 1.f, 0.0f, 1.0f, 1.0f }
|
||||||
|
};
|
||||||
|
|
||||||
int w, h, channels;
|
static const uint16_t quad_indices[] =
|
||||||
u8* img;
|
{
|
||||||
bgfx::TextureHandle tx;
|
0, 2, 1,
|
||||||
}
|
1, 2, 3
|
||||||
|
};
|
||||||
|
|
||||||
namespace ADVect::Graphics {
|
FT_Library library;
|
||||||
i16 Init(u16 width, u16 height) {
|
FT_Error error;
|
||||||
error = FT_Init_FreeType(&library);
|
|
||||||
|
struct Font {
|
||||||
|
FT_Face face = nullptr;
|
||||||
|
std::unordered_map<NVL::Char, bgfx::TextureHandle> cache{};
|
||||||
|
|
||||||
|
void cache_char(NVL::Char c) {
|
||||||
|
FT_GlyphSlot slot = face->glyph;
|
||||||
|
|
||||||
|
error = FT_Load_Char(face, c, FT_LOAD_RENDER);
|
||||||
if (error) {
|
if (error) {
|
||||||
std::cerr << "ADV: FreeType init error: " << error << std::endl;
|
std::cerr << "ADV: Failed to load character" << std::endl;
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
error = FT_New_Face(library, "SourceHanSans-Regular.ttc", 0, &face_regular);
|
if (cache.find(c) == cache.end() && slot->bitmap.width != 0) {
|
||||||
error = FT_New_Face(library, "SourceHanSans-Bold.ttc", 0, &face_bold);
|
|
||||||
if (error == FT_Err_Unknown_File_Format) {
|
|
||||||
std::cerr << "ADV: FreeType Unknown_File_Format: " << error << std::endl;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
else if (error) {
|
|
||||||
std::cerr << "ADV: FreeType font loading error: " << error << std::endl;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
error = FT_Set_Char_Size(face_regular, 0, 20 * 64, 72, 72);
|
|
||||||
error = FT_Set_Char_Size(face_bold, 0, 20 * 64, 72, 72);
|
|
||||||
if (error == FT_Err_Unknown_File_Format) {
|
|
||||||
std::cerr << "ADV: FreeType Set_Char_Size error: " << error << std::endl;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
float view[16];
|
|
||||||
bx::mtxTranslate(view, 0.f, 0.f, 1.0f);
|
|
||||||
float proj[16];
|
|
||||||
bx::mtxOrtho(proj, 0.0f, width, 0.0f, height, 0.1f, 100.0f, 0.f, bgfx::getCaps()->homogeneousDepth);
|
|
||||||
bgfx::setViewTransform(0, view, proj);
|
|
||||||
|
|
||||||
pcvDecl.begin()
|
|
||||||
.add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float)
|
|
||||||
.add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Float)
|
|
||||||
.end();
|
|
||||||
ibh = bgfx::createIndexBuffer(bgfx::makeRef(quad_indices, sizeof(quad_indices)));
|
|
||||||
vbh = bgfx::createVertexBuffer(bgfx::makeRef(quad_vert, sizeof(quad_vert)), pcvDecl);
|
|
||||||
|
|
||||||
img_vsh = loadShader("test.vert.bin");
|
|
||||||
img_fsh = loadShader("test.frag.bin");
|
|
||||||
img_program = bgfx::createProgram(img_vsh, img_fsh, true);
|
|
||||||
|
|
||||||
a_vsh = loadShader("swizzle_aaaa.vert.bin");
|
|
||||||
a_fsh = loadShader("swizzle_aaaa.frag.bin");
|
|
||||||
a_program = bgfx::createProgram(a_vsh, a_fsh, true);
|
|
||||||
|
|
||||||
s_texColor = bgfx::createUniform("s_texColor", bgfx::UniformType::Sampler);
|
|
||||||
|
|
||||||
|
|
||||||
img = stbi_load("image.png", &w, &h, &channels, 0);
|
|
||||||
if (img == NULL) {
|
|
||||||
std::cerr << "ADV: STB IMAGE loading failed" << std::endl;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
const bgfx::Memory* buf = bgfx::makeRef(img, w * h * channels * sizeof(u8));
|
|
||||||
tx = bgfx::createTexture2D(
|
|
||||||
w,
|
|
||||||
h,
|
|
||||||
false,
|
|
||||||
1,
|
|
||||||
bgfx::TextureFormat::RGBA8,
|
|
||||||
BGFX_TEXTURE_NONE | BGFX_SAMPLER_UVW_CLAMP,
|
|
||||||
buf
|
|
||||||
);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Shutdown() {
|
|
||||||
FT_Done_Face(face_regular);
|
|
||||||
FT_Done_Face(face_bold);
|
|
||||||
FT_Done_FreeType(library);
|
|
||||||
|
|
||||||
|
|
||||||
bgfx::destroy(a_vsh);
|
|
||||||
bgfx::destroy(a_fsh);
|
|
||||||
bgfx::destroy(img_vsh);
|
|
||||||
bgfx::destroy(img_fsh);
|
|
||||||
bgfx::destroy(a_program);
|
|
||||||
bgfx::destroy(img_program);
|
|
||||||
bgfx::destroy(ibh);
|
|
||||||
bgfx::destroy(vbh);
|
|
||||||
bgfx::destroy(s_texColor);
|
|
||||||
for (auto it = cache_regular .begin(); it != cache_regular.end(); it++) {
|
|
||||||
bgfx::destroy(it->second);
|
|
||||||
}
|
|
||||||
for (auto it = cache_bold.begin(); it != cache_bold.end(); it++) {
|
|
||||||
bgfx::destroy(it->second);
|
|
||||||
}
|
|
||||||
bgfx::destroy(tx);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Draws quad with texture on Z = 0
|
|
||||||
void DrawTexture(const bgfx::TextureHandle& tex, i32 pos_x, i32 pos_y, u32 w, u32 h) {
|
|
||||||
float mtx1[16], mtx2[16], mtx3[16];
|
|
||||||
bx::mtxTranslate(mtx1, pos_x, pos_y, 0.0f);
|
|
||||||
bx::mtxScale(mtx2, w, h, 1.0f);
|
|
||||||
bx::mtxMul(mtx3, mtx2, mtx1);
|
|
||||||
|
|
||||||
bgfx::setTransform(mtx3);
|
|
||||||
|
|
||||||
bgfx::setVertexBuffer(0, vbh);
|
|
||||||
bgfx::setIndexBuffer(ibh);
|
|
||||||
|
|
||||||
bgfx::setTexture(0, s_texColor, tex);
|
|
||||||
|
|
||||||
bgfx::setState(BGFX_STATE_DEFAULT | BGFX_STATE_BLEND_NORMAL);
|
|
||||||
bgfx::submit(0, img_program);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DrawTextureStencilAlpha(const bgfx::TextureHandle& tex, i32 pos_x, i32 pos_y, u32 w, u32 h) {
|
|
||||||
float mtx1[16], mtx2[16], mtx3[16];
|
|
||||||
bx::mtxTranslate(mtx1, pos_x, pos_y, 0.0f);
|
|
||||||
bx::mtxScale(mtx2, w, h, 1.0f);
|
|
||||||
bx::mtxMul(mtx3, mtx2, mtx1);
|
|
||||||
|
|
||||||
bgfx::setTransform(mtx3);
|
|
||||||
|
|
||||||
bgfx::setVertexBuffer(0, vbh);
|
|
||||||
bgfx::setIndexBuffer(ibh);
|
|
||||||
|
|
||||||
bgfx::setTexture(0, s_texColor, tex);
|
|
||||||
|
|
||||||
bgfx::setState((BGFX_STATE_DEFAULT | BGFX_STATE_BLEND_ALPHA) & ~(BGFX_STATE_WRITE_Z | BGFX_STATE_DEPTH_TEST_LESS));
|
|
||||||
bgfx::submit(0, a_program);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RenderString(const NVL::String& s, u32& pos_x, u32& pos_y, u32 col, u32 style_flags) {
|
|
||||||
FT_Face active = face_regular;
|
|
||||||
std::unordered_map<NVL::Char, bgfx::TextureHandle>* cache = &cache_regular;
|
|
||||||
switch (style_flags) {
|
|
||||||
case TEXT_NONE: break;
|
|
||||||
case TEXT_BOLD: active = face_bold; cache = &cache_bold; break;
|
|
||||||
case TEXT_ITALIC: break;
|
|
||||||
case TEXT_ITALIC | TEXT_BOLD: break;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
FT_GlyphSlot slot = active->glyph;
|
|
||||||
|
|
||||||
for (const auto& c : s) {
|
|
||||||
error = FT_Load_Char(active, c, FT_LOAD_RENDER);
|
|
||||||
if (error) continue;
|
|
||||||
|
|
||||||
if (cache->find(c) == cache->end() && 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, bgfx::createTexture2D(
|
||||||
slot->bitmap.width,
|
slot->bitmap.width,
|
||||||
slot->bitmap.rows,
|
slot->bitmap.rows,
|
||||||
false,
|
false,
|
||||||
|
@ -241,12 +95,187 @@ namespace ADVect::Graphics {
|
||||||
buf
|
buf
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::optional<Font> init_font(const char* path) {
|
||||||
|
Font f;
|
||||||
|
|
||||||
|
error = FT_New_Face(library, path, 0, &f.face);
|
||||||
|
if (error == FT_Err_Unknown_File_Format) {
|
||||||
|
std::cerr << "ADV: FreeType Unknown_File_Format: " << error << std::endl;
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
else if (error) {
|
||||||
|
std::cerr << "ADV: FreeType font loading error: " << error << std::endl;
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
error = FT_Set_Char_Size(f.face, 0, 20 * 64, 72, 72);
|
||||||
|
if (error) {
|
||||||
|
std::cerr << "ADV: FreeType Set_Char_Size error: " << error << std::endl;
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bgfx::ProgramHandle load_shader_program(const std::string& shader) {
|
||||||
|
return bgfx::createProgram(loadShader(shader + ".vert.bin"), loadShader(shader + ".frag.bin"), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<ImageTexture> get_image_texture(const std::string& file) {
|
||||||
|
ImageTexture i;
|
||||||
|
i.buffer = stbi_load("image.png", &i.w, &i.h, &i.channels, 0);
|
||||||
|
if (i.buffer == NULL) {
|
||||||
|
std::cerr << "ADV: STB IMAGE loading failed" << std::endl;
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
const bgfx::Memory* buf = bgfx::makeRef(i.buffer, i.w * i.h * i.channels * sizeof(u8));
|
||||||
|
i.tx = bgfx::createTexture2D(
|
||||||
|
i.w,
|
||||||
|
i.h,
|
||||||
|
false,
|
||||||
|
1,
|
||||||
|
bgfx::TextureFormat::RGBA8,
|
||||||
|
BGFX_TEXTURE_NONE | BGFX_SAMPLER_UVW_CLAMP,
|
||||||
|
buf
|
||||||
|
);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
void destroy_image_texture(ImageTexture& i) {
|
||||||
|
stbi_image_free(i.buffer);
|
||||||
|
bgfx::destroy(i.tx);
|
||||||
|
}
|
||||||
|
|
||||||
|
Font regular, bold;
|
||||||
|
ImageTexture bg;
|
||||||
|
bgfx::ProgramHandle a_program, img_program;
|
||||||
|
bgfx::UniformHandle s_texColor;
|
||||||
|
|
||||||
|
bgfx::IndexBufferHandle ibh;
|
||||||
|
bgfx::VertexBufferHandle vbh;
|
||||||
|
bgfx::VertexLayout pcvDecl;
|
||||||
|
|
||||||
|
std::unordered_map<std::string, ImageTexture> imgs;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace ADVect::Graphics {
|
||||||
|
bool Init(u16 width, u16 height) {
|
||||||
|
error = FT_Init_FreeType(&library);
|
||||||
|
if (error) {
|
||||||
|
std::cerr << "ADV: FreeType init error: " << error << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (auto f = init_font("SourceHanSerif-Regular.ttc")) regular = *f; else return false;
|
||||||
|
if (auto f = init_font("SourceHanSerif-Heavy.ttc")) bold = *f; else return false;
|
||||||
|
|
||||||
|
pcvDecl.begin()
|
||||||
|
.add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float)
|
||||||
|
.add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Float)
|
||||||
|
.end();
|
||||||
|
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");
|
||||||
|
a_program = load_shader_program("swizzle_aaaa");
|
||||||
|
|
||||||
|
s_texColor = bgfx::createUniform("s_texColor", bgfx::UniformType::Sampler);
|
||||||
|
|
||||||
|
if (auto i = get_image_texture("image.png")) bg = *i; else return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Shutdown() {
|
||||||
|
destroy_font(regular);
|
||||||
|
destroy_font(bold);
|
||||||
|
FT_Done_FreeType(library);
|
||||||
|
|
||||||
|
destroy_image_texture(bg);
|
||||||
|
|
||||||
|
for (auto it = imgs.begin(); it != imgs.end(); it++) {
|
||||||
|
destroy_image_texture(it->second);
|
||||||
|
}
|
||||||
|
|
||||||
|
bgfx::destroy(a_program);
|
||||||
|
bgfx::destroy(img_program);
|
||||||
|
|
||||||
|
bgfx::destroy(ibh);
|
||||||
|
bgfx::destroy(vbh);
|
||||||
|
|
||||||
|
bgfx::destroy(s_texColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draws quad with texture on Z = 0
|
||||||
|
void DrawTexture(const bgfx::TextureHandle& tex, i32 pos_x, i32 pos_y, u32 w, u32 h, u64 state, const bgfx::ProgramHandle& pg) {
|
||||||
|
float mtx1[16], mtx2[16], mtx3[16];
|
||||||
|
bx::mtxTranslate(mtx1, pos_x, pos_y, 0.0f);
|
||||||
|
bx::mtxScale(mtx2, w, h, 1.0f);
|
||||||
|
bx::mtxMul(mtx3, mtx2, mtx1);
|
||||||
|
|
||||||
|
bgfx::setTransform(mtx3);
|
||||||
|
|
||||||
|
bgfx::setVertexBuffer(0, vbh);
|
||||||
|
bgfx::setIndexBuffer(ibh);
|
||||||
|
|
||||||
|
bgfx::setTexture(0, s_texColor, tex);
|
||||||
|
|
||||||
|
bgfx::setState(state);
|
||||||
|
bgfx::submit(0, pg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawTextureImage(const bgfx::TextureHandle& tex, i32 pos_x, i32 pos_y, u32 w, u32 h) {
|
||||||
|
DrawTexture(tex, pos_x, pos_y, w, h, BGFX_STATE_DEFAULT | BGFX_STATE_BLEND_NORMAL, img_program);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawTextureImage(const ImageTexture& img, i32 pos_x, i32 pos_y) {
|
||||||
|
DrawTextureImage(img.tx, pos_x, pos_y, img.w, img.h);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImageTexture* GetImageTextureFromFile(const std::string& file) {
|
||||||
|
if (imgs.find(file) == imgs.end()) {
|
||||||
|
ImageTexture img;
|
||||||
|
if (auto i = get_image_texture(file)) {
|
||||||
|
img = *i;
|
||||||
|
imgs[file] = std::move(img);
|
||||||
|
return &imgs[file];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawTextureStencilAlpha(const bgfx::TextureHandle& tex, i32 pos_x, i32 pos_y, u32 w, u32 h) {
|
||||||
|
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 RenderString(const NVL::String& s, u32& pos_x, u32& pos_y, u32 col, u32 style_flags) {
|
||||||
|
Font* f = ®ular;
|
||||||
|
switch (style_flags) {
|
||||||
|
case TEXT_NONE: break;
|
||||||
|
case TEXT_BOLD: f = &bold; break;
|
||||||
|
case TEXT_ITALIC: break;
|
||||||
|
case TEXT_ITALIC | TEXT_BOLD: break;
|
||||||
|
}
|
||||||
|
|
||||||
|
FT_GlyphSlot& slot = f->face->glyph;
|
||||||
|
for (const auto& c : s) {
|
||||||
|
f->cache_char(c);
|
||||||
|
|
||||||
pos_x += slot->bitmap_left;
|
pos_x += slot->bitmap_left;
|
||||||
float ypos = pos_y - (slot->bitmap.rows - slot->bitmap_top);
|
float ypos = pos_y - (slot->bitmap.rows - slot->bitmap_top);
|
||||||
|
|
||||||
if (slot->bitmap.width != 0) {
|
if (slot->bitmap.width != 0) {
|
||||||
DrawTextureStencilAlpha((*cache)[c], pos_x, ypos, slot->bitmap.width, slot->bitmap.rows);
|
DrawTextureStencilAlpha((f->cache)[c], pos_x, ypos, slot->bitmap.width, slot->bitmap.rows);
|
||||||
}
|
}
|
||||||
|
|
||||||
pos_x += slot->advance.x >> 6;
|
pos_x += slot->advance.x >> 6;
|
||||||
|
@ -308,8 +337,7 @@ namespace ADVect::Graphics {
|
||||||
RenderString(str.substr(ms.back().end), pos_x, pos_y, col, TEXT_NONE);
|
RenderString(str.substr(ms.back().end), pos_x, pos_y, col, TEXT_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawRandomShit() {
|
void DrawFunkyAhhShit() {
|
||||||
|
DrawTextureImage(bg, 0, -40);
|
||||||
DrawTexture(tx, 0, -40, w, h);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
#include <Environment.h>
|
#include <Environment.h>
|
||||||
|
|
||||||
namespace ADVect::Graphics {
|
namespace ADVect::Graphics {
|
||||||
i16 Init(u16 width, u16 height);
|
bool Init(u16 width, u16 height);
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
|
|
||||||
enum MarkupStyle {
|
enum MarkupStyle {
|
||||||
|
@ -18,12 +18,21 @@ namespace ADVect::Graphics {
|
||||||
TEXT_OVERLINE = 1 << 4
|
TEXT_OVERLINE = 1 << 4
|
||||||
};
|
};
|
||||||
|
|
||||||
void DrawTexture(const bgfx::TextureHandle& tex, i32 pos_x, i32 pos_y, u32 w, u32 h);
|
struct ImageTexture {
|
||||||
|
i32 w, h, channels;
|
||||||
|
u8* buffer;
|
||||||
|
bgfx::TextureHandle tx;
|
||||||
|
};
|
||||||
|
ImageTexture* GetImageTextureFromFile(const std::string& file);
|
||||||
|
|
||||||
|
void DrawTexture(const bgfx::TextureHandle& tex, i32 pos_x, i32 pos_y, u32 w, u32 h, u64 state, const bgfx::ProgramHandle& pg);
|
||||||
|
void DrawTextureImage(const bgfx::TextureHandle& tex, i32 pos_x, i32 pos_y, u32 w, u32 h);
|
||||||
|
void DrawTextureImage(const ImageTexture& img, i32 pos_x, i32 pos_y);
|
||||||
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 RenderString(const NVL::String& s, u32& pos_x, u32& pos_y, u32 col, u32 style_flags);
|
void RenderString(const NVL::String& s, u32& pos_x, u32& pos_y, u32 col, u32 style_flags);
|
||||||
void RenderString(const NVL::String& s, u32&& pos_x, u32&& pos_y, u32 col, u32 style_flags);
|
void RenderString(const NVL::String& s, u32&& pos_x, u32&& pos_y, u32 col, u32 style_flags);
|
||||||
void RenderStringMarkup(const std::vector<NVL::Environment::Variable>& s, u32 pos_x, u32 pos_y, u32 col);
|
void RenderStringMarkup(const std::vector<NVL::Environment::Variable>& s, u32 pos_x, u32 pos_y, u32 col);
|
||||||
|
|
||||||
void DrawRandomShit();
|
void DrawFunkyAhhShit();
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ cmake_minimum_required (VERSION 3.8)
|
||||||
|
|
||||||
project (NVL)
|
project (NVL)
|
||||||
include_directories("include")
|
include_directories("include")
|
||||||
add_library (NVL STATIC "NouVeL.cpp" "Parser.cpp" "Environment.cpp" "Environment.h" "Common.h")
|
add_library (NVL STATIC "Parser.cpp" "Environment.cpp" "Environment.h" "Common.h")
|
||||||
# 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.
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
static_assert(sizeof(float) == 4);
|
||||||
|
static_assert(sizeof(double) == 8);
|
||||||
typedef float f32;
|
typedef float f32;
|
||||||
typedef double f64;
|
typedef double f64;
|
||||||
typedef int8_t i8;
|
typedef int8_t i8;
|
||||||
|
|
|
@ -29,9 +29,8 @@ namespace NVL::Environment {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Environment::enter(const String& name, Variable p) {
|
void Environment::enter(const String& name, Variable p) {
|
||||||
if (env.find(name) != env.end())
|
if (!env.emplace(name, p).second)
|
||||||
throw std::runtime_error("Redefinition of symbol in environment");
|
throw std::runtime_error("Redefinition of symbol in environment");
|
||||||
env.emplace(name, p);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Environment::set(const String& name, Variable p) {
|
void Environment::set(const String& name, Variable p) {
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
#if 0
|
|
||||||
#include <string>
|
|
||||||
#include <iostream>
|
|
||||||
#include <sstream>
|
|
||||||
#include "Parser.h"
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
const std::string PJ_DIR = "E:\\Archive\\Projects\\NouVeL\\NVL\\";
|
|
||||||
std::vector<NVL::Parse::Scene> SCENES = NVL::Parse::ParseFile(PJ_DIR + "dialogue.nvl");
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -15,20 +15,20 @@ namespace {
|
||||||
using namespace NVL;
|
using namespace NVL;
|
||||||
|
|
||||||
struct ParseGroup {
|
struct ParseGroup {
|
||||||
String accept;
|
const String accept;
|
||||||
|
|
||||||
constexpr operator String() const {
|
operator String() const {
|
||||||
return accept;
|
return accept;
|
||||||
}
|
}
|
||||||
constexpr bool operator== (const String& other) const {
|
bool operator== (const String& other) const {
|
||||||
return accept == other;
|
return accept == other;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Match {
|
struct Match {
|
||||||
String accept;
|
const String accept;
|
||||||
|
|
||||||
constexpr operator Char() const {
|
operator Char() const {
|
||||||
if (accept.length() == 1)
|
if (accept.length() == 1)
|
||||||
return accept[0];
|
return accept[0];
|
||||||
else {
|
else {
|
||||||
|
@ -36,28 +36,28 @@ namespace {
|
||||||
return '\0';
|
return '\0';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
constexpr bool operator== (const String& other) const {
|
bool operator== (const String& other) const {
|
||||||
return accept == other;
|
return accept == other;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const ParseGroup NUMERIC = { u"1234567890" };
|
const ParseGroup NUMERIC { u"1234567890" };
|
||||||
const Match DECIMAL_DOT = { u"." };
|
const Match DECIMAL_DOT { u"." };
|
||||||
const Match NEGATIVE = { u"-" };
|
const Match NEGATIVE { u"-" };
|
||||||
const ParseGroup ALPHA = { u"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" };
|
const ParseGroup ALPHA { u"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" };
|
||||||
const Match ARRAY_OPEN = { u"[" };
|
const Match ARRAY_OPEN { u"[" };
|
||||||
const Match ARRAY_CLOSE = { u"]" };
|
const Match ARRAY_CLOSE { u"]" };
|
||||||
const Match ARRAY_DELIM = { u"," };
|
const Match ARRAY_DELIM { u"," };
|
||||||
const Match GROUP_OPEN = { u"(" };
|
const Match GROUP_OPEN { u"(" };
|
||||||
const Match GROUP_CLOSE = { u")" };
|
const Match GROUP_CLOSE { u")" };
|
||||||
const Match QUOTE = { u"\"" };
|
const Match QUOTE { u"\"" };
|
||||||
const Match COMMENT_BEGIN = { u"//" };
|
const Match COMMENT_BEGIN { u"//" };
|
||||||
const Match DIALOGUE_OPEN = { u"<<-" };
|
const Match DIALOGUE_OPEN { u"<<-" };
|
||||||
const Match DIALOGUE_CLOSE = { u"->>" };
|
const Match DIALOGUE_CLOSE { u"->>" };
|
||||||
const Match BEGIN = { u"BEGIN" };
|
const Match BEGIN { u"BEGIN" };
|
||||||
const Match END = { u"END" };
|
const Match END { u"END" };
|
||||||
const ParseGroup SYMBOL = { ALPHA.accept + NUMERIC.accept + u"_"};
|
const ParseGroup SYMBOL { ALPHA.accept + NUMERIC.accept + u"_"};
|
||||||
const Match SPECIAL_SYMBOLS[] = {
|
const Match SPECIAL_SYMBOLS[] {
|
||||||
{ u"+" },
|
{ u"+" },
|
||||||
{ u"-" },
|
{ u"-" },
|
||||||
{ u"*" },
|
{ u"*" },
|
||||||
|
@ -68,34 +68,35 @@ namespace {
|
||||||
{ u"<=?" },
|
{ u"<=?" },
|
||||||
{ u">=?" }
|
{ u">=?" }
|
||||||
};
|
};
|
||||||
const ParseGroup WS = { u" \t\v\f\r\n" };
|
const ParseGroup WS { u" \t\v\f\r\n" };
|
||||||
const ParseGroup SEPARATOR = {
|
const ParseGroup SEPARATOR {
|
||||||
WS.accept +
|
WS.accept +
|
||||||
Char(ARRAY_OPEN) +
|
Char(ARRAY_OPEN) +
|
||||||
Char(ARRAY_CLOSE) +
|
Char(ARRAY_CLOSE) +
|
||||||
Char(GROUP_OPEN) +
|
Char(GROUP_OPEN) +
|
||||||
Char(GROUP_CLOSE) +
|
Char(GROUP_CLOSE) +
|
||||||
Char(ARRAY_DELIM) +
|
Char(ARRAY_DELIM) +
|
||||||
COMMENT_BEGIN.accept[0]
|
COMMENT_BEGIN.accept[0] +
|
||||||
|
u'\0'
|
||||||
};
|
};
|
||||||
const Match NEWLINE = { u"\n" };
|
const Match NEWLINE { u"\n" };
|
||||||
const ParseGroup ESCAPED = { u"\\\"" };
|
const ParseGroup ESCAPED { u"\\\"" };
|
||||||
|
|
||||||
const Match ESCAPE = { u"\\" };
|
const Match ESCAPE { u"\\" };
|
||||||
|
|
||||||
// Dialogue mode matches
|
// Dialogue mode matches
|
||||||
const Match MARKUP_OPEN = { u"[" };
|
const Match MARKUP_OPEN { u"[" };
|
||||||
const Match MARKUP_CLOSE = { u"]" };
|
const Match MARKUP_CLOSE { u"]" };
|
||||||
const Match SPEAKER_OPEN = { u"[" };
|
const Match SPEAKER_OPEN { u"[" };
|
||||||
const Match SPEAKER_CLOSE = { u"]" };
|
const Match SPEAKER_CLOSE { u"]" };
|
||||||
const Match MARKUP_TEXT_OPEN = { u"{" };
|
const Match MARKUP_TEXT_OPEN { u"{" };
|
||||||
const Match MARKUP_TEXT_CLOSE = { u"}" };
|
const Match MARKUP_TEXT_CLOSE { u"}" };
|
||||||
const Match TEMPLATE_IND = { u"$" };
|
const Match TEMPLATE_IND { u"$" };
|
||||||
const Match TEMPLATE_OPEN = { u"{" };
|
const Match TEMPLATE_OPEN { u"{" };
|
||||||
const Match TEMPLATE_CLOSE = { u"}" };
|
const Match TEMPLATE_CLOSE { u"}" };
|
||||||
|
|
||||||
const Match COMMAND_ESCAPE = { u"*!" };
|
const Match COMMAND_ESCAPE { u"*!" };
|
||||||
const ParseGroup DIALOGUE_ESCAPED_SINGLE = {
|
const ParseGroup DIALOGUE_ESCAPED_SINGLE {
|
||||||
ESCAPE.accept +
|
ESCAPE.accept +
|
||||||
Char(MARKUP_OPEN) +
|
Char(MARKUP_OPEN) +
|
||||||
Char(MARKUP_CLOSE) +
|
Char(MARKUP_CLOSE) +
|
||||||
|
@ -344,15 +345,13 @@ namespace {
|
||||||
*/
|
*/
|
||||||
Parse::Object MatchMarkup(String& s) {
|
Parse::Object MatchMarkup(String& s) {
|
||||||
static const srell::basic_regex<Char>
|
static const srell::basic_regex<Char>
|
||||||
typer(uR"((?:^|[^\\])\[([^\]]+)\]\s*\{([^\}]+)\})"), // G1 -> Specifiers, G2 -> Contents
|
typer(uR"((?<!\\)\[([^\]]+)\]\s*\{([^\}]+)\})"), // G1 -> Specifiers, G2 -> Contents
|
||||||
effect(uR"(\s*(?:([^,\(\)]+?)\s*\(\s*([^\(\)]+?)\s*\)|([^,\(\)]+?))\s*(?:,\s*|$))"), // G1 & G2 -> Func, G3 -> Attr
|
effect(uR"(\s*(?:([^,\(\)]+?)\s*\(\s*([^\(\)]+?)\s*\)|([^,\(\)]+?))\s*(?:,\s*|$))"), // G1 & G2 -> Func, G3 -> Attr
|
||||||
param(uR"(([^,]+?)\s*(?:,\s*|$))"); // Comma split of func args
|
param(uR"(([^,]+?)\s*(?:,\s*|$))"); // Comma split of func args
|
||||||
|
|
||||||
std::vector<Parse::Object> tags;
|
std::vector<Parse::Object> tags;
|
||||||
|
|
||||||
srell::match_results<String::const_iterator> tags_match;
|
srell::match_results<String::const_iterator> tags_match, effects_match, params_match;
|
||||||
srell::match_results<String::const_iterator> effects_match;
|
|
||||||
srell::match_results<String::const_iterator> params_match;
|
|
||||||
|
|
||||||
String reconstruction{};
|
String reconstruction{};
|
||||||
|
|
||||||
|
@ -365,9 +364,9 @@ namespace {
|
||||||
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;
|
||||||
Parse::Object m{ Parse::Type::Array, std::vector<Parse::Object>{} };
|
Parse::Object m{ Parse::Type::Array, std::vector<Parse::Object>{} };
|
||||||
reconstruction.append(tags_match.prefix().first, std::next(tags_match[0].first, 1)); // match will overmatch behind by 1
|
reconstruction.append(tags_match.prefix().first, tags_match[0].first);
|
||||||
reconstruction.append(tags_match[2].first, tags_match[2].second);
|
reconstruction.append(tags_match[2].first, tags_match[2].second);
|
||||||
running_offset += tags_match[2].first - std::next(tags_match[0].first, 1);
|
running_offset += tags_match[2].first - tags_match[0].first;
|
||||||
|
|
||||||
size_t begin = tags_match[2].first - s.cbegin() - running_offset;
|
size_t begin = tags_match[2].first - s.cbegin() - running_offset;
|
||||||
|
|
||||||
|
@ -452,6 +451,7 @@ namespace {
|
||||||
|
|
||||||
bool dialogue_mode = false;
|
bool dialogue_mode = false;
|
||||||
|
|
||||||
|
SkipComments(f, pos);
|
||||||
while (PeekToken(f, pos) != END.accept) {
|
while (PeekToken(f, pos) != END.accept) {
|
||||||
if (!dialogue_mode)
|
if (!dialogue_mode)
|
||||||
if (PeekToken(f, pos) == DIALOGUE_OPEN.accept) {
|
if (PeekToken(f, pos) == DIALOGUE_OPEN.accept) {
|
||||||
|
|
35
NVL/dante_ch.nvl
Normal file
35
NVL/dante_ch.nvl
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
BEGIN Inferno
|
||||||
|
ImageTrack BG
|
||||||
|
Show BG "image.png"
|
||||||
|
<<-
|
||||||
|
[但丁]
|
||||||
|
由我这里,直通[b]{悲惨之城}。
|
||||||
|
由我这里,直通[b]{无尽之苦}。
|
||||||
|
由我这里,直通[b]{堕落众生}。
|
||||||
|
圣裁于高天激发造我的君主;
|
||||||
|
造我的大能是[b, rb("C")]{神}的力量,是无上的[b, rb(" L L V M")]{智慧与众爱}所自出。
|
||||||
|
我永远不朽;在我之前,万象 未形,只有永恒的事物存在。
|
||||||
|
来者呀,快把一切希望弃扬。
|
||||||
|
我所见到的文字,毫无光彩, 用暗色刻在地狱之门的高处。
|
||||||
|
老师呀,讲得真可骇。
|
||||||
|
[维吉尔]
|
||||||
|
一切疑虑,必须在这里摆脱。
|
||||||
|
一切怯懦,必须在这里结束。
|
||||||
|
这个地方,我已经向你解说。
|
||||||
|
悲惨的群伦,你会在这里看见。
|
||||||
|
他们都享受不到心智的成果。
|
||||||
|
[]
|
||||||
|
维吉尔说完,就按着我的手,其和颜使我放心。
|
||||||
|
然后,他把我带到 凡眸不能目睹的景物之前。
|
||||||
|
那里,叹息、恸哭、凄厉的嚎咷 在星光全无的空中回荡旋涌。
|
||||||
|
起先,这景象使我哭泣哀号。
|
||||||
|
陌生的语言、可怕的话声、各种充满痛苦的言辞、愤怒的腔调、尖厉而沙哑的嗓子和众手乱动乱打的巨响,在骚然涡转咆哮,在无始无终的幽冥中永不休止,就像风沙在回飙里疾旋急搅。
|
||||||
|
[但丁]
|
||||||
|
老师呀,这是什么声音? 听起来好像有人在受着凌迟。
|
||||||
|
[维吉尔]
|
||||||
|
这些人处境可悯,他们都是可怜的亡魂,在世上不招闲言,也无令誉可矜。
|
||||||
|
他们跟一群卑鄙的天使同党。
|
||||||
|
这些天使,不是上帝的叛徒或信徒;他们为私利而自成一帮。
|
||||||
|
天穹嫌他们不够好,把他们放逐; 深坑呢,又不愿给他们栖身之地,怕坏人因此而显得光荣突出。
|
||||||
|
->>
|
||||||
|
END
|
52
NVL/dante_de.nvl
Normal file
52
NVL/dante_de.nvl
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
BEGIN Inferno
|
||||||
|
|
||||||
|
ImageTrack BG
|
||||||
|
Show BG "image.png"
|
||||||
|
|
||||||
|
<<-
|
||||||
|
[]
|
||||||
|
Durch mich geht’s ein zur Stadt der Qualerkornen,
|
||||||
|
Durch mich geht’s ein zum ew’gen Weheschlund,
|
||||||
|
Durch mich geht’s ein zum Volke der Verlornen.
|
||||||
|
Das Recht war meines hohen Schöpfers Grund;
|
||||||
|
Die Allmacht wollt’ in mir sich offenbaren;
|
||||||
|
Allweisheit ward und erste Liebe kund.
|
||||||
|
Die schon vor mir erschaffnen Dinge waren
|
||||||
|
Nur ewige; und ewig daur’ auch ich.
|
||||||
|
[b]{Laßt}, die ihr eingeht jede [b, rb(" H o p e")]{Hoffnung} fahren.
|
||||||
|
Die Inschrift zeigt’ in dunkler Farbe sich
|
||||||
|
Geschrieben dort am Gipfel einer Pforte.
|
||||||
|
[Dante]
|
||||||
|
Hart, Meister, ist ihr Sinn für mich.
|
||||||
|
[Virgil]
|
||||||
|
Hier sei jedweder Argwohn weggebannt,
|
||||||
|
Und jede Feigheit sterb’ an diesem Orte.
|
||||||
|
Wir sind zur Stelle, die ich dir genannt,
|
||||||
|
Hier wirst du jene Jammervollen schauen,
|
||||||
|
Für die das Heil des wahren Lichtes schwand.
|
||||||
|
[]
|
||||||
|
Er faßte meine Hand, daher Vertrauen
|
||||||
|
Durch sein Gesicht voll Mut auch ich gewann.
|
||||||
|
Drauf führt’ er mich in das geheime Grauen.
|
||||||
|
Dort hob Geächz, Geschrei und Klagen an,
|
||||||
|
Laut durch die sternenlose Luft ertönend,
|
||||||
|
So daß ich selber weinte, da’s begann.
|
||||||
|
Verschiedne Sprachen, Worte, gräßlich dröhnend,
|
||||||
|
Handschläge, Klänge heiseren Geschreis,
|
||||||
|
Die Wut, aufkreischend, und der Schmerz, erstöhnend –
|
||||||
|
Und, ich vom Wahn umstrickt und bang im Herzen
|
||||||
|
[Dante]
|
||||||
|
Meister, welch Geschrei, das sich erhebt?
|
||||||
|
Wer ist doch hier so ganz besiegt von Schmerzen?
|
||||||
|
[Virgil]
|
||||||
|
Der Klang, der durch die Lüfte bebt,
|
||||||
|
Kommt von den Jammerseelen jener Wesen,
|
||||||
|
Die ohne Schimpf und ohne Lob gelebt.
|
||||||
|
Gemischt sind die Nicht-Guten und Nicht-Bösen
|
||||||
|
Den Engeln, die nicht Gott getreu im Strauß,
|
||||||
|
Auch Meutrer nicht und nur für sich gewesen.
|
||||||
|
Die Himmel trieben sie als Mißzier aus,
|
||||||
|
Und da durch sie der Sünder Stolz erstünde,
|
||||||
|
Nimmt sie nicht ein der tiefen Hölle Graus.
|
||||||
|
->>
|
||||||
|
END
|
8
NVL/nobom.nvl
Normal file
8
NVL/nobom.nvl
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
BEGIN NOBOM
|
||||||
|
<<-
|
||||||
|
[Test]
|
||||||
|
This shouldn't throw.
|
||||||
|
Honestly!!
|
||||||
|
fix it
|
||||||
|
->>
|
||||||
|
END
|
Loading…
Add table
Reference in a new issue