Begin VN scene parser
This commit is contained in:
36
assets/games/pokergame/vn/Scene_1.xml
Normal file
36
assets/games/pokergame/vn/Scene_1.xml
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<vnscene>
|
||||||
|
<head>
|
||||||
|
<!-- Includes -->
|
||||||
|
<include path="visualnovel/scene/SimpleVNScene.hpp" />
|
||||||
|
<include path="prefabs/characters/DeathPrefab.hpp" />
|
||||||
|
|
||||||
|
<!-- <include scene="Scene_2" /> -->
|
||||||
|
|
||||||
|
<!-- Characters -->
|
||||||
|
<character class="DeathPrefab" name="death" />
|
||||||
|
|
||||||
|
<!-- Extra Assets -->
|
||||||
|
<asset type="AudioAsset" name="audio_test" />
|
||||||
|
|
||||||
|
<!-- Scene -->
|
||||||
|
<scene type="SimpleVNScene" name="Scene_1" />
|
||||||
|
|
||||||
|
<!-- Defaults -->
|
||||||
|
<!-- <default type="animation-curve">out-quad</default> -->
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<!-- Some other ideas I had:
|
||||||
|
<methods>
|
||||||
|
<method type="void" name="onSceneEnded">
|
||||||
|
// Literal CPP code here.
|
||||||
|
</method>
|
||||||
|
</methods>
|
||||||
|
-->
|
||||||
|
|
||||||
|
<events>
|
||||||
|
<pause duration="0.1" />
|
||||||
|
<text character="death" emotion="happy" string="scene.1.1" />
|
||||||
|
<character-fade character="death" duration="1.0" ease="out-quad" />
|
||||||
|
<scene-transition scene="Scene_2" />
|
||||||
|
</events>
|
||||||
|
</vnscene>
|
@ -1,36 +0,0 @@
|
|||||||
# This is a sample VN Scene that I am creating to create a scene generator.
|
|
||||||
# The scene generator will simply create a series of events, nothing more.
|
|
||||||
# Infact, the scene generator really is just a scene event with trailed events
|
|
||||||
# Generator.
|
|
||||||
|
|
||||||
# Scene name is probably going to be inherited from either the target or the
|
|
||||||
# filename
|
|
||||||
|
|
||||||
# By default the mode we are in is in TEXT mode, unless you explicitly change
|
|
||||||
# the mode. The text mode takes the person, emotion and text string and tries
|
|
||||||
# to convert it to this C++ equivallent code;
|
|
||||||
# new VisualNovelTextboxEvent(vnManager, this->[person]->vnCharacter, this->[person]->[emotion], [text])
|
|
||||||
|
|
||||||
# Here is our first example. We take death, give her an emotion, and write some
|
|
||||||
# text.
|
|
||||||
death:happy: scene.1.1
|
|
||||||
|
|
||||||
# Here, we inherit the existing emotion. I've also omitted the space because it
|
|
||||||
# is just there for show.
|
|
||||||
death:scene.1.1
|
|
||||||
|
|
||||||
# Now let's fade our character in. Fade char in events start like this
|
|
||||||
fade death in quad over 1.0
|
|
||||||
# Could also be written like any of these
|
|
||||||
# fade death out
|
|
||||||
# fade death in
|
|
||||||
# fade death out over 1.0 seconds
|
|
||||||
# fade death in over 1.0 seconds
|
|
||||||
# fade death in linear
|
|
||||||
# fade death out linear over 10 seconds
|
|
||||||
# fade death out over 10
|
|
||||||
# Basically the format just needs to be
|
|
||||||
# fade [character] [in/out] (easing function) (time)
|
|
||||||
# Each time a fade occurs the parameters will be remembered, and used for any
|
|
||||||
# other fade after that, so you just need to define the easing curve once per
|
|
||||||
# scene.
|
|
@ -39,6 +39,8 @@ tool_truetype(truetype_alice ${DIR_GAME_ASSETS}/font/Alice-Regular.ttf truetype_
|
|||||||
|
|
||||||
tool_audio(audio_test borrowed/sample_short.wav)
|
tool_audio(audio_test borrowed/sample_short.wav)
|
||||||
|
|
||||||
|
tool_vnscene(vnscene_1 ${DIR_GAME_ASSETS}/vn/Scene_1.xml)
|
||||||
|
|
||||||
add_dependencies(${DAWN_TARGET_NAME}
|
add_dependencies(${DAWN_TARGET_NAME}
|
||||||
locale_poker
|
locale_poker
|
||||||
|
|
||||||
@ -50,4 +52,6 @@ add_dependencies(${DAWN_TARGET_NAME}
|
|||||||
texture_test
|
texture_test
|
||||||
|
|
||||||
audio_test
|
audio_test
|
||||||
|
|
||||||
|
vnscene_1
|
||||||
)
|
)
|
@ -11,8 +11,6 @@
|
|||||||
#include "visualnovel/events/characters/VisualNovelTransformItemEvent.hpp"
|
#include "visualnovel/events/characters/VisualNovelTransformItemEvent.hpp"
|
||||||
#include "visualnovel/events/timing/VisualNovelBatchEvent.hpp"
|
#include "visualnovel/events/timing/VisualNovelBatchEvent.hpp"
|
||||||
|
|
||||||
#include "ui_test.hpp"
|
|
||||||
|
|
||||||
namespace Dawn {
|
namespace Dawn {
|
||||||
class Scene_1 : public SimpleVNScene {
|
class Scene_1 : public SimpleVNScene {
|
||||||
protected:
|
protected:
|
||||||
@ -22,10 +20,6 @@ namespace Dawn {
|
|||||||
|
|
||||||
this->death = DeathPrefab::create(this);
|
this->death = DeathPrefab::create(this);
|
||||||
this->death->material->color.a = 0;
|
this->death->material->color.a = 0;
|
||||||
// this->death->transform.setLocalPosition(glm::vec3(-100, 0, 0));
|
|
||||||
|
|
||||||
auto item = this->canvas->addElement<UITest>();
|
|
||||||
item->setTransform(UI_COMPONENT_ALIGN_STRETCH, UI_COMPONENT_ALIGN_STRETCH, glm::vec4(0, 0, 0, 0), 0.0f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void onSceneEnded() {
|
void onSceneEnded() {
|
||||||
|
@ -27,7 +27,10 @@ int32_t xmlLoadChild(xml_t *xml, char *data, int32_t i) {
|
|||||||
// Look for either an opening tag (<) or a word for a value.
|
// Look for either an opening tag (<) or a word for a value.
|
||||||
if(c == '>') continue;
|
if(c == '>') continue;
|
||||||
if(c == '<') {
|
if(c == '<') {
|
||||||
if(insideTag) {
|
if(data[i] == '!' && data[i+1] == '-') {
|
||||||
|
doing = XML_PARSING_COMMENT;
|
||||||
|
i += 2;
|
||||||
|
} else if(insideTag) {
|
||||||
i = xmlLoadChild(xml->children + xml->childrenCount++, data, i-1);
|
i = xmlLoadChild(xml->children + xml->childrenCount++, data, i-1);
|
||||||
doing = XML_PARSING_CHILD;
|
doing = XML_PARSING_CHILD;
|
||||||
} else {
|
} else {
|
||||||
@ -161,6 +164,13 @@ int32_t xmlLoadChild(xml_t *xml, char *data, int32_t i) {
|
|||||||
free(buffer);
|
free(buffer);
|
||||||
return i;
|
return i;
|
||||||
|
|
||||||
|
case XML_PARSING_COMMENT:
|
||||||
|
if(c != '-') continue;
|
||||||
|
if(data[i] != '-') continue;
|
||||||
|
if(data[i+1] != '>') continue;
|
||||||
|
i+= 2;
|
||||||
|
doing = XML_DOING_NOTHING;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#define XML_PARSING_VALUE 0x06
|
#define XML_PARSING_VALUE 0x06
|
||||||
#define XML_PARSING_CHILD 0x07
|
#define XML_PARSING_CHILD 0x07
|
||||||
#define XML_PARSING_CLOSE 0x08
|
#define XML_PARSING_CLOSE 0x08
|
||||||
|
#define XML_PARSING_COMMENT 0x09
|
||||||
|
|
||||||
#define XML_TEXT_BUFFER_MAX 2048
|
#define XML_TEXT_BUFFER_MAX 2048
|
||||||
#define XML_CHILD_COUNT_MAX 128
|
#define XML_CHILD_COUNT_MAX 128
|
||||||
|
@ -3,4 +3,17 @@
|
|||||||
# This software is released under the MIT License.
|
# This software is released under the MIT License.
|
||||||
# https://opensource.org/licenses/MIT
|
# https://opensource.org/licenses/MIT
|
||||||
|
|
||||||
add_subdirectory(vnscenegen)
|
add_subdirectory(vnscenegen)
|
||||||
|
|
||||||
|
# UI Tool
|
||||||
|
function(tool_vnscene target in)
|
||||||
|
add_custom_target(${target}
|
||||||
|
COMMAND vnscenegen "${DAWN_ASSETS_SOURCE_DIR}/${in}" "${DAWN_GENERATED_DIR}/scenes/${target}"
|
||||||
|
COMMENT "Generating VN Scene ${target} from ${in}"
|
||||||
|
DEPENDS vnscenegen
|
||||||
|
)
|
||||||
|
target_include_directories(${DAWN_TARGET_NAME}
|
||||||
|
PUBLIC
|
||||||
|
${DAWN_GENERATED_DIR}/scenes
|
||||||
|
)
|
||||||
|
endfunction()
|
@ -10,6 +10,7 @@ target_sources(vnscenegen
|
|||||||
PRIVATE
|
PRIVATE
|
||||||
main.cpp
|
main.cpp
|
||||||
../../utils/file.c
|
../../utils/file.c
|
||||||
|
../../utils/xml.c
|
||||||
)
|
)
|
||||||
target_include_directories(vnscenegen
|
target_include_directories(vnscenegen
|
||||||
PUBLIC
|
PUBLIC
|
||||||
|
@ -5,11 +5,199 @@
|
|||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include "../../utils/file.h"
|
#include "../../utils/file.h"
|
||||||
|
#include "../../utils/xml.h"
|
||||||
#include <memory.h>
|
#include <memory.h>
|
||||||
}
|
}
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
struct CharacterInformation {
|
||||||
|
std::string clazz;
|
||||||
|
std::string name;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Asset {
|
||||||
|
std::string type;
|
||||||
|
std::string name;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct HeaderInformation {
|
||||||
|
std::string type;
|
||||||
|
std::string name;
|
||||||
|
std::vector<std::string> includes;
|
||||||
|
std::vector<struct CharacterInformation> characters;
|
||||||
|
std::vector<struct Asset> assets;
|
||||||
|
};
|
||||||
|
|
||||||
|
int32_t parseInclude(struct HeaderInformation *info, xml_t *node) {
|
||||||
|
auto attrPath = xmlGetAttributeByName(node, "path");
|
||||||
|
if(attrPath == -1) {
|
||||||
|
std::cout << "Missing include path in VN Header Defintions." << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
info->includes.push_back(node->attributeDatas[attrPath]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t parseCharacter(struct HeaderInformation *info, xml_t *node) {
|
||||||
|
auto attrClass = xmlGetAttributeByName(node, "class");
|
||||||
|
if(attrClass == -1) {
|
||||||
|
std::cout << "Character definition is missing class" << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto attrName = xmlGetAttributeByName(node, "name");
|
||||||
|
if(attrName == -1) {
|
||||||
|
std::cout << "Character definition is missing name" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CharacterInformation character;
|
||||||
|
character.clazz = std::string(node->attributeDatas[attrClass]);
|
||||||
|
character.name = std::string(node->attributeDatas[attrName]);
|
||||||
|
info->characters.push_back(character);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t parseScene(struct HeaderInformation *info, xml_t *node) {
|
||||||
|
auto attrName = xmlGetAttributeByName(node, "name");
|
||||||
|
if(attrName == -1) {
|
||||||
|
std::cout << "VN Scene <scene> definition is missing name attribute" << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
info->name = std::string(node->attributeDatas[attrName]);
|
||||||
|
|
||||||
|
auto attrType = xmlGetAttributeByName(node, "type");
|
||||||
|
if(attrType == -1) {
|
||||||
|
info->type = "SimpleVNScene";
|
||||||
|
} else {
|
||||||
|
info->type = std::string(node->attributeDatas[attrType]);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t parseAsset(struct HeaderInformation *info, xml_t *node) {
|
||||||
|
auto attrType = xmlGetAttributeByName(node, "type");
|
||||||
|
if(attrType == -1) {
|
||||||
|
std::cout << "VN Scene Asset missing type attribute" << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
auto attrName = xmlGetAttributeByName(node, "name");
|
||||||
|
if(attrName == -1) {
|
||||||
|
std::cout << "VN Scene Asset missing name attribute" << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Asset ass;
|
||||||
|
ass.type = std::string(node->attributeDatas[attrType]);
|
||||||
|
ass.name = std::string(node->attributeDatas[attrName]);
|
||||||
|
info->assets.push_back(ass);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t parseHeader(struct HeaderInformation *info, xml_t *node) {
|
||||||
|
for(int32_t i = 0; i < node->childrenCount; i++) {
|
||||||
|
auto c = node->children + i;
|
||||||
|
auto n = std::string(c->node);
|
||||||
|
int32_t ret = 0;
|
||||||
|
|
||||||
|
std::cout << n << std::endl;
|
||||||
|
|
||||||
|
if(n == "include") {
|
||||||
|
ret = parseInclude(info, c);
|
||||||
|
} else if(n == "character") {
|
||||||
|
ret = parseCharacter(info, c);
|
||||||
|
} else if(n == "scene") {
|
||||||
|
ret = parseScene(info, c);
|
||||||
|
} else if (n == "asset") {
|
||||||
|
ret = parseAsset(info, c);
|
||||||
|
} else {
|
||||||
|
std::cout << "Parsing VN Scene header, unknown node " << n << std::endl;
|
||||||
|
}
|
||||||
|
if(ret != 0) return ret;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int main(int32_t argc, char *args[]) {
|
int main(int32_t argc, char *args[]) {
|
||||||
|
if(argc != 3) {
|
||||||
|
std::cout << "Invalid number of args passed to VNScene Generator" << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open input file.
|
||||||
|
char fileIn[FILENAME_MAX];
|
||||||
|
fileNormalizeSlashes(args[1]);
|
||||||
|
sprintf(fileIn, "%s", args[1]);
|
||||||
|
FILE *fin = fopen(fileIn, "rb");
|
||||||
|
if(fin == NULL) {
|
||||||
|
std::cout << "Failed to open input file " << fileIn << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tell file len
|
||||||
|
auto len = assetReadString(fin, NULL);
|
||||||
|
|
||||||
|
// Read data.
|
||||||
|
char *buffer = (char *)malloc(sizeof(char) * (len + 1));
|
||||||
|
if(buffer == NULL) {
|
||||||
|
std::cout << "Failed to create temporary memory." << std::endl;
|
||||||
|
fclose(fin);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
assetReadString(fin, buffer);
|
||||||
|
fclose(fin);
|
||||||
|
|
||||||
|
// Parse XML
|
||||||
|
xml_t xml;
|
||||||
|
xmlLoad(&xml, buffer);
|
||||||
|
free(buffer);
|
||||||
|
|
||||||
|
// First, read the header information
|
||||||
|
struct HeaderInformation header;
|
||||||
|
for(int32_t i = 0; i < xml.childrenCount; i++) {
|
||||||
|
auto child = xml.children + i;
|
||||||
|
if(std::string(child->node) != "head") continue;
|
||||||
|
auto ret = parseHeader(&header, child);
|
||||||
|
if(ret != 0) {
|
||||||
|
xmlDispose(&xml);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate header
|
||||||
|
if(header.name.size() == 0 || header.type.size() == 0) {
|
||||||
|
std::cout << "VN Scene header wasn't parsed properly." << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string bufferOut;
|
||||||
|
bufferOut += "#pragma once\n";
|
||||||
|
auto itInclude = header.includes.begin();
|
||||||
|
while(itInclude != header.includes.end()) {
|
||||||
|
bufferOut += "#include \"" + (*itInclude) + "\"\n";
|
||||||
|
++itInclude;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finished with XML data, now we can write data out.
|
||||||
|
xmlDispose(&xml);
|
||||||
|
|
||||||
|
char fileOut[FILENAME_MAX];
|
||||||
|
fileNormalizeSlashes(args[2]);
|
||||||
|
sprintf(fileOut, "%s.hpp", args[2]);
|
||||||
|
fileMkdirp(fileOut);
|
||||||
|
FILE *fout = fopen(fileOut, "wb");
|
||||||
|
if(fout == NULL) {
|
||||||
|
std::cout << "Failed to open output file." << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Buffer out data.
|
||||||
|
const char *bufferOutStr = bufferOut.c_str();
|
||||||
|
fwrite(bufferOutStr, sizeof(char), strlen(bufferOutStr), fout);
|
||||||
|
fclose(fout);
|
||||||
|
std::cout << "Generated Scene " << fileOut << std::endl;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
Reference in New Issue
Block a user