mirror of
https://github.com/korenkonder/ReDIVA.git
synced 2026-10-12 17:18:10 +03:00
7663 lines
304 KiB
C++
7663 lines
304 KiB
C++
/*
|
|
by korenkonder
|
|
GitHub/GitLab: korenkonder
|
|
|
|
Curve Editor code based on Animation Timeline code from https://github.com/crash5band/Glitter
|
|
*/
|
|
|
|
#if defined(ReDIVA_DEV)
|
|
#include "glitter_editor.hpp"
|
|
#include "../KKdLib/io/file_stream.hpp"
|
|
#include "../KKdLib/io/path.hpp"
|
|
#include "../KKdLib/dds.hpp"
|
|
#include "../KKdLib/interpolation.hpp"
|
|
#include "../KKdLib/str_utils.hpp"
|
|
#include "../KKdLib/txp.hpp"
|
|
#include "../KKdLib/vec.hpp"
|
|
#include "../CRE/Glitter/glitter.hpp"
|
|
#include "../CRE/camera.hpp"
|
|
#include "../CRE/data.hpp"
|
|
#include "../CRE/gl_state.hpp"
|
|
#include "../CRE/render_context.hpp"
|
|
#include "../CRE/shader_dev.hpp"
|
|
#include "../CRE/stage.hpp"
|
|
#include "../CRE/static_var.hpp"
|
|
#include "data_test/stage_test.hpp"
|
|
#include "imgui_helper.hpp"
|
|
#include "input.hpp"
|
|
#include <windows.h>
|
|
#include <commdlg.h>
|
|
#include <shobjidl.h>
|
|
#include <glad/glad.h>
|
|
|
|
static const float_t curve_base_values[] = {
|
|
0.0f,
|
|
0.0f,
|
|
0.0f,
|
|
0.0f,
|
|
0.0f,
|
|
0.0f,
|
|
1.0f,
|
|
1.0f,
|
|
1.0f,
|
|
1.0f,
|
|
1.0f,
|
|
1.0f,
|
|
1.0f,
|
|
1.0f,
|
|
1.0f,
|
|
1.0f,
|
|
1.0f,
|
|
1.0f,
|
|
1.0f,
|
|
1.0f,
|
|
0.0f,
|
|
0.0f,
|
|
0.0f,
|
|
0.0f,
|
|
0.0f,
|
|
0.0f,
|
|
0.0f,
|
|
0.0f,
|
|
0.0f,
|
|
0.0f,
|
|
};
|
|
|
|
static const float_t curve_editor_timeline_base_pos = 50.0f;
|
|
static ImVec4 tint_col = { 1.0f, 1.0f, 1.0f, 1.0f };
|
|
static ImVec4 border_col = { 1.0f, 1.0f, 1.0f, 0.5f };
|
|
|
|
extern int32_t width;
|
|
extern int32_t height;
|
|
extern vec2i internal_2d_res;
|
|
extern vec2i internal_3d_res;
|
|
extern bool input_reset;
|
|
extern bool input_locked;
|
|
|
|
extern bool close;
|
|
extern bool global_context_menu;
|
|
|
|
extern float_t rob_frame;
|
|
|
|
extern render_context* rctx_ptr;
|
|
|
|
static const char* glitter_editor_window_title = "Glitter Editor";
|
|
|
|
static void glitter_editor_select_particle(GlitterEditor* glt_edt);
|
|
static void glitter_editor_windows(GlitterEditor* glt_edt);
|
|
|
|
static void glitter_editor_reload(GlitterEditor* glt_edt);
|
|
static void glitter_editor_save(GlitterEditor* glt_edt);
|
|
static void glitter_editor_open_window(GlitterEditor* glt_edt);
|
|
static void glitter_editor_save_window(GlitterEditor* glt_edt);
|
|
static void glitter_editor_save_as_window(GlitterEditor* glt_edt);
|
|
static void glitter_editor_load_file(GlitterEditor* glt_edt, const char* path, const char* file);
|
|
static void glitter_editor_save_file(GlitterEditor* glt_edt, const char* path, const char* file);
|
|
static bool glitter_editor_list_open_window(Glitter::EffectGroup* eg);
|
|
static bool glitter_editor_resource_import(GlitterEditor* glt_edt);
|
|
static bool glitter_editor_resource_export(GlitterEditor* glt_edt);
|
|
|
|
static void glitter_editor_draw_emitter_type(GlitterEditor* glt_edt);
|
|
static void glitter_editor_draw_emitter_type_effect_inst(
|
|
GlitterEditor* glt_edt, Glitter::EffectInst* eff_inst);
|
|
static void glitter_editor_draw_emitter_type_emitter_inst_f2(
|
|
GlitterEditor* glt_edt, Glitter::EmitterInst* emit_inst, bool local);
|
|
static void glitter_editor_draw_emitter_type_emitter_inst_x(
|
|
GlitterEditor* glt_edt, Glitter::EmitterInst* emit_inst, bool local);
|
|
static void glitter_editor_draw_emitter_type_scene(GlitterEditor* glt_edt, Glitter::Scene* sc);
|
|
|
|
static void glitter_editor_disp_wireframe(GlitterEditor* glt_edt);
|
|
static void glitter_editor_disp_wireframe_effect_inst(
|
|
GlitterEditor* glt_edt, Glitter::EffectInst* eff_inst);
|
|
static void glitter_editor_disp_wireframe_render_scene(
|
|
GlitterEditor* glt_edt, Glitter::XRenderScene* rend_sc);
|
|
static void glitter_editor_disp_wireframe_render_scene(GlitterEditor* glt_edt,
|
|
Glitter::XRenderScene* rend_sc, GPM, Glitter::XRenderGroup* rend_group);
|
|
static void glitter_editor_disp_wireframe_scene(GlitterEditor* glt_edt, Glitter::Scene* sc);
|
|
|
|
static void glitter_editor_test_window(GlitterEditor* glt_edt);
|
|
static void glitter_editor_effects(GlitterEditor* glt_edt);
|
|
static void glitter_editor_effects_context_menu(GlitterEditor* glt_edt,
|
|
Glitter::Effect* effect, Glitter::Emitter* emitter, Glitter::Particle* particle,
|
|
ssize_t i_idx, ssize_t j_idx, ssize_t k_idx,
|
|
glitter_editor_selected_enum type);
|
|
static void glitter_editor_resources(GlitterEditor* glt_edt);
|
|
static void glitter_editor_resources_context_menu(GlitterEditor* glt_edt,
|
|
int32_t resource, ssize_t i_idx, bool selected_none);
|
|
static void glitter_editor_play_manager(GlitterEditor* glt_edt);
|
|
static void glitter_editor_property(GlitterEditor* glt_edt);
|
|
static void glitter_editor_property_effect(GlitterEditor* glt_edt);
|
|
static void glitter_editor_property_emitter(GlitterEditor* glt_edt);
|
|
static void glitter_editor_property_particle(GlitterEditor* glt_edt);
|
|
static bool glitter_editor_property_particle_texture(GlitterEditor* glt_edt,
|
|
const char* label, char** items, Glitter::Particle* particle,
|
|
GLuint* tex, uint64_t* tex_hash, int32_t tex_idx, bool* tex_anim,
|
|
int32_t* tex_frame, int32_t* tex_index, int32_t* tex_tex);
|
|
|
|
static void glitter_editor_popups(GlitterEditor* glt_edt);
|
|
static void glitter_editor_file_create_popup(GlitterEditor* glt_edt,
|
|
ImGuiIO& io, ImGuiStyle& style, ImFont* font, const float_t title_bar_size);
|
|
static void glitter_editor_file_load_popup(GlitterEditor* glt_edt,
|
|
ImGuiIO& io, ImGuiStyle& style, ImFont* font, const float_t title_bar_size);
|
|
static void glitter_editor_file_load_model_popup(GlitterEditor* glt_edt,
|
|
ImGuiIO& io, ImGuiStyle& style, ImFont* font, const float_t title_bar_size);
|
|
static void glitter_editor_file_load_error_list_popup(GlitterEditor* glt_edt,
|
|
ImGuiIO& io, ImGuiStyle& style, ImFont* font, const float_t title_bar_size);
|
|
static void glitter_editor_file_save_popup(GlitterEditor* glt_edt,
|
|
ImGuiIO& io, ImGuiStyle& style, ImFont* font, const float_t title_bar_size);
|
|
|
|
static void glitter_editor_curve_editor_curve_set(GlitterEditor* glt_edt,
|
|
Glitter::Curve* curve, Glitter::CurveType type);
|
|
static Glitter::Curve::Key* glitter_editor_curve_editor_get_closest_key(
|
|
GlitterEditor* glt_edt, Glitter::Curve* curve);
|
|
static Glitter::Curve::Key* glitter_editor_curve_editor_get_selected_key(
|
|
GlitterEditor* glt_edt, Glitter::Curve* curve);
|
|
static float_t glitter_editor_curve_editor_get_value(GlitterEditor* glt_edt,
|
|
Glitter::CurveType type);
|
|
static void glitter_editor_curve_editor_key_manager(GlitterEditor* glt_edt,
|
|
std::vector<Glitter::Curve::Key>* keys, bool* add_key, bool* del_key);
|
|
static void glitter_editor_curve_editor_property_window(GlitterEditor* glt_edt);
|
|
static void glitter_editor_curve_editor_selector(GlitterEditor* glt_edt);
|
|
static void glitter_editor_curve_editor_window(GlitterEditor* glt_edt);
|
|
static void glitter_editor_curve_editor_window_draw(GlitterEditor* glt_edt, const Glitter::CurveType type,
|
|
const ImU32 line_color, const bool line_front, const float_t min, const float_t max,
|
|
const ImVec2 canvas_size, const ImVec2 canvas_pos, const ImVec2 canvas_pos_min, const ImVec2 canvas_pos_max,
|
|
const bool fix_rot_z = false);
|
|
static void glitter_editor_curve_editor_window_draw(GlitterEditor* glt_edt, const Glitter::Curve* curve,
|
|
const ImU32 line_color, const bool line_front, const float_t min, const float_t max,
|
|
const ImVec2 canvas_size, const ImVec2 canvas_pos, const ImVec2 canvas_pos_min, const ImVec2 canvas_pos_max,
|
|
const bool fix_rot_z = false);
|
|
static void glitter_editor_curve_editor_window_draw(GlitterEditor* glt_edt, const Glitter::Curve* curve,
|
|
const ImU32 line_color, const bool line_front, const float_t min, const float_t max,
|
|
const ImVec2 canvas_size, const ImVec2 canvas_pos, const ImVec2 canvas_pos_min, const ImVec2 canvas_pos_max,
|
|
const bool fix_rot_z, const int32_t start_time, const int32_t end_time,
|
|
const int32_t base_start_time, const int32_t base_end_time, std::vector<ImVec2>& points, bool loop = false);
|
|
static void glitter_editor_curve_editor_window_draw_random_range(
|
|
GlitterEditor::CurveEditor* crv_edt, const float_t x1, const float_t x2,
|
|
const vec3 value, const vec3 random, const float_t min, const float_t max, const bool random_range_negate,
|
|
const ImVec2 canvas_size, const ImVec2 canvas_pos, const ImVec2 canvas_pos_min, const ImVec2 canvas_pos_max);
|
|
static void glitter_editor_curve_editor_window_draw_random_range(
|
|
GlitterEditor::CurveEditor* crv_edt, const float_t x1, const float_t x2,
|
|
const vec3 value1, const vec3 value2, const vec3 random1, const vec3 random2,
|
|
const float_t min, const float_t max, const bool random_range_negate,
|
|
const ImVec2 canvas_size, const ImVec2 canvas_pos, const ImVec2 canvas_pos_min, const ImVec2 canvas_pos_max);
|
|
|
|
static bool glitter_editor_hash_input(GlitterEditor* glt_edt,
|
|
const char* label, uint64_t* hash);
|
|
|
|
GlitterEditor glitter_editor;
|
|
|
|
GlitterEditor::CurveEditor::CurveEditor() : type(), type_flags(), animation(), list(),
|
|
key(), frame_width(), zoom_time(), prev_zoom_time(), zoom_value(), key_radius_in(),
|
|
key_radius_out(), height_offset(), frame(), draw_list(), io(), timeline_pos(),
|
|
range(), offset(), add_key(), del_key(), add_curve(), del_curve(), key_edit() {
|
|
|
|
}
|
|
|
|
void GlitterEditor::CurveEditor::ResetCurves() {
|
|
memset(&list, 0, sizeof(list));
|
|
animation = 0;
|
|
key = {};
|
|
}
|
|
|
|
void GlitterEditor::CurveEditor::ResetState(Glitter::CurveType type) {
|
|
this->type = type;
|
|
|
|
if (type != -1)
|
|
type_flags = (Glitter::CurveTypeFlags)(1 << type);
|
|
else
|
|
type_flags = (Glitter::CurveTypeFlags)0;
|
|
|
|
frame_width = 16;
|
|
zoom_time = 1.0f;
|
|
prev_zoom_time = 1.0f;
|
|
zoom_value = 1.0f;
|
|
key_radius_in = 6.0f;
|
|
key_radius_out = 8.0f;
|
|
height_offset = 20.0f;
|
|
frame = 0;
|
|
|
|
timeline_pos = -curve_editor_timeline_base_pos;
|
|
|
|
switch (type) {
|
|
case Glitter::CURVE_TRANSLATION_X:
|
|
case Glitter::CURVE_TRANSLATION_Y:
|
|
case Glitter::CURVE_TRANSLATION_Z:
|
|
range = 25.0f;
|
|
break;
|
|
case Glitter::CURVE_ROTATION_X:
|
|
case Glitter::CURVE_ROTATION_Y:
|
|
case Glitter::CURVE_ROTATION_Z:
|
|
range = 360.0f;
|
|
break;
|
|
case Glitter::CURVE_SCALE_X:
|
|
case Glitter::CURVE_SCALE_Y:
|
|
case Glitter::CURVE_SCALE_Z:
|
|
case Glitter::CURVE_SCALE_ALL:
|
|
range = 5.0f;
|
|
break;
|
|
case Glitter::CURVE_COLOR_R:
|
|
case Glitter::CURVE_COLOR_G:
|
|
case Glitter::CURVE_COLOR_B:
|
|
case Glitter::CURVE_COLOR_A:
|
|
case Glitter::CURVE_COLOR_RGB_SCALE:
|
|
case Glitter::CURVE_COLOR_R_2ND:
|
|
case Glitter::CURVE_COLOR_G_2ND:
|
|
case Glitter::CURVE_COLOR_B_2ND:
|
|
case Glitter::CURVE_COLOR_A_2ND:
|
|
case Glitter::CURVE_COLOR_RGB_SCALE_2ND:
|
|
range = 255.0f;
|
|
break;
|
|
case Glitter::CURVE_EMISSION_INTERVAL:
|
|
range = 20.0f;
|
|
break;
|
|
case Glitter::CURVE_PARTICLES_PER_EMISSION:
|
|
range = 50.0f;
|
|
break;
|
|
case Glitter::CURVE_U_SCROLL:
|
|
case Glitter::CURVE_V_SCROLL:
|
|
case Glitter::CURVE_U_SCROLL_ALPHA:
|
|
case Glitter::CURVE_V_SCROLL_ALPHA:
|
|
case Glitter::CURVE_U_SCROLL_2ND:
|
|
case Glitter::CURVE_V_SCROLL_2ND:
|
|
case Glitter::CURVE_U_SCROLL_ALPHA_2ND:
|
|
case Glitter::CURVE_V_SCROLL_ALPHA_2ND:
|
|
range = 1.0f;
|
|
break;
|
|
default:
|
|
range = 1.0f;
|
|
break;
|
|
}
|
|
|
|
offset = 0.0f;
|
|
|
|
add_key = false;
|
|
del_key = false;
|
|
}
|
|
|
|
void GlitterEditor::CurveEditor::SetFlag(const Glitter::CurveTypeFlags type_flag) {
|
|
switch (type) {
|
|
case Glitter::CURVE_TRANSLATION_X:
|
|
case Glitter::CURVE_TRANSLATION_Y:
|
|
case Glitter::CURVE_TRANSLATION_Z:
|
|
if (type_flag & Glitter::CURVE_TYPE_TRANSLATION_XYZ)
|
|
enum_xor(type_flags, type_flag);
|
|
break;
|
|
case Glitter::CURVE_ROTATION_X:
|
|
case Glitter::CURVE_ROTATION_Y:
|
|
case Glitter::CURVE_ROTATION_Z:
|
|
if (type_flag & Glitter::CURVE_TYPE_ROTATION_XYZ)
|
|
enum_xor(type_flags, type_flag);
|
|
break;
|
|
case Glitter::CURVE_SCALE_X:
|
|
case Glitter::CURVE_SCALE_Y:
|
|
case Glitter::CURVE_SCALE_Z:
|
|
case Glitter::CURVE_SCALE_ALL:
|
|
if (type_flag & (Glitter::CURVE_TYPE_SCALE_XYZ | Glitter::CURVE_TYPE_SCALE_ALL))
|
|
enum_xor(type_flags, type_flag);
|
|
break;
|
|
case Glitter::CURVE_COLOR_R:
|
|
case Glitter::CURVE_COLOR_G:
|
|
case Glitter::CURVE_COLOR_B:
|
|
case Glitter::CURVE_COLOR_A:
|
|
case Glitter::CURVE_COLOR_RGB_SCALE:
|
|
if (type_flag & (Glitter::CURVE_TYPE_COLOR_RGBA | Glitter::CURVE_TYPE_COLOR_RGB_SCALE))
|
|
enum_xor(type_flags, type_flag);
|
|
break;
|
|
case Glitter::CURVE_COLOR_R_2ND:
|
|
case Glitter::CURVE_COLOR_G_2ND:
|
|
case Glitter::CURVE_COLOR_B_2ND:
|
|
case Glitter::CURVE_COLOR_A_2ND:
|
|
case Glitter::CURVE_COLOR_RGB_SCALE_2ND:
|
|
if (type_flag & (Glitter::CURVE_TYPE_COLOR_RGBA_2ND | Glitter::CURVE_TYPE_COLOR_RGB_SCALE_2ND))
|
|
enum_xor(type_flags, type_flag);
|
|
break;
|
|
case Glitter::CURVE_U_SCROLL:
|
|
case Glitter::CURVE_V_SCROLL:
|
|
if (type_flag & Glitter::CURVE_TYPE_UV_SCROLL)
|
|
enum_xor(type_flags, type_flag);
|
|
break;
|
|
case Glitter::CURVE_U_SCROLL_ALPHA:
|
|
case Glitter::CURVE_V_SCROLL_ALPHA:
|
|
if (type_flag & Glitter::CURVE_TYPE_UV_SCROLL_ALPHA)
|
|
enum_xor(type_flags, type_flag);
|
|
break;
|
|
case Glitter::CURVE_U_SCROLL_2ND:
|
|
case Glitter::CURVE_V_SCROLL_2ND:
|
|
if (type_flag & Glitter::CURVE_TYPE_UV_SCROLL_2ND)
|
|
enum_xor(type_flags, type_flag);
|
|
break;
|
|
case Glitter::CURVE_U_SCROLL_ALPHA_2ND:
|
|
case Glitter::CURVE_V_SCROLL_ALPHA_2ND:
|
|
if (type_flag & Glitter::CURVE_TYPE_UV_SCROLL_ALPHA_2ND)
|
|
enum_xor(type_flags, type_flag);
|
|
break;
|
|
}
|
|
enum_or(type_flags, (1 << type));
|
|
}
|
|
|
|
GlitterEditor::GlitterEditor() : test(), create_popup(), load(), load_wait(), load_data(), load_data_wait(),
|
|
load_popup(), load_data_popup(), load_error_list_popup(), save(), save_popup(), save_compress(), save_encrypt(),
|
|
close(), close_editor(), input_play(), input_reload(), input_pause(), input_pause_temp(), input_reset(),
|
|
effect_group_add(), show_grid(), draw_flags(), resource_flags(), effect_flags(), emitter_flags(),
|
|
particle_flags(), load_glt_type(), save_glt_type(), load_data_type(), frame_counter(),
|
|
old_frame_counter(), start_frame(), end_frame(), counter(), effect_group(), scene(), hash(),
|
|
selected_type(), selected_resource(), selected_effect(), selected_emitter(), selected_particle(),
|
|
selected_edit_resource(), selected_edit_effect(), selected_edit_emitter(), selected_edit_particle() {
|
|
|
|
}
|
|
|
|
GlitterEditor::~GlitterEditor() {
|
|
|
|
}
|
|
|
|
bool GlitterEditor::init() {
|
|
LARGE_INTEGER time;
|
|
QueryPerformanceCounter(&time);
|
|
Glitter::glt_particle_manager->random.value = (uint32_t)(time.LowPart * hash_fnv1a64m_empty);
|
|
Glitter::glt_particle_manager->random.step = 1;
|
|
|
|
QueryPerformanceCounter(&time);
|
|
Glitter::glt_particle_manager->counter = (uint32_t)(time.LowPart * hash_murmurhash_empty);
|
|
|
|
Glitter::glt_particle_manager->emission = 1.0f;
|
|
Glitter::glt_particle_manager->draw_all = true;
|
|
Glitter::glt_particle_manager->draw_all_mesh = true;
|
|
|
|
reset();
|
|
dtm_stg_load(0);
|
|
dtw_stg_load(true);
|
|
|
|
input_reset = true;
|
|
|
|
/*char* path_x = "VRFL\\";
|
|
vector_old_string files_x = vector_old_empty(string);
|
|
path_get_files(&files_x, path_x);
|
|
for (string* i = files_x.begin; i != files_x.end;)
|
|
if (str_utils_check_ends_with(string_data(i), ".farc"))
|
|
i++;
|
|
else {
|
|
string_free(i);
|
|
vector_old_string_erase(&files_x, i - files_x.begin);
|
|
}
|
|
|
|
ssize_t c = vector_old_length(files_x);
|
|
GlitterFileReader* fr = 0;
|
|
if (files_x.begin) {
|
|
stream s;
|
|
s.open(L"name_VRFL.glitter.txt", L"rb");
|
|
size_t length = s.length;
|
|
uint8_t* data = force_malloc(length);
|
|
s.read(data, length);
|
|
s.close();
|
|
|
|
char* buf;
|
|
char** lines;
|
|
size_t count;
|
|
if (str_utils_text_file_parse(data, length, &buf, &lines, &count)) {
|
|
for (size_t i = 0; i < count; i++) {
|
|
char* t = strstr(lines[i], "#(?)");
|
|
if (t)
|
|
*t = 0;
|
|
}
|
|
|
|
uint64_t* hashes = force_malloc<uint64_t>(count);
|
|
for (size_t i = 0; i < count; i++) {
|
|
size_t len = utf8_length(lines[i]);
|
|
hashes[i] = hash_murmurhash(lines[i], min_def(len, 0x7F));
|
|
}
|
|
|
|
for (ssize_t i = 0; i < c; i++) {
|
|
char* file_x = str_utils_get_without_extension(string_data(&files_x.begin[i]));
|
|
|
|
char buf[0x200];
|
|
sprintf_s(buf, 0x100, "%hs\n", file_x);
|
|
OutputDebugStringA(buf);
|
|
|
|
glt_edt->load_glt_type = Glitter::X;
|
|
fr = glitter_file_reader_init(Glitter::X, path_x, file_x, 1.0f);
|
|
glitter_file_reader_read(fr, Glitter::glt_particle_manager->emission);
|
|
|
|
if (fr && fr->effect_group) {
|
|
Glitter::EffectGroup* eg = fr->effect_group;
|
|
for (Glitter::Effect** i = eg->effects.begin; i != eg->effects.end; i++) {
|
|
if (!*i)
|
|
continue;
|
|
|
|
Glitter::Effect* e = *i;
|
|
if (e->data.name_hash == hash_murmurhash_empty)
|
|
continue;
|
|
|
|
size_t j;
|
|
for (j = 0; j < count; j++)
|
|
if (e->data.name_hash == hashes[j])
|
|
break;
|
|
|
|
if (j == count) {
|
|
char buf[0x200];
|
|
sprintf_s(buf, 0x100, "%08llX\n", e->data.name_hash);
|
|
OutputDebugStringA(buf);
|
|
}
|
|
}
|
|
|
|
Glitter::EffectGroup_dispose(fr->effect_group);
|
|
}
|
|
free_def(file_x);
|
|
}
|
|
free_def(lines);
|
|
free_def(hashes);
|
|
}
|
|
free_def(data);
|
|
}
|
|
for (string* i = files_x.begin; i != files_x.end; i++)
|
|
string_free(i);
|
|
vector_old_string_free(&files_x);
|
|
glitter_file_reader_dispose(fr);
|
|
glt_edt->effect_group = 0;
|
|
return;*/
|
|
|
|
/*char* path_x = "X\\";
|
|
vector_old_string files_x = vector_old_empty(string);
|
|
path_get_files(&files_x, path_x);
|
|
for (string* i = files_x.begin; i != files_x.end;)
|
|
if (str_utils_check_ends_with(string_data(i), ".farc"))
|
|
i++;
|
|
else {
|
|
string_free(i);
|
|
vector_old_string_erase(&files_x, i - files_x.begin);
|
|
}
|
|
|
|
ssize_t c = vector_old_length(files_x);
|
|
GlitterFileReader* fr = 0;
|
|
if (files_x.begin)
|
|
for (ssize_t i = 0; i < c; i++) {
|
|
char* file_x = str_utils_get_without_extension(string_data(&files_x.begin[i]));
|
|
|
|
char buf[0x200];
|
|
sprintf_s(buf, 0x100, "%hs\n", file_x);
|
|
OutputDebugStringA(buf);
|
|
|
|
glt_edt->load_glt_type = Glitter::X;
|
|
fr = glitter_file_reader_init(Glitter::X, path_x, file_x, 1.0f);
|
|
glitter_file_reader_read(fr, Glitter::glt_particle_manager->emission);
|
|
|
|
if (fr && fr->effect_group) {
|
|
Glitter::EffectGroup* eg = fr->effect_group;
|
|
for (Glitter::Effect** i = eg->effects.begin; i != eg->effects.end; i++) {
|
|
if (!*i)
|
|
continue;
|
|
|
|
Glitter::Effect* e = *i;
|
|
if (!e->data.ext_anim)
|
|
continue;
|
|
|
|
Glitter::Effect_ext_anim* ea = e->data.ext_anim;
|
|
if (ea->instance_id) {
|
|
char buf[0x200];
|
|
sprintf_s(buf, 0x100, "%08llX %d\n", e->data.name_hash, ea->instance_id);
|
|
OutputDebugStringA(buf);
|
|
}
|
|
}
|
|
|
|
Glitter::EffectGroup_dispose(fr->effect_group);
|
|
}
|
|
free_def(file_x);
|
|
}
|
|
for (string* i = files_x.begin; i != files_x.end; i++)
|
|
string_free(i);
|
|
vector_old_string_free(&files_x);
|
|
glitter_file_reader_dispose(fr);
|
|
glt_edt->effect_group = 0;
|
|
return;*/
|
|
|
|
/*char* path_f2 = "F2\\";
|
|
char* path_ft = "AFT\\";
|
|
vector_old_string files_f2 = vector_old_empty(string);
|
|
vector_old_string files_ft = vector_old_empty(string);
|
|
path_get_files(&files_f2, path_f2);
|
|
path_get_files(&files_ft, path_ft);
|
|
for (string* i = files_f2.begin; i != files_f2.end;)
|
|
if (str_utils_check_ends_with(string_data(i), ".farc"))
|
|
i++;
|
|
else {
|
|
string_free(i);
|
|
vector_old_string_erase(&files_f2, i - files_f2.begin);
|
|
}
|
|
|
|
for (string* i = files_ft.begin; i != files_ft.end;)
|
|
if (str_utils_check_ends_with(string_data(i), ".farc"))
|
|
i++;
|
|
else {
|
|
string_free(i);
|
|
vector_old_string_erase(&files_ft, i - files_ft.begin);
|
|
}
|
|
|
|
stream s;
|
|
s.open(L"name_F2.glitter.txt", L"rb");
|
|
size_t length = s.length;
|
|
uint8_t* data = force_malloc(length);
|
|
s.read(data, length);
|
|
s.close();
|
|
|
|
char* buf;
|
|
char** lines;
|
|
size_t count;
|
|
if (str_utils_text_file_parse(data, length, &buf, &lines, &count)) {
|
|
for (size_t i = 0; i < count; i++) {
|
|
char* t = strstr(lines[i], "#(?)");
|
|
if (t)
|
|
*t = 0;
|
|
}
|
|
|
|
uint64_t* hashes = force_malloc<uint64_t>(count);
|
|
for (size_t i = 0; i < count; i++) {
|
|
size_t len = utf8_length(lines[i]);
|
|
hashes[i] = hash_murmurhash(lines[i], min_def(len, 0x7F));
|
|
}
|
|
|
|
ssize_t c = vector_old_length(files_f2);
|
|
GlitterFileReader* fr = 0;
|
|
if (files_f2.begin && files_ft.begin)
|
|
for (ssize_t i = 0; i < c; i++) {
|
|
char* file_f2 = str_utils_get_without_extension(string_data(&files_f2.begin[i]));
|
|
char* file_ft = str_utils_get_without_extension(string_data(&files_ft.begin[i]));
|
|
glt_edt->load_glt_type = Glitter::F2;
|
|
fr = glitter_file_reader_init(Glitter::F2, path_f2, file_f2, 1.0f);
|
|
glitter_file_reader_read(fr, Glitter::glt_particle_manager->emission);
|
|
|
|
if (fr && fr->effect_group) {
|
|
Glitter::EffectGroup* eg = fr->effect_group;
|
|
for (Glitter::Effect** i = eg->effects.begin; i != eg->effects.end; i++) {
|
|
if (!*i)
|
|
continue;
|
|
|
|
Glitter::Effect* e = *i;
|
|
memset(e->name, 0, 0x80);
|
|
if (e->data.name_hash == hash_murmurhash_empty)
|
|
continue;
|
|
|
|
size_t j;
|
|
for (j = 0; j < count; j++)
|
|
if (e->data.name_hash == hashes[j])
|
|
break;
|
|
|
|
if (j == count)
|
|
break;
|
|
|
|
size_t len = utf8_length(lines[j]);
|
|
memcpy(e->name, lines[j], min_def(len, 0x7F));
|
|
}
|
|
|
|
glt_edt->effect_group = fr->effect_group;
|
|
//glt_edt->save_glt_type = Glitter::FT;
|
|
//glitter_editor_save_file(path_ft, file_ft);
|
|
Glitter::EffectGroup_dispose(fr->effect_group);
|
|
}
|
|
free_def(file_f2);
|
|
free_def(file_ft);
|
|
}
|
|
glitter_file_reader_dispose(fr);
|
|
|
|
free_def(buf);
|
|
free_def(lines);
|
|
free_def(hashes);
|
|
}
|
|
for (string* i = files_f2.begin; i != files_f2.end; i++)
|
|
string_free(i);
|
|
vector_old_string_free(&files_f2);
|
|
|
|
for (string* i = files_ft.begin; i != files_ft.end; i++)
|
|
string_free(i);
|
|
vector_old_string_free(&files_ft);
|
|
free_def(data);
|
|
glt_edt->effect_group = 0;*/
|
|
return true;
|
|
}
|
|
|
|
bool GlitterEditor::ctrl() {
|
|
int32_t sel_rsrc = selected_resource;
|
|
Glitter::Effect* sel_efct = selected_effect;
|
|
Glitter::Emitter* sel_emit = selected_emitter;
|
|
Glitter::Particle* sel_ptcl = selected_particle;
|
|
|
|
if (effect_group_add) {
|
|
Glitter::glt_particle_manager->UnloadEffectGroup(hash);
|
|
|
|
GlitterEditor::reset_disp();
|
|
|
|
LARGE_INTEGER time;
|
|
QueryPerformanceCounter(&time);
|
|
|
|
Glitter::EffectGroup* eg = new Glitter::EffectGroup(load_glt_type);
|
|
char buf[0x200];
|
|
snprintf(buf, sizeof(buf), "eff_%016llx_main", time.LowPart * hash_fnv1a64m_empty);
|
|
hash = load_glt_type == Glitter::FT
|
|
? hash_utf8_fnv1a64m(buf) : hash_utf8_murmurhash(buf);
|
|
eg->hash = hash;
|
|
eg->load_count = 1;
|
|
Glitter::glt_particle_manager->effect_groups.insert({ hash, eg });
|
|
|
|
scene_counter = Glitter::glt_particle_manager->LoadScene(hash, eg->type != Glitter::FT
|
|
? hash_murmurhash_empty : hash_fnv1a64m_empty);
|
|
effect_group = eg;
|
|
}
|
|
|
|
Glitter::EffectGroup* eg = effect_group;
|
|
|
|
bool tex_reload = false;
|
|
if (resource_flags & GLITTER_EDITOR_IMPORT)
|
|
if (glitter_editor_resource_import(this))
|
|
tex_reload = true;
|
|
|
|
if (eg && sel_rsrc != -1) {
|
|
if (resource_flags & GLITTER_EDITOR_EXPORT)
|
|
glitter_editor_resource_export(this);
|
|
else if (resource_flags & GLITTER_EDITOR_DELETE) {
|
|
size_t rc = eg->resources_count;
|
|
|
|
ssize_t j = -1;
|
|
for (size_t i = 0; i < rc; i++)
|
|
if (i == sel_rsrc) {
|
|
j = i;
|
|
break;
|
|
}
|
|
|
|
if (j > -1) {
|
|
uint64_t hash = eg->resource_hashes[j];
|
|
eg->resource_hashes.erase(eg->resource_hashes.begin() + j);
|
|
eg->resources_tex.textures.erase(eg->resources_tex.textures.begin() + j);
|
|
eg->resources_count--;
|
|
|
|
uint64_t empty_hash = eg->type != Glitter::FT
|
|
? hash_murmurhash_empty : hash_fnv1a64m_empty;
|
|
for (Glitter::Effect*& i : eg->effects) {
|
|
if (!i)
|
|
continue;
|
|
|
|
Glitter::Effect* effect = i;
|
|
for (Glitter::Emitter*& j : effect->emitters) {
|
|
if (!j)
|
|
continue;
|
|
|
|
Glitter::Emitter* emitter = j;
|
|
for (Glitter::Particle*& k : emitter->particles) {
|
|
if (!k)
|
|
continue;
|
|
|
|
Glitter::Particle* particle = k;
|
|
if (particle->data.tex_hash == hash) {
|
|
particle->data.tex_hash = empty_hash;
|
|
particle->data.texture = 0;
|
|
}
|
|
|
|
if (particle->data.mask_tex_hash == hash) {
|
|
particle->data.mask_tex_hash = empty_hash;
|
|
particle->data.mask_texture = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
selected_resource = -1;
|
|
selected_edit_resource = -1;
|
|
tex_reload = true;
|
|
}
|
|
else if (resource_flags & GLITTER_EDITOR_MOVE_UP) {
|
|
size_t rc = eg->resources_count;
|
|
uint64_t* rh = eg->resource_hashes.data();
|
|
txp* rt = eg->resources_tex.textures.data();
|
|
|
|
ssize_t j = -1;
|
|
for (size_t i = 0; i < rc; i++)
|
|
if (i == sel_rsrc) {
|
|
j = i;
|
|
break;
|
|
}
|
|
|
|
if (j > 0) {
|
|
uint64_t temp_hash = rh[j - 1];
|
|
txp temp_tex = rt[j - 1];
|
|
rh[j - 1] = rh[j];
|
|
rt[j - 1] = rt[j];
|
|
rh[j] = temp_hash;
|
|
rt[j] = temp_tex;
|
|
input_reload = true;
|
|
}
|
|
tex_reload = true;
|
|
}
|
|
else if (resource_flags & GLITTER_EDITOR_MOVE_DOWN) {
|
|
size_t rc = eg->resources_count;
|
|
uint64_t* rh = eg->resource_hashes.data();
|
|
txp* rt = eg->resources_tex.textures.data();
|
|
|
|
ssize_t j = -1;
|
|
for (size_t i = 0; i < rc; i++)
|
|
if (i == sel_rsrc) {
|
|
j = i;
|
|
break;
|
|
}
|
|
|
|
if (j > -1 && j < (ssize_t)rc - 1) {
|
|
uint64_t temp_hash = rh[j + 1];
|
|
txp temp_tex = rt[j + 1];
|
|
rh[j + 1] = rh[j];
|
|
rt[j + 1] = rt[j];
|
|
rh[j] = temp_hash;
|
|
rt[j] = temp_tex;
|
|
input_reload = true;
|
|
}
|
|
tex_reload = true;
|
|
}
|
|
}
|
|
|
|
if (tex_reload && effect_group) {
|
|
//glitter_texture_load(&Glitter::glt_particle_manager, effect_group);
|
|
input_reload = true;
|
|
}
|
|
|
|
if (eg && effect_flags & GLITTER_EDITOR_ADD) {
|
|
ssize_t eff_count = eg->effects.size();
|
|
|
|
LARGE_INTEGER time;
|
|
QueryPerformanceCounter(&time);
|
|
|
|
Glitter::Effect* e = new Glitter::Effect(eg->type);
|
|
char name[0x80];
|
|
sprintf_s(name, sizeof(name), "eff_%08x",
|
|
(uint32_t)((eff_count + 1) * time.LowPart * hash_murmurhash_empty));
|
|
e->name = name;
|
|
eg->effects.push_back(e);
|
|
input_reload = true;
|
|
}
|
|
|
|
if (eg && selected_edit_effect)
|
|
if (effect_flags & GLITTER_EDITOR_DUPLICATE) {
|
|
ssize_t eff_count = eg->effects.size();
|
|
|
|
LARGE_INTEGER time;
|
|
QueryPerformanceCounter(&time);
|
|
|
|
Glitter::Effect* e = new Glitter::Effect(eg->type);
|
|
*e = *selected_edit_effect;
|
|
|
|
char name[0x80];
|
|
sprintf_s(name, sizeof(name), "eff_%08x",
|
|
(uint32_t)((eff_count + 1)* time.LowPart* hash_murmurhash_empty));
|
|
e->name.assign(name);
|
|
eg->effects.push_back(e);
|
|
input_reload = true;
|
|
}
|
|
else if (effect_flags & GLITTER_EDITOR_DELETE) {
|
|
ssize_t j = -1;
|
|
for (Glitter::Effect*& i : eg->effects)
|
|
if (i && i == selected_edit_effect) {
|
|
j = &i - eg->effects.data();
|
|
break;
|
|
}
|
|
|
|
if (j > -1)
|
|
eg->effects.erase(eg->effects.begin() + j);
|
|
selected_type = GLITTER_EDITOR_SELECTED_NONE;
|
|
selected_resource = -1;
|
|
selected_effect = 0;
|
|
selected_emitter = 0;
|
|
selected_particle = 0;
|
|
selected_edit_resource = -1;
|
|
selected_edit_effect = 0;
|
|
selected_edit_emitter = 0;
|
|
selected_edit_particle = 0;
|
|
|
|
if (eg->effects.size() < 1)
|
|
close = true;
|
|
else
|
|
input_reload = true;
|
|
}
|
|
else if (effect_flags & GLITTER_EDITOR_MOVE_UP) {
|
|
ssize_t j = -1;
|
|
for (Glitter::Effect*& i : eg->effects)
|
|
if (i == selected_effect) {
|
|
j = &i - eg->effects.data();
|
|
break;
|
|
}
|
|
|
|
if (j > 0) {
|
|
Glitter::Effect* temp = eg->effects.data()[j - 1];
|
|
eg->effects.data()[j - 1] = eg->effects.data()[j];
|
|
eg->effects.data()[j] = temp;
|
|
input_reload = true;
|
|
}
|
|
}
|
|
else if (effect_flags & GLITTER_EDITOR_MOVE_DOWN) {
|
|
ssize_t j = -1;
|
|
for (Glitter::Effect*& i : eg->effects)
|
|
if (i == selected_effect) {
|
|
j = &i - eg->effects.data();
|
|
break;
|
|
}
|
|
|
|
if (j > -1 && j < (ssize_t)eg->effects.size() - 1) {
|
|
Glitter::Effect* temp = eg->effects.data()[j + 1];
|
|
eg->effects.data()[j + 1] = eg->effects.data()[j];
|
|
eg->effects.data()[j] = temp;
|
|
input_reload = true;
|
|
}
|
|
}
|
|
else if (emitter_flags & GLITTER_EDITOR_ADD) {
|
|
Glitter::Emitter* e = new Glitter::Emitter(eg->type);
|
|
sel_efct->emitters.push_back(e);
|
|
input_reload = true;
|
|
}
|
|
|
|
if (eg && selected_edit_emitter)
|
|
if (emitter_flags & GLITTER_EDITOR_DUPLICATE) {
|
|
Glitter::Emitter* e = new Glitter::Emitter(eg->type);
|
|
*e = *selected_emitter;
|
|
sel_efct->emitters.push_back(e);
|
|
input_reload = true;
|
|
}
|
|
else if (emitter_flags & GLITTER_EDITOR_DELETE) {
|
|
ssize_t j = -1;
|
|
for (Glitter::Emitter*& i : sel_efct->emitters)
|
|
if (i && i == selected_edit_emitter) {
|
|
j = &i - sel_efct->emitters.data();
|
|
break;
|
|
}
|
|
|
|
if (j > -1)
|
|
sel_efct->emitters.erase(sel_efct->emitters.begin() + j);
|
|
selected_type = GLITTER_EDITOR_SELECTED_EFFECT;
|
|
selected_emitter = 0;
|
|
selected_particle = 0;
|
|
selected_edit_emitter = 0;
|
|
selected_edit_particle = 0;
|
|
input_reload = true;
|
|
}
|
|
else if (emitter_flags & GLITTER_EDITOR_MOVE_UP) {
|
|
ssize_t j = -1;
|
|
for (Glitter::Emitter*& i : sel_efct->emitters)
|
|
if (i == selected_emitter) {
|
|
j = &i - sel_efct->emitters.data();
|
|
break;
|
|
}
|
|
|
|
if (j > 0) {
|
|
Glitter::Emitter* temp = sel_efct->emitters.data()[j - 1];
|
|
sel_efct->emitters.data()[j - 1] = sel_efct->emitters.data()[j];
|
|
sel_efct->emitters.data()[j] = temp;
|
|
input_reload = true;
|
|
}
|
|
}
|
|
else if (emitter_flags & GLITTER_EDITOR_MOVE_DOWN) {
|
|
ssize_t j = -1;
|
|
for (Glitter::Emitter*& i : sel_efct->emitters)
|
|
if (i == selected_emitter) {
|
|
j = &i - sel_efct->emitters.data();
|
|
break;
|
|
}
|
|
|
|
if (j > -1 && j < (ssize_t)sel_efct->emitters.size() - 1) {
|
|
Glitter::Emitter* temp = sel_efct->emitters.data()[j + 1];
|
|
sel_efct->emitters.data()[j + 1] = sel_efct->emitters.data()[j];
|
|
sel_efct->emitters.data()[j] = temp;
|
|
input_reload = true;
|
|
}
|
|
}
|
|
else if (particle_flags & GLITTER_EDITOR_ADD) {
|
|
Glitter::Particle* p = new Glitter::Particle(eg->type);
|
|
sel_emit->particles.push_back(p);
|
|
input_reload = true;
|
|
}
|
|
|
|
if (eg && selected_edit_particle)
|
|
if (particle_flags & GLITTER_EDITOR_DUPLICATE) {
|
|
Glitter::Particle* p = new Glitter::Particle(eg->type);
|
|
*p = *selected_edit_particle;
|
|
sel_emit->particles.push_back(p);
|
|
input_reload = true;
|
|
}
|
|
else if (particle_flags & GLITTER_EDITOR_DELETE) {
|
|
ssize_t j = (ssize_t)-1;
|
|
for (Glitter::Particle*& i : sel_emit->particles)
|
|
if (i && i == selected_edit_particle) {
|
|
j = &i - sel_emit->particles.data();
|
|
break;
|
|
}
|
|
|
|
if (j > -1)
|
|
sel_emit->particles.erase(sel_emit->particles.begin() + j);
|
|
selected_type = GLITTER_EDITOR_SELECTED_EMITTER;
|
|
selected_particle = 0;
|
|
selected_edit_particle = 0;
|
|
input_reload = true;
|
|
}
|
|
else if (particle_flags & GLITTER_EDITOR_MOVE_UP) {
|
|
ssize_t j = -1;
|
|
for (Glitter::Particle*& i : sel_emit->particles)
|
|
if (i == selected_edit_particle) {
|
|
j = &i - sel_emit->particles.data();
|
|
break;
|
|
}
|
|
|
|
if (j > 0) {
|
|
Glitter::Particle* temp = sel_emit->particles.data()[j - 1];
|
|
sel_emit->particles.data()[j - 1] = sel_emit->particles.data()[j];
|
|
sel_emit->particles.data()[j] = temp;
|
|
input_reload = true;
|
|
}
|
|
}
|
|
else if (particle_flags & GLITTER_EDITOR_MOVE_DOWN) {
|
|
ssize_t j = -1;
|
|
for (Glitter::Particle*& i : sel_emit->particles)
|
|
if (i == selected_edit_particle) {
|
|
j = &i - sel_emit->particles.data();
|
|
break;
|
|
}
|
|
|
|
if (j > -1 && j < (ssize_t)sel_emit->particles.size() - 1) {
|
|
Glitter::Particle* temp = sel_emit->particles.data()[j + 1];
|
|
sel_emit->particles.data()[j + 1] = sel_emit->particles.data()[j];
|
|
sel_emit->particles.data()[j] = temp;
|
|
input_reload = true;
|
|
}
|
|
}
|
|
|
|
effect_group_add = false;
|
|
resource_flags = (glitter_editor_flags)0;
|
|
effect_flags = (glitter_editor_flags)0;
|
|
emitter_flags = (glitter_editor_flags)0;
|
|
particle_flags = (glitter_editor_flags)0;
|
|
|
|
if (load || save) {
|
|
char* file = str_utils_get_without_extension(this->file.c_str());
|
|
char* path = str_utils_split_right_get_left_include(this->file.c_str(), '\\');
|
|
|
|
if (load)
|
|
glitter_editor_load_file(this, path, file);
|
|
else if (save && effect_group)
|
|
glitter_editor_save_file(this, path, file);
|
|
|
|
save = false;
|
|
save_compress = false;
|
|
save_encrypt = false;
|
|
free_def(path);
|
|
free_def(file);
|
|
return close_editor;
|
|
}
|
|
else if (eg && load_data) {
|
|
bool load_success = true;
|
|
data_struct* ds = &data_list[load_data_type];
|
|
switch (ds->type) {
|
|
case DATA_F2LE:
|
|
case DATA_F2BE:
|
|
case DATA_VRFL:
|
|
case DATA_X:
|
|
case DATA_XHD: {
|
|
auto& hashes = ds->glitter_list_murmurhash;
|
|
for (Glitter::Effect*& i : eg->effects) {
|
|
if (!i)
|
|
continue;
|
|
|
|
Glitter::Effect* e = i;
|
|
e->name.clear();
|
|
if (e->data.name_hash == hash_murmurhash_empty)
|
|
continue;
|
|
|
|
auto elem = hashes.find(e->data.name_hash);
|
|
if (elem != hashes.end())
|
|
e->name.assign(elem->second);
|
|
else {
|
|
printf_debug("Couldn't find name for hash 0x%08X\n", e->data.name_hash);
|
|
load_success = false;
|
|
}
|
|
}
|
|
|
|
switch (ds->type) {
|
|
case DATA_VRFL:
|
|
case DATA_X:
|
|
case DATA_XHD:
|
|
if (!load_data_wait && eg->CheckModel()) {
|
|
eg->LoadModel(ds);
|
|
load_data_wait = true;
|
|
}
|
|
break;
|
|
}
|
|
} break;
|
|
case DATA_AFT:
|
|
case DATA_FT:
|
|
case DATA_M39: {
|
|
auto& hashes = ds->glitter_list_fnv1a64m;
|
|
for (Glitter::Effect* i : eg->effects) {
|
|
if (!i)
|
|
continue;
|
|
|
|
Glitter::Effect* e = i;
|
|
e->name.clear();
|
|
if (e->data.name_hash == hash_fnv1a64m_empty)
|
|
continue;
|
|
|
|
auto elem = hashes.find(e->data.name_hash);
|
|
if (elem != hashes.end())
|
|
e->name.assign(elem->second);
|
|
else {
|
|
printf_debug("Couldn't find name for hash 0x%016X\n", e->data.name_hash);
|
|
load_success = false;
|
|
}
|
|
}
|
|
} break;
|
|
}
|
|
|
|
if (load_data_wait)
|
|
switch (ds->type) {
|
|
case DATA_VRFL:
|
|
case DATA_X:
|
|
case DATA_XHD:
|
|
if (!eg->CheckLoadModel()) {
|
|
load_data_wait = false;
|
|
load_data = false;
|
|
}
|
|
break;
|
|
}
|
|
else
|
|
load_data = false;
|
|
|
|
if (!load_success && !glitter_editor_list_open_window(effect_group)) {
|
|
load = false;
|
|
load_data = false;
|
|
load_data_wait = false;
|
|
load_popup = false;
|
|
load_data_popup = false;
|
|
load_error_list_popup = true;
|
|
goto effect_unload;
|
|
}
|
|
return close_editor;
|
|
}
|
|
else if (close) {
|
|
effect_unload:
|
|
data_struct* ds = &data_list[load_data_type];
|
|
switch (ds->type) {
|
|
case DATA_VRFL:
|
|
case DATA_X:
|
|
case DATA_XHD:
|
|
if (eg)
|
|
eg->FreeModel();
|
|
break;
|
|
}
|
|
|
|
Glitter::glt_particle_manager->FreeSceneEffect(scene_counter);
|
|
Glitter::glt_particle_manager->UnloadEffectGroup(hash);
|
|
|
|
GlitterEditor::reset_disp();
|
|
effect_group = 0;
|
|
scene = 0;
|
|
hash = 0;
|
|
scene_counter = 0;
|
|
file.clear();
|
|
close = false;
|
|
return close_editor;
|
|
}
|
|
|
|
Glitter::glt_particle_manager->GetSceneStartEndFrame(&start_frame, &end_frame, scene_counter);
|
|
|
|
if (!effect_group) {
|
|
input_play = false;
|
|
input_reset = false;
|
|
return close_editor;
|
|
}
|
|
|
|
if (!(input_pause || input_pause_temp) && Glitter::glt_particle_manager->scenes.size())
|
|
frame_counter += get_delta_frame();
|
|
|
|
if (input_reload) {
|
|
Glitter::glt_particle_manager->FreeSceneEffect(scene_counter);
|
|
effect_group->emission = Glitter::glt_particle_manager->emission;
|
|
Glitter::glt_particle_manager->SetFrame(effect_group, &scene,
|
|
frame_counter, old_frame_counter, counter, &random, true);
|
|
Glitter::glt_particle_manager->selected_scene = scene;
|
|
scene_counter = scene->counter;
|
|
old_frame_counter = frame_counter;
|
|
input_reload = false;
|
|
}
|
|
|
|
if (old_frame_counter != frame_counter) {
|
|
if (end_frame > 0)
|
|
while (frame_counter >= (float_t)end_frame)
|
|
frame_counter -= (float_t)(end_frame - start_frame);
|
|
|
|
if (frame_counter < (float_t)start_frame)
|
|
frame_counter = (float_t)start_frame;
|
|
|
|
Glitter::glt_particle_manager->SetFrame(effect_group, &scene,
|
|
frame_counter, old_frame_counter, counter, &random, false);
|
|
Glitter::glt_particle_manager->selected_scene = scene;
|
|
scene_counter = scene->counter;
|
|
old_frame_counter = frame_counter;
|
|
}
|
|
|
|
if (input_play)
|
|
input_pause = false;
|
|
else if (input_reset) {
|
|
Glitter::glt_particle_manager->counter = counter;
|
|
frame_counter = (float_t)start_frame;
|
|
Glitter::glt_particle_manager->SetFrame(effect_group, &scene,
|
|
frame_counter, old_frame_counter, counter, &random, true);
|
|
Glitter::glt_particle_manager->selected_scene = scene;
|
|
scene_counter = scene->counter;
|
|
old_frame_counter = frame_counter;
|
|
input_pause = true;
|
|
}
|
|
input_play = false;
|
|
input_reset = false;
|
|
|
|
rob_frame = frame_counter;
|
|
|
|
if (!effect_group) {
|
|
GlitterEditor::reset_disp();
|
|
return close_editor;
|
|
}
|
|
|
|
glitter_editor_select_particle(this);
|
|
return close_editor;
|
|
}
|
|
|
|
bool GlitterEditor::dest() {
|
|
dtw_stg_unload();
|
|
dtm_stg_unload();
|
|
Glitter::glt_particle_manager->FreeSceneEffect(scene_counter);
|
|
Glitter::glt_particle_manager->UnloadEffectGroup(hash);
|
|
return true;
|
|
}
|
|
|
|
void GlitterEditor::disp() {
|
|
//if (glt_edt->draw_flags & GLITTER_EDITOR_DISP_WIREFRAME)
|
|
//glitter_editor_disp_wireframe(this);
|
|
|
|
if (draw_flags & GLITTER_EDITOR_DISP_EMITTER_TYPE)
|
|
glitter_editor_draw_emitter_type(this);
|
|
|
|
if (show_grid) {
|
|
mdl::EtcObj etc(mdl::ETC_OBJ_GRID);
|
|
etc.color = color_black;
|
|
etc.data.grid.w = 50;
|
|
etc.data.grid.h = 50;
|
|
etc.data.grid.ws = 50;
|
|
etc.data.grid.hs = 50;
|
|
rctx_ptr->disp_manager->entry_obj_etc(&mat4_identity, &etc);
|
|
}
|
|
}
|
|
|
|
void GlitterEditor::window() {
|
|
if (Input::IsKeyTapped(GLFW_KEY_O, GLFW_MOD_CONTROL))
|
|
glitter_editor_open_window(this);
|
|
else if (Input::IsKeyTapped(GLFW_KEY_F4, GLFW_MOD_CONTROL))
|
|
close = true;
|
|
else if (Input::IsKeyTapped(GLFW_KEY_F3, GLFW_MOD_CONTROL))
|
|
close_editor = true;
|
|
else if (Input::IsKeyTapped(GLFW_KEY_Q, GLFW_MOD_CONTROL))
|
|
close = true;
|
|
else if (Input::IsKeyTapped(GLFW_KEY_P))
|
|
test ^= true;
|
|
else if (Input::IsKeyTapped(GLFW_KEY_T))
|
|
input_play = true;
|
|
else if (Input::IsKeyTapped(GLFW_KEY_Y))
|
|
input_reload = true;
|
|
else if (Input::IsKeyTapped(GLFW_KEY_F))
|
|
input_pause = true;
|
|
else if (Input::IsKeyTapped(GLFW_KEY_G))
|
|
input_reset = true;
|
|
|
|
if (test)
|
|
glitter_editor_test_window(this);
|
|
else
|
|
glitter_editor_windows(this);
|
|
glitter_editor_popups(this);
|
|
|
|
if (input_locked) {
|
|
if (Input::IsKeyTapped(GLFW_KEY_S, GLFW_MOD_CONTROL | GLFW_MOD_SHIFT))
|
|
glitter_editor_save_as_window(this);
|
|
else if (Input::IsKeyTapped(GLFW_KEY_S, GLFW_MOD_CONTROL))
|
|
glitter_editor_save_window(this);
|
|
}
|
|
}
|
|
|
|
void GlitterEditor::reset() {
|
|
selected_type = GLITTER_EDITOR_SELECTED_NONE;
|
|
selected_resource = -1;
|
|
selected_effect = 0;
|
|
selected_emitter = 0;
|
|
selected_particle = 0;
|
|
selected_edit_resource = -1;
|
|
selected_edit_effect = 0;
|
|
selected_edit_emitter = 0;
|
|
selected_edit_particle = 0;
|
|
curve_editor.ResetState();
|
|
curve_editor.ResetCurves();
|
|
}
|
|
|
|
void GlitterEditor::reset_disp() {
|
|
Glitter::glt_particle_manager->selected_scene = 0;
|
|
Glitter::glt_particle_manager->selected_effect = 0;
|
|
Glitter::glt_particle_manager->selected_emitter = 0;
|
|
Glitter::glt_particle_manager->selected_particle = 0;
|
|
}
|
|
|
|
static void glitter_editor_select_particle(GlitterEditor* glt_edt) {
|
|
Glitter::glt_particle_manager->selected_scene = 0;
|
|
Glitter::glt_particle_manager->selected_effect = 0;
|
|
Glitter::glt_particle_manager->selected_emitter = 0;
|
|
Glitter::glt_particle_manager->selected_particle = 0;
|
|
Glitter::glt_particle_manager->draw_selected = false;
|
|
|
|
Glitter::EffectGroup* eg = glt_edt->effect_group;
|
|
Glitter::Scene* sc = 0;
|
|
for (Glitter::Scene*& i : Glitter::glt_particle_manager->scenes) {
|
|
if (!i)
|
|
continue;
|
|
|
|
Glitter::Scene* scene = i;
|
|
if (scene->effect_group == eg) {
|
|
sc = scene;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!sc)
|
|
return;
|
|
|
|
Glitter::EffectInst* eff = 0;
|
|
Glitter::EmitterInst* emit = 0;
|
|
Glitter::ParticleInst* ptcl = 0;
|
|
if (sc->type != Glitter::X)
|
|
for (Glitter::SceneEffect& i : sc->effects) {
|
|
if (!i.disp || !i.ptr)
|
|
continue;
|
|
|
|
Glitter::F2EffectInst* effect = (Glitter::F2EffectInst*)i.ptr;
|
|
if (effect->effect != glt_edt->selected_effect)
|
|
continue;
|
|
|
|
eff = effect;
|
|
for (Glitter::F2EmitterInst*& j : effect->emitters) {
|
|
if (!j)
|
|
continue;
|
|
|
|
Glitter::F2EmitterInst* emitter = j;
|
|
if (emitter->emitter != glt_edt->selected_emitter)
|
|
continue;
|
|
|
|
emit = emitter;
|
|
for (Glitter::F2ParticleInst*& k : emitter->particles) {
|
|
if (!k)
|
|
continue;
|
|
|
|
Glitter::F2ParticleInst* particle = k;
|
|
if (particle->particle == glt_edt->selected_particle) {
|
|
ptcl = particle;
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
for (Glitter::SceneEffect& i : sc->effects) {
|
|
if (!i.disp || !i.ptr)
|
|
continue;
|
|
|
|
Glitter::XEffectInst* effect = (Glitter::XEffectInst*)i.ptr;
|
|
if (effect->effect != glt_edt->selected_effect)
|
|
continue;
|
|
|
|
eff = effect;
|
|
for (Glitter::XEmitterInst*& j : effect->emitters) {
|
|
if (!j)
|
|
continue;
|
|
|
|
Glitter::XEmitterInst* emitter = j;
|
|
if (emitter->emitter != glt_edt->selected_emitter)
|
|
continue;
|
|
|
|
emit = emitter;
|
|
for (Glitter::XParticleInst*& k : emitter->particles) {
|
|
if (!k)
|
|
continue;
|
|
|
|
Glitter::XParticleInst* particle = k;
|
|
if (particle->particle == glt_edt->selected_particle) {
|
|
ptcl = particle;
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
Glitter::glt_particle_manager->selected_scene = sc;
|
|
if (eff) {
|
|
Glitter::glt_particle_manager->selected_effect = eff;
|
|
Glitter::glt_particle_manager->selected_emitter = emit;
|
|
Glitter::glt_particle_manager->selected_particle = ptcl;
|
|
}
|
|
else {
|
|
Glitter::glt_particle_manager->selected_effect = 0;
|
|
Glitter::glt_particle_manager->selected_emitter = 0;
|
|
Glitter::glt_particle_manager->selected_particle = 0;
|
|
}
|
|
Glitter::glt_particle_manager->draw_selected = glt_edt->draw_flags & GLITTER_EDITOR_DISP_SELECTED;
|
|
}
|
|
|
|
static void glitter_editor_windows(GlitterEditor* glt_edt) {
|
|
ImGuiIO& io = ImGui::GetIO();
|
|
ImGuiStyle& style = ImGui::GetStyle();
|
|
ImFont* font = ImGui::GetFont();
|
|
|
|
const float_t title_bar_size = font->FontSize
|
|
+ style.ItemSpacing.y + style.FramePadding.y * 2.0f;
|
|
|
|
ImVec2 main_menu_bar_size = { 0, 0 };
|
|
|
|
if (ImGui::BeginMainMenuBar()) {
|
|
bool is_x = glt_edt->effect_group
|
|
&& glt_edt->effect_group->type == Glitter::X ? true : false;
|
|
if (ImGui::BeginMenu("File", true)) {
|
|
if (ImGui::MenuItem("Open", "Ctrl+O"))
|
|
glitter_editor_open_window(glt_edt);
|
|
if (ImGui::MenuItem("Save", "Ctrl+S", false, !is_x))
|
|
glitter_editor_save_window(glt_edt);
|
|
if (ImGui::MenuItem("Save As..", "Ctrl+Shift+S", false, !is_x))
|
|
glitter_editor_save_as_window(glt_edt);
|
|
if (ImGui::MenuItem("Close", "Ctrl+F4"))
|
|
glt_edt->close = true;
|
|
if (ImGui::MenuItem("Close Editor", "Ctrl+F3"))
|
|
glt_edt->close_editor = true;
|
|
if (ImGui::MenuItem("Quit", "Ctrl+Q"))
|
|
close = true;
|
|
ImGui::EndMenu();
|
|
}
|
|
|
|
if (ImGui::BeginMenu("Edit", false)) {
|
|
ImGui::EndMenu();
|
|
}
|
|
|
|
if (ImGui::BeginMenu("Mode", glt_edt->effect_group ? true : false)) {
|
|
Glitter::EffectGroup* eg = glt_edt->effect_group;
|
|
if (eg->type != Glitter::X) {
|
|
if (ImGui::MenuItem("F2", 0, false, eg->type != Glitter::F2)) {
|
|
eg->type = Glitter::F2;
|
|
glitter_editor_reload(glt_edt);
|
|
}
|
|
|
|
if (ImGui::MenuItem("FT", 0, false, eg->type != Glitter::FT)) {
|
|
eg->type = Glitter::FT;
|
|
glitter_editor_reload(glt_edt);
|
|
}
|
|
}
|
|
else {
|
|
if (ImGui::MenuItem("X", 0, false, eg->type != Glitter::X)) {
|
|
eg->type = Glitter::X;
|
|
glitter_editor_reload(glt_edt);
|
|
}
|
|
}
|
|
ImGui::EndMenu();
|
|
}
|
|
|
|
if (ImGui::BeginMenu("View", true)) {
|
|
ImGui::CheckboxFlagsEnterKeyPressed("Wireframe",
|
|
(uint32_t*)&glt_edt->draw_flags, GLITTER_EDITOR_DISP_WIREFRAME);
|
|
ImGui::CheckboxFlagsEnterKeyPressed("Draw Selected",
|
|
(uint32_t*)&glt_edt->draw_flags, GLITTER_EDITOR_DISP_SELECTED);
|
|
ImGui::CheckboxFlagsEnterKeyPressed("No Draw",
|
|
(uint32_t*)&glt_edt->draw_flags, GLITTER_EDITOR_DISP_NO_DRAW);
|
|
ImGui::CheckboxFlagsEnterKeyPressed("Draw Emitter Type",
|
|
(uint32_t*)&glt_edt->draw_flags, GLITTER_EDITOR_DISP_EMITTER_TYPE);
|
|
ImGui::EndMenu();
|
|
}
|
|
input_locked |= ImGui::IsWindowFocused();
|
|
main_menu_bar_size = ImGui::GetWindowSize();
|
|
ImGui::EndMainMenuBar();
|
|
}
|
|
|
|
float_t x;
|
|
float_t y;
|
|
float_t w;
|
|
float_t h;
|
|
float_t win_x;
|
|
float_t win_y;
|
|
|
|
ImGuiWindowFlags window_flags;
|
|
bool selected = glt_edt->selected_effect || glt_edt->selected_emitter
|
|
|| glt_edt->selected_particle ? true : false;
|
|
|
|
win_x = min_def((float_t)width / 4.0f, 400.0f);
|
|
|
|
x = 0;
|
|
y = main_menu_bar_size.y;
|
|
w = min_def((float_t)width / 4.0f, 400.0f);
|
|
h = (float_t)height - y - min_def((float_t)height / 3.0f, 320.0f);
|
|
|
|
window_flags = 0;
|
|
window_flags |= ImGuiWindowFlags_NoTitleBar;
|
|
window_flags |= ImGuiWindowFlags_NoResize;
|
|
window_flags |= ImGuiWindowFlags_NoMove;
|
|
window_flags |= ImGuiWindowFlags_NoCollapse;
|
|
window_flags |= ImGuiWindowFlags_NoFocusOnAppearing;
|
|
window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus;
|
|
|
|
ImGui::SetNextWindowPos({ x, y }, ImGuiCond_Always);
|
|
ImGui::SetNextWindowSize({ w, h }, ImGuiCond_Always);
|
|
|
|
ImGui::PushID("Glitter Editor Effects Window");
|
|
if (ImGui::Begin("Effects", 0, window_flags)) {
|
|
if (ImGui::BeginTabBar("Effects Tab", 0)) {
|
|
if (ImGui::BeginTabItem("Effects", 0, 0)) {
|
|
if (glt_edt->effect_group)
|
|
glitter_editor_effects(glt_edt);
|
|
ImGui::EndTabItem();
|
|
}
|
|
|
|
ImGui::DisableElementPush(!!glt_edt->effect_group);
|
|
if (ImGui::BeginTabItem("Resources", 0, 0)) {
|
|
glitter_editor_resources_context_menu(glt_edt, -1, 0, true);
|
|
if (glt_edt->effect_group)
|
|
glitter_editor_resources(glt_edt);
|
|
ImGui::EndTabItem();
|
|
}
|
|
ImGui::DisableElementPop(!!glt_edt->effect_group);
|
|
|
|
if (ImGui::BeginTabItem("Play Manager", 0, 0)) {
|
|
glitter_editor_play_manager(glt_edt);
|
|
ImGui::EndTabItem();
|
|
}
|
|
ImGui::EndTabBar();
|
|
}
|
|
input_locked |= ImGui::IsWindowFocused();
|
|
ImGui::End();
|
|
}
|
|
ImGui::PopID();
|
|
|
|
win_x = min_def((float_t)width / 4.0f, 400.0f);
|
|
|
|
x = (float_t)width - win_x;
|
|
y = main_menu_bar_size.y;
|
|
w = win_x;
|
|
h = (float_t)height - y - min_def((float_t)height / 3.0f, 320.0f);
|
|
|
|
window_flags = 0;
|
|
window_flags |= ImGuiWindowFlags_NoResize;
|
|
window_flags |= ImGuiWindowFlags_NoMove;
|
|
window_flags |= ImGuiWindowFlags_NoCollapse;
|
|
window_flags |= ImGuiWindowFlags_NoFocusOnAppearing;
|
|
window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus;
|
|
|
|
ImGui::SetNextWindowPos({ x, y }, ImGuiCond_Always);
|
|
ImGui::SetNextWindowSize({ w, h }, ImGuiCond_Always);
|
|
|
|
ImGui::PushID("Glitter Editor Property Window");
|
|
if (ImGui::Begin("Property", 0, window_flags)) {
|
|
if (glt_edt->effect_group && selected)
|
|
glitter_editor_property(glt_edt);
|
|
input_locked |= ImGui::IsWindowFocused();
|
|
ImGui::End();
|
|
}
|
|
ImGui::PopID();
|
|
|
|
win_x = min_def((float_t)width / 4.0f, 400.0f);
|
|
win_y = min_def((float_t)height / 3.0f, 320.0f);
|
|
|
|
x = 0;
|
|
y = (float_t)height - win_y;
|
|
w = win_x;
|
|
h = win_y;
|
|
|
|
window_flags = 0;
|
|
window_flags |= ImGuiWindowFlags_NoResize;
|
|
window_flags |= ImGuiWindowFlags_NoMove;
|
|
window_flags |= ImGuiWindowFlags_NoCollapse;
|
|
window_flags |= ImGuiWindowFlags_NoFocusOnAppearing;
|
|
window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus;
|
|
|
|
ImGui::SetNextWindowPos({ x, y }, ImGuiCond_Always);
|
|
ImGui::SetNextWindowSize({ w, h }, ImGuiCond_Always);
|
|
|
|
ImGui::PushID("Glitter Editor Curve Editor Selector Window");
|
|
if (ImGui::Begin("Curve Editor Selector", 0, window_flags)) {
|
|
if (glt_edt->effect_group && selected)
|
|
glitter_editor_curve_editor_selector(glt_edt);
|
|
input_locked |= ImGui::IsWindowFocused();
|
|
ImGui::End();
|
|
}
|
|
ImGui::PopID();
|
|
|
|
win_x = min_def((float_t)width / 4.0f, 400.0f);
|
|
win_y = min_def((float_t)height / 3.0f, 320.0f);
|
|
|
|
x = (float_t)width - win_x;
|
|
y = (float_t)height - win_y;
|
|
w = win_x;
|
|
h = win_y;
|
|
|
|
window_flags = 0;
|
|
window_flags |= ImGuiWindowFlags_NoResize;
|
|
window_flags |= ImGuiWindowFlags_NoMove;
|
|
window_flags |= ImGuiWindowFlags_NoCollapse;
|
|
window_flags |= ImGuiWindowFlags_NoFocusOnAppearing;
|
|
window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus;
|
|
|
|
ImGui::SetNextWindowPos({ x, y }, ImGuiCond_Always);
|
|
ImGui::SetNextWindowSize({ w, h }, ImGuiCond_Always);
|
|
|
|
ImGui::PushID("Glitter Editor Curve Editor Property Window");
|
|
if (ImGui::Begin("Curve Editor Property", 0, window_flags)) {
|
|
if (glt_edt->effect_group && selected)
|
|
glitter_editor_curve_editor_property_window(glt_edt);
|
|
input_locked |= ImGui::IsWindowFocused();
|
|
ImGui::End();
|
|
}
|
|
ImGui::PopID();
|
|
|
|
win_x = min_def((float_t)width / 4.0f, 400.0f);
|
|
win_y = min_def((float_t)height / 3.0f, 320.0f);
|
|
|
|
x = win_x;
|
|
y = (float_t)height - win_y;
|
|
w = (float_t)width - win_x * 2.0f;
|
|
h = win_y;
|
|
|
|
window_flags = 0;
|
|
window_flags |= ImGuiWindowFlags_NoResize;
|
|
window_flags |= ImGuiWindowFlags_NoMove;
|
|
window_flags |= ImGuiWindowFlags_NoScrollbar;
|
|
window_flags |= ImGuiWindowFlags_NoScrollWithMouse;
|
|
window_flags |= ImGuiWindowFlags_NoCollapse;
|
|
window_flags |= ImGuiWindowFlags_NoFocusOnAppearing;
|
|
window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus;
|
|
|
|
ImGui::SetNextWindowPos({ x, y }, ImGuiCond_Always);
|
|
ImGui::SetNextWindowSize({ w, h }, ImGuiCond_Always);
|
|
|
|
ImGui::PushID("Glitter Editor Curve Editor Window");
|
|
if (ImGui::Begin("Curve Editor", 0, window_flags)) {
|
|
if (glt_edt->effect_group && selected)
|
|
glitter_editor_curve_editor_window(glt_edt);
|
|
input_locked |= ImGui::IsWindowFocused();
|
|
ImGui::End();
|
|
}
|
|
ImGui::PopID();
|
|
}
|
|
|
|
static void glitter_editor_reload(GlitterEditor* glt_edt) {
|
|
if (!glt_edt->effect_group)
|
|
return;
|
|
|
|
glt_edt->input_reload = true;
|
|
Glitter::EffectGroup* eg = glt_edt->effect_group;
|
|
Glitter::Scene* sc = glt_edt->scene;
|
|
sc->type = eg->type;
|
|
for (Glitter::Effect*& i : eg->effects) {
|
|
if (!i)
|
|
continue;
|
|
|
|
Glitter::Effect* effect = i;
|
|
if (eg->type != Glitter::FT)
|
|
effect->data.name_hash = hash_string_murmurhash(effect->name);
|
|
else
|
|
effect->data.name_hash = hash_string_fnv1a64m(effect->name);
|
|
|
|
for (Glitter::Curve*& c : effect->animation.curves)
|
|
if (c)
|
|
c->Recalculate(eg->type);
|
|
|
|
for (Glitter::Emitter*& j : effect->emitters) {
|
|
if (!j)
|
|
continue;
|
|
|
|
Glitter::Emitter* emitter = j;
|
|
for (Glitter::Curve*& c : emitter->animation.curves)
|
|
if (c)
|
|
c->Recalculate(eg->type);
|
|
|
|
for (Glitter::Particle*& k : emitter->particles) {
|
|
if (!k)
|
|
continue;
|
|
|
|
Glitter::Particle* particle = k;
|
|
for (Glitter::Curve*& c : particle->animation.curves)
|
|
if (c)
|
|
c->Recalculate(eg->type);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void glitter_editor_save(GlitterEditor* glt_edt) {
|
|
glt_edt->save_popup = glt_edt->effect_group
|
|
&& glt_edt->effect_group->type == Glitter::X ? false : true;
|
|
}
|
|
|
|
static void glitter_editor_open_window(GlitterEditor* glt_edt) {
|
|
if (FAILED(CoInitializeEx(0, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE)))
|
|
return;
|
|
|
|
wchar_t file[MAX_PATH] = {};
|
|
|
|
OPENFILENAMEW ofn = {};
|
|
ofn.lStructSize = sizeof(OPENFILENAMEW);
|
|
ofn.lpstrFilter = L"Glitter Farc Files (*.farc)\0*.farc\0\0";
|
|
ofn.lpstrFile = file;
|
|
ofn.nMaxFile = MAX_PATH;
|
|
ofn.lpstrTitle = L"File to Open";
|
|
if (GetOpenFileNameW(&ofn)) {
|
|
char* file_temp = utf16_to_utf8(file);
|
|
glt_edt->file.assign(file_temp);
|
|
free_def(file_temp);
|
|
glt_edt->load_popup = true;
|
|
}
|
|
CoUninitialize();
|
|
}
|
|
|
|
static void glitter_editor_save_window(GlitterEditor* glt_edt) {
|
|
if (!glt_edt->effect_group || !glt_edt->scene)
|
|
return;
|
|
|
|
if (glt_edt->file[0])
|
|
glitter_editor_save(glt_edt);
|
|
else
|
|
glitter_editor_save_as_window(glt_edt);
|
|
}
|
|
|
|
static void glitter_editor_save_as_window(GlitterEditor* glt_edt) {
|
|
if (glt_edt->effect_group
|
|
&& glt_edt->effect_group->type == Glitter::X) {
|
|
glt_edt->save_popup = false;
|
|
return;
|
|
}
|
|
|
|
if (FAILED(CoInitializeEx(0, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE))) {
|
|
glt_edt->save_popup = false;
|
|
return;
|
|
}
|
|
|
|
wchar_t file[MAX_PATH] = {};
|
|
|
|
OPENFILENAMEW ofn = {};
|
|
ofn.lStructSize = sizeof(OPENFILENAMEW);
|
|
ofn.lpstrFilter = L"Glitter Farc Files (*.farc)\0*.farc\0\0";
|
|
ofn.lpstrFile = file;
|
|
ofn.nMaxFile = MAX_PATH;
|
|
ofn.lpstrTitle = L"File to Save";
|
|
ofn.Flags = OFN_NONETWORKBUTTON;
|
|
if (GetSaveFileNameW(&ofn)) {
|
|
char* file_temp = utf16_to_utf8(file);
|
|
glt_edt->file.assign(file_temp);
|
|
free_def(file_temp);
|
|
glitter_editor_save(glt_edt);
|
|
}
|
|
else
|
|
glt_edt->save_popup = false;
|
|
CoUninitialize();
|
|
}
|
|
|
|
static void glitter_editor_load_file(GlitterEditor* glt_edt, const char* path, const char* file) {
|
|
if (!glt_edt->load_wait) {
|
|
Glitter::glt_particle_manager->FreeSceneEffect(glt_edt->scene_counter);
|
|
Glitter::glt_particle_manager->UnloadEffectGroup(glt_edt->hash);
|
|
|
|
GlitterEditor::reset_disp();
|
|
|
|
glt_edt->effect_group = 0;
|
|
glt_edt->scene = 0;
|
|
glt_edt->load_wait = true;
|
|
}
|
|
|
|
if (!glt_edt->load_data_wait && Glitter::glt_particle_manager->GetEffectGroup(glt_edt->hash))
|
|
return;
|
|
|
|
if (!glt_edt->load_data_wait) {
|
|
glt_edt->hash = Glitter::glt_particle_manager->LoadFile(glt_edt->load_glt_type,
|
|
&data_list[glt_edt->load_data_type], file, path, -1.0f, false);
|
|
glt_edt->load_data_wait = true;
|
|
}
|
|
else if (Glitter::glt_particle_manager->CheckNoFileReaders(glt_edt->hash)) {
|
|
Glitter::EffectGroup* eg = Glitter::glt_particle_manager->GetEffectGroup(glt_edt->hash);
|
|
if (eg) {
|
|
Glitter::glt_particle_manager->LoadScene(glt_edt->hash, eg->type != Glitter::FT
|
|
? hash_murmurhash_empty : hash_fnv1a64m_empty, false);
|
|
Glitter::Scene* sc = Glitter::glt_particle_manager->GetScene(glt_edt->hash);
|
|
if (sc) {
|
|
bool lst_not_valid = true;
|
|
enum_or(sc->flags, Glitter::SCENE_EDITOR);
|
|
if (glt_edt->load_glt_type == Glitter::FT) {
|
|
lst_not_valid = false;
|
|
for (Glitter::Effect*& i : eg->effects) {
|
|
if (!i)
|
|
continue;
|
|
|
|
Glitter::Effect* e = i;
|
|
if (e->data.name_hash != hash_string_fnv1a64m(e->name)) {
|
|
lst_not_valid = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
glt_edt->counter = Glitter::glt_particle_manager->counter;
|
|
glt_edt->effect_group = eg;
|
|
glt_edt->scene = sc;
|
|
glt_edt->scene_counter = sc->counter;
|
|
glt_edt->load_data_popup = lst_not_valid;
|
|
}
|
|
else {
|
|
Glitter::glt_particle_manager->UnloadEffectGroup(eg->hash);
|
|
glt_edt->counter = 0;
|
|
glt_edt->effect_group = 0;
|
|
glt_edt->scene = 0;
|
|
glt_edt->scene_counter = 0;
|
|
}
|
|
}
|
|
|
|
GlitterEditor::reset_disp();
|
|
|
|
Glitter::glt_particle_manager->GetSceneStartEndFrame(
|
|
&glt_edt->start_frame, &glt_edt->end_frame, glt_edt->scene_counter);
|
|
glt_edt->frame_counter = 0;
|
|
glt_edt->old_frame_counter = 0;
|
|
glt_edt->input_pause = true;
|
|
glt_edt->load = false;
|
|
glt_edt->load_wait = false;
|
|
glt_edt->load_data_wait = false;
|
|
}
|
|
else if (!Glitter::glt_particle_manager->CheckHasFileReader(glt_edt->hash)) {
|
|
glt_edt->load = false;
|
|
glt_edt->load_wait = false;
|
|
glt_edt->load_data_wait = false;
|
|
}
|
|
|
|
glt_edt->reset();
|
|
}
|
|
|
|
static void glitter_editor_save_file(GlitterEditor* glt_edt, const char* path, const char* file) {
|
|
Glitter::FileWriter::Write(glt_edt->save_glt_type, glt_edt->effect_group,
|
|
path, file, glt_edt->save_compress, glt_edt->save_encrypt);
|
|
}
|
|
|
|
static bool glitter_editor_list_open_window(Glitter::EffectGroup* eg) {
|
|
if (FAILED(CoInitializeEx(0, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE)))
|
|
return false;
|
|
|
|
bool ret = false;
|
|
|
|
wchar_t file[MAX_PATH] = {};
|
|
|
|
OPENFILENAMEW ofn = {};
|
|
ofn.lStructSize = sizeof(OPENFILENAMEW);
|
|
ofn.lpstrFilter = L"Glitter UTF-8 List Files (*.glitter.txt)\0*.glitter.txt\0\0";
|
|
ofn.lpstrFile = file;
|
|
ofn.nMaxFile = MAX_PATH;
|
|
ofn.lpstrTitle = L"File to Open";
|
|
if (GetOpenFileNameW(&ofn)) {
|
|
file_stream s;
|
|
s.open(file, L"rb");
|
|
size_t length = s.length;
|
|
uint8_t* data = force_malloc<uint8_t>(length);
|
|
s.read(data, length);
|
|
s.close();
|
|
|
|
char* buf;
|
|
char** lines;
|
|
size_t count;
|
|
if (str_utils_text_file_parse(data, length, buf, lines, count)) {
|
|
for (size_t i = 0; i < count; i++) {
|
|
char* t = strstr(lines[i], "#(?)");
|
|
if (t)
|
|
*t = 0;
|
|
}
|
|
|
|
uint64_t empty_hash = eg->type != Glitter::FT
|
|
? hash_murmurhash_empty : hash_fnv1a64m_empty;
|
|
uint64_t* hashes = force_malloc<uint64_t>(count);
|
|
if (eg->type != Glitter::FT)
|
|
for (size_t i = 0; i < count; i++) {
|
|
size_t len = utf8_length(lines[i]);
|
|
hashes[i] = hash_murmurhash(lines[i], min_def(len, 0x7F));
|
|
}
|
|
else
|
|
for (size_t i = 0; i < count; i++) {
|
|
size_t len = utf8_length(lines[i]);
|
|
hashes[i] = hash_fnv1a64m(lines[i], min_def(len, 0x7F));
|
|
}
|
|
|
|
ret = true;
|
|
for (Glitter::Effect*& i : eg->effects) {
|
|
if (!i)
|
|
continue;
|
|
|
|
Glitter::Effect* e = i;
|
|
e->name.clear();
|
|
if (e->data.name_hash == empty_hash)
|
|
continue;
|
|
|
|
size_t j;
|
|
for (j = 0; j < count; j++)
|
|
if (e->data.name_hash == hashes[j])
|
|
break;
|
|
|
|
if (j == count) {
|
|
ret = false;
|
|
continue;
|
|
}
|
|
|
|
e->name.assign(lines[j]);
|
|
}
|
|
|
|
free_def(buf);
|
|
free_def(lines);
|
|
free_def(hashes);
|
|
}
|
|
free_def(data);
|
|
}
|
|
CoUninitialize();
|
|
return ret;
|
|
}
|
|
|
|
static bool glitter_editor_resource_import(GlitterEditor* glt_edt) {
|
|
if (FAILED(CoInitializeEx(0, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE)))
|
|
return false;
|
|
|
|
bool ret = false;
|
|
|
|
wchar_t file[MAX_PATH] = {};
|
|
|
|
OPENFILENAMEW ofn = {};
|
|
ofn.lStructSize = sizeof(OPENFILENAMEW);
|
|
ofn.lpstrFilter = L"DirectDraw Sufrace Files (*.dds)\0*.dds\0\0";
|
|
ofn.lpstrFile = file;
|
|
ofn.nMaxFile = MAX_PATH;
|
|
ofn.lpstrTitle = L"File to Open";
|
|
if (GetOpenFileNameW(&ofn)) {
|
|
wchar_t* f = str_utils_get_without_extension(file);
|
|
wchar_t* p = str_utils_split_right_get_left(file, L'.');
|
|
|
|
uint64_t hash_ft = hash_utf16_fnv1a64m(f);
|
|
uint64_t hash_f2 = hash_utf16_murmurhash(f);
|
|
|
|
txp* tex;
|
|
uint32_t index;
|
|
|
|
Glitter::EffectGroup* eg = glt_edt->effect_group;
|
|
int32_t rc = eg->resources_count;
|
|
uint64_t* rh = eg->resource_hashes.data();
|
|
for (int32_t i = 0; i < rc; i++)
|
|
if (rh[i] == hash_ft || rh[i] == hash_f2)
|
|
goto DDSEnd;
|
|
{
|
|
dds d;
|
|
d.read(p);
|
|
if (!d.width || !d.height || !d.mipmaps_count || d.data.size() < 1)
|
|
goto DDSEnd;
|
|
|
|
eg->resources_tex.textures.push_back({});
|
|
tex = &eg->resources_tex.textures.back();
|
|
tex->array_size = d.has_cube_map ? 6 : 1;
|
|
tex->has_cube_map = d.has_cube_map;
|
|
tex->mipmaps_count = d.mipmaps_count;
|
|
|
|
tex->mipmaps.reserve((tex->has_cube_map ? 6LL : 1LL) * tex->mipmaps_count);
|
|
index = 0;
|
|
do
|
|
for (uint32_t i = 0; i < tex->mipmaps_count; i++) {
|
|
txp_mipmap tex_mip;
|
|
tex_mip.width = max_def(d.width >> i, 1u);
|
|
tex_mip.height = max_def(d.height >> i, 1u);
|
|
tex_mip.format = d.format;
|
|
|
|
uint32_t size = tex_mip.get_size();
|
|
tex_mip.size = size;
|
|
tex_mip.data.resize(size);
|
|
memcpy(tex_mip.data.data(), d.data[index], size);
|
|
tex->mipmaps.push_back(tex_mip);
|
|
index++;
|
|
}
|
|
while (index / tex->mipmaps_count < tex->array_size);
|
|
|
|
eg->resources_count++;
|
|
if (eg->type == Glitter::FT)
|
|
eg->resource_hashes.push_back(hash_ft);
|
|
else
|
|
eg->resource_hashes.push_back(hash_f2);
|
|
ret = true;
|
|
}
|
|
DDSEnd:
|
|
if (f)
|
|
free(f);
|
|
if (p)
|
|
free(p);
|
|
}
|
|
CoUninitialize();
|
|
return ret;
|
|
}
|
|
|
|
static bool glitter_editor_resource_export(GlitterEditor* glt_edt) {
|
|
int32_t sel_rsrc = glt_edt->selected_edit_resource;
|
|
|
|
if (FAILED(CoInitializeEx(0, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE)))
|
|
return false;
|
|
|
|
bool ret = false;
|
|
|
|
wchar_t file[MAX_PATH] = {};
|
|
|
|
OPENFILENAMEW ofn = {};
|
|
ofn.lStructSize = sizeof(OPENFILENAMEW);
|
|
ofn.lpstrFilter = L"DirectDraw Sufrace Files (*.dds)\0*.dds\0\0";
|
|
ofn.lpstrFile = file;
|
|
ofn.nMaxFile = MAX_PATH;
|
|
ofn.lpstrTitle = L"File to Save";
|
|
ofn.Flags = OFN_NONETWORKBUTTON;
|
|
if (GetSaveFileNameW(&ofn)) {
|
|
wchar_t* p = str_utils_split_right_get_left(file, L'.');
|
|
|
|
Glitter::EffectGroup* eg = glt_edt->effect_group;
|
|
txp& tex = eg->resources_tex.textures[sel_rsrc];
|
|
|
|
txp_format format = tex.mipmaps[0].format;
|
|
uint32_t width = tex.mipmaps[0].width;
|
|
uint32_t height = tex.mipmaps[0].height;
|
|
|
|
dds d;
|
|
d.format = format;
|
|
d.width = width;
|
|
d.height = height;
|
|
d.mipmaps_count = tex.mipmaps_count;
|
|
d.has_cube_map = tex.has_cube_map;
|
|
d.data.reserve((tex.has_cube_map ? 6LL : 1LL) * tex.mipmaps_count);
|
|
uint32_t index = 0;
|
|
do
|
|
for (uint32_t i = 0; i < tex.mipmaps_count; i++) {
|
|
uint32_t size = d.get_size(i);
|
|
void* data = force_malloc(size);
|
|
memcpy(data, tex.mipmaps[index].data.data(), size);
|
|
d.data.push_back(data);
|
|
index++;
|
|
}
|
|
while (index / tex.mipmaps_count < tex.array_size);
|
|
d.write(p);
|
|
ret = true;
|
|
if (p)
|
|
free(p);
|
|
}
|
|
CoUninitialize();
|
|
return ret;
|
|
}
|
|
|
|
static void glitter_editor_draw_emitter_type(GlitterEditor* glt_edt) {
|
|
if (Glitter::glt_particle_manager->flags & Glitter::PARTICLE_MANAGER_NOT_DISP)
|
|
return;
|
|
|
|
for (Glitter::Scene*& i : Glitter::glt_particle_manager->scenes)
|
|
if (i)
|
|
glitter_editor_draw_emitter_type_scene(glt_edt, i);
|
|
}
|
|
|
|
static void glitter_editor_draw_emitter_type_effect_inst(
|
|
GlitterEditor* glt_edt, Glitter::EffectInst* eff_inst) {
|
|
Glitter::EmitterInst* emit = Glitter::glt_particle_manager->selected_emitter;
|
|
if (!emit)
|
|
return;
|
|
|
|
Glitter::F2EffectInst* f2_eff_inst = dynamic_cast<Glitter::F2EffectInst*>(eff_inst);
|
|
if (f2_eff_inst && (f2_eff_inst->render_scene.GetCtrlCount(Glitter::PARTICLE_QUAD)
|
|
|| f2_eff_inst->render_scene.GetCtrlCount(Glitter::PARTICLE_LINE)
|
|
|| f2_eff_inst->render_scene.GetCtrlCount(Glitter::PARTICLE_LOCUS)))
|
|
for (Glitter::EmitterInst* i : f2_eff_inst->emitters)
|
|
if (i && i == emit) {
|
|
glitter_editor_draw_emitter_type_emitter_inst_f2(glt_edt,
|
|
i, !!(f2_eff_inst->data.flags & Glitter::EFFECT_LOCAL));
|
|
break;
|
|
}
|
|
|
|
Glitter::XEffectInst* x_eff_inst = dynamic_cast<Glitter::XEffectInst*>(eff_inst);
|
|
if (x_eff_inst && (x_eff_inst->render_scene.GetCtrlCount(Glitter::PARTICLE_QUAD)
|
|
|| x_eff_inst->render_scene.GetCtrlCount(Glitter::PARTICLE_LINE)
|
|
|| x_eff_inst->render_scene.GetCtrlCount(Glitter::PARTICLE_LOCUS)
|
|
|| x_eff_inst->render_scene.GetCtrlCount(Glitter::PARTICLE_MESH)))
|
|
for (Glitter::EmitterInst* i : x_eff_inst->emitters)
|
|
if (i && i == emit) {
|
|
glitter_editor_draw_emitter_type_emitter_inst_x(glt_edt,
|
|
i, !!(x_eff_inst->data.flags & Glitter::EFFECT_LOCAL));
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void glitter_editor_draw_emitter_type_emitter_inst_f2(
|
|
GlitterEditor* glt_edt, Glitter::EmitterInst* emit_inst, bool local) {
|
|
switch (emit_inst->data.type) {
|
|
case Glitter::EMITTER_BOX:
|
|
case Glitter::EMITTER_CYLINDER:
|
|
case Glitter::EMITTER_SPHERE:
|
|
case Glitter::EMITTER_POLYGON:
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
|
|
mat4 mat;
|
|
mat4_normalize_rotation(&emit_inst->mat, &mat);
|
|
if (local) {
|
|
GPM = Glitter::glt_particle_manager;
|
|
|
|
mat4_mul(&GPM_VAL->cam.inv_view, &emit_inst->mat, &mat);
|
|
mat4_mul(&GPM_VAL->cam.view, &mat, &mat);
|
|
mat4_mul(&mat, &GPM_VAL->cam.inv_view, &mat);
|
|
mat4_normalize_rotation(&mat, &mat);
|
|
}
|
|
else
|
|
mat4_normalize_rotation(&emit_inst->mat, &mat);
|
|
|
|
vec3 scale = emit_inst->scale * emit_inst->scale_all;
|
|
|
|
switch (emit_inst->data.type) {
|
|
case Glitter::EMITTER_BOX: {
|
|
mdl::EtcObj etc(mdl::ETC_OBJ_CUBE);
|
|
etc.color = 0x8F0000FF;
|
|
etc.constant = true;
|
|
etc.data.cube.size = vec3::max(emit_inst->data.box.size * scale, 0.1f);
|
|
etc.data.cube.wire = false;
|
|
rctx_ptr->disp_manager->entry_obj_etc(&mat, &etc, local);
|
|
|
|
if (glt_edt->draw_flags & GLITTER_EDITOR_DISP_WIREFRAME) {
|
|
etc.color = 0xFF000000;
|
|
etc.data.cube.wire = true;
|
|
rctx_ptr->disp_manager->entry_obj_etc(&mat, &etc, local);
|
|
}
|
|
} break;
|
|
case Glitter::EMITTER_CYLINDER: {
|
|
mdl::EtcObj etc(mdl::ETC_OBJ_CYLINDER);
|
|
etc.color = 0x8F00FF00;
|
|
etc.constant = true;
|
|
etc.data.cylinder.base = emit_inst->data.cylinder.radius * scale.x;
|
|
etc.data.cylinder.top = emit_inst->data.cylinder.radius * scale.x;
|
|
etc.data.cylinder.height = emit_inst->data.cylinder.height * scale.y;
|
|
etc.data.cylinder.slices = 16;
|
|
etc.data.cylinder.stacks = 1;
|
|
etc.data.cylinder.wire = false;
|
|
rctx_ptr->disp_manager->entry_obj_etc(&mat, &etc, local);
|
|
|
|
if (glt_edt->draw_flags & GLITTER_EDITOR_DISP_WIREFRAME) {
|
|
etc.color = 0xFF000000;
|
|
etc.data.cylinder.wire = true;
|
|
rctx_ptr->disp_manager->entry_obj_etc(&mat, &etc, local);
|
|
}
|
|
} break;
|
|
case Glitter::EMITTER_SPHERE: {
|
|
mdl::EtcObj etc(mdl::ETC_OBJ_SPHERE);
|
|
etc.color = 0x8FFF0000;
|
|
etc.constant = true;
|
|
etc.data.sphere.radius = emit_inst->data.sphere.radius * scale.x;
|
|
etc.data.sphere.slices = 16;
|
|
etc.data.sphere.stacks = 16;
|
|
etc.data.sphere.wire = false;
|
|
rctx_ptr->disp_manager->entry_obj_etc(&mat, &etc, local);
|
|
|
|
if (glt_edt->draw_flags & GLITTER_EDITOR_DISP_WIREFRAME) {
|
|
etc.color = 0xFF000000;
|
|
etc.data.sphere.wire = true;
|
|
rctx_ptr->disp_manager->entry_obj_etc(&mat, &etc, local);
|
|
}
|
|
} break;
|
|
case Glitter::EMITTER_POLYGON: {
|
|
mdl::EtcObj etc(mdl::ETC_OBJ_LINE);
|
|
etc.color = 0x8FFFFF00;
|
|
etc.constant = true;
|
|
etc.data.line.pos[0] = vec3(-emit_inst->data.polygon.size * scale.x * 0.5f, 0.0f, 0.0f);
|
|
etc.data.line.pos[1] = vec3(emit_inst->data.polygon.size * scale.x * 0.5f, 0.0f, 0.0f);
|
|
rctx_ptr->disp_manager->entry_obj_etc(&mat, &etc, local);
|
|
|
|
if (glt_edt->draw_flags & GLITTER_EDITOR_DISP_WIREFRAME) {
|
|
etc.color = 0xFF000000;
|
|
rctx_ptr->disp_manager->entry_obj_etc(&mat, &etc, local);
|
|
}
|
|
} break;
|
|
}
|
|
}
|
|
|
|
static void glitter_editor_draw_emitter_type_emitter_inst_x(
|
|
GlitterEditor* glt_edt, Glitter::EmitterInst* emit_inst, bool local) {
|
|
switch (emit_inst->data.type) {
|
|
case Glitter::EMITTER_BOX:
|
|
case Glitter::EMITTER_CYLINDER:
|
|
case Glitter::EMITTER_SPHERE:
|
|
case Glitter::EMITTER_POLYGON:
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
|
|
mat4 mat;
|
|
mat4_normalize_rotation(&emit_inst->mat, &mat);
|
|
if (local) {
|
|
GPM = Glitter::glt_particle_manager;
|
|
|
|
mat4_mul(&GPM_VAL->cam.inv_view, &emit_inst->mat, &mat);
|
|
mat4_mul(&GPM_VAL->cam.view, &mat, &mat);
|
|
mat4_mul(&mat, &GPM_VAL->cam.inv_view, &mat);
|
|
mat4_normalize_rotation(&mat, &mat);
|
|
}
|
|
else
|
|
mat4_normalize_rotation(&emit_inst->mat, &mat);
|
|
|
|
vec3 scale = emit_inst->scale * emit_inst->scale_all;
|
|
|
|
switch (emit_inst->data.type) {
|
|
case Glitter::EMITTER_BOX: {
|
|
mdl::EtcObj etc(mdl::ETC_OBJ_CUBE);
|
|
etc.color = 0x8F0000FF;
|
|
etc.constant = true;
|
|
etc.data.cube.size = vec3::max(emit_inst->data.box.size * scale, 0.1f);
|
|
etc.data.cube.wire = false;
|
|
rctx_ptr->disp_manager->entry_obj_etc(&mat, &etc, local);
|
|
|
|
if (glt_edt->draw_flags & GLITTER_EDITOR_DISP_WIREFRAME) {
|
|
etc.color = 0xFF000000;
|
|
etc.data.cube.wire = true;
|
|
rctx_ptr->disp_manager->entry_obj_etc(&mat, &etc, local);
|
|
}
|
|
} break;
|
|
case Glitter::EMITTER_CYLINDER: {
|
|
mdl::EtcObj etc(mdl::ETC_OBJ_CYLINDER);
|
|
etc.color = 0x8F00FF00;
|
|
etc.constant = true;
|
|
etc.data.cylinder.base = emit_inst->data.cylinder.radius * scale.x;
|
|
etc.data.cylinder.top = emit_inst->data.cylinder.radius * scale.x;
|
|
etc.data.cylinder.height = emit_inst->data.cylinder.height * scale.y;
|
|
etc.data.cylinder.slices = 16;
|
|
etc.data.cylinder.stacks = 1;
|
|
etc.data.cylinder.wire = false;
|
|
rctx_ptr->disp_manager->entry_obj_etc(&mat, &etc, local);
|
|
|
|
if (glt_edt->draw_flags & GLITTER_EDITOR_DISP_WIREFRAME) {
|
|
etc.color = 0xFF000000;
|
|
etc.data.cylinder.wire = true;
|
|
rctx_ptr->disp_manager->entry_obj_etc(&mat, &etc, local);
|
|
}
|
|
} break;
|
|
case Glitter::EMITTER_SPHERE: {
|
|
mdl::EtcObj etc(mdl::ETC_OBJ_SPHERE);
|
|
etc.color = 0x8FFF0000;
|
|
etc.constant = true;
|
|
etc.data.sphere.radius = emit_inst->data.sphere.radius * scale.x;
|
|
etc.data.sphere.slices = 16;
|
|
etc.data.sphere.stacks = 16;
|
|
etc.data.sphere.wire = false;
|
|
rctx_ptr->disp_manager->entry_obj_etc(&mat, &etc, local);
|
|
|
|
if (glt_edt->draw_flags & GLITTER_EDITOR_DISP_WIREFRAME) {
|
|
etc.color = 0xFF000000;
|
|
etc.data.sphere.wire = true;
|
|
rctx_ptr->disp_manager->entry_obj_etc(&mat, &etc, local);
|
|
}
|
|
} break;
|
|
case Glitter::EMITTER_POLYGON: {
|
|
mdl::EtcObj etc(mdl::ETC_OBJ_CYLINDER);
|
|
etc.color = 0x8FFFFF00;
|
|
etc.constant = true;
|
|
etc.data.cylinder.base = emit_inst->data.cylinder.radius * scale.x;
|
|
etc.data.cylinder.top = emit_inst->data.cylinder.radius * scale.x;
|
|
etc.data.cylinder.height = 0.0f;
|
|
etc.data.cylinder.slices = 16;
|
|
etc.data.cylinder.stacks = 0;
|
|
etc.data.cylinder.wire = false;
|
|
rctx_ptr->disp_manager->entry_obj_etc(&mat, &etc, local);
|
|
|
|
if (glt_edt->draw_flags & GLITTER_EDITOR_DISP_WIREFRAME) {
|
|
etc.color = 0xFF000000;
|
|
etc.data.cylinder.wire = true;
|
|
rctx_ptr->disp_manager->entry_obj_etc(&mat, &etc, local);
|
|
}
|
|
} break;
|
|
}
|
|
}
|
|
|
|
static void glitter_editor_draw_emitter_type_scene(GlitterEditor* glt_edt, Glitter::Scene* sc) {
|
|
if (sc->flags & Glitter::SCENE_NOT_DISP)
|
|
return;
|
|
|
|
GPM = Glitter::glt_particle_manager;
|
|
|
|
for (Glitter::SceneEffect& i : sc->effects)
|
|
if (i.ptr && i.disp) {
|
|
if (GPM_VAL->draw_selected && GPM_VAL->selected_effect
|
|
&& GPM_VAL->selected_effect != i.ptr)
|
|
continue;
|
|
|
|
glitter_editor_draw_emitter_type_effect_inst(glt_edt, i.ptr);
|
|
}
|
|
}
|
|
|
|
static void glitter_editor_disp_wireframe(GlitterEditor* glt_edt) {
|
|
if (Glitter::glt_particle_manager->flags & Glitter::PARTICLE_MANAGER_NOT_DISP)
|
|
return;
|
|
|
|
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
|
gl_state_disable_cull_face();
|
|
for (Glitter::Scene*& i : Glitter::glt_particle_manager->scenes)
|
|
if (i)
|
|
glitter_editor_disp_wireframe_scene(glt_edt, i);
|
|
gl_state_enable_cull_face();
|
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
|
}
|
|
|
|
static void glitter_editor_disp_wireframe_effect_inst(
|
|
GlitterEditor* glt_edt, Glitter::EffectInst* eff_inst) {
|
|
Glitter::XEffectInst* x_eff_inst = dynamic_cast<Glitter::XEffectInst*>(eff_inst);
|
|
if (!x_eff_inst)
|
|
return;
|
|
|
|
glitter_editor_disp_wireframe_render_scene(glt_edt, &x_eff_inst->render_scene);
|
|
}
|
|
|
|
static void glitter_editor_disp_wireframe_render_scene(
|
|
GlitterEditor* glt_edt, Glitter::XRenderScene* rend_sc) {
|
|
GPM = Glitter::glt_particle_manager;
|
|
|
|
Glitter::XEffectInst* eff = dynamic_cast<Glitter::XEffectInst*>(GPM_VAL->selected_effect);
|
|
Glitter::XEmitterInst* emit = dynamic_cast<Glitter::XEmitterInst*>(GPM_VAL->selected_emitter);
|
|
Glitter::XParticleInst* ptcl = dynamic_cast<Glitter::XParticleInst*>(GPM_VAL->selected_particle);
|
|
for (Glitter::XRenderGroup* i : rend_sc->groups) {
|
|
if (!i)
|
|
continue;
|
|
|
|
Glitter::XRenderGroup* rend_group = i;
|
|
if (rend_group->CannotDisp() && !GPM_VAL->draw_all)
|
|
continue;
|
|
|
|
if (!GPM_VAL->draw_selected || !eff) {
|
|
glitter_editor_disp_wireframe_render_scene(glt_edt, rend_sc, GPM_VAL, rend_group);
|
|
}
|
|
else if ((eff && ptcl) || (eff && !emit)) {
|
|
if (!ptcl || rend_group->particle == ptcl)
|
|
glitter_editor_disp_wireframe_render_scene(glt_edt, rend_sc, GPM_VAL, rend_group);
|
|
}
|
|
else if (emit)
|
|
for (Glitter::XParticleInst*& i : emit->particles) {
|
|
if (!i)
|
|
continue;
|
|
|
|
Glitter::XParticleInst* particle = i;
|
|
if (rend_group->particle == particle)
|
|
glitter_editor_disp_wireframe_render_scene(glt_edt, rend_sc, GPM_VAL, rend_group);
|
|
|
|
for (Glitter::XParticleInst*& j : particle->data.children)
|
|
if (j && rend_group->particle == j)
|
|
glitter_editor_disp_wireframe_render_scene(glt_edt, rend_sc, GPM_VAL, rend_group);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void glitter_editor_disp_wireframe_render_scene(GlitterEditor* glt_edt,
|
|
Glitter::XRenderScene* rend_sc, GPM, Glitter::XRenderGroup* rend_group) {
|
|
if (rend_group->disp < 1)
|
|
return;
|
|
|
|
mat4 mat;
|
|
mat4_mul(&rend_group->mat_draw, &GPM_VAL->cam.view, &mat);
|
|
mat4_mul(&mat, &GPM_VAL->cam.projection, &mat);
|
|
|
|
float_t emission = 1.0f;
|
|
if (rend_group->flags & Glitter::PARTICLE_EMISSION
|
|
|| rend_group->blend_mode == Glitter::PARTICLE_BLEND_TYPICAL)
|
|
emission = rend_group->emission;
|
|
|
|
glitter_batch_shader_data shader_data = {};
|
|
mat4_transpose(&mat, &mat);
|
|
shader_data.g_mvp[0] = mat.row0;
|
|
shader_data.g_mvp[1] = mat.row1;
|
|
shader_data.g_mvp[2] = mat.row2;
|
|
shader_data.g_mvp[3] = mat.row3;
|
|
shader_data.g_glitter_blend_color = 1.0f;
|
|
shader_data.g_state_material_diffuse = 0.0f;
|
|
shader_data.g_state_material_emission = { emission, emission, emission, 1.0f };
|
|
rctx_ptr->glitter_batch_ubo.WriteMemory(shader_data);
|
|
|
|
shaders_dev.set(SHADER_DEV_GLITTER_PT_WIREFRAME);
|
|
rctx_ptr->glitter_batch_ubo.Bind(2);
|
|
switch (rend_group->type) {
|
|
case Glitter::PARTICLE_QUAD:
|
|
gl_state_bind_vertex_array(rend_group->vao);
|
|
shaders_dev.enable_primitive_restart();
|
|
shaders_dev.draw_elements(GL_TRIANGLE_STRIP, (GLsizei)(5 * rend_group->disp - 1), GL_UNSIGNED_SHORT, 0);
|
|
shaders_dev.disable_primitive_restart();
|
|
break;
|
|
case Glitter::PARTICLE_LINE:
|
|
case Glitter::PARTICLE_LOCUS:
|
|
gl_state_bind_vertex_array(rend_group->vao);
|
|
if (rend_group->type == Glitter::PARTICLE_LINE)
|
|
for (std::pair<GLint, GLsizei>& i : rend_group->draw_list)
|
|
shaders_dev.draw_arrays(GL_LINE_STRIP, i.first, i.second);
|
|
else
|
|
for (std::pair<GLint, GLsizei>& i : rend_group->draw_list)
|
|
shaders_dev.draw_arrays(GL_TRIANGLE_STRIP, i.first, i.second);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void glitter_editor_disp_wireframe_scene(GlitterEditor* glt_edt, Glitter::Scene* sc) {
|
|
if (sc->flags & Glitter::SCENE_NOT_DISP)
|
|
return;
|
|
|
|
GPM = Glitter::glt_particle_manager;
|
|
|
|
for (Glitter::SceneEffect& i : sc->effects)
|
|
if (i.ptr && i.disp) {
|
|
if (GPM_VAL->draw_selected && GPM_VAL->selected_effect
|
|
&& GPM_VAL->selected_effect != i.ptr)
|
|
continue;
|
|
|
|
glitter_editor_disp_wireframe_effect_inst(glt_edt, i.ptr);
|
|
}
|
|
}
|
|
|
|
static void glitter_editor_test_window(GlitterEditor* glt_edt) {
|
|
Glitter::EffectGroup* eg = glt_edt->effect_group;
|
|
|
|
float_t win_x;
|
|
float_t win_y;
|
|
|
|
float_t x;
|
|
float_t y;
|
|
|
|
float_t w = 280.0f;
|
|
float_t h = 376.0f;
|
|
|
|
ImGui::SetNextWindowPos({ 0, 0 }, ImGuiCond_FirstUseEver);
|
|
ImGui::SetNextWindowSize({ w, h }, ImGuiCond_Always);
|
|
|
|
ImGuiWindowFlags window_flags = 0;
|
|
window_flags |= ImGuiWindowFlags_NoResize;
|
|
window_flags |= ImGuiWindowFlags_NoCollapse;
|
|
|
|
if (!ImGui::Begin("Glitter Editor Test Window", &glt_edt->test, window_flags)) {
|
|
input_locked |= ImGui::IsWindowFocused();
|
|
return;
|
|
}
|
|
|
|
if (ImGui::ButtonEnterKeyPressed("Reset Camera (R)"))
|
|
input_reset = true;
|
|
|
|
w = ImGui::GetContentRegionAvailWidth();
|
|
if (ImGui::BeginTable("buttons", 2)) {
|
|
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, w * 0.5f);
|
|
|
|
ImGui::TableNextColumn();
|
|
w = ImGui::GetContentRegionAvailWidth();
|
|
if (ImGui::ButtonEnterKeyPressed("Play (T)", { w, 0.0f }) || ImGui::IsKeyPressed(ImGuiKey_T))
|
|
glt_edt->input_play = true;
|
|
|
|
ImGui::TableNextColumn();
|
|
w = ImGui::GetContentRegionAvailWidth();
|
|
if (ImGui::ButtonEnterKeyPressed("Reload (Y)", { w, 0.0f }) || ImGui::IsKeyPressed(ImGuiKey_Y))
|
|
glt_edt->input_reload = true;
|
|
|
|
ImGui::TableNextColumn();
|
|
w = ImGui::GetContentRegionAvailWidth();
|
|
if (ImGui::ButtonEnterKeyPressed("Pause (F)", { w, 0.0f }) || ImGui::IsKeyPressed(ImGuiKey_F))
|
|
glt_edt->input_pause = true;
|
|
|
|
ImGui::TableNextColumn();
|
|
w = ImGui::GetContentRegionAvailWidth();
|
|
if (ImGui::ButtonEnterKeyPressed("Reset (G)", { w, 0.0f }) || ImGui::IsKeyPressed(ImGuiKey_G))
|
|
glt_edt->input_reset = true;
|
|
ImGui::EndTable();
|
|
}
|
|
|
|
ImGui::Separator();
|
|
|
|
glt_edt->old_frame_counter = glt_edt->frame_counter;
|
|
ImGui::ColumnSliderFloatButton("Frame", &glt_edt->frame_counter, 1.0f,
|
|
(float_t)glt_edt->start_frame, (float_t)glt_edt->end_frame, 10.0f, "%.0f", 0);
|
|
glt_edt->input_pause_temp = ImGui::IsItemActivatedAccum;
|
|
|
|
ImGui::Text("Start/End Frame: %d/%d", glt_edt->start_frame, glt_edt->end_frame);
|
|
|
|
ImGui::ColumnSliderFloatButton("Emission",
|
|
&Glitter::glt_particle_manager->emission, 0.01f, 1.0f, 2.0f, 0.1f, "%.2f", 0);
|
|
|
|
ImGui::Separator();
|
|
|
|
ImGui::CheckboxEnterKeyPressed("Show Grid", &glt_edt->show_grid);
|
|
|
|
ImGui::CheckboxEnterKeyPressed("Draw All", &Glitter::glt_particle_manager->draw_all);
|
|
|
|
ImGui::DisableElementPush(Glitter::glt_particle_manager->draw_all && eg && eg->type == Glitter::X);
|
|
ImGui::CheckboxEnterKeyPressed("Draw All Mesh", &Glitter::glt_particle_manager->draw_all_mesh);
|
|
ImGui::DisableElementPop(Glitter::glt_particle_manager->draw_all && eg && eg->type == Glitter::X);
|
|
|
|
ImGui::Separator();
|
|
|
|
ImGui::CheckboxFlagsEnterKeyPressed("Wireframe",
|
|
(uint32_t*)&glt_edt->draw_flags, GLITTER_EDITOR_DISP_WIREFRAME);
|
|
ImGui::CheckboxFlagsEnterKeyPressed("Draw Selected",
|
|
(uint32_t*)&glt_edt->draw_flags, GLITTER_EDITOR_DISP_SELECTED);
|
|
ImGui::CheckboxFlagsEnterKeyPressed("No Draw",
|
|
(uint32_t*)&glt_edt->draw_flags, GLITTER_EDITOR_DISP_NO_DRAW);
|
|
ImGui::CheckboxFlagsEnterKeyPressed("Draw Emitter Type",
|
|
(uint32_t*)&glt_edt->draw_flags, GLITTER_EDITOR_DISP_EMITTER_TYPE);
|
|
|
|
ImGui::Separator();
|
|
|
|
camera* cam = rctx_ptr->camera;
|
|
|
|
static const float_t fov_min = 0.0;
|
|
static const float_t fov_max = 180.0;
|
|
float_t fov = cam->get_fov();
|
|
if (ImGui::SliderScalar("Camera FOV", ImGuiDataType_Float, &fov, &fov_min, &fov_max, "%g"))
|
|
cam->set_fov(fov);
|
|
|
|
input_locked |= ImGui::IsWindowFocused();
|
|
ImGui::End();
|
|
|
|
win_x = min_def((float_t)width, 240.0f);
|
|
win_y = min_def((float_t)height, 96.0f);
|
|
|
|
x = 0.0f;
|
|
y = (float_t)height - win_y;
|
|
w = win_x;
|
|
h = win_y;
|
|
|
|
ImGui::SetNextWindowPos({ x, y }, ImGuiCond_Always);
|
|
ImGui::SetNextWindowSize({ w, h }, ImGuiCond_Always);
|
|
|
|
window_flags = 0;
|
|
window_flags |= ImGuiWindowFlags_NoTitleBar;
|
|
window_flags |= ImGuiWindowFlags_NoResize;
|
|
window_flags |= ImGuiWindowFlags_NoScrollbar;
|
|
window_flags |= ImGuiWindowFlags_NoCollapse;
|
|
window_flags |= ImGuiWindowFlags_NoMouseInputs;
|
|
window_flags |= ImGuiWindowFlags_NoNavInputs;
|
|
window_flags |= ImGuiWindowFlags_NoNavFocus;
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_Border, 0);
|
|
ImGui::PushStyleColor(ImGuiCol_WindowBg, 0);
|
|
if (ImGui::Begin("Glitter Test Sub##Data Test", 0, window_flags)) {
|
|
size_t ctrl;
|
|
size_t disp;
|
|
float_t frame;
|
|
int32_t life_time;
|
|
|
|
life_time = 0;
|
|
frame = Glitter::glt_particle_manager->GetSceneFrameLifeTime(glt_edt->scene_counter, &life_time);
|
|
ImGui::Text("%.0f - %.0f/%d", max_def(glt_edt->frame_counter - glt_edt->start_frame, 0), frame, life_time);
|
|
|
|
ctrl = Glitter::glt_particle_manager->GetCtrlCount(Glitter::PARTICLE_QUAD);
|
|
disp = Glitter::glt_particle_manager->GetDispCount(Glitter::PARTICLE_QUAD);
|
|
ImGui::Text(" Quad: ctrl%lld, disp%lld", ctrl, disp);
|
|
|
|
ctrl = Glitter::glt_particle_manager->GetCtrlCount(Glitter::PARTICLE_LOCUS);
|
|
disp = Glitter::glt_particle_manager->GetDispCount(Glitter::PARTICLE_LOCUS);
|
|
ImGui::Text("Locus: ctrl%lld, disp%lld", ctrl, disp);
|
|
|
|
ctrl = Glitter::glt_particle_manager->GetCtrlCount(Glitter::PARTICLE_LINE);
|
|
disp = Glitter::glt_particle_manager->GetDispCount(Glitter::PARTICLE_LINE);
|
|
ImGui::Text(" Line: ctrl%lld, disp%lld", ctrl, disp);
|
|
|
|
ctrl = Glitter::glt_particle_manager->GetCtrlCount(Glitter::PARTICLE_MESH);
|
|
disp = Glitter::glt_particle_manager->GetDispCount(Glitter::PARTICLE_MESH);
|
|
ImGui::Text(" Mesh: ctrl%lld, disp%lld", ctrl, disp);
|
|
ImGui::End();
|
|
}
|
|
ImGui::PopStyleColor(2);
|
|
}
|
|
|
|
static void glitter_editor_effects(GlitterEditor* glt_edt) {
|
|
char buf[0x200];
|
|
|
|
ImGuiTreeNodeFlags tree_node_base_flags = 0;
|
|
tree_node_base_flags |= ImGuiTreeNodeFlags_OpenOnDoubleClick;
|
|
tree_node_base_flags |= ImGuiTreeNodeFlags_OpenOnArrow;
|
|
tree_node_base_flags |= ImGuiTreeNodeFlags_SpanAvailWidth;
|
|
|
|
ImGuiTreeNodeFlags tree_node_flags;
|
|
|
|
Glitter::EffectGroup* eg = glt_edt->effect_group;
|
|
ImGui::PushID(eg);
|
|
ssize_t i_idx = 1;
|
|
for (Glitter::Effect*& i : eg->effects) {
|
|
if (!i) {
|
|
i_idx++;
|
|
continue;
|
|
}
|
|
|
|
Glitter::Effect* effect = i;
|
|
tree_node_flags = tree_node_base_flags;
|
|
if (effect == glt_edt->selected_effect && !glt_edt->selected_emitter
|
|
&& !glt_edt->selected_particle)
|
|
tree_node_flags |= ImGuiTreeNodeFlags_Selected;
|
|
|
|
const char* eff_str;
|
|
if (effect->data.ext_anim) {
|
|
if (effect->data.ext_anim->flags & Glitter::EFFECT_EXT_ANIM_CHARA_ANIM)
|
|
eff_str = "%s (%08X) [C]";
|
|
else
|
|
eff_str = "%s (%08X) [O]";
|
|
}
|
|
else if (effect->data.flags & Glitter::EFFECT_LOCAL)
|
|
eff_str = "%s (%08X) [L]";
|
|
else
|
|
eff_str = "%s (%08X)";
|
|
|
|
ImGui::PushID(effect);
|
|
if (ImGui::TreeNodeEx("effect", tree_node_flags, eff_str,
|
|
effect->name.c_str(), (uint32_t)((size_t)effect * hash_fnv1a64m_empty))) {
|
|
glitter_editor_effects_context_menu(glt_edt, effect, 0, 0,
|
|
i_idx, 0, 0, GLITTER_EDITOR_SELECTED_EFFECT);
|
|
|
|
ssize_t j_idx = 1;
|
|
for (Glitter::Emitter*& j : effect->emitters) {
|
|
if (!j) {
|
|
j_idx++;
|
|
continue;
|
|
}
|
|
|
|
Glitter::Emitter* emitter = j;
|
|
tree_node_flags = tree_node_base_flags;
|
|
if (emitter == glt_edt->selected_emitter && !glt_edt->selected_particle)
|
|
tree_node_flags |= ImGuiTreeNodeFlags_Selected;
|
|
|
|
const char* emit_str;
|
|
if (emitter->data.timer == Glitter::EMITTER_TIMER_BY_TIME) {
|
|
if (emitter->data.emission_interval <= -0.000001f)
|
|
emit_str = "Emitter %lld (%08X) [E]";
|
|
else if (emitter->data.emission_interval >= 0.000001f)
|
|
emit_str = "Emitter %lld (%08X) [T]";
|
|
else
|
|
emit_str = "Emitter %lld (%08X) [S]";
|
|
}
|
|
else if (emitter->data.timer == Glitter::EMITTER_TIMER_BY_DISTANCE)
|
|
emit_str = "Emitter %lld (%08X) [D]";
|
|
else
|
|
emit_str = "Emitter %lld (%08X)";
|
|
|
|
ImGui::PushID(emitter);
|
|
if (ImGui::TreeNodeEx("emitter", tree_node_flags, emit_str,
|
|
j_idx, (uint32_t)((size_t)emitter * hash_fnv1a64m_empty))) {
|
|
glitter_editor_effects_context_menu(glt_edt, effect, emitter, 0,
|
|
i_idx, j_idx, 0, GLITTER_EDITOR_SELECTED_EMITTER);
|
|
|
|
ssize_t k_idx = 1;
|
|
for (Glitter::Particle*& k : emitter->particles) {
|
|
if (!k) {
|
|
k_idx++;
|
|
continue;
|
|
}
|
|
|
|
Glitter::Particle* particle = k;
|
|
tree_node_flags = tree_node_base_flags;
|
|
|
|
const char* ptcl_str;
|
|
switch (particle->data.type) {
|
|
case Glitter::PARTICLE_QUAD:
|
|
ptcl_str = "Particle %lld (%08X) [Quad]";
|
|
break;
|
|
case Glitter::PARTICLE_LINE:
|
|
ptcl_str = "Particle %lld (%08X) [Line]";
|
|
break;
|
|
case Glitter::PARTICLE_LOCUS:
|
|
ptcl_str = "Particle %lld (%08X) [Locus]";
|
|
break;
|
|
case Glitter::PARTICLE_MESH:
|
|
ptcl_str = "Particle %lld (%08X) [Mesh]";
|
|
break;
|
|
default:
|
|
ptcl_str = "Particle %lld (%08X)";
|
|
break;
|
|
}
|
|
|
|
ImGui::PushID(particle);
|
|
snprintf(buf, sizeof(buf), ptcl_str,
|
|
k_idx, (uint32_t)((size_t)particle * hash_fnv1a64m_empty));
|
|
ImGui::Selectable(buf, particle == glt_edt->selected_particle,
|
|
0, { 0.0f, 0.0f });
|
|
glitter_editor_effects_context_menu(glt_edt, effect, emitter, particle,
|
|
i_idx, j_idx, k_idx, GLITTER_EDITOR_SELECTED_PARTICLE);
|
|
ImGui::PopID();
|
|
k_idx++;
|
|
}
|
|
ImGui::TreePop();
|
|
}
|
|
else
|
|
glitter_editor_effects_context_menu(glt_edt, effect, emitter, 0,
|
|
i_idx, j_idx, 0, GLITTER_EDITOR_SELECTED_EMITTER);
|
|
ImGui::PopID();
|
|
j_idx++;
|
|
}
|
|
ImGui::TreePop();
|
|
}
|
|
else
|
|
glitter_editor_effects_context_menu(glt_edt, effect, 0, 0,
|
|
i_idx, 0, 0, GLITTER_EDITOR_SELECTED_EFFECT);
|
|
ImGui::PopID();
|
|
i_idx++;
|
|
}
|
|
ImGui::PopID();
|
|
}
|
|
|
|
static void glitter_editor_effects_context_menu(GlitterEditor* glt_edt,
|
|
Glitter::Effect* effect, Glitter::Emitter* emitter, Glitter::Particle* particle,
|
|
ssize_t i_idx, ssize_t j_idx, ssize_t k_idx,
|
|
glitter_editor_selected_enum type) {
|
|
Glitter::Effect* sel_efct = glt_edt->selected_effect;
|
|
Glitter::Emitter* sel_emit = glt_edt->selected_emitter;
|
|
|
|
bool focused = ImGui::IsItemFocused();
|
|
|
|
ImGuiWindowFlags window_flags;
|
|
bool close;
|
|
|
|
static void* selected;
|
|
if (type == GLITTER_EDITOR_SELECTED_NONE) {
|
|
if (ImGui::IsWindowHovered() && ImGui::IsMouseReleased(ImGuiMouseButton_Right)) {
|
|
ImGui::OpenPopup("effects popup", ImGuiPopupFlags_MouseButtonRight);
|
|
selected = 0;
|
|
}
|
|
else if (selected)
|
|
goto End;
|
|
}
|
|
else if (ImGui::IsItemHovered() && ImGui::IsMouseReleased(ImGuiMouseButton_Right)) {
|
|
switch (type) {
|
|
case GLITTER_EDITOR_SELECTED_EFFECT:
|
|
selected = effect;
|
|
break;
|
|
case GLITTER_EDITOR_SELECTED_EMITTER:
|
|
selected = emitter;
|
|
break;
|
|
case GLITTER_EDITOR_SELECTED_PARTICLE:
|
|
selected = particle;
|
|
break;
|
|
default:
|
|
goto End;
|
|
}
|
|
ImGui::OpenPopup("effects popup", ImGuiPopupFlags_MouseButtonRight);
|
|
}
|
|
else
|
|
switch (type) {
|
|
case GLITTER_EDITOR_SELECTED_EFFECT:
|
|
if (selected != effect)
|
|
goto End;
|
|
break;
|
|
case GLITTER_EDITOR_SELECTED_EMITTER:
|
|
if (selected != emitter)
|
|
goto End;
|
|
break;
|
|
case GLITTER_EDITOR_SELECTED_PARTICLE:
|
|
if (selected != particle)
|
|
goto End;
|
|
break;
|
|
default:
|
|
goto End;
|
|
}
|
|
|
|
window_flags = 0;
|
|
window_flags |= ImGuiWindowFlags_NoTitleBar;
|
|
window_flags |= ImGuiWindowFlags_AlwaysAutoResize;
|
|
|
|
if (!ImGui::BeginPopup("effects popup", window_flags))
|
|
goto End;
|
|
|
|
global_context_menu = false;
|
|
|
|
close = false;
|
|
switch (type) {
|
|
case GLITTER_EDITOR_SELECTED_NONE: {
|
|
if (ImGui::MenuItem("Add Effect", 0)) {
|
|
if (!glt_edt->effect_group)
|
|
glt_edt->create_popup = true;
|
|
else
|
|
enum_or(glt_edt->effect_flags, GLITTER_EDITOR_ADD);
|
|
close = true;
|
|
}
|
|
} break;
|
|
case GLITTER_EDITOR_SELECTED_EFFECT: {
|
|
if (!glt_edt->effect_group)
|
|
break;
|
|
|
|
const char* eff_str;
|
|
if (effect->data.ext_anim) {
|
|
if (effect->data.ext_anim->flags & Glitter::EFFECT_EXT_ANIM_CHARA_ANIM)
|
|
eff_str = "%s (%08X) [C]";
|
|
else
|
|
eff_str = "%s (%08X) [O]";
|
|
}
|
|
else if (effect->data.flags & Glitter::EFFECT_LOCAL)
|
|
eff_str = "%s (%08X) [L]";
|
|
else
|
|
eff_str = "%s (%08X)";
|
|
|
|
Glitter::EffectGroup* eg = glt_edt->effect_group;
|
|
ImGui::Text(eff_str, effect->name.c_str(), (uint32_t)((size_t)effect * hash_fnv1a64m_empty));
|
|
ImGui::Separator();
|
|
if (ImGui::MenuItem("Duplicate Effect")) {
|
|
enum_or(glt_edt->effect_flags, GLITTER_EDITOR_DUPLICATE);
|
|
glt_edt->selected_edit_effect = effect;
|
|
close = true;
|
|
}
|
|
|
|
if (ImGui::MenuItem("Delete Effect")) {
|
|
enum_or(glt_edt->effect_flags, GLITTER_EDITOR_DELETE);
|
|
glt_edt->selected_edit_effect = effect;
|
|
close = true;
|
|
}
|
|
|
|
if (ImGui::MenuItem("Move Effect Up", 0, false, i_idx > 1)) {
|
|
enum_or(glt_edt->effect_flags, GLITTER_EDITOR_MOVE_UP);
|
|
glt_edt->selected_edit_effect = effect;
|
|
close = true;
|
|
}
|
|
|
|
if (ImGui::MenuItem("Move Effect Down", 0, false, i_idx < (ssize_t)eg->effects.size())) {
|
|
enum_or(glt_edt->effect_flags, GLITTER_EDITOR_MOVE_DOWN);
|
|
glt_edt->selected_edit_effect = effect;
|
|
close = true;
|
|
}
|
|
|
|
ImGui::Separator();
|
|
|
|
if (ImGui::MenuItem("Add Emitter")) {
|
|
enum_or(glt_edt->emitter_flags, GLITTER_EDITOR_ADD);
|
|
glt_edt->selected_edit_effect = effect;
|
|
close = true;
|
|
}
|
|
} break;
|
|
case GLITTER_EDITOR_SELECTED_EMITTER: {
|
|
if (!glt_edt->selected_effect)
|
|
break;
|
|
|
|
const char* emit_str;
|
|
if (emitter->data.timer == Glitter::EMITTER_TIMER_BY_TIME) {
|
|
if (emitter->data.emission_interval <= -0.000001f)
|
|
emit_str = "Emitter %lld (%08X) [E]";
|
|
else if (emitter->data.emission_interval >= 0.000001f)
|
|
emit_str = "Emitter %lld (%08X) [T]";
|
|
else
|
|
emit_str = "Emitter %lld (%08X) [S]";
|
|
}
|
|
else if (emitter->data.timer == Glitter::EMITTER_TIMER_BY_DISTANCE)
|
|
emit_str = "Emitter %lld (%08X) [D]";
|
|
else
|
|
emit_str = "Emitter %lld (%08X)";
|
|
|
|
ImGui::Text(emit_str, j_idx, (size_t)emitter * hash_fnv1a64m_empty);
|
|
ImGui::Separator();
|
|
if (ImGui::MenuItem("Duplicate Emitter")) {
|
|
enum_or(glt_edt->emitter_flags, GLITTER_EDITOR_DUPLICATE);
|
|
glt_edt->selected_edit_emitter = emitter;
|
|
close = true;
|
|
}
|
|
|
|
if (ImGui::MenuItem("Delete Emitter")) {
|
|
enum_or(glt_edt->emitter_flags, GLITTER_EDITOR_DELETE);
|
|
glt_edt->selected_edit_emitter = emitter;
|
|
close = true;
|
|
}
|
|
|
|
if (ImGui::MenuItem("Move Emitter Up", 0, false, j_idx > 1)) {
|
|
enum_or(glt_edt->emitter_flags, GLITTER_EDITOR_MOVE_UP);
|
|
glt_edt->selected_edit_emitter = emitter;
|
|
close = true;
|
|
}
|
|
|
|
if (ImGui::MenuItem("Move Emitter Down", 0, false,
|
|
j_idx < (ssize_t)sel_efct->emitters.size())) {
|
|
enum_or(glt_edt->emitter_flags, GLITTER_EDITOR_MOVE_DOWN);
|
|
glt_edt->selected_edit_emitter = emitter;
|
|
close = true;
|
|
}
|
|
|
|
ImGui::Separator();
|
|
|
|
if (ImGui::MenuItem("Add Particle")) {
|
|
enum_or(glt_edt->particle_flags, GLITTER_EDITOR_ADD);
|
|
glt_edt->selected_edit_emitter = emitter;
|
|
close = true;
|
|
}
|
|
} break;
|
|
case GLITTER_EDITOR_SELECTED_PARTICLE: {
|
|
if (!glt_edt->selected_emitter)
|
|
break;
|
|
|
|
const char* ptcl_str;
|
|
switch (particle->data.type) {
|
|
case Glitter::PARTICLE_QUAD:
|
|
ptcl_str = "Particle %lld (%08X) [Quad]";
|
|
break;
|
|
case Glitter::PARTICLE_LINE:
|
|
ptcl_str = "Particle %lld (%08X) [Line]";
|
|
break;
|
|
case Glitter::PARTICLE_LOCUS:
|
|
ptcl_str = "Particle %lld (%08X) [Locus]";
|
|
break;
|
|
case Glitter::PARTICLE_MESH:
|
|
ptcl_str = "Particle %lld (%08X) [Mesh]";
|
|
break;
|
|
default:
|
|
ptcl_str = "Particle %lld (%08X)";
|
|
break;
|
|
}
|
|
|
|
ImGui::Text(ptcl_str, k_idx, (uint32_t)((size_t)particle * hash_fnv1a64m_empty));
|
|
ImGui::Separator();
|
|
if (ImGui::MenuItem("Duplicate Particle")) {
|
|
enum_or(glt_edt->particle_flags, GLITTER_EDITOR_DUPLICATE);
|
|
glt_edt->selected_edit_particle = particle;
|
|
close = true;
|
|
}
|
|
|
|
if (ImGui::MenuItem("Delete Particle")) {
|
|
enum_or(glt_edt->particle_flags, GLITTER_EDITOR_DELETE);
|
|
glt_edt->selected_edit_particle = particle;
|
|
close = true;
|
|
}
|
|
|
|
if (ImGui::MenuItem("Move Particle Up", 0, false, k_idx > 1)) {
|
|
enum_or(glt_edt->particle_flags, GLITTER_EDITOR_MOVE_UP);
|
|
glt_edt->selected_edit_particle = particle;
|
|
close = true;
|
|
}
|
|
|
|
if (ImGui::MenuItem("Move Particle Down", 0, false,
|
|
k_idx < (ssize_t)sel_emit->particles.size())) {
|
|
enum_or(glt_edt->particle_flags, GLITTER_EDITOR_MOVE_DOWN);
|
|
glt_edt->selected_edit_particle = particle;
|
|
close = true;
|
|
}
|
|
} break;
|
|
}
|
|
|
|
if (close) {
|
|
ImGui::CloseCurrentPopup();
|
|
selected = 0;
|
|
}
|
|
input_locked |= ImGui::IsWindowFocused();
|
|
ImGui::EndPopup();
|
|
|
|
End:
|
|
if (!focused)
|
|
return;
|
|
|
|
switch (type) {
|
|
case GLITTER_EDITOR_SELECTED_EFFECT:
|
|
if (glt_edt->selected_type != type
|
|
|| glt_edt->selected_effect != effect)
|
|
glt_edt->reset();
|
|
glt_edt->selected_effect = effect;
|
|
glt_edt->selected_emitter = 0;
|
|
glt_edt->selected_particle = 0;
|
|
break;
|
|
case GLITTER_EDITOR_SELECTED_EMITTER:
|
|
if (glt_edt->selected_type != type
|
|
|| glt_edt->selected_emitter != emitter)
|
|
glt_edt->reset();
|
|
glt_edt->selected_effect = effect;
|
|
glt_edt->selected_emitter = emitter;
|
|
glt_edt->selected_particle = 0;
|
|
break;
|
|
case GLITTER_EDITOR_SELECTED_PARTICLE:
|
|
if (glt_edt->selected_type != type
|
|
|| glt_edt->selected_particle != particle)
|
|
glt_edt->reset();
|
|
glt_edt->selected_effect = effect;
|
|
glt_edt->selected_emitter = emitter;
|
|
glt_edt->selected_particle = particle;
|
|
break;
|
|
}
|
|
glt_edt->selected_type = type;
|
|
}
|
|
|
|
static void glitter_editor_resources(GlitterEditor* glt_edt) {
|
|
int32_t sel_rsrc = glt_edt->selected_resource;
|
|
|
|
char buf[0x200];
|
|
|
|
ImGuiTreeNodeFlags tree_node_base_flags = 0;
|
|
tree_node_base_flags |= ImGuiTreeNodeFlags_OpenOnDoubleClick;
|
|
tree_node_base_flags |= ImGuiTreeNodeFlags_OpenOnArrow;
|
|
tree_node_base_flags |= ImGuiTreeNodeFlags_SpanAvailWidth;
|
|
|
|
Glitter::EffectGroup* eg = glt_edt->effect_group;
|
|
texture** r = eg->resources;
|
|
int32_t rc = eg->resources_count;
|
|
uint64_t* rh = eg->resource_hashes.data();
|
|
txp* rt = eg->resources_tex.textures.data();
|
|
ImGui::PushID(eg);
|
|
ssize_t i_idx = 1;
|
|
for (int32_t i = 0; i < rc; i++, i_idx++) {
|
|
snprintf(buf, sizeof(buf), "Texture %d (%016llX)", i + 1, rh[i]);
|
|
ImGui::PushID(i);
|
|
ImGui::Selectable(buf, i == sel_rsrc, 0, { 0.0f, 0.0f });
|
|
if (ImGui::IsItemHovered()) {
|
|
txp_mipmap* rtm = rt[i].mipmaps.data();
|
|
float_t aspect = (float_t)rtm->width / (float_t)rtm->height;
|
|
|
|
ImVec2 size = { 192.0f, 192.0f };
|
|
if (aspect > 1.0f)
|
|
size.y /= aspect;
|
|
else if (aspect < 1.0f)
|
|
size.x *= aspect;
|
|
|
|
ImGui::BeginTooltip();
|
|
ImGui::Text("Tex Size: %dx%d", rtm->width, rtm->height);
|
|
ImGui::Image((void*)(size_t)r[i]->tex, size,
|
|
{ 0, 0 }, { 1, 1 }, tint_col, border_col);
|
|
ImGui::EndTooltip();
|
|
}
|
|
glitter_editor_resources_context_menu(glt_edt, i, i_idx, false);
|
|
ImGui::PopID();
|
|
}
|
|
ImGui::PopID();
|
|
}
|
|
|
|
static void glitter_editor_resources_context_menu(GlitterEditor* glt_edt,
|
|
int32_t resource, ssize_t i_idx, bool selected_none) {
|
|
bool focused = ImGui::IsItemFocused();
|
|
|
|
ImGuiWindowFlags window_flags;
|
|
bool close;
|
|
|
|
static size_t selected;
|
|
if (selected_none) {
|
|
if (ImGui::IsWindowHovered() && ImGui::IsMouseReleased(ImGuiMouseButton_Right)) {
|
|
ImGui::OpenPopup("resources popup", ImGuiPopupFlags_MouseButtonRight);
|
|
selected = -1;
|
|
}
|
|
else if (selected != -1)
|
|
goto End;
|
|
}
|
|
else if (ImGui::IsItemHovered() && ImGui::IsMouseReleased(ImGuiMouseButton_Right)) {
|
|
selected = resource;
|
|
ImGui::OpenPopup("resources popup", ImGuiPopupFlags_MouseButtonRight);
|
|
}
|
|
else if (selected != resource)
|
|
goto End;
|
|
|
|
window_flags = 0;
|
|
window_flags |= ImGuiWindowFlags_NoTitleBar;
|
|
window_flags |= ImGuiWindowFlags_AlwaysAutoResize;
|
|
|
|
if (!ImGui::BeginPopup("resources popup", window_flags))
|
|
goto End;
|
|
|
|
global_context_menu = false;
|
|
|
|
close = false;
|
|
if (selected_none) {
|
|
if (ImGui::MenuItem("Import Resource", 0)) {
|
|
enum_or(glt_edt->resource_flags, GLITTER_EDITOR_IMPORT);
|
|
close = true;
|
|
}
|
|
}
|
|
else {
|
|
size_t i = resource;
|
|
Glitter::EffectGroup* eg = glt_edt->effect_group;
|
|
ssize_t rc = eg->resources_count;
|
|
uint64_t* rh = eg->resource_hashes.data();
|
|
ImGui::Text("Texture %lld (%016llX)", i + 1, rh[i]);
|
|
ImGui::Separator();
|
|
if (ImGui::MenuItem("Export Resource")) {
|
|
enum_or(glt_edt->resource_flags, GLITTER_EDITOR_EXPORT);
|
|
glt_edt->selected_edit_resource = resource;
|
|
close = true;
|
|
}
|
|
|
|
if (ImGui::MenuItem("Delete Resource")) {
|
|
enum_or(glt_edt->resource_flags, GLITTER_EDITOR_DELETE);
|
|
glt_edt->selected_edit_resource = resource;
|
|
close = true;
|
|
}
|
|
|
|
if (ImGui::MenuItem("Move Resource Up", 0, false, i_idx > 1)) {
|
|
enum_or(glt_edt->resource_flags, GLITTER_EDITOR_MOVE_UP);
|
|
glt_edt->selected_edit_resource = resource;
|
|
close = true;
|
|
}
|
|
|
|
if (ImGui::MenuItem("Move Resource Down", 0, false,
|
|
i_idx < rc)) {
|
|
enum_or(glt_edt->resource_flags, GLITTER_EDITOR_MOVE_DOWN);
|
|
glt_edt->selected_edit_resource = resource;
|
|
close = true;
|
|
}
|
|
}
|
|
|
|
if (close) {
|
|
ImGui::CloseCurrentPopup();
|
|
selected = 0;
|
|
}
|
|
input_locked |= ImGui::IsWindowFocused();
|
|
ImGui::EndPopup();
|
|
|
|
End:
|
|
if (!focused)
|
|
return;
|
|
|
|
glt_edt->selected_resource = resource;
|
|
}
|
|
|
|
static void glitter_editor_play_manager(GlitterEditor* glt_edt) {
|
|
Glitter::EffectGroup* eg = glt_edt->effect_group;
|
|
|
|
if (ImGui::ButtonEnterKeyPressed("Reset Camera (R)"))
|
|
input_reset = true;
|
|
|
|
float_t w = ImGui::GetContentRegionAvailWidth();
|
|
if (ImGui::BeginTable("buttons", 2)) {
|
|
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, w * 0.5f);
|
|
|
|
ImGui::TableNextColumn();
|
|
w = ImGui::GetContentRegionAvailWidth();
|
|
if (ImGui::ButtonEnterKeyPressed("Play (T)", { w, 0.0f }) || ImGui::IsKeyPressed(ImGuiKey_T))
|
|
glt_edt->input_play = true;
|
|
|
|
ImGui::TableNextColumn();
|
|
w = ImGui::GetContentRegionAvailWidth();
|
|
if (ImGui::ButtonEnterKeyPressed("Reload (Y)", { w, 0.0f }) || ImGui::IsKeyPressed(ImGuiKey_Y))
|
|
glt_edt->input_reload = true;
|
|
|
|
ImGui::TableNextColumn();
|
|
w = ImGui::GetContentRegionAvailWidth();
|
|
if (ImGui::ButtonEnterKeyPressed("Pause (F)", { w, 0.0f }) || ImGui::IsKeyPressed(ImGuiKey_F))
|
|
glt_edt->input_pause = true;
|
|
|
|
ImGui::TableNextColumn();
|
|
w = ImGui::GetContentRegionAvailWidth();
|
|
if (ImGui::ButtonEnterKeyPressed("Reset (G)", { w, 0.0f }) || ImGui::IsKeyPressed(ImGuiKey_G))
|
|
glt_edt->input_reset = true;
|
|
ImGui::EndTable();
|
|
}
|
|
|
|
ImGui::Separator();
|
|
|
|
glt_edt->old_frame_counter = glt_edt->frame_counter;
|
|
ImGui::ColumnSliderFloatButton("Frame", &glt_edt->frame_counter, 1.0f,
|
|
(float_t)glt_edt->start_frame, (float_t)glt_edt->end_frame, 10.0f, "%.0f", 0);
|
|
glt_edt->input_pause_temp = ImGui::IsItemActivatedAccum;
|
|
|
|
ImGui::Text("Start/End Frame: %d/%d", glt_edt->start_frame, glt_edt->end_frame);
|
|
|
|
ImGui::Separator();
|
|
|
|
size_t ctrl;
|
|
size_t disp;
|
|
float_t frame;
|
|
int32_t life_time;
|
|
|
|
life_time = 0;
|
|
frame = Glitter::glt_particle_manager->GetSceneFrameLifeTime(glt_edt->scene_counter, &life_time);
|
|
ImGui::Text("%.0f - %.0f/%d", max_def(glt_edt->frame_counter - glt_edt->start_frame, 0), frame, life_time);
|
|
|
|
ctrl = Glitter::glt_particle_manager->GetCtrlCount(Glitter::PARTICLE_QUAD);
|
|
disp = Glitter::glt_particle_manager->GetDispCount(Glitter::PARTICLE_QUAD);
|
|
ImGui::Text(" Quad: ctrl%lld, disp%lld", ctrl, disp);
|
|
|
|
ctrl = Glitter::glt_particle_manager->GetCtrlCount(Glitter::PARTICLE_LOCUS);
|
|
disp = Glitter::glt_particle_manager->GetDispCount(Glitter::PARTICLE_LOCUS);
|
|
ImGui::Text("Locus: ctrl%lld, disp%lld", ctrl, disp);
|
|
|
|
ctrl = Glitter::glt_particle_manager->GetCtrlCount(Glitter::PARTICLE_LINE);
|
|
disp = Glitter::glt_particle_manager->GetDispCount(Glitter::PARTICLE_LINE);
|
|
ImGui::Text(" Line: ctrl%lld, disp%lld", ctrl, disp);
|
|
|
|
ctrl = Glitter::glt_particle_manager->GetCtrlCount(Glitter::PARTICLE_MESH);
|
|
disp = Glitter::glt_particle_manager->GetDispCount(Glitter::PARTICLE_MESH);
|
|
ImGui::Text(" Mesh: ctrl%lld, disp%lld", ctrl, disp);
|
|
|
|
ImGui::Separator();
|
|
|
|
ImGui::ColumnSliderFloatButton("Emission",
|
|
&Glitter::glt_particle_manager->emission, 0.01f, 1.0f, 2.0f, 0.1f, "%.2f", 0);
|
|
|
|
ImGui::Separator();
|
|
|
|
ImGui::CheckboxEnterKeyPressed("Show Grid", &glt_edt->show_grid);
|
|
|
|
ImGui::CheckboxEnterKeyPressed("Draw All", &Glitter::glt_particle_manager->draw_all);
|
|
|
|
ImGui::DisableElementPush(Glitter::glt_particle_manager->draw_all && eg && eg->type == Glitter::X);
|
|
ImGui::CheckboxEnterKeyPressed("Draw All Mesh", &Glitter::glt_particle_manager->draw_all_mesh);
|
|
ImGui::DisableElementPop(Glitter::glt_particle_manager->draw_all && eg && eg->type == Glitter::X);
|
|
|
|
ImGui::Separator();
|
|
|
|
camera* cam = rctx_ptr->camera;
|
|
|
|
static const float_t fov_min = 0.0f;
|
|
static const float_t fov_max = 180.0f;
|
|
float_t fov = cam->get_fov();
|
|
if (ImGui::SliderScalar("Camera FOV", ImGuiDataType_Float, &fov, &fov_min, &fov_max, "%g"))
|
|
cam->set_fov(fov);
|
|
}
|
|
|
|
static void glitter_editor_property(GlitterEditor* glt_edt) {
|
|
switch (glt_edt->selected_type) {
|
|
case GLITTER_EDITOR_SELECTED_EFFECT:
|
|
glitter_editor_property_effect(glt_edt);
|
|
break;
|
|
case GLITTER_EDITOR_SELECTED_EMITTER:
|
|
glitter_editor_property_emitter(glt_edt);
|
|
break;
|
|
case GLITTER_EDITOR_SELECTED_PARTICLE:
|
|
glitter_editor_property_particle(glt_edt);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void glitter_editor_property_effect(GlitterEditor* glt_edt) {
|
|
ImGui::SetColumnSpace(2.0f / 5.0f);
|
|
|
|
uint64_t hash_before = hash_fnv1a64m(glt_edt->selected_effect, sizeof(Glitter::Effect));
|
|
|
|
Glitter::EffectGroup* eg = glt_edt->effect_group;
|
|
Glitter::Effect* effect = glt_edt->selected_effect;
|
|
bool changed = false;
|
|
|
|
Glitter::CurveTypeFlags flags = Glitter::effect_curve_flags;
|
|
for (int32_t i = Glitter::CURVE_TRANSLATION_X; i <= Glitter::CURVE_V_SCROLL_ALPHA_2ND; i++)
|
|
for (Glitter::Curve*& j : effect->animation.curves)
|
|
if (j && j->type == i)
|
|
enum_and(flags, ~(1 << i));
|
|
|
|
std::string name;
|
|
name.reserve(0x200);
|
|
name.assign(effect->name.c_str());
|
|
if (ImGui::ColumnInputText("Name", (char*)name.c_str(), name.capacity(), 0, 0, 0)) {
|
|
effect->data.name_hash = eg->type != Glitter::FT
|
|
? hash_string_murmurhash(name) : hash_string_fnv1a64m(name);
|
|
effect->name.assign(name.c_str());
|
|
changed = true;
|
|
}
|
|
|
|
if (ImGui::ColumnDragInt("Appear Time",
|
|
&effect->data.appear_time, 1.0f, 0x0000, 0x7FFF, "%d", 0))
|
|
changed = true;
|
|
|
|
if (ImGui::ColumnDragInt("Life Time",
|
|
&effect->data.life_time, 1.0f, 0x0000, 0x7FFF - effect->data.appear_time, "%d", 0))
|
|
changed = true;
|
|
|
|
if (ImGui::ColumnDragInt("Start Time",
|
|
&effect->data.start_time, 1.0f, 0x0000, 0x7FFF - effect->data.appear_time, "%d", 0))
|
|
changed = true;
|
|
|
|
ImGui::Separator();
|
|
|
|
if (ImGui::ColumnDragVec3("Translation",
|
|
&effect->translation, 0.0001f, -FLT_MAX, FLT_MAX, "%g",
|
|
ImGuiSliderFlags_NoRoundToFormat,
|
|
flags & Glitter::CURVE_TYPE_TRANSLATION_XYZ))
|
|
changed = true;
|
|
|
|
vec3 rotation = effect->rotation * RAD_TO_DEG_FLOAT;
|
|
if (ImGui::ColumnDragVec3("Rotation",
|
|
&rotation, 0.0001f, -FLT_MAX, FLT_MAX, "%g",
|
|
ImGuiSliderFlags_NoRoundToFormat,
|
|
(flags & Glitter::CURVE_TYPE_ROTATION_XYZ) >> 3)) {
|
|
effect->rotation = rotation * DEG_TO_RAD_FLOAT;
|
|
changed = true;
|
|
}
|
|
|
|
if (ImGui::ColumnDragVec3("Scale",
|
|
&effect->scale, 0.0001f, -FLT_MAX, FLT_MAX, "%g",
|
|
ImGuiSliderFlags_NoRoundToFormat,
|
|
(flags & Glitter::CURVE_TYPE_SCALE_XYZ) >> 6))
|
|
changed = true;
|
|
|
|
ImGui::Separator();
|
|
|
|
if (ImGui::CheckboxFlagsEnterKeyPressed("Loop",
|
|
(uint32_t*)&effect->data.flags,
|
|
Glitter::EFFECT_LOOP))
|
|
changed = true;
|
|
|
|
if (ImGui::CheckboxFlagsEnterKeyPressed("Draw as Transparent",
|
|
(uint32_t*)&effect->data.flags,
|
|
Glitter::EFFECT_ALPHA))
|
|
changed = true;
|
|
|
|
if (ImGui::CheckboxFlagsEnterKeyPressed("Fog",
|
|
(uint32_t*)&effect->data.flags,
|
|
Glitter::EFFECT_FOG))
|
|
changed = true;
|
|
|
|
if (ImGui::CheckboxFlagsEnterKeyPressed("Fog Height",
|
|
(uint32_t*)&effect->data.flags,
|
|
Glitter::EFFECT_FOG_HEIGHT))
|
|
changed = true;
|
|
|
|
if (ImGui::CheckboxFlagsEnterKeyPressed("Use External Emission",
|
|
(uint32_t*)&effect->data.flags,
|
|
Glitter::EFFECT_EMISSION))
|
|
changed = true;
|
|
|
|
if (eg->type == Glitter::X)
|
|
if (ImGui::CheckboxFlagsEnterKeyPressed("Use Seed",
|
|
(uint32_t*)&effect->data.flags,
|
|
Glitter::EFFECT_USE_SEED))
|
|
changed = true;
|
|
|
|
if (effect->data.flags & Glitter::EFFECT_FOG && effect->data.flags & Glitter::EFFECT_FOG_HEIGHT) {
|
|
enum_and(effect->data.flags, ~Glitter::EFFECT_FOG_HEIGHT);
|
|
changed = true;
|
|
}
|
|
|
|
if (effect->data.flags & Glitter::EFFECT_FOG_HEIGHT && effect->data.flags & Glitter::EFFECT_FOG) {
|
|
enum_and(effect->data.flags, ~Glitter::EFFECT_FOG);
|
|
changed = true;
|
|
}
|
|
|
|
if (eg->type != Glitter::X) {
|
|
bool set_emission = effect->version == 7;
|
|
if (ImGui::CheckboxEnterKeyPressed("Set Emission",
|
|
&set_emission)) {
|
|
effect->version = set_emission ? 7 : 6;
|
|
changed = true;
|
|
}
|
|
|
|
if (effect->version == 7 && ImGui::ColumnDragFloat("Emission",
|
|
&effect->data.emission, 0.0001f, 0.0f, HALF_MAX, "%g",
|
|
ImGuiSliderFlags_NoRoundToFormat))
|
|
changed = true;
|
|
}
|
|
else {
|
|
if (effect->data.flags & Glitter::EFFECT_USE_SEED
|
|
&& ImGui::ColumnInputScalar("Seed", ImGuiDataType_U32, &effect->data.seed,
|
|
0, 0, "%08X", ImGuiInputTextFlags_CharsHexadecimal))
|
|
changed = true;
|
|
|
|
if (ImGui::ColumnDragFloat("Emission",
|
|
&effect->data.emission, 0.0001f, 0.0f, HALF_MAX, "%g",
|
|
ImGuiSliderFlags_NoRoundToFormat))
|
|
changed = true;
|
|
}
|
|
|
|
int32_t type;
|
|
if (effect->data.flags & Glitter::EFFECT_LOCAL)
|
|
type = 1;
|
|
else if (effect->data.ext_anim)
|
|
type = effect->data.ext_anim->flags & Glitter::EFFECT_EXT_ANIM_CHARA_ANIM ? 2 : 3;
|
|
else
|
|
type = 0;
|
|
|
|
if (ImGui::ColumnComboBox("Type", Glitter::effect_type_name,
|
|
4, &type, 0, false, &input_locked)) {
|
|
if (type == 1) {
|
|
enum_or(effect->data.flags, Glitter::EFFECT_LOCAL);
|
|
if (effect->data.ext_anim) {
|
|
delete effect->data.ext_anim;
|
|
effect->data.ext_anim = 0;
|
|
}
|
|
}
|
|
else {
|
|
enum_and(effect->data.flags, ~Glitter::EFFECT_LOCAL);
|
|
if (type == 2 || type == 3) {
|
|
if (!effect->data.ext_anim)
|
|
effect->data.ext_anim = force_malloc<Glitter::Effect::ExtAnim>();
|
|
if (type == 2)
|
|
enum_or(effect->data.ext_anim->flags, Glitter::EFFECT_EXT_ANIM_CHARA_ANIM);
|
|
else
|
|
enum_and(effect->data.ext_anim->flags, ~Glitter::EFFECT_EXT_ANIM_CHARA_ANIM);
|
|
}
|
|
else
|
|
if (effect->data.ext_anim) {
|
|
delete effect->data.ext_anim;
|
|
effect->data.ext_anim = 0;
|
|
}
|
|
}
|
|
changed = true;
|
|
}
|
|
|
|
if (!(effect->data.flags & Glitter::EFFECT_LOCAL) && effect->data.ext_anim) {
|
|
ImGui::Separator();
|
|
|
|
bool changed = false;
|
|
if (eg->type == Glitter::X) {
|
|
uint64_t hash_before = hash_fnv1a64m(effect->data.ext_anim_x,
|
|
sizeof(Glitter::Effect::ExtAnimX));
|
|
|
|
Glitter::Effect::ExtAnimX* ext_anim = effect->data.ext_anim_x;
|
|
if (ext_anim->flags & Glitter::EFFECT_EXT_ANIM_CHARA_ANIM) {
|
|
const int32_t max_chara = 4;
|
|
if (ImGui::ColumnComboBox("Chara Index", Glitter::effect_ext_anim_index_name,
|
|
max_chara, &ext_anim->chara_index, 0, false, &input_locked))
|
|
changed = true;
|
|
|
|
int32_t node_index = ext_anim->node_index;
|
|
if (node_index < Glitter::EFFECT_EXT_ANIM_CHARA_HEAD
|
|
|| node_index > Glitter::EFFECT_EXT_ANIM_CHARA_RIGHT_TOE)
|
|
node_index = Glitter::EFFECT_EXT_ANIM_CHARA_NONE;
|
|
node_index++;
|
|
|
|
if (ImGui::ColumnComboBox("Parent Bone", Glitter::effect_ext_anim_node_index_name,
|
|
Glitter::EFFECT_EXT_ANIM_CHARA_MAX,
|
|
&node_index, 0, true, &input_locked)) {
|
|
node_index--;
|
|
if (node_index < Glitter::EFFECT_EXT_ANIM_CHARA_HEAD
|
|
|| node_index > Glitter::EFFECT_EXT_ANIM_CHARA_RIGHT_TOE)
|
|
node_index = Glitter::EFFECT_EXT_ANIM_CHARA_NONE;
|
|
|
|
if (ext_anim->node_index != node_index) {
|
|
ext_anim->node_index = (Glitter::EffectExtAnimCharaNode)node_index;
|
|
changed = true;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
uint64_t object_hash = ext_anim->object_hash;
|
|
if (glitter_editor_hash_input(glt_edt, "Object Hash", &object_hash)) {
|
|
ext_anim->object_hash = (uint32_t)object_hash;
|
|
changed = true;
|
|
}
|
|
|
|
ImGui::ColumnInputScalar("Instance ID", ImGuiDataType_U32, &ext_anim->instance_id,
|
|
0, 0, "%d", ImGuiInputTextFlags_CharsDecimal);
|
|
|
|
uint64_t file_name_hash = ext_anim->file_name_hash;
|
|
if (glitter_editor_hash_input(glt_edt, "File Name Hash", &file_name_hash)) {
|
|
ext_anim->file_name_hash = (uint32_t)file_name_hash;
|
|
changed = true;
|
|
}
|
|
|
|
const size_t mesh_name_size = sizeof(ext_anim->mesh_name);
|
|
char mesh_name[sizeof(ext_anim->mesh_name)];
|
|
memcpy(mesh_name, ext_anim->mesh_name, mesh_name_size);
|
|
if (ImGui::ColumnInputText("Mesh Name", mesh_name, mesh_name_size, 0, 0, 0)) {
|
|
memcpy(ext_anim->mesh_name, mesh_name, mesh_name_size);
|
|
changed = true;
|
|
}
|
|
}
|
|
|
|
if (ImGui::CheckboxFlagsEnterKeyPressed("Trans Only",
|
|
(uint32_t*)&ext_anim->flags,
|
|
Glitter::EFFECT_EXT_ANIM_TRANS_ONLY))
|
|
changed = true;
|
|
|
|
if (ImGui::CheckboxFlagsEnterKeyPressed("No Trans X",
|
|
(uint32_t*)&ext_anim->flags,
|
|
Glitter::EFFECT_EXT_ANIM_NO_TRANS_X))
|
|
changed = true;
|
|
|
|
if (ImGui::CheckboxFlagsEnterKeyPressed("No Trans Y",
|
|
(uint32_t*)&ext_anim->flags,
|
|
Glitter::EFFECT_EXT_ANIM_NO_TRANS_Y))
|
|
changed = true;
|
|
|
|
if (ImGui::CheckboxFlagsEnterKeyPressed("No Trans Z",
|
|
(uint32_t*)&ext_anim->flags,
|
|
Glitter::EFFECT_EXT_ANIM_NO_TRANS_Z))
|
|
changed = true;
|
|
|
|
if (ImGui::CheckboxFlagsEnterKeyPressed("Draw Only when Chara Visible",
|
|
(uint32_t*)&ext_anim->flags,
|
|
Glitter::EFFECT_EXT_ANIM_NO_DRAW_IF_NO_DATA))
|
|
changed = true;
|
|
|
|
if (ImGui::CheckboxFlagsEnterKeyPressed("Get Then Update",
|
|
(uint32_t*)&ext_anim->flags,
|
|
Glitter::EFFECT_EXT_ANIM_GET_THEN_UPDATE))
|
|
changed = true;
|
|
|
|
uint64_t hash_after = hash_fnv1a64m(effect->data.ext_anim_x,
|
|
sizeof(Glitter::Effect::ExtAnimX));
|
|
if (hash_before != hash_after && changed)
|
|
glt_edt->input_reload = true;
|
|
}
|
|
else {
|
|
uint64_t hash_before = hash_fnv1a64m(effect->data.ext_anim,
|
|
sizeof(Glitter::Effect::ExtAnim));
|
|
|
|
Glitter::Effect::ExtAnim* ext_anim = effect->data.ext_anim;
|
|
if (ext_anim->flags & Glitter::EFFECT_EXT_ANIM_CHARA_ANIM) {
|
|
const int32_t max_chara = eg->type == Glitter::FT ? 6 : 3;
|
|
if (ImGui::ColumnComboBox("Chara Index", Glitter::effect_ext_anim_index_name,
|
|
max_chara, &ext_anim->chara_index, 0, false, &input_locked))
|
|
changed = true;
|
|
|
|
int32_t node_index = ext_anim->node_index;
|
|
if (node_index < Glitter::EFFECT_EXT_ANIM_CHARA_HEAD
|
|
|| node_index > Glitter::EFFECT_EXT_ANIM_CHARA_RIGHT_TOE)
|
|
node_index = Glitter::EFFECT_EXT_ANIM_CHARA_NONE;
|
|
node_index++;
|
|
|
|
if (ImGui::ColumnComboBox("Parent Bone", Glitter::effect_ext_anim_node_index_name,
|
|
Glitter::EFFECT_EXT_ANIM_CHARA_MAX,
|
|
&node_index, 0, true, &input_locked)) {
|
|
node_index--;
|
|
if (node_index < Glitter::EFFECT_EXT_ANIM_CHARA_HEAD
|
|
|| node_index > Glitter::EFFECT_EXT_ANIM_CHARA_RIGHT_TOE)
|
|
node_index = Glitter::EFFECT_EXT_ANIM_CHARA_NONE;
|
|
|
|
if (ext_anim->node_index != node_index) {
|
|
ext_anim->node_index = (Glitter::EffectExtAnimCharaNode)node_index;
|
|
changed = true;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
if (glitter_editor_hash_input(glt_edt, "Object Hash", &ext_anim->object_hash)) {
|
|
ext_anim->object = Glitter::Effect::ExtAnim::GetObjectInfo(ext_anim->object_hash,
|
|
&data_list[glt_edt->load_data_type].data_ft.obj_db);
|
|
changed = true;
|
|
}
|
|
|
|
const size_t mesh_name_size = sizeof(ext_anim->mesh_name);
|
|
char mesh_name[sizeof(ext_anim->mesh_name)];
|
|
memcpy(mesh_name, ext_anim->mesh_name, mesh_name_size);
|
|
if (ImGui::ColumnInputText("Mesh Name", mesh_name, mesh_name_size, 0, 0, 0)) {
|
|
memcpy(ext_anim->mesh_name, mesh_name, mesh_name_size);
|
|
changed = true;
|
|
}
|
|
}
|
|
|
|
if (ImGui::CheckboxFlagsEnterKeyPressed("Trans Only",
|
|
(uint32_t*)&ext_anim->flags,
|
|
Glitter::EFFECT_EXT_ANIM_TRANS_ONLY))
|
|
changed = true;
|
|
|
|
uint64_t hash_after = hash_fnv1a64m(effect->data.ext_anim, sizeof(Glitter::Effect::ExtAnim));
|
|
if (hash_before != hash_after && changed)
|
|
glt_edt->input_reload = true;
|
|
}
|
|
}
|
|
|
|
uint64_t hash_after = hash_fnv1a64m(glt_edt->selected_effect, sizeof(Glitter::Effect));
|
|
if (hash_before != hash_after && changed) {
|
|
for (Glitter::Emitter*& i : effect->emitters) {
|
|
if (!i)
|
|
continue;
|
|
|
|
Glitter::Emitter* emitter = i;
|
|
for (Glitter::Particle*& j : emitter->particles) {
|
|
if (!j)
|
|
continue;
|
|
|
|
Glitter::Particle* particle = j;
|
|
Glitter::ParticleFlag flags = particle->data.flags;
|
|
if (effect->data.flags & Glitter::EFFECT_LOCAL)
|
|
enum_or(flags, Glitter::PARTICLE_LOCAL);
|
|
else
|
|
enum_and(flags, ~Glitter::PARTICLE_LOCAL);
|
|
|
|
if (effect->data.flags & Glitter::EFFECT_EMISSION
|
|
|| particle->data.emission >= Glitter::min_emission)
|
|
enum_or(flags, Glitter::PARTICLE_EMISSION);
|
|
else
|
|
enum_and(flags, ~Glitter::PARTICLE_EMISSION);
|
|
particle->data.flags = flags;
|
|
}
|
|
}
|
|
glt_edt->input_reload = true;
|
|
}
|
|
|
|
ImGui::SetDefaultColumnSpace();
|
|
}
|
|
|
|
static void glitter_editor_property_emitter(GlitterEditor* glt_edt) {
|
|
Glitter::Effect* sel_efct = glt_edt->selected_effect;
|
|
Glitter::Emitter* sel_emit = glt_edt->selected_emitter;
|
|
|
|
ImGui::SetColumnSpace(2.0f / 5.0f);
|
|
|
|
uint64_t hash_before = hash_fnv1a64m(glt_edt->selected_emitter, sizeof(Glitter::Emitter));
|
|
|
|
Glitter::EffectGroup* eg = glt_edt->effect_group;
|
|
Glitter::Emitter* emitter = glt_edt->selected_emitter;
|
|
bool changed = false;
|
|
|
|
Glitter::CurveTypeFlags flags = Glitter::emitter_curve_flags;
|
|
for (int32_t i = Glitter::CURVE_TRANSLATION_X; i <= Glitter::CURVE_V_SCROLL_ALPHA_2ND; i++)
|
|
for (Glitter::Curve*& j : emitter->animation.curves)
|
|
if (j && j->type == i)
|
|
enum_and(flags, ~(1 << i));
|
|
|
|
ImGui::Text("Parent Effect:\nAppear Time: %d; Life Time: %d; Start Time: %d",
|
|
sel_efct->data.appear_time,
|
|
sel_efct->data.life_time,
|
|
sel_efct->data.start_time);
|
|
|
|
ImGui::Separator();
|
|
|
|
if (ImGui::ColumnDragInt("Start Time",
|
|
&emitter->data.start_time, 1.0f, 0x0000, 0x7FFF, "%d", 0))
|
|
changed = true;
|
|
|
|
if (ImGui::ColumnDragInt("Life Time",
|
|
&emitter->data.life_time, 1.0f, 0x0000, 0x7FFF, "%d", 0))
|
|
changed = true;
|
|
|
|
if (ImGui::ColumnDragInt("Loop Start Time", &emitter->data.loop_start_time,
|
|
1.0f, -0x0001, emitter->data.start_time + emitter->data.life_time, "%d", 0)) {
|
|
if (emitter->data.loop_start_time < emitter->data.start_time)
|
|
emitter->data.loop_start_time = 0;
|
|
changed = emitter->data.loop_start_time != sel_emit->data.loop_start_time;
|
|
}
|
|
|
|
if (ImGui::ColumnDragInt("Loop End Time", &emitter->data.loop_end_time,
|
|
1.0f, -0x0001, emitter->data.start_time + emitter->data.life_time, "%d", 0)) {
|
|
if (emitter->data.loop_end_time < 0)
|
|
emitter->data.loop_end_time = -1;
|
|
changed = emitter->data.loop_end_time != sel_emit->data.loop_end_time;
|
|
}
|
|
|
|
ImGui::Separator();
|
|
|
|
if (ImGui::ColumnDragVec3("Translation",
|
|
&emitter->translation, 0.0001f, -FLT_MAX, FLT_MAX, "%g",
|
|
ImGuiSliderFlags_NoRoundToFormat,
|
|
flags & Glitter::CURVE_TYPE_TRANSLATION_XYZ))
|
|
changed = true;
|
|
|
|
if (eg->type != Glitter::X) {
|
|
bool draw_z_axis = emitter->data.direction == Glitter::DIRECTION_Z_AXIS;
|
|
|
|
vec3 rotation = emitter->rotation;
|
|
if (draw_z_axis)
|
|
rotation.z -= (float_t)M_PI_2;
|
|
rotation *= RAD_TO_DEG_FLOAT;
|
|
if (ImGui::ColumnDragVec3("Rotation",
|
|
&rotation, 0.0001f, -FLT_MAX, FLT_MAX, "%g",
|
|
ImGuiSliderFlags_NoRoundToFormat,
|
|
(flags & Glitter::CURVE_TYPE_ROTATION_XYZ) >> 3)) {
|
|
rotation *= DEG_TO_RAD_FLOAT;
|
|
if (draw_z_axis)
|
|
rotation.z += (float_t)M_PI_2;
|
|
emitter->rotation = rotation;
|
|
changed = true;
|
|
}
|
|
}
|
|
else {
|
|
vec3 rotation = emitter->rotation * RAD_TO_DEG_FLOAT;
|
|
if (ImGui::ColumnDragVec3("Rotation",
|
|
&rotation, 0.0001f, -FLT_MAX, FLT_MAX, "%g",
|
|
ImGuiSliderFlags_NoRoundToFormat,
|
|
(flags & Glitter::CURVE_TYPE_ROTATION_XYZ) >> 3)) {
|
|
emitter->rotation = rotation * DEG_TO_RAD_FLOAT;
|
|
changed = true;
|
|
}
|
|
}
|
|
|
|
vec3 rotation_add = emitter->data.rotation_add * RAD_TO_DEG_FLOAT;
|
|
if (ImGui::ColumnDragVec3("Rotation Add",
|
|
&rotation_add, 0.0001f, -FLT_MAX, FLT_MAX, "%g",
|
|
ImGuiSliderFlags_NoRoundToFormat,
|
|
(flags & Glitter::CURVE_TYPE_ROTATION_XYZ) >> 3)) {
|
|
emitter->data.rotation_add = rotation_add * DEG_TO_RAD_FLOAT;
|
|
changed = true;
|
|
}
|
|
|
|
if (ImGui::ColumnDragVec3("Scale",
|
|
&emitter->scale, 0.0001f, -FLT_MAX, FLT_MAX, "%g",
|
|
ImGuiSliderFlags_NoRoundToFormat,
|
|
(flags & Glitter::CURVE_TYPE_SCALE_XYZ) >> 6))
|
|
changed = true;
|
|
|
|
ImGui::Separator();
|
|
|
|
if (ImGui::CheckboxFlagsEnterKeyPressed("Loop",
|
|
(uint32_t*)&emitter->data.flags,
|
|
Glitter::EMITTER_LOOP))
|
|
changed = true;
|
|
|
|
if (ImGui::CheckboxFlagsEnterKeyPressed("Kill On End",
|
|
(uint32_t*)&emitter->data.flags,
|
|
Glitter::EMITTER_KILL_ON_END))
|
|
changed = true;
|
|
|
|
if (eg->type == Glitter::X
|
|
&& ImGui::CheckboxFlagsEnterKeyPressed("Use Seed",
|
|
(uint32_t*)&emitter->data.flags,
|
|
Glitter::EMITTER_USE_SEED))
|
|
changed = true;
|
|
|
|
ImGui::Separator();
|
|
|
|
if (eg->type == Glitter::X) {
|
|
if (emitter->data.flags & Glitter::EMITTER_USE_SEED
|
|
&& ImGui::ColumnInputScalar("Seed", ImGuiDataType_U32, &emitter->data.seed,
|
|
0, 0, "%08X", ImGuiInputTextFlags_CharsHexadecimal))
|
|
changed = true;
|
|
|
|
if (ImGui::ColumnComboBox("Timer Type", Glitter::emitter_timer_name,
|
|
Glitter::EMITTER_TIMER_BY_DISTANCE,
|
|
(int32_t*)&emitter->data.timer, 0, true, &input_locked)) {
|
|
float_t emission_interval = emitter->data.emission_interval;
|
|
if (emitter->data.timer == Glitter::EMITTER_TIMER_BY_TIME)
|
|
emission_interval = clamp_def(floorf(emission_interval), 1.0f, FLT_MAX);
|
|
else
|
|
emission_interval = clamp_def(emission_interval, 0.0f, FLT_MAX);
|
|
emitter->data.emission_interval = emission_interval;
|
|
changed = true;
|
|
}
|
|
}
|
|
|
|
if (eg->type == Glitter::X
|
|
&& emitter->data.timer == Glitter::EMITTER_TIMER_BY_DISTANCE) {
|
|
if (ImGui::ColumnDragFloat("Emit Interval",
|
|
&emitter->data.emission_interval, 0.0001f, -1.0f, FLT_MAX, "%g",
|
|
ImGuiSliderFlags_NoRoundToFormat,
|
|
(flags & Glitter::CURVE_TYPE_EMISSION_INTERVAL) >> 20))
|
|
changed = true;
|
|
}
|
|
else {
|
|
Glitter::EmitterEmission emission;
|
|
if (emitter->data.emission_interval >= -0.000001f)
|
|
emission = emitter->data.emission_interval <= 0.000001f
|
|
? Glitter::EMITTER_EMISSION_ON_START : Glitter::EMITTER_EMISSION_ON_TIMER;
|
|
else
|
|
emission = Glitter::EMITTER_EMISSION_ON_END;
|
|
|
|
if (ImGui::ColumnComboBox("Emission Type", Glitter::emitter_emission_name,
|
|
Glitter::EMITTER_EMISSION_ON_END,
|
|
(int32_t*)&emission, 0, true, &input_locked)) {
|
|
float_t emission_interval;
|
|
switch (emission) {
|
|
case Glitter::EMITTER_EMISSION_ON_TIMER:
|
|
default:
|
|
emission_interval = 1.0f;
|
|
break;
|
|
case Glitter::EMITTER_EMISSION_ON_START:
|
|
emission_interval = 0.0f;
|
|
break;
|
|
case Glitter::EMITTER_EMISSION_ON_END:
|
|
emission_interval = -1.0f;
|
|
break;
|
|
}
|
|
|
|
if (emission_interval != emitter->data.emission_interval) {
|
|
emitter->data.emission_interval = emission_interval;
|
|
changed = true;
|
|
}
|
|
}
|
|
|
|
if (emission == Glitter::EMITTER_EMISSION_ON_TIMER
|
|
&& ImGui::ColumnDragFloat("Emit Interval",
|
|
&emitter->data.emission_interval, 1.0f, 1.0f, FLT_MAX, "%g",
|
|
ImGuiSliderFlags_NoRoundToFormat,
|
|
(flags & Glitter::CURVE_TYPE_EMISSION_INTERVAL) >> 20))
|
|
changed = true;
|
|
}
|
|
|
|
if (ImGui::ColumnDragFloat("PTC Per Emit",
|
|
&emitter->data.particles_per_emission, 1.0f, 0.0f, FLT_MAX, "%g",
|
|
ImGuiSliderFlags_NoRoundToFormat,
|
|
(flags & Glitter::CURVE_TYPE_PARTICLES_PER_EMISSION) >> 21))
|
|
changed = true;
|
|
|
|
Glitter::EmitterDirection direction = Glitter::emitter_direction_default;
|
|
Glitter::EmitterDirection prev_direction;
|
|
for (int32_t i = 0; i < Glitter::emitter_direction_types_count; i++)
|
|
if (Glitter::emitter_direction_types[i] == emitter->data.direction) {
|
|
direction = (Glitter::EmitterDirection)i;
|
|
break;
|
|
}
|
|
prev_direction = direction;
|
|
|
|
if (ImGui::ColumnComboBox("Direction", Glitter::emitter_direction_name,
|
|
Glitter::EMITTER_DIRECTION_EFFECT_ROTATION,
|
|
(int32_t*)&direction, 0, true, &input_locked))
|
|
if (Glitter::emitter_direction_types[direction] != emitter->data.direction) {
|
|
changed = true;
|
|
if (eg->type != Glitter::X) {
|
|
bool draw_z_axis =
|
|
direction == Glitter::EMITTER_DIRECTION_Z_AXIS;
|
|
bool prev_draw_z_axis =
|
|
prev_direction == Glitter::EMITTER_DIRECTION_Z_AXIS;
|
|
if (draw_z_axis && !prev_draw_z_axis) {
|
|
if (!(flags & Glitter::CURVE_TYPE_ROTATION_Z))
|
|
emitter->animation.AddValue(eg->type,
|
|
(float_t)M_PI_2, Glitter::CURVE_TYPE_ROTATION_Z);
|
|
emitter->rotation.z += (float_t)M_PI_2;
|
|
}
|
|
else if (!draw_z_axis && prev_draw_z_axis) {
|
|
if (!(flags & Glitter::CURVE_TYPE_ROTATION_Z))
|
|
emitter->animation.AddValue(eg->type,
|
|
(float_t)-M_PI_2, Glitter::CURVE_TYPE_ROTATION_Z);
|
|
emitter->rotation.z -= (float_t)M_PI_2;
|
|
}
|
|
}
|
|
emitter->data.direction = Glitter::emitter_direction_types[direction];
|
|
changed = true;
|
|
}
|
|
|
|
if (ImGui::ColumnComboBox("Type", Glitter::emitter_name,
|
|
Glitter::EMITTER_POLYGON,
|
|
(int32_t*)&emitter->data.type, 0, true, &input_locked))
|
|
changed = true;
|
|
|
|
ImGui::Separator();
|
|
|
|
switch (emitter->data.type) {
|
|
case Glitter::EMITTER_BOX: {
|
|
ImGui::PushID("Box");
|
|
if (ImGui::ColumnDragVec3("Size",
|
|
&emitter->data.box.size, 0.0001f, 0.0f, FLT_MAX, "%g",
|
|
ImGuiSliderFlags_NoRoundToFormat))
|
|
changed = true;
|
|
ImGui::PopID();
|
|
} break;
|
|
case Glitter::EMITTER_CYLINDER: {
|
|
float_t start_angle, end_angle;
|
|
|
|
ImGui::PushID("Cylinder");
|
|
if (ImGui::ColumnDragFloat("Radius",
|
|
&emitter->data.cylinder.radius, 0.0001f, 0.0f, FLT_MAX, "%g",
|
|
ImGuiSliderFlags_NoRoundToFormat))
|
|
changed = true;
|
|
|
|
if (ImGui::ColumnDragFloat("Height",
|
|
&emitter->data.cylinder.height, 0.0001f, 0.0f, FLT_MAX, "%g",
|
|
ImGuiSliderFlags_NoRoundToFormat))
|
|
changed = true;
|
|
|
|
start_angle = emitter->data.cylinder.start_angle * RAD_TO_DEG_FLOAT;
|
|
if (ImGui::ColumnDragFloat("Start Angle",
|
|
&start_angle, 0.0001f, -FLT_MAX, FLT_MAX, "%g",
|
|
ImGuiSliderFlags_NoRoundToFormat)) {
|
|
emitter->data.cylinder.start_angle = start_angle * DEG_TO_RAD_FLOAT;
|
|
changed = true;
|
|
}
|
|
|
|
end_angle = emitter->data.cylinder.end_angle * RAD_TO_DEG_FLOAT;
|
|
if (ImGui::ColumnDragFloat("End Angle",
|
|
&end_angle, 0.0001f, -FLT_MAX, FLT_MAX, "%g",
|
|
ImGuiSliderFlags_NoRoundToFormat)) {
|
|
emitter->data.cylinder.end_angle = end_angle * DEG_TO_RAD_FLOAT;
|
|
changed = true;
|
|
}
|
|
|
|
if (ImGui::CheckboxEnterKeyPressed("On Edge",
|
|
&emitter->data.cylinder.on_edge))
|
|
changed = true;
|
|
|
|
if (ImGui::ColumnComboBox("Direction",
|
|
Glitter::emitter_emission_direction_name,
|
|
Glitter::EMITTER_EMISSION_DIRECTION_INWARD,
|
|
(int32_t*)&emitter->data.cylinder.direction, 0, true, &input_locked))
|
|
changed = true;
|
|
ImGui::PopID();
|
|
} break;
|
|
case Glitter::EMITTER_SPHERE: {
|
|
float_t latitude, longitude;
|
|
|
|
ImGui::PushID("Sphere");
|
|
if (ImGui::ColumnDragFloat("Radius",
|
|
&emitter->data.sphere.radius, 0.0001f, 0.0f, FLT_MAX, "%g",
|
|
ImGuiSliderFlags_NoRoundToFormat))
|
|
changed = true;
|
|
|
|
latitude = emitter->data.sphere.latitude * RAD_TO_DEG_FLOAT;
|
|
if (ImGui::ColumnDragFloat("Latitude",
|
|
&latitude, 0.0001f, -FLT_MAX, FLT_MAX, "%g",
|
|
ImGuiSliderFlags_NoRoundToFormat)) {
|
|
emitter->data.sphere.latitude = latitude * DEG_TO_RAD_FLOAT;
|
|
changed = true;
|
|
}
|
|
|
|
longitude = emitter->data.sphere.longitude * RAD_TO_DEG_FLOAT;
|
|
if (ImGui::ColumnDragFloat("Longitude",
|
|
&longitude, 0.0001f, -FLT_MAX, FLT_MAX, "%g",
|
|
ImGuiSliderFlags_NoRoundToFormat)) {
|
|
emitter->data.sphere.longitude = longitude * DEG_TO_RAD_FLOAT;
|
|
changed = true;
|
|
}
|
|
|
|
if (ImGui::CheckboxEnterKeyPressed("On Edge",
|
|
&emitter->data.sphere.on_edge))
|
|
changed = true;
|
|
|
|
if (ImGui::ColumnComboBox("Direction",
|
|
Glitter::emitter_emission_direction_name,
|
|
Glitter::EMITTER_EMISSION_DIRECTION_INWARD,
|
|
(int32_t*)&emitter->data.sphere.direction, 0, true, &input_locked))
|
|
changed = true;
|
|
ImGui::PopID();
|
|
} break;
|
|
case Glitter::EMITTER_POLYGON: {
|
|
ImGui::PushID("Polygon");
|
|
if (ImGui::ColumnDragFloat("Scale",
|
|
&emitter->data.polygon.size, 0.0001f, 0.0f, FLT_MAX,
|
|
"%g", ImGuiSliderFlags_NoRoundToFormat))
|
|
changed = true;
|
|
|
|
if (ImGui::ColumnDragInt("Count",
|
|
&emitter->data.polygon.count, 1.0f, 0, 0x7FFFFF, "%d", 0))
|
|
changed = true;
|
|
|
|
if (eg->type == Glitter::X)
|
|
if (ImGui::ColumnComboBox("Direction",
|
|
Glitter::emitter_emission_direction_name,
|
|
Glitter::EMITTER_EMISSION_DIRECTION_INWARD,
|
|
(int32_t*)&emitter->data.cylinder.direction, 0, true, &input_locked))
|
|
changed = true;
|
|
ImGui::PopID();
|
|
} break;
|
|
}
|
|
|
|
uint64_t hash_after = hash_fnv1a64m(glt_edt->selected_emitter, sizeof(Glitter::Emitter));
|
|
if (hash_before != hash_after && changed)
|
|
glt_edt->input_reload = true;
|
|
|
|
ImGui::SetDefaultColumnSpace();
|
|
}
|
|
|
|
static void glitter_editor_property_particle(GlitterEditor* glt_edt) {
|
|
Glitter::Effect* sel_efct = glt_edt->selected_effect;
|
|
Glitter::Emitter* sel_emit = glt_edt->selected_emitter;
|
|
|
|
ImGui::SetColumnSpace(2.0f / 5.0f);
|
|
|
|
uint64_t hash_before = hash_fnv1a64m(glt_edt->selected_particle, sizeof(Glitter::Particle));
|
|
|
|
Glitter::EffectGroup* eg = glt_edt->effect_group;
|
|
Glitter::Particle* particle = glt_edt->selected_particle;
|
|
bool changed = false;
|
|
|
|
Glitter::CurveTypeFlags flags = (Glitter::CurveTypeFlags)0;
|
|
if (eg->type == Glitter::X)
|
|
flags = Glitter::particle_x_curve_flags;
|
|
else
|
|
flags = Glitter::particle_curve_flags;
|
|
|
|
if (particle->data.type != Glitter::PARTICLE_MESH) {
|
|
enum_and(flags, ~Glitter::CURVE_TYPE_UV_SCROLL_2ND);
|
|
if (particle->data.draw_type != Glitter::DIRECTION_PARTICLE_ROTATION)
|
|
enum_and(flags, ~(Glitter::CURVE_TYPE_ROTATION_X | Glitter::CURVE_TYPE_ROTATION_Y));
|
|
}
|
|
|
|
if (particle->data.sub_flags & Glitter::PARTICLE_SUB_USE_CURVE)
|
|
for (int32_t i = Glitter::CURVE_TRANSLATION_X; i <= Glitter::CURVE_V_SCROLL_ALPHA_2ND; i++)
|
|
for (Glitter::Curve*& j : particle->animation.curves)
|
|
if (j && j->type == i)
|
|
enum_and(flags, ~(1 << i));
|
|
|
|
ImGui::Text("Parent Effect:\nAppear Time: %d; Life Time: %d; Start Time: %d",
|
|
sel_efct->data.appear_time,
|
|
sel_efct->data.life_time,
|
|
sel_efct->data.start_time);
|
|
|
|
ImGui::Text("Parent Emitter:\nStart Time: %d; Life Time: %d\nLoop Start Time: %d; Loop End Time: %d",
|
|
sel_emit->data.start_time,
|
|
sel_emit->data.life_time,
|
|
sel_emit->data.loop_start_time,
|
|
sel_emit->data.loop_end_time);
|
|
|
|
ImGui::Separator();
|
|
|
|
bool flags_changed = false;
|
|
if (ImGui::CheckboxFlagsEnterKeyPressed("Loop",
|
|
(uint32_t*)&particle->data.flags,
|
|
Glitter::PARTICLE_LOOP))
|
|
flags_changed = true;
|
|
|
|
if (ImGui::CheckboxFlagsEnterKeyPressed("Emitter Local",
|
|
(uint32_t*)&particle->data.flags,
|
|
Glitter::PARTICLE_EMITTER_LOCAL))
|
|
flags_changed = true;
|
|
|
|
if (ImGui::CheckboxFlagsEnterKeyPressed("Scale Y by X",
|
|
(uint32_t*)&particle->data.flags,
|
|
Glitter::PARTICLE_SCALE_Y_BY_X))
|
|
flags_changed = true;
|
|
|
|
if (ImGui::CheckboxFlagsEnterKeyPressed("Rebound Plane",
|
|
(uint32_t*)&particle->data.flags,
|
|
Glitter::PARTICLE_REBOUND_PLANE))
|
|
flags_changed = true;
|
|
|
|
if (ImGui::CheckboxFlagsEnterKeyPressed("Rotate by Emitter",
|
|
(uint32_t*)&particle->data.flags,
|
|
Glitter::PARTICLE_ROTATE_BY_EMITTER))
|
|
flags_changed = true;
|
|
|
|
if (ImGui::CheckboxFlagsEnterKeyPressed("Scale by Emitter",
|
|
(uint32_t*)&particle->data.flags,
|
|
Glitter::PARTICLE_SCALE))
|
|
flags_changed = true;
|
|
|
|
if (ImGui::CheckboxFlagsEnterKeyPressed("Texture Mask##Flag",
|
|
(uint32_t*)&particle->data.flags,
|
|
Glitter::PARTICLE_TEXTURE_MASK))
|
|
flags_changed = true;
|
|
|
|
if (eg->type == Glitter::X) {
|
|
if (ImGui::CheckboxFlagsEnterKeyPressed("Disable Depth Test",
|
|
(uint32_t*)&particle->data.flags,
|
|
Glitter::PARTICLE_DEPTH_TEST))
|
|
flags_changed = true;
|
|
|
|
if (particle->data.type == Glitter::PARTICLE_LOCUS
|
|
&& ImGui::CheckboxFlagsEnterKeyPressed("Rotate Locus",
|
|
(uint32_t*)&particle->data.flags,
|
|
Glitter::PARTICLE_ROTATE_LOCUS))
|
|
flags_changed = true;
|
|
}
|
|
|
|
if (flags_changed)
|
|
changed = true;
|
|
|
|
ImGui::Separator();
|
|
|
|
if (eg->type == Glitter::X) {
|
|
vec2i life_time;
|
|
life_time.x = particle->data.life_time;
|
|
life_time.y = particle->data.life_time_random;
|
|
if (ImGui::ColumnDragVec2I("Life Time [R]",
|
|
&life_time, 1.0f, 0x0000, 0x7FFF, "%d", 0)) {
|
|
particle->data.life_time = life_time.x;
|
|
particle->data.life_time_random = life_time.y;
|
|
changed = true;
|
|
}
|
|
|
|
vec2i fade_in;
|
|
fade_in.x = particle->data.fade_in;
|
|
fade_in.y = particle->data.fade_in_random;
|
|
if (ImGui::ColumnDragVec2I("Fade In [R]",
|
|
&fade_in, 1.0f, 0x0000, 0x7FFF, "%d", 0)) {
|
|
particle->data.fade_in = fade_in.x;
|
|
particle->data.fade_in_random = fade_in.y;
|
|
changed = true;
|
|
}
|
|
|
|
vec2i fade_out;
|
|
fade_out.x = particle->data.fade_out;
|
|
fade_out.y = particle->data.fade_out_random;
|
|
if (ImGui::ColumnDragVec2I("Fade Out [R]",
|
|
&fade_out, 1.0f, 0x0000, 0x7FFF, "%d", 0)) {
|
|
particle->data.fade_out = fade_out.x;
|
|
particle->data.fade_out_random = fade_out.y;
|
|
changed = true;
|
|
}
|
|
|
|
if (ImGui::ColumnComboBox("Type", Glitter::particle_name,
|
|
Glitter::PARTICLE_MESH,
|
|
(int32_t*)&particle->data.type, 0, true, &input_locked))
|
|
changed = true;
|
|
}
|
|
else {
|
|
if (ImGui::ColumnDragInt("Life Time",
|
|
&particle->data.life_time, 1.0f, 0x0000, 0x7FFF, "%d", 0))
|
|
changed = true;
|
|
|
|
if (ImGui::ColumnComboBox("Type", Glitter::particle_name,
|
|
Glitter::PARTICLE_LOCUS,
|
|
(int32_t*)&particle->data.type, 0, true, &input_locked))
|
|
changed = true;
|
|
}
|
|
|
|
if (particle->data.type != Glitter::PARTICLE_MESH
|
|
&& ImGui::ColumnComboBox("Pivot", Glitter::pivot_name,
|
|
Glitter::PIVOT_BOTTOM_RIGHT,
|
|
(int32_t*)&particle->data.pivot, 0, true, &input_locked))
|
|
changed = true;
|
|
|
|
if (particle->data.type == Glitter::PARTICLE_QUAD || particle->data.type == Glitter::PARTICLE_MESH) {
|
|
Glitter::ParticleDrawType draw_type = Glitter::particle_draw_type_default;
|
|
Glitter::ParticleDrawType prev_draw_type;
|
|
for (int32_t i = 0; i < Glitter::particle_draw_types_count; i++)
|
|
if (Glitter::particle_draw_types[i] == particle->data.draw_type) {
|
|
draw_type = (Glitter::ParticleDrawType)i;
|
|
break;
|
|
}
|
|
prev_draw_type = draw_type;
|
|
|
|
if (ImGui::ColumnComboBox("Draw Type", Glitter::particle_draw_type_name,
|
|
Glitter::PARTICLE_DRAW_TYPE_EMIT_POSITION,
|
|
(int32_t*)&draw_type, 0, true, &input_locked))
|
|
if (Glitter::particle_draw_types[draw_type] != particle->data.draw_type) {
|
|
if (eg->type != Glitter::X) {
|
|
bool draw_prev_pos =
|
|
draw_type == Glitter::PARTICLE_DRAW_TYPE_PREV_POSITION
|
|
|| draw_type == Glitter::PARTICLE_DRAW_TYPE_PREV_POSITION_DUP;
|
|
bool prev_draw_prev_pos =
|
|
prev_draw_type == Glitter::PARTICLE_DRAW_TYPE_PREV_POSITION
|
|
|| prev_draw_type == Glitter::PARTICLE_DRAW_TYPE_PREV_POSITION_DUP;
|
|
bool draw_z_axis =
|
|
draw_type == Glitter::PARTICLE_DRAW_TYPE_Z_AXIS;
|
|
bool prev_draw_z_axis =
|
|
prev_draw_type == Glitter::PARTICLE_DRAW_TYPE_Z_AXIS;
|
|
if (draw_prev_pos && !prev_draw_prev_pos)
|
|
particle->data.rotation.z += (float_t)M_PI;
|
|
else if (!draw_prev_pos && prev_draw_prev_pos)
|
|
particle->data.rotation.z -= (float_t)M_PI;
|
|
else if (draw_z_axis && !prev_draw_z_axis) {
|
|
if (!(flags & Glitter::CURVE_TYPE_ROTATION_Z))
|
|
particle->animation.AddValue(eg->type,
|
|
(float_t)M_PI_2, Glitter::CURVE_TYPE_ROTATION_Z);
|
|
particle->data.rotation.z += (float_t)M_PI_2;
|
|
}
|
|
else if (!draw_z_axis && prev_draw_z_axis) {
|
|
if (!(flags & Glitter::CURVE_TYPE_ROTATION_Z))
|
|
particle->animation.AddValue(eg->type,
|
|
(float_t)-M_PI_2, Glitter::CURVE_TYPE_ROTATION_Z);
|
|
particle->data.rotation.z -= (float_t)M_PI_2;
|
|
}
|
|
}
|
|
particle->data.draw_type = Glitter::particle_draw_types[draw_type];
|
|
changed = true;
|
|
}
|
|
}
|
|
|
|
if (particle->data.type == Glitter::PARTICLE_QUAD)
|
|
if (ImGui::ColumnDragFloat("Z Offset",
|
|
&particle->data.z_offset, 0.0001f, -FLT_MAX, FLT_MAX,
|
|
"%g", ImGuiSliderFlags_NoRoundToFormat))
|
|
changed = true;
|
|
|
|
ImGui::Separator();
|
|
|
|
if (eg->type != Glitter::X) {
|
|
bool draw_prev_pos =
|
|
particle->data.draw_type == Glitter::DIRECTION_PREV_POSITION
|
|
|| particle->data.draw_type == Glitter::DIRECTION_PREV_POSITION_DUP;
|
|
bool draw_z_axis =
|
|
particle->data.draw_type == Glitter::DIRECTION_Z_AXIS;
|
|
|
|
vec3 rotation = particle->data.rotation;
|
|
if (draw_prev_pos)
|
|
rotation.z -= (float_t)M_PI;
|
|
else if (draw_z_axis)
|
|
rotation.z -= (float_t)M_PI_2;
|
|
rotation *= RAD_TO_DEG_FLOAT;
|
|
if (ImGui::ColumnDragVec3("Rotation",
|
|
&rotation, 0.0001f, -FLT_MAX, FLT_MAX, "%g",
|
|
ImGuiSliderFlags_NoRoundToFormat,
|
|
(flags & Glitter::CURVE_TYPE_ROTATION_XYZ) >> 3)) {
|
|
rotation *= DEG_TO_RAD_FLOAT;
|
|
if (draw_prev_pos)
|
|
rotation.z += (float_t)M_PI;
|
|
else if (draw_z_axis)
|
|
rotation.z += (float_t)M_PI_2;
|
|
particle->data.rotation = rotation;
|
|
changed = true;
|
|
}
|
|
}
|
|
else {
|
|
vec3 rotation = particle->data.rotation * RAD_TO_DEG_FLOAT;
|
|
if (ImGui::ColumnDragVec3("Rotation",
|
|
&rotation, 0.0001f, -FLT_MAX, FLT_MAX, "%g",
|
|
ImGuiSliderFlags_NoRoundToFormat,
|
|
(flags & Glitter::CURVE_TYPE_ROTATION_XYZ) >> 3)) {
|
|
particle->data.rotation = rotation * DEG_TO_RAD_FLOAT;
|
|
changed = true;
|
|
}
|
|
}
|
|
|
|
vec3 rotation_random = particle->data.rotation_random * RAD_TO_DEG_FLOAT;
|
|
if (ImGui::ColumnDragVec3("Rotation Random",
|
|
&rotation_random, 0.0001f, -FLT_MAX, FLT_MAX, "%g",
|
|
ImGuiSliderFlags_NoRoundToFormat,
|
|
(flags & Glitter::CURVE_TYPE_ROTATION_XYZ) >> 3)) {
|
|
particle->data.rotation_random = rotation_random * DEG_TO_RAD_FLOAT;
|
|
changed = true;
|
|
}
|
|
|
|
vec3 rotation_add = particle->data.rotation_add * RAD_TO_DEG_FLOAT;
|
|
if (ImGui::ColumnDragVec3("Rotation Add",
|
|
&rotation_add, 0.0001f, -FLT_MAX, FLT_MAX, "%g",
|
|
ImGuiSliderFlags_NoRoundToFormat,
|
|
(flags & Glitter::CURVE_TYPE_ROTATION_XYZ) >> 3)) {
|
|
particle->data.rotation_add = rotation_add * DEG_TO_RAD_FLOAT;
|
|
changed = true;
|
|
}
|
|
|
|
vec3 rotation_add_random = particle->data.rotation_add_random * RAD_TO_DEG_FLOAT;
|
|
if (ImGui::ColumnDragVec3("Rotation Add Random",
|
|
&rotation_add_random, 0.0001f, -FLT_MAX, FLT_MAX, "%g",
|
|
ImGuiSliderFlags_NoRoundToFormat,
|
|
(flags & Glitter::CURVE_TYPE_ROTATION_XYZ) >> 3)) {
|
|
particle->data.rotation_add_random = rotation_add_random * DEG_TO_RAD_FLOAT;
|
|
changed = true;
|
|
}
|
|
|
|
ImGui::DisableElementPush(particle->data.type != Glitter::PARTICLE_MESH);
|
|
if (ImGui::ColumnDragVec2("Scale",
|
|
(vec2*)&particle->data.scale, 0.0001f, -FLT_MAX, FLT_MAX, "%g",
|
|
ImGuiSliderFlags_NoRoundToFormat,
|
|
particle->data.flags & Glitter::PARTICLE_SCALE_Y_BY_X ? 0x01 : 0x03))
|
|
changed = true;
|
|
|
|
if (ImGui::ColumnDragVec2("Scale Random",
|
|
(vec2*)&particle->data.scale_random, 0.0001f, -FLT_MAX, FLT_MAX, "%g",
|
|
ImGuiSliderFlags_NoRoundToFormat,
|
|
particle->data.flags & Glitter::PARTICLE_SCALE_Y_BY_X ? 0x01 : 0x03))
|
|
changed = true;
|
|
ImGui::DisableElementPop(particle->data.type != Glitter::PARTICLE_MESH);
|
|
|
|
ImGui::Separator();
|
|
|
|
if (ImGui::ColumnDragVec3("Direction",
|
|
&particle->data.direction, 0.0001f, -FLT_MAX, FLT_MAX, "%g",
|
|
ImGuiSliderFlags_NoRoundToFormat))
|
|
changed = true;
|
|
|
|
if (ImGui::ColumnDragVec3("Direction Random",
|
|
&particle->data.direction_random, 0.0001f, -FLT_MAX, FLT_MAX, "%g",
|
|
ImGuiSliderFlags_NoRoundToFormat))
|
|
changed = true;
|
|
|
|
vec2 speed;
|
|
speed.x = particle->data.speed;
|
|
speed.y = particle->data.speed_random;
|
|
if (ImGui::ColumnDragVec2("Speed [R]",
|
|
&speed, 0.0001f, -FLT_MAX, FLT_MAX, "%g",
|
|
ImGuiSliderFlags_NoRoundToFormat)) {
|
|
particle->data.speed = speed.x;
|
|
particle->data.speed_random = speed.y;
|
|
changed = true;
|
|
}
|
|
|
|
vec2 deceleration;
|
|
deceleration.x = particle->data.deceleration;
|
|
deceleration.y = particle->data.deceleration_random;
|
|
if (ImGui::ColumnDragVec2("Deceleration [R]",
|
|
&deceleration, 0.0001f, -FLT_MAX, FLT_MAX, "%g",
|
|
ImGuiSliderFlags_NoRoundToFormat)) {
|
|
particle->data.deceleration = deceleration.x;
|
|
particle->data.deceleration_random = deceleration.y;
|
|
changed = true;
|
|
}
|
|
|
|
if (ImGui::ColumnDragVec3("Gravity",
|
|
&particle->data.gravity, 0.0001f, -FLT_MAX, FLT_MAX, "%g",
|
|
ImGuiSliderFlags_NoRoundToFormat))
|
|
changed = true;
|
|
|
|
if (ImGui::ColumnDragVec3("Acceleration",
|
|
&particle->data.acceleration, 0.0001f, -FLT_MAX, FLT_MAX, "%g",
|
|
ImGuiSliderFlags_NoRoundToFormat))
|
|
changed = true;
|
|
|
|
if (ImGui::ColumnDragVec3("Acceleration Random",
|
|
&particle->data.acceleration_random, 0.0001f, -FLT_MAX, FLT_MAX, "%g",
|
|
ImGuiSliderFlags_NoRoundToFormat))
|
|
changed = true;
|
|
|
|
vec2 reflection_coeff;
|
|
reflection_coeff.x = particle->data.reflection_coeff;
|
|
reflection_coeff.y = particle->data.reflection_coeff_random;
|
|
if (ImGui::ColumnDragVec2("Refl Coeff [R]",
|
|
&reflection_coeff, 0.0001f, -FLT_MAX, FLT_MAX, "%g",
|
|
ImGuiSliderFlags_NoRoundToFormat)) {
|
|
particle->data.reflection_coeff = reflection_coeff.x;
|
|
particle->data.reflection_coeff_random = reflection_coeff.y;
|
|
changed = true;
|
|
}
|
|
|
|
if (ImGui::ColumnDragFloat("Rebound Plane Y",
|
|
&particle->data.rebound_plane_y, 0.0001f, -FLT_MAX, FLT_MAX, "%g",
|
|
ImGuiSliderFlags_NoRoundToFormat))
|
|
changed = true;
|
|
|
|
ImGui::Separator();
|
|
|
|
vec4 color = particle->data.color;
|
|
if (ImGui::ColumnColorEdit4("Color", &color,
|
|
ImGuiColorEditFlags_NoLabel | ImGuiColorEditFlags_AlphaBar))
|
|
changed = true;
|
|
particle->data.color = color;
|
|
|
|
if (ImGui::ColumnComboBox("UV Index Type", Glitter::uv_index_type_name,
|
|
Glitter::UV_INDEX_USER,
|
|
(int32_t*)&particle->data.uv_index_type, 0, true, &input_locked))
|
|
changed = true;
|
|
|
|
vec2i split;
|
|
split.x = particle->data.split_u;
|
|
split.y = particle->data.split_v;
|
|
if (ImGui::ColumnSliderLogVec2I("UV Split",
|
|
&split, 1, 128, "%d", 0)) {
|
|
particle->data.split_u = (uint8_t)split.x;
|
|
particle->data.split_v = (uint8_t)split.y;
|
|
|
|
particle->data.split_uv.x = 1.0f / (float_t)particle->data.split_u;
|
|
particle->data.split_uv.y = 1.0f / (float_t)particle->data.split_v;
|
|
changed = true;
|
|
}
|
|
|
|
int32_t uv_max_count = (int32_t)(particle->data.split_u * particle->data.split_v);
|
|
if (uv_max_count)
|
|
uv_max_count--;
|
|
|
|
if (ImGui::ColumnDragInt("Frame Step UV",
|
|
&particle->data.frame_step_uv, 1.0f, 0x0000, 0x7FFF, "%d", 0))
|
|
changed = true;
|
|
|
|
if (ImGui::ColumnDragInt("UV Index Start",
|
|
&particle->data.uv_index_start, 1.0f, 0, uv_max_count, "%d", 0))
|
|
changed = true;
|
|
|
|
if (ImGui::ColumnDragInt("UV Index End",
|
|
&particle->data.uv_index_end, 1.0f, particle->data.uv_index_start + 1, uv_max_count + 1, "%d", 0))
|
|
changed = true;
|
|
|
|
if (ImGui::ColumnDragInt("UV Index",
|
|
&particle->data.uv_index, 1.0f, particle->data.uv_index_start,
|
|
particle->data.uv_index_end - 1, "%d", 0))
|
|
changed = true;
|
|
|
|
if (ImGui::ColumnDragVec2("UV Scroll Add",
|
|
&particle->data.uv_scroll_add, 0.0001f, -FLT_MAX, FLT_MAX, "%g",
|
|
ImGuiSliderFlags_NoRoundToFormat))
|
|
changed = true;
|
|
|
|
if (ImGui::ColumnDragFloat("UV Scroll Add Scale",
|
|
&particle->data.uv_scroll_add_scale, 0.0001f, -FLT_MAX, FLT_MAX, "%g",
|
|
ImGuiSliderFlags_NoRoundToFormat))
|
|
changed = true;
|
|
|
|
if (particle->data.type == Glitter::PARTICLE_MESH) {
|
|
bool uv_2nd_add = particle->data.sub_flags & Glitter::PARTICLE_SUB_UV_2ND_ADD ? true : false;
|
|
ImGui::DisableElementPush(uv_2nd_add);
|
|
if (ImGui::ColumnDragVec2("UV Scroll 2nd Add",
|
|
&particle->data.uv_scroll_2nd_add, 0.0001f, -FLT_MAX, FLT_MAX, "%g",
|
|
ImGuiSliderFlags_NoRoundToFormat))
|
|
changed = true;
|
|
|
|
if (ImGui::ColumnDragFloat("UV Scroll 2nd Add Scale",
|
|
&particle->data.uv_scroll_2nd_add_scale, 0.0001f, -FLT_MAX, FLT_MAX, "%g",
|
|
ImGuiSliderFlags_NoRoundToFormat))
|
|
changed = true;
|
|
ImGui::DisableElementPop(uv_2nd_add);
|
|
}
|
|
|
|
if (particle->data.type != Glitter::PARTICLE_MESH) {
|
|
int32_t idx0 = 0;
|
|
int32_t idx1 = 0;
|
|
Glitter::EffectGroup* eg = glt_edt->effect_group;
|
|
size_t rc = eg->resources_count;
|
|
uint64_t* rh = eg->resource_hashes.data();
|
|
for (size_t i = 0; i < rc && (!idx0 || !idx1); i++) {
|
|
if (!idx0 && rh[i] == particle->data.tex_hash)
|
|
idx0 = (int32_t)(i + 1);
|
|
|
|
if (!idx1 && rh[i] == particle->data.mask_tex_hash)
|
|
idx1 = (int32_t)(i + 1);
|
|
}
|
|
|
|
char** texture_name_list = new char*[rc + 1];
|
|
char* texture_names = new char[0x40 * (rc + 1)];
|
|
|
|
texture_name_list[0] = texture_names;
|
|
snprintf(texture_name_list[0], 0x40, "No Texture");
|
|
for (size_t i = 0; i < rc; i++)
|
|
snprintf(texture_name_list[i + 1] = &texture_names[0x40 * (i + 1)],
|
|
0x40, "Texture %lld (%016llX)", i + 1, rh[i]);
|
|
|
|
static bool tex0_anim;
|
|
static int32_t tex0_frame;
|
|
static int32_t tex0_index;
|
|
static int32_t tex0_tex;
|
|
if (glitter_editor_property_particle_texture(glt_edt, "Texture", texture_name_list,
|
|
particle, &particle->data.texture, &particle->data.tex_hash,
|
|
idx0, &tex0_anim, &tex0_frame, &tex0_index, &tex0_tex))
|
|
changed = true;
|
|
|
|
if (particle->data.flags & Glitter::PARTICLE_TEXTURE_MASK) {
|
|
static bool tex11_anim;
|
|
static int32_t tex1_frame;
|
|
static int32_t tex1_index;
|
|
static int32_t tex1_tex;
|
|
if (glitter_editor_property_particle_texture(glt_edt, "Texture Mask", texture_name_list,
|
|
particle, &particle->data.mask_texture, &particle->data.mask_tex_hash,
|
|
idx1, &tex11_anim, &tex1_frame, &tex1_index, &tex1_tex))
|
|
changed = true;
|
|
}
|
|
delete[] texture_names;
|
|
delete[] texture_name_list;
|
|
|
|
Glitter::ParticleBlendDraw blend_draw = Glitter::particle_blend_draw_default;
|
|
for (int32_t i = 0; i < Glitter::particle_blend_mask_types_count; i++)
|
|
if (Glitter::particle_blend_draw_types[i] == particle->data.blend_mode) {
|
|
blend_draw = (Glitter::ParticleBlendDraw)i;
|
|
break;
|
|
}
|
|
|
|
if (ImGui::ColumnComboBox("Blend Mode", Glitter::particle_blend_draw_name,
|
|
Glitter::PARTICLE_BLEND_DRAW_MULTIPLY,
|
|
(int32_t*)&blend_draw, 0, true, &input_locked))
|
|
if (Glitter::particle_blend_draw_types[blend_draw] != particle->data.blend_mode) {
|
|
particle->data.blend_mode = Glitter::particle_blend_draw_types[blend_draw];
|
|
changed = true;
|
|
}
|
|
|
|
if (particle->data.flags & Glitter::PARTICLE_TEXTURE_MASK) {
|
|
Glitter::ParticleBlendMask blend_mask = Glitter::particle_blend_mask_default;
|
|
for (int32_t i = 0; i < Glitter::particle_blend_mask_types_count; i++)
|
|
if (Glitter::particle_blend_mask_types[i] == particle->data.mask_blend_mode) {
|
|
blend_mask = (Glitter::ParticleBlendMask)i;
|
|
break;
|
|
}
|
|
|
|
if (ImGui::ColumnComboBox("Mask Blend Mode", Glitter::particle_blend_mask_name,
|
|
Glitter::PARTICLE_BLEND_MASK_MULTIPLY,
|
|
(int32_t*)&blend_mask, 0, true, &input_locked))
|
|
if (Glitter::particle_blend_mask_types[blend_mask] != particle->data.mask_blend_mode) {
|
|
particle->data.mask_blend_mode = Glitter::particle_blend_mask_types[blend_mask];
|
|
changed = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
switch (particle->data.uv_index_type) {
|
|
case Glitter::UV_INDEX_FIXED:
|
|
case Glitter::UV_INDEX_RANDOM:
|
|
case Glitter::UV_INDEX_FORWARD:
|
|
case Glitter::UV_INDEX_REVERSE:
|
|
case Glitter::UV_INDEX_USER:
|
|
particle->data.uv_index &= uv_max_count;
|
|
break;
|
|
case Glitter::UV_INDEX_INITIAL_RANDOM_FIXED:
|
|
case Glitter::UV_INDEX_INITIAL_RANDOM_FORWARD:
|
|
case Glitter::UV_INDEX_INITIAL_RANDOM_REVERSE:
|
|
if (particle->data.uv_index < particle->data.uv_index_start)
|
|
particle->data.uv_index = particle->data.uv_index_start;
|
|
else if (particle->data.uv_index_end >= 0 && particle->data.uv_index > particle->data.uv_index_end)
|
|
particle->data.uv_index = particle->data.uv_index_end;
|
|
|
|
particle->data.uv_index = min_def(particle->data.uv_index, uv_max_count);
|
|
break;
|
|
}
|
|
|
|
if (particle->data.uv_index_end >= 0)
|
|
particle->data.uv_index_count = particle->data.uv_index_end - particle->data.uv_index_start + 1;
|
|
else
|
|
particle->data.uv_index_count = uv_max_count - particle->data.uv_index_start;
|
|
|
|
if (particle->data.uv_index_count < 0)
|
|
particle->data.uv_index_count = 0;
|
|
|
|
if (ImGui::CheckboxFlagsEnterKeyPressed("Use Animation Curve",
|
|
(uint32_t*)&particle->data.sub_flags,
|
|
Glitter::PARTICLE_SUB_USE_CURVE))
|
|
changed = true;
|
|
|
|
if (eg->type == Glitter::X && particle->data.type == Glitter::PARTICLE_MESH)
|
|
if (ImGui::CheckboxFlagsEnterKeyPressed("UV Add",
|
|
(uint32_t*)&particle->data.sub_flags,
|
|
Glitter::PARTICLE_SUB_UV_2ND_ADD))
|
|
changed = true;
|
|
|
|
ImGui::Separator();
|
|
|
|
if (eg->type != Glitter::X || particle->data.type == Glitter::PARTICLE_QUAD)
|
|
if (ImGui::ColumnDragInt("Count",
|
|
&particle->data.count, 1.0f, 0x0000, 0x7FFFFF, "%d", 0))
|
|
changed = true;
|
|
|
|
if (ImGui::ColumnDragFloat("Emission",
|
|
&particle->data.emission, 0.0001f, 0.0f, HALF_MAX, "%g",
|
|
ImGuiSliderFlags_NoRoundToFormat)) {
|
|
if (sel_efct->data.flags & Glitter::EFFECT_EMISSION
|
|
|| particle->data.emission >= Glitter::min_emission)
|
|
enum_or(particle->data.flags, Glitter::PARTICLE_EMISSION);
|
|
else
|
|
enum_and(particle->data.flags, ~Glitter::PARTICLE_EMISSION);
|
|
changed = true;
|
|
}
|
|
|
|
if (ImGui::ColumnDragInt("Unk 0",
|
|
&particle->data.unk0, 1.0f, INT_MIN, INT_MAX, "%d", 0))
|
|
changed = true;
|
|
|
|
if (eg->version >= 7 && ImGui::ColumnDragInt("Unk 1",
|
|
&particle->data.unk1, 1.0f, INT_MIN, INT_MAX, "%d", 0))
|
|
changed = true;
|
|
|
|
if (particle->data.type == Glitter::PARTICLE_LOCUS) {
|
|
if (ImGui::ColumnDragInt("Locus Hist Size",
|
|
&particle->data.locus_history_size, 1.0f, 0x0000, 0x7FFFFF, "%d", 0))
|
|
changed = true;
|
|
|
|
if (ImGui::ColumnDragInt("Locus Hist Size Rand",
|
|
&particle->data.locus_history_size_random, 1.0f, 0x0000, 0x7FFFFF, "%d", 0))
|
|
changed = true;
|
|
}
|
|
else if (particle->data.type == Glitter::PARTICLE_MESH) {
|
|
ImGui::Separator();
|
|
|
|
Glitter::Particle::Mesh* mesh = &particle->data.mesh;
|
|
uint32_t set_id = (uint32_t)mesh->object_set_name_hash;
|
|
uint32_t obj_id = (uint32_t)mesh->object_name_hash;
|
|
|
|
ObjsetInfo* info = object_storage_get_objset_info(set_id);
|
|
ssize_t object_set_count = object_storage_get_obj_set_count();
|
|
|
|
/*ImGui::StartPropertyColumn("Object Set");
|
|
if (ImGui::BeginCombo("##Object Set", info ? info->name.c_str() : "None", 0)) {
|
|
ssize_t set_index = info ? object_storage_get_obj_set_index(set_id) : -1;
|
|
|
|
ImGui::PushID(-1);
|
|
if (ImGui::Selectable("None", !info)
|
|
|| ImGui::ItemKeyPressed(ImGuiKey_Enter))
|
|
set_index = -1;
|
|
ImGui::PopID();
|
|
|
|
for (ssize_t i = 0; i < object_set_count; i++) {
|
|
ObjsetInfo* info = object_storage_get_objset_info_by_index(i);
|
|
if (!info || !info->obj_set)
|
|
continue;
|
|
|
|
ImGui::PushID((int32_t)i);
|
|
if (ImGui::Selectable(info->name.c_str(), info->set_id == set_id)
|
|
|| ImGui::ItemKeyPressed(ImGuiKey_Enter)
|
|
|| (ImGui::IsItemFocused() && info->set_id != set_id))
|
|
set_index = i;
|
|
ImGui::PopID();
|
|
}
|
|
|
|
if (set_index == -1)
|
|
set_id = -1;
|
|
else
|
|
set_id = object_storage_get_objset_info_by_index(set_index)->set_id;
|
|
|
|
if (mesh->object_set_name_hash != set_id) {
|
|
mesh->object_set_name_hash = set_id;
|
|
mesh->object_name_hash = -1;
|
|
changed = true;
|
|
}
|
|
input_locked |= ImGui::IsWindowFocused();
|
|
ImGui::EndCombo();
|
|
}
|
|
ImGui::EndPropertyColumn();*/
|
|
|
|
ImGui::DisableElementPush(set_id != -1);
|
|
obj* obj = 0;
|
|
if (info && info->obj_set) {
|
|
obj_set* set = info->obj_set;
|
|
::obj** obj_data = set->obj_data;
|
|
for (uint32_t i = 0; i < set->obj_num; i++)
|
|
if (obj_data[i]->id == obj_id) {
|
|
obj = obj_data[i];
|
|
break;
|
|
}
|
|
}
|
|
|
|
ImGui::StartPropertyColumn("Object");
|
|
if (ImGui::BeginCombo("##Object", obj ? obj->name : "None", 0)) {
|
|
if (set_id != -1 && info && info->set_id == set_id && info->obj_set) {
|
|
obj_set* set = info->obj_set;
|
|
::obj** obj_data = set->obj_data;
|
|
ssize_t obj_index = -1;
|
|
for (uint32_t i = 0; i < set->obj_num; i++)
|
|
#pragma warning(suppress: 28182)
|
|
if (obj_data[i]->id == obj_id) {
|
|
obj_index = i;
|
|
break;
|
|
}
|
|
|
|
ImGui::PushID(-1);
|
|
if (ImGui::Selectable("None", !obj)
|
|
|| ImGui::ItemKeyPressed(ImGuiKey_Enter)
|
|
|| (ImGui::IsItemFocused() && obj))
|
|
obj_index = -1;
|
|
ImGui::PopID();
|
|
|
|
for (uint32_t i = 0; i < set->obj_num; i++) {
|
|
ImGui::PushID(i);
|
|
::obj* obj = obj_data[i];
|
|
if (ImGui::Selectable(obj->name, obj->id == obj_id)
|
|
|| ImGui::ItemKeyPressed(ImGuiKey_Enter)
|
|
|| (ImGui::IsItemFocused() && obj->id != obj_id))
|
|
obj_index = i;
|
|
ImGui::PopID();
|
|
}
|
|
|
|
if (obj_index == -1 || obj_index >= set->obj_num)
|
|
obj_id = -1;
|
|
else
|
|
obj_id = obj_data[obj_index]->id;
|
|
|
|
if (mesh->object_name_hash != obj_id) {
|
|
mesh->object_name_hash = obj_id;
|
|
changed = true;
|
|
}
|
|
}
|
|
input_locked |= ImGui::IsWindowFocused();
|
|
ImGui::EndCombo();
|
|
}
|
|
ImGui::EndPropertyColumn();
|
|
ImGui::DisableElementPop(set_id != -1);
|
|
|
|
/*if (glitter_editor_hash_input("Object Set Name Hash", &mesh->object_set_name_hash))
|
|
changed = true;
|
|
|
|
if (glitter_editor_hash_input("Object Name Hash", &mesh->object_name_hash))
|
|
changed = true;
|
|
|
|
const size_t mesh_name_size = sizeof(mesh->mesh_name);
|
|
char mesh_name[sizeof(mesh->mesh_name)];
|
|
memcpy(mesh_name, mesh->mesh_name, mesh_name_size);
|
|
if (ImGui::ColumnInputText("Mesh Name", mesh_name, mesh_name_size, 0, 0, 0)) {
|
|
memcpy(mesh->mesh_name, mesh_name, mesh_name_size);
|
|
changed = true;
|
|
}
|
|
|
|
if (glitter_editor_hash_input("Sub Mesh Hash", &mesh->sub_mesh_hash))
|
|
changed = true;*/
|
|
}
|
|
|
|
uint64_t hash_after = hash_fnv1a64m(glt_edt->selected_particle, sizeof(Glitter::Particle));
|
|
if (hash_before != hash_after && changed)
|
|
glt_edt->input_reload = true;
|
|
|
|
ImGui::SetDefaultColumnSpace();
|
|
}
|
|
|
|
static bool glitter_editor_property_particle_texture(GlitterEditor* glt_edt,
|
|
const char* label, char** items, Glitter::Particle* particle,
|
|
GLuint* tex, uint64_t* tex_hash, int32_t tex_idx, bool* tex_anim,
|
|
int32_t* tex_frame, int32_t* tex_index, int32_t* tex_tex) {
|
|
Glitter::EffectGroup* eg = glt_edt->effect_group;
|
|
size_t rc = eg->resources_count;
|
|
texture** r = eg->resources;
|
|
uint64_t* rh = eg->resource_hashes.data();
|
|
txp* rt = eg->resources_tex.textures.data();
|
|
|
|
const uint64_t empty_hash = eg->type != Glitter::FT
|
|
? hash_murmurhash_empty : hash_fnv1a64m_empty;
|
|
|
|
ImVec2 uv_min;
|
|
ImVec2 uv_max;
|
|
|
|
ImGui::StartPropertyColumn(label);
|
|
int32_t prev_tex_idx = tex_idx;
|
|
if (ImGui::BeginCombo("", items[tex_idx], 0)) {
|
|
int32_t uv_index = *tex_index;
|
|
if (!*tex_anim) {
|
|
*tex_anim = true;
|
|
*tex_frame = 0;
|
|
*tex_tex = tex_idx;
|
|
|
|
uv_index = particle->data.uv_index;
|
|
int32_t max_uv = particle->data.split_u * particle->data.split_v;
|
|
if (max_uv > 1 && particle->data.uv_index_count > 1) {
|
|
switch (particle->data.uv_index_type) {
|
|
case Glitter::UV_INDEX_INITIAL_RANDOM_FIXED:
|
|
case Glitter::UV_INDEX_INITIAL_RANDOM_FORWARD:
|
|
case Glitter::UV_INDEX_INITIAL_RANDOM_REVERSE: {
|
|
LARGE_INTEGER time;
|
|
QueryPerformanceCounter(&time);
|
|
uv_index = particle->data.uv_index_start
|
|
+ time.LowPart % particle->data.uv_index_count;
|
|
} break;
|
|
}
|
|
uv_index = min_def(uv_index, particle->data.uv_index_end);
|
|
}
|
|
}
|
|
else if (particle->data.uv_index_type == Glitter::UV_INDEX_INITIAL_RANDOM_FIXED) {
|
|
if (particle->data.uv_index_count > 0 && !(*tex_frame % 40)) {
|
|
uv_index = particle->data.uv_index;
|
|
|
|
LARGE_INTEGER time;
|
|
QueryPerformanceCounter(&time);
|
|
uv_index += time.LowPart % particle->data.uv_index_count;
|
|
}
|
|
}
|
|
else if (particle->data.frame_step_uv && !(*tex_frame % particle->data.frame_step_uv)) {
|
|
int32_t max_uv = particle->data.split_u * particle->data.split_v;
|
|
if (max_uv)
|
|
max_uv--;
|
|
|
|
switch (particle->data.uv_index_type) {
|
|
case Glitter::UV_INDEX_RANDOM:
|
|
uv_index = particle->data.uv_index_start;
|
|
if (particle->data.uv_index_count > 1) {
|
|
LARGE_INTEGER time;
|
|
QueryPerformanceCounter(&time);
|
|
uv_index += time.LowPart % particle->data.uv_index_count;
|
|
}
|
|
break;
|
|
case Glitter::UV_INDEX_FORWARD:
|
|
case Glitter::UV_INDEX_INITIAL_RANDOM_FORWARD:
|
|
uv_index = (uint8_t)(max_uv & (uv_index + 1));
|
|
break;
|
|
case Glitter::UV_INDEX_REVERSE:
|
|
case Glitter::UV_INDEX_INITIAL_RANDOM_REVERSE:
|
|
uv_index = (uint8_t)(max_uv & (uv_index - 1));
|
|
break;
|
|
}
|
|
}
|
|
*tex_index = uv_index;
|
|
|
|
vec2 uv;
|
|
uv.x = (float_t)(uv_index % particle->data.split_u) * particle->data.split_uv.x;
|
|
uv.y = (float_t)(uv_index / particle->data.split_u) * particle->data.split_uv.y;
|
|
uv_min.x = uv.x;
|
|
uv_min.y = uv.y;
|
|
uv_max.x = uv.x + particle->data.split_uv.x;
|
|
uv_max.y = uv.y + particle->data.split_uv.y;
|
|
|
|
for (int32_t n = 0; n <= rc; n++) {
|
|
ImGui::PushID(n);
|
|
if (ImGui::Selectable(items[n], tex_idx == n)
|
|
|| ImGui::ItemKeyPressed(ImGuiKey_Enter)
|
|
|| (ImGui::IsItemFocused() && tex_idx != n))
|
|
tex_idx = n;
|
|
|
|
if (ImGui::IsItemHovered(0) && n) {
|
|
if (*tex_tex != n) {
|
|
*tex_anim = true;
|
|
*tex_frame = 0;
|
|
*tex_tex = n;
|
|
|
|
uv_index = particle->data.uv_index;
|
|
int32_t max_uv = particle->data.split_u * particle->data.split_v;
|
|
if (max_uv > 1) {
|
|
switch (particle->data.uv_index_type) {
|
|
case Glitter::UV_INDEX_INITIAL_RANDOM_FIXED:
|
|
case Glitter::UV_INDEX_INITIAL_RANDOM_FORWARD:
|
|
case Glitter::UV_INDEX_INITIAL_RANDOM_REVERSE: {
|
|
LARGE_INTEGER time;
|
|
QueryPerformanceCounter(&time);
|
|
uv_index = particle->data.uv_index_start
|
|
+ time.LowPart % particle->data.uv_index_count;
|
|
} break;
|
|
}
|
|
}
|
|
*tex_index = uv_index;
|
|
|
|
vec2 uv;
|
|
uv.x = (float_t)(uv_index % particle->data.split_u) * particle->data.split_uv.x;
|
|
uv.y = (float_t)(uv_index / particle->data.split_u) * particle->data.split_uv.y;
|
|
uv_min.x = uv.x;
|
|
uv_min.y = uv.y;
|
|
uv_max.x = uv.x + particle->data.split_uv.x;
|
|
uv_max.y = uv.y + particle->data.split_uv.y;
|
|
}
|
|
|
|
txp_mipmap* rtm = rt[n - 1].mipmaps.data();
|
|
float_t aspect1 = (float_t)rtm->width / (float_t)rtm->height;
|
|
float_t aspect2 = aspect1;
|
|
if (particle->data.split_u * particle->data.split_v > 1)
|
|
aspect2 /= (float_t)particle->data.split_u
|
|
/ (float_t)particle->data.split_v;
|
|
|
|
ImVec2 size1 = { 192.0f, 192.0f };
|
|
if (aspect1 > 1.0f)
|
|
size1.y /= aspect1;
|
|
else if (aspect1 < 1.0f)
|
|
size1.x *= aspect1;
|
|
|
|
ImVec2 size2 = { 192.0f, 192.0f };
|
|
if (aspect2 > 1.0f)
|
|
size2.y /= aspect2;
|
|
else if (aspect2 < 1.0f)
|
|
size2.x *= aspect2;
|
|
|
|
ImGui::BeginTooltip();
|
|
ImGui::Text("Frame: %d\nUV Index %d", *tex_frame, *tex_index);
|
|
ImGui::Text("Tex Size: %dx%d", rtm->width, rtm->height);
|
|
ImGui::Image((void*)(size_t)r[n - 1]->tex, size1,
|
|
{ 0, 0 }, { 1, 1 }, tint_col, border_col);
|
|
ImGui::Text("Preview Tex Size: %gx%g",
|
|
particle->data.split_u > 1
|
|
? (float_t)rtm->width / (float_t)particle->data.split_u
|
|
: (float_t)rtm->width,
|
|
particle->data.split_u > 1
|
|
? (float_t)rtm->height / (float_t)particle->data.split_v
|
|
: (float_t)rtm->height);
|
|
ImGui::Image((void*)(size_t)r[n - 1]->tex, size2,
|
|
uv_min, uv_max, tint_col, border_col);
|
|
ImGui::EndTooltip();
|
|
}
|
|
|
|
if (tex_idx == n)
|
|
ImGui::SetItemDefaultFocus();
|
|
ImGui::PopID();
|
|
}
|
|
input_locked |= ImGui::IsWindowFocused();
|
|
ImGui::EndCombo();
|
|
(*tex_frame)++;
|
|
}
|
|
else {
|
|
*tex_anim = false;
|
|
*tex_frame = 0;
|
|
*tex_index = 0;
|
|
*tex_tex = 0;
|
|
}
|
|
bool res = prev_tex_idx != tex_idx;
|
|
ImGui::EndPropertyColumn();
|
|
|
|
if (res)
|
|
if (tex_idx) {
|
|
*tex = r[tex_idx - 1]->tex;
|
|
*tex_hash = rh[tex_idx - 1];
|
|
}
|
|
else {
|
|
*tex = 0;
|
|
*tex_hash = empty_hash;
|
|
}
|
|
return res;
|
|
}
|
|
|
|
static void glitter_editor_popups(GlitterEditor* glt_edt) {
|
|
ImGuiIO& io = ImGui::GetIO();
|
|
ImGuiStyle& style = ImGui::GetStyle();
|
|
ImFont* font = ImGui::GetFont();
|
|
|
|
const float_t title_bar_size = font->FontSize + style.ItemSpacing.y + style.FramePadding.y * 2.0f;
|
|
|
|
ImGui::PushID("Glitter Editor Glitter File Create Pop-up");
|
|
glitter_editor_file_create_popup(glt_edt, io, style, font, title_bar_size);
|
|
ImGui::PopID();
|
|
|
|
ImGui::PushID("Glitter Editor Glitter File Load Pop-up");
|
|
glitter_editor_file_load_popup(glt_edt, io, style, font, title_bar_size);
|
|
ImGui::PopID();
|
|
|
|
ImGui::PushID("Glitter Editor Glitter File Load Pop-up");
|
|
glitter_editor_file_load_model_popup(glt_edt, io, style, font, title_bar_size);
|
|
ImGui::PopID();
|
|
|
|
ImGui::PushID("Glitter Editor Glitter File Load Error List Pop-up");
|
|
glitter_editor_file_load_error_list_popup(glt_edt, io, style, font, title_bar_size);
|
|
ImGui::PopID();
|
|
|
|
ImGui::PushID("Glitter Editor Glitter File Save");
|
|
glitter_editor_file_save_popup(glt_edt, io, style, font, title_bar_size);
|
|
ImGui::PopID();
|
|
}
|
|
|
|
static void glitter_editor_file_create_popup(GlitterEditor* glt_edt,
|
|
ImGuiIO& io, ImGuiStyle& style, ImFont* font, const float_t title_bar_size) {
|
|
if (glt_edt->create_popup) {
|
|
ImGui::OpenPopup("Create Glitter File as...", 0);
|
|
glt_edt->create_popup = false;
|
|
}
|
|
|
|
float_t x;
|
|
float_t y;
|
|
float_t w;
|
|
float_t h;
|
|
float_t win_x;
|
|
float_t win_y;
|
|
|
|
Glitter::EffectGroup* eg = glt_edt->effect_group;
|
|
|
|
ImGuiWindowFlags window_flags;
|
|
|
|
const float_t button_width = 70.0f;
|
|
|
|
win_x = button_width * 2.0f + style.ItemSpacing.x * 1.0f;
|
|
win_y = title_bar_size + font->FontSize + style.ItemSpacing.y * 1.0f + style.FramePadding.y * 2.0f;
|
|
|
|
x = (float_t)width * 0.5f - win_x * 0.5f;
|
|
y = (float_t)height * 0.5f - win_y * 0.5f;
|
|
w = win_x;
|
|
h = win_y;
|
|
|
|
window_flags = 0;
|
|
window_flags |= ImGuiWindowFlags_NoResize;
|
|
window_flags |= ImGuiWindowFlags_NoMove;
|
|
window_flags |= ImGuiWindowFlags_NoScrollbar;
|
|
window_flags |= ImGuiWindowFlags_NoScrollWithMouse;
|
|
|
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowTitleAlign, { 0.5f, 0.5f });
|
|
ImGui::SetNextWindowPos({ x, y }, ImGuiCond_Always);
|
|
ImGui::SetNextWindowSize({ w, h }, ImGuiCond_Always);
|
|
if (ImGui::BeginPopupModal("Create Glitter File as...", 0, window_flags)) {
|
|
x = win_x * 0.5f - ImGui::GetContentRegionAvail().x * 0.5f;
|
|
y = title_bar_size;
|
|
|
|
ImGui::SetCursorPos({ x, y });
|
|
if (ImGui::BeginTable("buttons", 2)) {
|
|
bool close = false;
|
|
|
|
ImGui::TableNextColumn();
|
|
if (ImGui::ButtonEnterKeyPressed("F2", ImGui::GetContentRegionAvail())) {
|
|
glt_edt->load_glt_type = Glitter::F2;
|
|
close = true;
|
|
}
|
|
|
|
ImGui::TableNextColumn();
|
|
if (ImGui::ButtonEnterKeyPressed("FT", ImGui::GetContentRegionAvail())) {
|
|
glt_edt->load_glt_type = Glitter::FT;
|
|
close = true;
|
|
}
|
|
|
|
/*ImGui::TableNextColumn();
|
|
if (ImGui::ButtonEnterKeyPressed("X", ImGui::GetContentRegionAvail())) {
|
|
glt_edt->load_glt_type = Glitter::X;
|
|
close = true;
|
|
}*/
|
|
|
|
if (close) {
|
|
glt_edt->effect_group_add = true;
|
|
enum_or(glt_edt->effect_flags, GLITTER_EDITOR_ADD);
|
|
ImGui::CloseCurrentPopup();
|
|
}
|
|
ImGui::EndTable();
|
|
}
|
|
input_locked |= ImGui::IsWindowFocused();
|
|
ImGui::EndPopup();
|
|
}
|
|
ImGui::PopStyleVar();
|
|
}
|
|
|
|
static void glitter_editor_file_load_popup(GlitterEditor* glt_edt,
|
|
ImGuiIO& io, ImGuiStyle& style, ImFont* font, const float_t title_bar_size) {
|
|
if (glt_edt->load_popup) {
|
|
ImGui::OpenPopup("Load Glitter File as...", 0);
|
|
glt_edt->load_popup = false;
|
|
}
|
|
|
|
float_t x;
|
|
float_t y;
|
|
float_t w;
|
|
float_t h;
|
|
float_t win_x;
|
|
float_t win_y;
|
|
|
|
ImGuiWindowFlags window_flags;
|
|
|
|
const float_t button_width = 70.0f;
|
|
|
|
win_x = button_width * 3.0f + style.ItemSpacing.x * 2.0f;
|
|
win_y = title_bar_size + font->FontSize + style.ItemSpacing.y * 2.0f + style.FramePadding.y * 3.0f;
|
|
|
|
x = (float_t)width * 0.5f - win_x * 0.5f;
|
|
y = (float_t)height * 0.5f - win_y * 0.5f;
|
|
w = win_x;
|
|
h = win_y;
|
|
|
|
window_flags = 0;
|
|
window_flags |= ImGuiWindowFlags_NoResize;
|
|
window_flags |= ImGuiWindowFlags_NoMove;
|
|
window_flags |= ImGuiWindowFlags_NoScrollbar;
|
|
window_flags |= ImGuiWindowFlags_NoScrollWithMouse;
|
|
|
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowTitleAlign, { 0.5f, 0.5f });
|
|
ImGui::SetNextWindowPos({ x, y }, ImGuiCond_Always);
|
|
ImGui::SetNextWindowSize({ w, h }, ImGuiCond_Always);
|
|
if (ImGui::BeginPopupModal("Load Glitter File as...", 0, window_flags)) {
|
|
x = win_x * 0.5f - ImGui::GetContentRegionAvail().x * 0.5f;
|
|
y = title_bar_size;
|
|
|
|
ImGui::SetCursorPos({ x, y });
|
|
if (ImGui::BeginTable("buttons", 3)) {
|
|
bool close = false;
|
|
|
|
ImGui::TableNextColumn();
|
|
if (ImGui::ButtonEnterKeyPressed("F2", ImGui::GetContentRegionAvail())) {
|
|
glt_edt->load_glt_type = Glitter::F2;
|
|
close = true;
|
|
}
|
|
|
|
ImGui::TableNextColumn();
|
|
if (ImGui::ButtonEnterKeyPressed("FT", ImGui::GetContentRegionAvail())) {
|
|
glt_edt->load_glt_type = Glitter::FT;
|
|
close = true;
|
|
}
|
|
|
|
ImGui::TableNextColumn();
|
|
if (ImGui::ButtonEnterKeyPressed("X", ImGui::GetContentRegionAvail())) {
|
|
glt_edt->load_glt_type = Glitter::X;
|
|
close = true;
|
|
}
|
|
|
|
if (close) {
|
|
glt_edt->load = true;
|
|
ImGui::CloseCurrentPopup();
|
|
}
|
|
ImGui::EndTable();
|
|
}
|
|
input_locked |= ImGui::IsWindowFocused();
|
|
ImGui::EndPopup();
|
|
}
|
|
ImGui::PopStyleVar();
|
|
}
|
|
|
|
static void glitter_editor_file_load_model_popup(GlitterEditor* glt_edt,
|
|
ImGuiIO& io, ImGuiStyle& style, ImFont* font, const float_t title_bar_size) {
|
|
if (!glt_edt->effect_group) {
|
|
glt_edt->load_data_popup = false;
|
|
return;
|
|
}
|
|
|
|
bool data_aft_enable = data_list[DATA_AFT].data_paths.size() > 0;
|
|
bool data_f2le_enable = data_list[DATA_F2LE].data_paths.size() > 0;
|
|
bool data_f2be_enable = data_list[DATA_F2BE].data_paths.size() > 0;
|
|
bool data_ft_enable = data_list[DATA_FT].data_paths.size() > 0;
|
|
bool data_m39_enable = data_list[DATA_M39].data_paths.size() > 0;
|
|
bool data_vrfl_enable = data_list[DATA_VRFL].data_paths.size() > 0;
|
|
bool data_x_enable = data_list[DATA_X].data_paths.size() > 0;
|
|
bool data_xhd_enable = data_list[DATA_XHD].data_paths.size() > 0;
|
|
|
|
int32_t data_count = 0;
|
|
switch (glt_edt->effect_group->type) {
|
|
case Glitter::F2:
|
|
if (data_f2le_enable)
|
|
data_count++;
|
|
if (data_f2be_enable)
|
|
data_count++;
|
|
break;
|
|
case Glitter::FT:
|
|
if (data_aft_enable)
|
|
data_count++;
|
|
if (data_ft_enable)
|
|
data_count++;
|
|
if (data_m39_enable)
|
|
data_count++;
|
|
break;
|
|
case Glitter::X:
|
|
if (data_x_enable)
|
|
data_count++;
|
|
if (data_xhd_enable)
|
|
data_count++;
|
|
if (data_vrfl_enable)
|
|
data_count++;
|
|
break;
|
|
}
|
|
|
|
if (glt_edt->load_data_popup) {
|
|
if (data_count)
|
|
ImGui::OpenPopup("Which data should be loaded?", 0);
|
|
glt_edt->load_data_popup = false;
|
|
}
|
|
|
|
if (!data_count)
|
|
return;
|
|
|
|
float_t x;
|
|
float_t y;
|
|
float_t w;
|
|
float_t h;
|
|
float_t win_x;
|
|
float_t win_y;
|
|
|
|
ImGuiWindowFlags window_flags;
|
|
|
|
float_t button_width;
|
|
if (data_count == 3) {
|
|
button_width = 70.0f;
|
|
win_x = button_width * 3.0f + style.ItemSpacing.x * 2.0f;
|
|
}
|
|
else if (data_count == 2) {
|
|
button_width = 105.0f;
|
|
win_x = button_width * 2.0f + style.ItemSpacing.x;
|
|
}
|
|
else {
|
|
button_width = 210.0f;
|
|
win_x = button_width;
|
|
}
|
|
win_y = title_bar_size + font->FontSize + style.ItemSpacing.y * 2.0f + style.FramePadding.y * 3.0f;
|
|
|
|
x = (float_t)width * 0.5f - win_x * 0.5f;
|
|
y = (float_t)height * 0.5f - win_y * 0.5f;
|
|
w = win_x;
|
|
h = win_y;
|
|
|
|
window_flags = 0;
|
|
window_flags |= ImGuiWindowFlags_NoResize;
|
|
window_flags |= ImGuiWindowFlags_NoMove;
|
|
window_flags |= ImGuiWindowFlags_NoScrollbar;
|
|
window_flags |= ImGuiWindowFlags_NoScrollWithMouse;
|
|
|
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowTitleAlign, { 0.5f, 0.5f });
|
|
ImGui::SetNextWindowPos({ x, y }, ImGuiCond_Always);
|
|
ImGui::SetNextWindowSize({ w, h }, ImGuiCond_Always);
|
|
if (ImGui::BeginPopupModal("Which data should be loaded?", 0, window_flags)) {
|
|
x = win_x * 0.5f - ImGui::GetContentRegionAvail().x * 0.5f;
|
|
y = title_bar_size;
|
|
|
|
ImGui::SetCursorPos({ x, y });
|
|
if (ImGui::BeginTable("buttons", data_count)) {
|
|
bool close = false;
|
|
|
|
switch (glt_edt->effect_group->type) {
|
|
case Glitter::F2:
|
|
if (data_f2le_enable) {
|
|
ImGui::TableNextColumn();
|
|
if (ImGui::ButtonEnterKeyPressed("F2LE", ImGui::GetContentRegionAvail())) {
|
|
glt_edt->load_data_type = DATA_F2LE;
|
|
close = true;
|
|
}
|
|
}
|
|
|
|
if (data_f2be_enable) {
|
|
ImGui::TableNextColumn();
|
|
if (ImGui::ButtonEnterKeyPressed("F2BE", ImGui::GetContentRegionAvail())) {
|
|
glt_edt->load_data_type = DATA_F2BE;
|
|
close = true;
|
|
}
|
|
}
|
|
break;
|
|
case Glitter::FT:
|
|
if (data_aft_enable) {
|
|
ImGui::TableNextColumn();
|
|
if (ImGui::ButtonEnterKeyPressed("AFT", ImGui::GetContentRegionAvail())) {
|
|
glt_edt->load_data_type = DATA_AFT;
|
|
close = true;
|
|
}
|
|
}
|
|
|
|
if (data_ft_enable) {
|
|
ImGui::TableNextColumn();
|
|
if (ImGui::ButtonEnterKeyPressed("FT", ImGui::GetContentRegionAvail())) {
|
|
glt_edt->load_data_type = DATA_FT;
|
|
close = true;
|
|
}
|
|
}
|
|
|
|
if (data_m39_enable) {
|
|
ImGui::TableNextColumn();
|
|
if (ImGui::ButtonEnterKeyPressed("M39", ImGui::GetContentRegionAvail())) {
|
|
glt_edt->load_data_type = DATA_M39;
|
|
close = true;
|
|
}
|
|
}
|
|
break;
|
|
case Glitter::X:
|
|
if (data_x_enable) {
|
|
ImGui::TableNextColumn();
|
|
if (ImGui::ButtonEnterKeyPressed("X", ImGui::GetContentRegionAvail())) {
|
|
glt_edt->load_data_type = DATA_X;
|
|
close = true;
|
|
}
|
|
}
|
|
|
|
if (data_xhd_enable) {
|
|
ImGui::TableNextColumn();
|
|
if (ImGui::ButtonEnterKeyPressed("XHD", ImGui::GetContentRegionAvail())) {
|
|
glt_edt->load_data_type = DATA_XHD;
|
|
close = true;
|
|
}
|
|
}
|
|
|
|
if (data_vrfl_enable) {
|
|
ImGui::TableNextColumn();
|
|
if (ImGui::ButtonEnterKeyPressed("VRFL", ImGui::GetContentRegionAvail())) {
|
|
glt_edt->load_data_type = DATA_VRFL;
|
|
close = true;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (close) {
|
|
glt_edt->load_data = true;
|
|
ImGui::CloseCurrentPopup();
|
|
}
|
|
ImGui::EndTable();
|
|
}
|
|
input_locked |= ImGui::IsWindowFocused();
|
|
ImGui::EndPopup();
|
|
}
|
|
ImGui::PopStyleVar();
|
|
}
|
|
|
|
static void glitter_editor_file_load_error_list_popup(GlitterEditor* glt_edt,
|
|
ImGuiIO& io, ImGuiStyle& style, ImFont* font, const float_t title_bar_size) {
|
|
if (glt_edt->load_error_list_popup) {
|
|
ImGui::OpenPopup("Glitter File Load Error", 0);
|
|
glt_edt->load_error_list_popup = false;
|
|
}
|
|
|
|
float_t x;
|
|
float_t y;
|
|
float_t w;
|
|
float_t h;
|
|
float_t win_x;
|
|
float_t win_y;
|
|
|
|
ImGuiWindowFlags window_flags;
|
|
|
|
win_x = 264.0f;
|
|
win_y = title_bar_size + font->FontSize * 3.0f
|
|
+ style.ItemSpacing.y * 3.0f + style.FramePadding.y * 2.0f;
|
|
|
|
x = (float_t)width * 0.5f - win_x * 0.5f;
|
|
y = (float_t)height * 0.5f - win_y * 0.5f;
|
|
w = win_x;
|
|
h = win_y;
|
|
|
|
window_flags = 0;
|
|
window_flags |= ImGuiWindowFlags_NoResize;
|
|
window_flags |= ImGuiWindowFlags_NoMove;
|
|
window_flags |= ImGuiWindowFlags_NoScrollbar;
|
|
window_flags |= ImGuiWindowFlags_NoScrollWithMouse;
|
|
|
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowTitleAlign, { 0.5f, 0.5f });
|
|
ImGui::SetNextWindowPos({ x, y }, ImGuiCond_Always);
|
|
ImGui::SetNextWindowSize({ w, h }, ImGuiCond_Always);
|
|
if (ImGui::BeginPopupModal("Glitter File Load Error", 0, window_flags)) {
|
|
ImGui::SetCursorPosY(title_bar_size);
|
|
ImGui::Text("Can't find name in Glitter List File\n"
|
|
"for hash in Glitter Effect File");
|
|
|
|
ImGui::SetCursorPosX(ImGui::GetContentRegionAvail().x * 0.5f - 20.0f);
|
|
|
|
x = 40.0f;
|
|
y = font->FontSize + style.FramePadding.y * 2.0f;
|
|
if (ImGui::ButtonEnterKeyPressed("OK", { x, y }))
|
|
ImGui::CloseCurrentPopup();
|
|
input_locked |= ImGui::IsWindowFocused();
|
|
ImGui::EndPopup();
|
|
}
|
|
ImGui::PopStyleVar();
|
|
}
|
|
|
|
static void glitter_editor_file_save_popup(GlitterEditor* glt_edt,
|
|
ImGuiIO& io, ImGuiStyle& style, ImFont* font, const float_t title_bar_size) {
|
|
if (glt_edt->save_popup) {
|
|
ImGui::OpenPopup("Save Glitter File as...", 0);
|
|
glt_edt->save_popup = false;
|
|
}
|
|
|
|
float_t x;
|
|
float_t y;
|
|
float_t w;
|
|
float_t h;
|
|
float_t win_x;
|
|
float_t win_y;
|
|
|
|
Glitter::EffectGroup* eg = glt_edt->effect_group;
|
|
ImGuiWindowFlags window_flags;
|
|
|
|
const float_t button_width = 70.0f;
|
|
|
|
if (eg && eg->type != Glitter::X)
|
|
win_x = button_width * 4.0f + style.ItemSpacing.x * 3.0f;
|
|
else
|
|
win_x = button_width * 3.0f + style.ItemSpacing.x * 2.0f;
|
|
win_y = title_bar_size + font->FontSize + style.ItemSpacing.y * 2.0f + style.FramePadding.y * 3.0f;
|
|
|
|
x = (float_t)width * 0.5f - win_x * 0.5f;
|
|
y = (float_t)height * 0.5f - win_y * 0.5f;
|
|
w = win_x;
|
|
h = win_y;
|
|
|
|
window_flags = 0;
|
|
window_flags |= ImGuiWindowFlags_NoResize;
|
|
window_flags |= ImGuiWindowFlags_NoMove;
|
|
window_flags |= ImGuiWindowFlags_NoScrollbar;
|
|
window_flags |= ImGuiWindowFlags_NoScrollWithMouse;
|
|
|
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowTitleAlign, { 0.5f, 0.5f });
|
|
ImGui::SetNextWindowPos({ x, y }, ImGuiCond_Always);
|
|
ImGui::SetNextWindowSize({ w, h }, ImGuiCond_Always);
|
|
if (ImGui::BeginPopupModal("Save Glitter File as...", 0, window_flags)) {
|
|
x = win_x * 0.5f - ImGui::GetContentRegionAvail().x * 0.5f;
|
|
y = title_bar_size;
|
|
|
|
ImGui::SetCursorPos({ x, y });
|
|
/*if (eg && eg->type == Glitter::X) {
|
|
if (ImGui::BeginTable("buttons", 3)) {
|
|
bool close = false;
|
|
|
|
ImGui::TableNextColumn();
|
|
if (ImGui::ButtonEnterKeyPressed("X", ImGui::GetContentRegionAvail())) {
|
|
glt_edt->save = true;
|
|
glt_edt->save_compress = false;
|
|
glt_edt->save_encrypt = false;
|
|
glt_edt->save_glt_type = Glitter::X;
|
|
close = true;
|
|
}
|
|
|
|
ImGui::TableNextColumn();
|
|
if (ImGui::ButtonEnterKeyPressed("X HD", ImGui::GetContentRegionAvail())) {
|
|
glt_edt->save = true;
|
|
glt_edt->save_compress = true;
|
|
glt_edt->save_encrypt = true;
|
|
glt_edt->save_glt_type = Glitter::X;
|
|
close = true;
|
|
}
|
|
|
|
ImGui::TableNextColumn();
|
|
if (ImGui::ButtonEnterKeyPressed("None", ImGui::GetContentRegionAvail())) {
|
|
glt_edt->save = false;
|
|
glt_edt->save_compress = false;
|
|
glt_edt->save_encrypt = false;
|
|
close = true;
|
|
}
|
|
|
|
if (close)
|
|
ImGui::CloseCurrentPopup();
|
|
ImGui::EndTable();
|
|
}
|
|
}
|
|
else*/ {
|
|
if (ImGui::BeginTable("buttons", 4)) {
|
|
bool close = false;
|
|
|
|
ImGui::TableNextColumn();
|
|
if (ImGui::ButtonEnterKeyPressed("F2 PSV", ImGui::GetContentRegionAvail())) {
|
|
glt_edt->save = true;
|
|
glt_edt->save_compress = false;
|
|
glt_edt->save_encrypt = false;
|
|
glt_edt->save_glt_type = Glitter::F2;
|
|
close = true;
|
|
}
|
|
|
|
ImGui::TableNextColumn();
|
|
if (ImGui::ButtonEnterKeyPressed("F2 PS3", ImGui::GetContentRegionAvail())) {
|
|
glt_edt->save = true;
|
|
glt_edt->save_compress = true;
|
|
glt_edt->save_encrypt = true;
|
|
glt_edt->save_glt_type = Glitter::F2;
|
|
close = true;
|
|
}
|
|
|
|
ImGui::TableNextColumn();
|
|
if (ImGui::ButtonEnterKeyPressed("FT", ImGui::GetContentRegionAvail())) {
|
|
glt_edt->save = true;
|
|
glt_edt->save_compress = false;
|
|
glt_edt->save_encrypt = false;
|
|
glt_edt->save_glt_type = Glitter::FT;
|
|
close = true;
|
|
}
|
|
|
|
ImGui::TableNextColumn();
|
|
if (ImGui::ButtonEnterKeyPressed("None", ImGui::GetContentRegionAvail())) {
|
|
glt_edt->save = false;
|
|
glt_edt->save_compress = false;
|
|
glt_edt->save_encrypt = false;
|
|
close = true;
|
|
}
|
|
|
|
if (close)
|
|
ImGui::CloseCurrentPopup();
|
|
ImGui::EndTable();
|
|
}
|
|
}
|
|
input_locked |= ImGui::IsWindowFocused();
|
|
ImGui::EndPopup();
|
|
}
|
|
ImGui::PopStyleVar();
|
|
}
|
|
|
|
inline static float_t convert_height_to_value(GlitterEditor::CurveEditor* crv_edt,
|
|
float_t val, float_t pos, float_t size, float_t min, float_t max) {
|
|
float_t t = (val - pos - crv_edt->height_offset) / (size - crv_edt->height_offset);
|
|
return (1.0f - t) * (max - min) + min;
|
|
}
|
|
inline static float_t convert_value_to_height(GlitterEditor::CurveEditor* crv_edt,
|
|
float_t val, float_t pos, float_t size, float_t min, float_t max) {
|
|
float_t t = 1.0f - (val - min) / (max - min);
|
|
return pos + t * (size - crv_edt->height_offset) + crv_edt->height_offset;
|
|
}
|
|
|
|
static void glitter_editor_curve_editor_curve_set(GlitterEditor* glt_edt,
|
|
Glitter::Curve* curve, Glitter::CurveType type) {
|
|
Glitter::EffectGroup* eg = glt_edt->effect_group;
|
|
curve->type = type;
|
|
curve->repeat = false;
|
|
curve->start_time = 0;
|
|
curve->end_time = 0;
|
|
curve->flags = (Glitter::CurveFlag)0;
|
|
curve->random_range = 0.0f;
|
|
curve->keys.clear();
|
|
#if defined(ReDIVA_DEV)
|
|
curve->keys_rev.clear();
|
|
#endif
|
|
if (eg && eg->type == Glitter::X) {
|
|
curve->version = 2;
|
|
curve->keys_version = 3;
|
|
}
|
|
else {
|
|
curve->version = 1;
|
|
curve->keys_version = 2;
|
|
}
|
|
}
|
|
|
|
static Glitter::Curve::Key* glitter_editor_curve_editor_get_closest_key(
|
|
GlitterEditor* glt_edt, Glitter::Curve* curve) {
|
|
GlitterEditor::CurveEditor* crv_edt = &glt_edt->curve_editor;
|
|
|
|
Glitter::Curve::Key* key = 0;
|
|
std::vector<Glitter::Curve::Key>* keys = &curve->keys_rev;
|
|
for (Glitter::Curve::Key& i : *keys) {
|
|
if (i.frame == crv_edt->frame)
|
|
return &i;
|
|
|
|
if (!key || (key && abs(i.frame - crv_edt->frame)
|
|
<= abs(key->frame - crv_edt->frame)))
|
|
key = &i;
|
|
}
|
|
return &key[0];
|
|
}
|
|
|
|
static Glitter::Curve::Key* glitter_editor_curve_editor_get_selected_key(
|
|
GlitterEditor* glt_edt, Glitter::Curve* curve) {
|
|
GlitterEditor::CurveEditor* crv_edt = &glt_edt->curve_editor;
|
|
|
|
std::vector<Glitter::Curve::Key>* keys = &curve->keys_rev;
|
|
for (Glitter::Curve::Key& i : *keys)
|
|
if (i.frame == crv_edt->frame)
|
|
return &i;
|
|
return 0;
|
|
}
|
|
|
|
static float_t glitter_editor_curve_editor_get_value(GlitterEditor* glt_edt, Glitter::CurveType type) {
|
|
Glitter::Emitter* sel_emit = glt_edt->selected_emitter;
|
|
Glitter::Effect* sel_efct = glt_edt->selected_effect;
|
|
Glitter::Particle* sel_ptcl = glt_edt->selected_particle;
|
|
|
|
float_t value = curve_base_values[type];
|
|
switch (glt_edt->selected_type) {
|
|
case GLITTER_EDITOR_SELECTED_EFFECT:
|
|
switch (type) {
|
|
case Glitter::CURVE_TRANSLATION_X:
|
|
value = sel_efct->translation.x;
|
|
break;
|
|
case Glitter::CURVE_TRANSLATION_Y:
|
|
value = sel_efct->translation.y;
|
|
break;
|
|
case Glitter::CURVE_TRANSLATION_Z:
|
|
value = sel_efct->translation.z;
|
|
break;
|
|
case Glitter::CURVE_ROTATION_X:
|
|
value = sel_efct->rotation.x;
|
|
break;
|
|
case Glitter::CURVE_ROTATION_Y:
|
|
value = sel_efct->rotation.y;
|
|
break;
|
|
case Glitter::CURVE_ROTATION_Z:
|
|
value = sel_efct->rotation.z;
|
|
break;
|
|
case Glitter::CURVE_SCALE_X:
|
|
value = sel_efct->scale.x;
|
|
break;
|
|
case Glitter::CURVE_SCALE_Y:
|
|
value = sel_efct->scale.y;
|
|
break;
|
|
case Glitter::CURVE_SCALE_Z:
|
|
value = sel_efct->scale.z;
|
|
break;
|
|
case Glitter::CURVE_SCALE_ALL:
|
|
break;
|
|
}
|
|
break;
|
|
case GLITTER_EDITOR_SELECTED_EMITTER:
|
|
switch (type) {
|
|
case Glitter::CURVE_TRANSLATION_X:
|
|
value = sel_emit->translation.x;
|
|
break;
|
|
case Glitter::CURVE_TRANSLATION_Y:
|
|
value = sel_emit->translation.y;
|
|
break;
|
|
case Glitter::CURVE_TRANSLATION_Z:
|
|
value = sel_emit->translation.z;
|
|
break;
|
|
case Glitter::CURVE_ROTATION_X:
|
|
value = sel_emit->rotation.x;
|
|
break;
|
|
case Glitter::CURVE_ROTATION_Y:
|
|
value = sel_emit->rotation.y;
|
|
break;
|
|
case Glitter::CURVE_ROTATION_Z:
|
|
value = sel_emit->rotation.z;
|
|
break;
|
|
case Glitter::CURVE_SCALE_X:
|
|
value = sel_emit->scale.x;
|
|
break;
|
|
case Glitter::CURVE_SCALE_Y:
|
|
value = sel_emit->scale.y;
|
|
break;
|
|
case Glitter::CURVE_SCALE_Z:
|
|
value = sel_emit->scale.z;
|
|
break;
|
|
case Glitter::CURVE_EMISSION_INTERVAL:
|
|
value = sel_emit->data.emission_interval;
|
|
break;
|
|
case Glitter::CURVE_PARTICLES_PER_EMISSION:
|
|
value = sel_emit->data.particles_per_emission;
|
|
break;
|
|
}
|
|
break;
|
|
case GLITTER_EDITOR_SELECTED_PARTICLE:
|
|
switch (type) {
|
|
case Glitter::CURVE_ROTATION_X:
|
|
value = sel_ptcl->data.rotation.x;
|
|
break;
|
|
case Glitter::CURVE_ROTATION_Y:
|
|
value = sel_ptcl->data.rotation.y;
|
|
break;
|
|
case Glitter::CURVE_ROTATION_Z:
|
|
value = sel_ptcl->data.rotation.z;
|
|
break;
|
|
case Glitter::CURVE_SCALE_X:
|
|
value = sel_ptcl->data.scale.x;
|
|
break;
|
|
case Glitter::CURVE_SCALE_Y:
|
|
value = sel_ptcl->data.scale.y;
|
|
break;
|
|
case Glitter::CURVE_SCALE_Z:
|
|
value = sel_ptcl->data.scale.z;
|
|
break;
|
|
case Glitter::CURVE_COLOR_R:
|
|
value = sel_ptcl->data.color.x;
|
|
break;
|
|
case Glitter::CURVE_COLOR_G:
|
|
value = sel_ptcl->data.color.y;
|
|
break;
|
|
case Glitter::CURVE_COLOR_B:
|
|
value = sel_ptcl->data.color.z;
|
|
break;
|
|
case Glitter::CURVE_COLOR_A:
|
|
value = sel_ptcl->data.color.w;
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
return value;
|
|
}
|
|
|
|
static void glitter_editor_curve_editor_key_manager(GlitterEditor* glt_edt,
|
|
std::vector<Glitter::Curve::Key>* keys, bool* add_key, bool* del_key) {
|
|
GlitterEditor::CurveEditor* crv_edt = &glt_edt->curve_editor;
|
|
|
|
Glitter::Curve* curve = crv_edt->list[crv_edt->type];
|
|
*add_key = true;
|
|
*del_key = false;
|
|
for (Glitter::Curve::Key& i : *keys)
|
|
if (i.frame > curve->end_time)
|
|
break;
|
|
else if (i.frame == crv_edt->frame) {
|
|
*add_key = false;
|
|
*del_key = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void glitter_editor_curve_editor_property_window(GlitterEditor* glt_edt) {
|
|
Glitter::Emitter* sel_emit = glt_edt->selected_emitter;
|
|
GlitterEditor::CurveEditor* crv_edt = &glt_edt->curve_editor;
|
|
Glitter::Particle* sel_ptcl = glt_edt->selected_particle;
|
|
|
|
crv_edt->key_edit = false;
|
|
if (crv_edt->type < Glitter::CURVE_TRANSLATION_X
|
|
|| crv_edt->type > Glitter::CURVE_V_SCROLL_ALPHA_2ND)
|
|
return;
|
|
|
|
Glitter::EffectGroup* eg = glt_edt->effect_group;
|
|
Glitter::Curve* curve = crv_edt->list[crv_edt->type];
|
|
if (!curve)
|
|
return;
|
|
|
|
const bool fix_rot_z = eg->type != Glitter::X && curve->type == Glitter::CURVE_ROTATION_Z
|
|
&& ((glt_edt->selected_type == GLITTER_EDITOR_SELECTED_EMITTER
|
|
&& sel_emit->data.direction == Glitter::DIRECTION_Z_AXIS)
|
|
|| (glt_edt->selected_type == GLITTER_EDITOR_SELECTED_PARTICLE
|
|
&& sel_ptcl->data.draw_type == Glitter::DIRECTION_Z_AXIS));
|
|
|
|
float_t scale;
|
|
float_t inv_scale;
|
|
float_t min;
|
|
float_t min_random;
|
|
|
|
if (curve->type >= Glitter::CURVE_ROTATION_X && curve->type <= Glitter::CURVE_ROTATION_Z) {
|
|
scale = RAD_TO_DEG_FLOAT;
|
|
inv_scale = DEG_TO_RAD_FLOAT;
|
|
}
|
|
else if (curve->type >= Glitter::CURVE_COLOR_R && curve->type <= Glitter::CURVE_COLOR_RGB_SCALE_2ND) {
|
|
scale = 255.0f;
|
|
inv_scale = (float_t)(1.0 / 255.0);
|
|
}
|
|
else {
|
|
scale = 1.0f;
|
|
inv_scale = 1.0f;
|
|
}
|
|
|
|
if (curve->type == Glitter::CURVE_EMISSION_INTERVAL) {
|
|
min = -1.0f;
|
|
min_random = 0.0f;
|
|
}
|
|
else if (curve->type == Glitter::CURVE_PARTICLES_PER_EMISSION) {
|
|
min = 0.0f;
|
|
min_random = 0.0f;
|
|
}
|
|
else {
|
|
min = -FLT_MAX;
|
|
min_random = -FLT_MAX;
|
|
}
|
|
|
|
bool random_range = curve->flags & Glitter::CURVE_RANDOM_RANGE ? true : false;
|
|
bool key_random_range = curve->flags & Glitter::CURVE_KEY_RANDOM_RANGE ? true : false;
|
|
|
|
bool changed = false;
|
|
bool key_edit = false;
|
|
|
|
float_t value = 0.0f;
|
|
if (curve->keys_rev.size() > 1) {
|
|
Glitter::Curve::Key* i_begin = curve->keys_rev.data();
|
|
Glitter::Curve::Key* i_end = curve->keys_rev.data() + curve->keys_rev.size();
|
|
Glitter::Curve::Key* c = i_begin;
|
|
Glitter::Curve::Key* n = c + 1;
|
|
while (n != i_end && n->frame < crv_edt->frame) {
|
|
c++;
|
|
n++;
|
|
}
|
|
|
|
if (c + 1 != i_end)
|
|
switch (c->type) {
|
|
case Glitter::KEY_CONSTANT:
|
|
value = n->frame == crv_edt->frame ? n->value : c->value;
|
|
break;
|
|
case Glitter::KEY_LINEAR:
|
|
value = Glitter::Curve::InterpolateLinear(c->value, n->value,
|
|
(float_t)c->frame, (float_t)n->frame, (float_t)crv_edt->frame);
|
|
break;
|
|
case Glitter::KEY_HERMITE:
|
|
value = Glitter::Curve::InterpolateHermite(
|
|
c->value, n->value - c->value, c->tangent2, n->tangent1,
|
|
(float_t)c->frame, (float_t)n->frame, (float_t)crv_edt->frame);
|
|
break;
|
|
}
|
|
}
|
|
else if (curve->keys_rev.size() == 1)
|
|
value = curve->keys_rev.data()[0].value;
|
|
else if (curve->type >= Glitter::CURVE_TRANSLATION_X && curve->type <= Glitter::CURVE_V_SCROLL_ALPHA_2ND)
|
|
value = glitter_editor_curve_editor_get_value(glt_edt, curve->type);
|
|
else
|
|
value = 0.0f;
|
|
|
|
value *= scale;
|
|
ImGui::Text("Frame: %d; Value: %g", crv_edt->frame, value);
|
|
|
|
if (crv_edt->key && ImGui::TreeNodeEx("Key", ImGuiTreeNodeFlags_DefaultOpen)) {
|
|
Glitter::Curve::Key* c = crv_edt->key;
|
|
Glitter::Curve::Key* n = curve->keys_rev.data() + curve->keys_rev.size()
|
|
- crv_edt->key > 1 ? &crv_edt->key[1] : 0;
|
|
if (ImGui::ColumnComboBox("Type", Glitter::key_name,
|
|
Glitter::KEY_HERMITE,
|
|
(int32_t*)&c->type, 0, true, &input_locked))
|
|
changed = true;
|
|
key_edit |= ImGui::IsItemFocused();
|
|
|
|
float_t value = c->value;
|
|
if (fix_rot_z)
|
|
value -= (float_t)M_PI_2;
|
|
value *= scale;
|
|
if (ImGui::ColumnDragFloat("Value",
|
|
&value, 0.0001f, min, FLT_MAX, "%g",
|
|
ImGuiSliderFlags_NoRoundToFormat)) {
|
|
value *= inv_scale;
|
|
if (fix_rot_z)
|
|
value += (float_t)M_PI_2;
|
|
c->value = value;
|
|
changed = true;
|
|
}
|
|
key_edit |= ImGui::IsItemFocused();
|
|
|
|
ImGui::DisableElementPush(key_random_range);
|
|
float_t random = c->random_range * scale;
|
|
if (ImGui::ColumnDragFloat("Random Range",
|
|
&random, 0.0001f, min_random, FLT_MAX, "%g",
|
|
ImGuiSliderFlags_NoRoundToFormat)) {
|
|
random *= inv_scale;
|
|
if (random != c->random_range) {
|
|
c->random_range = random;
|
|
changed = true;
|
|
}
|
|
}
|
|
key_edit |= ImGui::IsItemFocused();
|
|
ImGui::DisableElementPop(key_random_range);
|
|
|
|
if (n && c->type == Glitter::KEY_HERMITE) {
|
|
float_t tangent2 = c->tangent2 * scale;
|
|
if (ImGui::ColumnDragFloat("Tangent 1",
|
|
&tangent2, 0.0001f, -FLT_MAX, FLT_MAX, "%g",
|
|
ImGuiSliderFlags_NoRoundToFormat)) {
|
|
c->tangent2 = tangent2 * inv_scale;
|
|
changed = true;
|
|
}
|
|
key_edit |= ImGui::IsItemFocused();
|
|
|
|
float_t tangent1 = n->tangent1 * scale;
|
|
if (ImGui::ColumnDragFloat("Tangent 2",
|
|
&tangent1, 0.0001f, -FLT_MAX, FLT_MAX, "%g",
|
|
ImGuiSliderFlags_NoRoundToFormat)) {
|
|
n->tangent1 = tangent1 * inv_scale;
|
|
changed = true;
|
|
}
|
|
key_edit |= ImGui::IsItemFocused();
|
|
}
|
|
ImGui::TreePop();
|
|
}
|
|
crv_edt->key_edit = key_edit;
|
|
|
|
if (ImGui::TreeNodeEx("Curve", ImGuiTreeNodeFlags_DefaultOpen)) {
|
|
if (ImGui::CheckboxEnterKeyPressed("Repeat", &curve->repeat))
|
|
changed = true;
|
|
|
|
int32_t start_time = curve->start_time;
|
|
if (ImGui::ColumnDragInt("Start Time",
|
|
&start_time, 1, 0, 0x7FFF, "%d", 0)) {
|
|
if (curve->end_time < start_time) {
|
|
curve->end_time = start_time;
|
|
changed = true;
|
|
}
|
|
|
|
if (curve->start_time != start_time) {
|
|
curve->start_time = start_time;
|
|
changed = true;
|
|
}
|
|
}
|
|
|
|
int32_t end_time = curve->end_time;
|
|
if (ImGui::ColumnDragInt("End Time",
|
|
&end_time, 1, 0, 0x7FFF, "%d", 0)) {
|
|
if (curve->start_time > end_time)
|
|
end_time = curve->start_time;
|
|
|
|
if (curve->end_time != end_time) {
|
|
curve->end_time = end_time;
|
|
changed = true;
|
|
}
|
|
}
|
|
|
|
ImGui::DisableElementPush(random_range);
|
|
float_t random = curve->random_range * scale;
|
|
if (ImGui::ColumnDragFloat("Random Range",
|
|
&random, 0.0001f, min_random, FLT_MAX, "%g",
|
|
ImGuiSliderFlags_NoRoundToFormat)) {
|
|
random *= inv_scale;
|
|
if (random != curve->random_range) {
|
|
curve->random_range = random;
|
|
changed = true;
|
|
}
|
|
}
|
|
ImGui::DisableElementPop(random_range);
|
|
|
|
int32_t c_type = curve->version;
|
|
ImGui::Text("C Type:");
|
|
ImGui::SameLine();
|
|
ImGui::SetNextItemWidth(60.0f);
|
|
if (ImGui::InputInt("##C Type:", &c_type, 1, 1)) {
|
|
if (eg->type == Glitter::X)
|
|
c_type = clamp_def(c_type, 1, 2);
|
|
else
|
|
c_type = clamp_def(c_type, 0, 1);
|
|
|
|
if (c_type != curve->version)
|
|
changed = true;
|
|
curve->version = c_type;
|
|
}
|
|
|
|
int32_t k_type = curve->keys_version;
|
|
ImGui::SameLine();
|
|
ImGui::Text("K Type:");
|
|
ImGui::SameLine();
|
|
ImGui::SetNextItemWidth(60.0f);
|
|
if (ImGui::InputInt("##K Type:", &k_type, 1, 1)) {
|
|
if (eg->type == Glitter::X)
|
|
k_type = clamp_def(k_type, 2, 3);
|
|
else
|
|
k_type = clamp_def(k_type, 0, 2);
|
|
|
|
if (k_type != curve->keys_version)
|
|
changed = true;
|
|
curve->keys_version = k_type;
|
|
}
|
|
|
|
ImGui::Separator();
|
|
|
|
ImGui::PushID("Flags");
|
|
if (ImGui::CheckboxFlagsEnterKeyPressed("Baked",
|
|
(uint32_t*)&curve->flags,
|
|
Glitter::CURVE_BAKED))
|
|
changed = true;
|
|
|
|
if (eg->type == Glitter::X) {
|
|
ImGui::DisableElementPush(curve->flags & Glitter::CURVE_BAKED ? true : false);
|
|
if (ImGui::CheckboxFlagsEnterKeyPressed("Baked Full",
|
|
(uint32_t*)&curve->flags,
|
|
Glitter::CURVE_BAKED_FULL))
|
|
changed = true;
|
|
ImGui::DisableElementPop(curve->flags & Glitter::CURVE_BAKED ? true : false);
|
|
}
|
|
|
|
ImGui::Separator();
|
|
|
|
if (ImGui::CheckboxFlagsEnterKeyPressed("Random Range",
|
|
(uint32_t*)&curve->flags,
|
|
Glitter::CURVE_RANDOM_RANGE))
|
|
changed = true;
|
|
|
|
if (ImGui::CheckboxFlagsEnterKeyPressed("Key Random Range",
|
|
(uint32_t*)&curve->flags,
|
|
Glitter::CURVE_KEY_RANDOM_RANGE))
|
|
changed = true;
|
|
|
|
if (ImGui::CheckboxFlagsEnterKeyPressed("Random Range Negate",
|
|
(uint32_t*)&curve->flags,
|
|
Glitter::CURVE_RANDOM_RANGE_NEGATE))
|
|
changed = true;
|
|
|
|
if (ImGui::CheckboxFlagsEnterKeyPressed("Step Random",
|
|
(uint32_t*)&curve->flags,
|
|
Glitter::CURVE_STEP))
|
|
changed = true;
|
|
|
|
if (ImGui::CheckboxFlagsEnterKeyPressed("Curve Negate",
|
|
(uint32_t*)&curve->flags,
|
|
Glitter::CURVE_NEGATE))
|
|
changed = true;
|
|
|
|
if (ImGui::CheckboxFlagsEnterKeyPressed(eg->type == Glitter::FT
|
|
? "Scale Random by Value" : "Scale Random by Value * 0.01",
|
|
(uint32_t*)&curve->flags,
|
|
Glitter::CURVE_RANDOM_RANGE_MULT))
|
|
changed = true;
|
|
ImGui::PopID();
|
|
ImGui::TreePop();
|
|
}
|
|
|
|
if (crv_edt->list[crv_edt->type]) {
|
|
if (changed) {
|
|
curve->Recalculate(eg->type);
|
|
glt_edt->input_reload = true;
|
|
}
|
|
|
|
uint64_t hash1 = hash_fnv1a64m(crv_edt->list[crv_edt->type], sizeof(Glitter::Curve));
|
|
uint64_t hash2 = hash_fnv1a64m(curve, sizeof(Glitter::Effect));
|
|
if (hash1 != hash2)
|
|
*crv_edt->list[crv_edt->type] = *curve;
|
|
}
|
|
}
|
|
|
|
static void glitter_editor_curve_editor_selector_list_box_selectable(GlitterEditor* glt_edt,
|
|
const Glitter::CurveTypeFlags flags, const char* label, const Glitter::CurveType type, bool& reset) {
|
|
if (!(flags & type))
|
|
return;
|
|
|
|
GlitterEditor::CurveEditor* crv_edt = &glt_edt->curve_editor;
|
|
|
|
char buf[0x40];
|
|
sprintf_s(buf, sizeof(buf), crv_edt->list[type] ? "%s [*]" : "%s", label);
|
|
if (!ImGui::Selectable(buf, crv_edt->type == type))
|
|
return;
|
|
|
|
if (crv_edt->type != type) {
|
|
glt_edt->curve_editor.ResetState(type);
|
|
reset = true;
|
|
}
|
|
}
|
|
|
|
static void glitter_editor_curve_editor_selector_list_box_multi_selectable(GlitterEditor* glt_edt,
|
|
const Glitter::CurveTypeFlags flags, const char* label, const Glitter::CurveType type, bool& reset) {
|
|
if (!(flags & (1 << type)))
|
|
return;
|
|
|
|
GlitterEditor::CurveEditor* crv_edt = &glt_edt->curve_editor;
|
|
|
|
char buf[0x40];
|
|
sprintf_s(buf, sizeof(buf), crv_edt->type_flags & (1 << type)
|
|
? (crv_edt->list[type] ? "[V] %s [*]" : "[V] %s")
|
|
: (crv_edt->list[type] ? " %s [*]" : " %s"), label);
|
|
if (!ImGui::Selectable(buf, crv_edt->type == type))
|
|
return;
|
|
|
|
if (Input::IsKeyDown(GLFW_KEY_LEFT_CONTROL) || Input::IsKeyDown(GLFW_KEY_RIGHT_CONTROL))
|
|
glt_edt->curve_editor.SetFlag((Glitter::CurveTypeFlags)(1 << type));
|
|
else if (crv_edt->type != type) {
|
|
glt_edt->curve_editor.ResetState(type);
|
|
reset = true;
|
|
}
|
|
}
|
|
|
|
static void glitter_editor_curve_editor_selector(GlitterEditor* glt_edt) {
|
|
GlitterEditor::CurveEditor* crv_edt = &glt_edt->curve_editor;
|
|
int32_t sel_rsrc = glt_edt->selected_resource;
|
|
Glitter::Effect* sel_efct = glt_edt->selected_effect;
|
|
Glitter::Emitter* sel_emit = glt_edt->selected_emitter;
|
|
Glitter::Particle* sel_ptcl = glt_edt->selected_particle;
|
|
|
|
Glitter::EffectGroup* eg = glt_edt->effect_group;
|
|
Glitter::CurveTypeFlags flags = (Glitter::CurveTypeFlags)0;
|
|
Glitter::Animation* anim = 0;
|
|
switch (glt_edt->selected_type) {
|
|
case GLITTER_EDITOR_SELECTED_EFFECT:
|
|
flags = Glitter::effect_curve_flags;
|
|
anim = &sel_efct->animation;
|
|
break;
|
|
case GLITTER_EDITOR_SELECTED_EMITTER:
|
|
flags = Glitter::emitter_curve_flags;
|
|
anim = &sel_emit->animation;
|
|
break;
|
|
case GLITTER_EDITOR_SELECTED_PARTICLE:
|
|
if (eg->type == Glitter::X)
|
|
flags = Glitter::particle_x_curve_flags;
|
|
else
|
|
flags = Glitter::particle_curve_flags;
|
|
anim = &sel_ptcl->animation;
|
|
|
|
if (sel_ptcl->data.type != Glitter::PARTICLE_MESH) {
|
|
enum_and(flags, ~Glitter::CURVE_TYPE_UV_SCROLL_2ND);
|
|
if (sel_ptcl->data.draw_type != Glitter::DIRECTION_PARTICLE_ROTATION)
|
|
enum_and(flags, ~(Glitter::CURVE_TYPE_ROTATION_X | Glitter::CURVE_TYPE_ROTATION_Y));
|
|
}
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
crv_edt->animation = anim;
|
|
|
|
for (int32_t i = Glitter::CURVE_TRANSLATION_X; i <= Glitter::CURVE_V_SCROLL_ALPHA_2ND; i++) {
|
|
bool found = false;
|
|
std::vector<Glitter::Curve*>::iterator j;
|
|
for (j = anim->curves.begin(); j != anim->curves.end(); j++)
|
|
if (*j && (*j)->type == i) {
|
|
found = true;
|
|
break;
|
|
}
|
|
crv_edt->list[i] = found ? *j : 0;
|
|
}
|
|
|
|
bool reset = false;
|
|
ImVec2 cont_reg_avail = ImGui::GetContentRegionAvail();
|
|
if (ImGui::BeginListBox("##Curves", { cont_reg_avail.x * 0.5f, cont_reg_avail.y })) {
|
|
ImGuiTreeNodeFlags tree_node_flags = 0;
|
|
tree_node_flags |= ImGuiTreeNodeFlags_DefaultOpen;
|
|
tree_node_flags |= ImGuiTreeNodeFlags_OpenOnDoubleClick;
|
|
tree_node_flags |= ImGuiTreeNodeFlags_OpenOnArrow;
|
|
tree_node_flags |= ImGuiTreeNodeFlags_SpanAvailWidth;
|
|
|
|
if (flags & Glitter::CURVE_TYPE_TRANSLATION_XYZ
|
|
&& ImGui::TreeNodeEx("Translation", tree_node_flags)) {
|
|
ImGui::PushID("T");
|
|
glitter_editor_curve_editor_selector_list_box_multi_selectable(glt_edt, flags, "X",
|
|
Glitter::CURVE_TRANSLATION_X, reset);
|
|
glitter_editor_curve_editor_selector_list_box_multi_selectable(glt_edt, flags, "Y",
|
|
Glitter::CURVE_TRANSLATION_Y, reset);
|
|
glitter_editor_curve_editor_selector_list_box_multi_selectable(glt_edt, flags, "Z",
|
|
Glitter::CURVE_TRANSLATION_Z, reset);
|
|
ImGui::PopID();
|
|
ImGui::TreePop();
|
|
}
|
|
|
|
if (flags & Glitter::CURVE_TYPE_ROTATION_XYZ
|
|
&& ImGui::TreeNodeEx("Rotation", tree_node_flags)) {
|
|
ImGui::PushID("R");
|
|
glitter_editor_curve_editor_selector_list_box_multi_selectable(glt_edt, flags, "X",
|
|
Glitter::CURVE_ROTATION_X, reset);
|
|
glitter_editor_curve_editor_selector_list_box_multi_selectable(glt_edt, flags, "Y",
|
|
Glitter::CURVE_ROTATION_Y, reset);
|
|
glitter_editor_curve_editor_selector_list_box_multi_selectable(glt_edt, flags, "Z",
|
|
Glitter::CURVE_ROTATION_Z, reset);
|
|
ImGui::PopID();
|
|
ImGui::TreePop();
|
|
}
|
|
|
|
if (flags & (Glitter::CURVE_TYPE_SCALE_XYZ | Glitter::CURVE_TYPE_SCALE_ALL)
|
|
&& ImGui::TreeNodeEx("Scale", tree_node_flags)) {
|
|
ImGui::PushID("S");
|
|
glitter_editor_curve_editor_selector_list_box_multi_selectable(glt_edt, flags, "X",
|
|
Glitter::CURVE_SCALE_X, reset);
|
|
glitter_editor_curve_editor_selector_list_box_multi_selectable(glt_edt, flags, "Y",
|
|
Glitter::CURVE_SCALE_Y, reset);
|
|
glitter_editor_curve_editor_selector_list_box_multi_selectable(glt_edt, flags, "Z",
|
|
Glitter::CURVE_SCALE_Z, reset);
|
|
glitter_editor_curve_editor_selector_list_box_multi_selectable(glt_edt, flags, "All",
|
|
Glitter::CURVE_SCALE_ALL, reset);
|
|
ImGui::PopID();
|
|
ImGui::TreePop();
|
|
}
|
|
|
|
if (flags & (Glitter::CURVE_TYPE_COLOR_RGBA | Glitter::CURVE_TYPE_COLOR_RGB_SCALE)
|
|
&& ImGui::TreeNodeEx("Color", tree_node_flags)) {
|
|
ImGui::PushID("C");
|
|
glitter_editor_curve_editor_selector_list_box_multi_selectable(glt_edt, flags, "R",
|
|
Glitter::CURVE_COLOR_R, reset);
|
|
glitter_editor_curve_editor_selector_list_box_multi_selectable(glt_edt, flags, "G",
|
|
Glitter::CURVE_COLOR_G, reset);
|
|
glitter_editor_curve_editor_selector_list_box_multi_selectable(glt_edt, flags, "B",
|
|
Glitter::CURVE_COLOR_B, reset);
|
|
glitter_editor_curve_editor_selector_list_box_multi_selectable(glt_edt, flags, "A",
|
|
Glitter::CURVE_COLOR_A, reset);
|
|
glitter_editor_curve_editor_selector_list_box_multi_selectable(glt_edt, flags, "RGB Scale",
|
|
Glitter::CURVE_COLOR_RGB_SCALE, reset);
|
|
ImGui::PopID();
|
|
ImGui::TreePop();
|
|
}
|
|
|
|
if (flags & (Glitter::CURVE_TYPE_COLOR_RGBA_2ND | Glitter::CURVE_TYPE_COLOR_RGB_SCALE_2ND)
|
|
&& ImGui::TreeNodeEx("Color 2nd", tree_node_flags)) {
|
|
ImGui::PushID("C2");
|
|
glitter_editor_curve_editor_selector_list_box_multi_selectable(glt_edt, flags, "R",
|
|
Glitter::CURVE_COLOR_R_2ND, reset);
|
|
glitter_editor_curve_editor_selector_list_box_multi_selectable(glt_edt, flags, "G",
|
|
Glitter::CURVE_COLOR_G_2ND, reset);
|
|
glitter_editor_curve_editor_selector_list_box_multi_selectable(glt_edt, flags, "B",
|
|
Glitter::CURVE_COLOR_B_2ND, reset);
|
|
glitter_editor_curve_editor_selector_list_box_multi_selectable(glt_edt, flags, "A",
|
|
Glitter::CURVE_COLOR_A_2ND, reset);
|
|
glitter_editor_curve_editor_selector_list_box_multi_selectable(glt_edt, flags, "RGB Scale",
|
|
Glitter::CURVE_COLOR_RGB_SCALE_2ND, reset);
|
|
ImGui::PopID();
|
|
ImGui::TreePop();
|
|
}
|
|
|
|
glitter_editor_curve_editor_selector_list_box_selectable(glt_edt, flags, "Emit Interval",
|
|
Glitter::CURVE_EMISSION_INTERVAL, reset);
|
|
glitter_editor_curve_editor_selector_list_box_selectable(glt_edt, flags, "PTC Per Emit",
|
|
Glitter::CURVE_PARTICLES_PER_EMISSION, reset);
|
|
|
|
if (flags & (Glitter::CURVE_TYPE_UV_SCROLL | Glitter::CURVE_TYPE_UV_SCROLL_ALPHA)
|
|
&& ImGui::TreeNodeEx("UV Scroll", tree_node_flags)) {
|
|
ImGui::PushID("UV");
|
|
glitter_editor_curve_editor_selector_list_box_multi_selectable(glt_edt, flags, "Y",
|
|
Glitter::CURVE_U_SCROLL, reset);
|
|
glitter_editor_curve_editor_selector_list_box_multi_selectable(glt_edt, flags, "V",
|
|
Glitter::CURVE_V_SCROLL, reset);
|
|
glitter_editor_curve_editor_selector_list_box_multi_selectable(glt_edt, flags, "U Alpha",
|
|
Glitter::CURVE_U_SCROLL_ALPHA, reset);
|
|
glitter_editor_curve_editor_selector_list_box_multi_selectable(glt_edt, flags, "V Alpha",
|
|
Glitter::CURVE_V_SCROLL_ALPHA, reset);
|
|
ImGui::PopID();
|
|
ImGui::TreePop();
|
|
}
|
|
|
|
if (flags & (Glitter::CURVE_TYPE_UV_SCROLL_2ND | Glitter::CURVE_TYPE_UV_SCROLL_ALPHA_2ND)
|
|
&& ImGui::TreeNodeEx("UV Scroll 2nd", tree_node_flags)) {
|
|
ImGui::PushID("UV2");
|
|
glitter_editor_curve_editor_selector_list_box_multi_selectable(glt_edt, flags, "U",
|
|
Glitter::CURVE_U_SCROLL_2ND, reset);
|
|
glitter_editor_curve_editor_selector_list_box_multi_selectable(glt_edt, flags, "V",
|
|
Glitter::CURVE_V_SCROLL_2ND, reset);
|
|
glitter_editor_curve_editor_selector_list_box_multi_selectable(glt_edt, flags, "U Alpha",
|
|
Glitter::CURVE_U_SCROLL_ALPHA_2ND, reset);
|
|
glitter_editor_curve_editor_selector_list_box_multi_selectable(glt_edt, flags, "V Alpha",
|
|
Glitter::CURVE_V_SCROLL_ALPHA_2ND, reset);
|
|
ImGui::PopID();
|
|
ImGui::TreePop();
|
|
}
|
|
input_locked |= ImGui::IsWindowFocused();
|
|
ImGui::EndListBox();
|
|
}
|
|
|
|
if (crv_edt->type < Glitter::CURVE_TRANSLATION_X
|
|
|| crv_edt->type > Glitter::CURVE_V_SCROLL_ALPHA_2ND)
|
|
return;
|
|
|
|
Glitter::Curve* curve = crv_edt->list[crv_edt->type];
|
|
|
|
if (reset && curve)
|
|
crv_edt->key = &glitter_editor_curve_editor_get_closest_key(glt_edt, curve)[0];
|
|
|
|
ImGui::SameLine();
|
|
ImGui::BeginGroup();
|
|
ImGui::SetColumnSpace(3.0f / 7.0f);
|
|
float_t zoom_time = crv_edt->zoom_time * 100.0f;
|
|
ImGui::ColumnSliderFloatButton("Zoom Time",
|
|
&zoom_time, 1.0f, 5.0f, 500.0f, 10.0f, "%.1f%%", 0);
|
|
crv_edt->zoom_time = zoom_time * 0.01f;
|
|
|
|
int32_t zoom_value = (int32_t)prj::roundf(crv_edt->zoom_value * 100.0f);
|
|
ImGui::ColumnSliderIntButton("Zoom Value", &zoom_value, 10, 1000, "%d%%", 0);
|
|
crv_edt->zoom_value = (float_t)zoom_value * 0.01f;
|
|
|
|
ImGui::ColumnDragFloat("Range",
|
|
&crv_edt->range, 0.0001f, 0.0f, FLT_MAX, "%g", 0);
|
|
ImGui::ColumnDragFloat("Offset",
|
|
&crv_edt->offset, 0.0001f, -FLT_MAX, FLT_MAX, "%g", 0);
|
|
ImGui::SetDefaultColumnSpace();
|
|
|
|
bool add_key = false;
|
|
bool del_key = false;
|
|
if (curve)
|
|
glitter_editor_curve_editor_key_manager(glt_edt, &curve->keys_rev, &add_key, &del_key);
|
|
|
|
ImGui::Separator();
|
|
float_t w = ImGui::GetContentRegionAvailWidth();
|
|
ImGui::DisableElementPush(add_key);
|
|
if (ImGui::ButtonEnterKeyPressed("Add Key", { w, 0.0f }))
|
|
crv_edt->add_key = true;
|
|
ImGui::DisableElementPop(add_key);
|
|
|
|
ImGui::DisableElementPush(del_key);
|
|
if (ImGui::ButtonEnterKeyPressed("Delete Key", { w, 0.0f }))
|
|
crv_edt->del_key = true;
|
|
ImGui::DisableElementPop(del_key);
|
|
|
|
bool has_curve_in_list = curve ? true : false;
|
|
ImGui::DisableElementPush(!has_curve_in_list);
|
|
if (ImGui::ButtonEnterKeyPressed("Add Curve", { w, 0.0f }))
|
|
crv_edt->add_curve = true;
|
|
ImGui::DisableElementPop(!has_curve_in_list);
|
|
|
|
ImGui::DisableElementPush(has_curve_in_list);
|
|
if (ImGui::ButtonEnterKeyPressed("Delete Curve", { w, 0.0f }))
|
|
crv_edt->del_curve = true;
|
|
ImGui::DisableElementPop(has_curve_in_list);
|
|
ImGui::EndGroup();
|
|
}
|
|
|
|
static void glitter_editor_curve_editor_window(GlitterEditor* glt_edt) {
|
|
Glitter::Emitter* sel_emit = glt_edt->selected_emitter;
|
|
Glitter::Particle* sel_ptcl = glt_edt->selected_particle;
|
|
GlitterEditor::CurveEditor* crv_edt = &glt_edt->curve_editor;
|
|
|
|
if (crv_edt->type < Glitter::CURVE_TRANSLATION_X
|
|
|| crv_edt->type > Glitter::CURVE_V_SCROLL_ALPHA_2ND)
|
|
return;
|
|
|
|
switch (glt_edt->selected_type) {
|
|
case GLITTER_EDITOR_SELECTED_EFFECT:
|
|
case GLITTER_EDITOR_SELECTED_EMITTER:
|
|
case GLITTER_EDITOR_SELECTED_PARTICLE:
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
|
|
Glitter::EffectGroup* eg = glt_edt->effect_group;
|
|
Glitter::Curve* curve = crv_edt->list[crv_edt->type];
|
|
std::vector<Glitter::Curve::Key>* keys = curve ? &curve->keys_rev : 0;
|
|
bool changed = false;
|
|
|
|
bool fix_rot_z = eg->type != Glitter::X && curve && curve->type == Glitter::CURVE_ROTATION_Z
|
|
&& ((glt_edt->selected_type == GLITTER_EDITOR_SELECTED_EMITTER
|
|
&& sel_emit->data.direction == Glitter::DIRECTION_Z_AXIS)
|
|
|| (glt_edt->selected_type == GLITTER_EDITOR_SELECTED_PARTICLE
|
|
&& sel_ptcl->data.draw_type == Glitter::DIRECTION_Z_AXIS));
|
|
|
|
bool add_key = false;
|
|
bool del_key = false;
|
|
if (curve)
|
|
glitter_editor_curve_editor_key_manager(glt_edt, keys, &add_key, &del_key);
|
|
|
|
if (ImGui::IsWindowFocused()) {
|
|
if (add_key && ImGui::IsKeyPressed(ImGuiKey_Insert))
|
|
crv_edt->add_key = true;
|
|
else if (del_key && ImGui::IsKeyPressed(ImGuiKey_Delete))
|
|
crv_edt->del_key = true;
|
|
else if (ImGui::IsKeyPressed(ImGuiKey_RightArrow))
|
|
crv_edt->frame++;
|
|
else if (ImGui::IsKeyPressed(ImGuiKey_LeftArrow))
|
|
crv_edt->frame--;
|
|
|
|
if (curve)
|
|
crv_edt->frame = clamp_def(crv_edt->frame, curve->start_time, curve->end_time);
|
|
}
|
|
|
|
bool exist = true;
|
|
if (crv_edt->add_key && add_key) {
|
|
if (!crv_edt->list[crv_edt->type] || !keys || !keys->size()) {
|
|
if (!crv_edt->list[crv_edt->type]) {
|
|
Glitter::Curve* c = new Glitter::Curve(eg->type);
|
|
crv_edt->animation->curves.push_back(curve);
|
|
crv_edt->list[crv_edt->type] = c;
|
|
curve = c;
|
|
}
|
|
|
|
glitter_editor_curve_editor_curve_set(glt_edt, curve, crv_edt->type);
|
|
|
|
if (!keys)
|
|
keys = &curve->keys_rev;
|
|
|
|
Glitter::Curve::Key key;
|
|
key.frame = 0;
|
|
key.value = glitter_editor_curve_editor_get_value(glt_edt, curve->type);
|
|
keys->push_back(key);
|
|
|
|
crv_edt->frame = 0;
|
|
changed = true;
|
|
}
|
|
else {
|
|
Glitter::Curve::Key* i_begin = keys->data();
|
|
Glitter::Curve::Key* i_end = keys->data() + keys->size();
|
|
Glitter::Curve::Key* i = i_begin;
|
|
bool is_before_start = keys->data()[0].frame > crv_edt->frame;
|
|
bool has_key_after = false;
|
|
if (!is_before_start)
|
|
for (i++; i != i_end; i++)
|
|
if (crv_edt->frame <= i->frame) {
|
|
has_key_after = i_end - i > 0;
|
|
break;
|
|
}
|
|
|
|
ssize_t pos = i - i_begin;
|
|
if (!is_before_start)
|
|
pos--;
|
|
|
|
if (!is_before_start && has_key_after) {
|
|
Glitter::Curve::Key* c = i - 1;
|
|
Glitter::Curve::Key* n = i;
|
|
|
|
Glitter::Curve::Key key;
|
|
key.frame = crv_edt->frame;
|
|
key.type = c->type;
|
|
switch (c->type) {
|
|
case Glitter::KEY_CONSTANT:
|
|
key.value = c->value;
|
|
key.random_range = c->random_range;
|
|
break;
|
|
case Glitter::KEY_LINEAR: {
|
|
float_t t = (float_t)(key.frame - c->frame) / (float_t)(n->frame - c->frame);
|
|
key.value = lerp_def(c->value, n->value, t);
|
|
key.random_range = lerp_def(c->random_range, n->random_range, t);
|
|
} break;
|
|
case Glitter::KEY_HERMITE: {
|
|
int32_t df = n->frame - c->frame;
|
|
int32_t _df = key.frame - c->frame;
|
|
std::vector<float_t> v_arr = interpolate_chs(c->value, n->value, c->tangent2, n->tangent1, 0, df);
|
|
key.value = v_arr[_df];
|
|
key.random_range = lerp_def(c->random_range, n->random_range, (float_t)_df / (float_t)df);
|
|
interpolate_chs_reverse(v_arr.data(), v_arr.size(), c->tangent2, key.tangent1, 0, _df);
|
|
interpolate_chs_reverse(v_arr.data(), v_arr.size(), key.tangent2, n->tangent1, _df, df);
|
|
} break;
|
|
}
|
|
keys->insert(keys->begin() + ++pos, key);
|
|
}
|
|
else if (is_before_start) {
|
|
Glitter::Curve::Key* n = i;
|
|
|
|
Glitter::Curve::Key key;
|
|
key.frame = crv_edt->frame;
|
|
key.type = n->type;
|
|
key.value = n->value;
|
|
key.random_range = n->random_range;
|
|
keys->insert(keys->begin() + pos, key);
|
|
}
|
|
else {
|
|
Glitter::Curve::Key* c = i - 1;
|
|
|
|
Glitter::Curve::Key key;
|
|
key.frame = crv_edt->frame;
|
|
key.type = c->type;
|
|
key.value = c->value;
|
|
key.random_range = c->random_range;
|
|
keys->insert(keys->begin() + ++pos, key);
|
|
}
|
|
*crv_edt->list[crv_edt->type] = *curve;
|
|
changed = true;
|
|
}
|
|
}
|
|
else if (keys && crv_edt->del_key && del_key) {
|
|
Glitter::Curve::Key* i_begin = keys->data();
|
|
Glitter::Curve::Key* i_end = keys->data() + keys->size();
|
|
for (Glitter::Curve::Key* i = i_begin; i != i_end; i++)
|
|
if (&i[0] == crv_edt->key) {
|
|
bool has_key_before = keys->front().frame < i->frame;
|
|
bool has_key_after = keys->back().frame > i->frame;
|
|
if (has_key_before && i[-1].type == Glitter::KEY_HERMITE && has_key_after) {
|
|
Glitter::Curve::Key* c = i - 1;
|
|
Glitter::Curve::Key* n = i + 1;
|
|
int32_t df_c = i->frame - c->frame;
|
|
int32_t df_n = n->frame - i->frame;
|
|
|
|
std::vector<float_t> v_arr_c = interpolate_chs(c->value,
|
|
i->value, c->tangent2, i->tangent1, 0, df_c);
|
|
|
|
std::vector<float_t> v_arr_n = i->type == Glitter::KEY_HERMITE
|
|
? interpolate_chs(i->value, n->value, i->tangent2, n->tangent1, 0, df_n)
|
|
: interpolate_linear(i->value, n->value, 0, df_n);
|
|
|
|
size_t v_length = v_arr_c.size() + v_arr_n.size() - 1;
|
|
float_t* v_arr = new float_t[v_length];
|
|
memmove(v_arr, v_arr_c.data(), (v_arr_c.size() - 1) * sizeof(float_t));
|
|
memmove(v_arr + (v_arr_c.size() - 1), v_arr_n.data(), v_arr_n.size() * sizeof(float_t));
|
|
interpolate_chs_reverse(v_arr, v_length, c->tangent2,
|
|
n->tangent1, 0, (size_t)n->frame - c->frame);
|
|
delete[] v_arr;
|
|
}
|
|
keys->erase(keys->begin() + (i - i_begin));
|
|
changed = true;
|
|
break;
|
|
}
|
|
}
|
|
else if (crv_edt->add_curve) {
|
|
Glitter::Curve* c = new Glitter::Curve(eg->type);
|
|
crv_edt->animation->curves.push_back(c);
|
|
crv_edt->list[crv_edt->type] = c;
|
|
curve = c;
|
|
|
|
glitter_editor_curve_editor_curve_set(glt_edt, curve, crv_edt->type);
|
|
*crv_edt->list[crv_edt->type] = *curve;
|
|
crv_edt->frame = curve->start_time;
|
|
changed = true;
|
|
}
|
|
else if (crv_edt->del_curve) {
|
|
Glitter::Curve* c = crv_edt->list[crv_edt->type];
|
|
Glitter::Animation* anim = crv_edt->animation;
|
|
for (std::vector<Glitter::Curve*>::iterator i = anim->curves.begin(); i != anim->curves.end(); i++)
|
|
if (*i && *i == c) {
|
|
delete* i;
|
|
anim->curves.erase(i);
|
|
break;
|
|
}
|
|
|
|
crv_edt->list[crv_edt->type] = 0;
|
|
crv_edt->frame = 0;
|
|
changed = true;
|
|
}
|
|
crv_edt->add_key = false;
|
|
crv_edt->del_key = false;
|
|
crv_edt->add_curve = false;
|
|
crv_edt->del_curve = false;
|
|
|
|
if (!curve || !keys)
|
|
return;
|
|
|
|
int32_t start_time = curve->start_time;
|
|
int32_t end_time = curve->end_time;
|
|
|
|
ImGuiIO& io = ImGui::GetIO();
|
|
ImGuiStyle& style = ImGui::GetStyle();
|
|
ImFont* font = ImGui::GetFont();
|
|
|
|
ImVec2 cont_reg_avail = ImGui::GetContentRegionAvail();
|
|
|
|
ImVec2 canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max;
|
|
ImDrawList* draw_list = ImGui::GetWindowDrawList();
|
|
crv_edt->draw_list = draw_list;
|
|
canvas_size = cont_reg_avail;
|
|
canvas_pos = ImGui::GetCursorScreenPos();
|
|
canvas_pos_min.x = canvas_pos.x;
|
|
canvas_pos_min.y = canvas_pos.y;
|
|
canvas_pos_max.x = canvas_pos.x + canvas_size.x;
|
|
canvas_pos_max.y = canvas_pos.y + canvas_size.y;
|
|
|
|
ImRect boundaries;
|
|
boundaries.Min = canvas_pos;
|
|
boundaries.Max.x = canvas_pos.x + canvas_size.x;
|
|
boundaries.Max.y = canvas_pos.y + canvas_size.y;
|
|
|
|
if (crv_edt->zoom_time != crv_edt->prev_zoom_time) {
|
|
float_t timeline_pos = crv_edt->timeline_pos + curve_editor_timeline_base_pos;
|
|
timeline_pos *= crv_edt->zoom_time / crv_edt->prev_zoom_time;
|
|
crv_edt->timeline_pos = timeline_pos - curve_editor_timeline_base_pos;
|
|
}
|
|
crv_edt->prev_zoom_time = crv_edt->zoom_time;
|
|
|
|
float_t frame_width = crv_edt->frame_width * crv_edt->zoom_time;
|
|
canvas_pos.x -= crv_edt->timeline_pos;
|
|
|
|
ImGui::ItemSize(boundaries);
|
|
bool hovered = ImGui::IsMouseHoveringRect(boundaries.Min, boundaries.Max);
|
|
ImGui::RenderFrame(boundaries.Min, boundaries.Max, ImGui::GetColorU32(ImGuiCol_FrameBg), true, 1.0f);
|
|
|
|
static bool can_drag;
|
|
if (hovered && ImGui::IsMouseClicked(ImGuiMouseButton_Left, false))
|
|
can_drag = true;
|
|
|
|
if (can_drag && (ImGui::IsKeyDown(ImGuiKey_LeftShift) || ImGui::IsKeyDown(ImGuiKey_RightShift))) {
|
|
crv_edt->key = glitter_editor_curve_editor_get_closest_key(glt_edt, curve);
|
|
crv_edt->frame = crv_edt->key->frame;
|
|
}
|
|
else
|
|
crv_edt->key = glitter_editor_curve_editor_get_selected_key(glt_edt, curve);
|
|
|
|
if (can_drag && ImGui::IsMouseReleased(ImGuiMouseButton_Left))
|
|
can_drag = false;
|
|
|
|
float_t timeline_max_offset = (end_time - start_time) * frame_width;
|
|
timeline_max_offset = max_def(timeline_max_offset, 0.0f) - curve_editor_timeline_base_pos;
|
|
|
|
draw_list->PushClipRect(boundaries.Min, boundaries.Max, true);
|
|
|
|
const int32_t graph_start = start_time + (int32_t)((crv_edt->timeline_pos
|
|
+ frame_width - 1.0f) / frame_width);
|
|
const int32_t graph_end = start_time + (int32_t)((crv_edt->timeline_pos + canvas_size.x
|
|
+ frame_width - 1.0f) / frame_width);
|
|
|
|
const ImU32 line_color_valid_bold = ImGui::GetColorU32({ 0.5f, 0.5f, 0.5f, 0.75f });
|
|
const ImU32 line_color_valid = ImGui::GetColorU32({ 0.4f, 0.4f, 0.4f, 0.45f });
|
|
const ImU32 line_color_not_valid_bold = ImGui::GetColorU32({ 0.3f, 0.3f, 0.3f, 0.75f });
|
|
const ImU32 line_color_not_valid = ImGui::GetColorU32({ 0.2f, 0.2f, 0.2f, 0.45f });
|
|
|
|
for (int32_t frame = graph_start; frame <= graph_end; frame++) {
|
|
if (frame < start_time)
|
|
continue;
|
|
|
|
int32_t f = frame - start_time;
|
|
float_t x = canvas_pos.x + f * frame_width;
|
|
float_t y = canvas_pos.y + (f % 2 ? 10.0f : 0.0f) + canvas_size.y;
|
|
|
|
bool bold_frame = !(f % 10) || !f || frame == end_time;
|
|
bool valid_frame = f >= 0 && frame <= end_time;
|
|
|
|
ImU32 line_color = bold_frame
|
|
? (valid_frame ? line_color_valid_bold : line_color_not_valid_bold)
|
|
: (valid_frame ? line_color_valid : line_color_not_valid );
|
|
draw_list->AddLine({ x, y - canvas_size.y },
|
|
{ x, y }, line_color, 0.80f);
|
|
|
|
if (bold_frame) {
|
|
char buf[0x20];
|
|
snprintf(buf, sizeof(buf), "%d", frame);
|
|
draw_list->AddText({ x + 3, canvas_pos.y }, line_color, buf);
|
|
}
|
|
}
|
|
|
|
float_t scale;
|
|
if (curve->type >= Glitter::CURVE_ROTATION_X && curve->type <= Glitter::CURVE_ROTATION_Z)
|
|
scale = RAD_TO_DEG_FLOAT;
|
|
else if (curve->type >= Glitter::CURVE_COLOR_R && curve->type <= Glitter::CURVE_COLOR_RGB_SCALE_2ND)
|
|
scale = 255.0f;
|
|
else
|
|
scale = 1.0f;
|
|
|
|
float_t max = crv_edt->range * (1.0f / crv_edt->zoom_value);
|
|
float_t min;
|
|
if (curve->type == Glitter::CURVE_EMISSION_INTERVAL) {
|
|
min = -1.0f;
|
|
if (crv_edt->offset > 0.0f) {
|
|
min += crv_edt->offset * (1.0f / crv_edt->zoom_value);
|
|
max += crv_edt->offset * (1.0f / crv_edt->zoom_value);
|
|
}
|
|
}
|
|
else if (curve->type == Glitter::CURVE_PARTICLES_PER_EMISSION) {
|
|
min = 0.0f;
|
|
if (crv_edt->offset > 0.0f) {
|
|
min += crv_edt->offset * (1.0f / crv_edt->zoom_value);
|
|
max += crv_edt->offset * (1.0f / crv_edt->zoom_value);
|
|
}
|
|
}
|
|
else {
|
|
min = -max;
|
|
min += crv_edt->offset * (1.0f / crv_edt->zoom_value);
|
|
max += crv_edt->offset * (1.0f / crv_edt->zoom_value);
|
|
}
|
|
|
|
if (curve->type >= Glitter::CURVE_ROTATION_X && curve->type <= Glitter::CURVE_ROTATION_Z) {
|
|
max *= DEG_TO_RAD_FLOAT;
|
|
min *= DEG_TO_RAD_FLOAT;
|
|
}
|
|
else if (curve->type >= Glitter::CURVE_COLOR_R && curve->type <= Glitter::CURVE_COLOR_RGB_SCALE_2ND) {
|
|
max *= (float_t)(1.0 / 255.0);
|
|
min *= (float_t)(1.0 / 255.0);
|
|
}
|
|
|
|
float_t base_line = convert_value_to_height(crv_edt, 0.0f, canvas_pos.y, canvas_size.y, min, max);
|
|
|
|
ImVec2 p1, p2, p3;
|
|
p1.x = canvas_pos_min.x;
|
|
p1.y = canvas_pos.y + crv_edt->height_offset;
|
|
p2.x = p1.x + canvas_size.x;
|
|
p2.y = canvas_pos.y + crv_edt->height_offset;
|
|
p3.x = canvas_pos_min.x;
|
|
p3.y = canvas_pos.y;
|
|
draw_list->AddLine(p1, p2,
|
|
ImGui::GetColorU32({ 0.5f, 0.5f, 0.5f, 0.85f }), 2.0f);
|
|
|
|
const ImU32 red_color = ImGui::GetColorU32({ 1.0f, 0.0f, 0.0f, 1.00f });
|
|
const ImU32 green_color = ImGui::GetColorU32({ 0.0f, 1.0f, 0.0f, 1.00f });
|
|
const ImU32 blue_color = ImGui::GetColorU32({ 0.0f, 0.0f, 1.0f, 1.00f });
|
|
const ImU32 white_color = ImGui::GetColorU32({ 1.0f, 1.0f, 1.0f, 1.00f });
|
|
const ImU32 nwhite_color = ImGui::GetColorU32({ 1.0f, 1.0f, 1.0f, 0.75f });
|
|
const ImU32 red_bcolor = ImGui::GetColorU32({ 1.0f, 0.0f, 0.0f, 0.50f });
|
|
const ImU32 green_bcolor = ImGui::GetColorU32({ 0.0f, 1.0f, 0.0f, 0.50f });
|
|
const ImU32 blue_bcolor = ImGui::GetColorU32({ 0.0f, 0.0f, 1.0f, 0.50f });
|
|
const ImU32 white_bcolor = ImGui::GetColorU32({ 1.0f, 1.0f, 1.0f, 0.50f });
|
|
const ImU32 nwhite_bcolor = ImGui::GetColorU32({ 1.0f, 1.0f, 1.0f, 0.25f });
|
|
|
|
const ImU32 default_color = ImGui::GetColorU32({ 1.0f, 1.0f, 1.0f, 1.0f });
|
|
const ImU32 selected_color = ImGui::GetColorU32({ 0.0f, 1.0f, 1.0f, 1.0f });
|
|
|
|
switch (crv_edt->type) {
|
|
case Glitter::CURVE_TRANSLATION_X:
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_TRANSLATION_Y, green_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_TRANSLATION_Z, blue_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_TRANSLATION_X, red_color , true,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
break;
|
|
case Glitter::CURVE_TRANSLATION_Y:
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_TRANSLATION_X, red_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_TRANSLATION_Z, blue_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_TRANSLATION_Y, green_color , true,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
break;
|
|
case Glitter::CURVE_TRANSLATION_Z:
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_TRANSLATION_X, red_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_TRANSLATION_Y, green_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_TRANSLATION_Z, blue_color , true,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
|
|
break;
|
|
case Glitter::CURVE_ROTATION_X:
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_ROTATION_Y, green_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_ROTATION_Z, blue_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_ROTATION_X, red_color , true,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
break;
|
|
case Glitter::CURVE_ROTATION_Y:
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_ROTATION_X, red_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_ROTATION_Z, blue_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_ROTATION_Y, green_color , true,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
break;
|
|
case Glitter::CURVE_ROTATION_Z:
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_ROTATION_X, red_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_ROTATION_Y, green_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_ROTATION_Z, blue_color , true,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
break;
|
|
case Glitter::CURVE_SCALE_X:
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_SCALE_Y , green_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_SCALE_Z , blue_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_SCALE_ALL, nwhite_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_SCALE_X , red_color , true,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
break;
|
|
case Glitter::CURVE_SCALE_Y:
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_SCALE_X , red_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_SCALE_Z , blue_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_SCALE_ALL, nwhite_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_SCALE_Y , green_color , true,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
break;
|
|
case Glitter::CURVE_SCALE_Z:
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_SCALE_X , red_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_SCALE_Y , green_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_SCALE_ALL, nwhite_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_SCALE_Z , blue_color , true,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
break;
|
|
case Glitter::CURVE_SCALE_ALL:
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_SCALE_X , red_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_SCALE_Y , green_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_SCALE_Z , blue_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_SCALE_ALL, nwhite_color , true,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
break;
|
|
case Glitter::CURVE_COLOR_R:
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_COLOR_G , blue_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_COLOR_B , green_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_COLOR_A , white_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_COLOR_RGB_SCALE, nwhite_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_COLOR_R , red_color , true,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
break;
|
|
case Glitter::CURVE_COLOR_G:
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_COLOR_R , red_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_COLOR_B , green_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_COLOR_A , white_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_COLOR_RGB_SCALE, nwhite_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_COLOR_G , blue_color , true,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
break;
|
|
case Glitter::CURVE_COLOR_B:
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_COLOR_R , red_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_COLOR_G , blue_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_COLOR_A , white_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_COLOR_RGB_SCALE, nwhite_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_COLOR_B , green_color , true,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
break;
|
|
case Glitter::CURVE_COLOR_A:
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_COLOR_R , red_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_COLOR_G , blue_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_COLOR_B , green_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_COLOR_RGB_SCALE, nwhite_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_COLOR_A , white_color , true,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
break;
|
|
case Glitter::CURVE_COLOR_RGB_SCALE:
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_COLOR_R , red_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_COLOR_G , blue_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_COLOR_B , green_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_COLOR_A , white_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_COLOR_RGB_SCALE, nwhite_color , true,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
break;
|
|
case Glitter::CURVE_COLOR_R_2ND:
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_COLOR_G_2ND , blue_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_COLOR_B_2ND , green_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_COLOR_A_2ND , white_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_COLOR_RGB_SCALE_2ND, nwhite_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_COLOR_R_2ND , red_color , true,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
|
|
break;
|
|
case Glitter::CURVE_COLOR_G_2ND:
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_COLOR_R_2ND , red_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_COLOR_B_2ND , green_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_COLOR_A_2ND , white_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_COLOR_RGB_SCALE_2ND, nwhite_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_COLOR_G_2ND , blue_color , true,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
break;
|
|
case Glitter::CURVE_COLOR_B_2ND:
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_COLOR_R_2ND , red_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_COLOR_G_2ND , blue_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_COLOR_A_2ND , white_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_COLOR_RGB_SCALE_2ND, nwhite_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_COLOR_B_2ND , green_color , true,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
break;
|
|
case Glitter::CURVE_COLOR_A_2ND:
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_COLOR_R_2ND , red_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_COLOR_G_2ND , blue_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_COLOR_B_2ND , green_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_COLOR_RGB_SCALE_2ND, nwhite_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_COLOR_A_2ND , white_color , true,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
break;
|
|
case Glitter::CURVE_COLOR_RGB_SCALE_2ND:
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_COLOR_R_2ND , red_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_COLOR_G_2ND , blue_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_COLOR_B_2ND , green_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_COLOR_A_2ND , white_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_COLOR_RGB_SCALE_2ND, nwhite_color , true,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
break;
|
|
case Glitter::CURVE_U_SCROLL:
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_V_SCROLL, green_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_U_SCROLL, red_color , true,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
break;
|
|
case Glitter::CURVE_V_SCROLL:
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_U_SCROLL, red_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_V_SCROLL, green_color , true,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
break;
|
|
case Glitter::CURVE_U_SCROLL_ALPHA:
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_V_SCROLL_ALPHA, green_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_U_SCROLL_ALPHA, red_color , true,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
break;
|
|
case Glitter::CURVE_V_SCROLL_ALPHA:
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_U_SCROLL_ALPHA, red_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_V_SCROLL_ALPHA, green_color , true,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
break;
|
|
case Glitter::CURVE_U_SCROLL_2ND:
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_V_SCROLL, green_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_U_SCROLL, red_color , true,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
break;
|
|
case Glitter::CURVE_V_SCROLL_2ND:
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_U_SCROLL_2ND, red_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_V_SCROLL_2ND, green_color , true,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
break;
|
|
case Glitter::CURVE_U_SCROLL_ALPHA_2ND:
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_V_SCROLL_ALPHA_2ND, green_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_U_SCROLL_ALPHA_2ND, red_color , true,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
break;
|
|
case Glitter::CURVE_V_SCROLL_ALPHA_2ND:
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_V_SCROLL_ALPHA_2ND, green_bcolor, false,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, Glitter::CURVE_U_SCROLL_ALPHA_2ND, red_color , true,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
break;
|
|
default:
|
|
glitter_editor_curve_editor_window_draw(glt_edt, curve, default_color, true,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
break;
|
|
}
|
|
|
|
for (int32_t j = 0; j < 5; j++) {
|
|
float_t x_pos = canvas_pos_min.x;
|
|
float_t y_pos = canvas_pos.y + j * 0.25f * (canvas_size.y
|
|
- crv_edt->height_offset) + crv_edt->height_offset;
|
|
|
|
ImU32 line_color = j % 2 == 1
|
|
? ImGui::GetColorU32({ 0.35f, 0.35f, 0.35f, 0.45f })
|
|
: ImGui::GetColorU32({ 0.45f, 0.45f, 0.45f, 0.75f });
|
|
bool last = j == 4;
|
|
if (j && !last)
|
|
draw_list->AddLine({ x_pos, y_pos },
|
|
{ x_pos + canvas_size.x, y_pos }, line_color, 0.80f);
|
|
|
|
float_t val = (max - j * 0.25f * (max - min)) * scale;
|
|
char buf[0x20];
|
|
snprintf(buf, sizeof(buf), "%.2f", val);
|
|
draw_list->AddText({ x_pos + 2, y_pos + (last ? -16 : -2) },
|
|
ImGui::GetColorU32({ 0.65f, 0.65f, 0.65f, 0.85f }), buf);
|
|
}
|
|
|
|
const ImU32 key_constant_color = ImGui::GetColorU32({ 1.0f, 0.0f, 0.0f, 1.0f });
|
|
const ImU32 key_linear_color = ImGui::GetColorU32({ 0.0f, 1.0f, 0.0f, 1.0f });
|
|
const ImU32 key_hermite_color = ImGui::GetColorU32({ 0.0f, 0.0f, 1.0f, 1.0f });
|
|
|
|
bool dragged = false;
|
|
bool holding_tan = false;
|
|
Glitter::Curve::Key* i_begin = keys->data();
|
|
Glitter::Curve::Key* i_end = keys->data() + keys->size();
|
|
for (Glitter::Curve::Key* i = i_begin; i != i_end; i++) {
|
|
if (i->frame < graph_start)
|
|
continue;
|
|
else if (i->frame > graph_end)
|
|
break;
|
|
|
|
float_t base_value = i->value;
|
|
if (fix_rot_z)
|
|
base_value -= (float_t)M_PI_2;
|
|
float_t x = canvas_pos.x + ((size_t)i->frame - start_time) * frame_width;
|
|
float_t y = convert_value_to_height(crv_edt, base_value, canvas_pos.y, canvas_size.y, min, max);
|
|
|
|
if (!(x >= p3.x - 10.0f && x <= p3.x + canvas_size.x + 10.0f)
|
|
|| !(y >= p3.y - 10.0f && y <= p3.y + canvas_size.y + 10.0f))
|
|
continue;
|
|
|
|
ImU32 value_color;
|
|
switch (i->type) {
|
|
case Glitter::KEY_CONSTANT:
|
|
value_color = key_constant_color;
|
|
break;
|
|
case Glitter::KEY_LINEAR:
|
|
default:
|
|
value_color = key_linear_color;
|
|
break;
|
|
case Glitter::KEY_HERMITE:
|
|
value_color = key_hermite_color;
|
|
break;
|
|
}
|
|
|
|
ImGui::PushID(i);
|
|
ImGui::SetCursorScreenPos({ x - 7.5f, y - 7.5f });
|
|
ImGui::InvisibleButton("val", { 15.0f, 15.0f }, 0);
|
|
|
|
if (can_drag && ImGui::IsItemActive()
|
|
&& ImGui::IsMouseDragging(ImGuiMouseButton_Left, -1.0f)) {
|
|
float_t old_y = y;
|
|
|
|
static int32_t base_frame;
|
|
static float_t base_y;
|
|
if ((ImGui::IsKeyPressed(ImGuiKey_LeftShift, false) && !ImGui::IsKeyDown(ImGuiKey_RightShift))
|
|
|| (ImGui::IsKeyPressed(ImGuiKey_RightShift, false) && !ImGui::IsKeyDown(ImGuiKey_LeftShift))) {
|
|
base_frame = i->frame;
|
|
base_y = base_value;
|
|
}
|
|
|
|
if (i->frame >= start_time && i->frame <= end_time) {
|
|
int32_t start = i - i_begin > 0 ? (i - 1)->frame + 1 : start_time;
|
|
int32_t end = i_end - i > 1 ? (i + 1)->frame - 1 : end_time;
|
|
crv_edt->frame = (int32_t)prj::roundf((io.MousePos.x - canvas_pos.x) / frame_width);
|
|
crv_edt->frame = clamp_def(crv_edt->frame + start_time, start, end);
|
|
if (i->frame != crv_edt->frame) {
|
|
i->frame = crv_edt->frame;
|
|
changed = true;
|
|
}
|
|
}
|
|
|
|
static float_t mouse_delta_history;
|
|
if ((ImGui::IsKeyPressed(ImGuiKey_LeftShift, false) && !ImGui::IsKeyDown(ImGuiKey_RightShift))
|
|
|| (ImGui::IsKeyPressed(ImGuiKey_RightShift, false) && !ImGui::IsKeyDown(ImGuiKey_LeftShift)))
|
|
mouse_delta_history = io.MouseDelta.y;
|
|
else if ((ImGui::IsKeyReleased(ImGuiKey_LeftShift) && !ImGui::IsKeyDown(ImGuiKey_RightShift))
|
|
|| ImGui::IsKeyReleased(ImGuiKey_RightShift) && !ImGui::IsKeyDown(ImGuiKey_LeftShift)) {
|
|
y += mouse_delta_history;
|
|
y += io.MouseDelta.y;
|
|
}
|
|
else if (ImGui::IsKeyDown(ImGuiKey_LeftShift) || ImGui::IsKeyDown(ImGuiKey_RightShift))
|
|
mouse_delta_history += io.MouseDelta.y;
|
|
else
|
|
y += io.MouseDelta.y;
|
|
|
|
if (old_y != y) {
|
|
float_t value = convert_height_to_value(crv_edt,
|
|
y, canvas_pos.y, canvas_size.y, min, max);
|
|
dragged = true;
|
|
|
|
if (base_value != value) {
|
|
if (fix_rot_z)
|
|
value += (float_t)M_PI_2;
|
|
i->value = value;
|
|
changed = true;
|
|
}
|
|
crv_edt->key = &i[0];
|
|
}
|
|
}
|
|
|
|
if (i - i_begin > 0 && (i - 1)->type == Glitter::KEY_HERMITE) {
|
|
ImU32 tangent1_color;
|
|
float_t tangent1;
|
|
ImVec2 circle_pos;
|
|
circle_pos.x = x - 25.0f;
|
|
circle_pos.y = y - base_line + convert_value_to_height(crv_edt, tangent1 = i->tangent1,
|
|
canvas_pos.y, canvas_size.y, min, max);
|
|
draw_list->AddLine({ x, y }, circle_pos, default_color, 1.5f);
|
|
|
|
if ((circle_pos.x >= p3.x - 10.0f && circle_pos.x <= p3.x + canvas_size.x + 10.0f)
|
|
&& (circle_pos.y >= p3.y - 10.0f && circle_pos.y <= p3.y + canvas_size.y + 10.0f)) {
|
|
ImGui::SetCursorScreenPos({ circle_pos.x - 7.5f, circle_pos.y - 7.5f });
|
|
ImGui::InvisibleButton("tan1", { 15.0f, 15.0f }, 0);
|
|
|
|
if (can_drag && ImGui::IsItemActive()) {
|
|
if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) {
|
|
i->tangent1 = convert_height_to_value(crv_edt,
|
|
circle_pos.y + io.MouseDelta.y - y + base_line,
|
|
canvas_pos.y, canvas_size.y, min, max);
|
|
|
|
if (i->tangent1 != tangent1)
|
|
changed = true;
|
|
}
|
|
holding_tan = true;
|
|
tangent1_color = selected_color;
|
|
}
|
|
else
|
|
tangent1_color = default_color;
|
|
|
|
draw_list->AddCircleFilled(circle_pos,
|
|
crv_edt->key_radius_in, tangent1_color, 12);
|
|
}
|
|
}
|
|
|
|
if (i_end - i > 1 && i->type == Glitter::KEY_HERMITE) {
|
|
ImU32 tangent2_color;
|
|
float_t tangent2;
|
|
ImVec2 circle_pos;
|
|
circle_pos.x = x + 25.0f;
|
|
circle_pos.y = y - base_line + convert_value_to_height(crv_edt, tangent2 = i->tangent2,
|
|
canvas_pos.y, canvas_size.y, min, max);
|
|
draw_list->AddLine({ x, y }, circle_pos, default_color, 1.5f);
|
|
|
|
if ((circle_pos.x >= p3.x - 10.0f && circle_pos.x <= p3.x + canvas_size.x + 10.0f)
|
|
&& (circle_pos.y >= p3.y - 10.0f && circle_pos.y <= p3.y + canvas_size.y + 10.0f)) {
|
|
ImGui::SetCursorScreenPos({ circle_pos.x - 7.5f, circle_pos.y - 7.5f });
|
|
ImGui::InvisibleButton("tan2", { 15.0f, 15.0f }, 0);
|
|
|
|
if (can_drag && ImGui::IsItemActive()) {
|
|
if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) {
|
|
i->tangent2 = convert_height_to_value(crv_edt,
|
|
circle_pos.y + io.MouseDelta.y - y + base_line,
|
|
canvas_pos.y, canvas_size.y, min, max);
|
|
|
|
if (i->tangent2 != tangent2)
|
|
changed = true;
|
|
}
|
|
holding_tan = true;
|
|
tangent2_color = selected_color;
|
|
}
|
|
else
|
|
tangent2_color = default_color;
|
|
|
|
draw_list->AddCircleFilled(circle_pos,
|
|
crv_edt->key_radius_in, tangent2_color, 12);
|
|
}
|
|
}
|
|
|
|
draw_list->AddCircleFilled({ x, y },
|
|
crv_edt->key_radius_out, crv_edt->key == &i[0] ? selected_color : default_color, 12);
|
|
draw_list->AddCircleFilled({ x, y },
|
|
crv_edt->key_radius_in, value_color, 12);
|
|
ImGui::PopID();
|
|
}
|
|
|
|
if (!crv_edt->key_edit && can_drag && ImGui::IsMouseDown(ImGuiMouseButton_Left) && (!holding_tan || dragged)) {
|
|
int32_t frame = (int32_t)prj::roundf((io.MousePos.x - canvas_pos.x) / frame_width);
|
|
crv_edt->frame = clamp_def(frame + start_time, start_time, end_time);
|
|
if (ImGui::IsKeyDown(ImGuiKey_LeftShift) || ImGui::IsKeyDown(ImGuiKey_RightShift)) {
|
|
crv_edt->key = glitter_editor_curve_editor_get_closest_key(glt_edt, curve);
|
|
crv_edt->frame = crv_edt->key->frame;
|
|
}
|
|
else
|
|
crv_edt->key = glitter_editor_curve_editor_get_selected_key(glt_edt, curve);
|
|
}
|
|
crv_edt->frame = clamp_def(crv_edt->frame, start_time, end_time);
|
|
|
|
int32_t cursor_frame = crv_edt->frame - start_time;
|
|
ImVec2 cursor_pos = canvas_pos;
|
|
cursor_pos.x += cursor_frame * frame_width;
|
|
if (cursor_pos.x >= p1.x - 10.0f && cursor_pos.x <= p1.x + canvas_size.x + 10.0f) {
|
|
ImU32 cursor_color = ImGui::GetColorU32({ 0.8f, 0.8f, 0.8f, 0.75f });
|
|
p1.x = cursor_pos.x;
|
|
p1.y = canvas_pos.y + canvas_size.y;
|
|
draw_list->AddLine(cursor_pos, p1, cursor_color, 2.5f);
|
|
|
|
p1 = p2 = p3 = cursor_pos;
|
|
p1.x -= 10.0f;
|
|
p2.y += 10.0f;
|
|
p3.x += 10.0f;
|
|
draw_list->AddTriangleFilled(p1, p2, p3, cursor_color);
|
|
}
|
|
draw_list->PopClipRect();
|
|
|
|
if (hovered)
|
|
if (ImGui::IsKeyDown(ImGuiKey_LeftShift) || ImGui::IsKeyDown(ImGuiKey_RightShift))
|
|
crv_edt->timeline_pos -= io.MouseWheel * 25.0f * 4.0f;
|
|
else
|
|
crv_edt->timeline_pos -= io.MouseWheel * 25.0f;
|
|
|
|
crv_edt->timeline_pos = clamp_def(crv_edt->timeline_pos,
|
|
-curve_editor_timeline_base_pos, timeline_max_offset);
|
|
|
|
if (crv_edt->list[crv_edt->type] && changed) {
|
|
curve->Recalculate(eg->type);
|
|
*crv_edt->list[crv_edt->type] = *curve;
|
|
glt_edt->input_reload = true;
|
|
}
|
|
}
|
|
|
|
inline static void glitter_editor_curve_editor_window_draw(GlitterEditor* glt_edt, const Glitter::CurveType type,
|
|
const ImU32 line_color, const bool line_front, const float_t min, const float_t max,
|
|
const ImVec2 canvas_size, const ImVec2 canvas_pos, const ImVec2 canvas_pos_min, const ImVec2 canvas_pos_max,
|
|
const bool fix_rot_z) {
|
|
GlitterEditor::CurveEditor* crv_edt = &glt_edt->curve_editor;
|
|
if (!(crv_edt->type_flags & (1 << type)) || !crv_edt->list[type])
|
|
return;
|
|
|
|
glitter_editor_curve_editor_window_draw(glt_edt, crv_edt->list[type], line_color, line_front,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max, fix_rot_z);
|
|
}
|
|
|
|
static void glitter_editor_curve_editor_window_draw(GlitterEditor* glt_edt, const Glitter::Curve* curve,
|
|
const ImU32 line_color, const bool line_front, const float_t min, const float_t max,
|
|
const ImVec2 canvas_size, const ImVec2 canvas_pos, const ImVec2 canvas_pos_min, const ImVec2 canvas_pos_max,
|
|
const bool fix_rot_z) {
|
|
GlitterEditor::CurveEditor* crv_edt = &glt_edt->curve_editor;
|
|
ImDrawList* draw_list = crv_edt->draw_list;
|
|
const ImU32 random_range_color = ImGui::GetColorU32({ 0.5f, 0.5f, 0.0f, 0.25f });
|
|
const ImU32 key_random_range_color = ImGui::GetColorU32({ 0.5f, 0.0f, 0.5f, 0.25f });
|
|
|
|
const std::vector<Glitter::Curve::Key>* keys = &curve->keys_rev;
|
|
if (!keys->size())
|
|
return;
|
|
|
|
const float_t frame_width = crv_edt->frame_width * crv_edt->zoom_time;
|
|
|
|
const float_t line_thickness = line_front ? 3.0f : 1.0f;
|
|
|
|
if (keys->size() == 1) {
|
|
if (line_front && (curve->flags
|
|
& (Glitter::CURVE_RANDOM_RANGE | Glitter::CURVE_KEY_RANDOM_RANGE))) {
|
|
const float_t random_range = curve->random_range;
|
|
const bool random_range_mult = curve->flags & Glitter::CURVE_RANDOM_RANGE_MULT;
|
|
const bool random_range_negate = curve->flags & Glitter::CURVE_RANDOM_RANGE_NEGATE;
|
|
const bool glt_type_ft = glt_edt->effect_group->type == Glitter::FT;
|
|
|
|
const Glitter::Curve::Key* c = &keys->data()[0];
|
|
const Glitter::KeyType k_type = c->type;
|
|
const float_t c_frame = (float_t)c->frame;
|
|
const float_t c_value = fix_rot_z ? c->value - (float_t)M_PI_2 : c->value;
|
|
const float_t c_random_range = random_range_mult && glt_type_ft
|
|
? c->random_range * c_value : c->random_range;
|
|
|
|
const vec3 value = { c_value + c_random_range, c_value, c_value - c_random_range };
|
|
const vec3 random = !random_range_mult
|
|
? random_range : glt_type_ft
|
|
? (random_range * value) : (random_range * value * 0.01f);
|
|
|
|
glitter_editor_curve_editor_window_draw_random_range(crv_edt,
|
|
canvas_pos_min.x, canvas_pos_max.x,
|
|
value, random, min, max, random_range_negate,
|
|
canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
}
|
|
|
|
const Glitter::Curve::Key* c = &keys->data()[0];
|
|
const float_t c_value = fix_rot_z ? c->value - (float_t)M_PI_2 : c->value;
|
|
|
|
float_t y = convert_value_to_height(crv_edt, c_value,
|
|
canvas_pos.y, canvas_size.y, min, max);
|
|
|
|
draw_list->AddLine({ canvas_pos_min.x, y },
|
|
{ canvas_pos_max.x, y }, line_color, line_thickness);
|
|
return;
|
|
}
|
|
|
|
const Glitter::Curve* base_curve = crv_edt->list[crv_edt->type];
|
|
const int32_t start_time = curve->start_time;
|
|
const int32_t end_time = curve-> end_time;
|
|
const int32_t base_start_time = base_curve->start_time;
|
|
const int32_t base_end_time = base_curve-> end_time;
|
|
|
|
std::vector<ImVec2> points;
|
|
if (curve->repeat && end_time - start_time) {
|
|
const int32_t graph_start = base_start_time + (int32_t)((crv_edt->timeline_pos
|
|
+ frame_width - 1.0f) / frame_width);
|
|
const int32_t graph_end = base_start_time + (int32_t)((crv_edt->timeline_pos + canvas_size.x
|
|
+ frame_width - 1.0f) / frame_width);
|
|
|
|
const int32_t delta_time = end_time - start_time;
|
|
int32_t repeat_count_pre = (start_time - graph_start + delta_time - 1) / delta_time;
|
|
int32_t repeat_count_post = (graph_end - end_time + delta_time - 1) / delta_time;
|
|
repeat_count_pre = max_def(repeat_count_pre , 0);
|
|
repeat_count_post = max_def(repeat_count_post, 0);
|
|
|
|
for (int32_t i = repeat_count_pre; i >= 1; i--)
|
|
glitter_editor_curve_editor_window_draw(glt_edt, curve, line_color, line_front,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max,
|
|
fix_rot_z, start_time, end_time,
|
|
base_start_time + delta_time * i, base_end_time + delta_time * i, points, true);
|
|
glitter_editor_curve_editor_window_draw(glt_edt, curve, line_color, line_front,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max,
|
|
fix_rot_z, start_time, end_time, base_start_time, base_end_time, points, true);
|
|
for (int32_t i = 1; i <= repeat_count_post; i++)
|
|
glitter_editor_curve_editor_window_draw(glt_edt, curve, line_color, line_front,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max,
|
|
fix_rot_z, start_time, end_time,
|
|
base_start_time - delta_time * i, base_end_time - delta_time * i, points, true);
|
|
}
|
|
else {
|
|
glitter_editor_curve_editor_window_draw(glt_edt, curve, line_color, line_front,
|
|
min, max, canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max,
|
|
fix_rot_z, start_time, end_time, base_start_time, base_end_time, points);
|
|
}
|
|
draw_list->AddPolyline(points.data(),
|
|
(int32_t)points.size(), line_color, 0, line_thickness);
|
|
}
|
|
|
|
static void glitter_editor_curve_editor_window_draw(GlitterEditor* glt_edt, const Glitter::Curve* curve,
|
|
const ImU32 line_color, const bool line_front, const float_t min, const float_t max,
|
|
const ImVec2 canvas_size, const ImVec2 canvas_pos, const ImVec2 canvas_pos_min, const ImVec2 canvas_pos_max,
|
|
const bool fix_rot_z, const int32_t start_time, const int32_t end_time,
|
|
const int32_t base_start_time, const int32_t base_end_time, std::vector<ImVec2>& points, bool loop) {
|
|
GlitterEditor::CurveEditor* crv_edt = &glt_edt->curve_editor;
|
|
ImDrawList* draw_list = crv_edt->draw_list;
|
|
const ImU32 random_range_color = ImGui::GetColorU32({ 0.5f, 0.5f, 0.0f, 0.25f });
|
|
const ImU32 key_random_range_color = ImGui::GetColorU32({ 0.5f, 0.0f, 0.5f, 0.25f });
|
|
|
|
const std::vector<Glitter::Curve::Key>* keys = &curve->keys_rev;
|
|
|
|
const float_t frame_width = crv_edt->frame_width * crv_edt->zoom_time;
|
|
|
|
const float_t line_thickness = line_front ? 3.0f : 1.0f;
|
|
|
|
if (line_front && (curve->flags
|
|
& (Glitter::CURVE_RANDOM_RANGE | Glitter::CURVE_KEY_RANDOM_RANGE))) {
|
|
const float_t random_range = curve->random_range;
|
|
const bool random_range_mult = curve->flags & Glitter::CURVE_RANDOM_RANGE_MULT;
|
|
const bool random_range_negate = curve->flags & Glitter::CURVE_RANDOM_RANGE_NEGATE;
|
|
const bool glt_type_ft = glt_edt->effect_group->type == Glitter::FT;
|
|
|
|
bool first_frame_found = false;
|
|
|
|
const Glitter::Curve::Key* i_begin = keys->data();
|
|
const Glitter::Curve::Key* i_end = keys->data() + keys->size();
|
|
for (const Glitter::Curve::Key* i = i_begin; i != i_end; i++) {
|
|
if (i->frame <= start_time || i->frame > start_time && !first_frame_found) {
|
|
if (i_end - i <= 1)
|
|
break;
|
|
else if (i[1].frame <= start_time)
|
|
continue;
|
|
|
|
const Glitter::Curve::Key* c = i;
|
|
const Glitter::Curve::Key* n = i + 1;
|
|
const float_t c_value = fix_rot_z ? c->value - (float_t)M_PI_2 : c->value;
|
|
const float_t n_value = fix_rot_z ? n->value - (float_t)M_PI_2 : n->value;
|
|
const float_t c_random_range = random_range_mult && glt_type_ft
|
|
? c->random_range * c_value : c->random_range;
|
|
const float_t n_random_range = random_range_mult && glt_type_ft
|
|
? n->random_range * n_value : n->random_range;
|
|
|
|
const vec3 c_value_vec = { c_value + c_random_range, c_value, c_value - c_random_range };
|
|
const vec3 n_value_vec = { n_value + n_random_range, n_value, n_value - n_random_range };
|
|
|
|
vec3 value;
|
|
if (i->frame < start_time)
|
|
switch (c->type) {
|
|
case Glitter::KEY_CONSTANT:
|
|
value = c_value_vec;
|
|
break;
|
|
case Glitter::KEY_LINEAR:
|
|
default:
|
|
value = Glitter::Curve::InterpolateLinear(c_value_vec, n_value_vec,
|
|
vec3((float_t)c->frame), vec3((float_t)n->frame), vec3((float_t)start_time));
|
|
break;
|
|
case Glitter::KEY_HERMITE:
|
|
value = Glitter::Curve::InterpolateHermite(c_value_vec, n_value_vec - c_value_vec,
|
|
vec3((float_t)c->tangent2), vec3((float_t)n->tangent1),
|
|
vec3((float_t)c->frame), vec3((float_t)n->frame), vec3((float_t)start_time));
|
|
break;
|
|
}
|
|
else
|
|
value = c_value_vec;
|
|
|
|
const vec3 random = !random_range_mult
|
|
? random_range : glt_type_ft
|
|
? (random_range * value) : (random_range * value * 0.01f);
|
|
|
|
const float_t x1 = loop
|
|
? canvas_pos.x + (float_t)(start_time - base_start_time) * frame_width
|
|
: canvas_pos_min.x;
|
|
const float_t x2 = canvas_pos.x + (float_t)(max_def(i->frame,
|
|
start_time) - base_start_time) * frame_width;
|
|
glitter_editor_curve_editor_window_draw_random_range(crv_edt, x1, x2,
|
|
value, random, min, max, random_range_negate,
|
|
canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
first_frame_found = true;
|
|
}
|
|
else if (i->frame > end_time || i->frame == end_time || i_end - i <= 1 && i->frame <= end_time) {
|
|
vec3 value;
|
|
if (i->frame > end_time) {
|
|
const Glitter::Curve::Key* c = i - 1;
|
|
const Glitter::Curve::Key* n = i;
|
|
const float_t c_value = fix_rot_z ? c->value - (float_t)M_PI_2 : c->value;
|
|
const float_t n_value = fix_rot_z ? n->value - (float_t)M_PI_2 : n->value;
|
|
const float_t c_random_range = random_range_mult && glt_type_ft
|
|
? c->random_range * c_value : c->random_range;
|
|
const float_t n_random_range = random_range_mult && glt_type_ft
|
|
? n->random_range * n_value : n->random_range;
|
|
|
|
const vec3 c_value_vec = { c_value + c_random_range, c_value, c_value - c_random_range };
|
|
const vec3 n_value_vec = { n_value + n_random_range, n_value, n_value - n_random_range };
|
|
|
|
switch (c->type) {
|
|
case Glitter::KEY_CONSTANT:
|
|
value = c_value_vec;
|
|
break;
|
|
case Glitter::KEY_LINEAR:
|
|
default:
|
|
value = Glitter::Curve::InterpolateLinear(c_value_vec, n_value_vec,
|
|
vec3((float_t)c->frame), vec3((float_t)n->frame), vec3((float_t)end_time));
|
|
break;
|
|
case Glitter::KEY_HERMITE:
|
|
value = Glitter::Curve::InterpolateHermite(c_value_vec, n_value_vec - c_value_vec,
|
|
vec3((float_t)c->tangent2), vec3((float_t)n->tangent1),
|
|
vec3((float_t)c->frame), vec3((float_t)n->frame), vec3((float_t)end_time));
|
|
break;
|
|
}
|
|
}
|
|
else {
|
|
const Glitter::Curve::Key* c = i;
|
|
const float_t c_value = fix_rot_z ? c->value - (float_t)M_PI_2 : c->value;
|
|
const float_t c_random_range = random_range_mult && glt_type_ft
|
|
? c->random_range * c_value : c->random_range;
|
|
value = { c_value + c_random_range, c_value, c_value - c_random_range };
|
|
}
|
|
|
|
const vec3 random = !random_range_mult
|
|
? random_range : glt_type_ft
|
|
? (random_range * value) : (random_range * value * 0.01f);
|
|
|
|
const float_t x1 = canvas_pos.x + (float_t)(min_def(i->frame,
|
|
end_time) - base_start_time) * frame_width;
|
|
const float_t x2 = loop
|
|
? canvas_pos.x + (float_t)(end_time - base_start_time) * frame_width
|
|
: canvas_pos_max.x;
|
|
glitter_editor_curve_editor_window_draw_random_range(crv_edt, x1, x2,
|
|
value, random, min, max, random_range_negate,
|
|
canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
break;
|
|
}
|
|
else if (i_end - i <= 1)
|
|
break;
|
|
|
|
const Glitter::Curve::Key* c = i;
|
|
const Glitter::Curve::Key* n = i + 1;
|
|
const Glitter::KeyType k_type = c->type;
|
|
const float_t c_value = fix_rot_z ? c->value - (float_t)M_PI_2 : c->value;
|
|
const float_t n_value = fix_rot_z ? n->value - (float_t)M_PI_2 : n->value;
|
|
const float_t c_random_range = random_range_mult && glt_type_ft
|
|
? c->random_range * c_value : c->random_range;
|
|
const float_t n_random_range = random_range_mult && glt_type_ft
|
|
? n->random_range * n_value : n->random_range;
|
|
|
|
switch (k_type) {
|
|
case Glitter::KEY_CONSTANT: {
|
|
const vec3 value = { c_value + c_random_range, c_value, c_value - c_random_range };
|
|
const vec3 random = !random_range_mult
|
|
? random_range : glt_type_ft
|
|
? (random_range * value) : (random_range * value * 0.01f);
|
|
|
|
const int32_t c_frame = max_def(c->frame, start_time);
|
|
const int32_t n_frame = min_def(n->frame, end_time);
|
|
const float_t x1 = canvas_pos.x + (float_t)(c_frame - base_start_time) * frame_width;
|
|
const float_t x2 = canvas_pos.x + (float_t)(n_frame - base_start_time) * frame_width;
|
|
glitter_editor_curve_editor_window_draw_random_range(crv_edt, x1, x2,
|
|
value, random, min, max, random_range_negate,
|
|
canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
} break;
|
|
case Glitter::KEY_LINEAR: {
|
|
const int32_t c_frame = max_def(c->frame, start_time);
|
|
const int32_t n_frame = min_def(n->frame, end_time);
|
|
const float_t x1 = canvas_pos.x + (float_t)(c_frame - base_start_time) * frame_width;
|
|
const float_t x2 = canvas_pos.x + (float_t)(n_frame - base_start_time) * frame_width;
|
|
|
|
const float_t _c_value = Glitter::Curve::InterpolateLinear(c_value, n_value,
|
|
(float_t)c->frame, (float_t)n->frame, (float_t)c_frame);
|
|
const float_t _n_value = Glitter::Curve::InterpolateLinear(c_value, n_value,
|
|
(float_t)c->frame, (float_t)n->frame, (float_t)n_frame);
|
|
|
|
const vec3 c_value_vec = { _c_value + c_random_range, _c_value, _c_value - c_random_range };
|
|
const vec3 n_value_vec = { _n_value + n_random_range, _n_value, _n_value - n_random_range };
|
|
const vec3 c_random = !random_range_mult
|
|
? random_range : glt_type_ft
|
|
? (random_range * c_value_vec) : (random_range * c_value_vec * 0.01f);
|
|
const vec3 n_random = !random_range_mult
|
|
? random_range : glt_type_ft
|
|
? (random_range * n_value_vec) : (random_range * n_value_vec * 0.01f);
|
|
|
|
glitter_editor_curve_editor_window_draw_random_range(crv_edt, x1, x2,
|
|
c_value_vec, n_value_vec, c_random, n_random, min, max, random_range_negate,
|
|
canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
} break;
|
|
case Glitter::KEY_HERMITE: {
|
|
const float_t c_frame = (float_t)c->frame;
|
|
const float_t n_frame = (float_t)n->frame;
|
|
const float_t c_tangent2 = c->tangent2;
|
|
const float_t n_tangent1 = n->tangent1;
|
|
|
|
const vec3 c_frame_vec = c_frame;
|
|
const vec3 n_frame_vec = n_frame;
|
|
const vec3 c_value_vec = { c_value + c_random_range, c_value, c_value - c_random_range };
|
|
const vec3 n_value_vec = { n_value + n_random_range, n_value, n_value - n_random_range };
|
|
const vec3 c_tangent2_vec = c_tangent2;
|
|
const vec3 n_tangent1_vec = n_tangent1;
|
|
const int32_t frame_width_int = (int32_t)prj::roundf(frame_width);
|
|
for (int32_t j = c->frame; j < n->frame; j++) {
|
|
if (j < start_time)
|
|
continue;
|
|
else if (j >= end_time)
|
|
break;
|
|
|
|
for (int32_t k = 0; k < frame_width_int; k++) {
|
|
const float_t frame = (float_t)j + (float_t)k / frame_width;
|
|
const vec3 frame_vec = frame;
|
|
|
|
const vec3 value = Glitter::Curve::InterpolateHermite(c_value_vec, n_value_vec - c_value_vec,
|
|
c_tangent2_vec, n_tangent1_vec, c_frame_vec, n_frame_vec, frame_vec);
|
|
const vec3 random = !random_range_mult
|
|
? random_range : glt_type_ft
|
|
? (random_range * value) : (random_range * value * 0.01f);
|
|
|
|
const float_t x1 = canvas_pos.x
|
|
+ (float_t)(j - base_start_time) * frame_width + (float_t)k;
|
|
const float_t x2 = canvas_pos.x
|
|
+ (float_t)(j - base_start_time) * frame_width + (float_t)(k + 1);
|
|
glitter_editor_curve_editor_window_draw_random_range(crv_edt, x1, x2,
|
|
value, random, min, max, random_range_negate,
|
|
canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max);
|
|
}
|
|
}
|
|
} break;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool first_frame_found = false;
|
|
|
|
const Glitter::Curve::Key* i_begin = keys->data();
|
|
const Glitter::Curve::Key* i_end = keys->data() + keys->size();
|
|
for (const Glitter::Curve::Key* i = i_begin; i != i_end; i++) {
|
|
if (i->frame <= start_time || i->frame > start_time && !first_frame_found) {
|
|
if (i_end - i <= 1)
|
|
break;
|
|
else if (i[1].frame <= start_time)
|
|
continue;
|
|
|
|
const Glitter::Curve::Key* c = i;
|
|
const Glitter::Curve::Key* n = i + 1;
|
|
const float_t c_value = fix_rot_z ? c->value - (float_t)M_PI_2 : c->value;
|
|
const float_t n_value = fix_rot_z ? n->value - (float_t)M_PI_2 : n->value;
|
|
|
|
float_t value;
|
|
if (i->frame < start_time)
|
|
switch (c->type) {
|
|
case Glitter::KEY_CONSTANT:
|
|
value = c_value;
|
|
break;
|
|
case Glitter::KEY_LINEAR:
|
|
default:
|
|
value = Glitter::Curve::InterpolateLinear(c_value, n_value,
|
|
(float_t)c->frame, (float_t)n->frame, (float_t)start_time);
|
|
break;
|
|
case Glitter::KEY_HERMITE:
|
|
value = Glitter::Curve::InterpolateHermite(c_value, n_value - c_value,
|
|
(float_t)c->tangent2, (float_t)n->tangent1,
|
|
(float_t)c->frame, (float_t)n->frame, (float_t)start_time);
|
|
break;
|
|
}
|
|
else
|
|
value = c_value;
|
|
|
|
const float_t x1 = loop
|
|
? canvas_pos.x + (float_t)(start_time - base_start_time) * frame_width
|
|
: canvas_pos_min.x;
|
|
const float_t x2 = canvas_pos.x + (float_t)(max_def(i->frame,
|
|
start_time) - base_start_time) * frame_width;
|
|
const float_t y = convert_value_to_height(crv_edt, value,
|
|
canvas_pos.y, canvas_size.y, min, max);
|
|
|
|
if ((x1 > canvas_pos_min.x || x2 > canvas_pos_min.x)
|
|
&& (x1 < canvas_pos_max.x || x2 < canvas_pos_max.x)) {
|
|
if (!points.size() || points.back().x < x1 || points.back().y != y)
|
|
points.push_back({ x1, y });
|
|
if (points.back().x < x2 || points.back().y != y)
|
|
points.push_back({ x2, y });
|
|
}
|
|
first_frame_found = true;
|
|
}
|
|
else if (i->frame > end_time || i->frame == end_time || i_end - i <= 1 && i->frame <= end_time) {
|
|
float_t value;
|
|
if (i->frame > end_time) {
|
|
const Glitter::Curve::Key* c = i - 1;
|
|
const Glitter::Curve::Key* n = i;
|
|
const float_t c_value = fix_rot_z ? c->value - (float_t)M_PI_2 : c->value;
|
|
const float_t n_value = fix_rot_z ? n->value - (float_t)M_PI_2 : n->value;
|
|
|
|
switch (c->type) {
|
|
case Glitter::KEY_CONSTANT:
|
|
value = c_value;
|
|
break;
|
|
case Glitter::KEY_LINEAR:
|
|
default:
|
|
value = Glitter::Curve::InterpolateLinear(c_value, n_value,
|
|
(float_t)c->frame, (float_t)n->frame, (float_t)end_time);
|
|
break;
|
|
case Glitter::KEY_HERMITE:
|
|
value = Glitter::Curve::InterpolateHermite(c_value, n_value - c_value,
|
|
(float_t)c->tangent2, (float_t)n->tangent1,
|
|
(float_t)c->frame, (float_t)n->frame, (float_t)end_time);
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
value = i->value;
|
|
|
|
const float_t x1 = canvas_pos.x + (float_t)(min_def(i->frame,
|
|
end_time) - base_start_time) * frame_width;
|
|
const float_t x2 = loop
|
|
? canvas_pos.x + (float_t)(end_time - base_start_time) * frame_width
|
|
: canvas_pos_max.x;
|
|
const float_t y = convert_value_to_height(crv_edt, value,
|
|
canvas_pos.y, canvas_size.y, min, max);
|
|
if ((x1 > canvas_pos_min.x || x2 > canvas_pos_min.x)
|
|
&& (x1 < canvas_pos_max.x || x2 < canvas_pos_max.x)) {
|
|
if (!points.size() || points.back().x < x1 || points.back().y != y)
|
|
points.push_back({ x1, y });
|
|
if (points.back().x < x2 || points.back().y != y)
|
|
points.push_back({ x2, y });
|
|
}
|
|
break;
|
|
}
|
|
else if (i_end - i <= 1)
|
|
break;
|
|
|
|
const Glitter::Curve::Key* c = i;
|
|
const Glitter::Curve::Key* n = i + 1;
|
|
const float_t c_value = fix_rot_z ? c->value - (float_t)M_PI_2 : c->value;
|
|
const float_t n_value = fix_rot_z ? n->value - (float_t)M_PI_2 : n->value;
|
|
|
|
if (c->type == Glitter::KEY_CONSTANT) {
|
|
const int32_t c_frame = max_def(c->frame, start_time);
|
|
const int32_t n_frame = min_def(n->frame, end_time);
|
|
const float_t x1 = canvas_pos.x + (float_t)(c_frame - base_start_time) * frame_width;
|
|
const float_t x2 = canvas_pos.x + (float_t)(n_frame - base_start_time) * frame_width;
|
|
|
|
const float_t y1 = convert_value_to_height(crv_edt, c_value,
|
|
canvas_pos.y, canvas_size.y, min, max);
|
|
const float_t y2 = convert_value_to_height(crv_edt, n_value,
|
|
canvas_pos.y, canvas_size.y, min, max);
|
|
|
|
if ((x1 > canvas_pos_min.x || x2 > canvas_pos_min.x)
|
|
&& (x1 < canvas_pos_max.x || x2 < canvas_pos_max.x)) {
|
|
if (!points.size() || points.back().x < x1 || points.back().y != y1)
|
|
points.push_back({ x1, y1 });
|
|
if (points.back().x < x2 || points.back().y != y1)
|
|
points.push_back({ x2, y1 });
|
|
if (points.back().x < x2 || points.back().y != y2)
|
|
points.push_back({ x2, y2 });
|
|
}
|
|
}
|
|
else if (c->type == Glitter::KEY_LINEAR) {
|
|
const int32_t c_frame = max_def(c->frame, start_time);
|
|
const int32_t n_frame = min_def(n->frame, end_time);
|
|
const float_t x1 = canvas_pos.x + (float_t)(c_frame - base_start_time) * frame_width;
|
|
const float_t x2 = canvas_pos.x + (float_t)(n_frame - base_start_time) * frame_width;
|
|
|
|
const float_t _c_value = Glitter::Curve::InterpolateLinear(c_value, n_value,
|
|
(float_t)c->frame, (float_t)n->frame, (float_t)c_frame);
|
|
const float_t _n_value = Glitter::Curve::InterpolateLinear(c_value, n_value,
|
|
(float_t)c->frame, (float_t)n->frame, (float_t)n_frame);
|
|
|
|
const float_t y1 = convert_value_to_height(crv_edt, _c_value,
|
|
canvas_pos.y, canvas_size.y, min, max);
|
|
const float_t y2 = convert_value_to_height(crv_edt, _n_value,
|
|
canvas_pos.y, canvas_size.y, min, max);
|
|
|
|
if ((x1 > canvas_pos_min.x || x2 > canvas_pos_min.x)
|
|
&& (x1 < canvas_pos_max.x || x2 < canvas_pos_max.x)) {
|
|
if (!points.size() || points.back().x < x1 || points.back().y != y1)
|
|
points.push_back({ x1, y1 });
|
|
if (points.back().x < x2 || points.back().y != y2)
|
|
points.push_back({ x2, y2 });
|
|
}
|
|
}
|
|
else if (c->type == Glitter::KEY_HERMITE) {
|
|
const float_t c_frame = (float_t)c->frame;
|
|
const float_t n_frame = (float_t)n->frame;
|
|
const float_t c_tangent2 = (float_t)c->tangent2;
|
|
const float_t n_tangent1 = (float_t)n->tangent1;
|
|
|
|
float_t value = Glitter::Curve::InterpolateHermite(c_value, n_value - c_value,
|
|
c_tangent2, n_tangent1,
|
|
c_frame, n_frame, (float_t)max_def(c->frame, start_time));
|
|
float_t x = canvas_pos.x + (float_t)(max_def(c->frame, start_time)
|
|
- base_start_time) * frame_width;
|
|
float_t y = convert_value_to_height(crv_edt, value,
|
|
canvas_pos.y, canvas_size.y, min, max);
|
|
if (!points.size() || points.back().x < x || points.back().y != y)
|
|
points.push_back({ x, y });
|
|
|
|
const int32_t frame_width_int = (int32_t)prj::roundf(frame_width);
|
|
for (int32_t j = c->frame; j < n->frame; j++) {
|
|
if (j < start_time)
|
|
continue;
|
|
else if (j >= end_time)
|
|
break;
|
|
|
|
for (int32_t k = 0; k < frame_width_int; k++) {
|
|
const float_t value = Glitter::Curve::InterpolateHermite(c_value, n_value - c_value,
|
|
c_tangent2, n_tangent1, c_frame, n_frame, (float_t)j + (float_t)k / frame_width);
|
|
|
|
float_t x = canvas_pos.x
|
|
+ (float_t)(j - base_start_time) * frame_width + (float_t)k;
|
|
const float_t y = convert_value_to_height(crv_edt, value,
|
|
canvas_pos.y, canvas_size.y, min, max);
|
|
|
|
if ((x > canvas_pos_min.x || points.back().x < canvas_pos_max.x
|
|
&& canvas_pos_max.x < x) && points.back().x < x)
|
|
points.push_back({ x, y });
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void glitter_editor_curve_editor_window_draw_random_range(
|
|
GlitterEditor::CurveEditor* crv_edt, const float_t x1, const float_t x2,
|
|
const vec3 value, const vec3 random, const float_t min, const float_t max, const bool random_range_negate,
|
|
const ImVec2 canvas_size, const ImVec2 canvas_pos, const ImVec2 canvas_pos_min, const ImVec2 canvas_pos_max) {
|
|
const ImU32 random_range_color = ImGui::GetColorU32({ 0.5f, 0.5f, 0.0f, 0.25f });
|
|
const ImU32 key_random_range_color = ImGui::GetColorU32({ 0.5f, 0.0f, 0.5f, 0.25f });
|
|
|
|
if ((x1 <= canvas_pos_min.x && x2 <= canvas_pos_min.x) || (x1 >= canvas_pos_max.x && x2 >= canvas_pos_max.x))
|
|
return;
|
|
|
|
ImDrawList* draw_list = crv_edt->draw_list;
|
|
if (value.x < value.y || value.y > value.z) {
|
|
float_t y1 = convert_value_to_height(crv_edt, value.x + random.x,
|
|
canvas_pos.y, canvas_size.y, min, max);
|
|
float_t y2 = convert_value_to_height(crv_edt, value.x,
|
|
canvas_pos.y, canvas_size.y, min, max);
|
|
float_t y3 = y2;
|
|
float_t y4;
|
|
float_t y5;
|
|
float_t y6;
|
|
if (!random_range_negate)
|
|
y4 = convert_value_to_height(crv_edt, value.y,
|
|
canvas_pos.y, canvas_size.y, min, max);
|
|
else {
|
|
y4 = convert_value_to_height(crv_edt, value.z,
|
|
canvas_pos.y, canvas_size.y, min, max);
|
|
y5 = y4;
|
|
y6 = convert_value_to_height(crv_edt, value.z - random.z,
|
|
canvas_pos.y, canvas_size.y, min, max);
|
|
}
|
|
|
|
if (y1 > y2) {
|
|
float_t t = y2;
|
|
y2 = y1;
|
|
y1 = t;
|
|
}
|
|
|
|
if (y3 > y4) {
|
|
float_t t = y4;
|
|
y4 = y3;
|
|
y3 = t;
|
|
}
|
|
|
|
if (random_range_negate && y5 > y6) {
|
|
float_t t = y6;
|
|
y6 = y5;
|
|
y5 = t;
|
|
}
|
|
|
|
y1 = clamp_def(y1, canvas_pos_min.y, canvas_pos_max.y);
|
|
y2 = clamp_def(y2, canvas_pos_min.y, canvas_pos_max.y);
|
|
y3 = clamp_def(y3, canvas_pos_min.y, canvas_pos_max.y);
|
|
y4 = clamp_def(y4, canvas_pos_min.y, canvas_pos_max.y);
|
|
|
|
if (random_range_negate) {
|
|
y5 = clamp_def(y5, canvas_pos_min.y, canvas_pos_max.y);
|
|
y6 = clamp_def(y6, canvas_pos_min.y, canvas_pos_max.y);
|
|
}
|
|
|
|
if (y1 != y2)
|
|
draw_list->AddRectFilled({ x1, y1 }, { x2, y2 }, random_range_color);
|
|
|
|
if (y3 != y4)
|
|
draw_list->AddRectFilled({ x1, y3 }, { x2, y4 }, key_random_range_color);
|
|
|
|
if (random_range_negate && y5 != y6)
|
|
draw_list->AddRectFilled({ x1, y5 }, { x2, y6 }, random_range_color);
|
|
}
|
|
else {
|
|
float_t y1 = convert_value_to_height(crv_edt, value.y + random.y,
|
|
canvas_pos.y, canvas_size.y, min, max);
|
|
float_t y2;
|
|
if (!random_range_negate)
|
|
y2 = convert_value_to_height(crv_edt, value.y,
|
|
canvas_pos.y, canvas_size.y, min, max);
|
|
else
|
|
y2 = convert_value_to_height(crv_edt, value.y - random.y,
|
|
canvas_pos.y, canvas_size.y, min, max);
|
|
|
|
if (y1 > y2) {
|
|
float_t t = y2;
|
|
y2 = y1;
|
|
y1 = t;
|
|
}
|
|
|
|
y1 = clamp_def(y1, canvas_pos_min.y, canvas_pos_max.y);
|
|
y2 = clamp_def(y2, canvas_pos_min.y, canvas_pos_max.y);
|
|
if (y1 != y2)
|
|
draw_list->AddRectFilled({ x1, y1 }, { x2, y2 }, random_range_color);
|
|
}
|
|
}
|
|
|
|
static void glitter_editor_curve_editor_window_draw_random_range(
|
|
GlitterEditor::CurveEditor* crv_edt, const float_t x1, const float_t x2,
|
|
const vec3 value1, const vec3 value2, const vec3 random1, const vec3 random2,
|
|
const float_t min, const float_t max, const bool random_range_negate,
|
|
const ImVec2 canvas_size, const ImVec2 canvas_pos, const ImVec2 canvas_pos_min, const ImVec2 canvas_pos_max) {
|
|
const ImU32 random_range_color = ImGui::GetColorU32({ 0.5f, 0.5f, 0.0f, 0.25f });
|
|
const ImU32 key_random_range_color = ImGui::GetColorU32({ 0.5f, 0.0f, 0.5f, 0.25f });
|
|
|
|
if ((x1 <= canvas_pos_min.x && x2 <= canvas_pos_min.x) || (x1 >= canvas_pos_max.x && x2 >= canvas_pos_max.x))
|
|
return;
|
|
|
|
ImDrawList* draw_list = crv_edt->draw_list;
|
|
if (value1.x < value1.y || value1.y != value1.z
|
|
|| value2.x < value2.y || value2.y != value2.z) {
|
|
float_t y11 = convert_value_to_height(crv_edt, value1.x + random1.x,
|
|
canvas_pos.y, canvas_size.y, min, max);
|
|
float_t y21 = convert_value_to_height(crv_edt, value2.x + random2.x,
|
|
canvas_pos.y, canvas_size.y, min, max);
|
|
float_t y12 = convert_value_to_height(crv_edt, value1.x,
|
|
canvas_pos.y, canvas_size.y, min, max);
|
|
float_t y22 = convert_value_to_height(crv_edt, value2.x,
|
|
canvas_pos.y, canvas_size.y, min, max);
|
|
float_t y13 = y12;
|
|
float_t y23 = y22;
|
|
float_t y14;
|
|
float_t y24;
|
|
float_t y15;
|
|
float_t y25;
|
|
float_t y16;
|
|
float_t y26;
|
|
if (!random_range_negate) {
|
|
y14 = convert_value_to_height(crv_edt, value1.y,
|
|
canvas_pos.y, canvas_size.y, min, max);
|
|
y24 = convert_value_to_height(crv_edt, value2.y,
|
|
canvas_pos.y, canvas_size.y, min, max);
|
|
}
|
|
else {
|
|
y14 = convert_value_to_height(crv_edt, value1.z,
|
|
canvas_pos.y, canvas_size.y, min, max);
|
|
y24 = convert_value_to_height(crv_edt, value2.z,
|
|
canvas_pos.y, canvas_size.y, min, max);
|
|
y15 = y14;
|
|
y25 = y24;
|
|
y16 = convert_value_to_height(crv_edt, value1.z - random1.z,
|
|
canvas_pos.y, canvas_size.y, min, max);
|
|
y26 = convert_value_to_height(crv_edt, value2.z - random2.z,
|
|
canvas_pos.y, canvas_size.y, min, max);
|
|
}
|
|
|
|
if (y11 > y12) {
|
|
float_t t = y12;
|
|
y12 = y11;
|
|
y11 = t;
|
|
}
|
|
|
|
if (y21 > y22) {
|
|
float_t t = y22;
|
|
y22 = y21;
|
|
y21 = t;
|
|
}
|
|
|
|
if (y13 > y14) {
|
|
float_t t = y14;
|
|
y14 = y13;
|
|
y13 = t;
|
|
}
|
|
|
|
if (y23 > y24) {
|
|
float_t t = y24;
|
|
y24 = y23;
|
|
y23 = t;
|
|
}
|
|
|
|
if (random_range_negate) {
|
|
if (y15 > y16) {
|
|
float_t t = y16;
|
|
y16 = y15;
|
|
y15 = t;
|
|
}
|
|
|
|
if (y25 > y26) {
|
|
float_t t = y26;
|
|
y26 = y25;
|
|
y25 = t;
|
|
}
|
|
}
|
|
|
|
if (y11 != y12 || y21 != y22)
|
|
draw_list->AddQuadFilled({ x1, y11 }, { x2, y21 }, { x2, y22 }, { x1, y12 }, random_range_color);
|
|
|
|
if (y13 != y14 || y23 != y24)
|
|
draw_list->AddQuadFilled({ x1, y13 }, { x2, y23 }, { x2, y24 }, { x1, y14 }, key_random_range_color);
|
|
|
|
if (random_range_negate && (y15 != y16 || y25 != y26))
|
|
draw_list->AddQuadFilled({ x1, y15 }, { x2, y25 }, { x2, y26 }, { x1, y16 }, random_range_color);
|
|
}
|
|
else {
|
|
float_t y11 = convert_value_to_height(crv_edt, value1.y + random1.y,
|
|
canvas_pos.y, canvas_size.y, min, max);
|
|
float_t y21 = convert_value_to_height(crv_edt, value2.y + random2.y,
|
|
canvas_pos.y, canvas_size.y, min, max);
|
|
float_t y12;
|
|
float_t y22;
|
|
if (!random_range_negate) {
|
|
y12 = convert_value_to_height(crv_edt, value1.y,
|
|
canvas_pos.y, canvas_size.y, min, max);
|
|
y22 = convert_value_to_height(crv_edt, value2.y,
|
|
canvas_pos.y, canvas_size.y, min, max);
|
|
}
|
|
else {
|
|
y12 = convert_value_to_height(crv_edt, value1.y - random1.y,
|
|
canvas_pos.y, canvas_size.y, min, max);
|
|
y22 = convert_value_to_height(crv_edt, value2.y - random2.y,
|
|
canvas_pos.y, canvas_size.y, min, max);
|
|
}
|
|
|
|
if (y11 > y12) {
|
|
float_t t = y12;
|
|
y12 = y11;
|
|
y11 = t;
|
|
}
|
|
|
|
if (y21 > y22) {
|
|
float_t t = y22;
|
|
y22 = y21;
|
|
y21 = t;
|
|
}
|
|
|
|
if (y11 != y12 || y21 != y22)
|
|
draw_list->AddQuadFilled({ x1, y11 }, { x1, y21 }, { x2, y22 }, { x2, y12 }, random_range_color);
|
|
}
|
|
}
|
|
|
|
static bool glitter_editor_hash_input(GlitterEditor* glt_edt, const char* label, uint64_t* hash) {
|
|
uint64_t h = *hash;
|
|
if (glt_edt->effect_group->type == Glitter::FT) {
|
|
if (ImGui::ColumnInputScalar(label, ImGuiDataType_U64, &h,
|
|
0, 0, "%016llX", ImGuiInputTextFlags_CharsHexadecimal) && !h)
|
|
h = hash_fnv1a64m_empty;
|
|
}
|
|
else {
|
|
if (ImGui::ColumnInputScalar(label, ImGuiDataType_U32, &h,
|
|
0, 0, "%08X", ImGuiInputTextFlags_CharsHexadecimal) && !h)
|
|
h = hash_murmurhash_empty;
|
|
}
|
|
|
|
if (h == *hash)
|
|
return false;
|
|
|
|
*hash = h;
|
|
return true;
|
|
}
|
|
#endif
|