paint: improve timeline skinning
This commit is contained in:
@@ -5,7 +5,6 @@ ui_handle_t *h0;
|
||||
ui_handle_t *h1;
|
||||
ui_handle_t *h2;
|
||||
ui_handle_t *h3;
|
||||
ui_handle_t *h4;
|
||||
|
||||
void *tilesheet;
|
||||
int baking;
|
||||
@@ -17,8 +16,7 @@ int frame;
|
||||
int col;
|
||||
int row;
|
||||
int wait;
|
||||
int skinning;
|
||||
int reimported;
|
||||
int reskinned;
|
||||
|
||||
void on_update() {
|
||||
if (!baking) {
|
||||
@@ -28,11 +26,13 @@ void on_update() {
|
||||
iron_delay_idle_sleep();
|
||||
|
||||
if (frame < frames) {
|
||||
if (skinning && !reimported) {
|
||||
project_reimport_mesh_skinned(frame);
|
||||
reimported = 1;
|
||||
wait = 2; // Wait for re-import and re-render
|
||||
return;
|
||||
if (!reskinned) {
|
||||
reskinned = 1;
|
||||
// Pose the mesh at this frame, only meshes imported with skinning applied
|
||||
if (project_reskin_mesh(frame)) {
|
||||
wait = 2; // Wait for re-render
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (wait > 0) {
|
||||
@@ -50,7 +50,7 @@ void on_update() {
|
||||
col = 0;
|
||||
row = row + 1;
|
||||
}
|
||||
reimported = 0;
|
||||
reskinned = 0;
|
||||
}
|
||||
else {
|
||||
viewport_save_texture(tilesheet);
|
||||
@@ -69,13 +69,11 @@ void on_ui() {
|
||||
ui_slider(h1, "Tile Size", 0, 512, true, 1, true, UI_ALIGN_LEFT, true);
|
||||
ui_slider(h2, "Columns", 0, 64, true, 1, true, UI_ALIGN_LEFT, true);
|
||||
ui_slider(h3, "Frames", 0, 1024, true, 1, true, UI_ALIGN_LEFT, true);
|
||||
ui_check(h4, "Skinning", "");
|
||||
|
||||
if (ui_button("Bake", UI_ALIGN_CENTER, "") && !baking) {
|
||||
tile_size = h1->f;
|
||||
columns = h2->f;
|
||||
frames = h3->f;
|
||||
skinning = h4->b;
|
||||
|
||||
// Square atlas
|
||||
int size = tile_size * columns;
|
||||
@@ -86,7 +84,7 @@ void on_ui() {
|
||||
col = 0;
|
||||
row = 0;
|
||||
wait = 2;
|
||||
reimported = 0;
|
||||
reskinned = 0;
|
||||
baking = 1;
|
||||
context_t *c = script_get_context();
|
||||
c->capturing_screenshot = true;
|
||||
@@ -104,8 +102,6 @@ void main() {
|
||||
h2->f = 8;
|
||||
h3 = ui_handle_create();
|
||||
h3->f = 64;
|
||||
h4 = ui_handle_create();
|
||||
h4->b = 0;
|
||||
tilesheet = NULL;
|
||||
baking = 0;
|
||||
gc_root(plugin);
|
||||
@@ -113,7 +109,6 @@ void main() {
|
||||
gc_root(h1);
|
||||
gc_root(h2);
|
||||
gc_root(h3);
|
||||
gc_root(h4);
|
||||
plugin_notify_on_ui(plugin, on_ui);
|
||||
plugin_notify_on_update(plugin, on_update);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,9 @@
|
||||
#include "engine.h"
|
||||
#include "iron_array.h"
|
||||
#include "iron_map.h"
|
||||
#include "iron_obj.h"
|
||||
#include "iron_ui.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
void *io_svg_parse(char *buf);
|
||||
void *io_exr_parse(char *buf, size_t len);
|
||||
@@ -79,6 +81,57 @@ static void *import_svg(char *path) {
|
||||
return io_svg_parse((char *)b->buffer);
|
||||
}
|
||||
|
||||
static buffer_t *plugins_skin_blob = NULL;
|
||||
|
||||
void plugins_skin_data_clear() {
|
||||
gc_unroot(plugins_skin_blob);
|
||||
plugins_skin_blob = NULL;
|
||||
}
|
||||
|
||||
static void plugins_skin_data_set(buffer_t *b) {
|
||||
plugins_skin_data_clear();
|
||||
plugins_skin_blob = b;
|
||||
gc_root(plugins_skin_blob);
|
||||
}
|
||||
|
||||
bool plugins_skin_data_exists() {
|
||||
return plugins_skin_blob != NULL;
|
||||
}
|
||||
|
||||
static void plugins_free_raw_mesh(raw_mesh_t *raw) {
|
||||
i16_array_t *arrays[] = {raw->posa, raw->nora, raw->texa, raw->texa1, raw->cola};
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
if (arrays[i] != NULL) {
|
||||
free(arrays[i]->buffer);
|
||||
free(arrays[i]);
|
||||
}
|
||||
}
|
||||
if (raw->inda != NULL) {
|
||||
free(raw->inda->buffer);
|
||||
free(raw->inda);
|
||||
}
|
||||
free(raw->name);
|
||||
free(raw);
|
||||
}
|
||||
|
||||
bool plugins_skin_data_apply(int frame, i16_array_t *posa, i16_array_t *nora, float *scale_pos) {
|
||||
if (plugins_skin_blob == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
raw_mesh_t *raw = io_gltf_parse_skinned((char *)plugins_skin_blob->buffer, plugins_skin_blob->length, NULL, frame);
|
||||
if (raw == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(posa->buffer, raw->posa->buffer, posa->length * sizeof(int16_t));
|
||||
memcpy(nora->buffer, raw->nora->buffer, nora->length * sizeof(int16_t));
|
||||
*scale_pos = raw->scale_pos;
|
||||
|
||||
plugins_free_raw_mesh(raw);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void *import_gltf_glb(char *path) {
|
||||
buffer_t *b = data_get_blob(path);
|
||||
data_delete_blob(path);
|
||||
@@ -86,6 +139,7 @@ static void *import_gltf_glb(char *path) {
|
||||
return io_gltf_parse((char *)b->buffer, b->length, path);
|
||||
}
|
||||
else {
|
||||
plugins_skin_data_set(b);
|
||||
return io_gltf_parse_skinned((char *)b->buffer, b->length, path, plugins_skinning_frame);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -441,7 +441,7 @@ void project_import_mesh(bool replace_existing, void (*done
|
||||
void project_append_mesh();
|
||||
void project_import_mesh_box(char *path, bool replace_existing, bool clear_layers, bool keep_camera, void (*done)(void));
|
||||
void project_reimport_mesh();
|
||||
void project_reimport_mesh_skinned(int frame);
|
||||
bool project_reskin_mesh(int frame);
|
||||
void project_unwrap_mesh_box();
|
||||
void project_import_asset(char *filters, bool hdr_as_envmap);
|
||||
void project_import_swatches(bool replace_existing);
|
||||
@@ -612,6 +612,9 @@ void import_keymap_run(char *path);
|
||||
void tab_plugins_draw(ui_handle_t *htab);
|
||||
void plugin_uv_unwrap_button();
|
||||
void plugin_uv_unwrap_per_object_button(mesh_object_t *mo);
|
||||
void plugins_skin_data_clear();
|
||||
bool plugins_skin_data_exists();
|
||||
bool plugins_skin_data_apply(int frame, i16_array_t *posa, i16_array_t *nora, float *scale_pos);
|
||||
void make_discard_color_id(node_shader_t *kong, char *tex_coord);
|
||||
void make_discard_face(node_shader_t *kong);
|
||||
void make_discard_uv_island(node_shader_t *kong);
|
||||
|
||||
@@ -19,6 +19,12 @@ void import_mesh_run(char *path, bool _clear_layers, bool replace_existing, bool
|
||||
import_mesh_no_reset = keep_camera;
|
||||
g_context->layer_filter = 0;
|
||||
|
||||
#ifdef WITH_PLUGINS
|
||||
if (replace_existing) {
|
||||
plugins_skin_data_clear();
|
||||
}
|
||||
#endif
|
||||
|
||||
char *p = to_lower_case(path);
|
||||
if (ends_with(p, ".obj")) {
|
||||
import_obj_run(path, replace_existing);
|
||||
|
||||
@@ -44,7 +44,7 @@ void project_save(bool save_and_quit);
|
||||
char *project_filepath_get();
|
||||
char *project_basepath_get();
|
||||
void project_filepath_set(char *s);
|
||||
void project_reimport_mesh_skinned(i32 frame);
|
||||
bool project_reskin_mesh(int frame);
|
||||
void context_set_viewport_shader(void *viewport_shader);
|
||||
void context_set_viewport_mode(int mode);
|
||||
void context_set_camera_controls(int i);
|
||||
@@ -1252,7 +1252,7 @@ void minic_register_builtins() {
|
||||
R(gpu_create_render_target, "p(i,i,i)");
|
||||
R(viewport_capture_screenshot_to, "v(p,f,f,f,f)");
|
||||
R(viewport_save_texture, "v(p)");
|
||||
R(project_reimport_mesh_skinned, "v(i)");
|
||||
R(project_reskin_mesh, "b(i)");
|
||||
R(iron_delay_idle_sleep, "v()");
|
||||
|
||||
// json
|
||||
|
||||
+23
-11
@@ -376,18 +376,30 @@ void project_reimport_mesh() {
|
||||
}
|
||||
}
|
||||
|
||||
void project_reimport_mesh_skinned(int frame) {
|
||||
extern bool import_mesh_no_scale;
|
||||
extern bool import_mesh_keep_timeline;
|
||||
extern int plugins_skinning_frame;
|
||||
if (g_project->mesh_assets != NULL && g_project->mesh_assets->length > 0 && iron_file_exists(g_project->mesh_assets->buffer[0])) {
|
||||
plugins_skinning_frame = frame;
|
||||
import_mesh_no_scale = true;
|
||||
import_mesh_keep_timeline = true;
|
||||
import_mesh_run(g_project->mesh_assets->buffer[0], false, true, true);
|
||||
import_mesh_keep_timeline = false;
|
||||
plugins_skinning_frame = -1;
|
||||
bool project_reskin_mesh(int frame) {
|
||||
#ifdef WITH_PLUGINS
|
||||
if (!plugins_skin_data_exists()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mesh_data_t *md = context_main_object()->data;
|
||||
vertex_array_t *pos = mesh_data_get_vertex_array(md, "pos");
|
||||
vertex_array_t *nor = mesh_data_get_vertex_array(md, "nor");
|
||||
if (!plugins_skin_data_apply(frame, pos->values, nor->values, &md->scale_pos)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mesh_data_build_vertices(md->_->vertex_buffer, md->vertex_arrays);
|
||||
|
||||
if (g_context->merged_object != NULL) {
|
||||
util_mesh_merge(NULL);
|
||||
}
|
||||
g_context->ddirty = 4;
|
||||
render_path_raytrace_ready = false;
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void project_unwrap_mesh(raw_mesh_t *mesh, void (*done)(raw_mesh_t *)) {
|
||||
|
||||
@@ -35,7 +35,6 @@ i32 tab_timeline_scroll_drag_v = 0;
|
||||
|
||||
static i32 tab_timeline_max_frames = 200;
|
||||
static i32 tab_timeline_frame_rate = 24;
|
||||
static bool tab_timeline_skinning = false;
|
||||
static any_array_t *tab_timeline_keyframes = NULL;
|
||||
static any_array_t *tab_timeline_origins = NULL;
|
||||
static i32 tab_timeline_last_frame = 0;
|
||||
@@ -489,9 +488,7 @@ static void tab_timeline_frame_change_on_next_frame(void *_) {
|
||||
to == 0 ? tab_timeline_load_mesh_origins() : tab_timeline_load_mesh_from_keyframes((float)to);
|
||||
}
|
||||
|
||||
if (tab_timeline_skinning) {
|
||||
project_reimport_mesh_skinned(to);
|
||||
}
|
||||
project_reskin_mesh(to);
|
||||
}
|
||||
|
||||
static void tab_timeline_add_keyframe_on_next_frame(void *_) {
|
||||
@@ -946,14 +943,6 @@ void tab_timeline_draw_edit() {
|
||||
ui_menu_keep_open = true;
|
||||
}
|
||||
|
||||
ui_handle_t *hskin = ui_handle(__ID__);
|
||||
hskin->b = tab_timeline_skinning;
|
||||
ui_check(hskin, tr("Skinning"), "");
|
||||
if (hskin->changed) {
|
||||
tab_timeline_skinning = hskin->b;
|
||||
ui_menu_keep_open = true;
|
||||
}
|
||||
|
||||
if (ui_menu_button(tr("Clear"), "", ICON_ERASE)) {
|
||||
sys_notify_on_next_frame(&tab_timeline_clear_on_next_frame, NULL);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user