The Omega Refactor(TM) + Input Options
This commit is contained in:
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -8,6 +8,3 @@
|
||||
[submodule "include/tinyxml2"]
|
||||
path = include/tinyxml2
|
||||
url = https://github.com/leethomason/tinyxml2
|
||||
[submodule "include/inih"]
|
||||
path = include/inih
|
||||
url = https://github.com/benhoyt/inih
|
||||
|
@@ -1,11 +1,10 @@
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
# at least some form of vcpkg detect...
|
||||
if(WIN32 AND DEFINED ENV{VCPKG_ROOT} AND NOT DEFINED CMAKE_TOOLCHAIN_FILE)
|
||||
set(CMAKE_TOOLCHAIN_FILE "$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake"
|
||||
CACHE STRING "Vcpkg toolchain file")
|
||||
endif()
|
||||
|
||||
project(anm2ed C CXX)
|
||||
project(anm2ed CXX)
|
||||
|
||||
find_package(SDL3 REQUIRED CONFIG REQUIRED COMPONENTS SDL3-shared)
|
||||
find_package(GLEW REQUIRED)
|
||||
@@ -20,28 +19,23 @@ file(GLOB SOURCES
|
||||
"include/imgui/backends/imgui_impl_sdl3.cpp"
|
||||
"include/imgui/backends/imgui_impl_opengl3.cpp"
|
||||
"include/tinyxml2/tinyxml2.cpp"
|
||||
"include/inih/ini.c"
|
||||
"${PROJECT_SOURCE_DIR}/src/*.cpp"
|
||||
"${PROJECT_SOURCE_DIR}/src/*.h"
|
||||
)
|
||||
|
||||
add_executable(${PROJECT_NAME} ${SOURCES})
|
||||
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE include include/imgui include/tinyxml2 include/inih src)
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE include include/imgui include/tinyxml2 src)
|
||||
if (NOT MSVC)
|
||||
set(CMAKE_CXX_FLAGS "-g -O2 -std=c++23 -Wall -Wextra -pedantic -Wno-unused-variable -Wno-unused-parameter -Wno-ignored-qualifiers -Wno-parentheses -Wno-missing-field-initializers -Wno-unused-function -Wno-class-memaccess -Wno-delete-incomplete")
|
||||
set(CMAKE_CXX_FLAGS "-g -O2 -std=c++23 -Wall -Wextra -pedantic -fmax-errors=1")
|
||||
else()
|
||||
# /std:c++latest is required to make MSVC grant access to all the latest C++ stuff (C++23 is listed as preview even on dev previews of MSVC....)
|
||||
# /STACK allocation size change is a hack, a proper fix would be to remove all the instances of allocating gigantic objects on the stack :pleading_face:
|
||||
# /EHsc is probably also a hack, makes compile warnings about std::chrono go away
|
||||
set(CMAKE_CXX_FLAGS "/std:c++latest /EHsc")
|
||||
target_link_options(${PROJECT_NAME} PRIVATE "/STACK:0xffffff")
|
||||
set(CMAKE_CXX_FLAGS "/std:c++latest /EHsc") # /std:c++latest is required to make MSVC grant access to all the latest C++ stuff (C++23 is listed as preview even on dev previews of MSVC....)
|
||||
endif()
|
||||
|
||||
if(NOT MSVC)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE m)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE m)
|
||||
endif()
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE OpenGL::GL GLEW::GLEW SDL3::SDL3)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE OpenGL::GL GLEW::GLEW SDL3::SDL3)
|
||||
|
||||
message("System: ${CMAKE_SYSTEM_NAME}")
|
||||
message("Project: ${PROJECT_NAME}")
|
||||
|
69
settings.ini
69
settings.ini
@@ -1,69 +0,0 @@
|
||||
[Settings]
|
||||
panX=-521.000000
|
||||
panY=258.000000
|
||||
|
||||
# Dear ImGui
|
||||
[Window][Window]
|
||||
Pos=0,32
|
||||
Size=1918,1030
|
||||
Collapsed=0
|
||||
|
||||
[Window][Debug##Default]
|
||||
Pos=60,60
|
||||
Size=400,400
|
||||
Collapsed=0
|
||||
|
||||
[Window][Animations]
|
||||
Pos=1197,40
|
||||
Size=485,342
|
||||
Collapsed=0
|
||||
DockId=0x00000005,0
|
||||
|
||||
[Window][Events]
|
||||
Pos=1197,384
|
||||
Size=485,345
|
||||
Collapsed=0
|
||||
DockId=0x00000006,0
|
||||
|
||||
[Window][Spritesheets]
|
||||
Pos=1684,40
|
||||
Size=226,689
|
||||
Collapsed=0
|
||||
DockId=0x00000002,0
|
||||
|
||||
[Window][Spritesheet Editor]
|
||||
Pos=60,60
|
||||
Size=32,35
|
||||
Collapsed=0
|
||||
|
||||
[Window][Timeline]
|
||||
Pos=8,731
|
||||
Size=1902,323
|
||||
Collapsed=0
|
||||
DockId=0x0000000A,0
|
||||
|
||||
[Window][Frame Properties]
|
||||
Pos=890,40
|
||||
Size=305,689
|
||||
Collapsed=0
|
||||
DockId=0x00000008,0
|
||||
|
||||
[Window][Animation Preview]
|
||||
Pos=8,40
|
||||
Size=880,689
|
||||
Collapsed=0
|
||||
DockId=0x00000007,0
|
||||
|
||||
[Docking][Data]
|
||||
DockSpace ID=0xFB691B2E Window=0xFA2EAA04 Pos=8,40 Size=1902,1014 Split=Y Selected=0x024430EF
|
||||
DockNode ID=0x00000009 Parent=0xFB691B2E SizeRef=1902,689 Split=X
|
||||
DockNode ID=0x00000001 Parent=0x00000009 SizeRef=1674,1014 Split=X Selected=0x024430EF
|
||||
DockNode ID=0x00000003 Parent=0x00000001 SizeRef=1187,1014 Split=X Selected=0x024430EF
|
||||
DockNode ID=0x00000007 Parent=0x00000003 SizeRef=880,1014 CentralNode=1 Selected=0x024430EF
|
||||
DockNode ID=0x00000008 Parent=0x00000003 SizeRef=305,1014 Selected=0x754E368F
|
||||
DockNode ID=0x00000004 Parent=0x00000001 SizeRef=485,1014 Split=Y Selected=0x8A65D963
|
||||
DockNode ID=0x00000005 Parent=0x00000004 SizeRef=485,504 Selected=0xC1986EE2
|
||||
DockNode ID=0x00000006 Parent=0x00000004 SizeRef=485,508 Selected=0x8A65D963
|
||||
DockNode ID=0x00000002 Parent=0x00000009 SizeRef=226,1014 Selected=0x4EFD0020
|
||||
DockNode ID=0x0000000A Parent=0xFB691B2E SizeRef=1902,323 Selected=0x4F89F0DC
|
||||
|
103
src/COMMON.h
103
src/COMMON.h
@@ -2,34 +2,29 @@
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
#include <GL/glew.h>
|
||||
#include <GL/gl.h>
|
||||
#include <glm/glm/glm.hpp>
|
||||
#include <glm/glm/gtc/type_ptr.hpp>
|
||||
#include <glm/glm/gtc/matrix_transform.hpp>
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <tinyxml2.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <filesystem>
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <cstring>
|
||||
#include <filesystem>
|
||||
#include <format>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <ranges>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <ranges>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "STRINGS.h"
|
||||
|
||||
#ifndef PATH_MAX
|
||||
#define PATH_MAX 4096
|
||||
#endif
|
||||
|
||||
typedef uint8_t u8;
|
||||
typedef uint16_t u16;
|
||||
typedef uint32_t u32;
|
||||
@@ -46,14 +41,58 @@ typedef double f64;
|
||||
#define PI (GLM_PI)
|
||||
#define TAU (PI * 2)
|
||||
|
||||
using namespace glm; // fuck you
|
||||
using namespace glm;
|
||||
|
||||
#define MIN(x, min) (x < min ? min : x)
|
||||
#define MAX(x, max) (x > max ? max : x)
|
||||
#define CLAMP(x, min, max) (MIN(MAX(x, max), min))
|
||||
|
||||
// Converts a string to a bool
|
||||
static inline bool string_to_bool(const std::string& string)
|
||||
{
|
||||
return string == "true" || string == "1";
|
||||
};
|
||||
|
||||
// Given a file path, sets the working directory to it
|
||||
static inline void working_directory_from_file_set(const std::string& path)
|
||||
{
|
||||
std::filesystem::path filePath = path;
|
||||
std::filesystem::path parentPath = filePath.parent_path();
|
||||
std::filesystem::current_path(parentPath);
|
||||
};
|
||||
|
||||
// Converts an enum to a string value
|
||||
static inline const char* enum_to_string(const char* array[], s32 count, s32 index)
|
||||
{
|
||||
return (index >= 0 && index < count) ? array[index] : "";
|
||||
};
|
||||
|
||||
// Converts a string to an enum value
|
||||
static inline s32 string_to_enum(const std::string& string, const char* const* array, s32 n)
|
||||
{
|
||||
for (s32 i = 0; i < n; i++)
|
||||
if (string == array[i])
|
||||
return i;
|
||||
return -1;
|
||||
};
|
||||
|
||||
// Macro to define enum to string functions
|
||||
#define DEFINE_ENUM_TO_STRING_FUNCTION(function, array, count) \
|
||||
static inline std::string function(s32 index) \
|
||||
{ \
|
||||
return enum_to_string(array, count, index); \
|
||||
};
|
||||
|
||||
// Macro to define string to enum functions
|
||||
#define DEFINE_STRING_TO_ENUM_FUNCTION(function, enumType, stringArray, count) \
|
||||
static inline enumType function(const std::string& string) \
|
||||
{ \
|
||||
return static_cast<enumType>(string_to_enum(string, stringArray, count)); \
|
||||
};
|
||||
|
||||
#define COLOR_FLOAT_TO_INT(x) (static_cast<int>((x) * 255.0f))
|
||||
#define COLOR_INT_TO_FLOAT(x) ((x) / 255.0f)
|
||||
#define PERCENT_TO_UNIT(x) (x / 100.0f)
|
||||
|
||||
#define TICK_DELAY 33.3f
|
||||
#define SECOND 1000.0f
|
||||
@@ -82,8 +121,8 @@ static const f32 GL_UV_VERTICES[] =
|
||||
1, 1, 1.0f, 1.0f,
|
||||
0, 1, 0.0f, 1.0f
|
||||
};
|
||||
#define IMVEC2_VEC2(value) ImVec2(value.x, value.y)
|
||||
#define VEC2_IMVEC2(value) glm::vec2(value.x, value.y)
|
||||
|
||||
|
||||
#define IMVEC4_VEC4(value) ImVec4(value.r, value.g, value.b, value.a)
|
||||
|
||||
static const GLuint GL_TEXTURE_INDICES[] = {0, 1, 2, 2, 3, 0};
|
||||
@@ -95,19 +134,15 @@ static const vec4 COLOR_OPAQUE = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||
static const vec4 COLOR_TRANSPARENT = {0.0f, 0.0f, 0.0f, 1.0f};
|
||||
static const vec3 COLOR_OFFSET_NONE = {0.0f, 0.0f, 0.0f};
|
||||
|
||||
static inline const char* enum_to_string(const char* arr[], s32 count, s32 index) { return (index >= 0 && index < count) ? arr[index] : "undefined"; }
|
||||
static inline s32 string_to_enum(const char* str, const char* const* arr, s32 n) { for (s32 i=0; i<n; ++i) if (!strcmp(str, arr[i])) return i; return -1; }
|
||||
static inline bool string_to_bool(const char* str) { if (strcmp(str, "true") == 0) return true; return false; }
|
||||
|
||||
template<typename T>
|
||||
static inline s32 map_next_id_get(const std::map<s32, T>& map) {
|
||||
s32 id = 0; for (const auto& [key, _] : map) if (key != id) break; else ++id; return id;
|
||||
}
|
||||
|
||||
/* Swaps elements in a map */
|
||||
/* If neither key exists, do nothing */
|
||||
/* If one key exists, change its ID */
|
||||
/* If both keys exist, swap */
|
||||
// Swaps elements in a map
|
||||
// If neither key exists, do nothing
|
||||
// If one key exists, change its ID
|
||||
// If both keys exist, swap
|
||||
template<typename Map, typename Key>
|
||||
static inline void map_swap(Map& map, const Key& key1, const Key& key2)
|
||||
{
|
||||
@@ -132,14 +167,4 @@ static inline void map_swap(Map& map, const Key& key1, const Key& key2)
|
||||
map[key1] = std::move(it2->second);
|
||||
map.erase(it2);
|
||||
}
|
||||
};
|
||||
|
||||
#define DEFINE_ENUM_TO_STRING_FN(fn_name, arr, count) \
|
||||
static inline const char* fn_name(s32 index) { \
|
||||
return enum_to_string(arr, count, index); \
|
||||
}
|
||||
|
||||
#define DEFINE_STRING_TO_ENUM_FN(fn_name, enum_type, str_array, count) \
|
||||
static inline enum_type fn_name(const char* str) { \
|
||||
return (enum_type)string_to_enum(str, str_array, count); \
|
||||
}
|
||||
};
|
155
src/PACKED.h
155
src/PACKED.h
@@ -2,8 +2,8 @@
|
||||
|
||||
#include "COMMON.h"
|
||||
|
||||
static const unsigned int TEXTURE_ATLAS_LENGTH = 916;
|
||||
static const unsigned char TEXTURE_ATLAS[] =
|
||||
const u32 TEXTURE_ATLAS_LENGTH = 916;
|
||||
const u8 TEXTURE_ATLAS[] =
|
||||
{
|
||||
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
|
||||
0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x68,
|
||||
@@ -84,7 +84,6 @@ static const unsigned char TEXTURE_ATLAS[] =
|
||||
0xae, 0x42, 0x60, 0x82
|
||||
};
|
||||
|
||||
#define TEXTURE_COUNT (TEXTURE_TARGET + 1)
|
||||
enum TextureType
|
||||
{
|
||||
TEXTURE_ROOT,
|
||||
@@ -117,17 +116,18 @@ enum TextureType
|
||||
TEXTURE_PICKER,
|
||||
TEXTURE_FRAME,
|
||||
TEXTURE_FRAME_ALT,
|
||||
TEXTURE_TARGET
|
||||
TEXTURE_TARGET,
|
||||
TEXTURE_COUNT
|
||||
};
|
||||
|
||||
static const vec2 ATLAS_SIZE = {96, 104};
|
||||
static const vec2 TEXTURE_SIZE = {16, 16};
|
||||
static const vec2 TEXTURE_SIZE_SMALL = {8, 8};
|
||||
static const vec2 TEXTURE_SIZE_BIG = {32, 32};
|
||||
static const vec2 TEXTURE_SIZE_OBLONG = {16, 40};
|
||||
const vec2 ATLAS_SIZE = {96, 104};
|
||||
const vec2 TEXTURE_SIZE = {16, 16};
|
||||
const vec2 TEXTURE_SIZE_SMALL = {8, 8};
|
||||
const vec2 TEXTURE_SIZE_BIG = {32, 32};
|
||||
const vec2 TEXTURE_SIZE_OBLONG = {16, 40};
|
||||
|
||||
#define ATLAS_UV(x,y){(f32)x / ATLAS_SIZE[0], (f32) y / ATLAS_SIZE[1]}
|
||||
static const vec2 ATLAS_UVS[TEXTURE_COUNT][2] =
|
||||
const vec2 ATLAS_UVS[TEXTURE_COUNT][2] =
|
||||
{
|
||||
{ ATLAS_UV( 0, 0), ATLAS_UV( 16, 16) }, /* 16 x 16 v */
|
||||
{ ATLAS_UV( 16, 0), ATLAS_UV( 32, 16) },
|
||||
@@ -162,7 +162,7 @@ static const vec2 ATLAS_UVS[TEXTURE_COUNT][2] =
|
||||
{ ATLAS_UV( 48, 64), ATLAS_UV( 80, 96) } /* 32 x 32 */
|
||||
};
|
||||
|
||||
static const vec2 ATLAS_SIZES[TEXTURE_COUNT] =
|
||||
const vec2 ATLAS_SIZES[TEXTURE_COUNT] =
|
||||
{
|
||||
TEXTURE_SIZE,
|
||||
TEXTURE_SIZE,
|
||||
@@ -197,89 +197,92 @@ static const vec2 ATLAS_SIZES[TEXTURE_COUNT] =
|
||||
TEXTURE_SIZE_BIG
|
||||
};
|
||||
|
||||
#define IMVEC2_ATLAS_UV_GET(type) IMVEC2_VEC2(ATLAS_UVS[type][0]), IMVEC2_VEC2(ATLAS_UVS[type][1])
|
||||
#define ATLAS_UV_VERTICES(type) UV_VERTICES(ATLAS_UVS[type][0], ATLAS_UVS[type][1])
|
||||
|
||||
/* Shaders */
|
||||
struct ShaderData
|
||||
{
|
||||
const char* vertex;
|
||||
const char* fragment;
|
||||
std::string vertex;
|
||||
std::string fragment;
|
||||
};
|
||||
|
||||
#define SHADER_COUNT (SHADER_LINE_DOTTED + 1)
|
||||
enum ShaderType
|
||||
{
|
||||
SHADER_LINE,
|
||||
SHADER_TEXTURE,
|
||||
SHADER_LINE_DOTTED
|
||||
SHADER_LINE_DOTTED,
|
||||
SHADER_COUNT
|
||||
};
|
||||
|
||||
static const char SHADER_VERTEX[] =
|
||||
"#version 330 core\n" \
|
||||
"layout (location = 0) in vec2 i_position;\n" \
|
||||
"layout (location = 1) in vec2 i_uv;\n" \
|
||||
"\n" \
|
||||
"out vec2 i_uv_out;\n" \
|
||||
"\n" \
|
||||
"uniform mat4 u_transform;\n" \
|
||||
"\n" \
|
||||
"void main()\n" \
|
||||
"{\n" \
|
||||
" i_uv_out = i_uv;\n" \
|
||||
" gl_Position = u_transform * vec4(i_position, 0.0, 1.0);\n" \
|
||||
"}\n";
|
||||
const std::string SHADER_VERTEX = R"(
|
||||
#version 330 core
|
||||
layout (location = 0) in vec2 i_position;
|
||||
layout (location = 1) in vec2 i_uv;
|
||||
|
||||
static const char SHADER_TEXTURE_FRAGMENT[] =
|
||||
"#version 330 core\n" \
|
||||
"in vec2 i_uv_out;\n" \
|
||||
"uniform sampler2D u_texture;\n" \
|
||||
"uniform vec4 u_tint;\n" \
|
||||
"uniform vec3 u_color_offset;\n" \
|
||||
"out vec4 o_fragColor;\n" \
|
||||
"void main()\n" \
|
||||
"{\n" \
|
||||
" vec4 texColor = texture(u_texture, i_uv_out);\n" \
|
||||
" texColor *= u_tint;\n" \
|
||||
" texColor.rgb += u_color_offset;\n" \
|
||||
" o_fragColor = texColor;\n" \
|
||||
"}\n";
|
||||
out vec2 i_uv_out;
|
||||
|
||||
static const char SHADER_FRAGMENT[] =
|
||||
"#version 330 core\n" \
|
||||
"out vec4 o_fragColor;\n" \
|
||||
"uniform vec4 u_color;\n" \
|
||||
"\n" \
|
||||
"void main()\n" \
|
||||
"{\n" \
|
||||
" o_fragColor = u_color;\n" \
|
||||
"}\n";
|
||||
uniform mat4 u_transform;
|
||||
|
||||
static const char SHADER_LINE_DOTTED_FRAGMENT[] =
|
||||
"#version 330 core\n" \
|
||||
"uniform vec4 u_color;\n" \
|
||||
"out vec4 o_fragColor;\n" \
|
||||
"void main()\n" \
|
||||
"{\n" \
|
||||
" float patternX = mod(gl_FragCoord.x, 10.0);\n" \
|
||||
" float patternY = mod(gl_FragCoord.y, 10.0);\n" \
|
||||
" if (patternX < 5.0 || patternY < 5.0)\n" \
|
||||
" {\n" \
|
||||
" o_fragColor = u_color;\n" \
|
||||
" }\n" \
|
||||
" else\n" \
|
||||
" {\n" \
|
||||
" discard;\n" \
|
||||
" }\n" \
|
||||
"}\n";
|
||||
void main()
|
||||
{
|
||||
i_uv_out = i_uv;
|
||||
gl_Position = u_transform * vec4(i_position, 0.0, 1.0);
|
||||
}
|
||||
)";
|
||||
|
||||
static const char SHADER_UNIFORM_COLOR[] = "u_color";
|
||||
static const char SHADER_UNIFORM_TRANSFORM[] = "u_transform";
|
||||
static const char SHADER_UNIFORM_TINT[] = "u_tint";
|
||||
static const char SHADER_UNIFORM_COLOR_OFFSET[] = "u_color_offset";
|
||||
static const char SHADER_UNIFORM_TEXTURE[] = "u_texture";
|
||||
const std::string SHADER_FRAGMENT = R"(
|
||||
#version 330 core
|
||||
out vec4 o_fragColor;
|
||||
uniform vec4 u_color;
|
||||
|
||||
static const ShaderData SHADER_DATA[SHADER_COUNT] =
|
||||
void main()
|
||||
{
|
||||
o_fragColor = u_color;
|
||||
}
|
||||
)";
|
||||
|
||||
const std::string SHADER_TEXTURE_FRAGMENT = R"(
|
||||
#version 330 core
|
||||
in vec2 i_uv_out;
|
||||
uniform sampler2D u_texture;
|
||||
uniform vec4 u_tint;
|
||||
uniform vec3 u_color_offset;
|
||||
out vec4 o_fragColor;
|
||||
void main()
|
||||
{
|
||||
vec4 texColor = texture(u_texture, i_uv_out);
|
||||
texColor *= u_tint;
|
||||
texColor.rgb += u_color_offset;
|
||||
o_fragColor = texColor;
|
||||
}
|
||||
)";
|
||||
|
||||
const std::string SHADER_LINE_DOTTED_FRAGMENT = R"(
|
||||
#version 330 core
|
||||
uniform vec4 u_color;
|
||||
out vec4 o_fragColor;
|
||||
void main()
|
||||
{
|
||||
float patternX = mod(gl_FragCoord.x, 10.0);
|
||||
float patternY = mod(gl_FragCoord.y, 10.0);
|
||||
if (patternX < 5.0 || patternY < 5.0)
|
||||
{
|
||||
o_fragColor = u_color;
|
||||
}
|
||||
else
|
||||
{
|
||||
discard;
|
||||
}
|
||||
}
|
||||
)";
|
||||
|
||||
#define SHADER_UNIFORM_COLOR "u_color"
|
||||
#define SHADER_UNIFORM_TRANSFORM "u_transform"
|
||||
#define SHADER_UNIFORM_TINT "u_tint"
|
||||
#define SHADER_UNIFORM_COLOR_OFFSET "u_color_offset"
|
||||
#define SHADER_UNIFORM_TEXTURE "u_texture"
|
||||
|
||||
const ShaderData SHADER_DATA[SHADER_COUNT] =
|
||||
{
|
||||
{SHADER_VERTEX, SHADER_FRAGMENT},
|
||||
{SHADER_VERTEX, SHADER_TEXTURE_FRAGMENT},
|
||||
|
@@ -1,37 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#define STRING_UNDEFINED "undefined"
|
||||
#define STRING_EMPTY ""
|
||||
|
||||
#define STRING_WINDOW_TITLE "Anm2Ed"
|
||||
#define STRING_WINDOW_TITLE_EDITING "Anm2Ed (%s)"
|
||||
|
||||
#define STRING_ANM2_CREATED_ON_FORMAT "%d-%B-%Y %I:%M:%S %p"
|
||||
|
||||
#define STRING_ERROR_SDL_INIT "[ERROR] Could not initialize SDL (%s)\n"
|
||||
#define STRING_ERROR_GL_CONTEXT_INIT "[ERROR] Could not initialize OpenGL context (%s)\n"
|
||||
#define STRING_ERROR_FILE_READ "[ERROR] Could not read from file: %s\n"
|
||||
#define STRING_ERROR_SHADER_INIT "[ERROR] Could not initialize shader: %i\n%s"
|
||||
#define STRING_ERROR_TEXTURE_INIT "[ERROR] Could not initialize texture: %s\n"
|
||||
#define STRING_ERROR_ANM2_READ "[ERROR] Could not read anm2 from file %s: %s\n"
|
||||
#define STRING_ERROR_ANM2_WRITE "[ERROR] Could not write anm2 to file %s: %s\n"
|
||||
#define STRING_ERROR_SETTINGS_INIT "[ERROR] Could not load settings file (%s). Should be created on program exit.\n"
|
||||
#define STRING_ERROR_SDL_INIT "[ERROR] Could not initialize SDL: "
|
||||
#define STRING_ERROR_GL_CONTEXT_INIT "[ERROR] Could not initialize OpenGL context: "
|
||||
#define STRING_ERROR_FILE_READ "[ERROR] Could not read from file: "
|
||||
#define STRING_ERROR_SHADER_INIT "[ERROR] Could not initialize shader: "
|
||||
#define STRING_ERROR_TEXTURE_INIT "[ERROR] Could not initialize texture: "
|
||||
#define STRING_ERROR_ANM2_READ "[ERROR] Could not read anm2 from file: "
|
||||
#define STRING_ERROR_ANM2_WRITE "[ERROR] Could not write anm2 to file: "
|
||||
#define STRING_ERROR_SETTINGS_INIT "[ERROR] Could not load settings file: "
|
||||
|
||||
#define STRING_INFO_INIT "[INFO] Initializing\n"
|
||||
#define STRING_INFO_QUIT "[INFO] Exited\n"
|
||||
#define STRING_INFO_SDL_INIT "[INFO] Initialized SDL\n"
|
||||
#define STRING_INFO_SDL_QUIT "[INFO] Quit SDL\n"
|
||||
#define STRING_INFO_GLEW_INIT "[INFO] Initialized GLEW\n"
|
||||
#define STRING_INFO_GL_CONTEXT_INIT "[INFO] Initialized OpenGL context\n"
|
||||
#define STRING_INFO_FILE_READ "[INFO] Read from file: %s\n"
|
||||
#define STRING_INFO_SHADER_INIT "[INFO] Initialized shader: %i\n"
|
||||
#define STRING_INFO_TEXTURE_INIT "[INFO] Initialized texture: %s\n"
|
||||
#define STRING_INFO_ANM2_WRITE "[INFO] Wrote anm2 to file: %s\n"
|
||||
#define STRING_INFO_ANM2_READ "[INFO] Read anm2 from file: %s\n"
|
||||
#define STRING_INFO_OPENGL "[INFO] OpenGL %s\n"
|
||||
#define STRING_INFO_INIT "[INFO] Initializing"
|
||||
#define STRING_INFO_QUIT "[INFO] Exited"
|
||||
#define STRING_INFO_SDL_INIT "[INFO] Initialized SDL"
|
||||
#define STRING_INFO_SDL_QUIT "[INFO] Quit SDL"
|
||||
#define STRING_INFO_GLEW_INIT "[INFO] Initialized GLEW"
|
||||
#define STRING_INFO_GL_CONTEXT_INIT "[INFO] Initialized OpenGL context"
|
||||
#define STRING_INFO_FILE_READ "[INFO] Read from file: "
|
||||
#define STRING_INFO_TEXTURE_INIT "[INFO] Initialized texture: "
|
||||
#define STRING_INFO_ANM2_WRITE "[INFO] Wrote anm2 to file: "
|
||||
#define STRING_INFO_ANM2_READ "[INFO] Read anm2 from file: "
|
||||
#define STRING_INFO_OPENGL "OpenGL"
|
||||
|
||||
#define STRING_INFO_IMGUI_INIT "[INFO] Initialized Dear Imgui\n"
|
||||
#define STRING_INFO_IMGUI_FREE "[INFO] Freed Dear Imgui\n"
|
||||
#define STRING_INFO_IMGUI_INIT "[INFO] Initialized Dear Imgui"
|
||||
#define STRING_INFO_IMGUI_FREE "[INFO] Freed Dear Imgui"
|
||||
|
||||
#define STRING_DIALOG_ANM2_READ "Select .anm2 file to read..."
|
||||
#define STRING_DIALOG_ANM2_WRITE "Select .anm2 file to write to..."
|
||||
@@ -48,7 +43,7 @@
|
||||
#define STRING_ANM2_ROOT "Root"
|
||||
|
||||
#define STRING_PREVIEW_FRAMES_DIRECTORY "frames/"
|
||||
#define STRING_PREVIEW_FRAMES_FORMAT "%s/%03d.png"
|
||||
#define STRING_PREVIEW_FRAMES_FORMAT "{}/{:03}.png"
|
||||
|
||||
#define STRING_IMGUI_WINDOW "Window"
|
||||
#define STRING_IMGUI_DOCKSPACE "Dockspace"
|
||||
@@ -78,14 +73,14 @@
|
||||
#define STRING_IMGUI_ANIMATIONS_REMOVE "Remove"
|
||||
#define STRING_IMGUI_ANIMATIONS_DUPLICATE "Duplicate"
|
||||
#define STRING_IMGUI_ANIMATIONS_SET_AS_DEFAULT "Set as Default"
|
||||
#define STRING_IMGUI_ANIMATIONS_DEFAULT_ANIMATION_FORMAT "(*) %s "
|
||||
#define STRING_IMGUI_ANIMATIONS_DEFAULT_ANIMATION_FORMAT "(*) {}"
|
||||
#define STRING_IMGUI_ANIMATIONS_DRAG_DROP "Animation Drag/Drop"
|
||||
|
||||
#define STRING_IMGUI_EVENTS "Events"
|
||||
#define STRING_IMGUI_EVENTS_EVENT_LABEL "##Event"
|
||||
#define STRING_IMGUI_EVENTS_ADD "Add"
|
||||
#define STRING_IMGUI_EVENTS_REMOVE "Remove"
|
||||
#define STRING_IMGUI_EVENT_FORMAT "#%i %s"
|
||||
#define STRING_IMGUI_EVENT_FORMAT "#{} {}"
|
||||
#define STRING_IMGUI_EVENTS_DRAG_DROP "Event Drag/Drop"
|
||||
|
||||
#define STRING_IMGUI_SPRITESHEETS "Spritesheets"
|
||||
@@ -93,7 +88,7 @@
|
||||
#define STRING_IMGUI_SPRITESHEETS_REMOVE "Remove"
|
||||
#define STRING_IMGUI_SPRITESHEETS_RELOAD "Reload"
|
||||
#define STRING_IMGUI_SPRITESHEETS_REPLACE "Replace"
|
||||
#define STRING_IMGUI_SPRITESHEET_FORMAT "#%i %s"
|
||||
#define STRING_IMGUI_SPRITESHEET_FORMAT "#{} {}"
|
||||
#define STRING_IMGUI_SPRITESHEETS_DRAG_DROP "Spritesheet Drag/Drop"
|
||||
|
||||
#define STRING_IMGUI_FRAME_PROPERTIES "Frame Properties"
|
||||
@@ -136,7 +131,7 @@
|
||||
#define STRING_IMGUI_ANIMATION_PREVIEW_ROOT_TRANSFORM "Root Transform"
|
||||
#define STRING_IMGUI_ANIMATION_PREVIEW_SHOW_PIVOT "Show Pivot"
|
||||
#define STRING_IMGUI_ANIMATION_PREVIEW_POSITION "##Position"
|
||||
#define STRING_IMGUI_ANIMATION_PREVIEW_POSITION_FORMAT "Position: {%5.0f, %5.0f}"
|
||||
#define STRING_IMGUI_POSITION_FORMAT "Position: {{{:5}, {:5}}}"
|
||||
|
||||
#define STRING_IMGUI_SPRITESHEET_EDITOR "Spritesheet Editor"
|
||||
#define STRING_IMGUI_SPRITESHEET_EDITOR_LABEL "##Animation Preview"
|
||||
@@ -154,7 +149,6 @@
|
||||
#define STRING_IMGUI_SPRITESHEET_EDITOR_CENTER_VIEW "Center View"
|
||||
#define STRING_IMGUI_SPRITESHEET_EDITOR_BORDER "Border"
|
||||
#define STRING_IMGUI_SPRITESHEET_EDITOR_POSITION "##Position"
|
||||
#define STRING_IMGUI_SPRITESHEET_EDITOR_POSITION_FORMAT "Position: {%5.0f, %5.0f}"
|
||||
|
||||
#define STRING_IMGUI_TIMELINE "Timeline"
|
||||
#define STRING_IMGUI_TIMELINE_HEADER "##Header"
|
||||
@@ -162,9 +156,7 @@
|
||||
#define STRING_IMGUI_TIMELINE_ELEMENT_DOWN "##Down"
|
||||
#define STRING_IMGUI_TIMELINE_ELEMENT_FRAMES "Element Frames"
|
||||
#define STRING_IMGUI_TIMELINE_ROOT "Root"
|
||||
#define STRING_IMGUI_TIMELINE_ELEMENT_FORMAT "#%i %s"
|
||||
#define STRING_IMGUI_TIMELINE_SPRITESHEET_FORMAT "#%i"
|
||||
#define STRING_IMGUI_TIMELINE_SPRITESHEET_UNKNOWN "#?"
|
||||
#define STRING_IMGUI_TIMELINE_ITEM_FORMAT "#{} {}"
|
||||
#define STRING_IMGUI_TIMELINE_ELEMENT_SPRITESHEET_ID_LABEL "##Timeline Element Spritesheet ID"
|
||||
#define STRING_IMGUI_TIMELINE_ELEMENT_NAME_LABEL "##Timeline Element Name"
|
||||
#define STRING_IMGUI_TIMELINE_TRIGGERS "Triggers"
|
||||
@@ -196,6 +188,7 @@
|
||||
#define STRING_IMGUI_TIMELINE_ELEMENT_REMOVE "Remove Element"
|
||||
#define STRING_IMGUI_TIMELINE_LOOP "Loop"
|
||||
#define STRING_IMGUI_TIMELINE_FPS "FPS"
|
||||
#define STRING_IMGUI_TIMELINE_SPRITESHEET_ID_FORMAT "#{}"
|
||||
#define STRING_IMGUI_TIMELINE_CREATED_BY "Author"
|
||||
#define STRING_IMGUI_TIMELINE_CREATED_ON "Created on: %s"
|
||||
#define STRING_IMGUI_TIMELINE_VERSION "Version: %i"
|
||||
|
466
src/anm2.cpp
466
src/anm2.cpp
@@ -2,25 +2,24 @@
|
||||
|
||||
using namespace tinyxml2;
|
||||
|
||||
/* Sets the anm2's date to the system's current date */
|
||||
void
|
||||
anm2_created_on_set(Anm2* self)
|
||||
static void _anm2_created_on_set(Anm2* self);
|
||||
|
||||
// Sets the anm2's date to the system's current date
|
||||
static void
|
||||
_anm2_created_on_set(Anm2* self)
|
||||
{
|
||||
time_t currentTime;
|
||||
struct tm* local;
|
||||
char date[ANM2_STRING_MAX];
|
||||
auto now = std::chrono::system_clock::now();
|
||||
std::time_t time = std::chrono::system_clock::to_time_t(now);
|
||||
std::tm localTime = *std::localtime(&time);
|
||||
|
||||
currentTime = time(NULL);
|
||||
local = localtime(¤tTime);
|
||||
|
||||
strftime(date, ANM2_STRING_MAX, STRING_ANM2_CREATED_ON_FORMAT, local);
|
||||
|
||||
strncpy(self->createdOn, date, ANM2_STRING_MAX);
|
||||
std::ostringstream timeString;
|
||||
timeString << std::put_time(&localTime, STRING_ANM2_CREATED_ON_FORMAT);
|
||||
self->createdOn = timeString.str();
|
||||
}
|
||||
|
||||
/* Serializes the anm2 struct into XML and exports it to the given path */
|
||||
// Serializes the anm2 struct into XML and exports it to the given path
|
||||
bool
|
||||
anm2_serialize(Anm2* self, const char* path)
|
||||
anm2_serialize(Anm2* self, const std::string& path)
|
||||
{
|
||||
XMLDocument document;
|
||||
XMLError error;
|
||||
@@ -34,108 +33,111 @@ anm2_serialize(Anm2* self, const char* path)
|
||||
XMLElement* eventsElement;
|
||||
XMLElement* animationsElement;
|
||||
|
||||
if (!self || !path)
|
||||
if (!self || path.empty())
|
||||
return false;
|
||||
|
||||
/* Update creation date on first version */
|
||||
// Update creation date on first version
|
||||
if (self->version == 0)
|
||||
anm2_created_on_set(self);
|
||||
_anm2_created_on_set(self);
|
||||
|
||||
/* Increment anm2's version */
|
||||
// Set anm2 path to argument
|
||||
self->path = path;
|
||||
|
||||
// Update version
|
||||
self->version++;
|
||||
|
||||
/* AnimatedActor */
|
||||
// AnimatedActor
|
||||
animatedActorElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_ANIMATED_ACTOR]);
|
||||
document.InsertFirstChild(animatedActorElement);
|
||||
|
||||
/* Info */
|
||||
// Info
|
||||
infoElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_INFO]);
|
||||
infoElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_CREATED_BY], self->createdBy); /* CreatedBy */
|
||||
infoElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_CREATED_ON], self->createdOn); /* CreatedOn */
|
||||
infoElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_VERSION], self->version); /* Version; note its incrementation */
|
||||
infoElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_FPS], self->fps); /* FPS */
|
||||
infoElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_CREATED_BY], self->createdBy.c_str()); // CreatedBy
|
||||
infoElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_CREATED_ON], self->createdOn.c_str()); // CreatedOn
|
||||
infoElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_VERSION], self->version); // Version
|
||||
infoElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_FPS], self->fps); // FPS
|
||||
animatedActorElement->InsertEndChild(infoElement);
|
||||
|
||||
/* Content */
|
||||
// Content
|
||||
contentElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_CONTENT]);
|
||||
|
||||
/* Spritesheets */
|
||||
// Spritesheets
|
||||
spritesheetsElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_SPRITESHEETS]);
|
||||
|
||||
for (auto & [id, spritesheet] : self->spritesheets)
|
||||
{
|
||||
XMLElement* spritesheetElement;
|
||||
|
||||
/* Spritesheet */
|
||||
// Spritesheet
|
||||
spritesheetElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_SPRITESHEET]);
|
||||
spritesheetElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_PATH], spritesheet.path); /* Path */
|
||||
spritesheetElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_ID], id); /* ID */
|
||||
spritesheetElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_PATH], spritesheet.path.c_str()); // Path
|
||||
spritesheetElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_ID], id); // ID
|
||||
spritesheetsElement->InsertEndChild(spritesheetElement);
|
||||
}
|
||||
|
||||
contentElement->InsertEndChild(spritesheetsElement);
|
||||
|
||||
/* Layers */
|
||||
// Layers
|
||||
layersElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_LAYERS]);
|
||||
|
||||
for (auto & [id, layer] : self->layers)
|
||||
{
|
||||
XMLElement* layerElement;
|
||||
|
||||
/* Layer */
|
||||
// Layer
|
||||
layerElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_LAYER]);
|
||||
layerElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_NAME], layer.name); /* Path */
|
||||
layerElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_ID], id); /* ID */
|
||||
layerElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_SPRITESHEET_ID], layer.spritesheetID); /* SpritesheetId */
|
||||
layerElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_NAME], layer.name.c_str()); // Path
|
||||
layerElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_ID], id); // ID
|
||||
layerElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_SPRITESHEET_ID], layer.spritesheetID); // SpritesheetId
|
||||
|
||||
layersElement->InsertEndChild(layerElement);
|
||||
}
|
||||
|
||||
contentElement->InsertEndChild(layersElement);
|
||||
|
||||
/* Nulls */
|
||||
// Nulls
|
||||
nullsElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_NULLS]);
|
||||
|
||||
for (auto & [id, null] : self->nulls)
|
||||
{
|
||||
XMLElement* nullElement;
|
||||
|
||||
/* Null */
|
||||
// Null
|
||||
nullElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_NULL]);
|
||||
nullElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_NAME], null.name); /* Name */
|
||||
nullElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_ID], id); /* ID */
|
||||
nullElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_NAME], null.name.c_str()); // Name
|
||||
nullElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_ID], id); // ID
|
||||
|
||||
/* special case; only serialize if this is true */
|
||||
// special case; only serialize if this is true
|
||||
if (null.isShowRect)
|
||||
nullElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_SHOW_RECT], null.isShowRect); /* ShowRect */
|
||||
nullElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_SHOW_RECT], null.isShowRect); // ShowRect
|
||||
nullsElement->InsertEndChild(nullElement);
|
||||
}
|
||||
|
||||
contentElement->InsertEndChild(nullsElement);
|
||||
|
||||
/* Events */
|
||||
// Events
|
||||
eventsElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_EVENTS]);
|
||||
|
||||
for (auto & [id, event] : self->events)
|
||||
{
|
||||
XMLElement* eventElement;
|
||||
|
||||
/* Event */
|
||||
// Event
|
||||
eventElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_EVENT]);
|
||||
eventElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_NAME], event.name); /* Name */
|
||||
eventElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_ID], id); /* ID */
|
||||
eventElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_NAME], event.name.c_str()); // Name
|
||||
eventElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_ID], id); // ID
|
||||
eventsElement->InsertEndChild(eventElement);
|
||||
}
|
||||
|
||||
contentElement->InsertEndChild(eventsElement);
|
||||
|
||||
animatedActorElement->InsertEndChild(contentElement);
|
||||
|
||||
/* Animations */
|
||||
|
||||
// Animations
|
||||
animationsElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_ANIMATIONS]);
|
||||
animationsElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_DEFAULT_ANIMATION], self->defaultAnimation);
|
||||
animationsElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_DEFAULT_ANIMATION], self->defaultAnimation.c_str()); // DefaultAnimation
|
||||
|
||||
for (auto & [id, animation] : self->animations)
|
||||
for (const auto & [id, animation] : self->animations)
|
||||
{
|
||||
XMLElement* animationElement;
|
||||
XMLElement* rootAnimationElement;
|
||||
@@ -143,86 +145,86 @@ anm2_serialize(Anm2* self, const char* path)
|
||||
XMLElement* nullAnimationsElement;
|
||||
XMLElement* triggersElement;
|
||||
|
||||
/* Animation */
|
||||
// Animation
|
||||
animationElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_ANIMATION]);
|
||||
|
||||
animationElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_NAME], animation.name); /* Name */
|
||||
animationElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_FRAME_NUM], animation.frameNum); /* FrameNum */
|
||||
animationElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_LOOP], animation.isLoop); /* Loop */
|
||||
animationElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_NAME], animation.name.c_str()); // Name
|
||||
animationElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_FRAME_NUM], animation.frameNum); // FrameNum
|
||||
animationElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_LOOP], animation.isLoop); // Loop
|
||||
|
||||
/* RootAnimation */
|
||||
// RootAnimation
|
||||
rootAnimationElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_ROOT_ANIMATION]);
|
||||
|
||||
for (auto & frame : animation.rootAnimation.frames)
|
||||
for (const auto & frame : animation.rootAnimation.frames)
|
||||
{
|
||||
XMLElement* frameElement;
|
||||
|
||||
/* Frame */
|
||||
// Frame
|
||||
frameElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_FRAME]);
|
||||
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_X_POSITION], frame.position.x); /* XPosition */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_Y_POSITION], frame.position.y); /* YPosition */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_X_PIVOT], frame.pivot.x); /* XPivot */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_Y_PIVOT], frame.pivot.y); /* YPivot */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_X_SCALE], frame.scale.x); /* XScale */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_Y_SCALE], frame.scale.y); /* XScale */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_DELAY], frame.delay); /* Delay */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_VISIBLE], frame.isVisible); /* Visible */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_RED_TINT], COLOR_FLOAT_TO_INT(frame.tintRGBA.r)); /* RedTint */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_GREEN_TINT], COLOR_FLOAT_TO_INT(frame.tintRGBA.g)); /* GreenTint */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_BLUE_TINT], COLOR_FLOAT_TO_INT(frame.tintRGBA.b)); /* BlueTint */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_ALPHA_TINT], COLOR_FLOAT_TO_INT(frame.tintRGBA.a)); /* AlphaTint */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_RED_OFFSET], COLOR_FLOAT_TO_INT(frame.offsetRGB.r)); /* RedOffset */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_GREEN_OFFSET], COLOR_FLOAT_TO_INT(frame.offsetRGB.g)); /* GreenOffset */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_BLUE_OFFSET], COLOR_FLOAT_TO_INT(frame.offsetRGB.b)); /* BlueOffset */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_ROTATION], frame.rotation); /* Rotation */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_INTERPOLATED], frame.isInterpolated); /* Interpolated */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_X_POSITION], frame.position.x); // XPosition
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_Y_POSITION], frame.position.y); // YPosition
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_X_PIVOT], frame.pivot.x); // XPivot
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_Y_PIVOT], frame.pivot.y); // YPivot
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_X_SCALE], frame.scale.x); // XScale
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_Y_SCALE], frame.scale.y); // YScale
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_DELAY], frame.delay); // Delay
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_VISIBLE], frame.isVisible); // Visible
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_RED_TINT], COLOR_FLOAT_TO_INT(frame.tintRGBA.r)); // RedTint
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_GREEN_TINT], COLOR_FLOAT_TO_INT(frame.tintRGBA.g)); // GreenTint
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_BLUE_TINT], COLOR_FLOAT_TO_INT(frame.tintRGBA.b)); // BlueTint
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_ALPHA_TINT], COLOR_FLOAT_TO_INT(frame.tintRGBA.a)); // AlphaTint
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_RED_OFFSET], COLOR_FLOAT_TO_INT(frame.offsetRGB.r)); // RedOffset
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_GREEN_OFFSET], COLOR_FLOAT_TO_INT(frame.offsetRGB.g)); // GreenOffset
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_BLUE_OFFSET], COLOR_FLOAT_TO_INT(frame.offsetRGB.b)); // BlueOffset
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_ROTATION], frame.rotation); // Rotation
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_INTERPOLATED], frame.isInterpolated); // Interpolated
|
||||
|
||||
rootAnimationElement->InsertEndChild(frameElement);
|
||||
}
|
||||
|
||||
animationElement->InsertEndChild(rootAnimationElement);
|
||||
|
||||
/* LayerAnimations */
|
||||
// LayerAnimations
|
||||
layerAnimationsElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_LAYER_ANIMATIONS]);
|
||||
|
||||
for (const auto & [layerID, layerAnimation] : animation.layerAnimations)
|
||||
{
|
||||
XMLElement* layerAnimationElement;
|
||||
|
||||
/* LayerAnimation */
|
||||
// LayerAnimation
|
||||
layerAnimationElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_LAYER_ANIMATION]);
|
||||
layerAnimationElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_LAYER_ID], layerID); /* LayerID */
|
||||
layerAnimationElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_VISIBLE], layerAnimation.isVisible); /* Visible */
|
||||
layerAnimationElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_LAYER_ID], layerID); // LayerId
|
||||
layerAnimationElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_VISIBLE], layerAnimation.isVisible); // Visible
|
||||
|
||||
for (auto & frame : layerAnimation.frames)
|
||||
{
|
||||
XMLElement* frameElement;
|
||||
|
||||
/* Frame */
|
||||
// Frame
|
||||
frameElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_FRAME]);
|
||||
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_X_POSITION], frame.position.x); /* XPosition */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_Y_POSITION], frame.position.y); /* YPosition */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_X_PIVOT], frame.pivot.x); /* XPivot */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_Y_PIVOT], frame.pivot.y); /* YPivot */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_X_CROP], frame.crop.x); /* XCrop */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_Y_CROP], frame.crop.y); /* YCrop */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_WIDTH], frame.size.x); /* Width */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_HEIGHT], frame.size.y); /* Height */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_X_SCALE], frame.scale.x); /* XScale */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_Y_SCALE], frame.scale.y); /* XScale */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_X_POSITION], frame.position.x); // XPosition
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_Y_POSITION], frame.position.y); // YPosition
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_X_PIVOT], frame.pivot.x); // XPivot
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_Y_PIVOT], frame.pivot.y); // YPivot
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_X_CROP], frame.crop.x); // XCrop
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_Y_CROP], frame.crop.y); // YCrop
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_WIDTH], frame.size.x); // Width
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_HEIGHT], frame.size.y); // Height
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_X_SCALE], frame.scale.x); // XScale
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_Y_SCALE], frame.scale.y); // YScale
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_DELAY], frame.delay); /* Delay */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_VISIBLE], frame.isVisible); /* Visible */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_RED_TINT], COLOR_FLOAT_TO_INT(frame.tintRGBA.r)); /* RedTint */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_GREEN_TINT], COLOR_FLOAT_TO_INT(frame.tintRGBA.g)); /* GreenTint */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_BLUE_TINT], COLOR_FLOAT_TO_INT(frame.tintRGBA.b)); /* BlueTint */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_ALPHA_TINT], COLOR_FLOAT_TO_INT(frame.tintRGBA.a)); /* AlphaTint */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_RED_OFFSET], COLOR_FLOAT_TO_INT(frame.offsetRGB.r)); /* RedOffset */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_GREEN_OFFSET], COLOR_FLOAT_TO_INT(frame.offsetRGB.g)); /* GreenOffset */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_BLUE_OFFSET], COLOR_FLOAT_TO_INT(frame.offsetRGB.b)); /* BlueOffset */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_ROTATION], frame.rotation); /* Rotation */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_INTERPOLATED], frame.isInterpolated); /* Interpolated */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_VISIBLE], frame.isVisible); // Visible
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_RED_TINT], COLOR_FLOAT_TO_INT(frame.tintRGBA.r)); // RedTint
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_GREEN_TINT], COLOR_FLOAT_TO_INT(frame.tintRGBA.g)); // GreenTint
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_BLUE_TINT], COLOR_FLOAT_TO_INT(frame.tintRGBA.b)); // BlueTint
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_ALPHA_TINT], COLOR_FLOAT_TO_INT(frame.tintRGBA.a)); // AlphaTint
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_RED_OFFSET], COLOR_FLOAT_TO_INT(frame.offsetRGB.r)); // RedOffset
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_GREEN_OFFSET], COLOR_FLOAT_TO_INT(frame.offsetRGB.g)); // GreenOffset
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_BLUE_OFFSET], COLOR_FLOAT_TO_INT(frame.offsetRGB.b)); // BlueOffset
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_ROTATION], frame.rotation); // Rotation
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_INTERPOLATED], frame.isInterpolated); // Interpolated
|
||||
|
||||
layerAnimationElement->InsertEndChild(frameElement);
|
||||
}
|
||||
@@ -232,42 +234,42 @@ anm2_serialize(Anm2* self, const char* path)
|
||||
|
||||
animationElement->InsertEndChild(layerAnimationsElement);
|
||||
|
||||
/* NullAnimations */
|
||||
// NullAnimations
|
||||
nullAnimationsElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_NULL_ANIMATIONS]);
|
||||
|
||||
for (const auto & [nullID, nullAnimation] : animation.nullAnimations)
|
||||
{
|
||||
XMLElement* nullAnimationElement;
|
||||
|
||||
/* NullAnimation */
|
||||
// NullAnimation
|
||||
nullAnimationElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_NULL_ANIMATION]);
|
||||
nullAnimationElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_NULL_ID], nullID); /* NullID */
|
||||
nullAnimationElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_VISIBLE], nullAnimation.isVisible); /* Visible */
|
||||
nullAnimationElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_NULL_ID], nullID); // NullId
|
||||
nullAnimationElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_VISIBLE], nullAnimation.isVisible); // Visible
|
||||
|
||||
for (auto & frame : nullAnimation.frames)
|
||||
for (const auto & frame : nullAnimation.frames)
|
||||
{
|
||||
XMLElement* frameElement;
|
||||
|
||||
/* Frame */
|
||||
// Frame
|
||||
frameElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_FRAME]);
|
||||
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_X_POSITION], frame.position.x); /* XPosition */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_Y_POSITION], frame.position.y); /* YPosition */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_X_PIVOT], frame.pivot.x); /* XPivot */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_Y_PIVOT], frame.pivot.y); /* YPivot */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_X_SCALE], frame.scale.x); /* XScale */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_Y_SCALE], frame.scale.y); /* XScale */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_DELAY], frame.delay); /* Delay */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_VISIBLE], frame.isVisible); /* Visible */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_RED_TINT], COLOR_FLOAT_TO_INT(frame.tintRGBA.r)); /* RedTint */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_GREEN_TINT], COLOR_FLOAT_TO_INT(frame.tintRGBA.g)); /* GreenTint */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_BLUE_TINT], COLOR_FLOAT_TO_INT(frame.tintRGBA.b)); /* BlueTint */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_ALPHA_TINT], COLOR_FLOAT_TO_INT(frame.tintRGBA.a)); /* AlphaTint */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_RED_OFFSET], COLOR_FLOAT_TO_INT(frame.offsetRGB.r)); /* RedOffset */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_GREEN_OFFSET], COLOR_FLOAT_TO_INT(frame.offsetRGB.g)); /* GreenOffset */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_BLUE_OFFSET], COLOR_FLOAT_TO_INT(frame.offsetRGB.b)); /* BlueOffset */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_ROTATION], frame.rotation); /* Rotation */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_INTERPOLATED], frame.isInterpolated); /* Interpolated */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_X_POSITION], frame.position.x); // XPosition
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_Y_POSITION], frame.position.y); // YPosition
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_X_PIVOT], frame.pivot.x); // XPivot
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_Y_PIVOT], frame.pivot.y); // YPivot
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_X_SCALE], frame.scale.x); // XScale
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_Y_SCALE], frame.scale.y); // XScale
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_DELAY], frame.delay); // Delay
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_VISIBLE], frame.isVisible); // Visible
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_RED_TINT], COLOR_FLOAT_TO_INT(frame.tintRGBA.r)); // RedTint
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_GREEN_TINT], COLOR_FLOAT_TO_INT(frame.tintRGBA.g)); // GreenTint
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_BLUE_TINT], COLOR_FLOAT_TO_INT(frame.tintRGBA.b)); // BlueTint
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_ALPHA_TINT], COLOR_FLOAT_TO_INT(frame.tintRGBA.a)); // AlphaTint
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_RED_OFFSET], COLOR_FLOAT_TO_INT(frame.offsetRGB.r)); // RedOffset
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_GREEN_OFFSET], COLOR_FLOAT_TO_INT(frame.offsetRGB.g)); // GreenOffset
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_BLUE_OFFSET], COLOR_FLOAT_TO_INT(frame.offsetRGB.b)); // BlueOffset
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_ROTATION], frame.rotation); // Rotation
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_INTERPOLATED], frame.isInterpolated); // Interpolated
|
||||
|
||||
nullAnimationElement->InsertEndChild(frameElement);
|
||||
}
|
||||
@@ -277,17 +279,17 @@ anm2_serialize(Anm2* self, const char* path)
|
||||
|
||||
animationElement->InsertEndChild(nullAnimationsElement);
|
||||
|
||||
/* Triggers */
|
||||
// Triggers
|
||||
triggersElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_TRIGGERS]);
|
||||
|
||||
for (auto & frame : animation.triggers.frames)
|
||||
for (const auto & frame : animation.triggers.frames)
|
||||
{
|
||||
XMLElement* triggerElement;
|
||||
|
||||
/* Trigger */
|
||||
// Trigger
|
||||
triggerElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_TRIGGER]);
|
||||
triggerElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_EVENT_ID], frame.eventID); /* EventID */
|
||||
triggerElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_AT_FRAME], frame.atFrame); /* AtFrame */
|
||||
triggerElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_EVENT_ID], frame.eventID); // EventID
|
||||
triggerElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_AT_FRAME], frame.atFrame); // AtFrame
|
||||
triggersElement->InsertEndChild(triggerElement);
|
||||
}
|
||||
|
||||
@@ -298,23 +300,22 @@ anm2_serialize(Anm2* self, const char* path)
|
||||
|
||||
animatedActorElement->InsertEndChild(animationsElement);
|
||||
|
||||
error = document.SaveFile(path);
|
||||
error = document.SaveFile(path.c_str());
|
||||
|
||||
if (error != XML_SUCCESS)
|
||||
{
|
||||
printf(STRING_ERROR_ANM2_WRITE, path, document.ErrorStr());
|
||||
std::cout << STRING_ERROR_ANM2_WRITE << path << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
printf(STRING_INFO_ANM2_WRITE, path);
|
||||
strncpy(self->path, path, PATH_MAX - 1);
|
||||
std::cout << STRING_INFO_ANM2_WRITE << path << std::endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Loads the .anm2 file and deserializes it into the struct equivalent */
|
||||
// Loads the .anm2 file and deserializes it into the struct equivalent
|
||||
bool
|
||||
anm2_deserialize(Anm2* self, Resources* resources, const char* path)
|
||||
anm2_deserialize(Anm2* self, Resources* resources, const std::string& path)
|
||||
{
|
||||
XMLDocument xmlDocument;
|
||||
XMLError xmlError;
|
||||
@@ -335,69 +336,72 @@ anm2_deserialize(Anm2* self, Resources* resources, const char* path)
|
||||
Anm2Event addEvent;
|
||||
Anm2Spritesheet addSpritesheet;
|
||||
|
||||
if (!self || path.empty())
|
||||
return false;
|
||||
|
||||
*self = Anm2{};
|
||||
|
||||
xmlError = xmlDocument.LoadFile(path);
|
||||
xmlError = xmlDocument.LoadFile(path.c_str());
|
||||
|
||||
if (xmlError != XML_SUCCESS)
|
||||
{
|
||||
printf(STRING_ERROR_ANM2_READ, path, xmlDocument.ErrorStr());
|
||||
std::cout << STRING_ERROR_ANM2_READ << path << xmlDocument.ErrorStr() << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Free the loaded textures used by resources so new ones for the anm2 can be loaded
|
||||
resources_textures_free(resources);
|
||||
|
||||
/* Save old working directory and then use anm2's path as directory */
|
||||
/* (useful for loading textures from anm2 correctly) */
|
||||
// Save old working directory and then use anm2's path as directory
|
||||
// (used for loading textures from anm2 correctly which are relative)
|
||||
std::filesystem::path workingPath = std::filesystem::current_path();
|
||||
std::filesystem::path filePath = path;
|
||||
std::filesystem::path parentPath = filePath.parent_path();
|
||||
std::filesystem::current_path(parentPath);
|
||||
strncpy(self->path, path, PATH_MAX - 1);
|
||||
working_directory_from_file_set(path);
|
||||
|
||||
xmlRoot = xmlDocument.FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_ANIMATED_ACTOR]);
|
||||
self->path = path;
|
||||
|
||||
xmlRoot = xmlDocument.FirstChildElement(ANM2_ELEMENT_ENUM_TO_STRING(ANM2_ELEMENT_ANIMATED_ACTOR).c_str());
|
||||
xmlElement = xmlRoot;
|
||||
|
||||
// Iterate through elements
|
||||
while (xmlElement)
|
||||
{
|
||||
const XMLAttribute* xmlAttribute = NULL;
|
||||
const XMLElement* xmlChild = NULL;
|
||||
s32 id = 0;
|
||||
|
||||
/* Elements */
|
||||
anm2Element = anm2_element_from_string(xmlElement->Name());
|
||||
|
||||
anm2Element = ANM2_ELEMENT_STRING_TO_ENUM(xmlElement->Name());
|
||||
|
||||
switch (anm2Element)
|
||||
{
|
||||
case ANM2_ELEMENT_SPRITESHEET:
|
||||
case ANM2_ELEMENT_SPRITESHEET: // Spritesheet
|
||||
spritesheet = &addSpritesheet;
|
||||
break;
|
||||
case ANM2_ELEMENT_LAYER:
|
||||
case ANM2_ELEMENT_LAYER: // Layer
|
||||
layer = &addLayer;
|
||||
break;
|
||||
case ANM2_ELEMENT_NULL:
|
||||
case ANM2_ELEMENT_NULL: // Null
|
||||
null = &addNull;
|
||||
break;
|
||||
case ANM2_ELEMENT_EVENT:
|
||||
case ANM2_ELEMENT_EVENT: // Event
|
||||
event = &addEvent;
|
||||
break;
|
||||
case ANM2_ELEMENT_ANIMATION:
|
||||
case ANM2_ELEMENT_ANIMATION: // Animation
|
||||
id = map_next_id_get(self->animations);
|
||||
self->animations[id] = Anm2Animation{};
|
||||
animation = &self->animations[id];
|
||||
break;
|
||||
case ANM2_ELEMENT_ROOT_ANIMATION:
|
||||
case ANM2_ELEMENT_ROOT_ANIMATION: // RootAnimation
|
||||
item = &animation->rootAnimation;
|
||||
break;
|
||||
case ANM2_ELEMENT_LAYER_ANIMATION:
|
||||
case ANM2_ELEMENT_NULL_ANIMATION:
|
||||
case ANM2_ELEMENT_LAYER_ANIMATION: // LayerAnimation
|
||||
case ANM2_ELEMENT_NULL_ANIMATION: // NullAnimation
|
||||
item = &addItem;
|
||||
break;
|
||||
case ANM2_ELEMENT_TRIGGERS:
|
||||
case ANM2_ELEMENT_TRIGGERS: // Triggers
|
||||
item = &animation->triggers;
|
||||
break;
|
||||
case ANM2_ELEMENT_FRAME:
|
||||
case ANM2_ELEMENT_TRIGGER:
|
||||
case ANM2_ELEMENT_FRAME: // Frame
|
||||
case ANM2_ELEMENT_TRIGGER: // Trigger
|
||||
item->frames.push_back(Anm2Frame{});
|
||||
frame = &item->frames.back();
|
||||
default:
|
||||
@@ -406,42 +410,42 @@ anm2_deserialize(Anm2* self, Resources* resources, const char* path)
|
||||
|
||||
/* Attributes */
|
||||
xmlAttribute = xmlElement->FirstAttribute();
|
||||
|
||||
|
||||
while (xmlAttribute)
|
||||
{
|
||||
anm2Attribute = anm2_attribute_from_string(xmlAttribute->Name());
|
||||
anm2Attribute = ANM2_ATTRIBUTE_STRING_TO_ENUM(xmlAttribute->Name());
|
||||
|
||||
switch (anm2Attribute)
|
||||
{
|
||||
case ANM2_ATTRIBUTE_CREATED_BY:
|
||||
strncpy(self->createdBy, xmlAttribute->Value(), ANM2_STRING_MAX - 1);
|
||||
case ANM2_ATTRIBUTE_CREATED_BY: // CreatedBy
|
||||
self->createdBy = xmlAttribute->Value();
|
||||
break;
|
||||
case ANM2_ATTRIBUTE_CREATED_ON:
|
||||
strncpy(self->createdOn, xmlAttribute->Value(), ANM2_STRING_MAX - 1);
|
||||
case ANM2_ATTRIBUTE_CREATED_ON: // CreatedOn
|
||||
self->createdOn = xmlAttribute->Value();
|
||||
break;
|
||||
case ANM2_ATTRIBUTE_VERSION:
|
||||
case ANM2_ATTRIBUTE_VERSION: // Version
|
||||
self->version = atoi(xmlAttribute->Value());
|
||||
break;
|
||||
case ANM2_ATTRIBUTE_FPS:
|
||||
case ANM2_ATTRIBUTE_FPS: // FPS
|
||||
self->fps = atoi(xmlAttribute->Value());
|
||||
break;
|
||||
case ANM2_ATTRIBUTE_ID:
|
||||
case ANM2_ATTRIBUTE_ID: // ID
|
||||
id = atoi(xmlAttribute->Value());
|
||||
switch (anm2Element)
|
||||
{
|
||||
case ANM2_ELEMENT_SPRITESHEET:
|
||||
case ANM2_ELEMENT_SPRITESHEET: // Spritesheet
|
||||
self->spritesheets[id] = addSpritesheet;
|
||||
spritesheet = &self->spritesheets[id];
|
||||
break;
|
||||
case ANM2_ELEMENT_LAYER:
|
||||
case ANM2_ELEMENT_LAYER: // Layer
|
||||
self->layers[id] = addLayer;
|
||||
layer = &self->layers[id];
|
||||
break;
|
||||
case ANM2_ELEMENT_NULL:
|
||||
case ANM2_ELEMENT_NULL: // Null
|
||||
self->nulls[id] = addNull;
|
||||
null = &self->nulls[id];
|
||||
break;
|
||||
case ANM2_ELEMENT_EVENT:
|
||||
case ANM2_ELEMENT_EVENT: // Event
|
||||
self->events[id] = addEvent;
|
||||
event = &self->events[id];
|
||||
break;
|
||||
@@ -449,33 +453,33 @@ anm2_deserialize(Anm2* self, Resources* resources, const char* path)
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ANM2_ATTRIBUTE_LAYER_ID:
|
||||
case ANM2_ATTRIBUTE_LAYER_ID: // LayerId
|
||||
id = atoi(xmlAttribute->Value());
|
||||
animation->layerAnimations[id] = addItem;
|
||||
item = &animation->layerAnimations[id];
|
||||
break;
|
||||
case ANM2_ATTRIBUTE_NULL_ID:
|
||||
case ANM2_ATTRIBUTE_NULL_ID: // NullId
|
||||
id = atoi(xmlAttribute->Value());
|
||||
animation->nullAnimations[id] = addItem;
|
||||
item = &animation->nullAnimations[id];
|
||||
break;
|
||||
case ANM2_ATTRIBUTE_PATH:
|
||||
strncpy(spritesheet->path, xmlAttribute->Value(), PATH_MAX - 1);
|
||||
case ANM2_ATTRIBUTE_PATH: // Path
|
||||
spritesheet->path = xmlAttribute->Value();
|
||||
break;
|
||||
case ANM2_ATTRIBUTE_NAME:
|
||||
case ANM2_ATTRIBUTE_NAME: // Name
|
||||
switch (anm2Element)
|
||||
{
|
||||
case ANM2_ELEMENT_LAYER:
|
||||
strncpy(layer->name, xmlAttribute->Value(), ANM2_STRING_MAX - 1);
|
||||
layer->name = std::string(xmlAttribute->Value());
|
||||
break;
|
||||
case ANM2_ELEMENT_NULL:
|
||||
strncpy(null->name, xmlAttribute->Value(), ANM2_STRING_MAX - 1);
|
||||
null->name = std::string(xmlAttribute->Value());
|
||||
break;
|
||||
case ANM2_ELEMENT_ANIMATION:
|
||||
strncpy(animation->name, xmlAttribute->Value(), ANM2_STRING_MAX - 1);
|
||||
animation->name = std::string(xmlAttribute->Value());
|
||||
break;
|
||||
case ANM2_ELEMENT_EVENT:
|
||||
strncpy(event->name, xmlAttribute->Value(), ANM2_STRING_MAX - 1);
|
||||
event->name = std::string(xmlAttribute->Value());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -488,7 +492,7 @@ anm2_deserialize(Anm2* self, Resources* resources, const char* path)
|
||||
null->isShowRect = string_to_bool(xmlAttribute->Value());
|
||||
break;
|
||||
case ANM2_ATTRIBUTE_DEFAULT_ANIMATION:
|
||||
strncpy(self->defaultAnimation, xmlAttribute->Value(), ANM2_STRING_MAX - 1);
|
||||
self->defaultAnimation = xmlAttribute->Value();
|
||||
break;
|
||||
case ANM2_ATTRIBUTE_FRAME_NUM:
|
||||
animation->frameNum = atoi(xmlAttribute->Value());
|
||||
@@ -584,11 +588,10 @@ anm2_deserialize(Anm2* self, Resources* resources, const char* path)
|
||||
xmlAttribute = xmlAttribute->Next();
|
||||
}
|
||||
|
||||
/* Load spritesheet textures */
|
||||
// Load this anm2's spritesheet textures
|
||||
if (anm2Element == ANM2_ELEMENT_SPRITESHEET)
|
||||
anm2_spritesheet_texture_load(self, resources, spritesheet->path , id);
|
||||
resources_texture_init(resources, spritesheet->path , id);
|
||||
|
||||
/* Iterate through children */
|
||||
xmlChild = xmlElement->FirstChildElement();
|
||||
|
||||
if (xmlChild)
|
||||
@@ -597,7 +600,7 @@ anm2_deserialize(Anm2* self, Resources* resources, const char* path)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Iterate through siblings */
|
||||
// Iterate through siblings
|
||||
while (xmlElement)
|
||||
{
|
||||
const XMLElement* xmlNext;
|
||||
@@ -610,20 +613,20 @@ anm2_deserialize(Anm2* self, Resources* resources, const char* path)
|
||||
break;
|
||||
}
|
||||
|
||||
/* If no siblings, return to parent. If no parent, end parsing */
|
||||
// If no siblings, return to parent. If no parent, end parsing
|
||||
xmlElement = xmlElement->Parent() ? xmlElement->Parent()->ToElement() : NULL;
|
||||
}
|
||||
}
|
||||
|
||||
printf(STRING_INFO_ANM2_READ, path);
|
||||
|
||||
/* Set working directory back to old */
|
||||
std::cout << STRING_INFO_ANM2_READ << path << std::endl;
|
||||
|
||||
// Return to old working directory
|
||||
std::filesystem::current_path(workingPath);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Adds a new layer to the anm2 */
|
||||
// Adds a layer to the anm2
|
||||
void
|
||||
anm2_layer_add(Anm2* self)
|
||||
{
|
||||
@@ -635,17 +638,22 @@ anm2_layer_add(Anm2* self)
|
||||
animation.layerAnimations[id] = Anm2Item{};
|
||||
}
|
||||
|
||||
/* Removes a layer from the anm2 given the index/id */
|
||||
// Removes a layer from the anm2
|
||||
void
|
||||
anm2_layer_remove(Anm2* self, s32 id)
|
||||
{
|
||||
// Make sure the layer exists
|
||||
auto it = self->layers.find(id);
|
||||
if (it == self->layers.end())
|
||||
return;
|
||||
|
||||
self->layers.erase(id);
|
||||
|
||||
for (auto & [animationID, animation] : self->animations)
|
||||
animation.layerAnimations.erase(id);
|
||||
}
|
||||
|
||||
/* Adds a new null to the anm2 */
|
||||
// Adds a null to the anm2
|
||||
void
|
||||
anm2_null_add(Anm2* self)
|
||||
{
|
||||
@@ -657,36 +665,41 @@ anm2_null_add(Anm2* self)
|
||||
animation.nullAnimations[id] = Anm2Item{};
|
||||
}
|
||||
|
||||
/* Removes a null from the anm2 given the index/id */
|
||||
// Removes the specified null from the anm2
|
||||
void
|
||||
anm2_null_remove(Anm2* self, s32 id)
|
||||
{
|
||||
// Make sure the null exists
|
||||
auto it = self->nulls.find(id);
|
||||
if (it == self->nulls.end())
|
||||
return;
|
||||
|
||||
self->nulls.erase(id);
|
||||
|
||||
for (auto & [animationID, animation] : self->animations)
|
||||
animation.nullAnimations.erase(id);
|
||||
}
|
||||
|
||||
/* Adds a new animation to the anm2, makes sure to keep the layeranimations/nullsanimation check */
|
||||
// Adds an animation to the anm2
|
||||
s32
|
||||
anm2_animation_add(Anm2* self)
|
||||
{
|
||||
s32 id = map_next_id_get(self->animations);
|
||||
Anm2Animation animation;
|
||||
|
||||
/* match layers */
|
||||
// Match layers
|
||||
for (auto & [layerID, layer] : self->layers)
|
||||
{
|
||||
animation.layerAnimations[layerID] = Anm2Item{};
|
||||
}
|
||||
|
||||
/* match nulls */
|
||||
// Match nulls
|
||||
for (auto & [nullID, null] : self->nulls)
|
||||
{
|
||||
animation.nullAnimations[nullID] = Anm2Item{};
|
||||
}
|
||||
|
||||
/* add a root frame */
|
||||
// Add a root frame
|
||||
animation.rootAnimation.frames.push_back(Anm2Frame{});
|
||||
|
||||
self->animations[id] = animation;
|
||||
@@ -694,34 +707,19 @@ anm2_animation_add(Anm2* self)
|
||||
return id;
|
||||
}
|
||||
|
||||
// Removes an animation by id from the anm2
|
||||
void
|
||||
anm2_animation_remove(Anm2* self, s32 id)
|
||||
{
|
||||
self->animations.erase(id);
|
||||
}
|
||||
|
||||
/* Makes an entirely new anm2 */
|
||||
// Sets the anm2 to default
|
||||
void
|
||||
anm2_new(Anm2* self)
|
||||
{
|
||||
*self = Anm2{};
|
||||
anm2_created_on_set(self);
|
||||
}
|
||||
|
||||
void
|
||||
anm2_spritesheet_texture_load(Anm2* self, Resources* resources, const char* path, s32 id)
|
||||
{
|
||||
Texture texture;
|
||||
|
||||
if (resources->textures.find(id) != resources->textures.end() && resources->textures[id].id != resources->textures[TEXTURE_ERROR].id)
|
||||
texture_free(&resources->textures[id]);
|
||||
|
||||
if (texture_from_path_init(&texture, path))
|
||||
resources->textures[id] = texture;
|
||||
else
|
||||
texture.isInvalid = true;
|
||||
|
||||
resources->textures[id] = texture;
|
||||
_anm2_created_on_set(self);
|
||||
}
|
||||
|
||||
Anm2Animation*
|
||||
@@ -733,7 +731,7 @@ anm2_animation_from_reference(Anm2* self, Anm2Reference* reference)
|
||||
return &it->second;
|
||||
}
|
||||
|
||||
/* Returns the item from a anm2 reference. */
|
||||
// Returns the item from a anm2 reference.
|
||||
Anm2Item*
|
||||
anm2_item_from_reference(Anm2* self, Anm2Reference* reference)
|
||||
{
|
||||
@@ -767,7 +765,7 @@ anm2_item_from_reference(Anm2* self, Anm2Reference* reference)
|
||||
}
|
||||
}
|
||||
|
||||
/* Gets the frame from the reference's properties */
|
||||
// Gets the frame from the reference's properties
|
||||
Anm2Frame*
|
||||
anm2_frame_from_reference(Anm2* self, Anm2Reference* reference)
|
||||
{
|
||||
@@ -782,14 +780,15 @@ anm2_frame_from_reference(Anm2* self, Anm2Reference* reference)
|
||||
return &item->frames[reference->frameIndex];
|
||||
}
|
||||
|
||||
/* Creates/fetches a frame from a given time. */
|
||||
/* Returns true/false if frame will be valid or not. */
|
||||
// Creates or fetches a frame from a given time.
|
||||
void
|
||||
anm2_frame_from_time(Anm2* self, Anm2Frame* frame, Anm2Reference reference, f32 time)
|
||||
{
|
||||
Anm2Animation* animation = anm2_animation_from_reference(self, &reference);
|
||||
|
||||
/* Out of range */
|
||||
if (!animation)
|
||||
return;
|
||||
|
||||
if (time < 0 || time > animation->frameNum)
|
||||
return;
|
||||
|
||||
@@ -807,8 +806,7 @@ anm2_frame_from_time(Anm2* self, Anm2Frame* frame, Anm2Reference reference, f32
|
||||
*frame = item->frames[i];
|
||||
delayNext += frame->delay;
|
||||
|
||||
/* If a frame is within the time constraints, it's a time matched frame, break */
|
||||
/* Otherwise, the last found frame parsed will be used. */
|
||||
// Use the last parsed frame as the given frame.
|
||||
if (time >= delayCurrent && time < delayNext)
|
||||
{
|
||||
if (i + 1 < (s32)item->frames.size())
|
||||
@@ -821,7 +819,7 @@ anm2_frame_from_time(Anm2* self, Anm2Frame* frame, Anm2Reference reference, f32
|
||||
delayCurrent += frame->delay;
|
||||
}
|
||||
|
||||
/* Interpolate only if there's a frame following */
|
||||
// Interpolate, but only if there's a frame following.
|
||||
if (frame->isInterpolated && nextFrame)
|
||||
{
|
||||
f32 interpolationTime = (time - delayCurrent) / (delayNext - delayCurrent);
|
||||
@@ -834,11 +832,10 @@ anm2_frame_from_time(Anm2* self, Anm2Frame* frame, Anm2Reference reference, f32
|
||||
}
|
||||
}
|
||||
|
||||
/* Returns the current length of the animation, from the used frames. */
|
||||
// Returns the animation's length, based on the present frames.
|
||||
s32
|
||||
anm2_animation_length_get(Anm2* self, s32 animationID)
|
||||
{
|
||||
/* Get valid animation */
|
||||
auto it = self->animations.find(animationID);
|
||||
if (it == self->animations.end())
|
||||
return -1;
|
||||
@@ -846,28 +843,29 @@ anm2_animation_length_get(Anm2* self, s32 animationID)
|
||||
Anm2Animation* animation = &it->second;
|
||||
s32 delayHighest = 0;
|
||||
|
||||
/* Root frames */
|
||||
// Go through all items and see which one has the latest frame; that's the length
|
||||
// Root
|
||||
for (auto & frame : animation->rootAnimation.frames)
|
||||
delayHighest = std::max(delayHighest, frame.delay);
|
||||
|
||||
/* Layer frames */
|
||||
// Layer
|
||||
for (auto & [id, item] : animation->layerAnimations)
|
||||
for (auto & frame : item.frames)
|
||||
delayHighest = std::max(delayHighest, frame.delay);
|
||||
|
||||
/* Null frames */
|
||||
// Null
|
||||
for (auto & [id, item] : animation->nullAnimations)
|
||||
for (auto & frame : item.frames)
|
||||
delayHighest = std::max(delayHighest, frame.delay);
|
||||
|
||||
/* Trigger frames (assuming this is from `animation->triggers.frames`) */
|
||||
// Triggers
|
||||
for (auto & trigger : animation->triggers.frames)
|
||||
delayHighest = std::max(delayHighest, trigger.atFrame);
|
||||
|
||||
return delayHighest;
|
||||
}
|
||||
|
||||
/* Will try adding a frame to the anm2 given the specified reference */
|
||||
// Will try adding a frame to the anm2 given the specified reference
|
||||
Anm2Frame*
|
||||
anm2_frame_add(Anm2* self, Anm2Reference* reference, s32 time)
|
||||
{
|
||||
@@ -884,7 +882,7 @@ anm2_frame_add(Anm2* self, Anm2Reference* reference, s32 time)
|
||||
|
||||
if (reference->itemType == ANM2_TRIGGERS)
|
||||
{
|
||||
/* don't add redudant triggers (i.e. at same time) */
|
||||
// Don't add redundant triggers
|
||||
for (auto & frameCheck : item->frames)
|
||||
{
|
||||
if (frameCheck.atFrame == time)
|
||||
@@ -898,20 +896,20 @@ anm2_frame_add(Anm2* self, Anm2Reference* reference, s32 time)
|
||||
{
|
||||
s32 frameDelayCount = 0;
|
||||
|
||||
/* Add up all delay to see where this new frame might lie */
|
||||
// Get the latest frame delay, to see where this frame might lie
|
||||
for (auto & frameCheck : item->frames)
|
||||
frameDelayCount += frameCheck.delay;
|
||||
|
||||
/* If adding the smallest frame would be over the length, don't bother */
|
||||
// If adding the smallest frame delay would be over the length, don't bother
|
||||
if (frameDelayCount + ANM2_FRAME_DELAY_MIN > animation->frameNum)
|
||||
return NULL;
|
||||
|
||||
/* Will insert next to frame if frame exists */
|
||||
// Will insert next to frame if frame exists
|
||||
Anm2Frame* checkFrame = anm2_frame_from_reference(self, reference);
|
||||
|
||||
if (checkFrame)
|
||||
{
|
||||
/* Will shrink frame delay to fit */
|
||||
// Will shrink frame delay to fit
|
||||
if (frameDelayCount + checkFrame->delay > animation->frameNum)
|
||||
frame.delay = animation->frameNum - frameDelayCount;
|
||||
|
||||
@@ -929,14 +927,14 @@ anm2_frame_add(Anm2* self, Anm2Reference* reference, s32 time)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Clears anm2 reference */
|
||||
// Clears the anm2 reference, totally
|
||||
void
|
||||
anm2_reference_clear(Anm2Reference* self)
|
||||
{
|
||||
*self = Anm2Reference{};
|
||||
}
|
||||
|
||||
/* Clears anm2 item reference */
|
||||
// Clears the anm2 reference's item
|
||||
void
|
||||
anm2_reference_item_clear(Anm2Reference* self)
|
||||
{
|
||||
@@ -944,7 +942,7 @@ anm2_reference_item_clear(Anm2Reference* self)
|
||||
self->itemID = -1;
|
||||
}
|
||||
|
||||
/* Clears anm2 reference */
|
||||
// Clears the anm2 reference's frame
|
||||
void
|
||||
anm2_reference_frame_clear(Anm2Reference* self)
|
||||
{
|
||||
|
45
src/anm2.h
45
src/anm2.h
@@ -6,15 +6,12 @@
|
||||
#define ANM2_SCALE_CONVERT(x) ((f32)x / 100.0f)
|
||||
#define ANM2_TINT_CONVERT(x) ((f32)x / 255.0f)
|
||||
|
||||
#define ANM2_STRING_MAX 0xFF
|
||||
#define ANM2_STRING_FORMATTED_MAX 0xFFF
|
||||
#define ANM2_PATH_FORMATTED_MAX PATH_MAX + 0xFF
|
||||
#define ANM2_BUFFER_MAX 0xFFFFF
|
||||
#define ANM2_FPS_MIN 0
|
||||
#define ANM2_FPS_MAX 120
|
||||
#define ANM2_FRAME_NUM_MIN 1
|
||||
#define ANM2_FRAME_NUM_MAX 1000000
|
||||
#define ANM2_FRAME_DELAY_MIN 1
|
||||
#define ANM2_STRING_MAX 0xFF
|
||||
|
||||
/* Elements */
|
||||
#define ANM2_ELEMENT_LIST \
|
||||
@@ -53,7 +50,8 @@ static const char* ANM2_ELEMENT_STRINGS[] = {
|
||||
#undef X
|
||||
};
|
||||
|
||||
DEFINE_STRING_TO_ENUM_FN(anm2_element_from_string, Anm2Element, ANM2_ELEMENT_STRINGS, ANM2_ELEMENT_COUNT)
|
||||
DEFINE_STRING_TO_ENUM_FUNCTION(ANM2_ELEMENT_STRING_TO_ENUM, Anm2Element, ANM2_ELEMENT_STRINGS, ANM2_ELEMENT_COUNT)
|
||||
DEFINE_ENUM_TO_STRING_FUNCTION(ANM2_ELEMENT_ENUM_TO_STRING, ANM2_ELEMENT_STRINGS, ANM2_ELEMENT_COUNT)
|
||||
|
||||
#define ANM2_ATTRIBUTE_LIST \
|
||||
X(CREATED_BY, "CreatedBy") \
|
||||
@@ -107,38 +105,39 @@ static const char* ANM2_ATTRIBUTE_STRINGS[] = {
|
||||
#undef X
|
||||
};
|
||||
|
||||
DEFINE_STRING_TO_ENUM_FN(anm2_attribute_from_string, Anm2Attribute, ANM2_ATTRIBUTE_STRINGS, ANM2_ATTRIBUTE_COUNT)
|
||||
DEFINE_STRING_TO_ENUM_FUNCTION(ANM2_ATTRIBUTE_STRING_TO_ENUM, Anm2Attribute, ANM2_ATTRIBUTE_STRINGS, ANM2_ATTRIBUTE_COUNT)
|
||||
DEFINE_ENUM_TO_STRING_FUNCTION(ANM2_ATTRIBUTE_ENUM_TO_STRING, ANM2_ATTRIBUTE_STRINGS, ANM2_ATTRIBUTE_COUNT)
|
||||
|
||||
#define ANM2_COUNT (ANM2_TRIGGER + 1)
|
||||
enum Anm2Type
|
||||
{
|
||||
ANM2_NONE,
|
||||
ANM2_ROOT,
|
||||
ANM2_LAYER,
|
||||
ANM2_NULL,
|
||||
ANM2_TRIGGERS
|
||||
ANM2_TRIGGERS,
|
||||
ANM2_COUNT
|
||||
};
|
||||
|
||||
struct Anm2Spritesheet
|
||||
{
|
||||
char path[PATH_MAX] = STRING_EMPTY;
|
||||
std::string path;
|
||||
};
|
||||
|
||||
struct Anm2Layer
|
||||
{
|
||||
std::string name = STRING_ANM2_NEW_LAYER;
|
||||
s32 spritesheetID = -1;
|
||||
char name[ANM2_STRING_MAX] = STRING_ANM2_NEW_LAYER;
|
||||
};
|
||||
|
||||
struct Anm2Null
|
||||
{
|
||||
char name[ANM2_STRING_MAX] = STRING_ANM2_NEW_NULL;
|
||||
std::string name = STRING_ANM2_NEW_NULL;
|
||||
bool isShowRect = false;
|
||||
};
|
||||
|
||||
struct Anm2Event
|
||||
{
|
||||
char name[ANM2_STRING_MAX] = STRING_ANM2_NEW_EVENT;
|
||||
std::string name = STRING_ANM2_NEW_EVENT;
|
||||
};
|
||||
|
||||
struct Anm2Frame
|
||||
@@ -167,7 +166,7 @@ struct Anm2Item
|
||||
struct Anm2Animation
|
||||
{
|
||||
s32 frameNum = ANM2_FRAME_NUM_MIN;
|
||||
char name[ANM2_STRING_MAX] = STRING_ANM2_NEW_ANIMATION;
|
||||
std::string name = STRING_ANM2_NEW_ANIMATION;
|
||||
bool isLoop = true;
|
||||
Anm2Item rootAnimation;
|
||||
std::map<s32, Anm2Item> layerAnimations;
|
||||
@@ -177,23 +176,23 @@ struct Anm2Animation
|
||||
|
||||
struct Anm2
|
||||
{
|
||||
char path[PATH_MAX] = STRING_EMPTY;
|
||||
s32 fps = 30;
|
||||
s32 version = 0;
|
||||
char createdBy[ANM2_STRING_MAX] = STRING_ANM2_CREATED_BY_DEFAULT;
|
||||
char createdOn[ANM2_STRING_MAX] = STRING_EMPTY;
|
||||
char defaultAnimation[ANM2_STRING_MAX] = STRING_EMPTY;
|
||||
std::string path;
|
||||
std::string defaultAnimation;
|
||||
std::string createdBy = STRING_ANM2_CREATED_BY_DEFAULT;
|
||||
std::string createdOn;
|
||||
std::map<s32, Anm2Spritesheet> spritesheets;
|
||||
std::map<s32, Anm2Layer> layers;
|
||||
std::map<s32, Anm2Null> nulls;
|
||||
std::map<s32, Anm2Event> events;
|
||||
std::map<s32, Anm2Animation> animations;
|
||||
s32 fps = 30;
|
||||
s32 version = 0;
|
||||
};
|
||||
|
||||
struct Anm2Reference
|
||||
{
|
||||
Anm2Type itemType = ANM2_NONE;
|
||||
s32 animationID = -1;
|
||||
Anm2Type itemType = ANM2_NONE;
|
||||
s32 itemID = -1;
|
||||
s32 frameIndex = -1;
|
||||
|
||||
@@ -204,13 +203,13 @@ void anm2_layer_add(Anm2* self);
|
||||
void anm2_layer_remove(Anm2* self, s32 id);
|
||||
void anm2_null_add(Anm2* self);
|
||||
void anm2_null_remove(Anm2* self, s32 id);
|
||||
bool anm2_serialize(Anm2* self, const char* path);
|
||||
bool anm2_deserialize(Anm2* self, Resources* resources, const char* path);
|
||||
bool anm2_serialize(Anm2* self, const std::string& path);
|
||||
bool anm2_deserialize(Anm2* self, Resources* resources, const std::string& path);
|
||||
void anm2_new(Anm2* self);
|
||||
void anm2_created_on_set(Anm2* self);
|
||||
s32 anm2_animation_add(Anm2* self);
|
||||
void anm2_animation_remove(Anm2* self, s32 id);
|
||||
void anm2_spritesheet_texture_load(Anm2* self, Resources* resources, const char* path, s32 id);
|
||||
void anm2_spritesheet_texture_load(Anm2* self, Resources* resources, const std::string& path, s32 id);
|
||||
Anm2Animation* anm2_animation_from_reference(Anm2* self, Anm2Reference* reference);
|
||||
Anm2Item* anm2_item_from_reference(Anm2* self, Anm2Reference* reference);
|
||||
Anm2Frame* anm2_frame_from_reference(Anm2* self, Anm2Reference* reference);
|
||||
|
@@ -2,6 +2,7 @@
|
||||
|
||||
static void _dialog_callback(void* userdata, const char* const* filelist, s32 filter);
|
||||
|
||||
// Callback that runs during the file dialog; will get the path and determine if one has been selected
|
||||
static void
|
||||
_dialog_callback(void* userdata, const char* const* filelist, s32 filter)
|
||||
{
|
||||
@@ -11,13 +12,14 @@ _dialog_callback(void* userdata, const char* const* filelist, s32 filter)
|
||||
|
||||
if (filelist && filelist[0] && strlen(filelist[0]) > 0)
|
||||
{
|
||||
strncpy(self->path, filelist[0], PATH_MAX - 1);
|
||||
self->path = filelist[0];
|
||||
self->isSelected = true;
|
||||
}
|
||||
else
|
||||
self->isSelected = false;
|
||||
}
|
||||
|
||||
// Initializes dialog
|
||||
void
|
||||
dialog_init(Dialog* self, Anm2* anm2, Anm2Reference* reference, Resources* resources, SDL_Window* window)
|
||||
{
|
||||
@@ -27,7 +29,7 @@ dialog_init(Dialog* self, Anm2* anm2, Anm2Reference* reference, Resources* resou
|
||||
self->window = window;
|
||||
}
|
||||
|
||||
/* Opens file dialog for user to pick anm2 files */
|
||||
// Opens file dialog to open a new anm2
|
||||
void
|
||||
dialog_anm2_open(Dialog* self)
|
||||
{
|
||||
@@ -35,7 +37,7 @@ dialog_anm2_open(Dialog* self)
|
||||
self->type = DIALOG_ANM2_OPEN;
|
||||
}
|
||||
|
||||
/* Opens file dialog for user to save new anm2 files */
|
||||
// Opens file dialog to save anm2
|
||||
void
|
||||
dialog_anm2_save(Dialog* self)
|
||||
{
|
||||
@@ -43,7 +45,7 @@ dialog_anm2_save(Dialog* self)
|
||||
self->type = DIALOG_ANM2_SAVE;
|
||||
}
|
||||
|
||||
/* Opens file dialog for user to pick png files for spritesheets */
|
||||
// Opens file dialog to open png
|
||||
void
|
||||
dialog_png_open(Dialog* self)
|
||||
{
|
||||
@@ -51,7 +53,7 @@ dialog_png_open(Dialog* self)
|
||||
self->type = DIALOG_PNG_OPEN;
|
||||
}
|
||||
|
||||
/* Opens file dialog for user to pick png file to replace selected one */
|
||||
// Opens file dialog to replace a given png
|
||||
void
|
||||
dialog_png_replace(Dialog* self)
|
||||
{
|
||||
@@ -59,6 +61,7 @@ dialog_png_replace(Dialog* self)
|
||||
self->type = DIALOG_PNG_REPLACE;
|
||||
}
|
||||
|
||||
// Ticks dialog
|
||||
void
|
||||
dialog_tick(Dialog* self)
|
||||
{
|
||||
@@ -82,19 +85,19 @@ dialog_tick(Dialog* self)
|
||||
case DIALOG_PNG_OPEN:
|
||||
id = map_next_id_get(self->resources->textures);
|
||||
self->anm2->spritesheets[id] = Anm2Spritesheet{};
|
||||
strncpy(self->anm2->spritesheets[id].path, self->path, PATH_MAX);
|
||||
anm2_spritesheet_texture_load(self->anm2, self->resources, self->path, id);
|
||||
self->path = self->anm2->spritesheets[id].path;
|
||||
resources_texture_init(self->resources, self->path, id);
|
||||
break;
|
||||
case DIALOG_PNG_REPLACE:
|
||||
strncpy(self->anm2->spritesheets[self->replaceID].path, self->path, PATH_MAX);
|
||||
anm2_spritesheet_texture_load(self->anm2, self->resources, self->path, self->replaceID);
|
||||
self->anm2->spritesheets[self->replaceID].path = self->path;
|
||||
resources_texture_init(self->resources, self->path, self->replaceID);
|
||||
self->replaceID = -1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
memset(self->path, '\0', PATH_MAX);
|
||||
self->path.clear();
|
||||
self->isSelected = false;
|
||||
}
|
||||
}
|
||||
|
12
src/dialog.h
12
src/dialog.h
@@ -4,12 +4,12 @@
|
||||
#include "resources.h"
|
||||
#include "window.h"
|
||||
|
||||
static const SDL_DialogFileFilter DIALOG_FILE_FILTER_ANM2[] =
|
||||
const SDL_DialogFileFilter DIALOG_FILE_FILTER_ANM2[] =
|
||||
{
|
||||
{"Anm2", "anm2;xml"}
|
||||
};
|
||||
|
||||
static const SDL_DialogFileFilter DIALOG_FILE_FILTER_PNG[] =
|
||||
const SDL_DialogFileFilter DIALOG_FILE_FILTER_PNG[] =
|
||||
{
|
||||
{"png", "png"}
|
||||
};
|
||||
@@ -20,7 +20,8 @@ enum DialogType
|
||||
DIALOG_ANM2_OPEN,
|
||||
DIALOG_ANM2_SAVE,
|
||||
DIALOG_PNG_OPEN,
|
||||
DIALOG_PNG_REPLACE
|
||||
DIALOG_PNG_REPLACE,
|
||||
DIALOG_FRAME_DIRECTORY_OPEN,
|
||||
};
|
||||
|
||||
struct Dialog
|
||||
@@ -29,9 +30,9 @@ struct Dialog
|
||||
Anm2Reference* reference = NULL;
|
||||
Resources* resources = NULL;
|
||||
SDL_Window* window = NULL;
|
||||
std::string path;
|
||||
s32 replaceID = -1;
|
||||
enum DialogType type = DIALOG_NONE;
|
||||
char path[PATH_MAX] = "";
|
||||
DialogType type = DIALOG_NONE;
|
||||
bool isSelected = false;
|
||||
};
|
||||
|
||||
@@ -40,4 +41,5 @@ void dialog_anm2_open(Dialog* self);
|
||||
void dialog_png_open(Dialog* self);
|
||||
void dialog_png_replace(Dialog* self);
|
||||
void dialog_anm2_save(Dialog* self);
|
||||
void dialog_frame_directory_open(Dialog* self);
|
||||
void dialog_tick(Dialog* self);
|
@@ -2,6 +2,7 @@
|
||||
|
||||
static s32 _editor_grid_set(Editor* self);
|
||||
|
||||
// Sets the editor's grid
|
||||
static s32
|
||||
_editor_grid_set(Editor* self)
|
||||
{
|
||||
@@ -44,6 +45,7 @@ _editor_grid_set(Editor* self)
|
||||
return (s32)vertices.size();
|
||||
}
|
||||
|
||||
// Initializes editor
|
||||
void
|
||||
editor_init(Editor* self, Anm2* anm2, Anm2Reference* reference, Resources* resources, Settings* settings)
|
||||
{
|
||||
@@ -52,7 +54,7 @@ editor_init(Editor* self, Anm2* anm2, Anm2Reference* reference, Resources* resou
|
||||
self->resources = resources;
|
||||
self->settings = settings;
|
||||
|
||||
/* Framebuffer + texture */
|
||||
// Framebuffer + texture
|
||||
glGenFramebuffers(1, &self->fbo);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, self->fbo);
|
||||
@@ -72,11 +74,11 @@ editor_init(Editor* self, Anm2* anm2, Anm2Reference* reference, Resources* resou
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
||||
/* Grid */
|
||||
// Grid
|
||||
glGenVertexArrays(1, &self->gridVAO);
|
||||
glGenBuffers(1, &self->gridVBO);
|
||||
|
||||
/* Border */
|
||||
// Border
|
||||
glGenVertexArrays(1, &self->borderVAO);
|
||||
glGenBuffers(1, &self->borderVBO);
|
||||
|
||||
@@ -88,7 +90,7 @@ editor_init(Editor* self, Anm2* anm2, Anm2Reference* reference, Resources* resou
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(f32), (void*)0);
|
||||
|
||||
/* Viewing texture */
|
||||
// Texture
|
||||
glGenVertexArrays(1, &self->textureVAO);
|
||||
glGenBuffers(1, &self->textureVBO);
|
||||
glGenBuffers(1, &self->textureEBO);
|
||||
@@ -101,11 +103,11 @@ editor_init(Editor* self, Anm2* anm2, Anm2Reference* reference, Resources* resou
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self->textureEBO);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GL_TEXTURE_INDICES), GL_TEXTURE_INDICES, GL_STATIC_DRAW);
|
||||
|
||||
/* Position */
|
||||
// Position attribute
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(f32), (void*)0);
|
||||
|
||||
/* UV */
|
||||
// UV position attribute
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(f32), (void*)(2 * sizeof(f32)));
|
||||
|
||||
@@ -114,18 +116,18 @@ editor_init(Editor* self, Anm2* anm2, Anm2Reference* reference, Resources* resou
|
||||
_editor_grid_set(self);
|
||||
}
|
||||
|
||||
// Draws the editor
|
||||
void
|
||||
editor_draw(Editor* self)
|
||||
{
|
||||
GLuint shaderLine = self->resources->shaders[SHADER_LINE];
|
||||
GLuint shaderLineDotted = self->resources->shaders[SHADER_LINE_DOTTED];
|
||||
GLuint shaderTexture = self->resources->shaders[SHADER_TEXTURE];
|
||||
f32 zoomFactor = self->settings->editorZoom / 100.0f;
|
||||
f32 zoomFactor = PERCENT_TO_UNIT(self->settings->editorZoom);
|
||||
|
||||
/* Convert pan to pixels */
|
||||
// Get normalized panning
|
||||
glm::vec2 ndcPan = glm::vec2(-self->settings->editorPanX / (EDITOR_SIZE.x / 2.0f), -self->settings->editorPanY / (EDITOR_SIZE.y / 2.0f));
|
||||
|
||||
/* Transformation matrix */
|
||||
glm::mat4 editorTransform = glm::translate(glm::mat4(1.0f), glm::vec3(ndcPan, 0.0f));
|
||||
editorTransform = glm::scale(editorTransform, glm::vec3(zoomFactor, zoomFactor, 1.0f));
|
||||
|
||||
@@ -142,12 +144,10 @@ editor_draw(Editor* self)
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
s32 spritesheetID = self->reference->itemType == ANM2_LAYER ?
|
||||
self->anm2->layers[self->reference->itemID].spritesheetID : -1;
|
||||
|
||||
if (spritesheetID > -1)
|
||||
// Drawing the selected spritesheet
|
||||
if (self->spritesheetID > -1)
|
||||
{
|
||||
Texture* texture = &self->resources->textures[spritesheetID];
|
||||
Texture* texture = &self->resources->textures[self->spritesheetID];
|
||||
|
||||
glm::mat4 spritesheetTransform = editorTransform;
|
||||
glm::vec2 ndcScale = glm::vec2(texture->size.x, texture->size.y) / (EDITOR_SIZE * 0.5f);
|
||||
@@ -176,6 +176,7 @@ editor_draw(Editor* self)
|
||||
glBindVertexArray(0);
|
||||
glUseProgram(0);
|
||||
|
||||
// Border around the spritesheet
|
||||
if (self->settings->editorIsBorder)
|
||||
{
|
||||
glUseProgram(shaderLineDotted);
|
||||
@@ -193,10 +194,10 @@ editor_draw(Editor* self)
|
||||
|
||||
Anm2Frame* frame = (Anm2Frame*)anm2_frame_from_reference(self->anm2, self->reference);
|
||||
|
||||
/* Draw the layer frame's crop and pivot */
|
||||
// Drawing the frame's crop and pivot
|
||||
if (frame)
|
||||
{
|
||||
/* Rect */
|
||||
// Crop
|
||||
glm::mat4 rectTransform = editorTransform;
|
||||
|
||||
glm::vec2 rectNDCPos = frame->crop / (EDITOR_SIZE / 2.0f);
|
||||
@@ -217,7 +218,7 @@ editor_draw(Editor* self)
|
||||
glBindVertexArray(0);
|
||||
glUseProgram(0);
|
||||
|
||||
/* Pivot */
|
||||
// Pivot
|
||||
glm::mat4 pivotTransform = editorTransform;
|
||||
glm::vec2 pivotNDCPos = ((frame->crop + frame->pivot) - (EDITOR_PIVOT_SIZE / 2.0f)) / (EDITOR_SIZE / 2.0f);
|
||||
glm::vec2 pivotNDCScale = EDITOR_PIVOT_SIZE / (EDITOR_SIZE / 2.0f);
|
||||
@@ -252,6 +253,7 @@ editor_draw(Editor* self)
|
||||
}
|
||||
}
|
||||
|
||||
// Grid
|
||||
if (self->settings->editorIsGrid)
|
||||
{
|
||||
static ivec2 previousGridSize = {-1, -1};
|
||||
@@ -292,12 +294,14 @@ editor_draw(Editor* self)
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
// Ticks editor
|
||||
void
|
||||
editor_tick(Editor* self)
|
||||
{
|
||||
self->settings->editorZoom = CLAMP(self->settings->editorZoom, EDITOR_ZOOM_MIN, EDITOR_ZOOM_MAX);
|
||||
}
|
||||
|
||||
// Frees editor
|
||||
void
|
||||
editor_free(Editor* self)
|
||||
{
|
||||
|
11
src/editor.h
11
src/editor.h
@@ -12,11 +12,11 @@
|
||||
#define EDITOR_GRID_OFFSET_MIN 0
|
||||
#define EDITOR_GRID_OFFSET_MAX 100
|
||||
|
||||
static const vec2 EDITOR_SIZE = {5000, 5000};
|
||||
static const vec2 EDITOR_PIVOT_SIZE = {4, 4};
|
||||
static const vec4 EDITOR_TEXTURE_TINT = COLOR_OPAQUE;
|
||||
static const vec4 EDITOR_BORDER_TINT = COLOR_OPAQUE;
|
||||
static const vec4 EDITOR_FRAME_TINT = COLOR_RED;
|
||||
const vec2 EDITOR_SIZE = {5000, 5000};
|
||||
const vec2 EDITOR_PIVOT_SIZE = {4, 4};
|
||||
const vec4 EDITOR_TEXTURE_TINT = COLOR_OPAQUE;
|
||||
const vec4 EDITOR_BORDER_TINT = COLOR_OPAQUE;
|
||||
const vec4 EDITOR_FRAME_TINT = COLOR_RED;
|
||||
|
||||
struct Editor
|
||||
{
|
||||
@@ -34,6 +34,7 @@ struct Editor
|
||||
GLuint textureVBO;
|
||||
GLuint borderVAO;
|
||||
GLuint borderVBO;
|
||||
s32 spritesheetID = -1;
|
||||
};
|
||||
|
||||
void editor_init(Editor* self, Anm2* anm2, Anm2Reference* reference, Resources* resources, Settings* settings);
|
||||
|
659
src/imgui.cpp
659
src/imgui.cpp
File diff suppressed because it is too large
Load Diff
97
src/imgui.h
97
src/imgui.h
@@ -32,62 +32,63 @@
|
||||
#define IMGUI_PICKER_LINE_COLOR IM_COL32(255, 255, 255, 255)
|
||||
#define IMGUI_TOOLS_WIDTH_INCREMENT -2
|
||||
|
||||
#define IMGUI_POSITION_STRING_MAX 0xFF
|
||||
#define VEC2_TO_IMVEC2(value) ImVec2(value.x, value.y)
|
||||
#define IMVEC2_TO_VEC2(value) glm::vec2(value.x, value.y)
|
||||
#define IMVEC2_ATLAS_UV_GET(type) VEC2_TO_IMVEC2(ATLAS_UVS[type][0]), VEC2_TO_IMVEC2(ATLAS_UVS[type][1])
|
||||
|
||||
static const vec2 IMGUI_TASKBAR_MARGINS = {8, 4};
|
||||
static const vec2 IMGUI_SPRITESHEET_EDITOR_CROP_FORGIVENESS = {1, 1};
|
||||
const vec2 IMGUI_TASKBAR_MARGINS = {8, 4};
|
||||
const vec2 IMGUI_SPRITESHEET_EDITOR_CROP_FORGIVENESS = {1, 1};
|
||||
|
||||
static const ImVec2 IMGUI_RECORD_TOOLTIP_OFFSET = {16, 16};
|
||||
static const ImVec2 IMGUI_ANIMATION_PREVIEW_SETTINGS_SIZE = {1280, 105};
|
||||
static const ImVec2 IMGUI_ANIMATION_PREVIEW_SETTINGS_CHILD_SIZE = {200, 85};
|
||||
static const ImVec2 IMGUI_ANIMATION_PREVIEW_POSITION = {8, 135};
|
||||
const ImVec2 IMGUI_RECORD_TOOLTIP_OFFSET = {16, 16};
|
||||
const ImVec2 IMGUI_ANIMATION_PREVIEW_SETTINGS_SIZE = {1280, 105};
|
||||
const ImVec2 IMGUI_ANIMATION_PREVIEW_SETTINGS_CHILD_SIZE = {200, 85};
|
||||
const ImVec2 IMGUI_ANIMATION_PREVIEW_POSITION = {8, 135};
|
||||
|
||||
static const ImVec2 IMGUI_SPRITESHEET_EDITOR_SETTINGS_CHILD_SIZE = {200, 85};
|
||||
static const ImVec2 IMGUI_SPRITESHEET_EDITOR_SETTINGS_SIZE = {1280, 105};
|
||||
const ImVec2 IMGUI_SPRITESHEET_EDITOR_SETTINGS_CHILD_SIZE = {200, 85};
|
||||
const ImVec2 IMGUI_SPRITESHEET_EDITOR_SETTINGS_SIZE = {1280, 105};
|
||||
|
||||
static const ImVec2 IMGUI_TIMELINE_ELEMENT_LIST_SIZE = {300, 0};
|
||||
static const ImVec2 IMGUI_TIMELINE_FRAMES_SIZE = {0, 0};
|
||||
static const ImVec2 IMGUI_TIMELINE_ELEMENT_FRAMES_SIZE = {0, 0};
|
||||
static const ImVec2 IMGUI_TIMELINE_FRAME_SIZE = {16, 40};
|
||||
static const ImVec2 IMGUI_TIMELINE_VIEWER_SIZE = {0, 40};
|
||||
static const ImVec2 IMGUI_TIMELINE_ELEMENTS_TIMELINE_SIZE = {0, 40};
|
||||
static const ImVec2 IMGUI_TIMELINE_FRAME_INDICES_SIZE = {0, 40};
|
||||
static const ImVec2 IMGUI_TIMELINE_ELEMENT_SIZE = {300, 40};
|
||||
static const ImVec2 IMGUI_TIMELINE_ELEMENT_NAME_SIZE = {150, 20};
|
||||
static const ImVec2 IMGUI_TIMELINE_ELEMENT_SPRITESHEET_ID_SIZE = {60, 20};
|
||||
const ImVec2 IMGUI_TIMELINE_ELEMENT_LIST_SIZE = {300, 0};
|
||||
const ImVec2 IMGUI_TIMELINE_FRAMES_SIZE = {0, 0};
|
||||
const ImVec2 IMGUI_TIMELINE_ELEMENT_FRAMES_SIZE = {0, 0};
|
||||
const ImVec2 IMGUI_TIMELINE_FRAME_SIZE = {16, 40};
|
||||
const ImVec2 IMGUI_TIMELINE_VIEWER_SIZE = {0, 40};
|
||||
const ImVec2 IMGUI_TIMELINE_ELEMENTS_TIMELINE_SIZE = {0, 40};
|
||||
const ImVec2 IMGUI_TIMELINE_FRAME_INDICES_SIZE = {0, 40};
|
||||
const ImVec2 IMGUI_TIMELINE_ELEMENT_SIZE = {300, 40};
|
||||
const ImVec2 IMGUI_TIMELINE_ELEMENT_NAME_SIZE = {150, 20};
|
||||
const ImVec2 IMGUI_TIMELINE_ELEMENT_SPRITESHEET_ID_SIZE = {60, 20};
|
||||
|
||||
static const ImVec2 IMGUI_SPRITESHEET_SIZE = {0, 150};
|
||||
static const ImVec2 IMGUI_SPRITESHEET_PREVIEW_SIZE = {100, 100};
|
||||
static const ImVec2 IMGUI_IMAGE_TARGET_SIZE = {125, 125};
|
||||
static const ImVec2 IMGUI_ICON_BUTTON_SIZE = {24, 24};
|
||||
static const ImVec2 IMGUI_DUMMY_SIZE = {1, 1};
|
||||
const ImVec2 IMGUI_SPRITESHEET_SIZE = {0, 150};
|
||||
const ImVec2 IMGUI_SPRITESHEET_PREVIEW_SIZE = {100, 100};
|
||||
const ImVec2 IMGUI_IMAGE_TARGET_SIZE = {125, 125};
|
||||
const ImVec2 IMGUI_ICON_BUTTON_SIZE = {24, 24};
|
||||
const ImVec2 IMGUI_DUMMY_SIZE = {1, 1};
|
||||
|
||||
static const ImVec4 IMGUI_TIMELINE_HEADER_COLOR = {0.04, 0.04, 0.04, 1.0f};
|
||||
static const ImVec4 IMGUI_FRAME_BORDER_COLOR = {1.0f, 1.0f, 1.0f, 0.5f};
|
||||
static const ImVec4 IMGUI_FRAME_OVERLAY_COLOR = {0.0f, 0.0f, 0.0f, 0.25f};
|
||||
static const ImVec4 IMGUI_FRAME_INDICES_OVERLAY_COLOR = {0.113, 0.184, 0.286, 1.0f};
|
||||
static const ImVec4 IMGUI_FRAME_INDICES_COLOR = {0.113, 0.184, 0.286, 0.5f};
|
||||
const ImVec4 IMGUI_TIMELINE_HEADER_COLOR = {0.04, 0.04, 0.04, 1.0f};
|
||||
const ImVec4 IMGUI_FRAME_BORDER_COLOR = {1.0f, 1.0f, 1.0f, 0.5f};
|
||||
const ImVec4 IMGUI_FRAME_OVERLAY_COLOR = {0.0f, 0.0f, 0.0f, 0.25f};
|
||||
const ImVec4 IMGUI_FRAME_INDICES_OVERLAY_COLOR = {0.113, 0.184, 0.286, 1.0f};
|
||||
const ImVec4 IMGUI_FRAME_INDICES_COLOR = {0.113, 0.184, 0.286, 0.5f};
|
||||
|
||||
static const ImVec4 IMGUI_TIMELINE_ROOT_COLOR = {0.010, 0.049, 0.078, 1.0f};
|
||||
static const ImVec4 IMGUI_TIMELINE_LAYER_COLOR = {0.098, 0.039, 0.020, 1.0f};
|
||||
static const ImVec4 IMGUI_TIMELINE_NULL_COLOR = {0.020, 0.049, 0.000, 1.0f};
|
||||
static const ImVec4 IMGUI_TIMELINE_TRIGGERS_COLOR = {0.078, 0.020, 0.029, 1.0f};
|
||||
const ImVec4 IMGUI_TIMELINE_ROOT_COLOR = {0.010, 0.049, 0.078, 1.0f};
|
||||
const ImVec4 IMGUI_TIMELINE_LAYER_COLOR = {0.098, 0.039, 0.020, 1.0f};
|
||||
const ImVec4 IMGUI_TIMELINE_NULL_COLOR = {0.020, 0.049, 0.000, 1.0f};
|
||||
const ImVec4 IMGUI_TIMELINE_TRIGGERS_COLOR = {0.078, 0.020, 0.029, 1.0f};
|
||||
|
||||
static const ImVec4 IMGUI_TIMELINE_ROOT_FRAME_COLOR = {0.020, 0.294, 0.569, 0.5};
|
||||
static const ImVec4 IMGUI_TIMELINE_LAYER_FRAME_COLOR = {0.529, 0.157, 0.000, 0.5};
|
||||
static const ImVec4 IMGUI_TIMELINE_NULL_FRAME_COLOR = {0.137, 0.353, 0.000, 0.5};
|
||||
static const ImVec4 IMGUI_TIMELINE_TRIGGERS_FRAME_COLOR = {0.529, 0.118, 0.196, 0.5};
|
||||
const ImVec4 IMGUI_TIMELINE_ROOT_FRAME_COLOR = {0.020, 0.294, 0.569, 0.5};
|
||||
const ImVec4 IMGUI_TIMELINE_LAYER_FRAME_COLOR = {0.529, 0.157, 0.000, 0.5};
|
||||
const ImVec4 IMGUI_TIMELINE_NULL_FRAME_COLOR = {0.137, 0.353, 0.000, 0.5};
|
||||
const ImVec4 IMGUI_TIMELINE_TRIGGERS_FRAME_COLOR = {0.529, 0.118, 0.196, 0.5};
|
||||
|
||||
static const ImVec4 IMGUI_TIMELINE_ROOT_HIGHLIGHT_COLOR = {0.314, 0.588, 0.843, 0.75};
|
||||
static const ImVec4 IMGUI_TIMELINE_LAYER_HIGHLIGHT_COLOR = {0.882, 0.412, 0.216, 0.75};
|
||||
static const ImVec4 IMGUI_TIMELINE_NULL_HIGHLIGHT_COLOR = {0.431, 0.647, 0.294, 0.75};
|
||||
static const ImVec4 IMGUI_TIMELINE_TRIGGERS_HIGHLIGHT_COLOR = {0.804, 0.412, 0.490, 0.75};
|
||||
|
||||
static const ImVec4 IMGUI_TIMELINE_ROOT_ACTIVE_COLOR = {0.471, 0.882, 1.000, 0.75};
|
||||
static const ImVec4 IMGUI_TIMELINE_LAYER_ACTIVE_COLOR = {1.000, 0.618, 0.324, 0.75};
|
||||
static const ImVec4 IMGUI_TIMELINE_NULL_ACTIVE_COLOR = {0.646, 0.971, 0.441, 0.75};
|
||||
static const ImVec4 IMGUI_TIMELINE_TRIGGERS_ACTIVE_COLOR = {1.000, 0.618, 0.735, 0.75};
|
||||
const ImVec4 IMGUI_TIMELINE_ROOT_HIGHLIGHT_COLOR = {0.314, 0.588, 0.843, 0.75};
|
||||
const ImVec4 IMGUI_TIMELINE_LAYER_HIGHLIGHT_COLOR = {0.882, 0.412, 0.216, 0.75};
|
||||
const ImVec4 IMGUI_TIMELINE_NULL_HIGHLIGHT_COLOR = {0.431, 0.647, 0.294, 0.75};
|
||||
const ImVec4 IMGUI_TIMELINE_TRIGGERS_HIGHLIGHT_COLOR = {0.804, 0.412, 0.490, 0.75};
|
||||
|
||||
const ImVec4 IMGUI_TIMELINE_ROOT_ACTIVE_COLOR = {0.471, 0.882, 1.000, 0.75};
|
||||
const ImVec4 IMGUI_TIMELINE_LAYER_ACTIVE_COLOR = {1.000, 0.618, 0.324, 0.75};
|
||||
const ImVec4 IMGUI_TIMELINE_NULL_ACTIVE_COLOR = {0.646, 0.971, 0.441, 0.75};
|
||||
const ImVec4 IMGUI_TIMELINE_TRIGGERS_ACTIVE_COLOR = {1.000, 0.618, 0.735, 0.75};
|
||||
|
||||
struct Imgui
|
||||
{
|
||||
@@ -128,5 +129,5 @@ imgui_init
|
||||
);
|
||||
|
||||
void imgui_tick(Imgui* self);
|
||||
void imgui_draw(Imgui* self);
|
||||
void imgui_free(Imgui* self);
|
||||
void imgui_draw();
|
||||
void imgui_free();
|
@@ -2,81 +2,120 @@
|
||||
|
||||
static void _mouse_tick(Mouse* self);
|
||||
|
||||
// Ticks mouse
|
||||
static void
|
||||
_mouse_tick(Mouse* self)
|
||||
{
|
||||
s32 state;
|
||||
|
||||
memcpy(&self->previous, &self->current, sizeof(bool) * MOUSE_COUNT);
|
||||
memset(&self->current, '\0', sizeof(bool) * MOUSE_COUNT);
|
||||
std::memcpy(&self->previous, &self->current, sizeof(self->current));
|
||||
std::memset(&self->current, '\0', sizeof(self->current));
|
||||
|
||||
state = SDL_GetMouseState(NULL, NULL);
|
||||
|
||||
if (state & SDL_BUTTON_LMASK != 0)
|
||||
if ((state & SDL_BUTTON_LMASK) != 0)
|
||||
{
|
||||
self->current[MOUSE_LEFT] = true;
|
||||
}
|
||||
|
||||
if (state & SDL_BUTTON_RMASK != 0)
|
||||
if ((state & SDL_BUTTON_RMASK) != 0)
|
||||
{
|
||||
self->current[MOUSE_RIGHT] = true;
|
||||
}
|
||||
|
||||
SDL_GetMouseState(&self->position.x, &self->position.y);
|
||||
SDL_GetMouseState(&self->position.x, &self->position.y);
|
||||
|
||||
self->delta = self->position - self->oldPosition;
|
||||
self->oldPosition = self->position;
|
||||
}
|
||||
|
||||
// Ticks keyboard
|
||||
static void
|
||||
_keyboard_tick(Keyboard* self)
|
||||
{
|
||||
const bool* state;
|
||||
|
||||
memcpy(&self->previous, &self->current, sizeof(self->previous));
|
||||
memset(&self->current, '\0', sizeof(self->current));
|
||||
std::memcpy(&self->previous, &self->current, sizeof(self->previous));
|
||||
std::memset(&self->current, '\0', sizeof(self->current));
|
||||
|
||||
state = SDL_GetKeyboardState(NULL);
|
||||
|
||||
memcpy(&self->current, state, KEY_COUNT);
|
||||
std::memcpy(&self->current, state, KEY_COUNT);
|
||||
}
|
||||
|
||||
// Checks to see if the given mouse button has been pressed
|
||||
bool
|
||||
mouse_press(Mouse* self, MouseType type)
|
||||
{
|
||||
return (self->current[type] && !self->previous[type]);
|
||||
}
|
||||
|
||||
// Checks to see if the given mouse button is held
|
||||
bool
|
||||
mouse_held(Mouse* self, MouseType type)
|
||||
{
|
||||
return (self->current[type] && self->previous[type]);
|
||||
}
|
||||
|
||||
// Checks to see if the given mouse button is released
|
||||
bool
|
||||
mouse_release(Mouse* self, MouseType type)
|
||||
{
|
||||
return (!self->current[type] && self->previous[type]);
|
||||
}
|
||||
|
||||
// Checks to see if the given key is pressed
|
||||
bool
|
||||
key_press(Keyboard* self, KeyType type)
|
||||
{
|
||||
return (self->current[type] && !self->previous[type]);
|
||||
}
|
||||
|
||||
// Checks to see if the given key is held
|
||||
bool
|
||||
key_held(Keyboard* self, KeyType type)
|
||||
{
|
||||
return (self->current[type] && self->previous[type]);
|
||||
}
|
||||
|
||||
// Checks to see if the given key is released
|
||||
bool
|
||||
key_release(Keyboard* self, KeyType type)
|
||||
{
|
||||
return (!self->current[type] && self->previous[type]);
|
||||
}
|
||||
|
||||
// Checks to see if the given input is pressed
|
||||
bool
|
||||
input_press(Input* self, InputType type)
|
||||
{
|
||||
for (KeyType key : INPUT_KEYS[type])
|
||||
if (!key_press(&self->keyboard, (key)))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Checks to see if the given input is held
|
||||
bool
|
||||
input_held(Input* self, InputType type)
|
||||
{
|
||||
for (KeyType key : INPUT_KEYS[type])
|
||||
if (!key_held(&self->keyboard, (key)))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Checks to see if the given input is held
|
||||
bool
|
||||
input_release(Input* self, InputType type)
|
||||
{
|
||||
for (KeyType key : INPUT_KEYS[type])
|
||||
if (!key_release(&self->keyboard, (key)))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Ticks input
|
||||
void
|
||||
input_tick(Input* self)
|
||||
{
|
||||
|
491
src/input.h
491
src/input.h
@@ -2,272 +2,278 @@
|
||||
|
||||
#include "COMMON.h"
|
||||
|
||||
#define MOUSE_COUNT (MOUSE_RIGHT + 1)
|
||||
enum MouseType
|
||||
{
|
||||
MOUSE_LEFT,
|
||||
MOUSE_RIGHT
|
||||
MOUSE_RIGHT,
|
||||
MOUSE_COUNT
|
||||
};
|
||||
|
||||
#define KEY_COUNT (255)
|
||||
enum KeyType
|
||||
{
|
||||
KEY_UNKNOWN = 0,
|
||||
KEY_UNKNOWN_TWO = 1,
|
||||
KEY_UNKNOWN_THREE = 2,
|
||||
KEY_UNKNOWN_FOUR = 3,
|
||||
KEY_A = 4,
|
||||
KEY_B = 5,
|
||||
KEY_C = 6,
|
||||
KEY_D = 7,
|
||||
KEY_E = 8,
|
||||
KEY_F = 9,
|
||||
KEY_G = 10,
|
||||
KEY_H = 11,
|
||||
KEY_I = 12,
|
||||
KEY_J = 13,
|
||||
KEY_K = 14,
|
||||
KEY_L = 15,
|
||||
KEY_M = 16,
|
||||
KEY_N = 17,
|
||||
KEY_O = 18,
|
||||
KEY_P = 19,
|
||||
KEY_Q = 20,
|
||||
KEY_R = 21,
|
||||
KEY_S = 22,
|
||||
KEY_T = 23,
|
||||
KEY_U = 24,
|
||||
KEY_V = 25,
|
||||
KEY_W = 26,
|
||||
KEY_X = 27,
|
||||
KEY_Y = 28,
|
||||
KEY_Z = 29,
|
||||
KEY_1 = 30,
|
||||
KEY_2 = 31,
|
||||
KEY_3 = 32,
|
||||
KEY_4 = 33,
|
||||
KEY_5 = 34,
|
||||
KEY_6 = 35,
|
||||
KEY_7 = 36,
|
||||
KEY_8 = 37,
|
||||
KEY_9 = 38,
|
||||
KEY_0 = 39,
|
||||
KEY_RETURN = 40,
|
||||
KEY_ESCAPE = 41,
|
||||
KEY_BACKSPACE = 42,
|
||||
KEY_TAB = 43,
|
||||
KEY_SPACE = 44,
|
||||
KEY_MINUS = 45,
|
||||
KEY_EQUALS = 46,
|
||||
KEY_LEFTBRACKET = 47,
|
||||
KEY_RIGHTBRACKET = 48,
|
||||
KEY_BACKSLASH = 49,
|
||||
KEY_NONUSHASH = 50,
|
||||
KEY_SEMICOLON = 51,
|
||||
KEY_APOSTROPHE = 52,
|
||||
KEY_GRAVE = 53,
|
||||
KEY_COMMA = 54,
|
||||
KEY_PERIOD = 55,
|
||||
KEY_SLASH = 56,
|
||||
KEY_CAPSLOCK = 57,
|
||||
KEY_F1 = 58,
|
||||
KEY_F2 = 59,
|
||||
KEY_F3 = 60,
|
||||
KEY_F4 = 61,
|
||||
KEY_F5 = 62,
|
||||
KEY_F6 = 63,
|
||||
KEY_F7 = 64,
|
||||
KEY_F8 = 65,
|
||||
KEY_F9 = 66,
|
||||
KEY_F10 = 67,
|
||||
KEY_F11 = 68,
|
||||
KEY_F12 = 69,
|
||||
KEY_PRINTSCREEN = 70,
|
||||
KEY_SCROLLLOCK = 71,
|
||||
KEY_PAUSE = 72,
|
||||
KEY_INSERT = 73,
|
||||
KEY_HOME = 74,
|
||||
KEY_PAGEUP = 75,
|
||||
KEY_DELETE = 76,
|
||||
KEY_END = 77,
|
||||
KEY_PAGEDOWN = 78,
|
||||
KEY_RIGHT = 79,
|
||||
KEY_LEFT = 80,
|
||||
KEY_DOWN = 81,
|
||||
KEY_UP = 82,
|
||||
KEY_NUMLOCKCLEAR = 83,
|
||||
KEY_KP_DIVIDE = 84,
|
||||
KEY_KP_MULTIPLY = 85,
|
||||
KEY_KP_MINUS = 86,
|
||||
KEY_KP_PLUS = 87,
|
||||
KEY_KP_ENTER = 88,
|
||||
KEY_KP_1 = 89,
|
||||
KEY_KP_2 = 90,
|
||||
KEY_KP_3 = 91,
|
||||
KEY_KP_4 = 92,
|
||||
KEY_KP_5 = 93,
|
||||
KEY_KP_6 = 94,
|
||||
KEY_KP_7 = 95,
|
||||
KEY_KP_8 = 96,
|
||||
KEY_KP_9 = 97,
|
||||
KEY_KP_0 = 98,
|
||||
KEY_KP_PERIOD = 99,
|
||||
KEY_NONUSBACKSLASH = 100,
|
||||
KEY_APPLICATION = 101,
|
||||
KEY_POWER = 102,
|
||||
KEY_KP_EQUALS = 103,
|
||||
KEY_F13 = 104,
|
||||
KEY_F14 = 105,
|
||||
KEY_F15 = 106,
|
||||
KEY_F16 = 107,
|
||||
KEY_F17 = 108,
|
||||
KEY_F18 = 109,
|
||||
KEY_F19 = 110,
|
||||
KEY_F20 = 111,
|
||||
KEY_F21 = 112,
|
||||
KEY_F22 = 113,
|
||||
KEY_F23 = 114,
|
||||
KEY_F24 = 115,
|
||||
KEY_EXECUTE = 116,
|
||||
KEY_HELP = 117,
|
||||
KEY_MENU = 118,
|
||||
KEY_SELECT = 119,
|
||||
KEY_STOP = 120,
|
||||
KEY_AGAIN = 121,
|
||||
KEY_UNDO = 122,
|
||||
KEY_CUT = 123,
|
||||
KEY_COPY = 124,
|
||||
KEY_PASTE = 125,
|
||||
KEY_FIND = 126,
|
||||
KEY_MUTE = 127,
|
||||
KEY_VOLUMEUP = 128,
|
||||
KEY_VOLUMEDOWN = 129,
|
||||
KEY_LOCKINGCAPSLOCK = 130,
|
||||
KEY_LOCKINGNUMLOCK = 131,
|
||||
KEY_LOCKINGSCROLLLOCK = 132,
|
||||
KEY_KP_COMMA = 133,
|
||||
KEY_KP_EQUALSAS400 = 134,
|
||||
KEY_INTERNATIONAL1 = 135,
|
||||
KEY_INTERNATIONAL2 = 136,
|
||||
KEY_INTERNATIONAL3 = 137,
|
||||
KEY_INTERNATIONAL4 = 138,
|
||||
KEY_INTERNATIONAL5 = 139,
|
||||
KEY_INTERNATIONAL6 = 140,
|
||||
KEY_INTERNATIONAL7 = 141,
|
||||
KEY_INTERNATIONAL8 = 142,
|
||||
KEY_INTERNATIONAL9 = 143,
|
||||
KEY_LANG1 = 144,
|
||||
KEY_LANG2 = 145,
|
||||
KEY_LANG3 = 146,
|
||||
KEY_LANG4 = 147,
|
||||
KEY_LANG5 = 148,
|
||||
KEY_LANG6 = 149,
|
||||
KEY_LANG7 = 150,
|
||||
KEY_LANG8 = 151,
|
||||
KEY_LANG9 = 152,
|
||||
KEY_ALTERASE = 153,
|
||||
KEY_SYSREQ = 154,
|
||||
KEY_CANCEL = 155,
|
||||
KEY_CLEAR = 156,
|
||||
KEY_PRIOR = 157,
|
||||
KEY_RETURN2 = 158,
|
||||
KEY_SEPARATOR = 159,
|
||||
KEY_OUT = 160,
|
||||
KEY_OPER = 161,
|
||||
KEY_CLEARAGAIN = 162,
|
||||
KEY_CRSEL = 163,
|
||||
KEY_EXSEL = 164,
|
||||
KEY_KP_00 = 176,
|
||||
KEY_KP_000 = 177,
|
||||
KEY_THOUSANDSSEPARATOR = 178,
|
||||
KEY_DECIMALSEPARATOR = 179,
|
||||
KEY_CURRENCYUNIT = 180,
|
||||
KEY_CURRENCYSUBUNIT = 181,
|
||||
KEY_KP_LEFTPAREN = 182,
|
||||
KEY_KP_RIGHTPAREN = 183,
|
||||
KEY_KP_LEFTBRACE = 184,
|
||||
KEY_KP_RIGHTBRACE = 185,
|
||||
KEY_KP_TAB = 186,
|
||||
KEY_KP_BACKSPACE = 187,
|
||||
KEY_KP_A = 188,
|
||||
KEY_KP_B = 189,
|
||||
KEY_KP_C = 190,
|
||||
KEY_KP_D = 191,
|
||||
KEY_KP_E = 192,
|
||||
KEY_KP_F = 193,
|
||||
KEY_KP_XOR = 194,
|
||||
KEY_KP_POWER = 195,
|
||||
KEY_KP_PERCENT = 196,
|
||||
KEY_KP_LESS = 197,
|
||||
KEY_KP_GREATER = 198,
|
||||
KEY_KP_AMPERSAND = 199,
|
||||
KEY_KP_DBLAMPERSAND = 200,
|
||||
KEY_KP_VERTICALBAR = 201,
|
||||
KEY_KP_DBLVERTICALBAR = 202,
|
||||
KEY_KP_COLON = 203,
|
||||
KEY_KP_HASH = 204,
|
||||
KEY_KP_SPACE = 205,
|
||||
KEY_KP_AT = 206,
|
||||
KEY_KP_EXCLAM = 207,
|
||||
KEY_KP_MEMSTORE = 208,
|
||||
KEY_KP_MEMRECALL = 209,
|
||||
KEY_KP_MEMCLEAR = 210,
|
||||
KEY_KP_MEMADD = 211,
|
||||
KEY_KP_MEMSUBTRACT = 212,
|
||||
KEY_KP_MEMMULTIPLY = 213,
|
||||
KEY_KP_MEMDIVIDE = 214,
|
||||
KEY_KP_PLUSMINUS = 215,
|
||||
KEY_KP_CLEAR = 216,
|
||||
KEY_KP_CLEARENTRY = 217,
|
||||
KEY_KP_BINARY = 218,
|
||||
KEY_KP_OCTAL = 219,
|
||||
KEY_KP_DECIMAL = 220,
|
||||
KEY_KP_HEXADECIMAL = 221,
|
||||
KEY_LCTRL = 224,
|
||||
KEY_LSHIFT = 225,
|
||||
KEY_LALT = 226,
|
||||
KEY_LGUI = 227,
|
||||
KEY_RCTRL = 228,
|
||||
KEY_RSHIFT = 229,
|
||||
KEY_RALT = 230,
|
||||
KEY_RGUI = 231
|
||||
KEY_UNKNOWN = 0,
|
||||
KEY_UNKNOWN_TWO = 1,
|
||||
KEY_UNKNOWN_THREE = 2,
|
||||
KEY_UNKNOWN_FOUR = 3,
|
||||
KEY_A = 4,
|
||||
KEY_B = 5,
|
||||
KEY_C = 6,
|
||||
KEY_D = 7,
|
||||
KEY_E = 8,
|
||||
KEY_F = 9,
|
||||
KEY_G = 10,
|
||||
KEY_H = 11,
|
||||
KEY_I = 12,
|
||||
KEY_J = 13,
|
||||
KEY_K = 14,
|
||||
KEY_L = 15,
|
||||
KEY_M = 16,
|
||||
KEY_N = 17,
|
||||
KEY_O = 18,
|
||||
KEY_P = 19,
|
||||
KEY_Q = 20,
|
||||
KEY_R = 21,
|
||||
KEY_S = 22,
|
||||
KEY_T = 23,
|
||||
KEY_U = 24,
|
||||
KEY_V = 25,
|
||||
KEY_W = 26,
|
||||
KEY_X = 27,
|
||||
KEY_Y = 28,
|
||||
KEY_Z = 29,
|
||||
KEY_1 = 30,
|
||||
KEY_2 = 31,
|
||||
KEY_3 = 32,
|
||||
KEY_4 = 33,
|
||||
KEY_5 = 34,
|
||||
KEY_6 = 35,
|
||||
KEY_7 = 36,
|
||||
KEY_8 = 37,
|
||||
KEY_9 = 38,
|
||||
KEY_0 = 39,
|
||||
KEY_RETURN = 40,
|
||||
KEY_ESCAPE = 41,
|
||||
KEY_BACKSPACE = 42,
|
||||
KEY_TAB = 43,
|
||||
KEY_SPACE = 44,
|
||||
KEY_MINUS = 45,
|
||||
KEY_EQUALS = 46,
|
||||
KEY_LEFTBRACKET = 47,
|
||||
KEY_RIGHTBRACKET = 48,
|
||||
KEY_BACKSLASH = 49,
|
||||
KEY_NONUSHASH = 50,
|
||||
KEY_SEMICOLON = 51,
|
||||
KEY_APOSTROPHE = 52,
|
||||
KEY_GRAVE = 53,
|
||||
KEY_COMMA = 54,
|
||||
KEY_PERIOD = 55,
|
||||
KEY_SLASH = 56,
|
||||
KEY_CAPSLOCK = 57,
|
||||
KEY_F1 = 58,
|
||||
KEY_F2 = 59,
|
||||
KEY_F3 = 60,
|
||||
KEY_F4 = 61,
|
||||
KEY_F5 = 62,
|
||||
KEY_F6 = 63,
|
||||
KEY_F7 = 64,
|
||||
KEY_F8 = 65,
|
||||
KEY_F9 = 66,
|
||||
KEY_F10 = 67,
|
||||
KEY_F11 = 68,
|
||||
KEY_F12 = 69,
|
||||
KEY_PRINTSCREEN = 70,
|
||||
KEY_SCROLLLOCK = 71,
|
||||
KEY_PAUSE = 72,
|
||||
KEY_INSERT = 73,
|
||||
KEY_HOME = 74,
|
||||
KEY_PAGEUP = 75,
|
||||
KEY_DELETE = 76,
|
||||
KEY_END = 77,
|
||||
KEY_PAGEDOWN = 78,
|
||||
KEY_RIGHT = 79,
|
||||
KEY_LEFT = 80,
|
||||
KEY_DOWN = 81,
|
||||
KEY_UP = 82,
|
||||
KEY_NUMLOCKCLEAR = 83,
|
||||
KEY_KP_DIVIDE = 84,
|
||||
KEY_KP_MULTIPLY = 85,
|
||||
KEY_KP_MINUS = 86,
|
||||
KEY_KP_PLUS = 87,
|
||||
KEY_KP_ENTER = 88,
|
||||
KEY_KP_1 = 89,
|
||||
KEY_KP_2 = 90,
|
||||
KEY_KP_3 = 91,
|
||||
KEY_KP_4 = 92,
|
||||
KEY_KP_5 = 93,
|
||||
KEY_KP_6 = 94,
|
||||
KEY_KP_7 = 95,
|
||||
KEY_KP_8 = 96,
|
||||
KEY_KP_9 = 97,
|
||||
KEY_KP_0 = 98,
|
||||
KEY_KP_PERIOD = 99,
|
||||
KEY_NONUSBACKSLASH = 100,
|
||||
KEY_APPLICATION = 101,
|
||||
KEY_POWER = 102,
|
||||
KEY_KP_EQUALS = 103,
|
||||
KEY_F13 = 104,
|
||||
KEY_F14 = 105,
|
||||
KEY_F15 = 106,
|
||||
KEY_F16 = 107,
|
||||
KEY_F17 = 108,
|
||||
KEY_F18 = 109,
|
||||
KEY_F19 = 110,
|
||||
KEY_F20 = 111,
|
||||
KEY_F21 = 112,
|
||||
KEY_F22 = 113,
|
||||
KEY_F23 = 114,
|
||||
KEY_F24 = 115,
|
||||
KEY_EXECUTE = 116,
|
||||
KEY_HELP = 117,
|
||||
KEY_MENU = 118,
|
||||
KEY_SELECT = 119,
|
||||
KEY_STOP = 120,
|
||||
KEY_AGAIN = 121,
|
||||
KEY_UNDO = 122,
|
||||
KEY_CUT = 123,
|
||||
KEY_COPY = 124,
|
||||
KEY_PASTE = 125,
|
||||
KEY_FIND = 126,
|
||||
KEY_MUTE = 127,
|
||||
KEY_VOLUMEUP = 128,
|
||||
KEY_VOLUMEDOWN = 129,
|
||||
KEY_LOCKINGCAPSLOCK = 130,
|
||||
KEY_LOCKINGNUMLOCK = 131,
|
||||
KEY_LOCKINGSCROLLLOCK = 132,
|
||||
KEY_KP_COMMA = 133,
|
||||
KEY_KP_EQUALSAS400 = 134,
|
||||
KEY_INTERNATIONAL1 = 135,
|
||||
KEY_INTERNATIONAL2 = 136,
|
||||
KEY_INTERNATIONAL3 = 137,
|
||||
KEY_INTERNATIONAL4 = 138,
|
||||
KEY_INTERNATIONAL5 = 139,
|
||||
KEY_INTERNATIONAL6 = 140,
|
||||
KEY_INTERNATIONAL7 = 141,
|
||||
KEY_INTERNATIONAL8 = 142,
|
||||
KEY_INTERNATIONAL9 = 143,
|
||||
KEY_LANG1 = 144,
|
||||
KEY_LANG2 = 145,
|
||||
KEY_LANG3 = 146,
|
||||
KEY_LANG4 = 147,
|
||||
KEY_LANG5 = 148,
|
||||
KEY_LANG6 = 149,
|
||||
KEY_LANG7 = 150,
|
||||
KEY_LANG8 = 151,
|
||||
KEY_LANG9 = 152,
|
||||
KEY_ALTERASE = 153,
|
||||
KEY_SYSREQ = 154,
|
||||
KEY_CANCEL = 155,
|
||||
KEY_CLEAR = 156,
|
||||
KEY_PRIOR = 157,
|
||||
KEY_RETURN2 = 158,
|
||||
KEY_SEPARATOR = 159,
|
||||
KEY_OUT = 160,
|
||||
KEY_OPER = 161,
|
||||
KEY_CLEARAGAIN = 162,
|
||||
KEY_CRSEL = 163,
|
||||
KEY_EXSEL = 164,
|
||||
KEY_KP_00 = 176,
|
||||
KEY_KP_000 = 177,
|
||||
KEY_THOUSANDSSEPARATOR = 178,
|
||||
KEY_DECIMALSEPARATOR = 179,
|
||||
KEY_CURRENCYUNIT = 180,
|
||||
KEY_CURRENCYSUBUNIT = 181,
|
||||
KEY_KP_LEFTPAREN = 182,
|
||||
KEY_KP_RIGHTPAREN = 183,
|
||||
KEY_KP_LEFTBRACE = 184,
|
||||
KEY_KP_RIGHTBRACE = 185,
|
||||
KEY_KP_TAB = 186,
|
||||
KEY_KP_BACKSPACE = 187,
|
||||
KEY_KP_A = 188,
|
||||
KEY_KP_B = 189,
|
||||
KEY_KP_C = 190,
|
||||
KEY_KP_D = 191,
|
||||
KEY_KP_E = 192,
|
||||
KEY_KP_F = 193,
|
||||
KEY_KP_XOR = 194,
|
||||
KEY_KP_POWER = 195,
|
||||
KEY_KP_PERCENT = 196,
|
||||
KEY_KP_LESS = 197,
|
||||
KEY_KP_GREATER = 198,
|
||||
KEY_KP_AMPERSAND = 199,
|
||||
KEY_KP_DBLAMPERSAND = 200,
|
||||
KEY_KP_VERTICALBAR = 201,
|
||||
KEY_KP_DBLVERTICALBAR = 202,
|
||||
KEY_KP_COLON = 203,
|
||||
KEY_KP_HASH = 204,
|
||||
KEY_KP_SPACE = 205,
|
||||
KEY_KP_AT = 206,
|
||||
KEY_KP_EXCLAM = 207,
|
||||
KEY_KP_MEMSTORE = 208,
|
||||
KEY_KP_MEMRECALL = 209,
|
||||
KEY_KP_MEMCLEAR = 210,
|
||||
KEY_KP_MEMADD = 211,
|
||||
KEY_KP_MEMSUBTRACT = 212,
|
||||
KEY_KP_MEMMULTIPLY = 213,
|
||||
KEY_KP_MEMDIVIDE = 214,
|
||||
KEY_KP_PLUSMINUS = 215,
|
||||
KEY_KP_CLEAR = 216,
|
||||
KEY_KP_CLEARENTRY = 217,
|
||||
KEY_KP_BINARY = 218,
|
||||
KEY_KP_OCTAL = 219,
|
||||
KEY_KP_DECIMAL = 220,
|
||||
KEY_KP_HEXADECIMAL = 221,
|
||||
KEY_LCTRL = 224,
|
||||
KEY_LSHIFT = 225,
|
||||
KEY_LALT = 226,
|
||||
KEY_LGUI = 227,
|
||||
KEY_RCTRL = 228,
|
||||
KEY_RSHIFT = 229,
|
||||
KEY_RALT = 230,
|
||||
KEY_RGUI = 231,
|
||||
KEY_COUNT = 255
|
||||
};
|
||||
|
||||
#define INPUT_COUNT (INPUT_REDO + 1)
|
||||
enum InputType
|
||||
{
|
||||
INPUT_MOD,
|
||||
INPUT_DELETE,
|
||||
INPUT_PLAY,
|
||||
INPUT_PAN,
|
||||
INPUT_MOVE,
|
||||
INPUT_ROTATE,
|
||||
INPUT_SCALE,
|
||||
INPUT_CROP,
|
||||
INPUT_LEFT,
|
||||
INPUT_RIGHT,
|
||||
INPUT_UP,
|
||||
INPUT_DOWN,
|
||||
INPUT_ROTATE_LEFT,
|
||||
INPUT_ROTATE_RIGHT,
|
||||
INPUT_ZOOM_IN,
|
||||
INPUT_ZOOM_OUT,
|
||||
INPUT_UNDO,
|
||||
INPUT_REDO
|
||||
INPUT_REDO,
|
||||
INPUT_SAVE,
|
||||
INPUT_COUNT
|
||||
};
|
||||
|
||||
static const KeyType INPUT_KEYS[INPUT_COUNT]
|
||||
const std::vector<KeyType> INPUT_KEYS[INPUT_COUNT] =
|
||||
{
|
||||
KEY_SPACE,
|
||||
KEY_T,
|
||||
KEY_S,
|
||||
KEY_C,
|
||||
KEY_LEFT,
|
||||
KEY_RIGHT,
|
||||
KEY_UP,
|
||||
KEY_DOWN,
|
||||
KEY_Q,
|
||||
KEY_W,
|
||||
KEY_1,
|
||||
KEY_2,
|
||||
KEY_Z,
|
||||
KEY_Y
|
||||
{ KEY_LSHIFT },
|
||||
{ KEY_DELETE },
|
||||
{ KEY_SPACE },
|
||||
{ KEY_P },
|
||||
{ KEY_M },
|
||||
{ KEY_R },
|
||||
{ KEY_S },
|
||||
{ KEY_C },
|
||||
{ KEY_LEFT },
|
||||
{ KEY_RIGHT },
|
||||
{ KEY_UP },
|
||||
{ KEY_DOWN },
|
||||
{ KEY_1 },
|
||||
{ KEY_2 },
|
||||
{ KEY_Z },
|
||||
{ KEY_Y },
|
||||
{ KEY_LCTRL }
|
||||
};
|
||||
|
||||
struct Keyboard
|
||||
@@ -298,4 +304,7 @@ bool mouse_release(Mouse* self, MouseType type);
|
||||
bool key_press(Keyboard* self, KeyType type);
|
||||
bool key_held(Keyboard* self, KeyType type);
|
||||
bool key_release(Keyboard* self, KeyType type);
|
||||
bool input_press(Input* self, InputType type);
|
||||
bool input_held(Input* self, InputType type);
|
||||
bool input_release(Input* self, InputType type);
|
||||
void input_tick(Input* self);
|
@@ -5,10 +5,10 @@ main(s32 argc, char* argv[])
|
||||
{
|
||||
State state;
|
||||
|
||||
/* If anm2 given on command line, set state argument to that (will be loaded) */
|
||||
// If anm2 given on command line, set state argument to that (will be loaded)
|
||||
if (argc > 0 && argv[1])
|
||||
{
|
||||
strncpy(state.argument, argv[1], PATH_MAX - 1);
|
||||
state.argument = argv[1];
|
||||
state.isArgument = true;
|
||||
}
|
||||
|
||||
|
@@ -3,6 +3,7 @@
|
||||
static void _preview_axis_set(Preview* self);
|
||||
static s32 _preview_grid_set(Preview* self);
|
||||
|
||||
// Sets the preview's axis (lines across x/y)
|
||||
static void
|
||||
_preview_axis_set(Preview* self)
|
||||
{
|
||||
@@ -16,7 +17,7 @@ _preview_axis_set(Preview* self)
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
/* Sets and returns the grid's vertices */
|
||||
// Sets and returns the grid's vertices
|
||||
static s32
|
||||
_preview_grid_set(Preview* self)
|
||||
{
|
||||
@@ -59,6 +60,7 @@ _preview_grid_set(Preview* self)
|
||||
return (s32)vertices.size();
|
||||
}
|
||||
|
||||
// Initializes preview
|
||||
void
|
||||
preview_init(Preview* self, Anm2* anm2, Anm2Reference* reference, f32* time, Resources* resources, Settings* settings)
|
||||
{
|
||||
@@ -68,7 +70,7 @@ preview_init(Preview* self, Anm2* anm2, Anm2Reference* reference, f32* time, Res
|
||||
self->resources = resources;
|
||||
self->settings = settings;
|
||||
|
||||
/* Framebuffer + texture */
|
||||
// Framebuffer + texture
|
||||
glGenFramebuffers(1, &self->fbo);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, self->fbo);
|
||||
@@ -88,15 +90,15 @@ preview_init(Preview* self, Anm2* anm2, Anm2Reference* reference, f32* time, Res
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
||||
/* Axis */
|
||||
// Axis
|
||||
glGenVertexArrays(1, &self->axisVAO);
|
||||
glGenBuffers(1, &self->axisVBO);
|
||||
|
||||
/* Grid */
|
||||
// Grid
|
||||
glGenVertexArrays(1, &self->gridVAO);
|
||||
glGenBuffers(1, &self->gridVBO);
|
||||
|
||||
/* Rect */
|
||||
// Rect
|
||||
glGenVertexArrays(1, &self->rectVAO);
|
||||
glGenBuffers(1, &self->rectVBO);
|
||||
|
||||
@@ -108,7 +110,7 @@ preview_init(Preview* self, Anm2* anm2, Anm2Reference* reference, f32* time, Res
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(f32), (void*)0);
|
||||
|
||||
/* Texture */
|
||||
// Texture
|
||||
glGenVertexArrays(1, &self->textureVAO);
|
||||
glGenBuffers(1, &self->textureVBO);
|
||||
glGenBuffers(1, &self->textureEBO);
|
||||
@@ -121,11 +123,11 @@ preview_init(Preview* self, Anm2* anm2, Anm2Reference* reference, f32* time, Res
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self->textureEBO);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GL_TEXTURE_INDICES), GL_TEXTURE_INDICES, GL_STATIC_DRAW);
|
||||
|
||||
/* Position */
|
||||
// Position attribute
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(f32), (void*)0);
|
||||
|
||||
/* UV */
|
||||
// UV attribute
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(f32), (void*)(2 * sizeof(f32)));
|
||||
|
||||
@@ -135,6 +137,7 @@ preview_init(Preview* self, Anm2* anm2, Anm2Reference* reference, f32* time, Res
|
||||
_preview_grid_set(self);
|
||||
}
|
||||
|
||||
// Ticks preview
|
||||
void
|
||||
preview_tick(Preview* self)
|
||||
{
|
||||
@@ -142,12 +145,14 @@ preview_tick(Preview* self)
|
||||
|
||||
Anm2Animation* animation = anm2_animation_from_reference(self->anm2, self->reference);
|
||||
|
||||
// If animation is valid, manage playback
|
||||
if (animation)
|
||||
{
|
||||
if (self->isPlaying)
|
||||
{
|
||||
*self->time += (f32)self->anm2->fps / TICK_RATE;
|
||||
|
||||
// If looping, return back to 0; if not, stop at length
|
||||
if (*self->time >= (f32)animation->frameNum - 1)
|
||||
{
|
||||
if (self->settings->playbackIsLoop && !self->isRecording)
|
||||
@@ -157,11 +162,13 @@ preview_tick(Preview* self)
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure to clamp time within appropriate range
|
||||
if (!self->isPlaying)
|
||||
*self->time = CLAMP(*self->time, 0.0f, (f32)animation->frameNum - 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Draws preview
|
||||
void
|
||||
preview_draw(Preview* self)
|
||||
{
|
||||
@@ -171,7 +178,7 @@ preview_draw(Preview* self)
|
||||
static f32 recordFrameTimeNext = 0.0f;
|
||||
static s32 recordFrameIndex = 0;
|
||||
|
||||
f32 zoomFactor = self->settings->previewZoom / 100.0f;
|
||||
f32 zoomFactor = PERCENT_TO_UNIT(self->settings->previewZoom);
|
||||
glm::vec2 ndcPan = glm::vec2(-self->settings->previewPanX / (PREVIEW_SIZE.x / 2.0f), -self->settings->previewPanY / (PREVIEW_SIZE.y / 2.0f));
|
||||
glm::mat4 previewTransform = glm::translate(glm::mat4(1.0f), glm::vec3(ndcPan, 0.0f));
|
||||
previewTransform = glm::scale(previewTransform, glm::vec3(zoomFactor, zoomFactor, 1.0f));
|
||||
@@ -188,7 +195,7 @@ preview_draw(Preview* self)
|
||||
);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
/* Grid */
|
||||
// Grid
|
||||
if (self->settings->previewIsGrid)
|
||||
{
|
||||
static ivec2 previousGridSize = {-1, -1};
|
||||
@@ -220,7 +227,7 @@ preview_draw(Preview* self)
|
||||
glUseProgram(0);
|
||||
}
|
||||
|
||||
/* Axes */
|
||||
// Axes
|
||||
if (self->settings->previewIsAxis)
|
||||
{
|
||||
glUseProgram(shaderLine);
|
||||
@@ -249,21 +256,22 @@ preview_draw(Preview* self)
|
||||
}
|
||||
|
||||
Anm2Animation* animation = anm2_animation_from_reference(self->anm2, self->reference);
|
||||
|
||||
/* Animation */
|
||||
s32& animationID = self->reference->animationID;
|
||||
|
||||
// Animation
|
||||
if (animation)
|
||||
{
|
||||
Anm2Frame rootFrame;
|
||||
Anm2Frame frame;
|
||||
anm2_frame_from_time(self->anm2, &rootFrame, Anm2Reference{ANM2_ROOT, self->reference->animationID, 0, 0}, *self->time);
|
||||
anm2_frame_from_time(self->anm2, &rootFrame, Anm2Reference{animationID, ANM2_ROOT, 0, 0}, *self->time);
|
||||
|
||||
/* Layers */
|
||||
// Layers
|
||||
for (auto & [id, layerAnimation] : animation->layerAnimations)
|
||||
{
|
||||
if (!layerAnimation.isVisible || layerAnimation.frames.size() <= 0)
|
||||
continue;
|
||||
|
||||
anm2_frame_from_time(self->anm2, &frame, Anm2Reference{ANM2_LAYER, self->reference->animationID, id, 0}, *self->time);
|
||||
anm2_frame_from_time(self->anm2, &frame, Anm2Reference{animationID, ANM2_LAYER, id, 0}, *self->time);
|
||||
|
||||
if (!frame.isVisible)
|
||||
continue;
|
||||
@@ -275,8 +283,12 @@ preview_draw(Preview* self)
|
||||
|
||||
glm::mat4 layerTransform = previewTransform;
|
||||
|
||||
glm::vec2 position = self->settings->previewIsRootTransform ? (frame.position + rootFrame.position) : frame.position;
|
||||
glm::vec2 scale = frame.scale / 100.0f;
|
||||
glm::vec2 position = self->settings->previewIsRootTransform ?
|
||||
(frame.position + rootFrame.position) : frame.position;
|
||||
|
||||
glm::vec2 scale = self->settings->previewIsRootTransform ?
|
||||
PERCENT_TO_UNIT(frame.scale) * PERCENT_TO_UNIT(rootFrame.scale) : PERCENT_TO_UNIT(frame.scale);
|
||||
|
||||
glm::vec2 ndcPos = position / (PREVIEW_SIZE / 2.0f);
|
||||
glm::vec2 ndcPivotOffset = (frame.pivot * scale) / (PREVIEW_SIZE / 2.0f);
|
||||
glm::vec2 ndcScale = (frame.size * scale) / (PREVIEW_SIZE / 2.0f);
|
||||
@@ -316,6 +328,7 @@ preview_draw(Preview* self)
|
||||
glUseProgram(0);
|
||||
}
|
||||
|
||||
// Root target
|
||||
if (animation->rootAnimation.isVisible && rootFrame.isVisible)
|
||||
{
|
||||
glm::mat4 rootTransform = previewTransform;
|
||||
@@ -350,25 +363,29 @@ preview_draw(Preview* self)
|
||||
glUseProgram(0);
|
||||
}
|
||||
|
||||
/* Pivots */
|
||||
// Layer pivots
|
||||
if (self->settings->previewIsShowPivot)
|
||||
{
|
||||
/* Layers (Reversed) */
|
||||
// Layers (Reversed)
|
||||
for (auto & [id, layerAnimation] : animation->layerAnimations)
|
||||
{
|
||||
if (!layerAnimation.isVisible || layerAnimation.frames.size() <= 0)
|
||||
continue;
|
||||
|
||||
anm2_frame_from_time(self->anm2, &frame, Anm2Reference{ANM2_LAYER, self->reference->animationID, id, 0}, *self->time);
|
||||
anm2_frame_from_time(self->anm2, &frame, Anm2Reference{animationID, ANM2_LAYER, id, 0}, *self->time);
|
||||
|
||||
if (!frame.isVisible)
|
||||
continue;
|
||||
|
||||
glm::mat4 pivotTransform = previewTransform;
|
||||
|
||||
glm::vec2 position = self->settings->previewIsRootTransform ? (frame.position + rootFrame.position) : frame.position;
|
||||
glm::vec2 position = self->settings->previewIsRootTransform
|
||||
? (frame.position + rootFrame.position) : frame.position;
|
||||
|
||||
glm::vec2 ndcPos = position /(PREVIEW_SIZE / 2.0f);
|
||||
glm::vec2 scale = self->settings->previewIsRootTransform ?
|
||||
PERCENT_TO_UNIT(frame.scale) * PERCENT_TO_UNIT(rootFrame.scale) : PERCENT_TO_UNIT(frame.scale);
|
||||
|
||||
glm::vec2 ndcPos = (position - (PREVIEW_PIVOT_SIZE / 2.0f)) / (PREVIEW_SIZE / 2.0f);
|
||||
glm::vec2 ndcScale = PREVIEW_PIVOT_SIZE / (PREVIEW_SIZE / 2.0f);
|
||||
|
||||
pivotTransform = glm::translate(pivotTransform, glm::vec3(ndcPos, 0.0f));
|
||||
@@ -400,13 +417,13 @@ preview_draw(Preview* self)
|
||||
}
|
||||
}
|
||||
|
||||
/* Nulls */
|
||||
// Null target/rect
|
||||
for (auto & [id, nullAnimation] : animation->nullAnimations)
|
||||
{
|
||||
if (!nullAnimation.isVisible || nullAnimation.frames.size() <= 0)
|
||||
continue;
|
||||
|
||||
anm2_frame_from_time(self->anm2, &frame, Anm2Reference{ANM2_NULL, id, 0}, *self->time);
|
||||
anm2_frame_from_time(self->anm2, &frame, Anm2Reference{animationID, ANM2_NULL, id, 0}, *self->time);
|
||||
|
||||
if (!frame.isVisible)
|
||||
continue;
|
||||
@@ -449,6 +466,7 @@ preview_draw(Preview* self)
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glUseProgram(0);
|
||||
|
||||
// Null rect
|
||||
if (null->isShowRect)
|
||||
{
|
||||
glm::mat4 rectTransform = previewTransform;
|
||||
@@ -476,10 +494,12 @@ preview_draw(Preview* self)
|
||||
}
|
||||
}
|
||||
|
||||
// Manage recording
|
||||
if (self->isRecording && animation)
|
||||
{
|
||||
if (recordFrameIndex == 0)
|
||||
{
|
||||
// Create frames directory, if it exists
|
||||
if
|
||||
(
|
||||
std::filesystem::exists(STRING_PREVIEW_FRAMES_DIRECTORY) &&
|
||||
@@ -496,18 +516,16 @@ preview_draw(Preview* self)
|
||||
if (isRecordThisFrame)
|
||||
{
|
||||
size_t frameSize = (self->recordSize.x * self->recordSize.y * 4);
|
||||
u8* frame = (u8*)malloc(frameSize);
|
||||
memset(frame, '\0',frameSize);
|
||||
char path[PATH_MAX];
|
||||
u8* frame = (u8*)calloc(frameSize, 1);
|
||||
std:: string path;
|
||||
|
||||
vec2 position =
|
||||
{
|
||||
self->settings->previewPanX - (PREVIEW_SIZE.x / 2.0f) + (self->recordSize.x / 2.0f),
|
||||
self->settings->previewPanY - (PREVIEW_SIZE.y / 2.0f) + (self->recordSize.y / 2.0f)
|
||||
};
|
||||
|
||||
memset(path, '\0', PATH_MAX);
|
||||
|
||||
snprintf(path, PATH_MAX, STRING_PREVIEW_FRAMES_FORMAT, STRING_PREVIEW_FRAMES_DIRECTORY, recordFrameIndex);
|
||||
path = std::format(STRING_PREVIEW_FRAMES_FORMAT, STRING_PREVIEW_FRAMES_DIRECTORY, recordFrameIndex);
|
||||
|
||||
glReadBuffer(GL_FRONT);
|
||||
glReadPixels
|
||||
|
@@ -5,8 +5,9 @@
|
||||
#include "input.h"
|
||||
#include "settings.h"
|
||||
|
||||
static const vec2 PREVIEW_SIZE = {5000, 5000};
|
||||
static const vec2 PREVIEW_CENTER = {0, 0};
|
||||
const vec2 PREVIEW_SIZE = {5000, 5000};
|
||||
const vec2 PREVIEW_CENTER = {0, 0};
|
||||
|
||||
|
||||
#define PREVIEW_ZOOM_MIN 1
|
||||
#define PREVIEW_ZOOM_MAX 1000
|
||||
@@ -16,10 +17,13 @@ static const vec2 PREVIEW_CENTER = {0, 0};
|
||||
#define PREVIEW_GRID_OFFSET_MIN 0
|
||||
#define PREVIEW_GRID_OFFSET_MAX 100
|
||||
#define PREVIEW_MOVE_STEP 1
|
||||
#define PREVIEW_MOVE_STEP_MOD 10
|
||||
#define PREVIEW_ROTATE_STEP 1
|
||||
#define PREVIEW_ROTATE_STEP_MOD 10
|
||||
#define PREVIEW_SCALE_STEP 1
|
||||
#define PREVIEW_SCALE_STEP_MOD 10
|
||||
|
||||
static const f32 PREVIEW_AXIS_VERTICES[] =
|
||||
const f32 PREVIEW_AXIS_VERTICES[] =
|
||||
{
|
||||
-1.0f, 0.0f,
|
||||
1.0f, 0.0f,
|
||||
@@ -27,13 +31,13 @@ static const f32 PREVIEW_AXIS_VERTICES[] =
|
||||
0.0f, 1.0f
|
||||
};
|
||||
|
||||
static const vec2 PREVIEW_NULL_RECT_SIZE = {100, 100};
|
||||
static const vec2 PREVIEW_POINT_SIZE = {2, 2};
|
||||
static const vec2 PREVIEW_PIVOT_SIZE = {4, 4};
|
||||
static const vec4 PREVIEW_ROOT_TINT = COLOR_GREEN;
|
||||
static const vec4 PREVIEW_NULL_TINT = COLOR_BLUE;
|
||||
static const vec4 PREVIEW_PIVOT_TINT = COLOR_RED;
|
||||
static const vec2 PREVIEW_TARGET_SIZE = {16, 16};
|
||||
const vec2 PREVIEW_NULL_RECT_SIZE = {100, 100};
|
||||
const vec2 PREVIEW_POINT_SIZE = {2, 2};
|
||||
const vec2 PREVIEW_PIVOT_SIZE = {4, 4};
|
||||
const vec4 PREVIEW_ROOT_TINT = COLOR_GREEN;
|
||||
const vec4 PREVIEW_NULL_TINT = COLOR_BLUE;
|
||||
const vec4 PREVIEW_PIVOT_TINT = COLOR_RED;
|
||||
const vec2 PREVIEW_TARGET_SIZE = {16, 16};
|
||||
|
||||
struct Preview
|
||||
{
|
||||
|
@@ -1,6 +1,23 @@
|
||||
#include "resources.h"
|
||||
|
||||
/* Loads in resources */
|
||||
// Loads a texture, given a path and an id for it to be assigned to
|
||||
void
|
||||
resources_texture_init(Resources* resources, const std::string& path, s32 id)
|
||||
{
|
||||
Texture texture;
|
||||
|
||||
if (resources->textures.find(id) != resources->textures.end() && resources->textures[id].id != resources->textures[TEXTURE_ERROR].id)
|
||||
texture_free(&resources->textures[id]);
|
||||
|
||||
if (texture_from_path_init(&texture, path))
|
||||
resources->textures[id] = texture;
|
||||
else
|
||||
texture.isInvalid = true;
|
||||
|
||||
resources->textures[id] = texture;
|
||||
}
|
||||
|
||||
// Loads in resources
|
||||
void
|
||||
resources_init(Resources* self)
|
||||
{
|
||||
@@ -10,7 +27,7 @@ resources_init(Resources* self)
|
||||
shader_init(&self->shaders[i], SHADER_DATA[i].vertex, SHADER_DATA[i].fragment);
|
||||
}
|
||||
|
||||
/* Frees resources*/
|
||||
// Frees resources
|
||||
void
|
||||
resources_free(Resources* self)
|
||||
{
|
||||
@@ -22,7 +39,7 @@ resources_free(Resources* self)
|
||||
texture_free(&self->atlas);
|
||||
}
|
||||
|
||||
/* Frees loaded textures */
|
||||
// Frees loaded textures
|
||||
void
|
||||
resources_textures_free(Resources* self)
|
||||
{
|
||||
|
@@ -12,5 +12,6 @@ struct Resources
|
||||
};
|
||||
|
||||
void resources_init(Resources* self);
|
||||
void resources_texture_init(Resources* resources, const std::string& path, s32 id);
|
||||
void resources_free(Resources* self);
|
||||
void resources_textures_free(Resources* self);
|
||||
|
167
src/settings.cpp
167
src/settings.cpp
@@ -1,31 +1,36 @@
|
||||
#include "settings.h"
|
||||
|
||||
static void _settings_setting_load(Settings* self, char* line);
|
||||
static void _settings_setting_write(Settings* self, SDL_IOStream* io, SettingsItem type);
|
||||
static void _settings_setting_load(Settings* self, const std::string& line);
|
||||
static void _settings_setting_write(Settings* self, std::ostream& out, SettingsEntry entry);
|
||||
|
||||
/* Load a particular settings from a line */
|
||||
static void
|
||||
_settings_setting_load(Settings* self, char* line)
|
||||
static void
|
||||
_settings_setting_load(Settings* self, const std::string& line)
|
||||
{
|
||||
for (int i = 0; i < SETTINGS_COUNT; i++)
|
||||
for (s32 i = 0; i < SETTINGS_COUNT; i++)
|
||||
{
|
||||
if (strncmp(line, SETTINGS_ENTRIES[i].value, strlen(SETTINGS_ENTRIES[i].value)) == 0)
|
||||
const std::string& key = SETTINGS_ENTRIES[i].key;
|
||||
size_t keyLength = key.length();
|
||||
|
||||
// Compare keys
|
||||
if (line.compare(0, keyLength, key) == 0)
|
||||
{
|
||||
char* value = line + strlen(SETTINGS_ENTRIES[i].value);
|
||||
const char* value = line.c_str() + keyLength;
|
||||
void* target = (u8*)self + SETTINGS_ENTRIES[i].offset;
|
||||
|
||||
// Based on type, assign value to offset of settings
|
||||
switch (SETTINGS_ENTRIES[i].type)
|
||||
{
|
||||
case SETTINGS_TYPE_INT:
|
||||
*(s32*)target = std::atoi(value);
|
||||
break;
|
||||
case SETTINGS_TYPE_BOOL:
|
||||
*(s32*)target = atoi(value);
|
||||
*(s32*)target = string_to_bool(std::string(value));
|
||||
break;
|
||||
case SETTINGS_TYPE_FLOAT:
|
||||
*(f32*)target = atof(value);
|
||||
*(f32*)target = std::atof(value);
|
||||
break;
|
||||
case SETTINGS_TYPE_STRING:
|
||||
strncpy((char*)target, value, SETTINGS_BUFFER_ITEM - 1);
|
||||
((char*)target)[SETTINGS_BUFFER_ITEM - 1] = '\0';
|
||||
*(std::string*)target = std::string(value);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -35,126 +40,100 @@ _settings_setting_load(Settings* self, char* line)
|
||||
}
|
||||
}
|
||||
|
||||
/* Writes a particular setting to the current IO */
|
||||
static void
|
||||
_settings_setting_write(Settings* self, SDL_IOStream* io, SettingsItem type)
|
||||
// Writes a given setting to the stream
|
||||
static void
|
||||
_settings_setting_write(Settings* self, std::ostream& out, SettingsEntry entry)
|
||||
{
|
||||
char valueBuffer[SETTINGS_BUFFER_ITEM];
|
||||
SettingsEntry entry = SETTINGS_ENTRIES[type];
|
||||
|
||||
u8* selfPointer = (u8*)self;
|
||||
|
||||
memset(valueBuffer, '\0', sizeof(valueBuffer));
|
||||
std::string value;
|
||||
|
||||
switch (entry.type)
|
||||
{
|
||||
case SETTINGS_TYPE_INT:
|
||||
snprintf(valueBuffer, SETTINGS_BUFFER_ITEM, entry.format, *(s32*)(selfPointer + entry.offset));
|
||||
value = std::format("{}", *(s32*)(selfPointer + entry.offset));
|
||||
break;
|
||||
case SETTINGS_TYPE_BOOL:
|
||||
snprintf(valueBuffer, SETTINGS_BUFFER_ITEM, entry.format, *(bool*)(selfPointer + entry.offset));
|
||||
value = std::format("{}", *(bool*)(selfPointer + entry.offset));
|
||||
break;
|
||||
case SETTINGS_TYPE_FLOAT:
|
||||
snprintf(valueBuffer, SETTINGS_BUFFER_ITEM, entry.format, *(f32*)(selfPointer + entry.offset));
|
||||
case SETTINGS_TYPE_FLOAT:
|
||||
value = std::format("{:.3f}", *(f32*)(selfPointer + entry.offset));
|
||||
break;
|
||||
case SETTINGS_TYPE_STRING:
|
||||
snprintf(valueBuffer, SETTINGS_BUFFER_ITEM, entry.value, entry.format, *(char*)(selfPointer + entry.offset));
|
||||
value = *(std::string*)(selfPointer + entry.offset);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
SDL_WriteIO(io, valueBuffer, strlen(valueBuffer));
|
||||
SDL_WriteIO(io, "\n", strlen("\n"));
|
||||
out << entry.key << value << "\n";
|
||||
}
|
||||
|
||||
/* Saves the program's settings to the PATH_SETTINGS file */
|
||||
void
|
||||
// Saves the current settings
|
||||
// Note: this is just for this program's settings, additional imgui settings handled elsewhere
|
||||
void
|
||||
settings_save(Settings* self)
|
||||
{
|
||||
char buffer[SETTINGS_BUFFER];
|
||||
std::ifstream input(PATH_SETTINGS);
|
||||
std::string oldContents;
|
||||
|
||||
/* Get the original settings.ini buffer (as previously saved by imgui before this is called) */
|
||||
memset(buffer, '\0', SETTINGS_BUFFER);
|
||||
|
||||
SDL_IOStream* io = SDL_IOFromFile(PATH_SETTINGS, "r");
|
||||
|
||||
if (!io)
|
||||
{
|
||||
printf(STRING_ERROR_SETTINGS_INIT, PATH_SETTINGS);
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_ReadIO(io, buffer, SETTINGS_BUFFER);
|
||||
SDL_CloseIO(io);
|
||||
|
||||
io = SDL_IOFromFile(PATH_SETTINGS, "w");
|
||||
|
||||
if (!io)
|
||||
if (!input)
|
||||
{
|
||||
printf(STRING_ERROR_SETTINGS_INIT, PATH_SETTINGS);
|
||||
std::cout << STRING_ERROR_SETTINGS_INIT << PATH_SETTINGS << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
/* [Settings] */
|
||||
SDL_WriteIO(io, SETTINGS_SECTION, strlen(SETTINGS_SECTION));
|
||||
SDL_WriteIO(io, "\n", strlen("\n"));
|
||||
// We're writing after the imgui stuff
|
||||
oldContents.assign((std::istreambuf_iterator<char>(input)), std::istreambuf_iterator<char>());
|
||||
input.close();
|
||||
|
||||
/* Write down all elements */
|
||||
std::ofstream output(PATH_SETTINGS);
|
||||
if (!output)
|
||||
{
|
||||
std::cout << STRING_ERROR_SETTINGS_INIT << PATH_SETTINGS << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// [Settings]
|
||||
output << SETTINGS_SECTION << "\n";
|
||||
|
||||
// Write each setting
|
||||
for (s32 i = 0; i < SETTINGS_COUNT; i++)
|
||||
_settings_setting_write(self, io, (SettingsItem)i);
|
||||
_settings_setting_write(self, output, SETTINGS_ENTRIES[i]);
|
||||
|
||||
SDL_WriteIO(io, "\n", strlen("\n"));
|
||||
// Write the the imgui section
|
||||
output << "\n" << SETTINGS_SECTION_IMGUI << "\n";
|
||||
output << oldContents;
|
||||
|
||||
/* specify that the other settings are imgui */
|
||||
SDL_WriteIO(io, SETTINGS_SECTION_IMGUI, strlen(SETTINGS_SECTION_IMGUI));
|
||||
SDL_WriteIO(io, "\n", strlen("\n"));
|
||||
|
||||
/* Then write original contents */
|
||||
SDL_WriteIO(io, buffer, strlen(buffer));
|
||||
SDL_CloseIO(io);
|
||||
output.close();
|
||||
}
|
||||
|
||||
/* Loads the settings from the PATH_SETTINGS file */
|
||||
void
|
||||
// Load settings
|
||||
void
|
||||
settings_load(Settings* self)
|
||||
{
|
||||
char buffer[SETTINGS_BUFFER];
|
||||
char* line = NULL;
|
||||
|
||||
memset(buffer, '\0', SETTINGS_BUFFER);
|
||||
|
||||
SDL_IOStream* io = SDL_IOFromFile(PATH_SETTINGS, "r");
|
||||
|
||||
if (!io)
|
||||
{
|
||||
printf(STRING_ERROR_SETTINGS_INIT, PATH_SETTINGS);
|
||||
return;
|
||||
}
|
||||
|
||||
size_t bytesRead = SDL_ReadIO(io, buffer, SETTINGS_BUFFER);
|
||||
SDL_CloseIO(io);
|
||||
|
||||
buffer[bytesRead] = '\0';
|
||||
|
||||
line = strtok(buffer, "\n");
|
||||
|
||||
/* The settings will be the first section in the file */
|
||||
/* Go through its elements, load them to settings, and go on with your day */
|
||||
while (line != NULL)
|
||||
std::ifstream file(PATH_SETTINGS);
|
||||
if (!file)
|
||||
{
|
||||
if (strcmp(line, SETTINGS_SECTION) == 0)
|
||||
std::cerr << STRING_ERROR_SETTINGS_INIT << PATH_SETTINGS << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
std::string line;
|
||||
bool inSettingsSection = false;
|
||||
|
||||
// Iterare through settings lines until the imgui section is reached, then end
|
||||
while (std::getline(file, line))
|
||||
{
|
||||
if (line == SETTINGS_SECTION)
|
||||
{
|
||||
line = strtok(NULL, "\n");
|
||||
inSettingsSection = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
_settings_setting_load(self, line);
|
||||
|
||||
/* get out here */
|
||||
if (strcmp(line, SETTINGS_SECTION_IMGUI) == 0)
|
||||
break;
|
||||
if (line == SETTINGS_SECTION_IMGUI)
|
||||
break;
|
||||
|
||||
line = strtok(NULL, "\n");
|
||||
if (inSettingsSection)
|
||||
_settings_setting_load(self, line);
|
||||
}
|
||||
}
|
143
src/settings.h
143
src/settings.h
@@ -17,61 +17,12 @@ enum SettingsValueType
|
||||
|
||||
struct SettingsEntry
|
||||
{
|
||||
const char* value;
|
||||
const char* format;
|
||||
std::string key;
|
||||
SettingsValueType type;
|
||||
s32 offset;
|
||||
};
|
||||
|
||||
#define SETTINGS_COUNT (SETTINGS_EDITOR_BACKGROUND_COLOR_A + 1)
|
||||
enum SettingsItem
|
||||
{
|
||||
SETTINGS_WINDOW_W,
|
||||
SETTINGS_WINDOW_H,
|
||||
SETTINGS_PLAYBACK_IS_LOOP,
|
||||
SETTINGS_PREVIEW_IS_AXIS,
|
||||
SETTINGS_PREVIEW_IS_GRID,
|
||||
SETTINGS_PREVIEW_IS_ROOT_TRANSFORM,
|
||||
SETTINGS_PREVIEW_IS_SHOW_PIVOT,
|
||||
SETTINGS_PREVIEW_PAN_X,
|
||||
SETTINGS_PREVIEW_PAN_Y,
|
||||
SETTINGS_PREVIEW_ZOOM,
|
||||
SETTINGS_PREVIEW_GRID_SIZE_X,
|
||||
SETTINGS_PREVIEW_GRID_SIZE_Y,
|
||||
SETTINGS_PREVIEW_GRID_OFFSET_X,
|
||||
SETTINGS_PREVIEW_GRID_OFFSET_Y,
|
||||
SETTINGS_PREVIEW_GRID_COLOR_R,
|
||||
SETTINGS_PREVIEW_GRID_COLOR_G,
|
||||
SETTINGS_PREVIEW_GRID_COLOR_B,
|
||||
SETTINGS_PREVIEW_GRID_COLOR_A,
|
||||
SETTINGS_PREVIEW_AXIS_COLOR_R,
|
||||
SETTINGS_PREVIEW_AXIS_COLOR_G,
|
||||
SETTINGS_PREVIEW_AXIS_COLOR_B,
|
||||
SETTINGS_PREVIEW_AXIS_COLOR_A,
|
||||
SETTINGS_PREVIEW_BACKGROUND_COLOR_R,
|
||||
SETTINGS_PREVIEW_BACKGROUND_COLOR_G,
|
||||
SETTINGS_PREVIEW_BACKGROUND_COLOR_B,
|
||||
SETTINGS_PREVIEW_BACKGROUND_COLOR_A,
|
||||
SETTINGS_EDITOR_IS_GRID,
|
||||
SETTINGS_EDITOR_IS_GRID_SNAP,
|
||||
SETTINGS_EDITOR_IS_BORDER,
|
||||
SETTINGS_EDITOR_PAN_X,
|
||||
SETTINGS_EDITOR_PAN_Y,
|
||||
SETTINGS_EDITOR_ZOOM,
|
||||
SETTINGS_EDITOR_GRID_SIZE_X,
|
||||
SETTINGS_EDITOR_GRID_SIZE_Y,
|
||||
SETTINGS_EDITOR_GRID_OFFSET_X,
|
||||
SETTINGS_EDITOR_GRID_OFFSET_Y,
|
||||
SETTINGS_EDITOR_GRID_COLOR_R,
|
||||
SETTINGS_EDITOR_GRID_COLOR_G,
|
||||
SETTINGS_EDITOR_GRID_COLOR_B,
|
||||
SETTINGS_EDITOR_GRID_COLOR_A,
|
||||
SETTINGS_EDITOR_BACKGROUND_COLOR_R,
|
||||
SETTINGS_EDITOR_BACKGROUND_COLOR_G,
|
||||
SETTINGS_EDITOR_BACKGROUND_COLOR_B,
|
||||
SETTINGS_EDITOR_BACKGROUND_COLOR_A,
|
||||
};
|
||||
|
||||
#define SETTINGS_COUNT 44
|
||||
struct Settings
|
||||
{
|
||||
s32 windowW = 1920;
|
||||
@@ -120,52 +71,52 @@ struct Settings
|
||||
f32 editorBackgroundColorA = 1.0f;
|
||||
};
|
||||
|
||||
static const SettingsEntry SETTINGS_ENTRIES[SETTINGS_COUNT] =
|
||||
const SettingsEntry SETTINGS_ENTRIES[SETTINGS_COUNT] =
|
||||
{
|
||||
{"windowW=", "windowW=%i", SETTINGS_TYPE_INT, offsetof(Settings, windowW)},
|
||||
{"windowH=", "windowH=%i", SETTINGS_TYPE_INT, offsetof(Settings, windowH)},
|
||||
{"playbackIsLoop=", "playbackIsLoop=%i", SETTINGS_TYPE_BOOL, offsetof(Settings, playbackIsLoop)},
|
||||
{"previewIsAxis=", "previewIsAxis=%i", SETTINGS_TYPE_BOOL, offsetof(Settings, previewIsAxis)},
|
||||
{"previewIsGrid=", "previewIsGrid=%i", SETTINGS_TYPE_BOOL, offsetof(Settings, previewIsGrid)},
|
||||
{"previewIsRootTransform=", "previewIsRootTransform=%i", SETTINGS_TYPE_BOOL, offsetof(Settings, previewIsRootTransform)},
|
||||
{"previewIsShowPivot=", "previewIsShowPivot=%i", SETTINGS_TYPE_BOOL, offsetof(Settings, previewIsShowPivot)},
|
||||
{"previewPanX=", "previewPanX=%f", SETTINGS_TYPE_FLOAT, offsetof(Settings, previewPanX)},
|
||||
{"previewPanY=", "previewPanY=%f", SETTINGS_TYPE_FLOAT, offsetof(Settings, previewPanY)},
|
||||
{"previewZoom=", "previewZoom=%f", SETTINGS_TYPE_FLOAT, offsetof(Settings, previewZoom)},
|
||||
{"previewGridSizeX=", "previewGridSizeX=%i", SETTINGS_TYPE_INT, offsetof(Settings, previewGridSizeX)},
|
||||
{"previewGridSizeY=", "previewGridSizeY=%i", SETTINGS_TYPE_INT, offsetof(Settings, previewGridSizeY)},
|
||||
{"previewGridOffsetX=", "previewGridOffsetX=%i", SETTINGS_TYPE_INT, offsetof(Settings, previewGridOffsetX)},
|
||||
{"previewGridOffsetY=", "previewGridOffsetY=%i", SETTINGS_TYPE_INT, offsetof(Settings, previewGridOffsetY)},
|
||||
{"previewGridColorR=", "previewGridColorR=%f", SETTINGS_TYPE_FLOAT, offsetof(Settings, previewGridColorR)},
|
||||
{"previewGridColorG=", "previewGridColorG=%f", SETTINGS_TYPE_FLOAT, offsetof(Settings, previewGridColorG)},
|
||||
{"previewGridColorB=", "previewGridColorB=%f", SETTINGS_TYPE_FLOAT, offsetof(Settings, previewGridColorB)},
|
||||
{"previewGridColorA=", "previewGridColorA=%f", SETTINGS_TYPE_FLOAT, offsetof(Settings, previewGridColorA)},
|
||||
{"previewAxisColorR=", "previewAxisColorR=%f", SETTINGS_TYPE_FLOAT, offsetof(Settings, previewAxisColorR)},
|
||||
{"previewAxisColorG=", "previewAxisColorG=%f", SETTINGS_TYPE_FLOAT, offsetof(Settings, previewAxisColorG)},
|
||||
{"previewAxisColorB=", "previewAxisColorB=%f", SETTINGS_TYPE_FLOAT, offsetof(Settings, previewAxisColorB)},
|
||||
{"previewAxisColorA=", "previewAxisColorA=%f", SETTINGS_TYPE_FLOAT, offsetof(Settings, previewAxisColorA)},
|
||||
{"previewBackgroundColorR=", "previewBackgroundColorR=%f", SETTINGS_TYPE_FLOAT, offsetof(Settings, previewBackgroundColorR)},
|
||||
{"previewBackgroundColorG=", "previewBackgroundColorG=%f", SETTINGS_TYPE_FLOAT, offsetof(Settings, previewBackgroundColorG)},
|
||||
{"previewBackgroundColorB=", "previewBackgroundColorB=%f", SETTINGS_TYPE_FLOAT, offsetof(Settings, previewBackgroundColorB)},
|
||||
{"previewBackgroundColorA=", "previewBackgroundColorA=%f", SETTINGS_TYPE_FLOAT, offsetof(Settings, previewBackgroundColorA)},
|
||||
{"editorIsGrid=", "editorIsGrid=%i", SETTINGS_TYPE_BOOL, offsetof(Settings, editorIsGrid)},
|
||||
{"editorIsGridSnap=", "editorIsGridSnap=%i", SETTINGS_TYPE_BOOL, offsetof(Settings, editorIsGridSnap)},
|
||||
{"editorIsBorder=", "editorIsBorder=%i", SETTINGS_TYPE_BOOL, offsetof(Settings, editorIsBorder)},
|
||||
{"editorPanX=", "editorPanX=%f", SETTINGS_TYPE_FLOAT, offsetof(Settings, editorPanX)},
|
||||
{"editorPanY=", "editorPanY=%f", SETTINGS_TYPE_FLOAT, offsetof(Settings, editorPanY)},
|
||||
{"editorZoom=", "editorZoom=%f", SETTINGS_TYPE_FLOAT, offsetof(Settings, editorZoom)},
|
||||
{"editorGridSizeX=", "editorGridSizeX=%i", SETTINGS_TYPE_INT, offsetof(Settings, editorGridSizeX)},
|
||||
{"editorGridSizeY=", "editorGridSizeY=%i", SETTINGS_TYPE_INT, offsetof(Settings, editorGridSizeY)},
|
||||
{"editorGridOffsetX=", "editorGridOffsetX=%i", SETTINGS_TYPE_INT, offsetof(Settings, editorGridOffsetX)},
|
||||
{"editorGridOffsetY=", "editorGridOffsetY=%i", SETTINGS_TYPE_INT, offsetof(Settings, editorGridOffsetY)},
|
||||
{"editorGridColorR=", "editorGridColorR=%f", SETTINGS_TYPE_FLOAT, offsetof(Settings, editorGridColorR)},
|
||||
{"editorGridColorG=", "editorGridColorG=%f", SETTINGS_TYPE_FLOAT, offsetof(Settings, editorGridColorG)},
|
||||
{"editorGridColorB=", "editorGridColorB=%f", SETTINGS_TYPE_FLOAT, offsetof(Settings, editorGridColorB)},
|
||||
{"editorGridColorA=", "editorGridColorA=%f", SETTINGS_TYPE_FLOAT, offsetof(Settings, editorGridColorA)},
|
||||
{"editorBackgroundColorR=", "editorBackgroundColorR=%f", SETTINGS_TYPE_FLOAT, offsetof(Settings, editorBackgroundColorR)},
|
||||
{"editorBackgroundColorG=", "editorBackgroundColorG=%f", SETTINGS_TYPE_FLOAT, offsetof(Settings, editorBackgroundColorG)},
|
||||
{"editorBackgroundColorB=", "editorBackgroundColorB=%f", SETTINGS_TYPE_FLOAT, offsetof(Settings, editorBackgroundColorB)},
|
||||
{"editorBackgroundColorA=", "editorBackgroundColorA=%f", SETTINGS_TYPE_FLOAT, offsetof(Settings, editorBackgroundColorA)}
|
||||
{"windowW=", SETTINGS_TYPE_INT, offsetof(Settings, windowW)},
|
||||
{"windowH=", SETTINGS_TYPE_INT, offsetof(Settings, windowH)},
|
||||
{"playbackIsLoop=", SETTINGS_TYPE_BOOL, offsetof(Settings, playbackIsLoop)},
|
||||
{"previewIsAxis=", SETTINGS_TYPE_BOOL, offsetof(Settings, previewIsAxis)},
|
||||
{"previewIsGrid=", SETTINGS_TYPE_BOOL, offsetof(Settings, previewIsGrid)},
|
||||
{"previewIsRootTransform=", SETTINGS_TYPE_BOOL, offsetof(Settings, previewIsRootTransform)},
|
||||
{"previewIsShowPivot=", SETTINGS_TYPE_BOOL, offsetof(Settings, previewIsShowPivot)},
|
||||
{"previewPanX=", SETTINGS_TYPE_FLOAT, offsetof(Settings, previewPanX)},
|
||||
{"previewPanY=", SETTINGS_TYPE_FLOAT, offsetof(Settings, previewPanY)},
|
||||
{"previewZoom=", SETTINGS_TYPE_FLOAT, offsetof(Settings, previewZoom)},
|
||||
{"previewGridSizeX=", SETTINGS_TYPE_INT, offsetof(Settings, previewGridSizeX)},
|
||||
{"previewGridSizeY=", SETTINGS_TYPE_INT, offsetof(Settings, previewGridSizeY)},
|
||||
{"previewGridOffsetX=", SETTINGS_TYPE_INT, offsetof(Settings, previewGridOffsetX)},
|
||||
{"previewGridOffsetY=", SETTINGS_TYPE_INT, offsetof(Settings, previewGridOffsetY)},
|
||||
{"previewGridColorR=", SETTINGS_TYPE_FLOAT, offsetof(Settings, previewGridColorR)},
|
||||
{"previewGridColorG=", SETTINGS_TYPE_FLOAT, offsetof(Settings, previewGridColorG)},
|
||||
{"previewGridColorB=", SETTINGS_TYPE_FLOAT, offsetof(Settings, previewGridColorB)},
|
||||
{"previewGridColorA=", SETTINGS_TYPE_FLOAT, offsetof(Settings, previewGridColorA)},
|
||||
{"previewAxisColorR=", SETTINGS_TYPE_FLOAT, offsetof(Settings, previewAxisColorR)},
|
||||
{"previewAxisColorG=", SETTINGS_TYPE_FLOAT, offsetof(Settings, previewAxisColorG)},
|
||||
{"previewAxisColorB=", SETTINGS_TYPE_FLOAT, offsetof(Settings, previewAxisColorB)},
|
||||
{"previewAxisColorA=", SETTINGS_TYPE_FLOAT, offsetof(Settings, previewAxisColorA)},
|
||||
{"previewBackgroundColorR=", SETTINGS_TYPE_FLOAT, offsetof(Settings, previewBackgroundColorR)},
|
||||
{"previewBackgroundColorG=", SETTINGS_TYPE_FLOAT, offsetof(Settings, previewBackgroundColorG)},
|
||||
{"previewBackgroundColorB=", SETTINGS_TYPE_FLOAT, offsetof(Settings, previewBackgroundColorB)},
|
||||
{"previewBackgroundColorA=", SETTINGS_TYPE_FLOAT, offsetof(Settings, previewBackgroundColorA)},
|
||||
{"editorIsGrid=", SETTINGS_TYPE_BOOL, offsetof(Settings, editorIsGrid)},
|
||||
{"editorIsGridSnap=", SETTINGS_TYPE_BOOL, offsetof(Settings, editorIsGridSnap)},
|
||||
{"editorIsBorder=", SETTINGS_TYPE_BOOL, offsetof(Settings, editorIsBorder)},
|
||||
{"editorPanX=", SETTINGS_TYPE_FLOAT, offsetof(Settings, editorPanX)},
|
||||
{"editorPanY=", SETTINGS_TYPE_FLOAT, offsetof(Settings, editorPanY)},
|
||||
{"editorZoom=", SETTINGS_TYPE_FLOAT, offsetof(Settings, editorZoom)},
|
||||
{"editorGridSizeX=", SETTINGS_TYPE_INT, offsetof(Settings, editorGridSizeX)},
|
||||
{"editorGridSizeY=", SETTINGS_TYPE_INT, offsetof(Settings, editorGridSizeY)},
|
||||
{"editorGridOffsetX=", SETTINGS_TYPE_INT, offsetof(Settings, editorGridOffsetX)},
|
||||
{"editorGridOffsetY=", SETTINGS_TYPE_INT, offsetof(Settings, editorGridOffsetY)},
|
||||
{"editorGridColorR=", SETTINGS_TYPE_FLOAT, offsetof(Settings, editorGridColorR)},
|
||||
{"editorGridColorG=", SETTINGS_TYPE_FLOAT, offsetof(Settings, editorGridColorG)},
|
||||
{"editorGridColorB=", SETTINGS_TYPE_FLOAT, offsetof(Settings, editorGridColorB)},
|
||||
{"editorGridColorA=", SETTINGS_TYPE_FLOAT, offsetof(Settings, editorGridColorA)},
|
||||
{"editorBackgroundColorR=", SETTINGS_TYPE_FLOAT, offsetof(Settings, editorBackgroundColorR)},
|
||||
{"editorBackgroundColorG=", SETTINGS_TYPE_FLOAT, offsetof(Settings, editorBackgroundColorG)},
|
||||
{"editorBackgroundColorB=", SETTINGS_TYPE_FLOAT, offsetof(Settings, editorBackgroundColorB)},
|
||||
{"editorBackgroundColorA=", SETTINGS_TYPE_FLOAT, offsetof(Settings, editorBackgroundColorA)}
|
||||
};
|
||||
|
||||
void settings_save(Settings* self);
|
||||
|
@@ -1,14 +1,15 @@
|
||||
#include "shader.h"
|
||||
|
||||
static bool _shader_compile(GLuint* self, const char* text);
|
||||
static bool _shader_compile(GLuint* self, const std::string& text);
|
||||
|
||||
// Compiles the shader; returns true/false based on success
|
||||
static bool
|
||||
_shader_compile(GLuint* self, const char* text)
|
||||
_shader_compile(GLuint* self, const std::string& text)
|
||||
{
|
||||
char compileLog[SHADER_BUFFER_MAX];
|
||||
std::string compileLog;
|
||||
s32 isCompile;
|
||||
|
||||
const GLchar* source = text;
|
||||
const GLchar* source = text.c_str();
|
||||
|
||||
glShaderSource(*self, 1, &source, NULL);
|
||||
|
||||
@@ -17,16 +18,17 @@ _shader_compile(GLuint* self, const char* text)
|
||||
|
||||
if (!isCompile)
|
||||
{
|
||||
glGetShaderInfoLog(*self, SHADER_BUFFER_MAX, NULL, compileLog);
|
||||
printf(STRING_ERROR_SHADER_INIT, *self, compileLog);
|
||||
glGetShaderInfoLog(*self, SHADER_INFO_LOG_MAX, NULL, &compileLog[0]);
|
||||
std::cout << STRING_ERROR_SHADER_INIT << *self << std::endl << compileLog << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Initializes a given shader with vertex/fragment
|
||||
bool
|
||||
shader_init(GLuint* self, const char* vertex, const char* fragment)
|
||||
shader_init(GLuint* self, const std::string& vertex, const std::string& fragment)
|
||||
{
|
||||
GLuint vertexHandle;
|
||||
GLuint fragmentHandle;
|
||||
@@ -51,11 +53,10 @@ shader_init(GLuint* self, const char* vertex, const char* fragment)
|
||||
glDeleteShader(vertexHandle);
|
||||
glDeleteShader(fragmentHandle);
|
||||
|
||||
printf(STRING_INFO_SHADER_INIT, *self);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Frees a given shader
|
||||
void
|
||||
shader_free(GLuint* self)
|
||||
{
|
||||
|
@@ -2,7 +2,7 @@
|
||||
|
||||
#include "COMMON.h"
|
||||
|
||||
#define SHADER_BUFFER_MAX 2048
|
||||
#define SHADER_INFO_LOG_MAX 0xFF
|
||||
|
||||
bool shader_init(GLuint* self, const char* vertex, const char* fragment);
|
||||
bool shader_init(GLuint* self, const std::string& vertex, const std::string& fragment);
|
||||
void shader_free(GLuint* self);
|
@@ -1,11 +1,15 @@
|
||||
#include "snapshots.h"
|
||||
|
||||
// Pushes the undo stack
|
||||
void
|
||||
snapshots_undo_stack_push(Snapshots* self, Snapshot* snapshot)
|
||||
{
|
||||
// If stack over the limit, shift it
|
||||
if (self->undoStack.top >= SNAPSHOT_STACK_MAX)
|
||||
{
|
||||
memmove(&self->undoStack.snapshots[0], &self->undoStack.snapshots[1], sizeof(Snapshot) * (SNAPSHOT_STACK_MAX - 1));
|
||||
for (s32 i = 0; i < SNAPSHOT_STACK_MAX - 1; i++)
|
||||
self->undoStack.snapshots[i] = self->undoStack.snapshots[i + 1];
|
||||
|
||||
self->undoStack.top = SNAPSHOT_STACK_MAX - 1;
|
||||
}
|
||||
|
||||
@@ -13,6 +17,7 @@ snapshots_undo_stack_push(Snapshots* self, Snapshot* snapshot)
|
||||
self->redoStack.top = 0;
|
||||
}
|
||||
|
||||
// Pops the undo stack
|
||||
bool
|
||||
snapshots_undo_stack_pop(Snapshots* self, Snapshot* snapshot)
|
||||
{
|
||||
@@ -24,18 +29,21 @@ snapshots_undo_stack_pop(Snapshots* self, Snapshot* snapshot)
|
||||
return true;
|
||||
}
|
||||
|
||||
// Pushes the redo stack
|
||||
void
|
||||
snapshots_redo_stack_push(Snapshots* self, Snapshot* snapshot)
|
||||
{
|
||||
if (self->redoStack.top >= SNAPSHOT_STACK_MAX)
|
||||
{
|
||||
memmove(&self->redoStack.snapshots[0], &self->redoStack.snapshots[1], sizeof(Snapshot) * (SNAPSHOT_STACK_MAX - 1));
|
||||
for (s32 i = 0; i < SNAPSHOT_STACK_MAX - 1; i++)
|
||||
self->redoStack.snapshots[i] = self->redoStack.snapshots[i + 1];
|
||||
self->redoStack.top = SNAPSHOT_STACK_MAX - 1;
|
||||
}
|
||||
|
||||
self->redoStack.snapshots[self->redoStack.top++] = *snapshot;
|
||||
}
|
||||
|
||||
// Pops the redo stack
|
||||
bool
|
||||
snapshots_redo_stack_pop(Snapshots* self, Snapshot* snapshot)
|
||||
{
|
||||
@@ -46,6 +54,7 @@ snapshots_redo_stack_pop(Snapshots* self, Snapshot* snapshot)
|
||||
return true;
|
||||
}
|
||||
|
||||
// Initializes snapshots
|
||||
void
|
||||
snapshots_init(Snapshots* self, Anm2* anm2, Anm2Reference* reference, f32* time, Input* input)
|
||||
{
|
||||
@@ -55,11 +64,16 @@ snapshots_init(Snapshots* self, Anm2* anm2, Anm2Reference* reference, f32* time,
|
||||
self->input = input;
|
||||
}
|
||||
|
||||
// Ticks snapshots
|
||||
void
|
||||
snapshots_tick(Snapshots* self)
|
||||
{
|
||||
/* Undo */
|
||||
if (key_press(&self->input->keyboard, INPUT_KEYS[INPUT_UNDO]))
|
||||
if (input_press(self->input, INPUT_UNDO))
|
||||
self->isUndo = true;
|
||||
|
||||
// isUndo disconnected, if another part of the program wants to set it
|
||||
if (self->isUndo)
|
||||
{
|
||||
Snapshot snapshot;
|
||||
if (snapshots_undo_stack_pop(self, &snapshot))
|
||||
@@ -71,10 +85,16 @@ snapshots_tick(Snapshots* self)
|
||||
*self->reference = snapshot.reference;
|
||||
*self->time = snapshot.time;
|
||||
}
|
||||
|
||||
self->isUndo = false;
|
||||
}
|
||||
|
||||
/* Redo */
|
||||
if (key_press(&self->input->keyboard, INPUT_KEYS[INPUT_REDO]))
|
||||
if (input_press(self->input, INPUT_REDO))
|
||||
self->isRedo = true;
|
||||
|
||||
// isRedo disconnected, if another part of the program wants to set it
|
||||
if (self->isRedo)
|
||||
{
|
||||
Snapshot snapshot;
|
||||
if (snapshots_redo_stack_pop(self, &snapshot))
|
||||
@@ -86,5 +106,7 @@ snapshots_tick(Snapshots* self)
|
||||
*self->reference = snapshot.reference;
|
||||
*self->time = snapshot.time;
|
||||
}
|
||||
|
||||
self->isRedo = false;
|
||||
}
|
||||
}
|
@@ -9,7 +9,7 @@ struct Snapshot
|
||||
{
|
||||
Anm2 anm2;
|
||||
Anm2Reference reference;
|
||||
f32 time;
|
||||
f32 time = 0.0f;
|
||||
};
|
||||
|
||||
struct SnapshotStack
|
||||
@@ -26,6 +26,8 @@ struct Snapshots
|
||||
Input* input = NULL;
|
||||
SnapshotStack undoStack;
|
||||
SnapshotStack redoStack;
|
||||
bool isUndo = false;
|
||||
bool isRedo = false;
|
||||
};
|
||||
|
||||
void snapshots_undo_stack_push(Snapshots* self, Snapshot* snapshot);
|
||||
|
@@ -38,6 +38,21 @@ _tick(State* state)
|
||||
snapshots_tick(&state->snapshots);
|
||||
dialog_tick(&state->dialog);
|
||||
imgui_tick(&state->imgui);
|
||||
|
||||
if (input_release(&state->input, INPUT_SAVE))
|
||||
{
|
||||
// Open dialog if path empty, otherwise save in-place
|
||||
if (state->anm2.path.empty())
|
||||
dialog_anm2_save(&state->dialog);
|
||||
else
|
||||
anm2_serialize(&state->anm2, state->anm2.path);
|
||||
}
|
||||
|
||||
if (input_release(&state->input, INPUT_PLAY))
|
||||
{
|
||||
state->preview.isPlaying = !state->preview.isPlaying;
|
||||
state->preview.isRecording = false;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -45,7 +60,7 @@ _draw(State* state)
|
||||
{
|
||||
editor_draw(&state->editor);
|
||||
preview_draw(&state->preview);
|
||||
imgui_draw(&state->imgui);
|
||||
imgui_draw();
|
||||
|
||||
SDL_GL_SwapWindow(state->window);
|
||||
}
|
||||
@@ -55,16 +70,14 @@ init(State* state)
|
||||
{
|
||||
settings_load(&state->settings);
|
||||
|
||||
printf(STRING_INFO_INIT);
|
||||
std::cout << STRING_INFO_INIT << std::endl;
|
||||
|
||||
if (!SDL_Init(SDL_INIT_VIDEO))
|
||||
{
|
||||
printf(STRING_ERROR_SDL_INIT, SDL_GetError());
|
||||
std::cout << STRING_ERROR_SDL_INIT << SDL_GetError() << std::endl;
|
||||
quit(state);
|
||||
}
|
||||
|
||||
printf(STRING_INFO_SDL_INIT);
|
||||
|
||||
|
||||
SDL_CreateWindowAndRenderer
|
||||
(
|
||||
STRING_WINDOW_TITLE,
|
||||
@@ -81,14 +94,14 @@ init(State* state)
|
||||
|
||||
state->glContext = SDL_GL_CreateContext(state->window);
|
||||
|
||||
printf(STRING_INFO_OPENGL, glGetString(GL_VERSION));
|
||||
|
||||
if (!state->glContext)
|
||||
{
|
||||
printf(STRING_ERROR_GL_CONTEXT_INIT, SDL_GetError());
|
||||
std::cout << STRING_ERROR_GL_CONTEXT_INIT << SDL_GetError() << std::endl;
|
||||
quit(state);
|
||||
}
|
||||
|
||||
std::cout << STRING_INFO_SDL_INIT << "(" << STRING_INFO_OPENGL << glGetString(GL_VERSION) << ")" << std::endl;
|
||||
|
||||
glewInit();
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
@@ -96,7 +109,7 @@ init(State* state)
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glLineWidth(LINE_WIDTH);
|
||||
|
||||
printf(STRING_INFO_GLEW_INIT);
|
||||
std::cout << STRING_INFO_GLEW_INIT << std::endl;
|
||||
|
||||
resources_init(&state->resources);
|
||||
dialog_init(&state->dialog, &state->anm2, &state->reference, &state->resources, state->window);
|
||||
@@ -155,7 +168,7 @@ loop(State* state)
|
||||
void
|
||||
quit(State* state)
|
||||
{
|
||||
imgui_free(&state->imgui);
|
||||
imgui_free();
|
||||
settings_save(&state->settings);
|
||||
preview_free(&state->preview);
|
||||
editor_free(&state->editor);
|
||||
@@ -164,6 +177,6 @@ quit(State* state)
|
||||
SDL_GL_DestroyContext(state->glContext);
|
||||
SDL_Quit();
|
||||
|
||||
printf(STRING_INFO_QUIT);
|
||||
std::cout << STRING_INFO_QUIT << std::endl;
|
||||
}
|
||||
|
||||
|
@@ -26,7 +26,7 @@ struct State
|
||||
Snapshots snapshots;
|
||||
bool isArgument = false;
|
||||
bool isRunning = true;
|
||||
char argument[PATH_MAX] = STRING_EMPTY;
|
||||
std::string argument;
|
||||
u64 lastTick = 0;
|
||||
u64 tick = 0;
|
||||
};
|
||||
|
@@ -9,6 +9,7 @@
|
||||
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||
#include <stb_image_write.h>
|
||||
|
||||
// Generates GL texture and sets parameters
|
||||
void
|
||||
texture_gl_set(Texture* self, void* data)
|
||||
{
|
||||
@@ -26,26 +27,28 @@ texture_gl_set(Texture* self, void* data)
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
// Initializes texture from path; returns true/false on success
|
||||
bool
|
||||
texture_from_path_init(Texture* self, const char* path)
|
||||
texture_from_path_init(Texture* self, const std::string& path)
|
||||
{
|
||||
void* data;
|
||||
|
||||
data = stbi_load(path, &self->size.x, &self->size.y, &self->channels, 4);
|
||||
data = stbi_load(path.c_str(), &self->size.x, &self->size.y, &self->channels, 4);
|
||||
|
||||
if (!data)
|
||||
{
|
||||
printf(STRING_ERROR_TEXTURE_INIT, path);
|
||||
std::cout << STRING_ERROR_TEXTURE_INIT << path << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
printf(STRING_INFO_TEXTURE_INIT, path);
|
||||
std::cout << STRING_INFO_TEXTURE_INIT << path << std::endl;
|
||||
|
||||
texture_gl_set(self, data);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Initializes texture from data; returns true/false on success
|
||||
bool
|
||||
texture_from_data_init(Texture* self, const u8* data, u32 length)
|
||||
{
|
||||
@@ -61,17 +64,17 @@ texture_from_data_init(Texture* self, const u8* data, u32 length)
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Writes a *.png to the path from the data/size */
|
||||
/* Returns true on success */
|
||||
// Writes an image to the path from the data/size
|
||||
bool
|
||||
texture_from_data_write(const char* path, const u8* data, s32 width, s32 height)
|
||||
texture_from_data_write(const std::string& path, const u8* data, s32 width, s32 height)
|
||||
{
|
||||
return (bool)stbi_write_png(path, width, height, 4, data, width * 4);
|
||||
return (bool)stbi_write_png(path.c_str(), width, height, 4, data, width * 4);
|
||||
}
|
||||
|
||||
// Frees texture
|
||||
void
|
||||
texture_free(Texture* self)
|
||||
{
|
||||
glDeleteTextures(1, &self->id);
|
||||
memset(self, '\0', sizeof(Texture));
|
||||
*self = Texture{};
|
||||
}
|
@@ -11,7 +11,7 @@ struct Texture
|
||||
};
|
||||
|
||||
void texture_gl_set(Texture* self, void* data);
|
||||
bool texture_from_path_init(Texture* self, const char* path);
|
||||
bool texture_from_path_init(Texture* self, const std::string& path);
|
||||
bool texture_from_data_init(Texture* self, const u8* data, u32 length);
|
||||
void texture_free(Texture* self);
|
||||
bool texture_from_data_write(const char* path, const u8* data, s32 width, s32 height);
|
||||
bool texture_from_data_write(const std::string& path, const u8* data, s32 width, s32 height);
|
22
src/tool.cpp
22
src/tool.cpp
@@ -1,33 +1,31 @@
|
||||
#include "tool.h"
|
||||
|
||||
// Initializes tools
|
||||
void
|
||||
tool_init(Tool* self, Input* input)
|
||||
{
|
||||
self->input = input;
|
||||
}
|
||||
|
||||
// Ticks tools
|
||||
void
|
||||
tool_tick(Tool* self)
|
||||
{
|
||||
if (!self->isEnabled) return;
|
||||
|
||||
/* Input handling */
|
||||
if (key_press(&self->input->keyboard, INPUT_KEYS[INPUT_PAN]))
|
||||
// Input handling for tools
|
||||
if (input_release(self->input, INPUT_PAN))
|
||||
self->type = TOOL_PAN;
|
||||
|
||||
if (key_press(&self->input->keyboard, INPUT_KEYS[INPUT_MOVE]))
|
||||
if (input_release(self->input, INPUT_MOVE))
|
||||
self->type = TOOL_MOVE;
|
||||
|
||||
if (key_press(&self->input->keyboard, INPUT_KEYS[INPUT_SCALE]))
|
||||
if (input_release(self->input, INPUT_SCALE))
|
||||
self->type = TOOL_SCALE;
|
||||
|
||||
if (key_press(&self->input->keyboard, INPUT_KEYS[INPUT_CROP]))
|
||||
self->type = TOOL_CROP;
|
||||
|
||||
if
|
||||
(
|
||||
key_press(&self->input->keyboard, INPUT_KEYS[INPUT_ROTATE_LEFT]) ||
|
||||
key_press(&self->input->keyboard, INPUT_KEYS[INPUT_ROTATE_RIGHT])
|
||||
)
|
||||
if (input_release(self->input, INPUT_ROTATE))
|
||||
self->type = TOOL_ROTATE;
|
||||
|
||||
if (input_release(self->input, INPUT_CROP))
|
||||
self->type = TOOL_CROP;
|
||||
}
|
@@ -2,14 +2,14 @@
|
||||
|
||||
#include "input.h"
|
||||
|
||||
#define TOOL_COUNT (TOOL_CROP + 1)
|
||||
enum ToolType
|
||||
{
|
||||
TOOL_PAN,
|
||||
TOOL_MOVE,
|
||||
TOOL_ROTATE,
|
||||
TOOL_SCALE,
|
||||
TOOL_CROP
|
||||
TOOL_CROP,
|
||||
TOOL_COUNT
|
||||
};
|
||||
|
||||
struct Tool
|
||||
|
@@ -2,13 +2,13 @@
|
||||
|
||||
/* Sets the window title from the given anm2 */
|
||||
void
|
||||
window_title_from_path_set(SDL_Window* self, const char* path)
|
||||
window_title_from_path_set(SDL_Window* self, const std::string& path)
|
||||
{
|
||||
if (!strcmp(path, STRING_EMPTY) == 0)
|
||||
if (path.empty())
|
||||
{
|
||||
char windowTitle[WINDOW_TITLE_MAX];
|
||||
snprintf(windowTitle, WINDOW_TITLE_MAX, STRING_WINDOW_TITLE_EDITING, path);
|
||||
SDL_SetWindowTitle(self, windowTitle);
|
||||
std::string windowTitle = path;
|
||||
windowTitle = windowTitle + " (" + path + ")";
|
||||
SDL_SetWindowTitle(self, windowTitle.c_str());
|
||||
}
|
||||
else
|
||||
SDL_SetWindowTitle(self, STRING_WINDOW_TITLE);
|
||||
|
@@ -2,6 +2,4 @@
|
||||
|
||||
#include "COMMON.h"
|
||||
|
||||
#define WINDOW_TITLE_MAX 0xFF + PATH_MAX
|
||||
|
||||
void window_title_from_path_set(SDL_Window* self, const char* path);
|
||||
void window_title_from_path_set(SDL_Window* self, const std::string& path);
|
Reference in New Issue
Block a user