renpy: pause and dissolve
This commit is contained in:
parent
4ead8403f3
commit
bb10732ce1
8
Makefile
8
Makefile
@ -70,6 +70,7 @@ OBJS = \
|
||||
src/tga/tga.o \
|
||||
src/font/outline.o \
|
||||
src/renpy/vulkan.o \
|
||||
src/renpy/composite/vulkan.o \
|
||||
src/renpy/script.o \
|
||||
src/renpy/interpreter.o \
|
||||
src/renpy/interact.o \
|
||||
@ -130,8 +131,8 @@ all: main
|
||||
main: $(OBJS) $(LIBS)
|
||||
$(CC) $(ARCH) $(LDFLAGS) $(FLAGS) $(OPT) $(DEBUG) $^ -o $@
|
||||
|
||||
#%.spv: %.hlsl
|
||||
# ../dxc/bin/dxc -spirv -T lib_6_3 -fspv-target-env=vulkan1.3 $< -Fo $@
|
||||
%.spv: %.hlsl
|
||||
../dxc/bin/dxc -spirv -T lib_6_3 -fspv-target-env=vulkan1.3 $< -Fo $@
|
||||
|
||||
tool/pack_file: tool/pack_file.cpp
|
||||
make -C tool pack_file
|
||||
@ -141,6 +142,9 @@ tool/pack_file: tool/pack_file.cpp
|
||||
|
||||
src/pack.o: files.pack.zlib
|
||||
|
||||
#src/renpy/script.cpp: data/renpy/script.rpy
|
||||
# PYTHONPATH=renpy-parser python -m transform $< > $@
|
||||
|
||||
PACK_FILENAMES = $(shell cat filenames.txt)
|
||||
files.pack: tool/pack_file $(PACK_FILENAMES) filenames.txt
|
||||
./tool/pack_file $@ $(PACK_FILENAMES)
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
# Declare characters used by this game. The color argument colorizes the
|
||||
# name of the character.
|
||||
image bgwhite = "#ffffff"
|
||||
image bgblack = "#000000"
|
||||
image bgforest1 = "bg/forest1.png"
|
||||
image bgforest2 = "bg/forest2.png"
|
||||
image bgflower1 = "bg/flowerfield1.png"
|
||||
@ -62,6 +63,8 @@ label start:
|
||||
#play Chime "sfx/Chime.ogg" fadeout 1.0
|
||||
play sound "sfx/Chime.ogg"
|
||||
play MistAmbience "sfx/MistAmbience.ogg"
|
||||
scene bgblack
|
||||
pause 0.0
|
||||
scene bgwhite
|
||||
with Dissolve(3.0)
|
||||
#play music "IntroMusicTest.ogg"
|
||||
|
||||
@ -2,6 +2,7 @@ shader/font.spv
|
||||
data/font/outline/medieval_sharp_24.data
|
||||
|
||||
shader/renpy.spv
|
||||
shader/renpy_composite.spv
|
||||
data/renpy/images/flowers.dds
|
||||
data/renpy/images/bg/forest1.dds
|
||||
data/renpy/images/bg/forest2.dds
|
||||
|
||||
@ -110,15 +110,15 @@ namespace font::outline {
|
||||
int& outputIndex,
|
||||
int startIndex,
|
||||
int endIndex,
|
||||
uint32_t color);
|
||||
uint32_t color) const;
|
||||
void centered(int frameIndex, char const * const string, uint32_t& x, uint32_t& y,
|
||||
uint32_t minX,
|
||||
uint32_t maxWidth,
|
||||
int& outputIndex,
|
||||
uint32_t color);
|
||||
uint32_t color) const;
|
||||
void draw(VkCommandBuffer commandBuffer,
|
||||
uint32_t frameIndex,
|
||||
renpy::interpreter const& state);
|
||||
renpy::interpreter const& state) const;
|
||||
|
||||
LoadedFont load_font(font_desc const& desc);
|
||||
};
|
||||
|
||||
52
include/renpy/composite/vulkan.h
Normal file
52
include/renpy/composite/vulkan.h
Normal file
@ -0,0 +1,52 @@
|
||||
#pragma once
|
||||
|
||||
namespace renpy::composite {
|
||||
|
||||
struct vulkan {
|
||||
static constexpr int perVertexSize = (4) * 2;
|
||||
|
||||
// externally initialized, opaque handle
|
||||
VkInstance instance;
|
||||
VkDevice device;
|
||||
VkQueue queue;
|
||||
VkCommandPool commandPool;
|
||||
// externally initialized, structures
|
||||
VkPhysicalDeviceProperties physicalDeviceProperties;
|
||||
VkPhysicalDeviceMemoryProperties physicalDeviceMemoryProperties;
|
||||
// externally initialized, enum
|
||||
VkFormat colorFormat;
|
||||
VkFormat depthFormat;
|
||||
VkSampler linearSampler;
|
||||
|
||||
// internal vulkan state
|
||||
VkPipelineLayout pipelineLayout;
|
||||
VkShaderModule shaderModule;
|
||||
VkPipeline pipeline;
|
||||
VertexIndex vertexIndex;
|
||||
|
||||
VkDescriptorPool descriptorPool{ VK_NULL_HANDLE };
|
||||
static constexpr int descriptorSetLayoutCount = 1;
|
||||
VkDescriptorSetLayout descriptorSetLayouts[descriptorSetLayoutCount]; // unrelated to maxFrames, unrelated to descriptorCount
|
||||
VkDescriptorSet descriptorSet0;
|
||||
|
||||
void initial_state(VkInstance instance,
|
||||
VkDevice device,
|
||||
VkQueue queue,
|
||||
VkCommandPool commandPool,
|
||||
VkPhysicalDeviceProperties physicalDeviceProperties,
|
||||
VkPhysicalDeviceMemoryProperties physicalDeviceMemoryProperties,
|
||||
VkFormat colorFormat,
|
||||
VkFormat depthFormat,
|
||||
VkSampler linearSampler);
|
||||
void init();
|
||||
void load_vertex_index_buffer();
|
||||
void load_shader();
|
||||
void create_descriptor_sets();
|
||||
void write_descriptor_sets(VkImageView * imageViews, int imageViewCount);
|
||||
void create_pipeline();
|
||||
void draw(VkCommandBuffer commandBuffer,
|
||||
uint32_t frameIndex,
|
||||
float dissolveLerp,
|
||||
float textLerp);
|
||||
};
|
||||
}
|
||||
@ -3,6 +3,7 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#include "renpy/language.h"
|
||||
#include "renpy/script.h"
|
||||
|
||||
namespace renpy {
|
||||
struct top_left {
|
||||
@ -40,7 +41,15 @@ namespace renpy {
|
||||
uint32_t count;
|
||||
uint32_t optionIndex;
|
||||
} menu;
|
||||
bool interactionWait;
|
||||
uint32_t dissolveIndex;
|
||||
struct {
|
||||
bool voice;
|
||||
bool menu;
|
||||
bool dissolve;
|
||||
bool pause;
|
||||
} pause;
|
||||
double dissolveDuration;
|
||||
double pauseDuration;
|
||||
|
||||
uint32_t findImage(uint32_t imageIndex);
|
||||
void showImage(uint32_t imageIndex, uint32_t transformIndex);
|
||||
@ -48,5 +57,15 @@ namespace renpy {
|
||||
void reset();
|
||||
void interpret_one();
|
||||
void interpret();
|
||||
|
||||
inline bool interactionWait()
|
||||
{
|
||||
return pause.voice || pause.menu || pause.dissolve || pause.pause;
|
||||
}
|
||||
|
||||
inline bool dissolvePC()
|
||||
{
|
||||
return dissolveIndex < (uint32_t)script::dissolves_length && script::dissolves[dissolveIndex].first_statement == pc;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -48,7 +48,6 @@ namespace renpy::language {
|
||||
stop,
|
||||
pause,
|
||||
hide,
|
||||
dissolve,
|
||||
};
|
||||
|
||||
struct jump {
|
||||
@ -107,7 +106,9 @@ namespace renpy::language {
|
||||
};
|
||||
|
||||
struct dissolve {
|
||||
float duration;
|
||||
double duration;
|
||||
uint32_t first_statement;
|
||||
uint32_t count;
|
||||
};
|
||||
|
||||
struct statement {
|
||||
@ -124,7 +125,6 @@ namespace renpy::language {
|
||||
renpy::language::stop stop;
|
||||
renpy::language::pause pause;
|
||||
renpy::language::hide hide;
|
||||
renpy::language::dissolve dissolve;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@ -16,6 +16,9 @@ namespace renpy::script {
|
||||
extern const language::option options[];
|
||||
extern const int options_length;
|
||||
|
||||
extern const language::dissolve dissolves[];
|
||||
extern const int dissolves_length;
|
||||
|
||||
extern const language::statement statements[];
|
||||
extern const int statements_length;
|
||||
|
||||
|
||||
@ -80,11 +80,21 @@ namespace renpy {
|
||||
void load_images();
|
||||
void create_pipeline();
|
||||
void create_instance_buffers();
|
||||
|
||||
void draw_menu_frame(VkCommandBuffer commandBuffer,
|
||||
uint32_t frameIndex,
|
||||
renpy::interpreter const& state,
|
||||
int & outputIndex,
|
||||
int mx, int my) const;
|
||||
void draw_say_frame(VkCommandBuffer commandBuffer,
|
||||
uint32_t frameIndex,
|
||||
renpy::interpreter const& state,
|
||||
int & outputIndex) const;
|
||||
void draw(VkCommandBuffer commandBuffer,
|
||||
uint32_t frameIndex,
|
||||
renpy::interpreter const& state,
|
||||
int mx,
|
||||
int my);
|
||||
int mx, int my,
|
||||
bool drawText) const;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
@ -14,6 +14,7 @@ class State:
|
||||
statements: list
|
||||
menus: list
|
||||
entries: dict
|
||||
dissolves: list
|
||||
|
||||
images_lookup: dict[str, int] # identifier to image index
|
||||
colors_lookup: dict[str, int] # identifier to image index
|
||||
@ -35,6 +36,12 @@ class InternalMenu:
|
||||
class InternalJump:
|
||||
target: tuple
|
||||
|
||||
@dataclass
|
||||
class InternalDissolve:
|
||||
duration: int
|
||||
first_statement: int
|
||||
count: int
|
||||
|
||||
def lhs_key(lhs):
|
||||
return tuple(l.lexeme for l in lhs)
|
||||
|
||||
@ -46,7 +53,6 @@ simple_statement_types = {
|
||||
parse.Scene,
|
||||
parse.Show,
|
||||
parse.Voice,
|
||||
parse.With,
|
||||
parse.Stop,
|
||||
parse.Pause,
|
||||
parse.Hide,
|
||||
@ -123,6 +129,34 @@ def pass1(state, ast):
|
||||
state.statements.append(InternalJump(menu_end_key))
|
||||
assert menu_end_key not in state.labels_lookup
|
||||
state.labels_lookup[menu_end_key] = len(state.statements)
|
||||
elif type(ast) is parse.With:
|
||||
if ast.function_call.name.lexeme != b'Dissolve':
|
||||
assert False, ast
|
||||
duration, = ast.function_call.args
|
||||
duration = duration.lexeme
|
||||
|
||||
scene_index = None
|
||||
for i in reversed(range(len(state.statements))):
|
||||
if type(state.statements[i]) is parse.Scene:
|
||||
scene_index = i
|
||||
break
|
||||
for i in range(scene_index + 1, len(state.statements)):
|
||||
ast = state.statements[i]
|
||||
if type(ast) is parse.Voice:
|
||||
assert False, ast
|
||||
elif type(ast) is parse.Menu:
|
||||
assert False, ast
|
||||
elif type(ast) is parse.Pause:
|
||||
assert False, ast
|
||||
else:
|
||||
assert type(ast) in simple_statement_types, ast
|
||||
|
||||
assert scene_index is not None
|
||||
state.dissolves.append(InternalDissolve(
|
||||
duration = duration,
|
||||
first_statement = scene_index,
|
||||
count = len(state.statements) - scene_index,
|
||||
))
|
||||
elif type(ast) in simple_statement_types:
|
||||
pass
|
||||
else:
|
||||
@ -161,13 +195,6 @@ def pass2_statement(state, pc, statement):
|
||||
color = parse_color(state.colors[color_index].path.lexeme)
|
||||
comment = ".".join(k.decode('utf-8') for k in key)
|
||||
yield f"{{ .type = type::scene_color, .scene_color = {{ .color = 0x{color:06x} }} }}, // {pc} {comment}"
|
||||
elif type(statement) is parse.With:
|
||||
#print(f"not implemented: {statement}", file=sys.stderr)
|
||||
if statement.function_call.name.lexeme == b'Dissolve':
|
||||
duration, = statement.function_call.args
|
||||
yield f"{{ .type = type::dissolve, .dissolve = {{ .duration = {duration.lexeme} }} }}, // {pc}"
|
||||
else:
|
||||
assert False, (pc, statement)
|
||||
elif type(statement) is parse.Voice:
|
||||
comment = statement.path.lexeme.decode('utf-8')
|
||||
audio_index = state.audio_lookup[statement.path.lexeme]
|
||||
@ -217,7 +244,6 @@ def pass2_statement(state, pc, statement):
|
||||
comment = ".".join(k.decode('utf-8') for k in key)
|
||||
yield f"{{ .type = type::hide, .hide = {{ .imageIndex = {image_index} }} }}, // {pc} {comment}"
|
||||
else:
|
||||
pass
|
||||
assert False, (type(statement), statement)
|
||||
|
||||
def pass2_statements(state):
|
||||
@ -286,6 +312,13 @@ def pass2_options(state):
|
||||
yield "};"
|
||||
yield "const int options_length = (sizeof (options)) / (sizeof (options[0]));"
|
||||
|
||||
def pass2_dissolves(state):
|
||||
yield "const language::dissolve dissolves[] = {"
|
||||
for dissolve in state.dissolves:
|
||||
yield f"{{ .duration = {dissolve.duration}, .first_statement = {dissolve.first_statement}, .count = {dissolve.count} }},"
|
||||
yield "};"
|
||||
yield "const int dissolves_length = (sizeof (dissolves)) / (sizeof (dissolves[0]));"
|
||||
|
||||
def pass2(state):
|
||||
yield "#include \"renpy/language.h\""
|
||||
yield "#include \"renpy/script.h\""
|
||||
@ -297,6 +330,7 @@ def pass2(state):
|
||||
yield from pass2_audio(state)
|
||||
yield from pass2_images(state)
|
||||
yield from pass2_options(state)
|
||||
yield from pass2_dissolves(state)
|
||||
yield from pass2_statements(state)
|
||||
yield "}"
|
||||
|
||||
@ -315,6 +349,7 @@ image _internal_flowers = "flowers.png"
|
||||
statements = list(),
|
||||
menus = list(),
|
||||
entries = dict(),
|
||||
dissolves = list(),
|
||||
images_lookup = dict(),
|
||||
colors_lookup = dict(),
|
||||
characters_lookup = dict(),
|
||||
|
||||
@ -88,8 +88,8 @@ float4 PSMain(VSOutput input) : SV_TARGET
|
||||
if (color.w == 0.0)
|
||||
discard;
|
||||
|
||||
float gamma = 2.2;
|
||||
color.xyz = pow(color.xyz, float3(gamma.xxx));
|
||||
//float gamma = 2.2;
|
||||
//color.xyz = pow(color.xyz, float3(gamma.xxx));
|
||||
|
||||
return float4(color.xyzw);
|
||||
}
|
||||
|
||||
59
shader/renpy_composite.hlsl
Normal file
59
shader/renpy_composite.hlsl
Normal file
@ -0,0 +1,59 @@
|
||||
[[vk::binding(0, 0)]] SamplerState ClosestSampler;
|
||||
[[vk::binding(1, 0)]] Texture2D Texture[];
|
||||
|
||||
struct PushConstant {
|
||||
float DissolveLerp;
|
||||
float TextLerp;
|
||||
};
|
||||
|
||||
[[vk::push_constant]] PushConstant PushConstant;
|
||||
|
||||
struct VSInput
|
||||
{
|
||||
float2 Position : POSITION0;
|
||||
float2 Texture : TEXCOORD0;
|
||||
};
|
||||
|
||||
struct VSOutput
|
||||
{
|
||||
float4 Position : SV_POSITION;
|
||||
float2 Texture : NORMAL0;
|
||||
float DissolveLerp : DissolveLerp;
|
||||
float TextLerp : TextLerp;
|
||||
};
|
||||
|
||||
float4 mix(float4 x, float4 y, float a)
|
||||
{
|
||||
return x * (1 - a) + y * a;
|
||||
}
|
||||
|
||||
[shader("vertex")]
|
||||
VSOutput VSMain(VSInput input)
|
||||
{
|
||||
VSOutput output = (VSOutput)0;
|
||||
output.Position = float4(input.Position, 0, 1);
|
||||
output.Texture = input.Texture;
|
||||
output.DissolveLerp = PushConstant.DissolveLerp;
|
||||
output.TextLerp = PushConstant.TextLerp;
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
[shader("pixel")]
|
||||
float4 PSMain(VSOutput input) : SV_TARGET
|
||||
{
|
||||
float4 color0 = Texture[0].Sample(ClosestSampler, input.Texture);
|
||||
|
||||
float4 color = float4(0, 0, 0, 0);
|
||||
if (input.DissolveLerp >= 0) {
|
||||
float4 color1 = Texture[1].Sample(ClosestSampler, input.Texture);
|
||||
float4 color01 = mix(color0, color1, input.TextLerp);
|
||||
|
||||
float4 color2 = Texture[2].Sample(ClosestSampler, input.Texture);
|
||||
color = mix(color01, color2, input.DissolveLerp);
|
||||
} else {
|
||||
color = color0;
|
||||
}
|
||||
|
||||
return float4(color.xyzw);
|
||||
}
|
||||
@ -622,7 +622,7 @@ namespace font::outline {
|
||||
int& outputIndex,
|
||||
int startIndex,
|
||||
int endIndex,
|
||||
uint32_t color)
|
||||
uint32_t color) const
|
||||
{
|
||||
for (int i = startIndex; i < endIndex; i++) {
|
||||
char c = string[i];
|
||||
@ -645,7 +645,7 @@ namespace font::outline {
|
||||
uint32_t minX,
|
||||
uint32_t maxWidth,
|
||||
int& outputIndex,
|
||||
uint32_t color)
|
||||
uint32_t color) const
|
||||
{
|
||||
int stringIndex = 0;
|
||||
int lineStart = stringIndex;
|
||||
@ -700,7 +700,7 @@ namespace font::outline {
|
||||
|
||||
void font::draw(VkCommandBuffer commandBuffer,
|
||||
uint32_t frameIndex,
|
||||
renpy::interpreter const& state)
|
||||
renpy::interpreter const& state) const
|
||||
{
|
||||
// transfer
|
||||
int outputIndex = 0;
|
||||
|
||||
287
src/main.cpp
287
src/main.cpp
@ -23,6 +23,7 @@
|
||||
|
||||
#include "font/outline.h"
|
||||
#include "renpy/vulkan.h"
|
||||
#include "renpy/composite/vulkan.h"
|
||||
#include "renpy/interpreter.h"
|
||||
#include "renpy/interact.h"
|
||||
#include "renpy/script.h"
|
||||
@ -43,6 +44,11 @@ VkImage depthImage{ VK_NULL_HANDLE };
|
||||
VkImageView depthImageView{ VK_NULL_HANDLE };
|
||||
VkDeviceMemory depthMemory{ VK_NULL_HANDLE };
|
||||
|
||||
constexpr int colorImageCount = 3;
|
||||
VkImage colorImage[colorImageCount]{ VK_NULL_HANDLE, VK_NULL_HANDLE };
|
||||
VkImageView colorImageView[colorImageCount]{ VK_NULL_HANDLE, VK_NULL_HANDLE };
|
||||
VkDeviceMemory colorMemory[colorImageCount]{ VK_NULL_HANDLE, VK_NULL_HANDLE };
|
||||
|
||||
uint32_t shadowArrayLayers{ 6 };
|
||||
VkImage shadowDepthImage{ VK_NULL_HANDLE };
|
||||
VkImageView shadowDepthImageView{ VK_NULL_HANDLE };
|
||||
@ -114,6 +120,7 @@ void createDepth(VkDeviceSize nonCoherentAtomSize,
|
||||
uint32_t height,
|
||||
VkFormat format,
|
||||
VkImageUsageFlags usage,
|
||||
VkImageAspectFlags aspect,
|
||||
uint32_t arrayLayers,
|
||||
VkImage * image,
|
||||
VkDeviceMemory * memory,
|
||||
@ -160,7 +167,7 @@ void createDepth(VkDeviceSize nonCoherentAtomSize,
|
||||
.viewType = viewType,
|
||||
.format = format,
|
||||
.subresourceRange{
|
||||
.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT,
|
||||
.aspectMask = aspect,
|
||||
.levelCount = 1,
|
||||
.layerCount = arrayLayers
|
||||
}
|
||||
@ -275,6 +282,7 @@ void recreateSwapchain(VkSurfaceFormatKHR surfaceFormat,
|
||||
imageExtent.height,
|
||||
depthFormat,
|
||||
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
|
||||
VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT,
|
||||
arrayLayers,
|
||||
&depthImage,
|
||||
&depthMemory,
|
||||
@ -356,6 +364,151 @@ void gamepad_update(view & viewState)
|
||||
}
|
||||
}
|
||||
|
||||
void offscreenRender(VkCommandBuffer commandBuffer, int frameIndex,
|
||||
int mx, int my, int colorIndex, bool drawText,
|
||||
renpy::vulkan const & renpy_state,
|
||||
renpy::interpreter const & interpreter_state,
|
||||
font::outline::font const & font_state)
|
||||
{
|
||||
// barrier
|
||||
constexpr int colorBarriersCount = 2;
|
||||
VkImageMemoryBarrier2 colorBarriers[colorBarriersCount]{
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
|
||||
.srcStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT,
|
||||
.srcAccessMask = 0,
|
||||
.dstStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT,
|
||||
.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
.newLayout = VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL,
|
||||
.image = colorImage[colorIndex],
|
||||
.subresourceRange{
|
||||
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
.levelCount = 1,
|
||||
.layerCount = 1
|
||||
}
|
||||
},
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
|
||||
.srcStageMask = VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT,
|
||||
.srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
|
||||
.dstStageMask = VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT,
|
||||
.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
|
||||
.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
.newLayout = VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL,
|
||||
.image = depthImage,
|
||||
.subresourceRange{
|
||||
.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT,
|
||||
.levelCount = 1,
|
||||
.layerCount = 1
|
||||
}
|
||||
}
|
||||
};
|
||||
VkDependencyInfo colorBarrierDependencyInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
|
||||
.imageMemoryBarrierCount = colorBarriersCount,
|
||||
.pImageMemoryBarriers = colorBarriers
|
||||
};
|
||||
vkCmdPipelineBarrier2(commandBuffer, &colorBarrierDependencyInfo);
|
||||
|
||||
// attachments
|
||||
|
||||
VkRenderingAttachmentInfo colorRenderingAttachmentInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
|
||||
.imageView = colorImageView[colorIndex],
|
||||
.imageLayout = VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL,
|
||||
.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
|
||||
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
|
||||
.clearValue{ .color{ { 0.0f, 0.0f, 0.0f, 0.0f} } }
|
||||
};
|
||||
VkRenderingAttachmentInfo depthRenderingAttachmentInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
|
||||
.imageView = depthImageView,
|
||||
.imageLayout = VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL,
|
||||
.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
|
||||
.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
|
||||
.clearValue{ .depthStencil{ 1.0f, 0 } }
|
||||
};
|
||||
|
||||
VkRenderingInfo colorRenderingInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_RENDERING_INFO,
|
||||
.renderArea{ .extent{ .width = 1280, .height = 720 } },
|
||||
.layerCount = 1,
|
||||
.colorAttachmentCount = 1,
|
||||
.pColorAttachments = &colorRenderingAttachmentInfo,
|
||||
.pDepthAttachment = &depthRenderingAttachmentInfo,
|
||||
.pStencilAttachment = &depthRenderingAttachmentInfo,
|
||||
};
|
||||
vkCmdBeginRendering(commandBuffer, &colorRenderingInfo);
|
||||
|
||||
// viewport/scissor
|
||||
|
||||
VkViewport shadowViewport{
|
||||
.x = 0,
|
||||
.y = 0,
|
||||
.width = static_cast<float>(windowSize.x),
|
||||
.height = static_cast<float>(windowSize.y),
|
||||
.minDepth = 0.0f,
|
||||
.maxDepth = 1.0f
|
||||
};
|
||||
vkCmdSetViewport(commandBuffer, 0, 1, &shadowViewport);
|
||||
VkRect2D shadowScissor{
|
||||
.extent{
|
||||
.width = (uint32_t)windowSize.x,
|
||||
.height = (uint32_t)windowSize.y
|
||||
}
|
||||
};
|
||||
vkCmdSetScissor(commandBuffer, 0, 1, &shadowScissor);
|
||||
|
||||
// draw
|
||||
|
||||
//collada_state.vulkan.excludeMaterialIndex = lightMaterialIndex;
|
||||
//collada_state.vulkan.pipelineIndex = 0; // shadow pipeline
|
||||
//collada_state.draw();
|
||||
|
||||
renpy_state.draw(commandBuffer, frameIndex, interpreter_state, mx, my, drawText);
|
||||
if (drawText) {
|
||||
font_state.draw(commandBuffer, frameIndex, interpreter_state);
|
||||
}
|
||||
|
||||
vkCmdEndRendering(commandBuffer);
|
||||
|
||||
// barrier
|
||||
|
||||
{
|
||||
VkImageMemoryBarrier2 colorBarriers[1]{
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
|
||||
.srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
|
||||
.srcAccessMask = VK_ACCESS_MEMORY_READ_BIT,
|
||||
.dstStageMask = VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT,
|
||||
.dstAccessMask = VK_ACCESS_2_INPUT_ATTACHMENT_READ_BIT,
|
||||
.oldLayout = VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL,
|
||||
.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||
.image = colorImage[frameIndex],
|
||||
.subresourceRange{
|
||||
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
.levelCount = 1,
|
||||
.layerCount = 1,
|
||||
}
|
||||
}
|
||||
};
|
||||
VkDependencyInfo colorBarrierDependencyInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
|
||||
.imageMemoryBarrierCount = 1,
|
||||
.pImageMemoryBarriers = colorBarriers
|
||||
};
|
||||
vkCmdPipelineBarrier2(commandBuffer, &colorBarrierDependencyInfo);
|
||||
}
|
||||
}
|
||||
|
||||
static inline double clamp01(double a)
|
||||
{
|
||||
if (a < 0.0) return 0.0;
|
||||
if (a > 1.0) return 1.0;
|
||||
return a;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
file::init();
|
||||
@ -530,6 +683,16 @@ int main()
|
||||
VK_CHECK(vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, &surfaceFormatCount, surfaceFormats));
|
||||
uint32_t surfaceFormatIndex{ 0 };
|
||||
printf("surfaceFormatCount %d\n", surfaceFormatCount);
|
||||
for (uint32_t i = 0; i < surfaceFormatCount; i++) {
|
||||
if (surfaceFormats[i].format == VK_FORMAT_B8G8R8A8_UNORM) {
|
||||
surfaceFormatIndex = i;
|
||||
break;
|
||||
}
|
||||
if (surfaceFormats[i].format == VK_FORMAT_R8G8B8A8_UNORM) {
|
||||
surfaceFormatIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (uint32_t i = 0; i < surfaceFormatCount; i++) {
|
||||
printf("surfaceFormat[%d] %s %s%s\n", i, string_VkFormat(surfaceFormats[i].format), string_VkColorSpaceKHR(surfaceFormats[i].colorSpace), (i == surfaceFormatIndex) ? " [selected]" : "");
|
||||
}
|
||||
@ -564,6 +727,7 @@ int main()
|
||||
720,
|
||||
depthFormat,
|
||||
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||
VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT,
|
||||
shadowArrayLayers,
|
||||
&shadowDepthImage,
|
||||
&shadowDepthMemory,
|
||||
@ -656,6 +820,25 @@ int main()
|
||||
};
|
||||
VK_CHECK(vkCreateSampler(device, &samplerCreateInfo2, nullptr, &textureSamplers[2]));
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// off-screen color buffers
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
for (int i = 0; i < colorImageCount; i++) {
|
||||
uint32_t arrayLayers{ 1 };
|
||||
createDepth(physicalDeviceProperties.limits.nonCoherentAtomSize,
|
||||
physicalDeviceMemoryProperties,
|
||||
1280,
|
||||
720,
|
||||
surfaceFormat.format,
|
||||
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
arrayLayers,
|
||||
&colorImage[i],
|
||||
&colorMemory[i],
|
||||
&colorImageView[i]);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// initialize collada
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
@ -736,6 +919,23 @@ int main()
|
||||
renpy::interpreter interpreter_state;
|
||||
interpreter_state.reset();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// renpy composite
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
renpy::composite::vulkan composite_state;
|
||||
composite_state.initial_state(instance,
|
||||
device,
|
||||
queue,
|
||||
commandPool,
|
||||
physicalDeviceProperties,
|
||||
physicalDeviceMemoryProperties,
|
||||
surfaceFormat.format,
|
||||
depthFormat,
|
||||
textureSamplers[2]);
|
||||
composite_state.init();
|
||||
composite_state.write_descriptor_sets(colorImageView, colorImageCount);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// initialize view
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
@ -775,6 +975,9 @@ int main()
|
||||
int64_t start_time;
|
||||
SDL_GetCurrentTime(&start_time);
|
||||
|
||||
double pause_start = 0.0;
|
||||
double dissolve_start = 0.0;
|
||||
|
||||
//collada_state.update(0);
|
||||
|
||||
audio::init();
|
||||
@ -782,8 +985,39 @@ int main()
|
||||
|
||||
while (quit == false) {
|
||||
audio::update();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// interpreter update
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
interpreter_state.interpret();
|
||||
|
||||
if (interpreter_state.pause.pause) {
|
||||
if (pause_start == 0.0) {
|
||||
fprintf(stderr, "pause %f\n", interpreter_state.pauseDuration);
|
||||
pause_start = getTime(start_time);
|
||||
} else if (getTime(start_time) - pause_start >= interpreter_state.pauseDuration) {
|
||||
fprintf(stderr, "unpause %f\n", interpreter_state.pauseDuration);
|
||||
pause_start = 0.0;
|
||||
interpreter_state.pause.pause = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (interpreter_state.pause.dissolve) {
|
||||
if (dissolve_start == 0.0) {
|
||||
fprintf(stderr, "dissolve %f\n", interpreter_state.dissolveDuration);
|
||||
dissolve_start = getTime(start_time);
|
||||
} else if (getTime(start_time) - dissolve_start >= interpreter_state.dissolveDuration) {
|
||||
fprintf(stderr, "undissolve %f\n", interpreter_state.dissolveDuration);
|
||||
dissolve_start = 0.0;
|
||||
interpreter_state.pause.dissolve = false;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// sdl
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event)) {
|
||||
if (event.type == SDL_EVENT_QUIT) {
|
||||
@ -827,6 +1061,16 @@ int main()
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// renpy update
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
float mx;
|
||||
float my;
|
||||
uint32_t mouseFlags = SDL_GetMouseState(&mx, &my);
|
||||
bool mLeft = (mouseFlags & SDL_BUTTON_LMASK) != 0;
|
||||
renpy::update(interpreter_state, mx, my, mLeft);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// gamepad update
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
@ -902,6 +1146,7 @@ int main()
|
||||
// shadow render
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
// barrier
|
||||
VkImageMemoryBarrier2 shadowBarriers[1]{
|
||||
VkImageMemoryBarrier2{
|
||||
@ -1002,6 +1247,19 @@ int main()
|
||||
};
|
||||
vkCmdPipelineBarrier2(commandBuffer, &shadowBarrierDependencyInfo);
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// offscreen render
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
if (interpreter_state.pause.dissolve) {
|
||||
offscreenRender(commandBuffer, frameIndex, mx, my, 2, true, renpy_state, interpreter_state, font_state);
|
||||
} else {
|
||||
offscreenRender(commandBuffer, frameIndex, mx, my, 0, true, renpy_state, interpreter_state, font_state);
|
||||
offscreenRender(commandBuffer, frameIndex, mx, my, 1, false, renpy_state, interpreter_state, font_state);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// render
|
||||
@ -1086,7 +1344,12 @@ int main()
|
||||
.maxDepth = 1.0f
|
||||
};
|
||||
vkCmdSetViewport(commandBuffer, 0, 1, &viewport);
|
||||
VkRect2D scissor{ .extent{ .width = (uint32_t)windowSize.x, .height = (uint32_t)windowSize.y } };
|
||||
VkRect2D scissor{
|
||||
.extent{
|
||||
.width = (uint32_t)windowSize.x,
|
||||
.height = (uint32_t)windowSize.y
|
||||
}
|
||||
};
|
||||
vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
|
||||
|
||||
// draw
|
||||
@ -1099,13 +1362,19 @@ int main()
|
||||
|
||||
//minecraft_state.draw(commandBuffer, frameIndex);
|
||||
|
||||
float mx;
|
||||
float my;
|
||||
uint32_t mouseFlags = SDL_GetMouseState(&mx, &my);
|
||||
bool mLeft = (mouseFlags & SDL_BUTTON_LMASK) != 0;
|
||||
renpy::update(interpreter_state, mx, my, mLeft);
|
||||
renpy_state.draw(commandBuffer, frameIndex, interpreter_state, mx, my);
|
||||
font_state.draw(commandBuffer, frameIndex, interpreter_state);
|
||||
//renpy_state.draw(commandBuffer, frameIndex, interpreter_state, mx, my);
|
||||
//font_state.draw(commandBuffer, frameIndex, interpreter_state);
|
||||
|
||||
float dissolve_lerp = -1.0;
|
||||
float text_lerp = -1.0;
|
||||
constexpr double textDissolveDuration = 0.3;
|
||||
if (interpreter_state.pause.dissolve) {
|
||||
double delta = getTime(start_time) - dissolve_start;
|
||||
assert(interpreter_state.dissolveDuration > 0.0000001);
|
||||
dissolve_lerp = clamp01(delta / interpreter_state.dissolveDuration);
|
||||
text_lerp = clamp01(delta / textDissolveDuration);
|
||||
}
|
||||
composite_state.draw(commandBuffer, frameIndex, dissolve_lerp, text_lerp);
|
||||
|
||||
vkCmdEndRendering(commandBuffer);
|
||||
|
||||
|
||||
414
src/renpy/composite/vulkan.cpp
Normal file
414
src/renpy/composite/vulkan.cpp
Normal file
@ -0,0 +1,414 @@
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include "vulkan/vulkan.h"
|
||||
#else
|
||||
#include "volk/volk.h"
|
||||
#endif
|
||||
|
||||
#include "vulkan/vk_enum_string_helper.h"
|
||||
#include "vulkan_helper.h"
|
||||
#include "check.h"
|
||||
#include "new.h"
|
||||
#include "file.h"
|
||||
|
||||
#include "renpy/composite/vulkan.h"
|
||||
|
||||
namespace renpy::composite {
|
||||
static constexpr int imageCount = 3;
|
||||
|
||||
static const _Float16 vertexData[] = {
|
||||
// x y u v
|
||||
(_Float16)-1.0, (_Float16)-1.0, (_Float16)0.0, (_Float16)0.0,
|
||||
(_Float16)1.0, (_Float16)-1.0, (_Float16)1.0, (_Float16)0.0,
|
||||
(_Float16)-1.0, (_Float16)1.0, (_Float16)0.0, (_Float16)1.0,
|
||||
(_Float16)1.0, (_Float16)1.0, (_Float16)1.0, (_Float16)1.0,
|
||||
};
|
||||
static const uint32_t vertexSize = (sizeof (vertexData));
|
||||
|
||||
static const uint16_t indexData[] = {
|
||||
0, 1, 2, 3,
|
||||
};
|
||||
static const uint32_t indexSize = (sizeof (indexData));
|
||||
|
||||
void vulkan::initial_state(VkInstance instance,
|
||||
VkDevice device,
|
||||
VkQueue queue,
|
||||
VkCommandPool commandPool,
|
||||
VkPhysicalDeviceProperties physicalDeviceProperties,
|
||||
VkPhysicalDeviceMemoryProperties physicalDeviceMemoryProperties,
|
||||
VkFormat colorFormat,
|
||||
VkFormat depthFormat,
|
||||
VkSampler linearSampler)
|
||||
{
|
||||
this->instance = instance;
|
||||
this->device = device;
|
||||
this->queue = queue;
|
||||
this->commandPool = commandPool;
|
||||
|
||||
this->physicalDeviceProperties = physicalDeviceProperties;
|
||||
this->physicalDeviceMemoryProperties = physicalDeviceMemoryProperties;
|
||||
|
||||
this->colorFormat = colorFormat;
|
||||
this->depthFormat = depthFormat;
|
||||
|
||||
this->linearSampler = linearSampler;
|
||||
}
|
||||
|
||||
void vulkan::init()
|
||||
{
|
||||
load_vertex_index_buffer();
|
||||
load_shader();
|
||||
create_descriptor_sets();
|
||||
create_pipeline();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// vertex index buffer
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
void vulkan::load_vertex_index_buffer()
|
||||
{
|
||||
void const * vertexStart = (void const *)vertexData;
|
||||
void const * indexStart = (void const *)indexData;
|
||||
|
||||
vertexIndex = createVertexIndexBuffer(device,
|
||||
physicalDeviceProperties,
|
||||
physicalDeviceMemoryProperties,
|
||||
vertexStart, vertexSize,
|
||||
indexStart, indexSize);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// shader
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
void vulkan::load_shader()
|
||||
{
|
||||
uint32_t shaderSize;
|
||||
void const * shaderStart = file::open("shader/renpy_composite.spv", &shaderSize);
|
||||
|
||||
VkShaderModuleCreateInfo shaderModuleCreateInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
|
||||
.codeSize = shaderSize,
|
||||
.pCode = (uint32_t *)shaderStart
|
||||
};
|
||||
VK_CHECK(vkCreateShaderModule(device, &shaderModuleCreateInfo, nullptr, &shaderModule));
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// descriptor sets
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
void vulkan::create_descriptor_sets()
|
||||
{
|
||||
//
|
||||
// pool
|
||||
//
|
||||
constexpr int descriptorPoolSizesCount = 2;
|
||||
VkDescriptorPoolSize descriptorPoolSizes[descriptorPoolSizesCount]{
|
||||
{ // linear sampler
|
||||
.type = VK_DESCRIPTOR_TYPE_SAMPLER,
|
||||
.descriptorCount = 1,
|
||||
},
|
||||
{
|
||||
.type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
|
||||
.descriptorCount = imageCount,
|
||||
},
|
||||
};
|
||||
VkDescriptorPoolCreateInfo descriptorPoolCreateInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
|
||||
.maxSets = 1,
|
||||
.poolSizeCount = descriptorPoolSizesCount,
|
||||
.pPoolSizes = descriptorPoolSizes
|
||||
};
|
||||
VK_CHECK(vkCreateDescriptorPool(device, &descriptorPoolCreateInfo, nullptr, &descriptorPool));
|
||||
|
||||
//
|
||||
// (set 0, constant)
|
||||
//
|
||||
{
|
||||
constexpr int bindingCount = 2;
|
||||
VkDescriptorSetLayoutBinding descriptorSetLayoutBindings[bindingCount]{
|
||||
{
|
||||
.binding = 0,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER,
|
||||
.descriptorCount = 1,
|
||||
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT
|
||||
},
|
||||
{ // font image
|
||||
.binding = 1,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
|
||||
.descriptorCount = imageCount,
|
||||
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT
|
||||
}
|
||||
};
|
||||
|
||||
VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
|
||||
.bindingCount = bindingCount,
|
||||
.pBindings = descriptorSetLayoutBindings
|
||||
};
|
||||
VK_CHECK(vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCreateInfo, nullptr, &descriptorSetLayouts[0]));
|
||||
|
||||
VkDescriptorSetAllocateInfo descriptorSetAllocateInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
|
||||
.descriptorPool = descriptorPool,
|
||||
.descriptorSetCount = 1,
|
||||
.pSetLayouts = &descriptorSetLayouts[0]
|
||||
};
|
||||
VK_CHECK(vkAllocateDescriptorSets(device, &descriptorSetAllocateInfo, &descriptorSet0));
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// descriptor set writes
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
void vulkan::write_descriptor_sets(VkImageView * imageViews, int imageViewCount)
|
||||
{
|
||||
assert(imageViewCount == imageCount);
|
||||
constexpr uint32_t writeCount = 2;
|
||||
VkWriteDescriptorSet writeDescriptorSets[writeCount];
|
||||
uint32_t writeIndex = 0;
|
||||
|
||||
// set0 bindings
|
||||
VkDescriptorImageInfo samplerDescriptorImageInfo = {
|
||||
.sampler = linearSampler,
|
||||
};
|
||||
writeDescriptorSets[writeIndex++] = {
|
||||
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
.dstSet = descriptorSet0,
|
||||
.dstBinding = 0,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER,
|
||||
.pImageInfo = &samplerDescriptorImageInfo
|
||||
};
|
||||
|
||||
VkDescriptorImageInfo sceneDescriptorImageInfos[imageCount];
|
||||
for (int i = 0; i < imageCount; i++) {
|
||||
sceneDescriptorImageInfos[i] = {
|
||||
.imageView = imageViews[i],
|
||||
.imageLayout = VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL
|
||||
};
|
||||
}
|
||||
|
||||
writeDescriptorSets[writeIndex++] = {
|
||||
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
.dstSet = descriptorSet0,
|
||||
.dstBinding = 1,
|
||||
.descriptorCount = imageCount,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
|
||||
.pImageInfo = sceneDescriptorImageInfos
|
||||
};
|
||||
|
||||
assert(writeIndex == writeCount);
|
||||
vkUpdateDescriptorSets(device, writeIndex, writeDescriptorSets, 0, nullptr);
|
||||
//free(sceneDescriptorImageInfos);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// pipeline
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
void vulkan::create_pipeline()
|
||||
{
|
||||
VkPushConstantRange pushConstantRange{
|
||||
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT,
|
||||
.size = (sizeof (float)),
|
||||
};
|
||||
|
||||
VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
|
||||
.setLayoutCount = descriptorSetLayoutCount,
|
||||
.pSetLayouts = descriptorSetLayouts,
|
||||
.pushConstantRangeCount = 1,
|
||||
.pPushConstantRanges = &pushConstantRange,
|
||||
};
|
||||
VK_CHECK(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout));
|
||||
|
||||
VkPipelineInputAssemblyStateCreateInfo inputAssemblyState{
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
|
||||
.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP
|
||||
};
|
||||
|
||||
VkPipelineShaderStageCreateInfo shaderStages[2]{
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
|
||||
.stage = VK_SHADER_STAGE_VERTEX_BIT,
|
||||
.module = shaderModule,
|
||||
.pName = "VSMain"
|
||||
},
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
|
||||
.stage = VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||
.module = shaderModule,
|
||||
.pName = "PSMain"
|
||||
}
|
||||
};
|
||||
|
||||
VkPipelineViewportStateCreateInfo viewportState{
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
|
||||
.viewportCount = 1,
|
||||
.scissorCount = 1
|
||||
};
|
||||
|
||||
constexpr uint32_t dynamicStateCount = 2;
|
||||
VkDynamicState dynamicStates[dynamicStateCount]{
|
||||
VK_DYNAMIC_STATE_VIEWPORT,
|
||||
VK_DYNAMIC_STATE_SCISSOR,
|
||||
};
|
||||
VkPipelineDynamicStateCreateInfo dynamicState{
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
|
||||
.dynamicStateCount = dynamicStateCount,
|
||||
.pDynamicStates = dynamicStates
|
||||
};
|
||||
|
||||
VkPipelineDepthStencilStateCreateInfo depthStencilState{
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
|
||||
.depthTestEnable = VK_FALSE,
|
||||
.depthWriteEnable = VK_FALSE,
|
||||
.depthCompareOp = VK_COMPARE_OP_ALWAYS,
|
||||
.stencilTestEnable = VK_FALSE,
|
||||
.front = {
|
||||
.failOp = VK_STENCIL_OP_REPLACE,
|
||||
.passOp = VK_STENCIL_OP_REPLACE,
|
||||
.depthFailOp = VK_STENCIL_OP_REPLACE,
|
||||
.compareOp = VK_COMPARE_OP_ALWAYS,
|
||||
.compareMask = 0x01,
|
||||
.writeMask = 0x01,
|
||||
.reference = 1,
|
||||
},
|
||||
.back = {
|
||||
.failOp = VK_STENCIL_OP_REPLACE,
|
||||
.passOp = VK_STENCIL_OP_REPLACE,
|
||||
.depthFailOp = VK_STENCIL_OP_REPLACE,
|
||||
.compareOp = VK_COMPARE_OP_ALWAYS,
|
||||
.compareMask = 0x01,
|
||||
.writeMask = 0x01,
|
||||
.reference = 1,
|
||||
},
|
||||
};
|
||||
|
||||
VkPipelineRenderingCreateInfo renderingCreateInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO,
|
||||
.colorAttachmentCount = 1,
|
||||
.pColorAttachmentFormats = &colorFormat,
|
||||
.depthAttachmentFormat = depthFormat,
|
||||
.stencilAttachmentFormat = depthFormat
|
||||
};
|
||||
|
||||
VkPipelineColorBlendAttachmentState blendAttachment{
|
||||
.blendEnable = VK_FALSE,
|
||||
.srcColorBlendFactor = VK_BLEND_FACTOR_ONE,
|
||||
.dstColorBlendFactor = VK_BLEND_FACTOR_ZERO,
|
||||
.colorBlendOp = VK_BLEND_OP_ADD,
|
||||
.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE,
|
||||
.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO,
|
||||
.alphaBlendOp = VK_BLEND_OP_ADD,
|
||||
.colorWriteMask = 0xF,
|
||||
};
|
||||
VkPipelineColorBlendStateCreateInfo colorBlendState{
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
|
||||
.attachmentCount = 1,
|
||||
.pAttachments = &blendAttachment
|
||||
};
|
||||
VkPipelineRasterizationStateCreateInfo rasterizationState{
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
|
||||
//.cullMode = VK_CULL_MODE_BACK_BIT,
|
||||
.cullMode = VK_CULL_MODE_NONE,
|
||||
.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE,
|
||||
.lineWidth = 1.0f
|
||||
};
|
||||
VkPipelineMultisampleStateCreateInfo multisampleState{
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
|
||||
.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT
|
||||
};
|
||||
|
||||
constexpr int vertexBindingDescriptionsCount = 1;
|
||||
VkVertexInputBindingDescription vertexBindingDescriptions[vertexBindingDescriptionsCount]{
|
||||
{
|
||||
.binding = 0,
|
||||
.stride = perVertexSize,
|
||||
.inputRate = VK_VERTEX_INPUT_RATE_VERTEX
|
||||
},
|
||||
};
|
||||
|
||||
constexpr int vertexAttributeDescriptionsCount = 2;
|
||||
VkVertexInputAttributeDescription vertexAttributeDescriptions[vertexAttributeDescriptionsCount]{
|
||||
// per-vertex
|
||||
{ // position
|
||||
.location = 0,
|
||||
.binding = 0,
|
||||
.format = VK_FORMAT_R16G16_SFLOAT,
|
||||
.offset = 0,
|
||||
},
|
||||
{ // texture
|
||||
.location = 1,
|
||||
.binding = 0,
|
||||
.format = VK_FORMAT_R16G16_SFLOAT,
|
||||
.offset = 4,
|
||||
},
|
||||
};
|
||||
|
||||
VkPipelineVertexInputStateCreateInfo vertexInputState{
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
|
||||
.vertexBindingDescriptionCount = vertexBindingDescriptionsCount,
|
||||
.pVertexBindingDescriptions = vertexBindingDescriptions,
|
||||
.vertexAttributeDescriptionCount = vertexAttributeDescriptionsCount,
|
||||
.pVertexAttributeDescriptions = vertexAttributeDescriptions,
|
||||
};
|
||||
|
||||
VkGraphicsPipelineCreateInfo pipelineCreateInfos[1]{
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
|
||||
.pNext = &renderingCreateInfo,
|
||||
.stageCount = 2,
|
||||
.pStages = shaderStages,
|
||||
.pVertexInputState = &vertexInputState,
|
||||
.pInputAssemblyState = &inputAssemblyState,
|
||||
.pViewportState = &viewportState,
|
||||
.pRasterizationState = &rasterizationState,
|
||||
.pMultisampleState = &multisampleState,
|
||||
.pDepthStencilState = &depthStencilState,
|
||||
.pColorBlendState = &colorBlendState,
|
||||
.pDynamicState = &dynamicState,
|
||||
.layout = pipelineLayout
|
||||
},
|
||||
};
|
||||
|
||||
VK_CHECK(vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, pipelineCreateInfos, nullptr, &pipeline));
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// draw
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
void vulkan::draw(VkCommandBuffer commandBuffer,
|
||||
uint32_t frameIndex,
|
||||
float dissolveLerp,
|
||||
float textLerp)
|
||||
{
|
||||
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
|
||||
|
||||
float lerp[2] = { dissolveLerp, textLerp };
|
||||
vkCmdPushConstants(commandBuffer, pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, (sizeof (float)) * 2, lerp);
|
||||
|
||||
VkDescriptorSet descriptorSets[1] = {
|
||||
descriptorSet0,
|
||||
};
|
||||
vkCmdBindDescriptorSets(commandBuffer,
|
||||
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
pipelineLayout,
|
||||
0, 1, descriptorSets,
|
||||
0, nullptr);
|
||||
|
||||
vkCmdBindIndexBuffer(commandBuffer, vertexIndex.buffer, vertexIndex.indexOffset, VK_INDEX_TYPE_UINT16);
|
||||
|
||||
VkDeviceSize vertexOffsets[1]{ 0 };
|
||||
VkBuffer vertexBuffers[1]{ vertexIndex.buffer };
|
||||
vkCmdBindVertexBuffers(commandBuffer, 0, 1, vertexBuffers, vertexOffsets);
|
||||
|
||||
vkCmdDrawIndexed(commandBuffer, 4, 1, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
@ -22,7 +22,7 @@ namespace renpy {
|
||||
bool mDown = mLeft && (!lastmLeft);
|
||||
lastmLeft = mLeft;
|
||||
if (mDown) {
|
||||
state.interactionWait = false;
|
||||
state.pause.voice = false;
|
||||
}
|
||||
|
||||
if (state.menu.count == 0 || !mDown)
|
||||
|
||||
@ -10,13 +10,17 @@ namespace renpy {
|
||||
void interpreter::reset()
|
||||
{
|
||||
pc = 0;
|
||||
backgroundIndex = -1;
|
||||
backgroundIndex = ~0u;
|
||||
backgroundColor = 0;
|
||||
shownImagesCount = 0;
|
||||
say.stringIndex = -1;
|
||||
say.characterIndex = -1;
|
||||
say.stringIndex = ~0u;
|
||||
say.characterIndex = ~0u;
|
||||
menu.count = 0;
|
||||
interactionWait = false;
|
||||
dissolveIndex = 0;
|
||||
pause.voice = false;
|
||||
pause.menu = false;
|
||||
pause.dissolve = false;
|
||||
pause.pause = false;
|
||||
}
|
||||
|
||||
uint32_t interpreter::findImage(uint32_t imageIndex)
|
||||
@ -60,6 +64,8 @@ namespace renpy {
|
||||
|
||||
void interpreter::interpret_one()
|
||||
{
|
||||
uint32_t last_pc = pc;
|
||||
|
||||
assert(pc < (uint32_t)script::statements_length);
|
||||
|
||||
language::statement const& statement = script::statements[pc];
|
||||
@ -90,8 +96,8 @@ namespace renpy {
|
||||
backgroundIndex = statement.scene.imageIndex;
|
||||
|
||||
shownImagesCount = 0;
|
||||
say.stringIndex = -1;
|
||||
say.characterIndex = -1;
|
||||
say.stringIndex = ~0u;
|
||||
say.characterIndex = ~0u;
|
||||
pc += 1;
|
||||
break;
|
||||
case language::type::say:
|
||||
@ -99,7 +105,7 @@ namespace renpy {
|
||||
assert(statement.say.stringIndex < (uint32_t)script::strings_length);
|
||||
say.stringIndex = statement.say.stringIndex;
|
||||
say.characterIndex = statement.say.characterIndex;
|
||||
interactionWait = true;
|
||||
pause.voice = true;
|
||||
pc += 1;
|
||||
break;
|
||||
case language::type::hide:
|
||||
@ -129,22 +135,37 @@ namespace renpy {
|
||||
assert(statement.jump.statementIndex < (uint32_t)script::statements_length);
|
||||
pc = statement.jump.statementIndex;
|
||||
break;
|
||||
case language::type::pause:
|
||||
fprintf(stderr, "interpret_one[%d]: pause %f\n", pc, statement.pause.duration);
|
||||
pauseDuration = statement.pause.duration;
|
||||
pause.pause = true;
|
||||
pc += 1;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "unknown statement type at pc %d\n", pc);
|
||||
assert(false);
|
||||
pc += 1;
|
||||
break;
|
||||
}
|
||||
|
||||
assert(pc != last_pc);
|
||||
}
|
||||
|
||||
void interpreter::interpret()
|
||||
{
|
||||
while (!interactionWait) {
|
||||
//while (true) {
|
||||
uint32_t last_pc = pc;
|
||||
while (!interactionWait()) {
|
||||
if (dissolvePC()) {
|
||||
fprintf(stderr, "dissolve pc %d\n", pc);
|
||||
language::dissolve const & dissolve = script::dissolves[dissolveIndex];
|
||||
for (uint32_t i = 0; i < dissolve.count; i++) {
|
||||
interpret_one();
|
||||
assert(pc != last_pc);
|
||||
|
||||
//if (pc == 18) break;
|
||||
}
|
||||
pause.dissolve = true;
|
||||
dissolveDuration = dissolve.duration;
|
||||
dissolveIndex += 1;
|
||||
} else {
|
||||
interpret_one();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -223,27 +223,41 @@ const int images_length = (sizeof (images)) / (sizeof (images[0]));
|
||||
const language::option options[] = {
|
||||
{ .string = "Complain", .statementIndex = 19 }, // 0
|
||||
{ .string = "Rationalize", .statementIndex = 27 }, // 1
|
||||
{ .string = "Good idea", .statementIndex = 54 }, // 2
|
||||
{ .string = "I am too tired", .statementIndex = 61 }, // 3
|
||||
{ .string = "Beg for mercy", .statementIndex = 78 }, // 4
|
||||
{ .string = "Run", .statementIndex = 80 }, // 5
|
||||
{ .string = "Good idea", .statementIndex = 53 }, // 2
|
||||
{ .string = "I am too tired", .statementIndex = 60 }, // 3
|
||||
{ .string = "Beg for mercy", .statementIndex = 77 }, // 4
|
||||
{ .string = "Run", .statementIndex = 79 }, // 5
|
||||
};
|
||||
|
||||
const int options_length = (sizeof (options)) / (sizeof (options[0]));
|
||||
|
||||
const language::dissolve dissolves[] = {
|
||||
{ .duration = 3.0, .first_statement = 4, .count = 1 },
|
||||
{ .duration = 3.0, .first_statement = 11, .count = 1 },
|
||||
{ .duration = 1.0, .first_statement = 34, .count = 2 },
|
||||
{ .duration = 1.0, .first_statement = 39, .count = 1 },
|
||||
{ .duration = 3.0, .first_statement = 116, .count = 2 },
|
||||
{ .duration = 3.0, .first_statement = 120, .count = 1 },
|
||||
{ .duration = 2.0, .first_statement = 195, .count = 2 },
|
||||
{ .duration = 1.3, .first_statement = 199, .count = 3 },
|
||||
{ .duration = 3.0, .first_statement = 241, .count = 1 },
|
||||
};
|
||||
|
||||
const int dissolves_length = (sizeof (dissolves)) / (sizeof (dissolves[0]));
|
||||
|
||||
const language::statement statements[] = {
|
||||
{ .type = type::play, .play = { .audioIndex = 0 } }, // 0 sfx/Chime.ogg
|
||||
{ .type = type::play, .play = { .audioIndex = 1 } }, // 1 sfx/MistAmbience.ogg
|
||||
{ .type = type::scene_color, .scene_color = { .color = 0xffffff } }, // 2 bgwhite
|
||||
{ .type = type::dissolve, .dissolve = { .duration = 3.0 } }, // 3
|
||||
{ .type = type::say, .say = { .characterIndex = 4, .stringIndex = 0 } }, // 4 n "Far over the mountains of Almystice"
|
||||
{ .type = type::say, .say = { .characterIndex = 4, .stringIndex = 1 } }, // 5 n "Beyond the tumultuous waters of the Lilac Bay"
|
||||
{ .type = type::say, .say = { .characterIndex = 4, .stringIndex = 2 } }, // 6 n "And across the vast fields of Alysen"
|
||||
{ .type = type::play, .play = { .audioIndex = 2 } }, // 7 music/TinyForestMinstrels.ogg
|
||||
{ .type = type::say, .say = { .characterIndex = 4, .stringIndex = 3 } }, // 8 n "Tiny minstrels can be heard amongst the trees"
|
||||
{ .type = type::stop, .stop = { .audioIndex = 2, .fadeout = 5.5 } }, // 9 TinyForestMinstrels
|
||||
{ .type = type::scene, .scene = { .imageIndex = 1 } }, // 10 bgforest1
|
||||
{ .type = type::dissolve, .dissolve = { .duration = 3.0 } }, // 11
|
||||
{ .type = type::scene_color, .scene_color = { .color = 0x000000 } }, // 2 bgblack
|
||||
{ .type = type::pause, .pause = { .duration = 0.0 } }, // 3
|
||||
{ .type = type::scene_color, .scene_color = { .color = 0xffffff } }, // 4 bgwhite
|
||||
{ .type = type::say, .say = { .characterIndex = 4, .stringIndex = 0 } }, // 5 n "Far over the mountains of Almystice"
|
||||
{ .type = type::say, .say = { .characterIndex = 4, .stringIndex = 1 } }, // 6 n "Beyond the tumultuous waters of the Lilac Bay"
|
||||
{ .type = type::say, .say = { .characterIndex = 4, .stringIndex = 2 } }, // 7 n "And across the vast fields of Alysen"
|
||||
{ .type = type::play, .play = { .audioIndex = 2 } }, // 8 music/TinyForestMinstrels.ogg
|
||||
{ .type = type::say, .say = { .characterIndex = 4, .stringIndex = 3 } }, // 9 n "Tiny minstrels can be heard amongst the trees"
|
||||
{ .type = type::stop, .stop = { .audioIndex = 2, .fadeout = 5.5 } }, // 10 TinyForestMinstrels
|
||||
{ .type = type::scene, .scene = { .imageIndex = 1 } }, // 11 bgforest1
|
||||
{ .type = type::show, .show = { .imageIndex = 8, .transformIndex = transform::left } }, // 12 al
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 4 } }, // 13 a "Are we almost there?"
|
||||
{ .type = type::show, .show = { .imageIndex = 7, .transformIndex = transform::right } }, // 14 ei
|
||||
@ -268,218 +282,215 @@ const language::statement statements[] = {
|
||||
{ .type = type::stop, .stop = { .audioIndex = 2, .fadeout = 5.5 } }, // 33 TinyForestMinstrels
|
||||
{ .type = type::scene_color, .scene_color = { .color = 0xffffff } }, // 34 bgwhite
|
||||
{ .type = type::play, .play = { .audioIndex = 0 } }, // 35 sfx/Chime.ogg
|
||||
{ .type = type::dissolve, .dissolve = { .duration = 1.0 } }, // 36
|
||||
{ .type = type::play, .play = { .audioIndex = 0 } }, // 36 sfx/Chime.ogg
|
||||
{ .type = type::say, .say = { .characterIndex = 4, .stringIndex = 18 } }, // 37 n "As the minstrel mice girls continue along the path, the forest opens up into a beautiful field of flowers"
|
||||
{ .type = type::play, .play = { .audioIndex = 3 } }, // 38 music/PhrygianButterflies.ogg
|
||||
{ .type = type::scene, .scene = { .imageIndex = 3 } }, // 39 bgflower1
|
||||
{ .type = type::dissolve, .dissolve = { .duration = 1.0 } }, // 40
|
||||
{ .type = type::show, .show = { .imageIndex = 7, .transformIndex = transform::right } }, // 41 ei
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 19 } }, // 42 e "Look at all the butterflies! They are all so pretty!"
|
||||
{ .type = type::show, .show = { .imageIndex = 8, .transformIndex = transform::left } }, // 43 al
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 20 } }, // 44 a "This place is like a dream..."
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 21 } }, // 45 e "There are so many flowers this time of year"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 22 } }, // 46 e "I told you it would be worth the journey!"
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 23 } }, // 47 a "Can we stop for a bit now?"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 24 } }, // 48 e "Of course"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 25 } }, // 49 e "Ya know, Its a shame we didnt save some of those giant strawberries you found"
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 26 } }, // 50 a "I told you not to eat them all!"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 27 } }, // 51 e "Yah yah"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 28 } }, // 52 e "Anyways, shall I recite a tale?"
|
||||
{ .type = type::menu, .menu = { .count = 2, .optionIndex = 2 } }, // 53 "Good idea", "I am too tired"
|
||||
{ .type = type::stop, .stop = { .audioIndex = 3, .fadeout = 4.2 } }, // 54 PhrygianButterflies
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 29 } }, // 55 a "Why dont you sing the story of Eleanor the Hero!"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 30 } }, // 56 e "Sure"
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 31 } }, // 57 a "..."
|
||||
{ .type = type::play, .play = { .audioIndex = 4 } }, // 58 music/Poem1.ogg
|
||||
{ .type = type::pause, .pause = { .duration = 40 } }, // 59
|
||||
{ .type = type::jump, .jump = { .statementIndex = 65 } }, // 60 internal jump (b'__menu_end', 1)
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 32 } }, // 61 e "Serves you right for scaring those elephant-dogs"
|
||||
{ .type = type::stop, .stop = { .audioIndex = 3, .fadeout = 4.2 } }, // 62 PhrygianButterflies
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 33 } }, // 63 a "They were asking for it, you know"
|
||||
{ .type = type::jump, .jump = { .statementIndex = 65 } }, // 64 internal jump (b'__menu_end', 1)
|
||||
{ .type = type::jump, .jump = { .statementIndex = 66 } }, // 65 mainbranch2
|
||||
{ .type = type::hide, .hide = { .imageIndex = 7 } }, // 66 ei
|
||||
{ .type = type::show, .show = { .imageIndex = 6, .transformIndex = transform::right } }, // 67 catw
|
||||
{ .type = type::show, .show = { .imageIndex = 7, .transformIndex = transform::centerleft } }, // 68 ei
|
||||
{ .type = type::voice, .voice = { .audioIndex = 5 } }, // 69 placeholdermeow.mp3
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 34 } }, // 70 c "Rawrrrr"
|
||||
{ .type = type::hide, .hide = { .imageIndex = 6 } }, // 71 catw
|
||||
{ .type = type::show, .show = { .imageIndex = 5, .transformIndex = transform::right } }, // 72 cat
|
||||
{ .type = type::play, .play = { .audioIndex = 6 } }, // 73 music/ScaredMice.ogg
|
||||
{ .type = type::say, .say = { .characterIndex = 3, .stringIndex = 35 } }, // 74 mg "AHHHHHHHHHH!!!!!"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 36 } }, // 75 c "Nyanyanyanya"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 37 } }, // 76 c "Well, what do we have here? If it isn't two little meowse girls, all alone amongst the flowers"
|
||||
{ .type = type::menu, .menu = { .count = 2, .optionIndex = 4 } }, // 77 "Beg for mercy", "Run"
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 38 } }, // 78 a "Please don't eat us!!!"
|
||||
{ .type = type::jump, .jump = { .statementIndex = 83 } }, // 79 internal jump (b'__menu_end', 2)
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 39 } }, // 80 e "Alice don't run, our only chance is through pleading!"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 40 } }, // 81 e "Please don't eat us, miss kitty cat!!! ><"
|
||||
{ .type = type::jump, .jump = { .statementIndex = 83 } }, // 82 internal jump (b'__menu_end', 2)
|
||||
{ .type = type::jump, .jump = { .statementIndex = 84 } }, // 83 mainbranch3
|
||||
{ .type = type::stop, .stop = { .audioIndex = 6, .fadeout = 2.0 } }, // 84 ScaredMice
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 41 } }, // 85 c "I'm not gonna eat you nyanyanya"
|
||||
{ .type = type::play, .play = { .audioIndex = 2 } }, // 86 music/TinyForestMinstrels.ogg
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 42 } }, // 87 c "I just want to know what two little meowses are doing so very far away from home"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 43 } }, // 88 c "Also, are you minstrels?"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 44 } }, // 89 e "Y-Yes"
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 45 } }, // 90 a "W-We are on a quest to Castle Alysen..."
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 46 } }, // 91 e "Shh don't tell her that"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 47 } }, // 92 c "The Castle of Alysen you say?!?"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 48 } }, // 93 c "Why, that's where I am headed!"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 49 } }, // 94 e "You don't say..."
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 50 } }, // 95 c "Yah, I do actually"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 51 } }, // 96 e "So... Why might you be traveling to the castle?"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 52 } }, // 97 c "I belong to the lineage of Agrepen"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 53 } }, // 98 e "And what might that mean?"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 54 } }, // 99 c "The Agrepens are a long line of felines loyal to the crown of corvidae"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 55 } }, // 100 e "Really? That must mean you are a noble?"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 56 } }, // 101 c "Well, not really..."
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 57 } }, // 102 c "My father was one of the queens knights many years ago"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 58 } }, // 103 e "Ah I see"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 59 } }, // 104 e "So do you live at the castle or something?"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 60 } }, // 105 c "Well, no..."
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 61 } }, // 106 a "Then why are you traveling to Castle Alysen?"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 62 } }, // 107 c "uhhh"
|
||||
{ .type = type::play, .play = { .audioIndex = 1 } }, // 108 sfx/MistAmbience.ogg
|
||||
{ .type = type::stop, .stop = { .audioIndex = 2, .fadeout = 2.0 } }, // 109 TinyForestMinstrels
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 63 } }, // 110 c "I DONT NEED TO BE PRESSURED BY LITTLE MICE TO SAY ANYTHING!!!!"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 64 } }, // 111 c "GOOD DAY!"
|
||||
{ .type = type::hide, .hide = { .imageIndex = 5 } }, // 112 cat
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 65 } }, // 113 a "Wha..."
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 66 } }, // 114 e "Phew, I was scared she was gonna follow us the whole way"
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 67 } }, // 115 a "She didn't seem so bad"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 68 } }, // 116 e "Are you kidding? She's a crazy kitty!"
|
||||
{ .type = type::scene_color, .scene_color = { .color = 0xffffff } }, // 117 bgwhite
|
||||
{ .type = type::show, .show = { .imageIndex = 7, .transformIndex = transform::right } }, // 40 ei
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 19 } }, // 41 e "Look at all the butterflies! They are all so pretty!"
|
||||
{ .type = type::show, .show = { .imageIndex = 8, .transformIndex = transform::left } }, // 42 al
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 20 } }, // 43 a "This place is like a dream..."
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 21 } }, // 44 e "There are so many flowers this time of year"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 22 } }, // 45 e "I told you it would be worth the journey!"
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 23 } }, // 46 a "Can we stop for a bit now?"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 24 } }, // 47 e "Of course"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 25 } }, // 48 e "Ya know, Its a shame we didnt save some of those giant strawberries you found"
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 26 } }, // 49 a "I told you not to eat them all!"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 27 } }, // 50 e "Yah yah"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 28 } }, // 51 e "Anyways, shall I recite a tale?"
|
||||
{ .type = type::menu, .menu = { .count = 2, .optionIndex = 2 } }, // 52 "Good idea", "I am too tired"
|
||||
{ .type = type::stop, .stop = { .audioIndex = 3, .fadeout = 4.2 } }, // 53 PhrygianButterflies
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 29 } }, // 54 a "Why dont you sing the story of Eleanor the Hero!"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 30 } }, // 55 e "Sure"
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 31 } }, // 56 a "..."
|
||||
{ .type = type::play, .play = { .audioIndex = 4 } }, // 57 music/Poem1.ogg
|
||||
{ .type = type::pause, .pause = { .duration = 40 } }, // 58
|
||||
{ .type = type::jump, .jump = { .statementIndex = 64 } }, // 59 internal jump (b'__menu_end', 1)
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 32 } }, // 60 e "Serves you right for scaring those elephant-dogs"
|
||||
{ .type = type::stop, .stop = { .audioIndex = 3, .fadeout = 4.2 } }, // 61 PhrygianButterflies
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 33 } }, // 62 a "They were asking for it, you know"
|
||||
{ .type = type::jump, .jump = { .statementIndex = 64 } }, // 63 internal jump (b'__menu_end', 1)
|
||||
{ .type = type::jump, .jump = { .statementIndex = 65 } }, // 64 mainbranch2
|
||||
{ .type = type::hide, .hide = { .imageIndex = 7 } }, // 65 ei
|
||||
{ .type = type::show, .show = { .imageIndex = 6, .transformIndex = transform::right } }, // 66 catw
|
||||
{ .type = type::show, .show = { .imageIndex = 7, .transformIndex = transform::centerleft } }, // 67 ei
|
||||
{ .type = type::voice, .voice = { .audioIndex = 5 } }, // 68 placeholdermeow.mp3
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 34 } }, // 69 c "Rawrrrr"
|
||||
{ .type = type::hide, .hide = { .imageIndex = 6 } }, // 70 catw
|
||||
{ .type = type::show, .show = { .imageIndex = 5, .transformIndex = transform::right } }, // 71 cat
|
||||
{ .type = type::play, .play = { .audioIndex = 6 } }, // 72 music/ScaredMice.ogg
|
||||
{ .type = type::say, .say = { .characterIndex = 3, .stringIndex = 35 } }, // 73 mg "AHHHHHHHHHH!!!!!"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 36 } }, // 74 c "Nyanyanyanya"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 37 } }, // 75 c "Well, what do we have here? If it isn't two little meowse girls, all alone amongst the flowers"
|
||||
{ .type = type::menu, .menu = { .count = 2, .optionIndex = 4 } }, // 76 "Beg for mercy", "Run"
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 38 } }, // 77 a "Please don't eat us!!!"
|
||||
{ .type = type::jump, .jump = { .statementIndex = 82 } }, // 78 internal jump (b'__menu_end', 2)
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 39 } }, // 79 e "Alice don't run, our only chance is through pleading!"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 40 } }, // 80 e "Please don't eat us, miss kitty cat!!! ><"
|
||||
{ .type = type::jump, .jump = { .statementIndex = 82 } }, // 81 internal jump (b'__menu_end', 2)
|
||||
{ .type = type::jump, .jump = { .statementIndex = 83 } }, // 82 mainbranch3
|
||||
{ .type = type::stop, .stop = { .audioIndex = 6, .fadeout = 2.0 } }, // 83 ScaredMice
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 41 } }, // 84 c "I'm not gonna eat you nyanyanya"
|
||||
{ .type = type::play, .play = { .audioIndex = 2 } }, // 85 music/TinyForestMinstrels.ogg
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 42 } }, // 86 c "I just want to know what two little meowses are doing so very far away from home"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 43 } }, // 87 c "Also, are you minstrels?"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 44 } }, // 88 e "Y-Yes"
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 45 } }, // 89 a "W-We are on a quest to Castle Alysen..."
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 46 } }, // 90 e "Shh don't tell her that"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 47 } }, // 91 c "The Castle of Alysen you say?!?"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 48 } }, // 92 c "Why, that's where I am headed!"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 49 } }, // 93 e "You don't say..."
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 50 } }, // 94 c "Yah, I do actually"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 51 } }, // 95 e "So... Why might you be traveling to the castle?"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 52 } }, // 96 c "I belong to the lineage of Agrepen"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 53 } }, // 97 e "And what might that mean?"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 54 } }, // 98 c "The Agrepens are a long line of felines loyal to the crown of corvidae"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 55 } }, // 99 e "Really? That must mean you are a noble?"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 56 } }, // 100 c "Well, not really..."
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 57 } }, // 101 c "My father was one of the queens knights many years ago"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 58 } }, // 102 e "Ah I see"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 59 } }, // 103 e "So do you live at the castle or something?"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 60 } }, // 104 c "Well, no..."
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 61 } }, // 105 a "Then why are you traveling to Castle Alysen?"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 62 } }, // 106 c "uhhh"
|
||||
{ .type = type::play, .play = { .audioIndex = 1 } }, // 107 sfx/MistAmbience.ogg
|
||||
{ .type = type::stop, .stop = { .audioIndex = 2, .fadeout = 2.0 } }, // 108 TinyForestMinstrels
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 63 } }, // 109 c "I DONT NEED TO BE PRESSURED BY LITTLE MICE TO SAY ANYTHING!!!!"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 64 } }, // 110 c "GOOD DAY!"
|
||||
{ .type = type::hide, .hide = { .imageIndex = 5 } }, // 111 cat
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 65 } }, // 112 a "Wha..."
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 66 } }, // 113 e "Phew, I was scared she was gonna follow us the whole way"
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 67 } }, // 114 a "She didn't seem so bad"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 68 } }, // 115 e "Are you kidding? She's a crazy kitty!"
|
||||
{ .type = type::scene_color, .scene_color = { .color = 0xffffff } }, // 116 bgwhite
|
||||
{ .type = type::play, .play = { .audioIndex = 0 } }, // 117 sfx/Chime.ogg
|
||||
{ .type = type::play, .play = { .audioIndex = 0 } }, // 118 sfx/Chime.ogg
|
||||
{ .type = type::dissolve, .dissolve = { .duration = 3.0 } }, // 119
|
||||
{ .type = type::say, .say = { .characterIndex = 4, .stringIndex = 69 } }, // 120 n "After their encounter with the weird cat, the mice scurry out of the flower field and into the nearby meadow"
|
||||
{ .type = type::scene, .scene = { .imageIndex = 2 } }, // 121 bgforest2
|
||||
{ .type = type::dissolve, .dissolve = { .duration = 3.0 } }, // 122
|
||||
{ .type = type::show, .show = { .imageIndex = 7, .transformIndex = transform::right } }, // 123 ei
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 70 } }, // 124 e "I think this is the right way..."
|
||||
{ .type = type::show, .show = { .imageIndex = 8, .transformIndex = transform::left } }, // 125 al
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 71 } }, // 126 a "Then where did the path go?"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 72 } }, // 127 e "How am I supposed to know?"
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 73 } }, // 128 a "Did you hear that?!?!"
|
||||
{ .type = type::show, .show = { .imageIndex = 7, .transformIndex = transform::centerleft } }, // 129 ei
|
||||
{ .type = type::show, .show = { .imageIndex = 5, .transformIndex = transform::right } }, // 130 cat
|
||||
{ .type = type::play, .play = { .audioIndex = 3 } }, // 131 music/PhrygianButterflies.ogg
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 74 } }, // 132 c "Hey there..."
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 75 } }, // 133 c "I apologize"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 76 } }, // 134 c "I didn't mean to storm off like that"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 77 } }, // 135 e "Ha ha, no problem..."
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 78 } }, // 136 a "So... Why are you traveling to Castle Alysen?"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 79 } }, // 137 e "Alice!!!"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 80 } }, // 138 c "If you must know, I have been summoned by the queen"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 81 } }, // 139 c "I suspect that my poor reputation amongst the locals of Eastern Nidus has come back to haunt me"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 82 } }, // 140 c "Though I know not what what she has summoned me for"
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 83 } }, // 141 a "Ahhhhhh"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 84 } }, // 142 c "So then..."
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 85 } }, // 143 c "Why are YOU traveling to the Castle?"
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 86 } }, // 144 a "We are delivering a feather!!!"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 87 } }, // 145 e "Alice no!"
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 88 } }, // 146 a "A feather that belonged to the queen herself!!!"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 89 } }, // 147 e "Why you little..."
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 90 } }, // 148 c "A feather you say? One of the queens?"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 91 } }, // 149 c "How on the face of Al Mot might you have aquired such a thing?"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 92 } }, // 150 c "If it is authentic, that is..."
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 93 } }, // 151 e "Since Alice cannot keep a secret, I shall tell you"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 94 } }, // 152 e "Seven moons ago, our town was attacked by three owls and a band of mice from the northern principalities"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 95 } }, // 153 e "Eventually word spread to greater nearby settlements, and so"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 96 } }, // 154 e "Messengers from the keep in Musia sent for aid from the Ravens"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 97 } }, // 155 e "Four moons ago, the request was answered"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 98 } }, // 156 e "And a small group of mice accompanied by two ravens a fox, and three squirrels set out to the northern principalities"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 99 } }, // 157 e "Anyways, long story short, we drove those barbaric rats out of their home"
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 100 } }, // 158 a "They arent actual rats you know"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 101 } }, // 159 e "Obviously, but you wont catch me speaking kindly of them"
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 102 } }, // 160 a "And you forgot the most important part"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 103 } }, // 161 e "Yah yah, I am getting there"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 104 } }, // 162 e "So, essentially, my brother is trained in archery, and..."
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 105 } }, // 163 a "Speed it up already"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 106 } }, // 164 e "You tell it then!"
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 107 } }, // 165 a "My cousin found this feather in one of the highest towers of a castle far to the north"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 108 } }, // 166 c "How do you know it belongs to the queen?"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 109 } }, // 167 e "It said so itself above the display on the wall"
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 110 } }, // 168 a "Supposedly, it was in a room filled with treasures!"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 111 } }, // 169 c "That is very nice and all, but what are the two of you doing out here all alone?"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 112 } }, // 170 c "Do you expect every bird in Avia to respect your alliance with Castle Alysen?"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 113 } }, // 171 e "What do you mean?"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 114 } }, // 172 c "I mean, the two of you probably look like walking dinner to most creatures"
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 115 } }, // 173 a "I could go for some dinner..."
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 116 } }, // 174 e "Anyways..."
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 117 } }, // 175 e "To answer your question, upon returning to the village, the feather was taken from my brother by the needle guild"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 118 } }, // 176 e "So... Yesterday, after sundown"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 119 } }, // 177 e "We stole the feather from the guild hall before vanishing into the night"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 120 } }, // 178 e "Can you imagine the look on their stupid faces, when they woke up, and not only is the feather missing"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 121 } }, // 179 e "But so are we!"
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 122 } }, // 180 a "Hahahaha"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 123 } }, // 181 c "Are the two of you mad?"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 124 } }, // 182 c "I assume you are attempting to return the Queens feather?"
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 125 } }, // 183 a "Yes, we intend to deliver the feather to its rightful owner"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 126 } }, // 184 c "Absolute madness!"
|
||||
{ .type = type::say, .say = { .characterIndex = 3, .stringIndex = 31 } }, // 185 mg "..."
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 127 } }, // 186 c "I will follow the two of you"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 128 } }, // 187 c "To keep you safe, that is"
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 129 } }, // 188 a "Alright!"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 130 } }, // 189 e "Ha ha... Okay..."
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 131 } }, // 190 c "Great! Follow me, I know a shortcut! :3"
|
||||
{ .type = type::hide, .hide = { .imageIndex = 5 } }, // 191 cat
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 132 } }, // 192 a "Sounds good!"
|
||||
{ .type = type::hide, .hide = { .imageIndex = 8 } }, // 193 al
|
||||
{ .type = type::stop, .stop = { .audioIndex = 3, .fadeout = 2.0 } }, // 194 PhrygianButterflies
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 133 } }, // 195 e "Oh dear!"
|
||||
{ .type = type::hide, .hide = { .imageIndex = 7 } }, // 196 ei
|
||||
{ .type = type::scene_color, .scene_color = { .color = 0xffffff } }, // 197 bgwhite
|
||||
{ .type = type::play, .play = { .audioIndex = 0 } }, // 198 sfx/Chime.ogg
|
||||
{ .type = type::dissolve, .dissolve = { .duration = 2.0 } }, // 199
|
||||
{ .type = type::say, .say = { .characterIndex = 4, .stringIndex = 134 } }, // 200 n "And so the mice girls follow the noble cat further towards their destination"
|
||||
{ .type = type::scene, .scene = { .imageIndex = 4 } }, // 201 bgwheatfield1
|
||||
{ .type = type::play, .play = { .audioIndex = 7 } }, // 202 music/WheatFields.ogg
|
||||
{ .type = type::show, .show = { .imageIndex = 5, .transformIndex = transform::right } }, // 203 cat
|
||||
{ .type = type::dissolve, .dissolve = { .duration = 1.3 } }, // 204
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 135 } }, // 205 c "Nya"
|
||||
{ .type = type::show, .show = { .imageIndex = 8, .transformIndex = transform::left } }, // 206 al
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 136 } }, // 207 a "Look, your right, the castle is just up ahead!"
|
||||
{ .type = type::show, .show = { .imageIndex = 7, .transformIndex = transform::centerleft } }, // 208 ei
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 137 } }, // 209 e "Wait up"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 138 } }, // 210 c "I told you I knew a shortcut!"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 139 } }, // 211 c "Most people take the long way around"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 140 } }, // 212 e "Yah because these are royal wheatfields!"
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 141 } }, // 213 a "Who cares?"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 142 } }, // 214 e "Are you trying to get us killed?"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 143 } }, // 215 e "Its trespassing on royal land!"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 144 } }, // 216 c "Calm down, I have done this a million times"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 145 } }, // 217 e "That doesnt make me calm!"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 146 } }, // 218 c "How can the rolling fields of wheat not calm your spirit?"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 147 } }, // 219 c "You little mice truly are mad!"
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 148 } }, // 220 a "I like the wheat!"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 149 } }, // 221 e "Shut up!"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 150 } }, // 222 c "Sounds like someone needs a nap!"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 151 } }, // 223 e "Why? because I'm not insane like you?"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 152 } }, // 224 c "Yah, your so sane, that you decided to steal from your town and then run off alone to the country of birds"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 153 } }, // 225 c "The power of friendship wont protect the two of you from becoming dinner"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 154 } }, // 226 c "And that, is why I feel obligated to accompany you!"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 155 } }, // 227 e "Hey, we have a good reason!"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 156 } }, // 228 c "And what might that be?"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 157 } }, // 229 e "My brother found the feather, not the town guild, its a matter of family pride!"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 158 } }, // 230 c "Pride has touched the chosen meouse"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 159 } }, // 231 c "Flies she towards the Castle"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 160 } }, // 232 c "But her ambition burns far too bright, and silly myice dont have any wings to myelt"
|
||||
{ .type = type::say, .say = { .characterIndex = 3, .stringIndex = 161 } }, // 233 mg "What?"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 162 } }, // 234 c "Nyanyanya"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 163 } }, // 235 c "Nyevermind"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 164 } }, // 236 c "Sing me a song little minstrels!"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 165 } }, // 237 c "Very Nyice!"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 166 } }, // 238 c "Now tell me little minstrels, what are your names?"
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 167 } }, // 239 a "My name is Alice"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 168 } }, // 240 e "And my name is Eily"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 169 } }, // 241 e "What is your name?"
|
||||
{ .type = type::say, .say = { .characterIndex = 5, .stringIndex = 170 } }, // 242 l "My name is Leona!"
|
||||
{ .type = type::scene_color, .scene_color = { .color = 0xffffff } }, // 243 bgwhite
|
||||
{ .type = type::dissolve, .dissolve = { .duration = 3.0 } }, // 244
|
||||
{ .type = type::say, .say = { .characterIndex = 4, .stringIndex = 171 } }, // 245 n "And so, the odd trio walked through the wheatfields and towards the castle walls"
|
||||
{ .type = type::say, .say = { .characterIndex = 4, .stringIndex = 172 } }, // 246 n "Upon approaching the castle walls"
|
||||
{ .type = type::_return }, // 247
|
||||
{ .type = type::say, .say = { .characterIndex = 4, .stringIndex = 69 } }, // 119 n "After their encounter with the weird cat, the mice scurry out of the flower field and into the nearby meadow"
|
||||
{ .type = type::scene, .scene = { .imageIndex = 2 } }, // 120 bgforest2
|
||||
{ .type = type::show, .show = { .imageIndex = 7, .transformIndex = transform::right } }, // 121 ei
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 70 } }, // 122 e "I think this is the right way..."
|
||||
{ .type = type::show, .show = { .imageIndex = 8, .transformIndex = transform::left } }, // 123 al
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 71 } }, // 124 a "Then where did the path go?"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 72 } }, // 125 e "How am I supposed to know?"
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 73 } }, // 126 a "Did you hear that?!?!"
|
||||
{ .type = type::show, .show = { .imageIndex = 7, .transformIndex = transform::centerleft } }, // 127 ei
|
||||
{ .type = type::show, .show = { .imageIndex = 5, .transformIndex = transform::right } }, // 128 cat
|
||||
{ .type = type::play, .play = { .audioIndex = 3 } }, // 129 music/PhrygianButterflies.ogg
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 74 } }, // 130 c "Hey there..."
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 75 } }, // 131 c "I apologize"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 76 } }, // 132 c "I didn't mean to storm off like that"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 77 } }, // 133 e "Ha ha, no problem..."
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 78 } }, // 134 a "So... Why are you traveling to Castle Alysen?"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 79 } }, // 135 e "Alice!!!"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 80 } }, // 136 c "If you must know, I have been summoned by the queen"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 81 } }, // 137 c "I suspect that my poor reputation amongst the locals of Eastern Nidus has come back to haunt me"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 82 } }, // 138 c "Though I know not what what she has summoned me for"
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 83 } }, // 139 a "Ahhhhhh"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 84 } }, // 140 c "So then..."
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 85 } }, // 141 c "Why are YOU traveling to the Castle?"
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 86 } }, // 142 a "We are delivering a feather!!!"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 87 } }, // 143 e "Alice no!"
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 88 } }, // 144 a "A feather that belonged to the queen herself!!!"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 89 } }, // 145 e "Why you little..."
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 90 } }, // 146 c "A feather you say? One of the queens?"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 91 } }, // 147 c "How on the face of Al Mot might you have aquired such a thing?"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 92 } }, // 148 c "If it is authentic, that is..."
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 93 } }, // 149 e "Since Alice cannot keep a secret, I shall tell you"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 94 } }, // 150 e "Seven moons ago, our town was attacked by three owls and a band of mice from the northern principalities"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 95 } }, // 151 e "Eventually word spread to greater nearby settlements, and so"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 96 } }, // 152 e "Messengers from the keep in Musia sent for aid from the Ravens"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 97 } }, // 153 e "Four moons ago, the request was answered"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 98 } }, // 154 e "And a small group of mice accompanied by two ravens a fox, and three squirrels set out to the northern principalities"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 99 } }, // 155 e "Anyways, long story short, we drove those barbaric rats out of their home"
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 100 } }, // 156 a "They arent actual rats you know"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 101 } }, // 157 e "Obviously, but you wont catch me speaking kindly of them"
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 102 } }, // 158 a "And you forgot the most important part"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 103 } }, // 159 e "Yah yah, I am getting there"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 104 } }, // 160 e "So, essentially, my brother is trained in archery, and..."
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 105 } }, // 161 a "Speed it up already"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 106 } }, // 162 e "You tell it then!"
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 107 } }, // 163 a "My cousin found this feather in one of the highest towers of a castle far to the north"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 108 } }, // 164 c "How do you know it belongs to the queen?"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 109 } }, // 165 e "It said so itself above the display on the wall"
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 110 } }, // 166 a "Supposedly, it was in a room filled with treasures!"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 111 } }, // 167 c "That is very nice and all, but what are the two of you doing out here all alone?"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 112 } }, // 168 c "Do you expect every bird in Avia to respect your alliance with Castle Alysen?"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 113 } }, // 169 e "What do you mean?"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 114 } }, // 170 c "I mean, the two of you probably look like walking dinner to most creatures"
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 115 } }, // 171 a "I could go for some dinner..."
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 116 } }, // 172 e "Anyways..."
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 117 } }, // 173 e "To answer your question, upon returning to the village, the feather was taken from my brother by the needle guild"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 118 } }, // 174 e "So... Yesterday, after sundown"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 119 } }, // 175 e "We stole the feather from the guild hall before vanishing into the night"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 120 } }, // 176 e "Can you imagine the look on their stupid faces, when they woke up, and not only is the feather missing"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 121 } }, // 177 e "But so are we!"
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 122 } }, // 178 a "Hahahaha"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 123 } }, // 179 c "Are the two of you mad?"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 124 } }, // 180 c "I assume you are attempting to return the Queens feather?"
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 125 } }, // 181 a "Yes, we intend to deliver the feather to its rightful owner"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 126 } }, // 182 c "Absolute madness!"
|
||||
{ .type = type::say, .say = { .characterIndex = 3, .stringIndex = 31 } }, // 183 mg "..."
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 127 } }, // 184 c "I will follow the two of you"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 128 } }, // 185 c "To keep you safe, that is"
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 129 } }, // 186 a "Alright!"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 130 } }, // 187 e "Ha ha... Okay..."
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 131 } }, // 188 c "Great! Follow me, I know a shortcut! :3"
|
||||
{ .type = type::hide, .hide = { .imageIndex = 5 } }, // 189 cat
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 132 } }, // 190 a "Sounds good!"
|
||||
{ .type = type::hide, .hide = { .imageIndex = 8 } }, // 191 al
|
||||
{ .type = type::stop, .stop = { .audioIndex = 3, .fadeout = 2.0 } }, // 192 PhrygianButterflies
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 133 } }, // 193 e "Oh dear!"
|
||||
{ .type = type::hide, .hide = { .imageIndex = 7 } }, // 194 ei
|
||||
{ .type = type::scene_color, .scene_color = { .color = 0xffffff } }, // 195 bgwhite
|
||||
{ .type = type::play, .play = { .audioIndex = 0 } }, // 196 sfx/Chime.ogg
|
||||
{ .type = type::play, .play = { .audioIndex = 0 } }, // 197 sfx/Chime.ogg
|
||||
{ .type = type::say, .say = { .characterIndex = 4, .stringIndex = 134 } }, // 198 n "And so the mice girls follow the noble cat further towards their destination"
|
||||
{ .type = type::scene, .scene = { .imageIndex = 4 } }, // 199 bgwheatfield1
|
||||
{ .type = type::play, .play = { .audioIndex = 7 } }, // 200 music/WheatFields.ogg
|
||||
{ .type = type::show, .show = { .imageIndex = 5, .transformIndex = transform::right } }, // 201 cat
|
||||
{ .type = type::show, .show = { .imageIndex = 5, .transformIndex = transform::right } }, // 202 cat
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 135 } }, // 203 c "Nya"
|
||||
{ .type = type::show, .show = { .imageIndex = 8, .transformIndex = transform::left } }, // 204 al
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 136 } }, // 205 a "Look, your right, the castle is just up ahead!"
|
||||
{ .type = type::show, .show = { .imageIndex = 7, .transformIndex = transform::centerleft } }, // 206 ei
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 137 } }, // 207 e "Wait up"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 138 } }, // 208 c "I told you I knew a shortcut!"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 139 } }, // 209 c "Most people take the long way around"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 140 } }, // 210 e "Yah because these are royal wheatfields!"
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 141 } }, // 211 a "Who cares?"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 142 } }, // 212 e "Are you trying to get us killed?"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 143 } }, // 213 e "Its trespassing on royal land!"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 144 } }, // 214 c "Calm down, I have done this a million times"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 145 } }, // 215 e "That doesnt make me calm!"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 146 } }, // 216 c "How can the rolling fields of wheat not calm your spirit?"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 147 } }, // 217 c "You little mice truly are mad!"
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 148 } }, // 218 a "I like the wheat!"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 149 } }, // 219 e "Shut up!"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 150 } }, // 220 c "Sounds like someone needs a nap!"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 151 } }, // 221 e "Why? because I'm not insane like you?"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 152 } }, // 222 c "Yah, your so sane, that you decided to steal from your town and then run off alone to the country of birds"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 153 } }, // 223 c "The power of friendship wont protect the two of you from becoming dinner"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 154 } }, // 224 c "And that, is why I feel obligated to accompany you!"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 155 } }, // 225 e "Hey, we have a good reason!"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 156 } }, // 226 c "And what might that be?"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 157 } }, // 227 e "My brother found the feather, not the town guild, its a matter of family pride!"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 158 } }, // 228 c "Pride has touched the chosen meouse"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 159 } }, // 229 c "Flies she towards the Castle"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 160 } }, // 230 c "But her ambition burns far too bright, and silly myice dont have any wings to myelt"
|
||||
{ .type = type::say, .say = { .characterIndex = 3, .stringIndex = 161 } }, // 231 mg "What?"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 162 } }, // 232 c "Nyanyanya"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 163 } }, // 233 c "Nyevermind"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 164 } }, // 234 c "Sing me a song little minstrels!"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 165 } }, // 235 c "Very Nyice!"
|
||||
{ .type = type::say, .say = { .characterIndex = 1, .stringIndex = 166 } }, // 236 c "Now tell me little minstrels, what are your names?"
|
||||
{ .type = type::say, .say = { .characterIndex = 0, .stringIndex = 167 } }, // 237 a "My name is Alice"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 168 } }, // 238 e "And my name is Eily"
|
||||
{ .type = type::say, .say = { .characterIndex = 2, .stringIndex = 169 } }, // 239 e "What is your name?"
|
||||
{ .type = type::say, .say = { .characterIndex = 5, .stringIndex = 170 } }, // 240 l "My name is Leona!"
|
||||
{ .type = type::scene_color, .scene_color = { .color = 0xffffff } }, // 241 bgwhite
|
||||
{ .type = type::say, .say = { .characterIndex = 4, .stringIndex = 171 } }, // 242 n "And so, the odd trio walked through the wheatfields and towards the castle walls"
|
||||
{ .type = type::say, .say = { .characterIndex = 4, .stringIndex = 172 } }, // 243 n "Upon approaching the castle walls"
|
||||
{ .type = type::_return }, // 244
|
||||
};
|
||||
|
||||
const int statements_length = (sizeof (statements)) / (sizeof (statements[0]));
|
||||
|
||||
@ -514,31 +514,30 @@ namespace renpy {
|
||||
// draw
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
void vulkan::draw(VkCommandBuffer commandBuffer,
|
||||
void vulkan::draw_menu_frame(VkCommandBuffer commandBuffer,
|
||||
uint32_t frameIndex,
|
||||
renpy::interpreter const& state,
|
||||
int mx,
|
||||
int my)
|
||||
int & outputIndex,
|
||||
int mx, int my) const
|
||||
{
|
||||
int outputIndex = 0;
|
||||
// update
|
||||
instanceMappedData[maximumImageCount * frameIndex + outputIndex++] = {
|
||||
.size = {1280, 720},
|
||||
.topLeft = {0, 0},
|
||||
.color = state.backgroundColor,
|
||||
.imageIndex = (int16_t)state.backgroundIndex,
|
||||
};
|
||||
for (uint32_t i = 0; i < state.menu.count; i++) {
|
||||
int y = menu::yStride * i + menu::y;
|
||||
|
||||
for (uint32_t i = 0; i < state.shownImagesCount; i++) {
|
||||
renpy::top_left const& tl = renpy::transforms[state.shownImages[i].transformIndex];
|
||||
bool overlap = renpy::overlap(menu::width, menu::height, menu::x, y, mx, my);
|
||||
instanceMappedData[maximumImageCount * frameIndex + outputIndex++] = {
|
||||
.size = {452, 528},
|
||||
.topLeft = {(int16_t)tl.left, (int16_t)tl.top},
|
||||
.imageIndex = (int16_t)state.shownImages[i].imageIndex,
|
||||
.size = {menu::width, menu::height},
|
||||
.topLeft = {menu::x, (int16_t)(y)},
|
||||
.color = overlap ? 0xf0494493u : 0xa0ffffffu,
|
||||
.imageIndex = -3, // white gradient 2
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (state.menu.count == 0) {
|
||||
void vulkan::draw_say_frame(VkCommandBuffer commandBuffer,
|
||||
uint32_t frameIndex,
|
||||
renpy::interpreter const& state,
|
||||
int & outputIndex) const
|
||||
{
|
||||
instanceMappedData[maximumImageCount * frameIndex + outputIndex++] = {
|
||||
.size = {708, 200},
|
||||
.topLeft = {286, 720 - 200},
|
||||
@ -564,17 +563,37 @@ namespace renpy {
|
||||
.imageIndex = -4, // white gradient 2
|
||||
};
|
||||
}
|
||||
} else {
|
||||
for (uint32_t i = 0; i < state.menu.count; i++) {
|
||||
int y = menu::yStride * i + menu::y;
|
||||
}
|
||||
|
||||
bool overlap = renpy::overlap(menu::width, menu::height, menu::x, y, mx, my);
|
||||
void vulkan::draw(VkCommandBuffer commandBuffer,
|
||||
uint32_t frameIndex,
|
||||
renpy::interpreter const& state,
|
||||
int mx, int my,
|
||||
bool drawText) const
|
||||
{
|
||||
int outputIndex = 0;
|
||||
// update
|
||||
instanceMappedData[maximumImageCount * frameIndex + outputIndex++] = {
|
||||
.size = {menu::width, menu::height},
|
||||
.topLeft = {menu::x, (int16_t)(y)},
|
||||
.color = overlap ? 0xf0494493u : 0xa0ffffffu,
|
||||
.imageIndex = -3, // white gradient 2
|
||||
.size = {1280, 720},
|
||||
.topLeft = {0, 0},
|
||||
.color = state.backgroundColor,
|
||||
.imageIndex = (int16_t)state.backgroundIndex,
|
||||
};
|
||||
|
||||
for (uint32_t i = 0; i < state.shownImagesCount; i++) {
|
||||
renpy::top_left const& tl = renpy::transforms[state.shownImages[i].transformIndex];
|
||||
instanceMappedData[maximumImageCount * frameIndex + outputIndex++] = {
|
||||
.size = {452, 528},
|
||||
.topLeft = {(int16_t)tl.left, (int16_t)tl.top},
|
||||
.imageIndex = (int16_t)state.shownImages[i].imageIndex,
|
||||
};
|
||||
}
|
||||
|
||||
if (drawText) {
|
||||
if (state.menu.count != 0) {
|
||||
draw_menu_frame(commandBuffer, frameIndex, state, outputIndex, mx, my);
|
||||
} else if (state.say.stringIndex != ~0u) {
|
||||
draw_say_frame(commandBuffer, frameIndex, state, outputIndex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,2 +1 @@
|
||||
export VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation
|
||||
export VK_VALIDATION_VALIDATE_SYNC=1
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user