basics
This commit is contained in:
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
build/
|
||||
concept/
|
||||
packed/
|
4
.gitmodules
vendored
4
.gitmodules
vendored
@ -1,6 +1,10 @@
|
||||
[submodule "include/imgui"]
|
||||
path = include/imgui
|
||||
url = https://github.com/ocornut/imgui
|
||||
branch = docking
|
||||
[submodule "include/glm"]
|
||||
path = include/glm
|
||||
url = https://github.com/g-truc/glm
|
||||
[submodule "include/tinyxml2"]
|
||||
path = include/tinyxml2
|
||||
url = https://github.com/leethomason/tinyxml2
|
||||
|
@ -3,16 +3,21 @@ project(anm2ed CXX)
|
||||
|
||||
# Gather project sources
|
||||
file(GLOB SOURCES
|
||||
"${PROJECT_SOURCE_DIR}/include/imgui/*.cpp"
|
||||
"${PROJECT_SOURCE_DIR}/include/pugixml/*.cpp"
|
||||
"include/imgui/imgui.cpp"
|
||||
"include/imgui/imgui_draw.cpp"
|
||||
"include/imgui/imgui_tables.cpp"
|
||||
"include/imgui/imgui_widgets.cpp"
|
||||
"include/imgui/backends/imgui_impl_sdl3.cpp"
|
||||
"include/imgui/backends/imgui_impl_opengl3.cpp"
|
||||
"include/tinyxml2/tinyxml2.cpp"
|
||||
"${PROJECT_SOURCE_DIR}/src/*.cpp"
|
||||
)
|
||||
|
||||
add_executable(${PROJECT_NAME} ${SOURCES})
|
||||
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE include src)
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE include include/imgui include/tinyxml2 src )
|
||||
|
||||
set(CMAKE_CXX_FLAGS "-g -O2 -std=c++20 -Wall -Wextra -pedantic -Wno-unused-variable -Wno-unused-parameter -Wno-ignored-qualifiers -Wno-parentheses -Wno-unused-function -Wno-class-memaccess")
|
||||
set(CMAKE_CXX_FLAGS "-g -O2 -std=c++23 -Wall -Wextra -pedantic -Wno-unused-variable -Wno-unused-parameter -Wno-ignored-qualifiers -Wno-parentheses -Wno-unused-function -Wno-class-memaccess -Wno-delete-incomplete")
|
||||
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE m GL GLEW SDL3 SDL3_mixer)
|
||||
|
||||
|
Submodule include/imgui updated: cfa43e721a...d896eab166
59
src/COMMON.h
59
src/COMMON.h
@ -5,25 +5,23 @@
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <GL/gl.h>
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
#include <glm/glm/glm.hpp>
|
||||
#include <glm/glm/gtc/type_ptr.hpp>
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#include <pugixml.hpp>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <tinyxml2.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <ranges>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include "STRINGS.h"
|
||||
#include "RESOURCES.h"
|
||||
|
||||
using namespace glm;
|
||||
using namespace pugi;
|
||||
using namespace std;
|
||||
|
||||
typedef uint8_t u8;
|
||||
typedef uint16_t u16;
|
||||
@ -40,15 +38,40 @@ typedef double f64;
|
||||
|
||||
#define PI (GLM_PI)
|
||||
#define TAU (PI * 2)
|
||||
#define ATAN(x1, x2, y1, y2) (fmod((atan2(y2 - y1, x2 - x1) + TAU), TAU)) /* [0, 2PI] */
|
||||
|
||||
struct State
|
||||
using namespace glm; // fuck you
|
||||
|
||||
#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))
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
template<typename Map, typename Key>
|
||||
static inline void map_swap(Map& map, const Key& key1, const Key& key2)
|
||||
{
|
||||
SDL_Window* window;
|
||||
SDL_Renderer* renderer;
|
||||
SDL_GLContext glContext;
|
||||
vec3 clearColor = {0.69, 0.69, 0.69};
|
||||
u64 tick = 0;
|
||||
u64 lastTick = 0;
|
||||
bool isRunning = true;
|
||||
};
|
||||
auto it1 = map.find(key1);
|
||||
auto it2 = map.find(key2);
|
||||
if (it1 == map.end() || it2 == map.end())
|
||||
return;
|
||||
|
||||
using std::swap;
|
||||
swap(it1->second, it2->second);
|
||||
}
|
||||
|
||||
#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); \
|
||||
}
|
||||
|
302
src/PACKED.h
Normal file
302
src/PACKED.h
Normal file
@ -0,0 +1,302 @@
|
||||
#pragma once
|
||||
|
||||
#include "COMMON.h"
|
||||
|
||||
struct PackedData
|
||||
{
|
||||
const u8* data;
|
||||
u32 length;
|
||||
};
|
||||
|
||||
static const unsigned char texture_eye_closed[] = {
|
||||
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
|
||||
0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10,
|
||||
0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0xf3, 0xff, 0x61, 0x00, 0x00, 0x00,
|
||||
0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x5c, 0x46, 0x00, 0x00, 0x5c,
|
||||
0x46, 0x01, 0x14, 0x94, 0x43, 0x41, 0x00, 0x00, 0x00, 0x88, 0x49, 0x44,
|
||||
0x41, 0x54, 0x38, 0xcb, 0xb5, 0x52, 0x41, 0x0e, 0xc0, 0x20, 0x08, 0x13,
|
||||
0xb2, 0x7f, 0xab, 0x2f, 0xdf, 0xe4, 0xc0, 0xd2, 0x90, 0x82, 0xcb, 0xb2,
|
||||
0x71, 0x32, 0xd0, 0x4a, 0xa1, 0xb4, 0xf6, 0x47, 0x8c, 0x31, 0xce, 0x18,
|
||||
0x96, 0x63, 0x58, 0x89, 0x09, 0x03, 0x57, 0x9f, 0xcb, 0x8a, 0xf4, 0x03,
|
||||
0x24, 0x47, 0x60, 0x56, 0x93, 0x08, 0x98, 0x73, 0xd2, 0xce, 0xbd, 0x77,
|
||||
0xaa, 0x44, 0x7d, 0xe6, 0x4a, 0x76, 0x24, 0x23, 0x47, 0x76, 0xdd, 0x91,
|
||||
0xec, 0x75, 0xcf, 0x99, 0x0a, 0x7d, 0xda, 0x39, 0x1b, 0x4d, 0x51, 0xfe,
|
||||
0x7a, 0xcb, 0x8e, 0x8c, 0x98, 0x9b, 0x1b, 0xbd, 0x46, 0xff, 0xab, 0x1b,
|
||||
0xb9, 0x77, 0x60, 0x49, 0xb6, 0xa8, 0x6a, 0x27, 0x56, 0x33, 0x35, 0x92,
|
||||
0x1d, 0xd0, 0xce, 0x4e, 0xb7, 0xf1, 0x40, 0x5f, 0xab, 0x2b, 0x44, 0x85,
|
||||
0xf4, 0x90, 0xde, 0x9e, 0xb2, 0x32, 0x00, 0x93, 0x6f, 0xb9, 0x48, 0xfe,
|
||||
0x24, 0x2e, 0x5d, 0x0c, 0x84, 0xee, 0xa1, 0x31, 0xa2, 0x43, 0x00, 0x00,
|
||||
0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
|
||||
};
|
||||
static const unsigned int texture_eye_closed_len = 214;
|
||||
|
||||
static const unsigned char texture_animation[] =
|
||||
{
|
||||
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
|
||||
0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10,
|
||||
0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0xf3, 0xff, 0x61, 0x00, 0x00, 0x00,
|
||||
0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x5c, 0x46, 0x00, 0x00, 0x5c,
|
||||
0x46, 0x01, 0x14, 0x94, 0x43, 0x41, 0x00, 0x00, 0x00, 0x69, 0x49, 0x44,
|
||||
0x41, 0x54, 0x38, 0xcb, 0xcd, 0x51, 0x41, 0x0e, 0xc0, 0x20, 0x08, 0x83,
|
||||
0xc5, 0x7f, 0x03, 0x2f, 0x77, 0x72, 0x20, 0x61, 0x99, 0x0c, 0x8c, 0xcb,
|
||||
0xb2, 0x5e, 0x14, 0x05, 0x4a, 0x0b, 0xc0, 0x97, 0x60, 0xe6, 0x6e, 0xb0,
|
||||
0xb7, 0x96, 0x15, 0x59, 0xb2, 0x88, 0xd4, 0x99, 0x8c, 0xc5, 0x33, 0xea,
|
||||
0x7d, 0x96, 0xdb, 0x32, 0x26, 0x1c, 0x78, 0x22, 0x9b, 0x4a, 0xc8, 0x8a,
|
||||
0x2e, 0xb9, 0xde, 0x20, 0x3d, 0x89, 0x08, 0xfc, 0x24, 0x51, 0x6c, 0x24,
|
||||
0xc7, 0x6b, 0x2b, 0xf2, 0xab, 0xa9, 0xac, 0xf3, 0xe6, 0x81, 0x8e, 0x18,
|
||||
0x39, 0xbd, 0xdc, 0x35, 0xfb, 0xf3, 0xf1, 0xb6, 0x07, 0xdb, 0x0d, 0xb0,
|
||||
0x22, 0x21, 0x90, 0x85, 0xf0, 0x0b, 0x9c, 0x7f, 0x4e, 0x4a, 0x7e, 0x6e,
|
||||
0xdb, 0xca, 0xac, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae,
|
||||
0x42, 0x60, 0x82
|
||||
};
|
||||
static const unsigned int texture_animation_len = 183;
|
||||
|
||||
static const unsigned char texture_event[] =
|
||||
{
|
||||
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
|
||||
0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10,
|
||||
0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0xf3, 0xff, 0x61, 0x00, 0x00, 0x00,
|
||||
0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x5c, 0x46, 0x00, 0x00, 0x5c,
|
||||
0x46, 0x01, 0x14, 0x94, 0x43, 0x41, 0x00, 0x00, 0x00, 0x5e, 0x49, 0x44,
|
||||
0x41, 0x54, 0x38, 0xcb, 0xcd, 0x91, 0x49, 0x0e, 0x00, 0x21, 0x08, 0x04,
|
||||
0x71, 0xe2, 0xbf, 0x81, 0x97, 0xbb, 0x25, 0x24, 0x73, 0x40, 0x6c, 0x2f,
|
||||
0x6a, 0x5d, 0xa1, 0x41, 0x0b, 0xa2, 0x13, 0x88, 0x48, 0xe9, 0x78, 0xb5,
|
||||
0xbc, 0x0a, 0x5b, 0x50, 0x55, 0xdd, 0x7a, 0x42, 0xc2, 0xa3, 0xb1, 0xb1,
|
||||
0x35, 0x00, 0x09, 0x4f, 0x07, 0xa0, 0x61, 0x77, 0xc0, 0x3f, 0x6c, 0xff,
|
||||
0x6e, 0x12, 0xd3, 0x96, 0xed, 0x88, 0xa5, 0xf1, 0x88, 0xbe, 0x00, 0x96,
|
||||
0x68, 0xcd, 0xcc, 0x4c, 0x91, 0x8f, 0xfb, 0x67, 0xfc, 0xa2, 0xe7, 0x23,
|
||||
0x67, 0x9c, 0x6e, 0xf7, 0x84, 0xbd, 0x49, 0x05, 0xbd, 0xc3, 0x78, 0xc4,
|
||||
0x32, 0xe6, 0xac, 0x29, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44,
|
||||
0xae, 0x42, 0x60, 0x82
|
||||
};
|
||||
static const unsigned int texture_event_len = 172;
|
||||
|
||||
static const unsigned char texture_eye_open[] =
|
||||
{
|
||||
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
|
||||
0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10,
|
||||
0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0xf3, 0xff, 0x61, 0x00, 0x00, 0x00,
|
||||
0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x5c, 0x46, 0x00, 0x00, 0x5c,
|
||||
0x46, 0x01, 0x14, 0x94, 0x43, 0x41, 0x00, 0x00, 0x00, 0x64, 0x49, 0x44,
|
||||
0x41, 0x54, 0x38, 0xcb, 0x63, 0x60, 0x18, 0x05, 0x58, 0x41, 0x43, 0x43,
|
||||
0xc3, 0x7f, 0x74, 0x00, 0x12, 0x23, 0x4b, 0x23, 0x21, 0x83, 0x18, 0x91,
|
||||
0x39, 0x20, 0x05, 0x20, 0xba, 0xb1, 0xb1, 0x11, 0xab, 0x05, 0xf5, 0xf5,
|
||||
0xf5, 0x10, 0x4d, 0x40, 0x80, 0xd5, 0x66, 0x10, 0x8d, 0xcc, 0x46, 0xb6,
|
||||
0x15, 0x9b, 0x3c, 0xdc, 0x56, 0x74, 0xa7, 0xc1, 0x5c, 0x02, 0x93, 0x43,
|
||||
0x16, 0x43, 0xf7, 0x2a, 0x8a, 0x00, 0xb2, 0x01, 0xc8, 0x06, 0x12, 0x92,
|
||||
0xc7, 0x08, 0x03, 0x64, 0xdb, 0x51, 0x6c, 0x42, 0x53, 0x83, 0x33, 0x16,
|
||||
0xb0, 0x99, 0x8e, 0x4f, 0x8e, 0xe8, 0xa8, 0x24, 0x2a, 0x2d, 0x0c, 0x3d,
|
||||
0x00, 0x00, 0xde, 0x2d, 0xf2, 0x3a, 0xa5, 0xc2, 0xad, 0x18, 0x00, 0x00,
|
||||
0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
|
||||
};
|
||||
static const unsigned int texture_eye_open_len = 178;
|
||||
|
||||
static const unsigned char texture_layer[] =
|
||||
{
|
||||
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
|
||||
0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10,
|
||||
0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0xf3, 0xff, 0x61, 0x00, 0x00, 0x00,
|
||||
0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x5c, 0x46, 0x00, 0x00, 0x5c,
|
||||
0x46, 0x01, 0x14, 0x94, 0x43, 0x41, 0x00, 0x00, 0x00, 0x6b, 0x49, 0x44,
|
||||
0x41, 0x54, 0x38, 0xcb, 0xb5, 0x90, 0x8b, 0x0a, 0xc0, 0x20, 0x08, 0x45,
|
||||
0x33, 0xf6, 0xdf, 0xea, 0x97, 0x57, 0x83, 0x09, 0x19, 0x3e, 0x16, 0x5b,
|
||||
0x17, 0xc2, 0x44, 0xcf, 0x35, 0x2b, 0xe5, 0xa4, 0xda, 0xa3, 0xa8, 0x07,
|
||||
0x3c, 0xd0, 0x6c, 0x1e, 0x0a, 0x0d, 0xb2, 0x69, 0x96, 0x11, 0xec, 0x80,
|
||||
0x96, 0x51, 0xfd, 0xfa, 0x4f, 0xff, 0xac, 0x40, 0x44, 0x0a, 0x44, 0x44,
|
||||
0x13, 0x64, 0x66, 0x95, 0x0f, 0x0e, 0xae, 0xa8, 0x51, 0x8c, 0x56, 0xd0,
|
||||
0x5d, 0x61, 0x7d, 0x89, 0xa7, 0x7b, 0xb2, 0xdc, 0xeb, 0x0c, 0xcf, 0x85,
|
||||
0x0c, 0x54, 0xc3, 0x24, 0xb1, 0xa2, 0x1c, 0xab, 0xee, 0x4d, 0x69, 0x6f,
|
||||
0x62, 0xb6, 0xe3, 0x3e, 0x94, 0x99, 0x1d, 0x53, 0x07, 0x98, 0x83, 0x59,
|
||||
0xf9, 0x38, 0x5d, 0x6e, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e,
|
||||
0x44, 0xae, 0x42, 0x60, 0x82
|
||||
};
|
||||
static const unsigned int texture_layer_len = 185;
|
||||
|
||||
static const unsigned char texture_null[] =
|
||||
{
|
||||
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
|
||||
0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10,
|
||||
0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0xf3, 0xff, 0x61, 0x00, 0x00, 0x00,
|
||||
0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x5c, 0x46, 0x00, 0x00, 0x5c,
|
||||
0x46, 0x01, 0x14, 0x94, 0x43, 0x41, 0x00, 0x00, 0x00, 0x5f, 0x49, 0x44,
|
||||
0x41, 0x54, 0x38, 0xcb, 0xb5, 0x52, 0xcb, 0x0a, 0x00, 0x20, 0x08, 0xab,
|
||||
0xbe, 0x5c, 0xbf, 0xbc, 0xc7, 0x41, 0xa8, 0x70, 0x91, 0x69, 0x3b, 0x09,
|
||||
0xce, 0xa1, 0x9b, 0x29, 0xfd, 0x02, 0x11, 0x55, 0xc1, 0xa8, 0x11, 0x2f,
|
||||
0xa3, 0xc6, 0x18, 0x5c, 0x88, 0x1d, 0x1a, 0xaf, 0x78, 0x37, 0x85, 0x02,
|
||||
0xcc, 0xac, 0xd6, 0x26, 0x88, 0x07, 0x4f, 0x1b, 0xb8, 0x4f, 0x70, 0x09,
|
||||
0x48, 0x84, 0xf3, 0x29, 0xa7, 0x28, 0x61, 0xfe, 0xbb, 0x17, 0x50, 0x64,
|
||||
0x1e, 0x42, 0xc6, 0xed, 0x7d, 0x11, 0xcb, 0x96, 0xa7, 0xd1, 0x78, 0x31,
|
||||
0x26, 0xde, 0x3e, 0x4d, 0xc8, 0x73, 0x85, 0xa3, 0x01, 0xa9, 0x8a, 0x70,
|
||||
0xd3, 0x3d, 0xa4, 0xfe, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e,
|
||||
0x44, 0xae, 0x42, 0x60, 0x82
|
||||
};
|
||||
static const unsigned int texture_null_len = 173;
|
||||
|
||||
static const unsigned char texture_rect_hide[] = {
|
||||
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
|
||||
0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10,
|
||||
0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0xf3, 0xff, 0x61, 0x00, 0x00, 0x00,
|
||||
0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x5c, 0x46, 0x00, 0x00, 0x5c,
|
||||
0x46, 0x01, 0x14, 0x94, 0x43, 0x41, 0x00, 0x00, 0x00, 0x88, 0x49, 0x44,
|
||||
0x41, 0x54, 0x38, 0xcb, 0xb5, 0x93, 0x51, 0x0e, 0x80, 0x20, 0x0c, 0x43,
|
||||
0x65, 0x17, 0x07, 0x4e, 0xae, 0xc1, 0x64, 0xa6, 0xab, 0x1d, 0x12, 0x8d,
|
||||
0xfd, 0x31, 0x91, 0xbe, 0x8d, 0xcd, 0xba, 0x6d, 0x7f, 0xa8, 0xb5, 0xb6,
|
||||
0xb3, 0xc6, 0x3b, 0xe5, 0x2d, 0x08, 0x8d, 0x67, 0xad, 0x75, 0x5a, 0xbc,
|
||||
0xf7, 0xee, 0xfe, 0x93, 0x35, 0x3c, 0x44, 0xb8, 0x90, 0x94, 0x27, 0xe8,
|
||||
0xe9, 0xaa, 0x3c, 0x52, 0x3a, 0xf3, 0x0a, 0x8c, 0x8d, 0x8a, 0x1b, 0xfc,
|
||||
0xda, 0x0a, 0xc6, 0xb1, 0xd8, 0x6f, 0xb3, 0x85, 0x29, 0x98, 0x65, 0x5f,
|
||||
0xe0, 0xb4, 0xc0, 0x2a, 0x7c, 0x15, 0xf0, 0x6f, 0xcb, 0x8b, 0x44, 0x78,
|
||||
0x2c, 0xcd, 0x97, 0x8d, 0x8c, 0x61, 0x28, 0x42, 0xc2, 0x08, 0xce, 0x6e,
|
||||
0x10, 0x4c, 0x1c, 0xa4, 0x2c, 0xa1, 0xde, 0xfd, 0x96, 0x05, 0xf5, 0x0f,
|
||||
0x64, 0x01, 0x0a, 0x39, 0x50, 0xc5, 0x38, 0xb2, 0xdc, 0x55, 0x8d, 0xfd,
|
||||
0x4a, 0x07, 0xf4, 0xc4, 0xc2, 0x2e, 0xb7, 0xd3, 0xf8, 0x61, 0x00, 0x00,
|
||||
0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
|
||||
};
|
||||
static const unsigned int texture_rect_hide_len = 214;
|
||||
|
||||
static const unsigned char texture_rect_show[] =
|
||||
{
|
||||
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
|
||||
0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10,
|
||||
0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0xf3, 0xff, 0x61, 0x00, 0x00, 0x00,
|
||||
0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x5c, 0x46, 0x00, 0x00, 0x5c,
|
||||
0x46, 0x01, 0x14, 0x94, 0x43, 0x41, 0x00, 0x00, 0x00, 0x5c, 0x49, 0x44,
|
||||
0x41, 0x54, 0x38, 0xcb, 0x63, 0x60, 0x18, 0x34, 0xa0, 0xa1, 0xa1, 0xe1,
|
||||
0x3f, 0xb1, 0x00, 0xa4, 0x16, 0xc3, 0x00, 0x9c, 0x12, 0x38, 0x2c, 0xc2,
|
||||
0x6a, 0x00, 0xb1, 0xae, 0x45, 0x56, 0xcb, 0x44, 0xa9, 0xd7, 0x87, 0xa8,
|
||||
0x01, 0x8d, 0x8d, 0x8d, 0x0c, 0x14, 0x05, 0x22, 0x32, 0x60, 0x21, 0x27,
|
||||
0xe4, 0x41, 0x80, 0x11, 0x08, 0x88, 0xf6, 0x02, 0x48, 0x33, 0xb2, 0xb3,
|
||||
0x41, 0x6c, 0x0c, 0x17, 0xe3, 0x4a, 0x48, 0xc8, 0xe2, 0xb0, 0x94, 0x88,
|
||||
0x35, 0x41, 0xa1, 0x27, 0x65, 0x64, 0xc3, 0xd0, 0xf9, 0xc8, 0x9a, 0x19,
|
||||
0x29, 0x0d, 0x03, 0x8a, 0x01, 0x00, 0x43, 0x33, 0x93, 0xa2, 0x31, 0x56,
|
||||
0x19, 0xd4, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42,
|
||||
0x60, 0x82
|
||||
};
|
||||
static const unsigned int texture_rect_show_len = 170;
|
||||
|
||||
static const unsigned char texture_root[] =
|
||||
{
|
||||
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
|
||||
0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10,
|
||||
0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0xf3, 0xff, 0x61, 0x00, 0x00, 0x00,
|
||||
0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x5c, 0x46, 0x00, 0x00, 0x5c,
|
||||
0x46, 0x01, 0x14, 0x94, 0x43, 0x41, 0x00, 0x00, 0x00, 0x4d, 0x49, 0x44,
|
||||
0x41, 0x54, 0x38, 0xcb, 0x63, 0x60, 0x18, 0xfe, 0xa0, 0xa1, 0xa1, 0xe1,
|
||||
0x3f, 0x3e, 0xc0, 0x48, 0xc8, 0x00, 0x90, 0x22, 0x8a, 0x6d, 0x27, 0xdb,
|
||||
0x00, 0x98, 0x33, 0xf1, 0xa9, 0x61, 0x22, 0x56, 0x21, 0x5e, 0x03, 0x90,
|
||||
0x9d, 0x8c, 0xce, 0x6e, 0x6c, 0x6c, 0x24, 0x2d, 0xa4, 0x49, 0x71, 0x3e,
|
||||
0x5e, 0xff, 0x12, 0x6b, 0x00, 0xdc, 0x0b, 0x30, 0xa7, 0x22, 0x6b, 0x24,
|
||||
0xc6, 0xf9, 0x8c, 0xf8, 0xe2, 0x9c, 0x11, 0x08, 0x68, 0x12, 0x75, 0x83,
|
||||
0x0b, 0x00, 0x00, 0xff, 0xce, 0x78, 0xa9, 0x56, 0xe2, 0xe3, 0x36, 0x00,
|
||||
0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
|
||||
};
|
||||
static const unsigned int texture_root_len = 155;
|
||||
|
||||
static const unsigned char texture_spritesheet[] =
|
||||
{
|
||||
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
|
||||
0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10,
|
||||
0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0xf3, 0xff, 0x61, 0x00, 0x00, 0x00,
|
||||
0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x5c, 0x46, 0x00, 0x00, 0x5c,
|
||||
0x46, 0x01, 0x14, 0x94, 0x43, 0x41, 0x00, 0x00, 0x00, 0x72, 0x49, 0x44,
|
||||
0x41, 0x54, 0x38, 0xcb, 0xd5, 0x51, 0x41, 0x0e, 0x80, 0x30, 0x08, 0x63,
|
||||
0xc6, 0x7f, 0x0f, 0x5e, 0x8e, 0xd3, 0xc8, 0xd2, 0x6d, 0x64, 0xc3, 0x78,
|
||||
0x30, 0x36, 0xe1, 0xd2, 0xb4, 0x40, 0x81, 0xe8, 0x2b, 0x30, 0xb3, 0xbe,
|
||||
0x32, 0x6a, 0xc1, 0x54, 0x84, 0xc0, 0x69, 0xc8, 0x87, 0x8c, 0xc6, 0xe1,
|
||||
0x64, 0x6c, 0xb0, 0xa1, 0x39, 0xe7, 0x4c, 0x22, 0x72, 0xd5, 0x2a, 0xb7,
|
||||
0x69, 0x76, 0x34, 0xf7, 0xf0, 0xb8, 0xd3, 0x58, 0xf4, 0xa9, 0x21, 0x35,
|
||||
0x00, 0x8c, 0x87, 0xde, 0x1a, 0x21, 0xdd, 0x58, 0x7d, 0xc1, 0xd5, 0x60,
|
||||
0xd7, 0x27, 0xd3, 0xeb, 0x0d, 0xbc, 0xbf, 0xda, 0x91, 0xbc, 0x3b, 0xb8,
|
||||
0x11, 0x22, 0x31, 0x22, 0x11, 0x87, 0x18, 0xb3, 0xf5, 0x87, 0x0d, 0xfa,
|
||||
0xf5, 0xff, 0x81, 0x03, 0xfa, 0x3e, 0xcf, 0x06, 0xd1, 0x47, 0xd3, 0x66,
|
||||
0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
|
||||
};
|
||||
static const unsigned int texture_spritesheet_len = 192;
|
||||
|
||||
static const unsigned char texture_trigger[] =
|
||||
{
|
||||
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
|
||||
0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10,
|
||||
0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0xf3, 0xff, 0x61, 0x00, 0x00, 0x00,
|
||||
0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x5c, 0x46, 0x00, 0x00, 0x5c,
|
||||
0x46, 0x01, 0x14, 0x94, 0x43, 0x41, 0x00, 0x00, 0x00, 0x5f, 0x49, 0x44,
|
||||
0x41, 0x54, 0x38, 0xcb, 0xd5, 0x92, 0x01, 0x0a, 0x00, 0x20, 0x08, 0x03,
|
||||
0xab, 0x97, 0xeb, 0xcb, 0x2d, 0x21, 0x41, 0x64, 0x42, 0x51, 0x10, 0x1d,
|
||||
0x44, 0x20, 0x6e, 0xc8, 0xb4, 0x94, 0x5b, 0xc8, 0x64, 0x57, 0xd7, 0x62,
|
||||
0x81, 0x88, 0x44, 0x9f, 0xa2, 0x3f, 0x12, 0xc1, 0xba, 0x09, 0xfd, 0x34,
|
||||
0xd9, 0x44, 0xb0, 0xee, 0x05, 0x12, 0x30, 0x63, 0x9b, 0xcc, 0x1b, 0xd4,
|
||||
0xe8, 0x5a, 0x07, 0x2b, 0x59, 0x68, 0x1f, 0xcc, 0xe0, 0x38, 0xc4, 0x15,
|
||||
0x98, 0x39, 0x5f, 0x63, 0xdc, 0x80, 0x00, 0xb6, 0xee, 0xc0, 0x07, 0x97,
|
||||
0xad, 0xf5, 0xee, 0x21, 0xfd, 0x67, 0xf0, 0x9e, 0x0e, 0x79, 0xfa, 0x9b,
|
||||
0x11, 0x47, 0x7c, 0xbe, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e,
|
||||
0x44, 0xae, 0x42, 0x60, 0x82
|
||||
};
|
||||
static const unsigned int texture_trigger_len = 173;
|
||||
|
||||
static const unsigned char texture_arrow_up[] = {
|
||||
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
|
||||
0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10,
|
||||
0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0xf3, 0xff, 0x61, 0x00, 0x00, 0x00,
|
||||
0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x5c, 0x46, 0x00, 0x00, 0x5c,
|
||||
0x46, 0x01, 0x14, 0x94, 0x43, 0x41, 0x00, 0x00, 0x00, 0x43, 0x49, 0x44,
|
||||
0x41, 0x54, 0x38, 0xcb, 0x63, 0x60, 0xa0, 0x25, 0xf8, 0x0f, 0x05, 0xf8,
|
||||
0xd4, 0x30, 0xe2, 0xd3, 0x8c, 0xa2, 0x10, 0x08, 0x88, 0x36, 0x00, 0x97,
|
||||
0xad, 0xd8, 0x0c, 0x61, 0x24, 0x56, 0x33, 0x2e, 0x43, 0x18, 0x49, 0xd1,
|
||||
0x8c, 0xcd, 0x10, 0x46, 0x52, 0x35, 0xa3, 0x1b, 0xc2, 0x48, 0x8e, 0x66,
|
||||
0x64, 0x43, 0x28, 0x8e, 0x05, 0x26, 0x4a, 0xd3, 0xca, 0xa8, 0x01, 0x54,
|
||||
0x30, 0x80, 0x62, 0x00, 0x00, 0xbc, 0x66, 0x24, 0x0c, 0xf7, 0xc3, 0x33,
|
||||
0x72, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60,
|
||||
0x82
|
||||
};
|
||||
static const unsigned int texture_arrow_up_len = 145;
|
||||
static const unsigned char texture_arrow_down[] = {
|
||||
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
|
||||
0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10,
|
||||
0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0xf3, 0xff, 0x61, 0x00, 0x00, 0x00,
|
||||
0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x5c, 0x46, 0x00, 0x00, 0x5c,
|
||||
0x46, 0x01, 0x14, 0x94, 0x43, 0x41, 0x00, 0x00, 0x00, 0x4b, 0x49, 0x44,
|
||||
0x41, 0x54, 0x38, 0xcb, 0x63, 0x60, 0xa0, 0x10, 0x30, 0xe2, 0x92, 0xf8,
|
||||
0x0f, 0x04, 0x28, 0x0a, 0x81, 0x00, 0x9b, 0x3a, 0x26, 0x4a, 0x5d, 0x30,
|
||||
0x6a, 0x00, 0x15, 0x0c, 0x60, 0xc4, 0x16, 0x65, 0x44, 0x6b, 0x46, 0x8e,
|
||||
0x5b, 0x52, 0x0d, 0x81, 0xe9, 0x65, 0xc4, 0x97, 0x78, 0x08, 0x69, 0xc6,
|
||||
0x9a, 0x12, 0x09, 0x19, 0x82, 0x9e, 0x22, 0x19, 0x89, 0x49, 0xc6, 0xf8,
|
||||
0x92, 0x33, 0xc5, 0x79, 0x01, 0x2f, 0xf8, 0x0f, 0x05, 0x0c, 0xb4, 0x04,
|
||||
0x00, 0x05, 0x8c, 0x24, 0x0c, 0x43, 0x26, 0x91, 0x46, 0x00, 0x00, 0x00,
|
||||
0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
|
||||
};
|
||||
static const unsigned int texture_arrow_down_len = 153;
|
||||
|
||||
#define PACKED_TEXTURE_COUNT (PACKED_TEXTURE_ARROW_DOWN + 1)
|
||||
enum PackedTextureType
|
||||
{
|
||||
PACKED_TEXTURE_EYE_OPEN,
|
||||
PACKED_TEXTURE_EYE_CLOSED,
|
||||
PACKED_TEXTURE_ANIMATION,
|
||||
PACKED_TEXTURE_EVENT,
|
||||
PACKED_TEXTURE_LAYER,
|
||||
PACKED_TEXTURE_NULL,
|
||||
PACKED_TEXTURE_ROOT,
|
||||
PACKED_TEXTURE_SPRITESHEET,
|
||||
PACKED_TEXTURE_TRIGGER,
|
||||
PACKED_TEXTURE_RECT_SHOW,
|
||||
PACKED_TEXTURE_RECT_HIDE,
|
||||
PACKED_TEXTURE_ARROW_UP,
|
||||
PACKED_TEXTURE_ARROW_DOWN
|
||||
};
|
||||
|
||||
static const PackedData PACKED_TEXTURE_DATA[PACKED_TEXTURE_COUNT] =
|
||||
{
|
||||
{texture_eye_open, texture_eye_open_len},
|
||||
{texture_eye_closed, texture_eye_closed_len},
|
||||
{texture_animation, texture_animation_len},
|
||||
{texture_event, texture_event_len},
|
||||
{texture_layer, texture_layer_len},
|
||||
{texture_null, texture_null_len},
|
||||
{texture_root, texture_root_len},
|
||||
{texture_spritesheet, texture_spritesheet_len},
|
||||
{texture_trigger, texture_trigger_len},
|
||||
{texture_rect_show, texture_rect_show_len},
|
||||
{texture_rect_hide, texture_rect_hide_len},
|
||||
{texture_arrow_up, texture_arrow_up_len},
|
||||
{texture_arrow_down, texture_arrow_down_len},
|
||||
};
|
@ -1,4 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#define RESOURCE_SHADER_VERTEX_TEXTURE_QUAD "res/shader/texture_quad.vs"
|
||||
#define RESOURCE_SHADER_FRAGMENT_TEXTURE_QUAD "res/shader/texture_quad.fs"
|
205
src/STRINGS.h
205
src/STRINGS.h
@ -1,13 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#define STRING_UNDEFINED "undefined"
|
||||
#define STRING_EMPTY ""
|
||||
|
||||
#define STRING_WINDOW_TITLE "Anm2Ed"
|
||||
#define STRING_WINDOW_TITLE_EDITING "Anm2Ed (%s)"
|
||||
|
||||
#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: %s\n%s"
|
||||
#define STRING_ERROR_TEXTURE_INIT "[ERROR] Could not initialize texture: %s (%s)\n"
|
||||
#define STRING_ERROR_ANM2_INIT "[ERROR] Could not initialize anm2: %s (%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_INFO_INIT "[INFO] Initializing\n"
|
||||
#define STRING_INFO_QUIT "[INFO] Exited\n"
|
||||
@ -16,11 +21,201 @@
|
||||
#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: %s & %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_INIT "[INFO] Initialized anm2: %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_IMGUI_INIT "[INFO] Initialized Dear Imgui\n"
|
||||
#define STRING_INFO_IMGUI_FREE "[INFO] Freed Dear Imgui\n"
|
||||
|
||||
#define STRING_DIALOG_ANM2_READ "Select .anm2 file to read..."
|
||||
#define STRING_DIALOG_ANM2_WRITE "Select .anm2 file to write to..."
|
||||
#define STRING_DIALOG_ANM2_FILTER "Anm2 Files (*.anm2)"
|
||||
#define STRING_DIALOG_ANM2_FILTER_WILDCARD "*.anm2"
|
||||
#define STRING_DIALOG_ALL_FILTER "All Files (*.*)"
|
||||
#define STRING_DIALOG_ALL_FILTER_WILDCARD "*"
|
||||
|
||||
#define STRING_ANM2_CREATED_BY_DEFAULT "Unknown"
|
||||
#define STRING_ANM2_NEW_ANIMATION "New Animation"
|
||||
#define STRING_ANM2_NEW_LAYER "New Layer"
|
||||
#define STRING_ANM2_NEW_NULL "New Null"
|
||||
#define STRING_ANM2_NEW_EVENT "New Event"
|
||||
#define STRING_ANM2_ROOT "Root"
|
||||
|
||||
#define STRING_IMGUI_WINDOW "Window"
|
||||
#define STRING_IMGUI_DOCKSPACE "Dockspace"
|
||||
#define STRING_IMGUI_TASKBAR "Taskbar"
|
||||
#define STRING_IMGUI_TASKBAR_FILE "File"
|
||||
|
||||
#define STRING_IMGUI_FILE_MENU "File Menu"
|
||||
#define STRING_IMGUI_FILE_NEW "New"
|
||||
#define STRING_IMGUI_FILE_OPEN "Open"
|
||||
#define STRING_IMGUI_FILE_SAVE "Save"
|
||||
#define STRING_IMGUI_FILE_SAVE_AS "Save As"
|
||||
|
||||
#define STRING_IMGUI_PROPERTIES "Properties"
|
||||
#define STRING_IMGUI_PROPERTIES_FPS "FPS"
|
||||
#define STRING_IMGUI_PROPERTIES_FPS_LABEL "##FPS"
|
||||
#define STRING_IMGUI_PROPERTIES_CREATED_BY "Created by:"
|
||||
#define STRING_IMGUI_PROPERTIES_CREATED_BY_LABEL "##Created By"
|
||||
#define STRING_IMGUI_PROPERTIES_CREATED_ON "Created on: %s"
|
||||
#define STRING_IMGUI_PROPERTIES_VERSION "Version: %i"
|
||||
|
||||
#define STRING_IMGUI_ANIMATIONS "Animations"
|
||||
#define STRING_IMGUI_ANIMATIONS_ANIMATION_LABEL "##Animation"
|
||||
#define STRING_IMGUI_ANIMATIONS_ADD "Add"
|
||||
#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_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_SPRITESHEETS "Spritesheets"
|
||||
#define STRING_IMGUI_SPRITESHEETS_ADD "Add"
|
||||
#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_FRAME_PROPERTIES "Frame Properties"
|
||||
#define STRING_IMGUI_FRAME_PROPERTIES_CROP_POSITION "Crop Position"
|
||||
#define STRING_IMGUI_FRAME_PROPERTIES_CROP_SIZE "Crop Size"
|
||||
#define STRING_IMGUI_FRAME_PROPERTIES_POSITION "Position"
|
||||
#define STRING_IMGUI_FRAME_PROPERTIES_PIVOT "Pivot"
|
||||
#define STRING_IMGUI_FRAME_PROPERTIES_SCALE "Scale"
|
||||
#define STRING_IMGUI_FRAME_PROPERTIES_ROTATION "Rotation"
|
||||
#define STRING_IMGUI_FRAME_PROPERTIES_VISIBLE "Visible"
|
||||
#define STRING_IMGUI_FRAME_PROPERTIES_INTERPOLATED "Interpolated"
|
||||
#define STRING_IMGUI_FRAME_PROPERTIES_DURATION "Duration"
|
||||
#define STRING_IMGUI_FRAME_PROPERTIES_TINT "Tint"
|
||||
#define STRING_IMGUI_FRAME_PROPERTIES_COLOR_OFFSET "Color Offset"
|
||||
|
||||
#define STRING_IMGUI_ANIMATION_PREVIEW "Animation Preview"
|
||||
#define STRING_IMGUI_ANIMATION_PREVIEW_SETTINGS "##Animation Preview Settings"
|
||||
#define STRING_IMGUI_ANIMATION_PREVIEW_GRID_SETTINGS "##Grid Settings"
|
||||
#define STRING_IMGUI_ANIMATION_PREVIEW_GRID "Grid"
|
||||
#define STRING_IMGUI_ANIMATION_PREVIEW_GRID_SIZE "##Grid Size"
|
||||
#define STRING_IMGUI_ANIMATION_PREVIEW_GRID_COLOR "Color"
|
||||
#define STRING_IMGUI_ANIMATION_PREVIEW_ZOOM_SETTINGS "##Zoom Settings"
|
||||
#define STRING_IMGUI_ANIMATION_PREVIEW_ZOOM "Zoom"
|
||||
#define STRING_IMGUI_ANIMATION_PREVIEW_BACKGROUND_SETTINGS "##Background Settings"
|
||||
#define STRING_IMGUI_ANIMATION_PREVIEW_BACKGROUND_COLOR "Background Color"
|
||||
|
||||
#define STRING_IMGUI_SPRITESHEET_EDITOR "Spritesheet Editor"
|
||||
|
||||
#define STRING_IMGUI_TIMELINE "Timeline"
|
||||
#define STRING_IMGUI_TIMELINE_ELEMENT_SHIFT_ABOVE "Shift Above"
|
||||
#define STRING_IMGUI_TIMELINE_ELEMENT_SHIFT_BELOW "Shift Below"
|
||||
#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_ELEMENT_SPRITESHEET_ID_LABEL "##Timeline Element Spritesheet ID"
|
||||
#define STRING_IMGUI_TIMELINE_ELEMENT_NAME_LABEL "##Timeline Element Name"
|
||||
#define STRING_IMGUI_TIMELINE_TRIGGERS "Triggers"
|
||||
#define STRING_IMGUI_TIMELINE_ANIMATION_LABEL "##Timeline Animation"
|
||||
#define STRING_IMGUI_TIMELINE_ELEMENT_SHIFT_ARROWS_LABEL "##Timeline Shift Arrows"
|
||||
#define STRING_IMGUI_TIMELINE_ANIMATIONS "Animations"
|
||||
#define STRING_IMGUI_TIMELINE_PLAY "|> Play"
|
||||
#define STRING_IMGUI_TIMELINE_PAUSE "|| Pause"
|
||||
#define STRING_IMGUI_TIMELINE_ADD_FRAME "+ Add Frame"
|
||||
#define STRING_IMGUI_TIMELINE_REMOVE_FRAME "- Remove Frame"
|
||||
#define STRING_IMGUI_TIMELINE_FIT_ANIMATION_LENGTH "= Fit Animation Length"
|
||||
#define STRING_IMGUI_TIMELINE_ANIMATION LENGTH "Animation Length:"
|
||||
#define STRING_IMGUI_TIMELINE_VISIBLE "Visible"
|
||||
#define STRING_IMGUI_TIMELINE_LAYER "Layer"
|
||||
#define STRING_IMGUI_TIMELINE_NULL "Null"
|
||||
#define STRING_IMGUI_TIMELINE_RECT "Rect"
|
||||
#define STRING_IMGUI_TIMELINE_ELEMENTS "Elements"
|
||||
#define STRING_IMGUI_TIMELINE_ELEMENT_ADD "Add"
|
||||
#define STRING_IMGUI_TIMELINE_ELEMENT_ADD_MENU "Element Add Menu"
|
||||
#define STRING_IMGUI_TIMELINE_ELEMENT_ADD_MENU_LAYER "Add Layer..."
|
||||
#define STRING_IMGUI_TIMELINE_ELEMENT_ADD_MENU_NULL "Add Null..."
|
||||
#define STRING_IMGUI_TIMELINE_ELEMENT_REMOVE "Remove"
|
||||
|
||||
#define STRING_IMGUI_TOOLTIP_ANIMATIONS_SELECT "Select the animation to edit.\nYou can also click the name to edit it."
|
||||
#define STRING_IMGUI_TOOLTIP_ANIMATIONS_ADD "Add a new animation."
|
||||
#define STRING_IMGUI_TOOLTIP_ANIMATIONS_REMOVE "Removes the selected animation."
|
||||
#define STRING_IMGUI_TOOLTIP_ANIMATIONS_DUPLICATE "Duplicates the selected animation."
|
||||
#define STRING_IMGUI_TOOLTIP_ANIMATIONS_SET_AS_DEFAULT "Sets the selected animation as the default.\nDefault animations are marked with \"(*)\"."
|
||||
#define STRING_IMGUI_TOOLTIP_EVENTS_SELECT "Set the event for the trigger, or rename it."
|
||||
#define STRING_IMGUI_TOOLTIP_EVENTS_ADD "Add a new event."
|
||||
#define STRING_IMGUI_TOOLTIP_EVENTS_REMOVE "Removes the selected event."
|
||||
#define STRING_IMGUI_TOOLTIP_SPRITESHEETS_ADD "Opens the file dialog to load in a new sprite."
|
||||
#define STRING_IMGUI_TOOLTIP_SPRITESHEETS_REMOVE "Removes the selected spritesheet."
|
||||
#define STRING_IMGUI_TOOLTIP_SPRITESHEETS_RELOAD "Reloads the selected spritesheet."
|
||||
#define STRING_IMGUI_TOOLTIP_SPRITESHEETS_REPLACE "Replaces the selected spritesheet; opens up the file dialog."
|
||||
#define STRING_IMGUI_TOOLTIP_PROPERTIES_FPS "Change the FPS of the animation."
|
||||
#define STRING_IMGUI_TOOLTIP_PROPERTIES_CREATED_BY "Change the author of the animation."
|
||||
#define STRING_IMGUI_TOOLTIP_PROPERTIES_CREATED_ON_NOW "Set the date of creation to the current system time."
|
||||
#define STRING_IMGUI_TOOLTIP_FRAME_PROPERTIES_POSITION "Change the position of the frame."
|
||||
#define STRING_IMGUI_TOOLTIP_FRAME_PROPERTIES_CROP_POSITION "Change the crop position of the frame."
|
||||
#define STRING_IMGUI_TOOLTIP_FRAME_PROPERTIES_CROP_SIZE "Change the crop size of the frame."
|
||||
#define STRING_IMGUI_TOOLTIP_FRAME_PROPERTIES_PIVOT "Change the pivot of the frame."
|
||||
#define STRING_IMGUI_TOOLTIP_FRAME_PROPERTIES_SCALE "Change the scale of the frame."
|
||||
#define STRING_IMGUI_TOOLTIP_FRAME_PROPERTIES_ROTATION "Change the rotation of the frame."
|
||||
#define STRING_IMGUI_TOOLTIP_FRAME_PROPERTIES_DURATION "Change the duration of the frame."
|
||||
#define STRING_IMGUI_TOOLTIP_FRAME_PROPERTIES_TINT "Change the tint of the frame."
|
||||
#define STRING_IMGUI_TOOLTIP_FRAME_PROPERTIES_COLOR_OFFSET "Change the color offset of the frame."
|
||||
#define STRING_IMGUI_TOOLTIP_FRAME_PROPERTIES_VISIBLE "Toggles the visibility of the frame."
|
||||
#define STRING_IMGUI_TOOLTIP_FRAME_PROPERTIES_INTERPOLATED "Toggles the interpolation of the frame.\nBetween keyframes, will transform the values in the in-betweens to be smooth."
|
||||
#define STRING_IMGUI_TOOLTIP_TIMELINE_ELEMENT_ADD "Add a layer or null timeline element."
|
||||
#define STRING_IMGUI_TOOLTIP_TIMELINE_ELEMENT_NAME "Click to rename the element."
|
||||
#define STRING_IMGUI_TOOLTIP_TIMELINE_ELEMENT_SPRITESHEET "Click to change the spritesheet the layer is using."
|
||||
#define STRING_IMGUI_TOOLTIP_TIMELINE_ELEMENT_REMOVE "Remove a timeline element."
|
||||
#define STRING_IMGUI_TOOLTIP_TIMELINE_ELEMENT_SHIFT_UP "Shift this timeline element above.\nElements with higher indices will display further behind."
|
||||
#define STRING_IMGUI_TOOLTIP_TIMELINE_ELEMENT_SHIFT_DOWN "Shift this timeline element below.\nElements with lower indices will display further in front."
|
||||
#define STRING_IMGUI_TOOLTIP_TIMELINE_ELEMENT_VISIBLE "Toggle visibility for this element."
|
||||
#define STRING_IMGUI_TOOLTIP_TIMELINE_ELEMENT_RECT "Toggle visibility for a rectangle around the null."
|
||||
#define STRING_IMGUI_TOOLTIP_TIMELINE_ELEMENT_ROOT "This is the Root element."
|
||||
#define STRING_IMGUI_TOOLTIP_TIMELINE_ELEMENT_LAYER "This is a Layer element.\nThese are the main graphical animation elements.\nClick to rename."
|
||||
#define STRING_IMGUI_TOOLTIP_TIMELINE_ELEMENT_NULL "This is a Null element.\nThese are invisible elements where a game engine may have access to them for additional effects.\nClick to rename."
|
||||
#define STRING_IMGUI_TOOLTIP_TIMELINE_ELEMENT_TRIGGERS "This is the animation's Triggers.\nTriggers are special activations; each is bound to an Event."
|
||||
#define STRING_IMGUI_TOOLTIP_TIMELINE_PLAY "Plays the animation."
|
||||
#define STRING_IMGUI_TOOLTIP_TIMELINE_PAUSE "Pauses the animation."
|
||||
#define STRING_IMGUI_TOOLTIP_ANIMATION_PREVIEW_GRID "Toggles grid visibility on the animation preview."
|
||||
#define STRING_IMGUI_TOOLTIP_ANIMATION_PREVIEW_GRID_COLOR "Changes the animation preview grid color."
|
||||
#define STRING_IMGUI_TOOLTIP_ANIMATION_PREVIEW_GRID_SIZE "Changes the animation preview grid size (number of rows/columns)."
|
||||
#define STRING_IMGUI_TOOLTIP_ANIMATION_PREVIEW_ZOOM "Changes the animation preview zoom level."
|
||||
#define STRING_IMGUI_TOOLTIP_ANIMATION_PREVIEW_BACKGROUND_COLOR "Changes the background color of the animation preview."
|
||||
|
||||
#define STRING_OPENGL_VERSION "#version 330"
|
||||
|
||||
#define SHADER_VERTEX "#version 330 core\n" \
|
||||
"in vec2 l_position;\n" \
|
||||
"in vec2 l_uv;\n" \
|
||||
"\n" \
|
||||
"uniform mat3 u_view;\n" \
|
||||
"uniform mat3 u_projection;\n" \
|
||||
"uniform mat3 u_model;\n" \
|
||||
"\n" \
|
||||
"out vec2 o_uv;\n" \
|
||||
"\n" \
|
||||
"void main()\n" \
|
||||
"{\n" \
|
||||
" gl_Position = vec4(u_projection * u_view * u_model * vec3(l_position, 1.0), 1.0);\n" \
|
||||
" o_uv = l_uv;\n" \
|
||||
"}"
|
||||
|
||||
#define SHADER_FRAGMENT "#version 330 core\n" \
|
||||
"uniform vec4 u_tint;\n" \
|
||||
"uniform vec4 u_color_offset;\n" \
|
||||
"uniform sampler2D u_texture;\n" \
|
||||
"\n" \
|
||||
"in vec2 i_uv;\n" \
|
||||
"\n" \
|
||||
"out vec4 FragColor;\n" \
|
||||
"\n" \
|
||||
"void main()\n" \
|
||||
"{\n" \
|
||||
" FragColor = texture(u_texture, i_uv) * u_tint;\n" \
|
||||
" FragColor.rgb += u_color_offset.rgb;\n" \
|
||||
"\n" \
|
||||
" if (FragColor.a == 0.0) discard;\n" \
|
||||
"}\n"
|
||||
|
716
src/anm2.cpp
716
src/anm2.cpp
@ -1,32 +1,722 @@
|
||||
#include "anm2.h"
|
||||
|
||||
using namespace tinyxml2;
|
||||
|
||||
/* Sets the anm2's date to the system's current date */
|
||||
void
|
||||
anm2_created_on_set(Anm2* self)
|
||||
{
|
||||
time_t currentTime;
|
||||
struct tm* local;
|
||||
char date[ANM2_STRING_MAX];
|
||||
|
||||
currentTime = time(NULL);
|
||||
local = localtime(¤tTime);
|
||||
|
||||
strftime(date, ANM2_STRING_MAX, "%d-%B-%Y %I:%M:%S %p", local);
|
||||
|
||||
strncpy(self->createdOn, date, ANM2_STRING_MAX);
|
||||
}
|
||||
|
||||
/* Serializes the anm2 struct into XML and exports it to the given path */
|
||||
bool
|
||||
anm2_init(Anm2* self, const char* path)
|
||||
anm2_serialize(Anm2* self, const char* path)
|
||||
{
|
||||
xml_document document;
|
||||
xml_parse_result result;
|
||||
XMLDocument document;
|
||||
XMLError error;
|
||||
|
||||
memset(self, '\0', sizeof(Anm2));
|
||||
XMLElement* animatedActorElement;
|
||||
XMLElement* infoElement;
|
||||
XMLElement* contentElement;
|
||||
XMLElement* spritesheetsElement;
|
||||
XMLElement* layersElement;
|
||||
XMLElement* nullsElement;
|
||||
XMLElement* eventsElement;
|
||||
XMLElement* animationsElement;
|
||||
|
||||
result = document.load_file(path);
|
||||
if (!self || !path)
|
||||
return false;
|
||||
|
||||
if (!result)
|
||||
/* Update creation date on first version */
|
||||
if (self->version == 0)
|
||||
anm2_created_on_set(self);
|
||||
|
||||
/* Increment anm2's version */
|
||||
self->version++;
|
||||
|
||||
/* Set the anm2's date to the system time */
|
||||
|
||||
/* AnimatedActor */
|
||||
animatedActorElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_ANIMATED_ACTOR]);
|
||||
document.InsertFirstChild(animatedActorElement);
|
||||
|
||||
/* 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 */
|
||||
animatedActorElement->InsertEndChild(infoElement);
|
||||
|
||||
/* Content */
|
||||
contentElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_CONTENT]);
|
||||
|
||||
/* Spritesheets */
|
||||
spritesheetsElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_SPRITESHEETS]);
|
||||
|
||||
for (auto & [id, spritesheet] : self->spritesheets)
|
||||
{
|
||||
printf(STRING_ERROR_ANM2_INIT, path, result.description());
|
||||
XMLElement* spritesheetElement;
|
||||
|
||||
/* 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 */
|
||||
spritesheetsElement->InsertEndChild(spritesheetElement);
|
||||
}
|
||||
|
||||
contentElement->InsertEndChild(spritesheetsElement);
|
||||
|
||||
/* Layers */
|
||||
layersElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_LAYERS]);
|
||||
|
||||
for (auto & [id, layer] : self->layers)
|
||||
{
|
||||
XMLElement* layerElement;
|
||||
|
||||
/* 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 */
|
||||
|
||||
layersElement->InsertEndChild(layerElement);
|
||||
}
|
||||
|
||||
contentElement->InsertEndChild(layersElement);
|
||||
|
||||
/* Nulls */
|
||||
nullsElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_NULLS]);
|
||||
|
||||
for (auto & [id, null] : self->nulls)
|
||||
{
|
||||
XMLElement* nullElement;
|
||||
|
||||
/* 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 */
|
||||
|
||||
/* special case; only serialize if this is true */
|
||||
if (null.isShowRect)
|
||||
nullElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_SHOW_RECT], null.isShowRect); /* ShowRect */
|
||||
nullsElement->InsertEndChild(nullElement);
|
||||
}
|
||||
|
||||
contentElement->InsertEndChild(nullsElement);
|
||||
|
||||
/* Events */
|
||||
eventsElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_EVENTS]);
|
||||
|
||||
for (auto & [id, event] : self->events)
|
||||
{
|
||||
XMLElement* eventElement;
|
||||
|
||||
/* 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 */
|
||||
eventsElement->InsertEndChild(eventElement);
|
||||
}
|
||||
|
||||
contentElement->InsertEndChild(eventsElement);
|
||||
|
||||
animatedActorElement->InsertEndChild(contentElement);
|
||||
|
||||
/* Animations */
|
||||
animationsElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_ANIMATIONS]);
|
||||
animationsElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_DEFAULT_ANIMATION], self->defaultAnimation);
|
||||
|
||||
for (auto & [id, animation] : self->animations)
|
||||
{
|
||||
XMLElement* animationElement;
|
||||
XMLElement* rootAnimationElement;
|
||||
XMLElement* layerAnimationsElement;
|
||||
XMLElement* nullAnimationsElement;
|
||||
XMLElement* triggersElement;
|
||||
|
||||
/* 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 */
|
||||
|
||||
/* RootAnimation */
|
||||
rootAnimationElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_ROOT_ANIMATION]);
|
||||
|
||||
for (auto & frame : animation.rootAnimation.frames)
|
||||
{
|
||||
XMLElement* frameElement;
|
||||
|
||||
/* 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], frame.tintRGBA.r); /* RedTint */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_GREEN_TINT], frame.tintRGBA.g); /* GreenTint */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_BLUE_TINT], frame.tintRGBA.b); /* BlueTint */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_ALPHA_TINT], frame.tintRGBA.a); /* AlphaTint */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_RED_OFFSET], frame.offsetRGB.r); /* RedOffset */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_GREEN_OFFSET], frame.offsetRGB.g); /* GreenOffset */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_BLUE_OFFSET], 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 */
|
||||
layerAnimationsElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_LAYER_ANIMATIONS]);
|
||||
|
||||
for (const auto & [layerID, layerAnimation] : animation.layerAnimations)
|
||||
{
|
||||
XMLElement* layerAnimationElement;
|
||||
|
||||
/* 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 */
|
||||
|
||||
for (auto & frame : layerAnimation.frames)
|
||||
{
|
||||
XMLElement* frameElement;
|
||||
|
||||
/* 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_DELAY], frame.delay); /* Delay */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_VISIBLE], frame.isVisible); /* Visible */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_RED_TINT], frame.tintRGBA.r); /* RedTint */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_GREEN_TINT], frame.tintRGBA.g); /* GreenTint */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_BLUE_TINT], frame.tintRGBA.b); /* BlueTint */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_ALPHA_TINT], frame.tintRGBA.a); /* AlphaTint */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_RED_OFFSET], frame.offsetRGB.r); /* RedOffset */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_GREEN_OFFSET], frame.offsetRGB.g); /* GreenOffset */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_BLUE_OFFSET], 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);
|
||||
}
|
||||
|
||||
layerAnimationsElement->InsertEndChild(layerAnimationElement);
|
||||
}
|
||||
|
||||
animationElement->InsertEndChild(layerAnimationsElement);
|
||||
|
||||
/* NullAnimations */
|
||||
nullAnimationsElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_NULL_ANIMATIONS]);
|
||||
|
||||
for (const auto & [nullID, nullAnimation] : animation.nullAnimations)
|
||||
{
|
||||
XMLElement* nullAnimationElement;
|
||||
|
||||
/* 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 */
|
||||
|
||||
for (auto & frame : nullAnimation.frames)
|
||||
{
|
||||
XMLElement* frameElement;
|
||||
|
||||
/* 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], frame.tintRGBA.r); /* RedTint */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_GREEN_TINT], frame.tintRGBA.g); /* GreenTint */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_BLUE_TINT], frame.tintRGBA.b); /* BlueTint */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_ALPHA_TINT], frame.tintRGBA.a); /* AlphaTint */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_RED_OFFSET], frame.offsetRGB.r); /* RedOffset */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_GREEN_OFFSET], frame.offsetRGB.g); /* GreenOffset */
|
||||
frameElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_BLUE_OFFSET], 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);
|
||||
}
|
||||
|
||||
nullAnimationsElement->InsertEndChild(nullAnimationElement);
|
||||
}
|
||||
|
||||
animationElement->InsertEndChild(nullAnimationsElement);
|
||||
|
||||
/* Triggers */
|
||||
triggersElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_TRIGGERS]);
|
||||
|
||||
for (auto & trigger : animation.triggers.items)
|
||||
{
|
||||
XMLElement* triggerElement;
|
||||
|
||||
/* Trigger */
|
||||
triggerElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_TRIGGER]);
|
||||
triggerElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_EVENT_ID], trigger.eventID); /* EventID */
|
||||
triggerElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_AT_FRAME], trigger.atFrame); /* AtFrame */
|
||||
triggersElement->InsertEndChild(triggerElement);
|
||||
}
|
||||
|
||||
animationElement->InsertEndChild(triggersElement);
|
||||
|
||||
animationsElement->InsertEndChild(animationElement);
|
||||
}
|
||||
|
||||
animatedActorElement->InsertEndChild(animationsElement);
|
||||
|
||||
error = document.SaveFile(path);
|
||||
|
||||
if (error != XML_SUCCESS)
|
||||
{
|
||||
printf(STRING_ERROR_ANM2_WRITE, path, document.ErrorStr());
|
||||
return false;
|
||||
}
|
||||
|
||||
for (pugi::xml_node node : document.children())
|
||||
printf("%s\n", node.name());
|
||||
|
||||
printf(STRING_INFO_ANM2_INIT, path);
|
||||
printf(STRING_INFO_ANM2_WRITE, path);
|
||||
strncpy(self->path, path, PATH_MAX - 1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
anm2_free(Anm2* self)
|
||||
/* Loads the .anm2 file and deserializes it into the struct equivalent */
|
||||
bool
|
||||
anm2_deserialize(Anm2* self, const char* path)
|
||||
{
|
||||
XMLDocument document;
|
||||
XMLError error;
|
||||
const XMLElement* element;
|
||||
const XMLElement* root;
|
||||
Anm2Spritesheet* lastSpritesheet = NULL;
|
||||
Anm2Layer* lastLayer = NULL;
|
||||
Anm2Null* lastNull = NULL;
|
||||
Anm2Event* lastEvent = NULL;
|
||||
Anm2Animation* lastAnimation = NULL;
|
||||
Anm2LayerAnimation* lastLayerAnimation = NULL;
|
||||
Anm2NullAnimation* lastNullAnimation = NULL;
|
||||
Anm2Frame* lastFrame = NULL;
|
||||
Anm2Trigger* lastTrigger = NULL;
|
||||
Anm2Element anm2Element = ANM2_ELEMENT_ANIMATED_ACTOR;
|
||||
Anm2Attribute anm2Attribute = ANM2_ATTRIBUTE_ID;
|
||||
Anm2AnimationType animationType = ANM2_ROOT_ANIMATION;
|
||||
Anm2Null tempNull;
|
||||
Anm2Layer tempLayer;
|
||||
Anm2Spritesheet tempSpritesheet;
|
||||
Anm2Event tempEvent;
|
||||
|
||||
*self = Anm2{};
|
||||
|
||||
error = document.LoadFile(path);
|
||||
|
||||
if (error != XML_SUCCESS)
|
||||
{
|
||||
printf(STRING_ERROR_ANM2_READ, path, document.ErrorStr());
|
||||
return false;
|
||||
}
|
||||
|
||||
strncpy(self->path, path, PATH_MAX - 1);
|
||||
|
||||
root = document.FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_ANIMATED_ACTOR]);
|
||||
element = root;
|
||||
|
||||
while (element)
|
||||
{
|
||||
const XMLAttribute* attribute;
|
||||
const XMLElement* child;
|
||||
s32 id;
|
||||
|
||||
/* Elements */
|
||||
anm2Element = anm2_element_from_string(element->Name());
|
||||
|
||||
switch (anm2Element)
|
||||
{
|
||||
case ANM2_ELEMENT_SPRITESHEET:
|
||||
lastSpritesheet = &tempSpritesheet;
|
||||
break;
|
||||
case ANM2_ELEMENT_LAYER:
|
||||
lastLayer = &tempLayer;
|
||||
break;
|
||||
case ANM2_ELEMENT_NULL:
|
||||
lastNull = &tempNull;
|
||||
break;
|
||||
case ANM2_ELEMENT_EVENT:
|
||||
lastEvent = &tempEvent;
|
||||
break;
|
||||
case ANM2_ELEMENT_ANIMATION:
|
||||
id = map_next_id_get(self->animations);
|
||||
self->animations[id] = Anm2Animation{};
|
||||
lastAnimation = &self->animations[id];
|
||||
break;
|
||||
case ANM2_ELEMENT_ROOT_ANIMATION:
|
||||
animationType = ANM2_ROOT_ANIMATION;
|
||||
break;
|
||||
case ANM2_ELEMENT_LAYER_ANIMATION:
|
||||
animationType = ANM2_LAYER_ANIMATION;
|
||||
lastLayerAnimation = NULL;
|
||||
break;
|
||||
case ANM2_ELEMENT_NULL_ANIMATION:
|
||||
animationType = ANM2_NULL_ANIMATION;
|
||||
lastNullAnimation = NULL;
|
||||
break;
|
||||
case ANM2_ELEMENT_FRAME:
|
||||
switch (animationType)
|
||||
{
|
||||
case ANM2_ROOT_ANIMATION:
|
||||
lastAnimation->rootAnimation.frames.push_back(Anm2Frame{});
|
||||
lastFrame = &lastAnimation->rootAnimation.frames.back();
|
||||
break;
|
||||
case ANM2_LAYER_ANIMATION:
|
||||
if (!lastLayerAnimation) break;
|
||||
lastLayerAnimation->frames.push_back(Anm2Frame{});
|
||||
lastFrame = &lastLayerAnimation->frames.back();
|
||||
break;
|
||||
case ANM2_NULL_ANIMATION:
|
||||
if (!lastNullAnimation) break;
|
||||
lastNullAnimation->frames.push_back(Anm2Frame{});
|
||||
lastFrame = &lastNullAnimation->frames.back();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ANM2_ELEMENT_TRIGGER:
|
||||
lastAnimation->triggers.items.push_back(Anm2Trigger{});
|
||||
lastTrigger = &lastAnimation->triggers.items.back();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/* Attributes */
|
||||
attribute = element->FirstAttribute();
|
||||
|
||||
while (attribute)
|
||||
{
|
||||
anm2Attribute = anm2_attribute_from_string(attribute->Name());
|
||||
|
||||
switch (anm2Attribute)
|
||||
{
|
||||
case ANM2_ATTRIBUTE_CREATED_BY:
|
||||
strncpy(self->createdBy, attribute->Value(), ANM2_STRING_MAX - 1);
|
||||
break;
|
||||
case ANM2_ATTRIBUTE_CREATED_ON:
|
||||
strncpy(self->createdOn, attribute->Value(), ANM2_STRING_MAX - 1);
|
||||
break;
|
||||
case ANM2_ATTRIBUTE_VERSION:
|
||||
self->version = atoi(attribute->Value());
|
||||
break;
|
||||
case ANM2_ATTRIBUTE_FPS:
|
||||
self->fps = atoi(attribute->Value());
|
||||
break;
|
||||
case ANM2_ATTRIBUTE_ID:
|
||||
id = atoi(attribute->Value());
|
||||
switch (anm2Element)
|
||||
{
|
||||
case ANM2_ELEMENT_SPRITESHEET:
|
||||
self->spritesheets[id] = tempSpritesheet;
|
||||
lastSpritesheet = &self->spritesheets[id];
|
||||
break;
|
||||
case ANM2_ELEMENT_LAYER:
|
||||
self->layers[id] = tempLayer;
|
||||
lastLayer = &self->layers[id];
|
||||
break;
|
||||
case ANM2_ELEMENT_NULL:
|
||||
self->nulls[id] = tempNull;
|
||||
lastNull = &self->nulls[id];
|
||||
break;
|
||||
case ANM2_ELEMENT_EVENT:
|
||||
self->events[id] = tempEvent;
|
||||
lastEvent = &self->events[id];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ANM2_ATTRIBUTE_PATH:
|
||||
strncpy(lastSpritesheet->path, attribute->Value(), ANM2_STRING_MAX - 1);
|
||||
break;
|
||||
case ANM2_ATTRIBUTE_NAME:
|
||||
switch (anm2Element)
|
||||
{
|
||||
case ANM2_ELEMENT_LAYER:
|
||||
strncpy(lastLayer->name, attribute->Value(), ANM2_STRING_MAX - 1);
|
||||
break;
|
||||
case ANM2_ELEMENT_NULL:
|
||||
strncpy(lastNull->name, attribute->Value(), ANM2_STRING_MAX - 1);
|
||||
break;
|
||||
case ANM2_ELEMENT_ANIMATION:
|
||||
strncpy(lastAnimation->name, attribute->Value(), ANM2_STRING_MAX - 1);
|
||||
break;
|
||||
case ANM2_ELEMENT_EVENT:
|
||||
strncpy(lastEvent->name, attribute->Value(), ANM2_STRING_MAX - 1);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ANM2_ATTRIBUTE_SPRITESHEET_ID:
|
||||
lastLayer->spritesheetID = atoi(attribute->Value());
|
||||
break;
|
||||
case ANM2_ATTRIBUTE_SHOW_RECT:
|
||||
switch (anm2Element)
|
||||
{
|
||||
case ANM2_ELEMENT_NULL:
|
||||
lastNull->isShowRect = string_to_bool(attribute->Value());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ANM2_ATTRIBUTE_DEFAULT_ANIMATION:
|
||||
strncpy(self->defaultAnimation, attribute->Value(), ANM2_STRING_MAX - 1);
|
||||
break;
|
||||
case ANM2_ATTRIBUTE_FRAME_NUM:
|
||||
lastAnimation->frameNum = atoi(attribute->Value());
|
||||
break;
|
||||
case ANM2_ATTRIBUTE_LOOP:
|
||||
lastAnimation->isLoop = string_to_bool(attribute->Value());
|
||||
break;
|
||||
case ANM2_ATTRIBUTE_X_POSITION:
|
||||
lastFrame->position.x = atof(attribute->Value());
|
||||
break;
|
||||
case ANM2_ATTRIBUTE_Y_POSITION:
|
||||
lastFrame->position.y = atof(attribute->Value());
|
||||
break;
|
||||
case ANM2_ATTRIBUTE_X_PIVOT:
|
||||
lastFrame->pivot.x = atof(attribute->Value());
|
||||
break;
|
||||
case ANM2_ATTRIBUTE_Y_PIVOT:
|
||||
lastFrame->pivot.y = atof(attribute->Value());
|
||||
break;
|
||||
case ANM2_ATTRIBUTE_X_CROP:
|
||||
lastFrame->crop.x = atof(attribute->Value());
|
||||
break;
|
||||
case ANM2_ATTRIBUTE_Y_CROP:
|
||||
lastFrame->crop.y = atof(attribute->Value());
|
||||
break;
|
||||
case ANM2_ATTRIBUTE_WIDTH:
|
||||
lastFrame->size.x = atof(attribute->Value());
|
||||
break;
|
||||
case ANM2_ATTRIBUTE_HEIGHT:
|
||||
lastFrame->size.y = atof(attribute->Value());
|
||||
break;
|
||||
case ANM2_ATTRIBUTE_X_SCALE:
|
||||
lastFrame->scale.x = atof(attribute->Value());
|
||||
break;
|
||||
case ANM2_ATTRIBUTE_Y_SCALE:
|
||||
lastFrame->scale.y = atof(attribute->Value());
|
||||
break;
|
||||
case ANM2_ATTRIBUTE_DELAY:
|
||||
lastFrame->delay = atoi(attribute->Value());
|
||||
break;
|
||||
case ANM2_ATTRIBUTE_VISIBLE:
|
||||
switch (anm2Element)
|
||||
{
|
||||
case ANM2_ELEMENT_FRAME:
|
||||
lastFrame->isVisible = string_to_bool(attribute->Value());
|
||||
break;
|
||||
case ANM2_LAYER_ANIMATION:
|
||||
lastLayerAnimation->isVisible = string_to_bool(attribute->Value());
|
||||
break;
|
||||
case ANM2_NULL_ANIMATION:
|
||||
lastNullAnimation->isVisible = string_to_bool(attribute->Value());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ANM2_ATTRIBUTE_RED_TINT:
|
||||
lastFrame->tintRGBA.r = atof(attribute->Value());
|
||||
break;
|
||||
case ANM2_ATTRIBUTE_GREEN_TINT:
|
||||
lastFrame->tintRGBA.g = atof(attribute->Value());
|
||||
break;
|
||||
case ANM2_ATTRIBUTE_BLUE_TINT:
|
||||
lastFrame->tintRGBA.b = atof(attribute->Value());
|
||||
break;
|
||||
case ANM2_ATTRIBUTE_ALPHA_TINT:
|
||||
lastFrame->tintRGBA.a = atof(attribute->Value());
|
||||
break;
|
||||
case ANM2_ATTRIBUTE_RED_OFFSET:
|
||||
lastFrame->offsetRGB.r = atof(attribute->Value());
|
||||
break;
|
||||
case ANM2_ATTRIBUTE_GREEN_OFFSET:
|
||||
lastFrame->offsetRGB.g = atof(attribute->Value());
|
||||
break;
|
||||
case ANM2_ATTRIBUTE_BLUE_OFFSET:
|
||||
lastFrame->offsetRGB.b = atof(attribute->Value());
|
||||
break;
|
||||
case ANM2_ATTRIBUTE_ROTATION:
|
||||
lastFrame->rotation = atof(attribute->Value());
|
||||
break;
|
||||
case ANM2_ATTRIBUTE_INTERPOLATED:
|
||||
lastFrame->isInterpolated = string_to_bool(attribute->Value());
|
||||
break;
|
||||
case ANM2_ATTRIBUTE_LAYER_ID:
|
||||
id = atoi(attribute->Value());
|
||||
lastAnimation->layerAnimations[id] = Anm2LayerAnimation{};
|
||||
lastLayerAnimation = &lastAnimation->layerAnimations[id];
|
||||
break;
|
||||
case ANM2_ATTRIBUTE_NULL_ID:
|
||||
id = atoi(attribute->Value());
|
||||
lastAnimation->nullAnimations[id] = Anm2NullAnimation{};
|
||||
lastNullAnimation = &lastAnimation->nullAnimations[id];
|
||||
break;
|
||||
case ANM2_ATTRIBUTE_EVENT_ID:
|
||||
lastTrigger->eventID = atoi(attribute->Value());
|
||||
break;
|
||||
case ANM2_ATTRIBUTE_AT_FRAME:
|
||||
lastTrigger->atFrame = atoi(attribute->Value());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
attribute = attribute->Next();
|
||||
}
|
||||
|
||||
/* Iterate through children */
|
||||
child = element->FirstChildElement();
|
||||
|
||||
if (child)
|
||||
{
|
||||
element = child;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Iterate through siblings */
|
||||
while (element)
|
||||
{
|
||||
const XMLElement* next;
|
||||
|
||||
next = element->NextSiblingElement();
|
||||
|
||||
if (next)
|
||||
{
|
||||
element = next;
|
||||
break;
|
||||
}
|
||||
|
||||
/* If no siblings, return to parent. If no parent, end parsing */
|
||||
element = element->Parent() ? element->Parent()->ToElement() : NULL;
|
||||
}
|
||||
}
|
||||
|
||||
printf(STRING_INFO_ANM2_READ, path);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Adds a new layer to the anm2 */
|
||||
void
|
||||
anm2_layer_add(Anm2* self)
|
||||
{
|
||||
s32 id = map_next_id_get(self->layers);
|
||||
|
||||
self->layers[id] = Anm2Layer{};
|
||||
|
||||
for (auto & [animationID, animation] : self->animations)
|
||||
animation.layerAnimations[id] = Anm2LayerAnimation{};
|
||||
}
|
||||
|
||||
/* Removes a layer from the anm2 given the index/id */
|
||||
void
|
||||
anm2_layer_remove(Anm2* self, s32 id)
|
||||
{
|
||||
self->layers.erase(id);
|
||||
|
||||
for (auto& animationPair : self->animations)
|
||||
animationPair.second.layerAnimations.erase(id);
|
||||
}
|
||||
|
||||
/* Adds a new null to the anm2 */
|
||||
void
|
||||
anm2_null_add(Anm2* self)
|
||||
{
|
||||
s32 id = map_next_id_get(self->nulls);
|
||||
|
||||
self->nulls[id] = Anm2Null{};
|
||||
|
||||
for (auto & [animationID, animation] : self->animations)
|
||||
animation.nullAnimations[id] = Anm2NullAnimation{};
|
||||
}
|
||||
|
||||
/* Removes a null from the anm2 given the index/id */
|
||||
void
|
||||
anm2_null_remove(Anm2* self, s32 id)
|
||||
{
|
||||
self->nulls.erase(id);
|
||||
|
||||
for (auto& animationPair : self->animations)
|
||||
animationPair.second.nullAnimations.erase(id);
|
||||
}
|
||||
|
||||
/* Adds a new animation to the anm2, makes sure to keep the layeranimations/nullsanimation check */
|
||||
s32
|
||||
anm2_animation_add(Anm2* self)
|
||||
{
|
||||
s32 id = map_next_id_get(self->animations);
|
||||
Anm2Animation animation;
|
||||
|
||||
/* match layers */
|
||||
for (auto & [layerID, layer] : self->layers)
|
||||
animation.layerAnimations[layerID] = Anm2LayerAnimation{};
|
||||
|
||||
/* match nulls */
|
||||
for (auto & [nullID, null] : self->nulls)
|
||||
animation.nullAnimations[nullID] = Anm2NullAnimation{};
|
||||
|
||||
self->animations[id] = animation;
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
void
|
||||
anm2_animation_remove(Anm2* self, s32 id)
|
||||
{
|
||||
self->animations.erase(id);
|
||||
}
|
||||
|
||||
/* Makes an entirely new anm2 */
|
||||
void
|
||||
anm2_new(Anm2* self)
|
||||
{
|
||||
*self = Anm2{};
|
||||
anm2_created_on_set(self);
|
||||
}
|
405
src/anm2.h
405
src/anm2.h
@ -5,285 +5,216 @@
|
||||
#define ANM2_SCALE_CONVERT(x) ((f32)x / 100.0f)
|
||||
#define ANM2_TINT_CONVERT(x) ((f32)x / 255.0f)
|
||||
|
||||
#define ANM2_STRING_MAX 255
|
||||
#define ANM2_STRING_MAX 0xFF
|
||||
#define ANM2_STRING_FORMATTED_MAX 0xFFF
|
||||
#define ANM2_BUFFER_MAX 0xFFFFF
|
||||
#define ANM2_FPS_MIN 0
|
||||
#define ANM2_FPS_DEFAULT 30
|
||||
#define ANM2_FPS_MAX 60
|
||||
|
||||
/* Elements */
|
||||
#define STRING_ANM2_ELEMENT_ANIMATED_ACTOR "AnimatedActor"
|
||||
#define STRING_ANM2_ELEMENT_INFO "Info"
|
||||
#define STRING_ANM2_ELEMENT_CONTENT "Content"
|
||||
#define STRING_ANM2_ELEMENT_SPRITESHEETS "Spritesheets"
|
||||
#define STRING_ANM2_ELEMENT_SPRITESHEET "Spritesheet"
|
||||
#define STRING_ANM2_ELEMENT_LAYERS "Layers"
|
||||
#define STRING_ANM2_ELEMENT_LAYER "Layer"
|
||||
#define STRING_ANM2_ELEMENT_NULLS "Nulls"
|
||||
#define STRING_ANM2_ELEMENT_NULL "Null"
|
||||
#define STRING_ANM2_ELEMENT_EVENTS "Events"
|
||||
#define STRING_ANM2_ELEMENT_EVENT "Event"
|
||||
#define STRING_ANM2_ELEMENT_ANIMATIONS "Animations"
|
||||
#define STRING_ANM2_ELEMENT_ANIMATION "Animation"
|
||||
#define STRING_ANM2_ELEMENT_ROOT_ANIMATION "RootAnimation"
|
||||
#define STRING_ANM2_ELEMENT_FRAME "Frame"
|
||||
#define STRING_ANM2_ELEMENT_LAYER_ANIMATIONS "LayerAnimations"
|
||||
#define STRING_ANM2_ELEMENT_LAYER_ANIMATION "LayerAnimation"
|
||||
#define STRING_ANM2_ELEMENT_NULL_ANIMATIONS "NullAnimations"
|
||||
#define STRING_ANM2_ELEMENT_NULL_ANIMATION "NullAnimation"
|
||||
#define STRING_ANM2_ELEMENT_TRIGGERS "Triggers"
|
||||
#define STRING_ANM2_ELEMENT_TRIGGER "Trigger"
|
||||
#define ANM2_ELEMENT_LIST \
|
||||
X(ANIMATED_ACTOR, "AnimatedActor") \
|
||||
X(INFO, "Info") \
|
||||
X(CONTENT, "Content") \
|
||||
X(SPRITESHEETS, "Spritesheets") \
|
||||
X(SPRITESHEET, "Spritesheet") \
|
||||
X(LAYERS, "Layers") \
|
||||
X(LAYER, "Layer") \
|
||||
X(NULLS, "Nulls") \
|
||||
X(NULL, "Null") \
|
||||
X(EVENTS, "Events") \
|
||||
X(EVENT, "Event") \
|
||||
X(ANIMATIONS, "Animations") \
|
||||
X(ANIMATION, "Animation") \
|
||||
X(ROOT_ANIMATION, "RootAnimation") \
|
||||
X(FRAME, "Frame") \
|
||||
X(LAYER_ANIMATIONS, "LayerAnimations") \
|
||||
X(LAYER_ANIMATION, "LayerAnimation") \
|
||||
X(NULL_ANIMATIONS, "NullAnimations") \
|
||||
X(NULL_ANIMATION, "NullAnimation") \
|
||||
X(TRIGGERS, "Triggers") \
|
||||
X(TRIGGER, "Trigger")
|
||||
|
||||
/* Attributes */
|
||||
#define STRING_ANM2_ATTRIBUTE_CREATED_BY "CreatedBy"
|
||||
#define STRING_ANM2_ATTRIBUTE_CREATED_ON "CreatedOn"
|
||||
#define STRING_ANM2_ATTRIBUTE_FPS "Fps"
|
||||
#define STRING_ANM2_ATTRIBUTE_VERSION "Version"
|
||||
#define STRING_ANM2_ATTRIBUTE_ID "Id"
|
||||
#define STRING_ANM2_ATTRIBUTE_PATH "Path"
|
||||
#define STRING_ANM2_ATTRIBUTE_NAME "Name"
|
||||
#define STRING_ANM2_ATTRIBUTE_SPRITESHEET_ID "SpritesheetId"
|
||||
#define STRING_ANM2_ATTRIBUTE_SHOW_RECT "ShowRect"
|
||||
#define STRING_ANM2_ATTRIBUTE_DEFAULT_ANIMATION "DefaultAnimation"
|
||||
#define STRING_ANM2_ATTRIBUTE_FRAME_NUM "FrameNum"
|
||||
#define STRING_ANM2_ATTRIBUTE_LOOP "Loop"
|
||||
#define STRING_ANM2_ATTRIBUTE_X_POSITION "XPosition"
|
||||
#define STRING_ANM2_ATTRIBUTE_Y_POSITION "YPosition"
|
||||
#define STRING_ANM2_ATTRIBUTE_X_PIVOT "XPivot"
|
||||
#define STRING_ANM2_ATTRIBUTE_Y_PIVOT "YPivot"
|
||||
#define STRING_ANM2_ATTRIBUTE_X_CROP "XCrop"
|
||||
#define STRING_ANM2_ATTRIBUTE_Y_CROP "YCrop"
|
||||
#define STRING_ANM2_ATTRIBUTE_WIDTH "Width"
|
||||
#define STRING_ANM2_ATTRIBUTE_HEIGHT "Height"
|
||||
#define STRING_ANM2_ATTRIBUTE_X_SCALE "XScale"
|
||||
#define STRING_ANM2_ATTRIBUTE_Y_SCALE "YScale"
|
||||
#define STRING_ANM2_ATTRIBUTE_DELAY "Delay"
|
||||
#define STRING_ANM2_ATTRIBUTE_VISIBLE "Visible"
|
||||
#define STRING_ANM2_ATTRIBUTE_RED_TINT "RedTint"
|
||||
#define STRING_ANM2_ATTRIBUTE_GREEN_TINT "GreenTint"
|
||||
#define STRING_ANM2_ATTRIBUTE_BLUE_TINT "BlueTint"
|
||||
#define STRING_ANM2_ATTRIBUTE_ALPHA_TINT "AlphaTint"
|
||||
#define STRING_ANM2_ATTRIBUTE_RED_OFFSET "RedOffset"
|
||||
#define STRING_ANM2_ATTRIBUTE_GREEN_OFFSET "GreenOffset"
|
||||
#define STRING_ANM2_ATTRIBUTE_BLUE_OFFSET "BlueOffset"
|
||||
#define STRING_ANM2_ATTRIBUTE_ROTATION "Rotation"
|
||||
#define STRING_ANM2_ATTRIBUTE_INTERPOLATED "Interpolated"
|
||||
#define STRING_ANM2_ATTRIBUTE_LAYER_ID "LayerId"
|
||||
#define STRING_ANM2_ATTRIBUTE_NULL_ID "NullId"
|
||||
#define STRING_ANM2_ATTRIBUTE_EVENT_ID "EventId"
|
||||
#define STRING_ANM2_ATTRIBUTE_AT_FRAME "AtFrame"
|
||||
typedef enum {
|
||||
#define X(name, str) ANM2_ELEMENT_##name,
|
||||
ANM2_ELEMENT_LIST
|
||||
#undef X
|
||||
ANM2_ELEMENT_COUNT
|
||||
} Anm2Element;
|
||||
|
||||
#define ANM2_ELEMENT_COUNT (ANM2_ELEMENT_TRIGGER + 1)
|
||||
enum Anm2Element
|
||||
{
|
||||
ANM2_ELEMENT_ANIMATED_ACTOR,
|
||||
ANM2_ELEMENT_INFO,
|
||||
ANM2_ELEMENT_CONTENT,
|
||||
ANM2_ELEMENT_SPRITESHEETS,
|
||||
ANM2_ELEMENT_SPRITESHEET,
|
||||
ANM2_ELEMENT_LAYERS,
|
||||
ANM2_ELEMENT_LAYER,
|
||||
ANM2_ELEMENT_NULLS,
|
||||
ANM2_ELEMENT_NULL,
|
||||
ANM2_ELEMENT_EVENTS,
|
||||
ANM2_ELEMENT_EVENT,
|
||||
ANM2_ELEMENT_ANIMATIONS,
|
||||
ANM2_ELEMENT_ANIMATION,
|
||||
ANM2_ELEMENT_ROOT_ANIMATION,
|
||||
ANM2_ELEMENT_FRAME,
|
||||
ANM2_ELEMENT_LAYER_ANIMATIONS,
|
||||
ANM2_ELEMENT_LAYER_ANIMATION,
|
||||
ANM2_ELEMENT_NULL_ANIMATIONS,
|
||||
ANM2_ELEMENT_NULL_ANIMATION,
|
||||
ANM2_ELEMENT_TRIGGERS,
|
||||
ANM2_ELEMENT_TRIGGER
|
||||
static const char* ANM2_ELEMENT_STRINGS[] = {
|
||||
#define X(name, str) str,
|
||||
ANM2_ELEMENT_LIST
|
||||
#undef X
|
||||
};
|
||||
|
||||
static const char* ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_COUNT] =
|
||||
{
|
||||
STRING_ANM2_ELEMENT_ANIMATED_ACTOR,
|
||||
STRING_ANM2_ELEMENT_INFO,
|
||||
STRING_ANM2_ELEMENT_CONTENT,
|
||||
STRING_ANM2_ELEMENT_SPRITESHEETS,
|
||||
STRING_ANM2_ELEMENT_SPRITESHEET,
|
||||
STRING_ANM2_ELEMENT_LAYERS,
|
||||
STRING_ANM2_ELEMENT_LAYER,
|
||||
STRING_ANM2_ELEMENT_NULLS,
|
||||
STRING_ANM2_ELEMENT_NULL,
|
||||
STRING_ANM2_ELEMENT_EVENTS,
|
||||
STRING_ANM2_ELEMENT_EVENT,
|
||||
STRING_ANM2_ELEMENT_ANIMATIONS,
|
||||
STRING_ANM2_ELEMENT_ANIMATION,
|
||||
STRING_ANM2_ELEMENT_ROOT_ANIMATION,
|
||||
STRING_ANM2_ELEMENT_FRAME,
|
||||
STRING_ANM2_ELEMENT_LAYER_ANIMATIONS,
|
||||
STRING_ANM2_ELEMENT_LAYER_ANIMATION,
|
||||
STRING_ANM2_ELEMENT_NULL_ANIMATIONS,
|
||||
STRING_ANM2_ELEMENT_NULL_ANIMATION,
|
||||
STRING_ANM2_ELEMENT_TRIGGERS,
|
||||
STRING_ANM2_ELEMENT_TRIGGER
|
||||
DEFINE_STRING_TO_ENUM_FN(anm2_element_from_string, Anm2Element, ANM2_ELEMENT_STRINGS, ANM2_ELEMENT_COUNT)
|
||||
|
||||
#define ANM2_ATTRIBUTE_LIST \
|
||||
X(CREATED_BY, "CreatedBy") \
|
||||
X(CREATED_ON, "CreatedOn") \
|
||||
X(VERSION, "Version") \
|
||||
X(FPS, "Fps") \
|
||||
X(ID, "Id") \
|
||||
X(PATH, "Path") \
|
||||
X(NAME, "Name") \
|
||||
X(SPRITESHEET_ID, "SpritesheetId") \
|
||||
X(SHOW_RECT, "ShowRect") \
|
||||
X(DEFAULT_ANIMATION, "DefaultAnimation") \
|
||||
X(FRAME_NUM, "FrameNum") \
|
||||
X(LOOP, "Loop") \
|
||||
X(X_POSITION, "XPosition") \
|
||||
X(Y_POSITION, "YPosition") \
|
||||
X(X_PIVOT, "XPivot") \
|
||||
X(Y_PIVOT, "YPivot") \
|
||||
X(X_CROP, "XCrop") \
|
||||
X(Y_CROP, "YCrop") \
|
||||
X(WIDTH, "Width") \
|
||||
X(HEIGHT, "Height") \
|
||||
X(X_SCALE, "XScale") \
|
||||
X(Y_SCALE, "YScale") \
|
||||
X(DELAY, "Delay") \
|
||||
X(VISIBLE, "Visible") \
|
||||
X(RED_TINT, "RedTint") \
|
||||
X(GREEN_TINT, "GreenTint") \
|
||||
X(BLUE_TINT, "BlueTint") \
|
||||
X(ALPHA_TINT, "AlphaTint") \
|
||||
X(RED_OFFSET, "RedOffset") \
|
||||
X(GREEN_OFFSET, "GreenOffset") \
|
||||
X(BLUE_OFFSET, "BlueOffset") \
|
||||
X(ROTATION, "Rotation") \
|
||||
X(INTERPOLATED, "Interpolated") \
|
||||
X(LAYER_ID, "LayerId") \
|
||||
X(NULL_ID, "NullId") \
|
||||
X(EVENT_ID, "EventId") \
|
||||
X(AT_FRAME, "AtFrame")
|
||||
|
||||
typedef enum {
|
||||
#define X(name, str) ANM2_ATTRIBUTE_##name,
|
||||
ANM2_ATTRIBUTE_LIST
|
||||
#undef X
|
||||
ANM2_ATTRIBUTE_COUNT
|
||||
} Anm2Attribute;
|
||||
|
||||
static const char* ANM2_ATTRIBUTE_STRINGS[] = {
|
||||
#define X(name, str) str,
|
||||
ANM2_ATTRIBUTE_LIST
|
||||
#undef X
|
||||
};
|
||||
|
||||
#define ANM2_ATTRIBUTE_COUNT (ANM2_ATTRIBUTE_AT_FRAME + 1)
|
||||
enum Anm2Attribute
|
||||
{
|
||||
ANM2_ATTRIBUTE_CREATED_BY,
|
||||
ANM2_ATTRIBUTE_CREATED_ON,
|
||||
ANM2_ATTRIBUTE_FPS,
|
||||
ANM2_ATTRIBUTE_VERSION,
|
||||
ANM2_ATTRIBUTE_ID,
|
||||
ANM2_ATTRIBUTE_PATH,
|
||||
ANM2_ATTRIBUTE_NAME,
|
||||
ANM2_ATTRIBUTE_SPRITESHEET_ID,
|
||||
ANM2_ATTRIBUTE_SHOW_RECT,
|
||||
ANM2_ATTRIBUTE_DEFAULT_ANIMATION,
|
||||
ANM2_ATTRIBUTE_FRAME_NUM,
|
||||
ANM2_ATTRIBUTE_LOOP,
|
||||
ANM2_ATTRIBUTE_X_POSITION,
|
||||
ANM2_ATTRIBUTE_Y_POSITION,
|
||||
ANM2_ATTRIBUTE_X_PIVOT,
|
||||
ANM2_ATTRIBUTE_Y_PIVOT,
|
||||
ANM2_ATTRIBUTE_X_CROP,
|
||||
ANM2_ATTRIBUTE_Y_CROP,
|
||||
ANM2_ATTRIBUTE_WIDTH,
|
||||
ANM2_ATTRIBUTE_HEIGHT,
|
||||
ANM2_ATTRIBUTE_X_SCALE,
|
||||
ANM2_ATTRIBUTE_Y_SCALE,
|
||||
ANM2_ATTRIBUTE_DELAY,
|
||||
ANM2_ATTRIBUTE_VISIBLE,
|
||||
ANM2_ATTRIBUTE_RED_TINT,
|
||||
ANM2_ATTRIBUTE_GREEN_TINT,
|
||||
ANM2_ATTRIBUTE_BLUE_TINT,
|
||||
ANM2_ATTRIBUTE_ALPHA_TINT,
|
||||
ANM2_ATTRIBUTE_RED_OFFSET,
|
||||
ANM2_ATTRIBUTE_GREEN_OFFSET,
|
||||
ANM2_ATTRIBUTE_BLUE_OFFSET,
|
||||
ANM2_ATTRIBUTE_ROTATION,
|
||||
ANM2_ATTRIBUTE_INTERPOLATED,
|
||||
ANM2_ATTRIBUTE_LAYER_ID,
|
||||
ANM2_ATTRIBUTE_NULL_ID,
|
||||
ANM2_ATTRIBUTE_EVENT_ID,
|
||||
ANM2_ATTRIBUTE_AT_FRAME
|
||||
};
|
||||
DEFINE_STRING_TO_ENUM_FN(anm2_attribute_from_string, Anm2Attribute, ANM2_ATTRIBUTE_STRINGS, ANM2_ATTRIBUTE_COUNT)
|
||||
|
||||
static const char* ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_COUNT] =
|
||||
{
|
||||
STRING_ANM2_ATTRIBUTE_CREATED_BY,
|
||||
STRING_ANM2_ATTRIBUTE_CREATED_ON,
|
||||
STRING_ANM2_ATTRIBUTE_FPS,
|
||||
STRING_ANM2_ATTRIBUTE_VERSION,
|
||||
STRING_ANM2_ATTRIBUTE_ID,
|
||||
STRING_ANM2_ATTRIBUTE_PATH,
|
||||
STRING_ANM2_ATTRIBUTE_NAME,
|
||||
STRING_ANM2_ATTRIBUTE_SPRITESHEET_ID,
|
||||
STRING_ANM2_ATTRIBUTE_SHOW_RECT,
|
||||
STRING_ANM2_ATTRIBUTE_DEFAULT_ANIMATION,
|
||||
STRING_ANM2_ATTRIBUTE_FRAME_NUM,
|
||||
STRING_ANM2_ATTRIBUTE_LOOP,
|
||||
STRING_ANM2_ATTRIBUTE_X_POSITION,
|
||||
STRING_ANM2_ATTRIBUTE_Y_POSITION,
|
||||
STRING_ANM2_ATTRIBUTE_X_PIVOT,
|
||||
STRING_ANM2_ATTRIBUTE_Y_PIVOT,
|
||||
STRING_ANM2_ATTRIBUTE_X_CROP,
|
||||
STRING_ANM2_ATTRIBUTE_Y_CROP,
|
||||
STRING_ANM2_ATTRIBUTE_WIDTH,
|
||||
STRING_ANM2_ATTRIBUTE_HEIGHT,
|
||||
STRING_ANM2_ATTRIBUTE_X_SCALE,
|
||||
STRING_ANM2_ATTRIBUTE_Y_SCALE,
|
||||
STRING_ANM2_ATTRIBUTE_DELAY,
|
||||
STRING_ANM2_ATTRIBUTE_VISIBLE,
|
||||
STRING_ANM2_ATTRIBUTE_RED_TINT,
|
||||
STRING_ANM2_ATTRIBUTE_GREEN_TINT,
|
||||
STRING_ANM2_ATTRIBUTE_BLUE_TINT,
|
||||
STRING_ANM2_ATTRIBUTE_ALPHA_TINT,
|
||||
STRING_ANM2_ATTRIBUTE_RED_OFFSET,
|
||||
STRING_ANM2_ATTRIBUTE_GREEN_OFFSET,
|
||||
STRING_ANM2_ATTRIBUTE_BLUE_OFFSET,
|
||||
STRING_ANM2_ATTRIBUTE_ROTATION,
|
||||
STRING_ANM2_ATTRIBUTE_INTERPOLATED,
|
||||
STRING_ANM2_ATTRIBUTE_LAYER_ID,
|
||||
STRING_ANM2_ATTRIBUTE_NULL_ID,
|
||||
STRING_ANM2_ATTRIBUTE_EVENT_ID,
|
||||
STRING_ANM2_ATTRIBUTE_AT_FRAME
|
||||
};
|
||||
|
||||
#define ANM2_ANIMATION_TYPE_COUNT (ANM2_ANIMATION_NULL + 1)
|
||||
#define ANM2_ANIMATION_TYPE_COUNT (ANM2_ANIMATION_TRIGGERS + 1)
|
||||
enum Anm2AnimationType
|
||||
{
|
||||
ANM2_ANIMATION_ROOT,
|
||||
ANM2_ANIMATION_LAYER,
|
||||
ANM2_ANIMATION_NULL
|
||||
ANM2_NONE,
|
||||
ANM2_ROOT_ANIMATION,
|
||||
ANM2_LAYER_ANIMATION,
|
||||
ANM2_NULL_ANIMATION,
|
||||
ANM2_TRIGGERS
|
||||
};
|
||||
|
||||
struct Anm2Spritesheet
|
||||
{
|
||||
s32 id;
|
||||
char path[ANM2_STRING_MAX];
|
||||
char path[ANM2_STRING_MAX] = STRING_EMPTY;
|
||||
};
|
||||
|
||||
struct Anm2Layer
|
||||
{
|
||||
s32 id;
|
||||
char name[ANM2_STRING_MAX];
|
||||
s32 spritesheetID;
|
||||
s32 spritesheetID = -1;
|
||||
char name[ANM2_STRING_MAX] = STRING_ANM2_NEW_LAYER;
|
||||
};
|
||||
|
||||
struct Anm2Null
|
||||
{
|
||||
char name[ANM2_STRING_MAX] = STRING_ANM2_NEW_NULL;
|
||||
bool isShowRect = false;
|
||||
};
|
||||
|
||||
struct Anm2Event
|
||||
{
|
||||
s32 id;
|
||||
char name[ANM2_STRING_MAX];
|
||||
char name[ANM2_STRING_MAX] = STRING_ANM2_NEW_EVENT;
|
||||
};
|
||||
|
||||
struct Anm2Trigger
|
||||
{
|
||||
s32 eventID;
|
||||
s32 frame;
|
||||
s32 eventID = -1;
|
||||
s32 atFrame = -1;
|
||||
};
|
||||
|
||||
struct Anm2Frame
|
||||
{
|
||||
bool isInterpolated;
|
||||
bool isVisible;
|
||||
f32 rotation;
|
||||
s32 delay;
|
||||
ivec2 crop;
|
||||
ivec2 pivot;
|
||||
ivec2 position;
|
||||
ivec2 size;
|
||||
ivec2 scale;
|
||||
ivec3 colorOffset;
|
||||
ivec4 tint;
|
||||
s32 index;
|
||||
bool isInterpolated = false;
|
||||
bool isVisible = true;
|
||||
f32 rotation = 1.0f;
|
||||
s32 delay = 1;
|
||||
vec2 crop = {0.0f, 0.0f};
|
||||
vec2 pivot = {0.0f, 0.0f};
|
||||
vec2 position = {0.0f, 0.0f};
|
||||
vec2 size = {1.0f, 1.0f};
|
||||
vec2 scale = {1.0f, 1.0f};
|
||||
ivec3 offsetRGB = {0, 0, 0};
|
||||
ivec4 tintRGBA = {255, 255, 255, 255};
|
||||
};
|
||||
|
||||
struct Anm2LayerAnimation
|
||||
{
|
||||
s32 layerID;
|
||||
bool isVisible;
|
||||
vector<Anm2Frame> frames;
|
||||
bool isVisible = true;
|
||||
std::vector<Anm2Frame> frames;
|
||||
};
|
||||
|
||||
struct Anm2NullAnimation
|
||||
{
|
||||
bool isVisible = true;
|
||||
std::vector<Anm2Frame> frames;
|
||||
};
|
||||
|
||||
struct Anm2RootAnimation
|
||||
{
|
||||
bool isVisible = true;
|
||||
std::vector<Anm2Frame> frames;
|
||||
};
|
||||
|
||||
struct Anm2Triggers
|
||||
{
|
||||
bool isVisible = true;
|
||||
std::vector<Anm2Trigger> items;
|
||||
};
|
||||
|
||||
struct Anm2Animation
|
||||
{
|
||||
s32 id;
|
||||
s32 length;
|
||||
char name[ANM2_STRING_MAX];
|
||||
bool isVisible;
|
||||
bool isLoop;
|
||||
Anm2Frame rootAnimationFrame;
|
||||
vector<Anm2LayerAnimation> layerAnimations;
|
||||
vector<Anm2Trigger> triggers;
|
||||
s32 frameNum = 0;
|
||||
char name[ANM2_STRING_MAX] = STRING_ANM2_NEW_ANIMATION;
|
||||
bool isLoop = true;
|
||||
Anm2RootAnimation rootAnimation;
|
||||
std::map<s32, Anm2LayerAnimation> layerAnimations;
|
||||
std::map<s32, Anm2NullAnimation> nullAnimations;
|
||||
Anm2Triggers triggers;
|
||||
};
|
||||
|
||||
struct Anm2
|
||||
{
|
||||
s32 fps;
|
||||
s32 version;
|
||||
char createdBy[ANM2_STRING_MAX];
|
||||
char createdOn[ANM2_STRING_MAX];
|
||||
char defaultAnimation[ANM2_STRING_MAX];
|
||||
bool isInit;
|
||||
vector<Anm2Spritesheet> spritesheets;
|
||||
vector<Anm2Layer> layers;
|
||||
vector<Anm2Event> events;
|
||||
vector<Anm2Animation> animations;
|
||||
char path[PATH_MAX] = STRING_EMPTY;
|
||||
s32 fps = ANM2_FPS_DEFAULT;
|
||||
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::map<s32, Anm2Spritesheet> spritesheets;
|
||||
std::map<s32, Anm2Layer> layers;
|
||||
std::map<s32, Anm2Null> nulls;
|
||||
std::map<s32, Anm2Event> events;
|
||||
std::map<s32, Anm2Animation> animations;
|
||||
};
|
||||
|
||||
bool anm2_init(Anm2* self, const char* path);
|
||||
void anm2_free(Anm2* self);
|
||||
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, const char* 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);
|
59
src/dialog.cpp
Normal file
59
src/dialog.cpp
Normal file
@ -0,0 +1,59 @@
|
||||
#include "dialog.h"
|
||||
|
||||
static void _dialog_callback(void* userdata, const char* const* filelist, s32 filter);
|
||||
|
||||
static void
|
||||
_dialog_callback(void* userdata, const char* const* filelist, s32 filter)
|
||||
{
|
||||
Dialog* self;
|
||||
|
||||
self = (Dialog*)userdata;
|
||||
|
||||
if (filelist && filelist[0] && strlen(filelist[0]) > 0)
|
||||
{
|
||||
strncpy(self->path, filelist[0], PATH_MAX - 1);
|
||||
self->isSelected = true;
|
||||
}
|
||||
else
|
||||
self->isSelected = false;
|
||||
|
||||
}
|
||||
|
||||
/* Opens file dialog for user to pick anm2 files */
|
||||
void
|
||||
dialog_anm2_open(Dialog* self)
|
||||
{
|
||||
SDL_ShowOpenFileDialog(_dialog_callback, self, NULL, ANM2_DIALOG_FILE_FILTER, 1, NULL, false);
|
||||
self->type = DIALOG_ANM2_OPEN;
|
||||
}
|
||||
|
||||
/* Opens file dialog for user to save new anm2 files */
|
||||
void
|
||||
dialog_anm2_save(Dialog* self)
|
||||
{
|
||||
SDL_ShowSaveFileDialog(_dialog_callback, self, NULL, ANM2_DIALOG_FILE_FILTER, 1, NULL);
|
||||
self->type = DIALOG_ANM2_SAVE;
|
||||
}
|
||||
|
||||
void
|
||||
dialog_tick(Dialog* self)
|
||||
{
|
||||
if (self->isSelected)
|
||||
{
|
||||
switch (self->type)
|
||||
{
|
||||
case DIALOG_ANM2_OPEN:
|
||||
anm2_deserialize(self->anm2, self->path);
|
||||
break;
|
||||
case DIALOG_ANM2_SAVE:
|
||||
anm2_serialize(self->anm2, self->path);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
memset(self->path, '\0', PATH_MAX);
|
||||
self->isSelected = false;
|
||||
}
|
||||
}
|
||||
|
26
src/dialog.h
Normal file
26
src/dialog.h
Normal file
@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include "anm2.h"
|
||||
|
||||
static const SDL_DialogFileFilter ANM2_DIALOG_FILE_FILTER[] =
|
||||
{
|
||||
{"Anm2", "anm2;xml"}
|
||||
};
|
||||
|
||||
enum DialogType
|
||||
{
|
||||
DIALOG_ANM2_OPEN,
|
||||
DIALOG_ANM2_SAVE
|
||||
};
|
||||
|
||||
struct Dialog
|
||||
{
|
||||
Anm2* anm2 = NULL;
|
||||
enum DialogType type = DIALOG_ANM2_OPEN;
|
||||
char path[PATH_MAX] = "";
|
||||
bool isSelected = false;
|
||||
};
|
||||
|
||||
void dialog_anm2_open(Dialog* self);
|
||||
void dialog_anm2_save(Dialog* self);
|
||||
void dialog_tick(Dialog* self);
|
28
src/file.cpp
28
src/file.cpp
@ -1,28 +0,0 @@
|
||||
#include "file.h"
|
||||
|
||||
bool
|
||||
file_read(const char* path, void* buffer, size_t size)
|
||||
{
|
||||
SDL_IOStream* ioStream;
|
||||
|
||||
memset(buffer, '\0', size);
|
||||
|
||||
ioStream = SDL_IOFromFile(path, "r");
|
||||
|
||||
if (!ioStream)
|
||||
{
|
||||
printf(STRING_ERROR_FILE_READ, path);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!SDL_ReadIO(ioStream, buffer, size))
|
||||
{
|
||||
printf(STRING_ERROR_FILE_READ, path);
|
||||
return false;
|
||||
}
|
||||
|
||||
SDL_CloseIO(ioStream);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1,5 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "COMMON.h"
|
||||
|
||||
bool file_read(const char* path, void* buffer, size_t size);
|
860
src/imgui.cpp
860
src/imgui.cpp
@ -1,5 +1,280 @@
|
||||
#include "imgui.h"
|
||||
|
||||
static void _imgui_tooltip(const char* tooltip);
|
||||
static void _imgui_timeline_element(Imgui* self, void* element, s32* id, s32* index, Anm2AnimationType type, Anm2AnimationType* selectType, s32* selectID);
|
||||
|
||||
/* Makes a tooltip! */
|
||||
static void _imgui_tooltip(const char* tooltip)
|
||||
{
|
||||
if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayNormal))
|
||||
ImGui::SetTooltip("%s", tooltip);
|
||||
}
|
||||
|
||||
/* Displays each element of the timeline of a selected animation */
|
||||
static void
|
||||
_imgui_timeline_element(Imgui* self, void* element, s32* id, s32* index, Anm2AnimationType type, Anm2AnimationType* selectType, s32* selectID)
|
||||
{
|
||||
static s32 selectedElementIndex = -1;
|
||||
static s32 selectedSpritesheetIndex = -1;
|
||||
Anm2Layer* layer = NULL;
|
||||
Anm2LayerAnimation* layerAnimation = NULL;
|
||||
Anm2Null* null = NULL;
|
||||
Anm2NullAnimation* nullAnimation = NULL;
|
||||
Anm2RootAnimation* rootAnimation = NULL;
|
||||
Anm2Triggers* triggers = NULL;
|
||||
ImTextureID iconTexture = -1;
|
||||
|
||||
bool isArrows = false;
|
||||
bool* isShowRect = NULL;
|
||||
bool* isVisible = NULL;
|
||||
char nameBuffer[ANM2_STRING_MAX] = STRING_EMPTY;
|
||||
char nameVisible[ANM2_STRING_FORMATTED_MAX] = STRING_EMPTY;
|
||||
char* namePointer = NULL;
|
||||
s32* spritesheetID = NULL;
|
||||
bool isSelected = selectedElementIndex == *index;
|
||||
bool isChangeable = type != ANM2_ROOT_ANIMATION && type != ANM2_TRIGGERS;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case ANM2_ROOT_ANIMATION:
|
||||
rootAnimation = (Anm2RootAnimation*)element;
|
||||
iconTexture = self->packed->textures[PACKED_TEXTURE_ROOT].handle;
|
||||
strncpy(nameVisible, STRING_IMGUI_TIMELINE_ROOT, ANM2_STRING_FORMATTED_MAX);
|
||||
isVisible = &rootAnimation->isVisible;
|
||||
break;
|
||||
case ANM2_LAYER_ANIMATION:
|
||||
layerAnimation = (Anm2LayerAnimation*)element;
|
||||
layer = &self->anm2->layers[*id];
|
||||
iconTexture = self->packed->textures[PACKED_TEXTURE_LAYER].handle;
|
||||
isVisible = &layerAnimation->isVisible;
|
||||
spritesheetID = &layer->spritesheetID;
|
||||
namePointer = layer->name;
|
||||
snprintf(nameBuffer, ANM2_STRING_MAX, "%s", namePointer);
|
||||
snprintf(nameVisible, ANM2_STRING_FORMATTED_MAX, STRING_IMGUI_TIMELINE_ELEMENT_FORMAT, *id, namePointer);
|
||||
break;
|
||||
case ANM2_NULL_ANIMATION:
|
||||
nullAnimation = (Anm2NullAnimation*)element;
|
||||
null = &self->anm2->nulls[*id];
|
||||
iconTexture = self->packed->textures[PACKED_TEXTURE_NULL].handle;
|
||||
isVisible = &nullAnimation->isVisible;
|
||||
isShowRect = &null->isShowRect;
|
||||
namePointer = null->name;
|
||||
snprintf(nameBuffer, ANM2_STRING_MAX, "%s", namePointer);
|
||||
snprintf(nameVisible, ANM2_STRING_FORMATTED_MAX, STRING_IMGUI_TIMELINE_ELEMENT_FORMAT, *id, namePointer);
|
||||
break;
|
||||
case ANM2_TRIGGERS:
|
||||
triggers = (Anm2Triggers*)element;
|
||||
iconTexture = self->packed->textures[PACKED_TEXTURE_TRIGGER].handle;
|
||||
strncpy(nameVisible, STRING_IMGUI_TIMELINE_TRIGGERS, ANM2_STRING_FORMATTED_MAX);
|
||||
isVisible = &triggers->isVisible;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ImGui::BeginChild(nameVisible, IMGUI_TIMELINE_ELEMENT_SIZE, true, ImGuiWindowFlags_NoScrollbar);
|
||||
|
||||
ImGui::PushID(*index);
|
||||
|
||||
/* Shift arrows */
|
||||
if (isChangeable)
|
||||
{
|
||||
bool isSwap = false;
|
||||
bool isReversed = (type == ANM2_LAYER_ANIMATION);
|
||||
|
||||
auto arrows_draw = [&](auto it, auto begin, auto end, auto& map, bool* didSwap, bool isReversed)
|
||||
{
|
||||
bool canMoveUp = isReversed ? (std::next(it) != end) : (it != begin);
|
||||
bool canMoveDown = isReversed ? (it != begin) : (std::next(it) != end);
|
||||
|
||||
isArrows = canMoveUp || canMoveDown;
|
||||
|
||||
if (isArrows)
|
||||
ImGui::BeginChild(STRING_IMGUI_TIMELINE_ELEMENT_SHIFT_ARROWS_LABEL, IMGUI_TIMELINE_SHIFT_ARROWS_SIZE);
|
||||
|
||||
if (canMoveUp)
|
||||
{
|
||||
auto target = isReversed ? std::next(it) : std::prev(it);
|
||||
if (target != map.end() && ImGui::ImageButton(STRING_IMGUI_TIMELINE_ELEMENT_SHIFT_ABOVE, self->packed->textures[PACKED_TEXTURE_ARROW_UP].handle, IMGUI_ICON_SIZE))
|
||||
{
|
||||
map_swap(map, it->first, target->first);
|
||||
*didSwap = true;
|
||||
}
|
||||
|
||||
_imgui_tooltip(STRING_IMGUI_TOOLTIP_TIMELINE_ELEMENT_SHIFT_UP);
|
||||
|
||||
}
|
||||
|
||||
if (canMoveDown)
|
||||
{
|
||||
if (!canMoveUp)
|
||||
ImGui::Dummy(IMGUI_ICON_BUTTON_SIZE);
|
||||
|
||||
auto target = isReversed ? std::prev(it) : std::next(it);
|
||||
if (target != map.end() && ImGui::ImageButton(STRING_IMGUI_TIMELINE_ELEMENT_SHIFT_BELOW, self->packed->textures[PACKED_TEXTURE_ARROW_DOWN].handle, IMGUI_ICON_SIZE))
|
||||
{
|
||||
map_swap(map, it->first, target->first);
|
||||
*didSwap = true;
|
||||
}
|
||||
|
||||
_imgui_tooltip(STRING_IMGUI_TOOLTIP_TIMELINE_ELEMENT_SHIFT_DOWN);
|
||||
|
||||
}
|
||||
|
||||
if (isArrows)
|
||||
{
|
||||
ImGui::EndChild();
|
||||
ImGui::SameLine();
|
||||
}
|
||||
};
|
||||
|
||||
if (type == ANM2_LAYER_ANIMATION)
|
||||
{
|
||||
auto it = std::find_if(self->anm2->layers.begin(), self->anm2->layers.end(),
|
||||
[&](const auto& pair) { return &pair.second == layer; });
|
||||
|
||||
if (it != self->anm2->layers.end())
|
||||
arrows_draw(it, self->anm2->layers.begin(), self->anm2->layers.end(), self->anm2->layers, &isSwap, isReversed);
|
||||
}
|
||||
|
||||
if (type == ANM2_NULL_ANIMATION)
|
||||
{
|
||||
auto it = std::find_if(self->anm2->nulls.begin(), self->anm2->nulls.end(),
|
||||
[&](const auto& pair) { return &pair.second == null; });
|
||||
|
||||
if (it != self->anm2->nulls.end())
|
||||
arrows_draw(it, self->anm2->nulls.begin(), self->anm2->nulls.end(), self->anm2->nulls, &isSwap, isReversed);
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::BeginGroup();
|
||||
|
||||
ImGui::Image(iconTexture, IMGUI_ICON_SIZE);
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::BeginChild(STRING_IMGUI_TIMELINE_ELEMENT_NAME_LABEL, IMGUI_TIMELINE_ELEMENT_NAME_SIZE);
|
||||
|
||||
if (isSelected && isChangeable)
|
||||
{
|
||||
if (ImGui::InputText(STRING_IMGUI_TIMELINE_ANIMATION_LABEL, nameBuffer, ANM2_STRING_MAX, ImGuiInputTextFlags_EnterReturnsTrue))
|
||||
{
|
||||
strncpy(namePointer, nameBuffer, ANM2_STRING_MAX);
|
||||
selectedElementIndex = -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ImGui::Selectable(nameVisible, isSelected))
|
||||
{
|
||||
selectedElementIndex = *index;
|
||||
|
||||
if (selectType && selectID)
|
||||
{
|
||||
*selectType = type;
|
||||
*selectID = *id;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case ANM2_ROOT_ANIMATION:
|
||||
_imgui_tooltip(STRING_IMGUI_TOOLTIP_TIMELINE_ELEMENT_ROOT);
|
||||
break;
|
||||
case ANM2_LAYER_ANIMATION:
|
||||
_imgui_tooltip(STRING_IMGUI_TOOLTIP_TIMELINE_ELEMENT_LAYER);
|
||||
break;
|
||||
case ANM2_NULL_ANIMATION:
|
||||
_imgui_tooltip(STRING_IMGUI_TOOLTIP_TIMELINE_ELEMENT_NULL);
|
||||
break;
|
||||
case ANM2_TRIGGERS:
|
||||
_imgui_tooltip(STRING_IMGUI_TOOLTIP_TIMELINE_ELEMENT_TRIGGERS);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ImGui::EndChild();
|
||||
|
||||
/* Visiblity */
|
||||
if (isVisible)
|
||||
{
|
||||
ImTextureID visibilityIcon = *isVisible
|
||||
? self->packed->textures[PACKED_TEXTURE_EYE_OPEN].handle
|
||||
: self->packed->textures[PACKED_TEXTURE_EYE_CLOSED].handle;
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetContentRegionAvail().x - IMGUI_ICON_BUTTON_SIZE.x - ImGui::GetStyle().FramePadding.x * 2);
|
||||
|
||||
if (ImGui::ImageButton(STRING_IMGUI_TIMELINE_VISIBLE, visibilityIcon, IMGUI_ICON_SIZE))
|
||||
*isVisible = !*isVisible;
|
||||
|
||||
_imgui_tooltip(STRING_IMGUI_TOOLTIP_TIMELINE_ELEMENT_VISIBLE);
|
||||
}
|
||||
|
||||
/* Spritesheet IDs */
|
||||
if (spritesheetID)
|
||||
{
|
||||
char spritesheetIDName[ANM2_STRING_FORMATTED_MAX];
|
||||
|
||||
if (*spritesheetID == -1)
|
||||
snprintf(spritesheetIDName, ANM2_STRING_FORMATTED_MAX, STRING_IMGUI_TIMELINE_SPRITESHEET_UNKNOWN);
|
||||
else
|
||||
snprintf(spritesheetIDName, ANM2_STRING_FORMATTED_MAX, STRING_IMGUI_TIMELINE_SPRITESHEET_FORMAT, *spritesheetID);
|
||||
|
||||
ImGui::Image(self->packed->textures[PACKED_TEXTURE_SPRITESHEET].handle, IMGUI_ICON_SIZE);
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::BeginChild(STRING_IMGUI_TIMELINE_ELEMENT_SPRITESHEET_ID_LABEL, IMGUI_TIMELINE_SPRITESHEET_ID_SIZE);
|
||||
|
||||
if (selectedSpritesheetIndex == *index)
|
||||
{
|
||||
if (ImGui::DragInt(STRING_IMGUI_TIMELINE_ELEMENT_SPRITESHEET_ID_LABEL, spritesheetID, 0, 1, self->anm2->spritesheets.size() - 1))
|
||||
selectedSpritesheetIndex = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ImGui::Selectable(spritesheetIDName))
|
||||
selectedSpritesheetIndex = *index;
|
||||
}
|
||||
|
||||
_imgui_tooltip(STRING_IMGUI_TOOLTIP_TIMELINE_ELEMENT_SPRITESHEET);
|
||||
|
||||
ImGui::EndChild();
|
||||
}
|
||||
|
||||
/* ShowRect */
|
||||
if (isShowRect)
|
||||
{
|
||||
ImTextureID rectIcon = *isShowRect
|
||||
? self->packed->textures[PACKED_TEXTURE_RECT_HIDE].handle
|
||||
: self->packed->textures[PACKED_TEXTURE_RECT_SHOW].handle;
|
||||
|
||||
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetContentRegionAvail().x - IMGUI_ICON_BUTTON_SIZE.x - ImGui::GetStyle().FramePadding.x * 2);
|
||||
|
||||
if (ImGui::ImageButton(STRING_IMGUI_TIMELINE_RECT, rectIcon, IMGUI_ICON_SIZE))
|
||||
*isShowRect = !*isShowRect;
|
||||
|
||||
_imgui_tooltip(STRING_IMGUI_TOOLTIP_TIMELINE_ELEMENT_RECT);
|
||||
}
|
||||
|
||||
if (ImGui::IsMouseClicked(0) && !ImGui::IsAnyItemHovered() && ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem))
|
||||
{
|
||||
selectedElementIndex = -1;
|
||||
selectedSpritesheetIndex = -1;
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
|
||||
ImGui::EndGroup();
|
||||
|
||||
ImGui::EndChild();
|
||||
|
||||
*index = *index + 1;
|
||||
}
|
||||
|
||||
void
|
||||
imgui_init(SDL_Window* window, SDL_GLContext glContext)
|
||||
{
|
||||
@ -11,31 +286,604 @@ imgui_init(SDL_Window* window, SDL_GLContext glContext)
|
||||
ImGui_ImplSDL3_InitForOpenGL(window, glContext);
|
||||
ImGui_ImplOpenGL3_Init(STRING_OPENGL_VERSION);
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
|
||||
|
||||
printf(STRING_INFO_IMGUI_INIT);
|
||||
}
|
||||
|
||||
void
|
||||
imgui_tick(State* state)
|
||||
imgui_tick(Imgui* self)
|
||||
{
|
||||
static s32 selectedSpritesheetID = -1;
|
||||
static s32 selectedEventID = -1;
|
||||
static s32 selectedAnimationID = -1;
|
||||
static s32 selectedTimelineElementID = -1;
|
||||
static Anm2AnimationType selectedTimelineElementType = ANM2_NONE;
|
||||
static bool isInterpolated = true;
|
||||
static bool isVisible = true;
|
||||
|
||||
static f32 rotation = 0;
|
||||
static s32 duration = 0;
|
||||
static vec2 cropPosition = {0, 0};
|
||||
static vec2 cropSize = {0, 0};
|
||||
static vec2 pivot = {0, 0};
|
||||
static vec2 position = {0, 0};
|
||||
static vec2 xyScale = {0, 0};
|
||||
static vec3 offset = {0.0f, 0.0f, 0.0f};
|
||||
static vec4 tint = {0.0f, 0.0f, 0.0f, 1.0f};
|
||||
|
||||
ImVec2 previewWindowSize;
|
||||
ImVec2 previewSize;
|
||||
f32 previewAspect = 0.0f;
|
||||
f32 previewWindowAspect = 0.0f;
|
||||
|
||||
ImGuiWindowFlags taskbarWindowFlags;
|
||||
ImGuiWindowFlags dockspaceWindowFlags;
|
||||
ImGuiDockNodeFlags dockNodeFlags;
|
||||
|
||||
ImGui_ImplSDL3_NewFrame();
|
||||
ImGui_ImplOpenGL3_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
|
||||
ImGui::Begin("Hello, world!");
|
||||
ImGui::Text("Color");
|
||||
ImGui::ColorEdit3("Color", value_ptr(state->clearColor));
|
||||
taskbarWindowFlags = 0 |
|
||||
ImGuiWindowFlags_NoTitleBar |
|
||||
ImGuiWindowFlags_NoResize |
|
||||
ImGuiWindowFlags_NoMove |
|
||||
ImGuiWindowFlags_NoScrollbar |
|
||||
ImGuiWindowFlags_NoSavedSettings;
|
||||
|
||||
dockspaceWindowFlags = 0 |
|
||||
ImGuiWindowFlags_NoTitleBar |
|
||||
ImGuiWindowFlags_NoCollapse |
|
||||
ImGuiWindowFlags_NoResize |
|
||||
ImGuiWindowFlags_NoMove |
|
||||
ImGuiWindowFlags_NoBringToFrontOnFocus |
|
||||
ImGuiWindowFlags_NoNavFocus;
|
||||
|
||||
dockNodeFlags = 0 |
|
||||
ImGuiDockNodeFlags_PassthruCentralNode;
|
||||
|
||||
ImGuiViewport* viewport = ImGui::GetMainViewport();
|
||||
|
||||
/* Taskbar */
|
||||
ImGui::SetNextWindowPos(viewport->Pos);
|
||||
ImGui::SetNextWindowSize(ImVec2(viewport->Size.x, IMGUI_TASKBAR_HEIGHT));
|
||||
|
||||
ImGui::Begin(STRING_IMGUI_TASKBAR, NULL, taskbarWindowFlags);
|
||||
|
||||
if (ImGui::Selectable(STRING_IMGUI_TASKBAR_FILE, false, 0, ImGui::CalcTextSize(STRING_IMGUI_TASKBAR_FILE)))
|
||||
ImGui::OpenPopup(STRING_IMGUI_FILE_MENU);
|
||||
|
||||
if (ImGui::IsItemHovered() || ImGui::IsItemActive())
|
||||
ImGui::SetNextWindowPos(ImVec2(ImGui::GetItemRectMin().x, ImGui::GetItemRectMin().y + ImGui::GetItemRectSize().y));
|
||||
|
||||
if (ImGui::BeginPopup(STRING_IMGUI_FILE_MENU))
|
||||
{
|
||||
if (ImGui::Selectable(STRING_IMGUI_FILE_NEW))
|
||||
{
|
||||
selectedAnimationID = -1;
|
||||
selectedSpritesheetID = -1;
|
||||
selectedEventID = -1;
|
||||
anm2_new(self->anm2);
|
||||
window_title_from_anm2_set(self->window, self->anm2);
|
||||
|
||||
}
|
||||
|
||||
if (ImGui::Selectable(STRING_IMGUI_FILE_OPEN))
|
||||
{
|
||||
selectedAnimationID = -1;
|
||||
selectedEventID = -1;
|
||||
selectedSpritesheetID = -1;
|
||||
dialog_anm2_open(self->dialog);
|
||||
window_title_from_anm2_set(self->window, self->anm2);
|
||||
}
|
||||
|
||||
if (ImGui::Selectable(STRING_IMGUI_FILE_SAVE))
|
||||
{
|
||||
if (!strcmp(self->anm2->path, STRING_EMPTY) == 0)
|
||||
anm2_serialize(self->anm2, self->anm2->path);
|
||||
else
|
||||
dialog_anm2_save(self->dialog);
|
||||
}
|
||||
|
||||
if (ImGui::Selectable(STRING_IMGUI_FILE_SAVE_AS))
|
||||
{
|
||||
dialog_anm2_save(self->dialog);
|
||||
window_title_from_anm2_set(self->window, self->anm2);
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
|
||||
/* Dockspace */
|
||||
ImGui::SetNextWindowPos(ImVec2(viewport->Pos.x, viewport->Pos.y + IMGUI_TASKBAR_HEIGHT));
|
||||
ImGui::SetNextWindowSize(ImVec2(viewport->Size.x, viewport->Size.y - IMGUI_TASKBAR_HEIGHT));
|
||||
ImGui::SetNextWindowViewport(viewport->ID);
|
||||
|
||||
ImGui::Begin(STRING_IMGUI_WINDOW, NULL, dockspaceWindowFlags);
|
||||
|
||||
ImGuiID dockspace_id = ImGui::GetID(STRING_IMGUI_DOCKSPACE);
|
||||
ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), dockNodeFlags);
|
||||
|
||||
ImGui::End();
|
||||
|
||||
/* -- Properties -- */
|
||||
ImGui::Begin(STRING_IMGUI_PROPERTIES);
|
||||
|
||||
/* FPS */
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text(STRING_IMGUI_PROPERTIES_FPS);
|
||||
ImGui::SameLine();
|
||||
ImGui::SliderInt(STRING_IMGUI_PROPERTIES_FPS_LABEL, &self->anm2->fps, ANM2_FPS_MIN, ANM2_FPS_MAX);
|
||||
_imgui_tooltip(STRING_IMGUI_TOOLTIP_PROPERTIES_FPS);
|
||||
|
||||
/* CreatedBy */
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text(STRING_IMGUI_PROPERTIES_CREATED_BY);
|
||||
ImGui::SameLine();
|
||||
ImGui::InputText(STRING_IMGUI_PROPERTIES_CREATED_BY_LABEL, self->anm2->createdBy, ANM2_STRING_MAX);
|
||||
_imgui_tooltip(STRING_IMGUI_TOOLTIP_PROPERTIES_CREATED_BY);
|
||||
|
||||
/* CreatedOn */
|
||||
ImGui::Text(STRING_IMGUI_PROPERTIES_CREATED_ON, self->anm2->createdOn);
|
||||
|
||||
/* Version */
|
||||
ImGui::Text(STRING_IMGUI_PROPERTIES_VERSION, self->anm2->version);
|
||||
|
||||
ImGui::End();
|
||||
|
||||
/* -- Animations -- */
|
||||
ImGui::Begin(STRING_IMGUI_ANIMATIONS);
|
||||
|
||||
/* Iterate through all animations, can be selected and names can be edited */
|
||||
for (auto & [id, animation] : self->anm2->animations)
|
||||
{
|
||||
char name[ANM2_STRING_FORMATTED_MAX];
|
||||
char oldName[ANM2_STRING_MAX];
|
||||
bool isSelected = selectedAnimationID == id;
|
||||
static s32 defaultAnimationID = -1;
|
||||
|
||||
/* Distinguish default animation; if animation has the same name, only mark the first one as default */
|
||||
if (strcmp(animation.name, self->anm2->defaultAnimation) == 0)
|
||||
{
|
||||
snprintf(name, ANM2_STRING_FORMATTED_MAX, STRING_IMGUI_ANIMATIONS_DEFAULT_ANIMATION_FORMAT, animation.name);
|
||||
defaultAnimationID = id;
|
||||
}
|
||||
else
|
||||
strncpy(name, animation.name, ANM2_STRING_FORMATTED_MAX - 1);
|
||||
|
||||
ImGui::PushID(id);
|
||||
|
||||
ImGui::Image(self->packed->textures[PACKED_TEXTURE_ANIMATION].handle, IMGUI_ICON_SIZE);
|
||||
ImGui::SameLine();
|
||||
|
||||
if (isSelected)
|
||||
{
|
||||
if (ImGui::InputText(STRING_IMGUI_ANIMATIONS_ANIMATION_LABEL, animation.name, ANM2_STRING_MAX, ImGuiInputTextFlags_EnterReturnsTrue))
|
||||
{
|
||||
if (id == defaultAnimationID)
|
||||
strncpy(self->anm2->defaultAnimation, animation.name, ANM2_STRING_MAX);
|
||||
|
||||
selectedAnimationID = -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ImGui::Selectable(name, isSelected))
|
||||
selectedAnimationID = id;
|
||||
}
|
||||
|
||||
_imgui_tooltip(STRING_IMGUI_TOOLTIP_ANIMATIONS_SELECT);
|
||||
|
||||
ImGui::PopID();
|
||||
}
|
||||
|
||||
if (ImGui::Button(STRING_IMGUI_ANIMATIONS_ADD))
|
||||
{
|
||||
s32 id;
|
||||
bool isDefault = self->anm2->animations.size() == 0; /* first animation is default automatically */
|
||||
|
||||
id = anm2_animation_add(self->anm2);
|
||||
|
||||
selectedAnimationID = id;
|
||||
|
||||
if (isDefault)
|
||||
strncpy(self->anm2->defaultAnimation, self->anm2->animations[id].name, ANM2_STRING_MAX);
|
||||
}
|
||||
_imgui_tooltip(STRING_IMGUI_TOOLTIP_ANIMATIONS_ADD);
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
if (selectedAnimationID != -1)
|
||||
{
|
||||
/* Remove */
|
||||
if (ImGui::Button(STRING_IMGUI_ANIMATIONS_REMOVE))
|
||||
{
|
||||
anm2_animation_remove(self->anm2, selectedAnimationID);
|
||||
selectedAnimationID = -1;
|
||||
}
|
||||
_imgui_tooltip(STRING_IMGUI_TOOLTIP_ANIMATIONS_REMOVE);
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
/* Duplicate */
|
||||
if (ImGui::Button(STRING_IMGUI_ANIMATIONS_DUPLICATE))
|
||||
{
|
||||
s32 id = map_next_id_get(self->anm2->animations);
|
||||
self->anm2->animations.insert({id, self->anm2->animations[selectedAnimationID]});
|
||||
selectedAnimationID = id;
|
||||
}
|
||||
_imgui_tooltip(STRING_IMGUI_TOOLTIP_ANIMATIONS_DUPLICATE);
|
||||
|
||||
if (ImGui::Button(STRING_IMGUI_ANIMATIONS_SET_AS_DEFAULT))
|
||||
{
|
||||
strncpy(self->anm2->defaultAnimation, self->anm2->animations[selectedAnimationID].name, ANM2_STRING_MAX);
|
||||
selectedAnimationID = -1;
|
||||
}
|
||||
|
||||
_imgui_tooltip(STRING_IMGUI_TOOLTIP_ANIMATIONS_SET_AS_DEFAULT);
|
||||
}
|
||||
|
||||
if (ImGui::IsMouseClicked(0) && !ImGui::IsAnyItemHovered() && ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem))
|
||||
selectedAnimationID = -1;
|
||||
|
||||
ImGui::End();
|
||||
|
||||
/* -- Events -- */
|
||||
ImGui::Begin(STRING_IMGUI_EVENTS);
|
||||
|
||||
/* Iterate through all events, can be selected and names can be edited */
|
||||
for (auto & [id, event] : self->anm2->events)
|
||||
{
|
||||
char eventString[ANM2_STRING_FORMATTED_MAX];
|
||||
bool isSelected;
|
||||
|
||||
snprintf(eventString, ANM2_STRING_FORMATTED_MAX, STRING_IMGUI_EVENT_FORMAT, (s32)id, event.name);
|
||||
|
||||
ImGui::PushID(id);
|
||||
|
||||
ImGui::Image(self->packed->textures[PACKED_TEXTURE_EVENT].handle, IMGUI_ICON_SIZE);
|
||||
ImGui::SameLine();
|
||||
|
||||
isSelected = selectedEventID == id;
|
||||
|
||||
if (isSelected)
|
||||
{
|
||||
if (ImGui::InputText(STRING_IMGUI_EVENTS_EVENT_LABEL, event.name, ANM2_STRING_MAX, ImGuiInputTextFlags_EnterReturnsTrue))
|
||||
selectedEventID = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ImGui::Selectable(eventString, isSelected))
|
||||
selectedEventID = id;
|
||||
}
|
||||
|
||||
_imgui_tooltip(STRING_IMGUI_TOOLTIP_EVENTS_SELECT);
|
||||
|
||||
ImGui::PopID();
|
||||
}
|
||||
|
||||
if (ImGui::Button(STRING_IMGUI_EVENTS_ADD))
|
||||
{
|
||||
s32 id = map_next_id_get(self->anm2->events);
|
||||
self->anm2->events[id] = Anm2Event{};
|
||||
selectedEventID = id;
|
||||
}
|
||||
_imgui_tooltip(STRING_IMGUI_TOOLTIP_EVENTS_ADD);
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
if (selectedEventID != -1)
|
||||
{
|
||||
if (ImGui::Button(STRING_IMGUI_EVENTS_REMOVE))
|
||||
{
|
||||
self->anm2->events.erase(selectedEventID);
|
||||
selectedEventID = -1;
|
||||
}
|
||||
_imgui_tooltip(STRING_IMGUI_TOOLTIP_EVENTS_REMOVE);
|
||||
}
|
||||
|
||||
if (ImGui::IsMouseClicked(0) && !ImGui::IsAnyItemHovered() && ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem))
|
||||
selectedEventID = -1;
|
||||
|
||||
ImGui::End();
|
||||
|
||||
/* -- Spritesheets -- */
|
||||
ImGui::Begin(STRING_IMGUI_SPRITESHEETS);
|
||||
|
||||
for (auto [id, spritesheet] : self->anm2->spritesheets)
|
||||
{
|
||||
char spritesheetString[ANM2_STRING_FORMATTED_MAX];
|
||||
bool isSelected = false;
|
||||
|
||||
snprintf(spritesheetString, ANM2_STRING_FORMATTED_MAX, STRING_IMGUI_SPRITESHEET_FORMAT, (s32)id, spritesheet.path);
|
||||
|
||||
ImGui::BeginChild(spritesheetString, IMGUI_SPRITESHEET_SIZE, true, ImGuiWindowFlags_None);
|
||||
|
||||
ImGui::PushID(id);
|
||||
|
||||
ImGui::Image(self->packed->textures[PACKED_TEXTURE_SPRITESHEET].handle, IMGUI_ICON_SIZE);
|
||||
ImGui::SameLine();
|
||||
|
||||
isSelected = selectedSpritesheetID == id;
|
||||
if (ImGui::Selectable(spritesheetString, isSelected))
|
||||
selectedSpritesheetID = id;
|
||||
|
||||
ImGui::PopID();
|
||||
|
||||
ImGui::EndChild();
|
||||
}
|
||||
|
||||
ImGui::Button(STRING_IMGUI_SPRITESHEETS_ADD);
|
||||
_imgui_tooltip(STRING_IMGUI_TOOLTIP_SPRITESHEETS_ADD);
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
if (selectedSpritesheetID != -1)
|
||||
{
|
||||
if (ImGui::Button(STRING_IMGUI_SPRITESHEETS_REMOVE))
|
||||
{
|
||||
self->anm2->spritesheets.erase(selectedSpritesheetID);
|
||||
selectedSpritesheetID = -1;
|
||||
}
|
||||
_imgui_tooltip(STRING_IMGUI_TOOLTIP_SPRITESHEETS_REMOVE);
|
||||
|
||||
ImGui::SameLine();
|
||||
ImGui::Button(STRING_IMGUI_SPRITESHEETS_RELOAD);
|
||||
_imgui_tooltip(STRING_IMGUI_TOOLTIP_SPRITESHEETS_RELOAD);
|
||||
ImGui::SameLine();
|
||||
ImGui::Button(STRING_IMGUI_SPRITESHEETS_REPLACE);
|
||||
_imgui_tooltip(STRING_IMGUI_TOOLTIP_SPRITESHEETS_REPLACE);
|
||||
}
|
||||
|
||||
if (ImGui::IsMouseClicked(0) && !ImGui::IsAnyItemHovered() && ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem))
|
||||
selectedSpritesheetID = -1;
|
||||
|
||||
ImGui::End();
|
||||
|
||||
/* -- Frame Properties -- */
|
||||
|
||||
ImGui::Begin(STRING_IMGUI_FRAME_PROPERTIES);
|
||||
|
||||
ImGui::DragFloat2(STRING_IMGUI_FRAME_PROPERTIES_POSITION, value_ptr(position), 1, 0, 0, "%.0f");
|
||||
_imgui_tooltip(STRING_IMGUI_TOOLTIP_FRAME_PROPERTIES_POSITION);
|
||||
|
||||
ImGui::DragFloat2(STRING_IMGUI_FRAME_PROPERTIES_CROP_POSITION, value_ptr(cropPosition), 1, 0, 0, "%.0f");
|
||||
_imgui_tooltip(STRING_IMGUI_TOOLTIP_FRAME_PROPERTIES_CROP_POSITION);
|
||||
|
||||
ImGui::DragFloat2(STRING_IMGUI_FRAME_PROPERTIES_CROP_SIZE, value_ptr(cropSize), 1, 0, 0, "%.0f");
|
||||
_imgui_tooltip(STRING_IMGUI_TOOLTIP_FRAME_PROPERTIES_CROP_SIZE);
|
||||
|
||||
ImGui::DragFloat2(STRING_IMGUI_FRAME_PROPERTIES_PIVOT, value_ptr(pivot), 1, 0, 0, "%.0f");
|
||||
_imgui_tooltip(STRING_IMGUI_TOOLTIP_FRAME_PROPERTIES_PIVOT);
|
||||
|
||||
ImGui::DragFloat2(STRING_IMGUI_FRAME_PROPERTIES_SCALE, value_ptr(xyScale), 1.0, 0, 0, "%.1f");
|
||||
_imgui_tooltip(STRING_IMGUI_TOOLTIP_FRAME_PROPERTIES_SCALE);
|
||||
|
||||
ImGui::DragFloat(STRING_IMGUI_FRAME_PROPERTIES_ROTATION, &rotation, 1, 0, 0, "%.1f");
|
||||
_imgui_tooltip(STRING_IMGUI_TOOLTIP_FRAME_PROPERTIES_ROTATION);
|
||||
|
||||
ImGui::DragInt(STRING_IMGUI_FRAME_PROPERTIES_DURATION, &duration, 1, 0, 255);
|
||||
_imgui_tooltip(STRING_IMGUI_TOOLTIP_FRAME_PROPERTIES_DURATION);
|
||||
|
||||
ImGui::ColorEdit4(STRING_IMGUI_FRAME_PROPERTIES_TINT, value_ptr(tint));
|
||||
_imgui_tooltip(STRING_IMGUI_TOOLTIP_FRAME_PROPERTIES_TINT);
|
||||
|
||||
ImGui::ColorEdit3(STRING_IMGUI_FRAME_PROPERTIES_COLOR_OFFSET, value_ptr(offset));
|
||||
_imgui_tooltip(STRING_IMGUI_TOOLTIP_FRAME_PROPERTIES_COLOR_OFFSET);
|
||||
|
||||
ImGui::Checkbox(STRING_IMGUI_FRAME_PROPERTIES_VISIBLE, &isVisible);
|
||||
_imgui_tooltip(STRING_IMGUI_TOOLTIP_FRAME_PROPERTIES_VISIBLE);
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::Checkbox(STRING_IMGUI_FRAME_PROPERTIES_INTERPOLATED, &isInterpolated);
|
||||
_imgui_tooltip(STRING_IMGUI_TOOLTIP_FRAME_PROPERTIES_INTERPOLATED);
|
||||
|
||||
ImGui::End();
|
||||
|
||||
/* -- Animation Preview -- */
|
||||
|
||||
ImGui::Begin(STRING_IMGUI_ANIMATION_PREVIEW);
|
||||
|
||||
/* Settings */
|
||||
ImGui::BeginChild(STRING_IMGUI_ANIMATION_PREVIEW_SETTINGS, IMGUI_ANIMATION_PREVIEW_SETTINGS_SIZE, true);
|
||||
|
||||
/* Grid settings */
|
||||
ImGui::BeginChild(STRING_IMGUI_ANIMATION_PREVIEW_GRID_SETTINGS, IMGUI_ANIMATION_PREVIEW_SETTINGS_GRID_SIZE, true);
|
||||
|
||||
/* Grid toggle */
|
||||
ImGui::Checkbox(STRING_IMGUI_ANIMATION_PREVIEW_GRID, &self->preview->isGrid);
|
||||
_imgui_tooltip(STRING_IMGUI_TOOLTIP_ANIMATION_PREVIEW_GRID);
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
/* Grid Color */
|
||||
ImGui::ColorEdit4(STRING_IMGUI_ANIMATION_PREVIEW_GRID_COLOR, value_ptr(self->preview->gridColor), ImGuiColorEditFlags_NoInputs);
|
||||
_imgui_tooltip(STRING_IMGUI_TOOLTIP_ANIMATION_PREVIEW_GRID_COLOR);
|
||||
|
||||
/* Grid Size */
|
||||
ImGui::InputInt2(STRING_IMGUI_ANIMATION_PREVIEW_GRID_SIZE, value_ptr(self->preview->gridSize));
|
||||
self->preview->gridSize.x = CLAMP(self->preview->gridSize.x, PREVIEW_GRID_MIN, PREVIEW_GRID_MAX);
|
||||
self->preview->gridSize.y = CLAMP(self->preview->gridSize.y, PREVIEW_GRID_MIN, PREVIEW_GRID_MAX);
|
||||
_imgui_tooltip(STRING_IMGUI_TOOLTIP_ANIMATION_PREVIEW_GRID_SIZE);
|
||||
|
||||
ImGui::EndChild();
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
/* Zoom settings */
|
||||
ImGui::BeginChild(STRING_IMGUI_ANIMATION_PREVIEW_ZOOM_SETTINGS, IMGUI_ANIMATION_PREVIEW_SETTINGS_ZOOM_SIZE, true);
|
||||
|
||||
/* Zoom */
|
||||
ImGui::DragFloat(STRING_IMGUI_ANIMATION_PREVIEW_ZOOM, &self->preview->zoom, 1, PREVIEW_ZOOM_MIN, PREVIEW_ZOOM_MAX, "%.0f");
|
||||
_imgui_tooltip(STRING_IMGUI_TOOLTIP_ANIMATION_PREVIEW_ZOOM);
|
||||
|
||||
ImGui::EndChild();
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
/* Background settings */
|
||||
ImGui::BeginChild(STRING_IMGUI_ANIMATION_PREVIEW_BACKGROUND_SETTINGS, IMGUI_ANIMATION_PREVIEW_SETTINGS_BACKGROUND_SIZE, true);
|
||||
|
||||
/* Background color */
|
||||
ImGui::ColorEdit4(STRING_IMGUI_ANIMATION_PREVIEW_BACKGROUND_COLOR, value_ptr(self->preview->color), ImGuiColorEditFlags_NoInputs);
|
||||
_imgui_tooltip(STRING_IMGUI_TOOLTIP_ANIMATION_PREVIEW_BACKGROUND_COLOR);
|
||||
|
||||
ImGui::EndChild();
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::EndChild();
|
||||
|
||||
ImGui::Image(self->preview->texture, ImVec2(PREVIEW_SIZE.x, PREVIEW_SIZE.y));
|
||||
|
||||
ImGui::End();
|
||||
|
||||
/* -- Spritesheet Editor -- */
|
||||
|
||||
ImGui::Begin(STRING_IMGUI_SPRITESHEET_EDITOR);
|
||||
|
||||
ImGui::End();
|
||||
|
||||
/* -- Timeline -- */
|
||||
ImGui::Begin(STRING_IMGUI_TIMELINE);
|
||||
|
||||
if (selectedAnimationID != -1)
|
||||
{
|
||||
s32 index = 0;
|
||||
Anm2Animation* animation = &self->anm2->animations[selectedAnimationID];
|
||||
|
||||
ImGui::BeginChild(STRING_IMGUI_TIMELINE_ANIMATIONS, IMGUI_TIMELINE_ELEMENT_LIST_SIZE, true);
|
||||
|
||||
/* Root */
|
||||
_imgui_timeline_element(self, &animation->rootAnimation, NULL, &index, ANM2_ROOT_ANIMATION, NULL, NULL);
|
||||
|
||||
/* reverse order */
|
||||
for (auto it = animation->layerAnimations.rbegin(); it != animation->layerAnimations.rend(); it++)
|
||||
{
|
||||
s32 id = it->first;
|
||||
Anm2LayerAnimation& layer = it->second;
|
||||
|
||||
_imgui_timeline_element(self, &layer, &id, &index, ANM2_LAYER_ANIMATION, &selectedTimelineElementType, &selectedTimelineElementID);
|
||||
}
|
||||
|
||||
for (auto & [id, null] : animation->nullAnimations)
|
||||
_imgui_timeline_element(self, &null, (s32*)&id, &index, ANM2_NULL_ANIMATION, &selectedTimelineElementType, &selectedTimelineElementID);
|
||||
|
||||
/* Triggers */
|
||||
_imgui_timeline_element(self, &animation->triggers, NULL, &index, ANM2_TRIGGERS, NULL, NULL);
|
||||
|
||||
/* Element configuration */
|
||||
if (ImGui::Button(STRING_IMGUI_TIMELINE_ELEMENT_ADD))
|
||||
ImGui::OpenPopup(STRING_IMGUI_TIMELINE_ELEMENT_ADD_MENU);
|
||||
_imgui_tooltip(STRING_IMGUI_TOOLTIP_TIMELINE_ELEMENT_ADD);
|
||||
|
||||
|
||||
if (ImGui::BeginPopup(STRING_IMGUI_TIMELINE_ELEMENT_ADD_MENU))
|
||||
{
|
||||
if (ImGui::Selectable(STRING_IMGUI_TIMELINE_ELEMENT_ADD_MENU_LAYER))
|
||||
anm2_layer_add(self->anm2);
|
||||
|
||||
if (ImGui::Selectable(STRING_IMGUI_TIMELINE_ELEMENT_ADD_MENU_NULL))
|
||||
anm2_null_add(self->anm2);
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
if
|
||||
(
|
||||
selectedTimelineElementID != -1 &&
|
||||
((selectedTimelineElementType == ANM2_LAYER_ANIMATION) || (selectedTimelineElementType == ANM2_NULL_ANIMATION))
|
||||
)
|
||||
{
|
||||
if (ImGui::Button(STRING_IMGUI_TIMELINE_ELEMENT_REMOVE))
|
||||
{
|
||||
switch (selectedTimelineElementType)
|
||||
{
|
||||
case ANM2_LAYER_ANIMATION:
|
||||
anm2_layer_remove(self->anm2, selectedTimelineElementID);
|
||||
break;
|
||||
case ANM2_NULL_ANIMATION:
|
||||
anm2_null_remove(self->anm2, selectedTimelineElementID);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
selectedTimelineElementID = -1;
|
||||
selectedTimelineElementType = ANM2_NONE;
|
||||
}
|
||||
|
||||
_imgui_tooltip(STRING_IMGUI_TOOLTIP_TIMELINE_ELEMENT_REMOVE);
|
||||
}
|
||||
else
|
||||
{
|
||||
selectedTimelineElementID = -1;
|
||||
selectedTimelineElementType = ANM2_NONE;
|
||||
}
|
||||
|
||||
ImGui::EndChild();
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
/* Animation playback and frames */
|
||||
static bool isPlaying = false;
|
||||
|
||||
if (isPlaying)
|
||||
{
|
||||
if (ImGui::Button(STRING_IMGUI_TIMELINE_PAUSE))
|
||||
{
|
||||
isPlaying = !isPlaying;
|
||||
}
|
||||
_imgui_tooltip(STRING_IMGUI_TOOLTIP_TIMELINE_PLAY);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ImGui::Button(STRING_IMGUI_TIMELINE_PLAY))
|
||||
{
|
||||
isPlaying = !isPlaying;
|
||||
}
|
||||
_imgui_tooltip(STRING_IMGUI_TOOLTIP_TIMELINE_PAUSE);
|
||||
}
|
||||
|
||||
/*
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::Button(STRING_IMGUI_TIMELINE_ADD_FRAME))
|
||||
{
|
||||
|
||||
}
|
||||
_imgui_tooltip(STRING_IMGUI_TOOLTIP_TIMELINE_FRAME_ADD);
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::Button(STRING_IMGUI_TIMELINE_REMOVE_FRAME))
|
||||
{
|
||||
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
imgui_draw(void)
|
||||
imgui_draw(Imgui* self)
|
||||
{
|
||||
ImGui::Render();
|
||||
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
||||
}
|
||||
|
||||
void
|
||||
imgui_free(void)
|
||||
imgui_free(Imgui* self)
|
||||
{
|
||||
ImGui_ImplSDL3_Shutdown();
|
||||
ImGui_ImplOpenGL3_Shutdown();
|
||||
|
47
src/imgui.h
47
src/imgui.h
@ -1,15 +1,50 @@
|
||||
#pragma once
|
||||
|
||||
#include "COMMON.h"
|
||||
#include "dialog.h"
|
||||
#include "packed.h"
|
||||
#include "preview.h"
|
||||
#include "window.h"
|
||||
|
||||
#define IMGUI_IMPL_OPENGL_LOADER_CUSTOM
|
||||
#define IMGUI_ENABLE_DOCKING
|
||||
#include <imgui/imgui.h>
|
||||
#include <imgui/imgui_impl_sdl3.h>
|
||||
#include <imgui/imgui_impl_opengl3.h>
|
||||
#include <imgui/imgui_internal.h>
|
||||
#include <imgui/backends/imgui_impl_sdl3.h>
|
||||
#include <imgui/backends/imgui_impl_opengl3.h>
|
||||
|
||||
#define IMGUI_DRAG_SPEED 1.0
|
||||
#define IMGUI_TASKBAR_HEIGHT 32
|
||||
|
||||
static const vec2 IMGUI_TASKBAR_MARGINS = {8, 4};
|
||||
|
||||
static const ImVec2 IMGUI_ANIMATION_PREVIEW_SETTINGS_SIZE = {1280, 64};
|
||||
static const ImVec2 IMGUI_ANIMATION_PREVIEW_SETTINGS_GRID_SIZE = {150, 64};
|
||||
static const ImVec2 IMGUI_ANIMATION_PREVIEW_SETTINGS_ZOOM_SIZE = {150, 64};
|
||||
static const ImVec2 IMGUI_ANIMATION_PREVIEW_SETTINGS_BACKGROUND_SIZE = {150, 64};
|
||||
|
||||
static const ImVec2 IMGUI_TIMELINE_ELEMENT_LIST_SIZE = {260, 0};
|
||||
static const ImVec2 IMGUI_TIMELINE_ELEMENT_SIZE = {230, 64};
|
||||
static const ImVec2 IMGUI_TIMELINE_SPRITESHEET_ID_SIZE = {50, 20};
|
||||
static const ImVec2 IMGUI_TIMELINE_SHIFT_ARROWS_SIZE = {24, 48};
|
||||
static const ImVec2 IMGUI_TIMELINE_ELEMENT_NAME_SIZE = {125, 20};
|
||||
|
||||
static const ImVec2 IMGUI_SPRITESHEET_SIZE = {0, 150};
|
||||
static const ImVec2 IMGUI_ICON_SIZE = {16, 16};
|
||||
static const ImVec2 IMGUI_ICON_BUTTON_SIZE = {22, 22};
|
||||
static const ImVec2 IMGUI_DUMMY_SIZE = {1, 1};
|
||||
|
||||
#define IMGUI_TIMELINE_SHIFT_ARROWS_WIDTH (IMGUI_TIMELINE_SHIFT_ARROWS_SIZE.x * 1.35)
|
||||
|
||||
struct Imgui
|
||||
{
|
||||
Dialog* dialog = NULL;
|
||||
Packed* packed = NULL;
|
||||
Anm2* anm2 = NULL;
|
||||
Preview* preview = NULL;
|
||||
SDL_Window* window = NULL;
|
||||
};
|
||||
|
||||
void imgui_init(SDL_Window* window, SDL_GLContext glContext);
|
||||
void imgui_tick(State* state);
|
||||
void imgui_draw();
|
||||
void imgui_free();
|
||||
void imgui_tick(Imgui* self);
|
||||
void imgui_draw(Imgui* self);
|
||||
void imgui_free(Imgui* self);
|
||||
|
125
src/main.cpp
125
src/main.cpp
@ -1,128 +1,23 @@
|
||||
#include "main.h"
|
||||
|
||||
static void _init(State* state);
|
||||
static void _draw(State* state);
|
||||
static void _loop(State* state);
|
||||
static void _quit(State* state);
|
||||
static void _tick(State* state);
|
||||
|
||||
static void
|
||||
_init(State* state)
|
||||
{
|
||||
Shader shader;
|
||||
|
||||
printf(STRING_INFO_INIT);
|
||||
|
||||
if (!SDL_Init(SDL_INIT_VIDEO))
|
||||
{
|
||||
printf(STRING_ERROR_SDL_INIT, SDL_GetError());
|
||||
_quit(state);
|
||||
}
|
||||
|
||||
printf(STRING_INFO_SDL_INIT);
|
||||
|
||||
SDL_CreateWindowAndRenderer
|
||||
(
|
||||
STRING_WINDOW_TITLE,
|
||||
WINDOW_WIDTH,
|
||||
WINDOW_HEIGHT,
|
||||
WINDOW_FLAGS,
|
||||
&state->window,
|
||||
&state->renderer
|
||||
);
|
||||
|
||||
state->glContext = SDL_GL_CreateContext(state->window);
|
||||
|
||||
if (!state->glContext)
|
||||
{
|
||||
printf(STRING_ERROR_GL_CONTEXT_INIT, SDL_GetError());
|
||||
_quit(state);
|
||||
}
|
||||
|
||||
glewInit();
|
||||
|
||||
printf(STRING_INFO_GLEW_INIT);
|
||||
|
||||
shader_init(&shader, RESOURCE_SHADER_VERTEX_TEXTURE_QUAD, RESOURCE_SHADER_FRAGMENT_TEXTURE_QUAD);
|
||||
|
||||
imgui_init(state->window, state->glContext);
|
||||
|
||||
Anm2 anm2;
|
||||
|
||||
anm2_init(&anm2, "res/anm2/005.031_key.anm2");
|
||||
}
|
||||
|
||||
void
|
||||
_loop(State* state)
|
||||
{
|
||||
state->tick = SDL_GetTicks();
|
||||
|
||||
while (state->tick > state->lastTick + TICK_DELAY)
|
||||
{
|
||||
state->tick = SDL_GetTicks();
|
||||
|
||||
if (state->tick - state->lastTick < TICK_DELAY)
|
||||
SDL_Delay(TICK_DELAY - (state->tick - state->lastTick));
|
||||
|
||||
_tick(state);
|
||||
|
||||
imgui_tick(state);
|
||||
|
||||
_draw(state);
|
||||
|
||||
state->lastTick = state->tick;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_tick(State* state)
|
||||
{
|
||||
SDL_Event event;
|
||||
|
||||
while(SDL_PollEvent(&event))
|
||||
{
|
||||
ImGui_ImplSDL3_ProcessEvent(&event);
|
||||
|
||||
if (event.type == SDL_EVENT_QUIT)
|
||||
state->isRunning = false;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_draw(State* state)
|
||||
{
|
||||
glClearColor(state->clearColor.x, state->clearColor.y, state->clearColor.z, 1.0);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
imgui_draw();
|
||||
|
||||
SDL_GL_SwapWindow(state->window);
|
||||
}
|
||||
|
||||
void
|
||||
_quit(State* state)
|
||||
{
|
||||
imgui_free();
|
||||
|
||||
SDL_GL_DestroyContext(state->glContext);
|
||||
SDL_Quit();
|
||||
|
||||
printf(STRING_INFO_SDL_QUIT);
|
||||
|
||||
printf(STRING_INFO_QUIT);
|
||||
}
|
||||
|
||||
s32
|
||||
main(s32 argc, char* argv[])
|
||||
{
|
||||
State state;
|
||||
|
||||
_init(&state);
|
||||
/* 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.isArgument = true;
|
||||
}
|
||||
|
||||
init(&state);
|
||||
|
||||
while (state.isRunning)
|
||||
_loop(&state);
|
||||
loop(&state);
|
||||
|
||||
_quit(&state);
|
||||
quit(&state);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
10
src/main.h
10
src/main.h
@ -1,11 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
#include "texture.h"
|
||||
#include "shader.h"
|
||||
#include "imgui.h"
|
||||
#include "anm2.h"
|
||||
|
||||
#define TICK_DELAY 16
|
||||
#define WINDOW_WIDTH 1600
|
||||
#define WINDOW_HEIGHT 900
|
||||
#define WINDOW_FLAGS SDL_WINDOW_RESIZABLE
|
||||
#include "state.h"
|
17
src/packed.cpp
Normal file
17
src/packed.cpp
Normal file
@ -0,0 +1,17 @@
|
||||
#include "packed.h"
|
||||
|
||||
/* Loads in packed data */
|
||||
void
|
||||
packed_init(Packed* self)
|
||||
{
|
||||
for (s32 i = 0; i < PACKED_TEXTURE_COUNT; i++)
|
||||
texture_from_data_init(&self->textures[i], (u8*)PACKED_TEXTURE_DATA[i].data, PACKED_TEXTURE_DATA[i].length);
|
||||
}
|
||||
|
||||
/* Frees packed data */
|
||||
void
|
||||
packed_free(Packed* self)
|
||||
{
|
||||
for (s32 i = 0; i < PACKED_TEXTURE_COUNT; i++)
|
||||
texture_free(&self->textures[i]);
|
||||
}
|
12
src/packed.h
Normal file
12
src/packed.h
Normal file
@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include "PACKED.h"
|
||||
#include "texture.h"
|
||||
|
||||
struct Packed
|
||||
{
|
||||
Texture textures[PACKED_TEXTURE_COUNT];
|
||||
};
|
||||
|
||||
void packed_init(Packed* self);
|
||||
void packed_free(Packed* self);
|
48
src/preview.cpp
Normal file
48
src/preview.cpp
Normal file
@ -0,0 +1,48 @@
|
||||
#include "preview.h"
|
||||
|
||||
|
||||
/* Initializes the preview */
|
||||
void
|
||||
preview_init(Preview* self)
|
||||
{
|
||||
glGenFramebuffers(1, &self->fbo);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, self->fbo);
|
||||
|
||||
glGenTextures(1, &self->texture);
|
||||
glBindTexture(GL_TEXTURE_2D, self->texture);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, PREVIEW_SIZE.x, PREVIEW_SIZE.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, self->texture, 0);
|
||||
|
||||
glGenRenderbuffers(1, &self->rbo);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, self->rbo);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, PREVIEW_SIZE.x, PREVIEW_SIZE.y);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, self->rbo);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
void
|
||||
preview_draw(Preview* self)
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, self->fbo);
|
||||
glViewport(0, 0, PREVIEW_SIZE.x, PREVIEW_SIZE.y);
|
||||
|
||||
glClearColor(self->color.r, self->color.g, self->color.b, self->color.a);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0); // unbind
|
||||
}
|
||||
|
||||
void
|
||||
preview_free(Preview* self)
|
||||
{
|
||||
glDeleteTextures(1, &self->texture);
|
||||
glDeleteFramebuffers(1, &self->fbo);
|
||||
glDeleteRenderbuffers(1, &self->rbo);
|
||||
|
||||
memset(self, '\0', sizeof(Preview));
|
||||
}
|
26
src/preview.h
Normal file
26
src/preview.h
Normal file
@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include "texture.h"
|
||||
|
||||
static const ivec2 PREVIEW_SIZE = {1280, 720};
|
||||
|
||||
#define PREVIEW_ZOOM_MIN 0
|
||||
#define PREVIEW_ZOOM_MAX 400
|
||||
#define PREVIEW_GRID_MIN 0
|
||||
#define PREVIEW_GRID_MAX 20
|
||||
|
||||
struct Preview
|
||||
{
|
||||
GLuint texture;
|
||||
GLuint fbo;
|
||||
GLuint rbo;
|
||||
bool isGrid;
|
||||
f32 zoom = 100;
|
||||
ivec2 gridSize = {10, 10};
|
||||
vec4 color = {0.69, 0.69, 0.69, 1.0f};
|
||||
vec4 gridColor = {0.35, 0.35, 0.35, 1.0f};
|
||||
};
|
||||
|
||||
void preview_init(Preview* self);
|
||||
void preview_draw(Preview* self);
|
||||
void preview_free(Preview* self);
|
@ -1,17 +1,14 @@
|
||||
#include "shader.h"
|
||||
|
||||
static bool _shader_compile(GLuint handle, const char* path);
|
||||
static bool _shader_compile(GLuint handle, const char* text);
|
||||
|
||||
static bool
|
||||
_shader_compile(GLuint handle, const char* path)
|
||||
_shader_compile(GLuint handle, const char* text)
|
||||
{
|
||||
char buffer[SHADER_BUFFER_MAX];
|
||||
char compileLog[SHADER_BUFFER_MAX];
|
||||
s32 isCompile;
|
||||
|
||||
file_read(path, buffer, SHADER_BUFFER_MAX);
|
||||
|
||||
const GLchar* source = buffer;
|
||||
const GLchar* source = text;
|
||||
|
||||
glShaderSource(handle, 1, &source, NULL);
|
||||
|
||||
@ -21,7 +18,7 @@ _shader_compile(GLuint handle, const char* path)
|
||||
if (!isCompile)
|
||||
{
|
||||
glGetShaderInfoLog(handle, SHADER_BUFFER_MAX, NULL, compileLog);
|
||||
printf(STRING_ERROR_SHADER_INIT, path, compileLog);
|
||||
printf(STRING_ERROR_SHADER_INIT, handle, compileLog);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -29,7 +26,7 @@ _shader_compile(GLuint handle, const char* path)
|
||||
}
|
||||
|
||||
bool
|
||||
shader_init(Shader* self, const char* vertexPath, const char* fragmentPath)
|
||||
shader_init(Shader* self, const char* vertex, const char* fragment)
|
||||
{
|
||||
GLuint vertexHandle;
|
||||
GLuint fragmentHandle;
|
||||
@ -42,8 +39,8 @@ shader_init(Shader* self, const char* vertexPath, const char* fragmentPath)
|
||||
|
||||
if
|
||||
(
|
||||
!_shader_compile(vertexHandle, vertexPath) ||
|
||||
!_shader_compile(fragmentHandle, fragmentPath)
|
||||
!_shader_compile(vertexHandle, vertex) ||
|
||||
!_shader_compile(fragmentHandle, fragment)
|
||||
)
|
||||
return false;
|
||||
|
||||
@ -57,7 +54,7 @@ shader_init(Shader* self, const char* vertexPath, const char* fragmentPath)
|
||||
glDeleteShader(vertexHandle);
|
||||
glDeleteShader(fragmentHandle);
|
||||
|
||||
printf(STRING_INFO_SHADER_INIT, vertexPath, fragmentPath);
|
||||
printf(STRING_INFO_SHADER_INIT, self->handle);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "file.h"
|
||||
#include "COMMON.h"
|
||||
|
||||
#define SHADER_BUFFER_MAX 2048
|
||||
|
||||
@ -9,6 +9,6 @@ struct Shader
|
||||
GLuint handle = 0;
|
||||
};
|
||||
|
||||
bool shader_init(Shader* self, const char* vertexPath, const char* fragmentPath);
|
||||
bool shader_init(Shader* self, const char* vertex, const char* fragment);
|
||||
void shader_free(Shader* self);
|
||||
void shader_use(Shader* self);
|
||||
|
128
src/state.cpp
Normal file
128
src/state.cpp
Normal file
@ -0,0 +1,128 @@
|
||||
#include "state.h"
|
||||
|
||||
static void _tick(State* state);
|
||||
static void _draw(State* state);
|
||||
|
||||
static void
|
||||
_tick(State* state)
|
||||
{
|
||||
SDL_Event event;
|
||||
|
||||
while(SDL_PollEvent(&event))
|
||||
{
|
||||
ImGui_ImplSDL3_ProcessEvent(&event);
|
||||
|
||||
if (event.type == SDL_EVENT_QUIT)
|
||||
state->isRunning = false;
|
||||
}
|
||||
|
||||
dialog_tick(&state->dialog);
|
||||
imgui_tick(&state->imgui);
|
||||
}
|
||||
|
||||
static void
|
||||
_draw(State* state)
|
||||
{
|
||||
preview_draw(&state->preview);
|
||||
imgui_draw(&state->imgui);
|
||||
|
||||
SDL_GL_SwapWindow(state->window);
|
||||
}
|
||||
|
||||
void
|
||||
init(State* state)
|
||||
{
|
||||
Shader shader;
|
||||
|
||||
printf(STRING_INFO_INIT);
|
||||
|
||||
if (!SDL_Init(SDL_INIT_VIDEO))
|
||||
{
|
||||
printf(STRING_ERROR_SDL_INIT, SDL_GetError());
|
||||
quit(state);
|
||||
}
|
||||
|
||||
printf(STRING_INFO_SDL_INIT);
|
||||
|
||||
SDL_CreateWindowAndRenderer
|
||||
(
|
||||
STRING_WINDOW_TITLE,
|
||||
WINDOW_WIDTH,
|
||||
WINDOW_HEIGHT,
|
||||
WINDOW_FLAGS,
|
||||
&state->window,
|
||||
&state->renderer
|
||||
);
|
||||
|
||||
state->glContext = SDL_GL_CreateContext(state->window);
|
||||
|
||||
if (!state->glContext)
|
||||
{
|
||||
printf(STRING_ERROR_GL_CONTEXT_INIT, SDL_GetError());
|
||||
quit(state);
|
||||
}
|
||||
|
||||
glewInit();
|
||||
|
||||
preview_init(&state->preview);
|
||||
|
||||
printf(STRING_INFO_GLEW_INIT);
|
||||
|
||||
packed_init(&state->packed);
|
||||
|
||||
if (state->isArgument)
|
||||
anm2_deserialize(&state->anm2, state->argument);
|
||||
else
|
||||
anm2_new(&state->anm2);
|
||||
|
||||
window_title_from_anm2_set(state->window, &state->anm2);
|
||||
|
||||
state->imgui =
|
||||
{
|
||||
&state->dialog,
|
||||
&state->packed,
|
||||
&state->anm2,
|
||||
&state->preview,
|
||||
state->window
|
||||
};
|
||||
|
||||
imgui_init(state->window, state->glContext);
|
||||
|
||||
state->dialog.anm2 = &state->anm2;
|
||||
}
|
||||
|
||||
void
|
||||
loop(State* state)
|
||||
{
|
||||
state->tick = SDL_GetTicks();
|
||||
|
||||
while (state->tick > state->lastTick + TICK_DELAY)
|
||||
{
|
||||
state->tick = SDL_GetTicks();
|
||||
|
||||
if (state->tick - state->lastTick < TICK_DELAY)
|
||||
SDL_Delay(TICK_DELAY - (state->tick - state->lastTick));
|
||||
|
||||
_tick(state);
|
||||
|
||||
_draw(state);
|
||||
|
||||
state->lastTick = state->tick;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
quit(State* state)
|
||||
{
|
||||
imgui_free(&state->imgui);
|
||||
preview_free(&state->preview);
|
||||
packed_free(&state->packed);
|
||||
|
||||
SDL_GL_DestroyContext(state->glContext);
|
||||
SDL_Quit();
|
||||
|
||||
printf(STRING_INFO_SDL_QUIT);
|
||||
|
||||
printf(STRING_INFO_QUIT);
|
||||
}
|
||||
|
30
src/state.h
Normal file
30
src/state.h
Normal file
@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include "shader.h"
|
||||
#include "imgui.h"
|
||||
|
||||
#define TICK_DELAY 16
|
||||
#define WINDOW_WIDTH 1600
|
||||
#define WINDOW_HEIGHT 900
|
||||
#define WINDOW_FLAGS SDL_WINDOW_RESIZABLE
|
||||
|
||||
struct State
|
||||
{
|
||||
SDL_Window* window;
|
||||
SDL_Renderer* renderer;
|
||||
SDL_GLContext glContext;
|
||||
Imgui imgui;
|
||||
Dialog dialog;
|
||||
Preview preview;
|
||||
Anm2 anm2;
|
||||
Packed packed;
|
||||
char argument[PATH_MAX] = STRING_EMPTY;
|
||||
bool isArgument = false;
|
||||
u64 tick = 0;
|
||||
u64 lastTick = 0;
|
||||
bool isRunning = true;
|
||||
};
|
||||
|
||||
void init(State* state);
|
||||
void loop(State* state);
|
||||
void quit(State* state);
|
@ -6,16 +6,9 @@
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include <stb_image.h>
|
||||
|
||||
bool
|
||||
texture_init(Texture* self, const char* path)
|
||||
void
|
||||
texture_gl_set(Texture* self, void* data)
|
||||
{
|
||||
void* data;
|
||||
|
||||
data = stbi_load(path, &self->size[0], &self->size[1], &self->channels, 4);
|
||||
|
||||
if (!data)
|
||||
return false;
|
||||
|
||||
glGenTextures(1, &self->handle);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, self->handle);
|
||||
@ -27,7 +20,40 @@ texture_init(Texture* self, const char* path)
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0); /* unbinds */
|
||||
}
|
||||
|
||||
bool
|
||||
texture_from_path_init(Texture* self, const char* path)
|
||||
{
|
||||
void* data;
|
||||
|
||||
data = stbi_load(path, &self->size.x, &self->size.y, &self->channels, 4);
|
||||
|
||||
if (!data)
|
||||
{
|
||||
printf(STRING_ERROR_TEXTURE_INIT, path);
|
||||
return false;
|
||||
}
|
||||
|
||||
printf(STRING_INFO_TEXTURE_INIT, path);
|
||||
|
||||
texture_gl_set(self, data);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
texture_from_data_init(Texture* self, const u8* data, u32 length)
|
||||
{
|
||||
void* textureData;
|
||||
|
||||
textureData = stbi_load_from_memory(data, length, &self->size.x, &self->size.y, &self->channels, 4);
|
||||
|
||||
if (!textureData)
|
||||
return false;
|
||||
|
||||
texture_gl_set(self, textureData);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -9,5 +9,7 @@ struct Texture
|
||||
s32 channels = -1;
|
||||
};
|
||||
|
||||
bool texture_init(Texture* self, const char* path);
|
||||
void texture_gl_set(Texture* self, void* data);
|
||||
bool texture_from_path_init(Texture* self, const char* path);
|
||||
bool texture_from_data_init(Texture* self, const u8* data, u32 length);
|
||||
void texture_free(Texture* self);
|
||||
|
15
src/window.cpp
Normal file
15
src/window.cpp
Normal file
@ -0,0 +1,15 @@
|
||||
#include "window.h"
|
||||
|
||||
/* Sets the window title from the given anm2 */
|
||||
void
|
||||
window_title_from_anm2_set(SDL_Window* self, Anm2* anm2)
|
||||
{
|
||||
if (!strcmp(anm2->path, STRING_EMPTY) == 0)
|
||||
{
|
||||
char windowTitle[WINDOW_TITLE_MAX];
|
||||
snprintf(windowTitle, WINDOW_TITLE_MAX, STRING_WINDOW_TITLE_EDITING, anm2->path);
|
||||
SDL_SetWindowTitle(self, windowTitle);
|
||||
}
|
||||
else
|
||||
SDL_SetWindowTitle(self, STRING_WINDOW_TITLE);
|
||||
}
|
7
src/window.h
Normal file
7
src/window.h
Normal file
@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "anm2.h"
|
||||
|
||||
#define WINDOW_TITLE_MAX 0xFF + PATH_MAX
|
||||
|
||||
void window_title_from_anm2_set(SDL_Window* self, Anm2* anm2);
|
Reference in New Issue
Block a user