diff --git a/src/CRE/mdl/disp_manager.cpp b/src/CRE/mdl/disp_manager.cpp index c1cfa3b0..16a0f09a 100644 --- a/src/CRE/mdl/disp_manager.cpp +++ b/src/CRE/mdl/disp_manager.cpp @@ -2755,7 +2755,7 @@ namespace mdl { if (!object) return false; - std::vector* textures = objset_info_storage_get_obj_set_textures(obj_info.set_id); + std::vector* textures = objset_info_storage_get_obj_set_gentex(obj_info.set_id); obj_mesh_vertex_buffer* obj_vertex_buffer = objset_info_storage_get_obj_mesh_vertex_buffer(obj_info); obj_mesh_index_buffer* obj_index_buffer = objset_info_storage_get_obj_mesh_index_buffer(obj_info); diff --git a/src/CRE/object.cpp b/src/CRE/object.cpp index 0c87db0c..540c82b9 100644 --- a/src/CRE/object.cpp +++ b/src/CRE/object.cpp @@ -1937,9 +1937,34 @@ inline obj_mesh_vertex_buffer* objset_info_storage_get_obj_mesh_vertex_buffer(ob return 0; } +inline std::vector* objset_info_storage_get_obj_set_gentex(int32_t set) { + ObjsetInfo* info = objset_info_storage_get_objset_info(set); + if (info) + return &info->gentex; + return 0; +} + +uint32_t objset_info_storage_get_obj_set_tex_id(uint32_t set_id, int32_t tex_index) { + ObjsetInfo* info = objset_info_storage_get_objset_info(set_id); + if (!info) + return -1; + + obj_set* set = info->obj_set; + if (set && tex_index >= 0 && tex_index < set->tex_id_num) + return set->tex_id_data[tex_index]; + return -1; +} + +int32_t objset_info_storage_get_obj_set_tex_num(int32_t set) { + ObjsetInfo* info = objset_info_storage_get_objset_info(set); + if (info) + return info->tex_num; + return 0; +} + GLuint objset_info_storage_get_obj_set_texture(uint32_t set, uint32_t tex_id) { - std::vector* textures = objset_info_storage_get_obj_set_textures(set); - if (!textures) + std::vector* gentex = objset_info_storage_get_obj_set_gentex(set); + if (!gentex) return 0; ObjsetInfo* info = objset_info_storage_get_objset_info(set); @@ -1948,14 +1973,14 @@ GLuint objset_info_storage_get_obj_set_texture(uint32_t set, uint32_t tex_id) { auto elem = info->tex_id_data.find(tex_id); if (elem != info->tex_id_data.end()) - return (*textures)[elem->second]; + return (*gentex)[elem->second]; return 0; } -inline std::vector* objset_info_storage_get_obj_set_textures(int32_t set) { +inline texture** objset_info_storage_get_obj_set_textures(int32_t set) { ObjsetInfo* info = objset_info_storage_get_objset_info(set); if (info) - return &info->gentex; + return info->tex_data; return 0; } diff --git a/src/CRE/object.hpp b/src/CRE/object.hpp index 11e71706..1faab62b 100644 --- a/src/CRE/object.hpp +++ b/src/CRE/object.hpp @@ -139,8 +139,11 @@ extern obj_index_buffer* objset_info_storage_get_obj_index_buffers(uint32_t set_ extern obj_mesh_index_buffer* objset_info_storage_get_obj_mesh_index_buffer(object_info obj_info); extern obj_vertex_buffer* objset_info_storage_get_obj_vertex_buffers(uint32_t set_id); extern obj_mesh_vertex_buffer* objset_info_storage_get_obj_mesh_vertex_buffer(object_info obj_info); +extern std::vector* objset_info_storage_get_obj_set_gentex(int32_t set); +extern uint32_t objset_info_storage_get_obj_set_tex_id(uint32_t set_id, int32_t tex_index); +extern int32_t objset_info_storage_get_obj_set_tex_num(int32_t set); extern GLuint objset_info_storage_get_obj_set_texture(uint32_t set, uint32_t tex_id); -extern std::vector* objset_info_storage_get_obj_set_textures(int32_t set); +extern texture** objset_info_storage_get_obj_set_textures(int32_t set); extern int32_t objset_info_storage_load_set(void* data, const object_database* obj_db, const char* name); extern int32_t objset_info_storage_load_set(void* data, const object_database* obj_db, uint32_t set_id); extern int32_t objset_info_storage_load_set_hash(void* data, uint32_t hash); diff --git a/src/CRE/rob/ex_block.cpp b/src/CRE/rob/ex_block.cpp index f500843e..23b73c74 100644 --- a/src/CRE/rob/ex_block.cpp +++ b/src/CRE/rob/ex_block.cpp @@ -1532,7 +1532,7 @@ void RobCloth::Disp(const mat4* mat, render_context* rctx) { if (!obj) return; - std::vector* tex = objset_info_storage_get_obj_set_textures(itm_eq_obj->obj_info.set_id); + std::vector* textures = objset_info_storage_get_obj_set_gentex(itm_eq_obj->obj_info.set_id); vec3 center = (nodes.data()[0].pos + nodes.data()[root_count * nodes_count - 1].pos) * 0.5f; @@ -1552,7 +1552,7 @@ void RobCloth::Disp(const mat4* mat, render_context* rctx) { } rctx->disp_manager->set_texture_pattern((int32_t)itm_eq_obj->texture_pattern.size(), itm_eq_obj->texture_pattern.data()); - rctx->disp_manager->entry_obj_by_obj(mat, &o, tex, vertex_buffer, index_buffer, 0, itm_eq_obj->alpha); + rctx->disp_manager->entry_obj_by_obj(mat, &o, textures, vertex_buffer, index_buffer, 0, itm_eq_obj->alpha); rctx->disp_manager->set_texture_pattern(); } diff --git a/src/CRE/sprite.cpp b/src/CRE/sprite.cpp index 16ba4d46..a743836d 100644 --- a/src/CRE/sprite.cpp +++ b/src/CRE/sprite.cpp @@ -109,7 +109,7 @@ namespace spr { }; struct TexParam { - texture* texture; + const texture* texture; TexCoord texcoord; //int32_t pad[2]; @@ -1209,7 +1209,7 @@ namespace spr { static int32_t calc_sprite_texture_param(SprArgs* args, spr::TexParam* param, vec3* vtx, bool font) { int32_t tex_param_count = 0; - texture* tex = args->texture; + const texture* tex = args->texture; while (args) { param->texture = args->texture; diff --git a/src/CRE/sprite.hpp b/src/CRE/sprite.hpp index 06122922..6893b304 100644 --- a/src/CRE/sprite.hpp +++ b/src/CRE/sprite.hpp @@ -167,7 +167,7 @@ namespace spr { vec3 rot; vec2 skew_angle; mat4 mat; - texture* texture; + const texture* texture; int32_t shader; #if BREAK_SPRITE_VERTEX_LIMIT size_t vertex_array; diff --git a/src/CRE/texture.cpp b/src/CRE/texture.cpp index c02d17d5..fd9785b8 100644 --- a/src/CRE/texture.cpp +++ b/src/CRE/texture.cpp @@ -23,19 +23,19 @@ glid(), target(), internal_format(), max_mipmap_level(), size_texmem() { } -int32_t texture::get_height_align_mip_level(uint8_t mip_level) { +int32_t texture::get_height_align_mip_level(uint8_t mip_level) const { if (flags & TEXTURE_BLOCK_COMPRESSION) return max_def((uint32_t)height >> mip_level, 4u); else return max_def((uint32_t)height >> mip_level, 1u); } -int32_t texture::get_size_mip_level(uint8_t mip_level) { +int32_t texture::get_size_mip_level(uint8_t mip_level) const { return texture_get_size(internal_format, get_width_mip_level(mip_level), get_height_mip_level(mip_level)); } -int32_t texture::get_width_align_mip_level(uint8_t mip_level) { +int32_t texture::get_width_align_mip_level(uint8_t mip_level) const { if (flags & TEXTURE_BLOCK_COMPRESSION) return max_def((uint32_t)width >> mip_level, 4u); else @@ -71,8 +71,8 @@ texture* texture_alloc(texture_id id) { return tex; } -void texture_apply_color_tone(texture* chg_tex, - texture* org_tex, const color_tone* col_tone) { +void texture_apply_color_tone(const texture* chg_tex, + const texture* org_tex, const color_tone* col_tone) { if (!chg_tex || !org_tex || !col_tone || chg_tex->internal_format != org_tex->internal_format || chg_tex->width != org_tex->width @@ -438,6 +438,62 @@ int32_t texture_get_size(GLenum internal_format, int32_t width, int32_t height) } } +const char* texture_get_internal_format_name(GLenum internal_format) { + switch (internal_format) { + case GL_ALPHA8: + return "A8"; + case GL_LUMINANCE8: + return "L8"; + case GL_LUMINANCE8_ALPHA8: + return "L8A8"; + case GL_RGB5: + return "RGB5"; + case GL_RGB8: + return "RGB8"; + case GL_RGBA4: + return "RGBA4"; + case GL_RGB5_A1: + return "RGB5_A1"; + case GL_RGBA8: + return "RGBA8"; + case GL_DEPTH_COMPONENT16: + return "DEPTH16"; + case GL_DEPTH_COMPONENT24: + return "DEPTH24"; + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + return "DXT1"; + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + return "DXT1A"; + case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: + return "DXT3"; + case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: + return "DXT5"; + case GL_DEPTH24_STENCIL8: // Added + return "DEPTH24_STENCIL8"; + case GL_COMPRESSED_RED_RGTC1_EXT: + return "RGTC1(BC4)"; + case GL_COMPRESSED_RED_GREEN_RGTC2_EXT: + return "RGTC2(BC5)"; + case GL_DEPTH_COMPONENT32F: + return "DEPTH32"; + default: + return "unknown"; + } +} + +const char* texture_get_target_name(GLenum target) { + switch (target) { + case GL_TEXTURE_2D: + return "2D"; + case GL_TEXTURE_RECTANGLE: + return "RECTANGLE"; + case GL_TEXTURE_CUBE_MAP: + return "CUBE_MAP"; + default: + return "unknown"; + } +} + void texture_set_params(GLenum target, int32_t max_mipmap_level, bool use_high_anisotropy) { glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); diff --git a/src/CRE/texture.hpp b/src/CRE/texture.hpp index 8a412ec1..2823ad59 100644 --- a/src/CRE/texture.hpp +++ b/src/CRE/texture.hpp @@ -68,14 +68,14 @@ struct texture { texture(); - int32_t get_height_align_mip_level(uint8_t mip_level = 0); - int32_t get_size_mip_level(uint8_t mip_level = 0); - int32_t get_width_align_mip_level(uint8_t mip_level = 0); + int32_t get_height_align_mip_level(uint8_t mip_level = 0) const; + int32_t get_size_mip_level(uint8_t mip_level = 0) const; + int32_t get_width_align_mip_level(uint8_t mip_level = 0) const; - inline int32_t get_height_mip_level(uint8_t mip_level) { + inline int32_t get_height_mip_level(uint8_t mip_level) const { return max_def(height >> mip_level, 1); } - inline int32_t get_width_mip_level(uint8_t mip_level) { + inline int32_t get_width_mip_level(uint8_t mip_level) const { return max_def(width >> mip_level, 1); } }; @@ -95,8 +95,8 @@ struct texture_manager { }; extern texture* texture_alloc(texture_id id); -extern void texture_apply_color_tone(texture* chg_tex, - texture* org_tex, const color_tone* col_tone); +extern void texture_apply_color_tone(const texture* chg_tex, + const texture* org_tex, const color_tone* col_tone); extern texture* texture_create_copy_texture(texture_id id, texture* org_tex); extern texture* texture_create_copy_texture_apply_color_tone( texture_id id, texture* org_tex, const color_tone* col_tone); @@ -112,6 +112,9 @@ extern void texture_array_free(texture** arr); extern void texture_get_format_type_by_internal_format(GLenum internal_format, GLenum* format, GLenum* type); extern int32_t texture_get_size(GLenum internal_format, int32_t width, int32_t height); +extern const char* texture_get_internal_format_name(GLenum internal_format); +extern const char* texture_get_target_name(GLenum target); + extern void texture_set_params(GLenum target, int32_t max_mipmap_level, bool use_high_anisotropy); extern bool texture_txp_set_load(txp_set* t, texture*** texs, uint32_t* ids); diff --git a/src/ReDIVA/classes/graphics.cpp b/src/ReDIVA/classes/graphics.cpp index 97a60f85..f630b82d 100644 --- a/src/ReDIVA/classes/graphics.cpp +++ b/src/ReDIVA/classes/graphics.cpp @@ -4,6 +4,7 @@ */ #include "graphics.hpp" +#include "../graphics/color_change.hpp" #include "../graphics/face_light.hpp" #include "../graphics/fog.hpp" #include "../graphics/glitter.hpp" @@ -83,6 +84,20 @@ classes_data graphics_classes[] = { 0, 0, }, + { + "Color Change##Graphics", + CLASSES_IN_CONTEXT_MENU, + (classes_init_func)color_change_dw_init, + CLASSES_DATA_NO_FUNC, + CLASSES_DATA_NO_FUNC, + { + CLASS_DW, + false, + CLASS_DATA_NO_DATA, + }, + 0, + 0, + }, { "Glitter##Graphics", CLASSES_IN_CONTEXT_MENU, diff --git a/src/ReDIVA/graphics/color_change.cpp b/src/ReDIVA/graphics/color_change.cpp new file mode 100644 index 00000000..f0d164e1 --- /dev/null +++ b/src/ReDIVA/graphics/color_change.cpp @@ -0,0 +1,877 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#include "color_change.hpp" +#include "../../CRE/light_param/face.hpp" +#include "../../CRE/rob/rob.hpp" +#include "../../CRE/light_param.hpp" +#include "../../CRE/object.hpp" +#include "../../CRE/render_context.hpp" +#include "../../CRE/sprite.hpp" +#include "../../KKdLib/image.hpp" +#include "../dw.hpp" + +extern render_context* rctx_ptr; + +class ColorChangeDw : public dw::Shell { +public: + dw::ListBox* object_sets; + dw::ListBox* texture_names; + dw::Widget* type; + dw::Widget* format; + dw::Widget* size; + dw::Button* show_button; + dw::Button* auto_resize_button; + dw::ListBox* item_chara; + dw::ListBox* item_names; + dw::ListBox* item_texture_names; + dw::Button* over_write; + dw::Button* inverse; + dw::Slider* blend_r; + dw::Slider* blend_g; + dw::Slider* blend_b; + dw::Slider* offset_r; + dw::Slider* offset_g; + dw::Slider* offset_b; + dw::Slider* hue; + dw::Slider* value; + dw::Slider* saturation; + dw::Slider* contrast; + dw::Button* copy_button; + dw::Button* paset_button; + dw::Button* reset_button; + dw::Button* save_button; + dw::RowLayout* row_layout; + int32_t obj_set_index; + uint32_t obj_set_id; + bool set; + int32_t color_change_index; + std::vector textures; + std::vector color_tones; + color_tone color_tone_temp; + bool show; + bool auto_resize; + chara_index chara_index; + int32_t item_index; + size_t item_texture_index; + + ColorChangeDw(); + virtual ~ColorChangeDw() override; + virtual void Draw() override; + virtual void Reset() override; + + virtual void Hide() override; + + texture* GetChgTex(); + color_tone* GetColorTone(); + void GetColorToneDefault(color_tone& value); + const item_table_item* GetItem(int32_t item_index); + void GetItemColTone(); + const item_table_item_data* GetItemData(int32_t item_index); + int32_t GetItemNo(int32_t item_index); + const char* GetItemTexChangeName(); + texture* GetOrgTex(); + void GetSetColorTone(); + void GetTextureNames(); + bool LoadColorTone(); + void LoadItemNames(); + bool LoadTexture(); + void ReloadData(); + void ResetColorTone(); + void ResetData(); + void ResetTexture(); + void SetObjectSet(const char* str); + void SetTextureName(const char* name); + void UpdateData(); + void UpdateItemTextureNames(); + void UpdateTextureInfo(); + + static void AutoResizeCallback(dw::Button* data); + static void BlendBCallback(dw::Slider* data); + static void BlendGCallback(dw::Slider* data); + static void BlendRCallback(dw::Slider* data); + static void ContrastCallback(dw::Slider* data); + static void CopyCallback(dw::Button* data); + static void HueCallback(dw::Slider* data); + static void InverseCallback(dw::Button* data); + static void ItemCallback(dw::ListBox* data); + static void ItemCharaCallback(dw::ListBox* data); + static void ItemTextureCallback(dw::ListBox* data); + static void ObjectSetCallback(dw::ListBox* data); + static void OffsetBCallback(dw::Slider* data); + static void OffsetGCallback(dw::Slider* data); + static void OffsetRCallback(dw::Slider* data); + static void OverwriteCallback(dw::Button* data); + static void PasteCallback(dw::Button* data); + static void ResetCallback(dw::Button* data); + static void SaturationCallback(dw::Slider* data); + static void SaveCallback(dw::Button* data); + static void ShowCallback(dw::Button* data); + static void TextureCallback(dw::ListBox* data); + static void ValueCallback(dw::Slider* data); +}; + +ColorChangeDw* color_change_dw; + +static const char* get_dev_ram_color_change_param_dir(); + +void color_change_dw_init() { + if (!color_change_dw) { + color_change_dw = new ColorChangeDw; + color_change_dw->UpdateLayout(); + color_change_dw->sub_1402F38B0(); + } + else + color_change_dw->Disp(); +} + +ColorChangeDw::ColorChangeDw() { + data_struct* aft_data = &data_list[DATA_AFT]; + object_database* aft_obj_db = &aft_data->data_ft.obj_db; + + set = false; + obj_set_index = 0; + obj_set_id = aft_obj_db->get_object_set_id(0u); + color_change_index = 0; + + color_tone col_tone; + GetColorToneDefault(col_tone); + color_tone_temp = col_tone; + + show = true; + auto_resize = true; + chara_index = CHARA_MIKU; + item_index = 0; + item_texture_index = 0; + + SetText("COLOR CHANGE"); + + rect.pos = 0.0f; + SetSize({ 512.0f, 200.f }); + + const float_t glyph_height = font.GetFontGlyphHeight(); + + row_layout = new dw::RowLayout(dw::VERTICAL); + + dw::Composite* comp = new dw::Composite(this); + comp->layout = row_layout; + + dw::Group* texture_group = new dw::Group(comp); + texture_group->SetText("TEXTURE"); + + object_sets = new dw::ListBox(texture_group, (dw::Flags)(dw::FLAG_800 | dw::VERTICAL | dw::MULTISELECT)); + object_sets->SetText("listbox0"); + uint32_t obj_set_count = aft_obj_db->get_object_set_count(); + for (uint32_t i = obj_set_count, j = 0; i; i--, j++) + object_sets->AddItem(aft_obj_db->get_object_set_name(aft_obj_db->get_object_set_id(j))); + object_sets->AddSelectionListener(new dw::SelectionListenerOnHook( + (dw::SelectionListenerOnHook::CallbackFunc)ColorChangeDw::ObjectSetCallback)); + object_sets->SetItemIndex(obj_set_index); + object_sets->SetMaxItems(20); + object_sets->callback_data.v64 = this; + + texture_names = new dw::ListBox(texture_group, (dw::Flags)(dw::FLAG_800 | dw::VERTICAL | dw::MULTISELECT)); + texture_names->SetText("listbox1"); + + const int32_t tex_num = objset_info_storage_get_obj_set_tex_num(obj_set_id); + for (int32_t i = 0; i < tex_num; i++) + texture_names->AddItem(sprintf_s_string("%d", i)); + + texture_names->AddSelectionListener(new dw::SelectionListenerOnHook( + (dw::SelectionListenerOnHook::CallbackFunc)ColorChangeDw::TextureCallback)); + texture_names->SetItemIndex(0); + texture_names->SetMaxItems(20); + texture_names->callback_data.v64 = this; + + type = new dw::Label(texture_group, dw::FLAG_4000); + type->SetText("Type "); + type->callback_data.i64 = 2; + + format = new dw::Label(texture_group, dw::FLAG_4000); + format->SetText("Format "); + format->callback_data.i64 = 1; + + size = new dw::Label(texture_group, dw::FLAG_4000); + size->SetText("Size "); + size->callback_data.i64 = 1; + + show_button = new dw::Button(texture_group, dw::CHECKBOX); + show_button->SetText("Show"); + show_button->SetValue(show); + show_button->callback = (dw::Widget::Callback)ColorChangeDw::ShowCallback; + show_button->callback_data.v64 = this; + + auto_resize_button = new dw::Button(texture_group, dw::CHECKBOX); + auto_resize_button->SetText("Auto Resize 256x256"); + auto_resize_button->SetValue(auto_resize); + auto_resize_button->callback = (dw::Widget::Callback)ColorChangeDw::AutoResizeCallback; + auto_resize_button->callback_data.v64 = this; + + dw::Group* item_group = new dw::Group(comp); + item_group->SetText("ITEM"); + + item_chara = new dw::ListBox(item_group, (dw::Flags)(dw::FLAG_800 | dw::VERTICAL | dw::MULTISELECT)); + item_chara->SetText("listbox0"); + for (int32_t i = 0; i < CHARA_MAX; i++) + item_chara->AddItem(chara_index_get_name((::chara_index)i)); + item_chara->AddSelectionListener(new dw::SelectionListenerOnHook( + (dw::SelectionListenerOnHook::CallbackFunc)ColorChangeDw::ItemCharaCallback)); + item_chara->SetMaxItems(20); + item_chara->callback_data.v64 = this; + + item_names = new dw::ListBox(item_group, (dw::Flags)(dw::FLAG_800 | dw::VERTICAL | dw::MULTISELECT)); + item_names->SetText("listbox0"); + item_names->AddSelectionListener(new dw::SelectionListenerOnHook( + (dw::SelectionListenerOnHook::CallbackFunc)ColorChangeDw::ItemCallback)); + item_names->SetItemIndex(0); + item_names->SetMaxItems(20); + item_names->callback_data.v64 = this; + + item_texture_names = new dw::ListBox(item_group, (dw::Flags)(dw::FLAG_800 | dw::VERTICAL | dw::MULTISELECT)); + item_texture_names->SetText("listbox0"); + item_texture_names->AddSelectionListener(new dw::SelectionListenerOnHook( + (dw::SelectionListenerOnHook::CallbackFunc)ColorChangeDw::ItemTextureCallback)); + item_texture_names->SetItemIndex(0); + item_texture_names->SetMaxItems(20); + item_texture_names->callback_data.v64 = this; + + over_write = new dw::Button(item_group, dw::FLAG_8); + over_write->SetText("OVER WRITE"); + over_write->callback = (dw::Widget::Callback)ColorChangeDw::OverwriteCallback; + over_write->callback_data.v64 = this; + + dw::Group* color_group = new dw::Group(comp); + color_group->SetText("COLOR"); + + const char* inverse_text; + if (dw::translate) + inverse_text = u8"Inverse"; + else + inverse_text = u8"反転"; + + inverse = new dw::Button(color_group, dw::CHECKBOX); + inverse->SetText(inverse_text); + inverse->SetValue(col_tone.inverse); + inverse->callback = (dw::Widget::Callback)ColorChangeDw::InverseCallback; + inverse->callback_data.v64 = this; + + blend_r = dw::Slider::Create(color_group, (dw::Flags)(dw::FLAG_800 | dw::HORIZONTAL), + 0.0f, 0.0f, 100.0f, glyph_height, "BLEND R"); + blend_r->SetParams(col_tone.blend.x, 0.0f, 5.0f, 0.4f, 0.01f, 0.1f); + blend_r->format = "%4.2f"; + blend_r->AddSelectionListener(new dw::SelectionListenerOnHook( + (dw::SelectionListenerOnHook::CallbackFunc)ColorChangeDw::BlendRCallback)); + blend_r->callback_data.v64 = this; + + blend_g = dw::Slider::Create(color_group, (dw::Flags)(dw::FLAG_800 | dw::HORIZONTAL), + 0.0f, 0.0f, 100.0f, glyph_height, "BLEND G"); + blend_g->SetParams(col_tone.blend.y, 0.0f, 5.0f, 0.4f, 0.01f, 0.1f); + blend_g->format = "%4.2f"; + blend_g->AddSelectionListener(new dw::SelectionListenerOnHook( + (dw::SelectionListenerOnHook::CallbackFunc)ColorChangeDw::BlendGCallback)); + blend_g->callback_data.v64 = this; + + blend_b = dw::Slider::Create(color_group, (dw::Flags)(dw::FLAG_800 | dw::HORIZONTAL), + 0.0f, 0.0f, 100.0f, glyph_height, "BLEND B"); + blend_b->SetParams(col_tone.blend.z, 0.0f, 5.0f, 0.4f, 0.01f, 0.1f); + blend_b->format = "%4.2f"; + blend_b->AddSelectionListener(new dw::SelectionListenerOnHook( + (dw::SelectionListenerOnHook::CallbackFunc)ColorChangeDw::BlendBCallback)); + blend_b->callback_data.v64 = this; + + offset_r = dw::Slider::Create(color_group, (dw::Flags)(dw::FLAG_800 | dw::HORIZONTAL), + 0.0f, 0.0f, 100.0f, glyph_height, "OFFSET R"); + offset_r->SetParams(col_tone.offset.x, -1.0f, 1.0f, 0.4f, 0.01f, 0.1f); + offset_r->format = "%4.2f"; + offset_r->AddSelectionListener(new dw::SelectionListenerOnHook( + (dw::SelectionListenerOnHook::CallbackFunc)ColorChangeDw::OffsetRCallback)); + offset_r->callback_data.v64 = this; + + offset_g = dw::Slider::Create(color_group, (dw::Flags)(dw::FLAG_800 | dw::HORIZONTAL), + 0.0f, 0.0f, 100.0f, glyph_height, "OFFSET G"); + offset_g->SetParams(col_tone.offset.y, -1.0f, 1.0f, 0.4f, 0.01f, 0.1f); + offset_g->format = "%4.2f"; + offset_g->AddSelectionListener(new dw::SelectionListenerOnHook( + (dw::SelectionListenerOnHook::CallbackFunc)ColorChangeDw::OffsetGCallback)); + offset_g->callback_data.v64 = this; + + offset_b = dw::Slider::Create(color_group, (dw::Flags)(dw::FLAG_800 | dw::HORIZONTAL), + 0.0f, 0.0f, 100.0f, glyph_height, "OFFSET B"); + offset_b->SetParams(col_tone.offset.z, -1.0f, 1.0f, 0.4f, 0.01f, 0.1f); + offset_b->format = "%4.2f"; + offset_b->AddSelectionListener(new dw::SelectionListenerOnHook( + (dw::SelectionListenerOnHook::CallbackFunc)ColorChangeDw::OffsetBCallback)); + offset_b->callback_data.v64 = this; + + hue = dw::Slider::Create(color_group, (dw::Flags)(dw::FLAG_800 | dw::HORIZONTAL), + 0.0f, 0.0f, 100.0f, glyph_height, "H"); + hue->SetParams(col_tone.hue, 0.0f, 360.0f, 72.0f, 1.0f, 10.0); + hue->format = "%4.2f"; + hue->AddSelectionListener(new dw::SelectionListenerOnHook( + (dw::SelectionListenerOnHook::CallbackFunc)ColorChangeDw::HueCallback)); + hue->callback_data.v64 = this; + + saturation = dw::Slider::Create(color_group, (dw::Flags)(dw::FLAG_800 | dw::HORIZONTAL), + 0.0f, 0.0f, 100.0f, glyph_height, "S"); + saturation->SetParams(col_tone.saturation, 0.0f, 2.0f, 0.4f, 0.01f, 0.1f); + saturation->format = "%4.2f"; + saturation->AddSelectionListener(new dw::SelectionListenerOnHook( + (dw::SelectionListenerOnHook::CallbackFunc)ColorChangeDw::SaturationCallback)); + saturation->callback_data.v64 = this; + + value = dw::Slider::Create(color_group, (dw::Flags)(dw::FLAG_800 | dw::HORIZONTAL), + 0.0f, 0.0f, 100.0f, glyph_height, "V"); + value->SetParams(col_tone.value, -1.0f, 1.0f, 0.4f, 0.01f, 0.1f); + value->format = "%4.2f"; + value->AddSelectionListener(new dw::SelectionListenerOnHook( + (dw::SelectionListenerOnHook::CallbackFunc)ColorChangeDw::ValueCallback)); + value->callback_data.v64 = this; + + contrast = dw::Slider::Create(color_group, (dw::Flags)(dw::FLAG_800 | dw::HORIZONTAL), + 0.0f, 0.0f, 100.0f, glyph_height, "CONTRAST"); + contrast->SetParams(col_tone.contrast, 0.0f, 10.0, 2.0f, 0.01f, 0.1f); + contrast->format = "%4.2f"; + contrast->AddSelectionListener(new dw::SelectionListenerOnHook( + (dw::SelectionListenerOnHook::CallbackFunc)ColorChangeDw::ContrastCallback)); + contrast->callback_data.v64 = this; + + copy_button = new dw::Button(color_group, dw::FLAG_8); + copy_button->SetText("Copy"); + copy_button->callback = (dw::Widget::Callback)ColorChangeDw::CopyCallback; + copy_button->callback_data.v64 = this; + + paset_button = new dw::Button(color_group, dw::FLAG_8); + paset_button->SetText("Paste"); + paset_button->callback = (dw::Widget::Callback)ColorChangeDw::PasteCallback; + paset_button->callback_data.v64 = this; + + reset_button = new dw::Button(color_group, dw::FLAG_8); + reset_button->SetText("Reset"); + reset_button->callback = (dw::Widget::Callback)ColorChangeDw::ResetCallback; + reset_button->callback_data.v64 = this; + + (new dw::Label(color_group, dw::FLAG_4000))->SetText(" "); + + save_button = new dw::Button(color_group, dw::FLAG_8); + save_button->SetText("Save"); + save_button->callback = (dw::Widget::Callback)ColorChangeDw::SaveCallback; + save_button->callback_data.v64 = this; +} + +ColorChangeDw::~ColorChangeDw() { + +} + +void ColorChangeDw::Draw() { + UpdateData(); + UpdateTextureInfo(); + GetSetColorTone(); + + const texture* org_tex = GetOrgTex(); + const texture* chg_tex = GetChgTex(); + const color_tone* col_tone = GetColorTone(); + if (org_tex && chg_tex && col_tone) + texture_apply_color_tone(org_tex, chg_tex, col_tone); + + if (show) { + data_struct* aft_data = &data_list[DATA_AFT]; + sprite_database* aft_spr_db = &aft_data->data_ft.spr_db; + + if (org_tex) { + spr::SprArgs args; + args.texture = org_tex; + if (auto_resize) + args.SetSpriteSize(256.0f); + spr::put_sprite(args, aft_spr_db); + } + if (chg_tex) { + spr::SprArgs args; + args.texture = chg_tex; + args.trans.x = (float_t)chg_tex->width; + if (auto_resize) + { + args.SetSpriteSize(256.0f); + args.trans.x = 266.0; + } + spr::put_sprite(args, aft_spr_db); + } + } + + dw::Shell::Draw(); +} + +void ColorChangeDw::Reset() { + if (row_layout) { + delete row_layout; + row_layout = 0; + } + dw::Shell::Reset(); +} + +void ColorChangeDw::Hide() { + SetDisp(); +} + +texture* ColorChangeDw::GetChgTex() { + if (color_change_index < textures.size()) + return textures.data()[color_change_index]; + return 0; +} + +color_tone* ColorChangeDw::GetColorTone() { + if (color_change_index < color_tones.size()) + return &color_tones.data()[color_change_index]; + return 0; +} + +void ColorChangeDw::GetColorToneDefault(color_tone& value) { + value = color_tone(); +} + +const item_table_item* ColorChangeDw::GetItem(int32_t item_index) { + int32_t item_no = GetItemNo(item_index); + if (item_no != -1) + return item_table_handler_array_get_item(this->chara_index, item_no); + return 0; +} + +void ColorChangeDw::GetItemColTone() { + color_tone* col_tone = GetColorTone(); + if (col_tone) { + const item_table_item* item = GetItem(item_index); + if (item && item_texture_index < item->data.col.size()) + *col_tone = item->data.col.data()[item_texture_index].col_tone; + } +} + +const item_table_item_data* ColorChangeDw::GetItemData(int32_t item_index) { + const item_table_item* item = GetItem(item_index); + if (item) + return &item->data; + return 0; +} + +int32_t ColorChangeDw::GetItemNo(int32_t item_index) { + int32_t index = 0; + const item_table* item = item_table_handler_array_get_table(chara_index); + if (item) + for (auto& i : item->item) + if (i.second.attr & 0x68) { + if (item_index == index) + return 0; + index++; + } + return -1; +} + +const char* ColorChangeDw::GetItemTexChangeName() { + data_struct* aft_data = &data_list[DATA_AFT]; + texture_database* aft_tex_db = &aft_data->data_ft.tex_db; + + std::string item = item_texture_names->GetItemStr(item_texture_index); + const item_table_item_data* itm_data = GetItemData(item_index); + if (itm_data) + for (const item_table_item_data_tex& i : itm_data->tex) + if (!item.compare(aft_tex_db->get_texture_name(i.org))) + return aft_tex_db->get_texture_name(i.chg); + return 0; +} + +texture* ColorChangeDw::GetOrgTex() { + texture** textures = objset_info_storage_get_obj_set_textures(obj_set_id); + if (textures && color_change_index < objset_info_storage_get_obj_set_tex_num(obj_set_id)) + return textures[color_change_index]; + return 0; +} + +void ColorChangeDw::GetSetColorTone() { + color_tone* col_tone = GetColorTone(); + if (col_tone) { + inverse->SetValue(col_tone->inverse); + blend_r->SetValue(col_tone->blend.x); + blend_g->SetValue(col_tone->blend.y); + blend_b->SetValue(col_tone->blend.z); + offset_r->SetValue(col_tone->offset.x); + offset_g->SetValue(col_tone->offset.y); + offset_b->SetValue(col_tone->offset.z); + hue->SetValue(col_tone->hue); + saturation->SetValue(col_tone->saturation); + value->SetValue(col_tone->value); + contrast->SetValue(col_tone->contrast); + } +} + +void ColorChangeDw::GetTextureNames() { + data_struct* aft_data = &data_list[DATA_AFT]; + texture_database* aft_tex_db = &aft_data->data_ft.tex_db; + + if (!texture_names) + return; + + texture_names->ClearItems(); + + const int32_t tex_num = objset_info_storage_get_obj_set_tex_num(obj_set_id); + for (int32_t i = 0; i < tex_num; i++) { + uint32_t tex_id = objset_info_storage_get_obj_set_tex_id(obj_set_id, i); + + char buf[64]; + sprintf_s(buf, sizeof(buf), "%s", aft_tex_db->get_texture_name(tex_id)); + texture_names->AddItem(buf); + } + + texture_names->SetItemIndex(0); +} + +bool ColorChangeDw::LoadColorTone() { + ResetColorTone(); + if (!textures.size()) + return false; + + color_tone col_tone; + ColorChangeDw::GetColorToneDefault(col_tone); + for (texture*& i : textures) + color_tones.push_back(col_tone); + return true; +} + +void ColorChangeDw::LoadItemNames() { + +} + +bool ColorChangeDw::LoadTexture() { + ResetTexture(); + + texture** textures = objset_info_storage_get_obj_set_textures(obj_set_id); + if (!textures) + return false; + + const int32_t tex_num = objset_info_storage_get_obj_set_tex_num(obj_set_id); + for (int32_t i = 0; i < tex_num; i++) { + texture* tex = 0; + if (textures[i]->target == GL_TEXTURE_2D) { + tex = texture_create_copy_texture(texture_id(0x22, i), textures[i]); + if (!tex) + break; + } + this->textures.push_back(tex); + } + return true; +} + +void ColorChangeDw::ReloadData() { + ResetData(); + if (LoadTexture() && LoadColorTone()) + set = true; + else + ResetData(); +} + +void ColorChangeDw::ResetColorTone() { + color_tones.clear(); +} + +void ColorChangeDw::ResetData() { + set = false; + ResetTexture(); + ResetColorTone(); +} + +void ColorChangeDw::ResetTexture() { + if (!textures.size()) + return; + + for (texture*& i : textures) + if (i) { + texture_release(i); + i = 0; + } + textures.clear(); +} + +void ColorChangeDw::SetObjectSet(const char* str) { + if (!str) + return; + + const size_t size = object_sets->GetItemCount(); + for (size_t i = 0; i < size; i++) { + std::string item = object_sets->GetItemStr(i); + if (!item.compare(str)) { + object_sets->list->SetItemIndex(i); + ColorChangeDw::ObjectSetCallback(object_sets); + break; + } + } +} + +void ColorChangeDw::SetTextureName(const char* name) { + if (!name) + return; + + const size_t size = texture_names->GetItemCount(); + for (size_t i = 0; i < size; i++) { + std::string item = texture_names->GetItemStr(i); + if (!item.compare(name)) { + object_sets->list->SetItemIndex(i); + ColorChangeDw::TextureCallback(texture_names); + break; + } + } +} + +void ColorChangeDw::UpdateData() { + if (!set) + ReloadData(); + else if (!objset_info_storage_get_obj_set_textures(obj_set_id)) + ResetData(); +} + +void ColorChangeDw::UpdateItemTextureNames() { + data_struct* aft_data = &data_list[DATA_AFT]; + texture_database* aft_tex_db = &aft_data->data_ft.tex_db; + + if (!item_texture_names) + return; + + item_texture_names->ClearItems(); + const item_table_item_data* itm_data = GetItemData(item_index); + if (!itm_data) + return; + + for (const item_table_item_data_col& i : itm_data->col) { + const char* name = aft_tex_db->get_texture_name(i.tex_id); + if (name) + item_texture_names->AddItem(name); + } + + item_texture_names->SetItemIndex(0); + item_texture_index = 0; + + ColorChangeDw::ItemTextureCallback(item_texture_names); +} + +void ColorChangeDw::UpdateTextureInfo() { + const texture* org_tex = GetOrgTex(); + if (org_tex) { + std::string type("Type "); + type.append(texture_get_target_name(org_tex->target)); + this->type->SetText(type); + + std::string format("Format "); + format.append(texture_get_internal_format_name(org_tex->internal_format)); + this->format->SetText(format); + + std::string size("Size "); + size.append(sprintf_s_string("%d", org_tex->width)); + size.append("x"); + size.append(sprintf_s_string("%d", org_tex->height)); + this->size->SetText(size); + } + else { + type->SetText("Type ****"); + format->SetText("Format ****"); + size->SetText("Size ****"); + } +} + +void ColorChangeDw::AutoResizeCallback(dw::Button* data) { + ColorChangeDw* color_change_dw = (ColorChangeDw*)data->callback_data.v64; + color_change_dw->auto_resize = data->value; +} + +void ColorChangeDw::BlendBCallback(dw::Slider* data) { + ColorChangeDw* color_change_dw = (ColorChangeDw*)data->callback_data.v64; + color_tone* col_tone = color_change_dw->GetColorTone(); + if (col_tone) + col_tone->blend.z = data->scroll_bar->value; +} + +void ColorChangeDw::BlendGCallback(dw::Slider* data) { + ColorChangeDw* color_change_dw = (ColorChangeDw*)data->callback_data.v64; + color_tone* col_tone = color_change_dw->GetColorTone(); + if (col_tone) + col_tone->blend.y = data->scroll_bar->value; +} + +void ColorChangeDw::BlendRCallback(dw::Slider* data) { + ColorChangeDw* color_change_dw = (ColorChangeDw*)data->callback_data.v64; + color_tone* col_tone = color_change_dw->GetColorTone(); + if (col_tone) + col_tone->blend.x = data->scroll_bar->value; +} + +void ColorChangeDw::ContrastCallback(dw::Slider* data) { + ColorChangeDw* color_change_dw = (ColorChangeDw*)data->callback_data.v64; + color_tone* col_tone = color_change_dw->GetColorTone(); + if (col_tone) + col_tone->contrast = data->scroll_bar->value; +} + +void ColorChangeDw::CopyCallback(dw::Button* data) { + ColorChangeDw* color_change_dw = (ColorChangeDw*)data->callback_data.v64; + color_tone* col_tone = color_change_dw->GetColorTone(); + if (col_tone) + color_change_dw->color_tone_temp = *col_tone; +} + +void ColorChangeDw::HueCallback(dw::Slider* data) { + ColorChangeDw* color_change_dw = (ColorChangeDw*)data->callback_data.v64; + color_tone* col_tone = color_change_dw->GetColorTone(); + if (col_tone) + col_tone->hue = data->scroll_bar->value; +} + +void ColorChangeDw::InverseCallback(dw::Button* data) { + ColorChangeDw* color_change_dw = (ColorChangeDw*)data->callback_data.v64; + color_tone* col_tone = color_change_dw->GetColorTone(); + if (col_tone) + col_tone->inverse = data->value; +} + +void ColorChangeDw::ItemCallback(dw::ListBox* data) { + data_struct* aft_data = &data_list[DATA_AFT]; + object_database* aft_obj_db = &aft_data->data_ft.obj_db; + + int32_t index = (int32_t)data->list->selected_item; + ColorChangeDw* color_change_dw = (ColorChangeDw*)data->callback_data.v64; + color_change_dw->item_index = index; + + const item_table_item* item = color_change_dw->GetItem(index); + if (!item) { + color_change_dw->UpdateItemTextureNames(); + return; + } + + const char* name = 0; + for (const uint32_t& i : item->objset) + name = aft_obj_db->get_object_set_name(i); + + if (item->attr & 0x40) + name = aft_obj_db->get_object_set_name(chara_init_data_get(color_change_dw->chara_index)->object_set); + + if (name) { + color_change_dw->SetObjectSet(name); + color_change_dw->UpdateItemTextureNames(); + } +} + +void ColorChangeDw::ItemCharaCallback(dw::ListBox* data) { + ColorChangeDw* color_change_dw = (ColorChangeDw*)data->callback_data.v64; + color_change_dw->LoadItemNames(); + color_change_dw->ItemCallback(color_change_dw->item_names); +} + +void ColorChangeDw::ItemTextureCallback(dw::ListBox* data) { + ColorChangeDw* color_change_dw = (ColorChangeDw*)data->callback_data.v64; + color_change_dw->item_texture_index = data->list->selected_item; + + const item_table_item* item = color_change_dw->GetItem(color_change_dw->item_index); + if (!item) + return; + + const size_t size = data->GetItemCount(); + if (!size || color_change_dw->item_texture_index >= size) + return; + + if (item->attr & 0x04) { + const char* name = color_change_dw->GetItemTexChangeName(); + if (name) + color_change_dw->SetTextureName(name); + } + else { + std::string item = data->GetItemStr(color_change_dw->item_texture_index); + color_change_dw->SetTextureName(item.c_str()); + } +} + +void ColorChangeDw::ObjectSetCallback(dw::ListBox* data) { + data_struct* aft_data = &data_list[DATA_AFT]; + object_database* aft_obj_db = &aft_data->data_ft.obj_db; + + ColorChangeDw* color_change_dw = (ColorChangeDw*)data->callback_data.v64; + int32_t obj_set_index = (int32_t)data->list->selected_item; + color_change_dw->obj_set_index = obj_set_index; + + uint32_t obj_set_id = aft_obj_db->get_object_set_id(obj_set_index); + if (obj_set_id != color_change_dw->obj_set_id) { + color_change_dw->obj_set_id = obj_set_id; + color_change_dw->GetTextureNames(); + color_change_dw->ResetData(); + color_change_dw->ReloadData(); + } +} + +void ColorChangeDw::OffsetBCallback(dw::Slider* data) { + ColorChangeDw* color_change_dw = (ColorChangeDw*)data->callback_data.v64; + color_tone* col_tone = color_change_dw->GetColorTone(); + if (col_tone) + col_tone->offset.z = data->scroll_bar->value; +} + +void ColorChangeDw::OffsetGCallback(dw::Slider* data) { + ColorChangeDw* color_change_dw = (ColorChangeDw*)data->callback_data.v64; + color_tone* col_tone = color_change_dw->GetColorTone(); + if (col_tone) + col_tone->offset.y = data->scroll_bar->value; +} + +void ColorChangeDw::OffsetRCallback(dw::Slider* data) { + ColorChangeDw* color_change_dw = (ColorChangeDw*)data->callback_data.v64; + color_tone* col_tone = color_change_dw->GetColorTone(); + if (col_tone) + col_tone->offset.x = data->scroll_bar->value; +} + +void ColorChangeDw::OverwriteCallback(dw::Button* data) { + +} + +void ColorChangeDw::PasteCallback(dw::Button* data) { + ColorChangeDw* color_change_dw = (ColorChangeDw*)data->callback_data.v64; + color_tone* col_tone = color_change_dw->GetColorTone(); + if (col_tone) + *col_tone = color_change_dw->color_tone_temp; +} + +void ColorChangeDw::ResetCallback(dw::Button* data) { + ColorChangeDw* color_change_dw = (ColorChangeDw*)data->callback_data.v64; + color_tone* col_tone = color_change_dw->GetColorTone(); + if (col_tone) + color_change_dw->GetColorToneDefault(*col_tone); +} + +void ColorChangeDw::SaturationCallback(dw::Slider* data) { + ColorChangeDw* color_change_dw = (ColorChangeDw*)data->callback_data.v64; + color_tone* col_tone = color_change_dw->GetColorTone(); + if (col_tone) + col_tone->saturation = data->scroll_bar->value; +} + +void ColorChangeDw::SaveCallback(dw::Button* data) { + +} + +void ColorChangeDw::ShowCallback(dw::Button* data) { + ColorChangeDw* color_change_dw = (ColorChangeDw*)data->callback_data.v64; + color_change_dw->show = data->value; +} + +void ColorChangeDw::TextureCallback(dw::ListBox* data) { + size_t index = data->list->selected_item; + ColorChangeDw* color_change_dw = (ColorChangeDw*)data->callback_data.v64; + if (objset_info_storage_get_obj_set_textures(color_change_dw->obj_set_id) + && index < objset_info_storage_get_obj_set_tex_num(color_change_dw->obj_set_id)) + color_change_dw->color_change_index = index; +} + +void ColorChangeDw::ValueCallback(dw::Slider* data) { + ColorChangeDw* color_change_dw = (ColorChangeDw*)data->callback_data.v64; + color_tone* col_tone = color_change_dw->GetColorTone(); + if (col_tone) + col_tone->value = data->scroll_bar->value; +} + +static const char* get_dev_ram_color_change_param_dir() { + return "dev_ram/color_change_param"; +} diff --git a/src/ReDIVA/graphics/color_change.hpp b/src/ReDIVA/graphics/color_change.hpp new file mode 100644 index 00000000..95187083 --- /dev/null +++ b/src/ReDIVA/graphics/color_change.hpp @@ -0,0 +1,10 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#pragma once + +#include "../../KKdLib/default.hpp" + +extern void color_change_dw_init();