paint: edit uv map
This commit is contained in:
@@ -0,0 +1,176 @@
|
||||
|
||||
#include "global.h"
|
||||
|
||||
static i32_array_t *_selected_verts = NULL;
|
||||
static bool _is_dragging = false;
|
||||
static bool _is_box_sel = false;
|
||||
static f32 _box_x0;
|
||||
static f32 _box_y0;
|
||||
static f32 _box_x1;
|
||||
static f32 _box_y1;
|
||||
|
||||
static bool _is_selected(i32 idx) {
|
||||
for (i32 i = 0; i < _selected_verts->length; i++) {
|
||||
if (_selected_verts->buffer[i] == idx) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void _get_tex_transform(f32 *out_tx, f32 *out_ty, f32 *out_tw, f32 *out_th) {
|
||||
i32 headerh = g_config->layout->buffer[LAYOUT_SIZE_HEADER] == 1 ? ui_header_h * 2 : ui_header_h;
|
||||
i32 apph = iron_window_height() - g_config->layout->buffer[LAYOUT_SIZE_STATUS_H] + headerh;
|
||||
if (!base_view3d_show) {
|
||||
apph = base_h();
|
||||
}
|
||||
f32 wm = fmin(ui_view2d_ww, ui_view2d_wh);
|
||||
f32 tw = wm * 0.9f * ui_view2d_pan_scale;
|
||||
f32 th = tw;
|
||||
if (util_uv_uvmap != NULL) {
|
||||
th = tw * (util_uv_uvmap->height / (f32)util_uv_uvmap->width);
|
||||
}
|
||||
*out_tw = tw;
|
||||
*out_th = th;
|
||||
*out_tx = ui_view2d_ww / 2.0f - tw / 2.0f + ui_view2d_pan_x;
|
||||
*out_ty = apph / 2.0f - th / 2.0f + ui_view2d_pan_y;
|
||||
}
|
||||
|
||||
void edit_uvmap_update() {
|
||||
if (g_context->paint_object == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_selected_verts == NULL) {
|
||||
_selected_verts = i32_array_create_from_raw((i32[]){0}, 1);
|
||||
gc_root(_selected_verts);
|
||||
_selected_verts->length = 0;
|
||||
}
|
||||
|
||||
mesh_data_t *mesh = g_context->paint_object->data;
|
||||
i16_array_t *texa = mesh->vertex_arrays->buffer[2]->values;
|
||||
i32 num_verts = texa->length / 2;
|
||||
|
||||
f32 tx, ty, tw, th;
|
||||
_get_tex_transform(&tx, &ty, &tw, &th);
|
||||
|
||||
f32 mx = mouse_x - ui_view2d_wx;
|
||||
f32 my = mouse_y - ui_view2d_wy;
|
||||
bool in_view = mx >= 0 && mx < ui_view2d_ww && my >= 0 && my < ui_view2d_wh;
|
||||
|
||||
if (in_view && mouse_started("left")) {
|
||||
f32 min_dist_sq = 20.0f * 20.0f;
|
||||
i32 closest = -1;
|
||||
for (i32 i = 0; i < num_verts; i++) {
|
||||
f32 vx = tx + (f32)texa->buffer[i * 2] / 32767.0f * tw;
|
||||
f32 vy = ty + (f32)texa->buffer[i * 2 + 1] / 32767.0f * th;
|
||||
f32 dx = mx - vx;
|
||||
f32 dy = my - vy;
|
||||
f32 dist_sq = dx * dx + dy * dy;
|
||||
if (dist_sq < min_dist_sq) {
|
||||
min_dist_sq = dist_sq;
|
||||
closest = i;
|
||||
}
|
||||
}
|
||||
if (closest >= 0) {
|
||||
if (!_is_selected(closest)) {
|
||||
_selected_verts->length = 0;
|
||||
i32_array_push(_selected_verts, closest);
|
||||
}
|
||||
_is_dragging = true;
|
||||
}
|
||||
else {
|
||||
_selected_verts->length = 0;
|
||||
_is_box_sel = true;
|
||||
_box_x0 = _box_x1 = mx;
|
||||
_box_y0 = _box_y1 = my;
|
||||
}
|
||||
}
|
||||
|
||||
if (mouse_started("right")) {
|
||||
_selected_verts->length = 0;
|
||||
_is_dragging = false;
|
||||
_is_box_sel = false;
|
||||
ui_view2d_hwnd->redraws = 2;
|
||||
}
|
||||
|
||||
if (_is_dragging && mouse_down("left")) {
|
||||
f32 duv_x = ui->input_dx / tw * 32767.0f;
|
||||
f32 duv_y = ui->input_dy / th * 32767.0f;
|
||||
for (i32 i = 0; i < _selected_verts->length; i++) {
|
||||
i32 vi = _selected_verts->buffer[i];
|
||||
i32 new_x = (i32)texa->buffer[vi * 2] + (i32)duv_x;
|
||||
i32 new_y = (i32)texa->buffer[vi * 2 + 1] + (i32)duv_y;
|
||||
texa->buffer[vi * 2] = (i16)math_min(math_max(new_x, -32767), 32767);
|
||||
texa->buffer[vi * 2 + 1] = (i16)math_min(math_max(new_y, -32767), 32767);
|
||||
}
|
||||
util_uv_uvmap_cached = false;
|
||||
ui_view2d_hwnd->redraws = 2;
|
||||
}
|
||||
|
||||
if (_is_box_sel && mouse_down("left")) {
|
||||
_box_x1 = mx;
|
||||
_box_y1 = my;
|
||||
ui_view2d_hwnd->redraws = 2;
|
||||
}
|
||||
|
||||
if (mouse_released("left")) {
|
||||
if (_is_dragging) {
|
||||
_is_dragging = false;
|
||||
mesh_object_t *o = g_context->paint_object;
|
||||
mesh_data_build_vertices(o->data->_->vertex_buffer, o->data->vertex_arrays);
|
||||
util_uv_uvmap_cached = false;
|
||||
util_uv_trianglemap_cached = false;
|
||||
}
|
||||
if (_is_box_sel) {
|
||||
_is_box_sel = false;
|
||||
f32 bx0 = math_min(_box_x0, _box_x1);
|
||||
f32 bx1 = math_max(_box_x0, _box_x1);
|
||||
f32 by0 = math_min(_box_y0, _box_y1);
|
||||
f32 by1 = math_max(_box_y0, _box_y1);
|
||||
_selected_verts->length = 0;
|
||||
for (i32 i = 0; i < num_verts; i++) {
|
||||
f32 vx = tx + (f32)texa->buffer[i * 2] / 32767.0f * tw;
|
||||
f32 vy = ty + (f32)texa->buffer[i * 2 + 1] / 32767.0f * th;
|
||||
if (vx >= bx0 && vx <= bx1 && vy >= by0 && vy <= by1) {
|
||||
i32_array_push(_selected_verts, i);
|
||||
}
|
||||
}
|
||||
ui_view2d_hwnd->redraws = 2;
|
||||
}
|
||||
}
|
||||
|
||||
// All vertices - black squares
|
||||
f32 vs = 3.0f * UI_SCALE();
|
||||
draw_set_color(0xff000000);
|
||||
for (i32 i = 0; i < num_verts; i++) {
|
||||
f32 vx = tx + (f32)texa->buffer[i * 2] / 32767.0f * tw;
|
||||
f32 vy = ty + (f32)texa->buffer[i * 2 + 1] / 32767.0f * th;
|
||||
draw_filled_rect(vx - vs, vy - vs, vs * 2.0f, vs * 2.0f);
|
||||
}
|
||||
|
||||
// Selected vertices - white squares
|
||||
f32 s = 5.0f * UI_SCALE();
|
||||
draw_set_color(0xffffffff);
|
||||
for (i32 i = 0; i < _selected_verts->length; i++) {
|
||||
i32 vi = _selected_verts->buffer[i];
|
||||
f32 vx = tx + (f32)texa->buffer[vi * 2] / 32767.0f * tw;
|
||||
f32 vy = ty + (f32)texa->buffer[vi * 2 + 1] / 32767.0f * th;
|
||||
draw_filled_rect(vx - s, vy - s, s * 2.0f, s * 2.0f);
|
||||
}
|
||||
|
||||
// Box select rectangle
|
||||
if (_is_box_sel) {
|
||||
f32 bx = math_min(_box_x0, _box_x1);
|
||||
f32 by = math_min(_box_y0, _box_y1);
|
||||
f32 bw = math_abs(_box_x1 - _box_x0);
|
||||
f32 bh = math_abs(_box_y1 - _box_y0);
|
||||
draw_set_color(0xffffffff);
|
||||
draw_line_aa(bx, by, bx + bw, by, 1.0f);
|
||||
draw_line_aa(bx + bw, by, bx + bw, by + bh, 1.0f);
|
||||
draw_line_aa(bx + bw, by + bh, bx, by + bh, 1.0f);
|
||||
draw_line_aa(bx, by + bh, bx, by, 1.0f);
|
||||
}
|
||||
|
||||
draw_set_color(0xffffffff);
|
||||
}
|
||||
@@ -188,6 +188,7 @@ typedef enum {
|
||||
VIEW_2D_TYPE_NODE = 1,
|
||||
VIEW_2D_TYPE_FONT = 2,
|
||||
VIEW_2D_TYPE_LAYER = 3,
|
||||
VIEW_2D_TYPE_UVMAP = 4,
|
||||
} view_2d_type_t;
|
||||
|
||||
typedef enum {
|
||||
|
||||
@@ -700,3 +700,4 @@ float_node_t *float_node_create(ui_node_t *raw, f32_array_t *args);
|
||||
integer_node_t *integer_node_create(ui_node_t *raw, f32_array_t *args);
|
||||
separate_vector_node_t *separate_vector_node_create(ui_node_t *raw, f32_array_t *args);
|
||||
brush_output_node_t *brush_output_node_create(ui_node_t *raw, f32_array_t *args);
|
||||
void edit_uvmap_update();
|
||||
|
||||
@@ -101,6 +101,7 @@
|
||||
#include "config.c"
|
||||
#include "console.c"
|
||||
#include "context.c"
|
||||
#include "edit_uvmap.c"
|
||||
#include "export_arm.c"
|
||||
#include "export_exr.c"
|
||||
#include "export_mesh.c"
|
||||
|
||||
@@ -301,6 +301,10 @@ void tab_meshes_draw_edit() {
|
||||
ui_menu_sub_end();
|
||||
}
|
||||
|
||||
if (ui_menu_button(tr("Edit UV Map"), "", ICON_NONE)) {
|
||||
ui_base_show_2d_view(VIEW_2D_TYPE_UVMAP);
|
||||
}
|
||||
|
||||
#ifdef WITH_PLUGINS
|
||||
if (ui_menu_button(tr("UV Unwrap"), "", ICON_NONE)) {
|
||||
plugin_uv_unwrap_button();
|
||||
|
||||
@@ -101,7 +101,7 @@ void ui_view2d_render(void *_) {
|
||||
}
|
||||
|
||||
// Ensure UV map is drawn
|
||||
if (ui_view2d_uvmap_show) {
|
||||
if (ui_view2d_uvmap_show || ui_view2d_type == VIEW_2D_TYPE_UVMAP) {
|
||||
util_uv_cache_uv_map();
|
||||
}
|
||||
|
||||
@@ -178,7 +178,7 @@ void ui_view2d_render(void *_) {
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (ui_view2d_type == VIEW_2D_TYPE_LAYER) {
|
||||
else if (ui_view2d_type == VIEW_2D_TYPE_LAYER || ui_view2d_type == VIEW_2D_TYPE_UVMAP) {
|
||||
slot_layer_t *layer = l;
|
||||
|
||||
if (g_config->brush_live && render_path_paint_live_layer_drawn > 0) {
|
||||
@@ -273,6 +273,11 @@ void ui_view2d_render(void *_) {
|
||||
draw_scaled_image(util_uv_uvmap, tx, ty, tw, th);
|
||||
}
|
||||
|
||||
if (ui_view2d_type == VIEW_2D_TYPE_UVMAP) {
|
||||
draw_scaled_image(util_uv_uvmap, tx, ty, tw, th);
|
||||
edit_uvmap_update();
|
||||
}
|
||||
|
||||
// Menu
|
||||
i32 top_y = ui_menu_top_y();
|
||||
i32 ew = math_floor(UI_ELEMENT_W());
|
||||
@@ -414,10 +419,11 @@ void ui_view2d_render(void *_) {
|
||||
ui->_y = 2 + start_y;
|
||||
}
|
||||
|
||||
char *view_type = ui_view2d_type == VIEW_2D_TYPE_ASSET ? tr("Asset")
|
||||
: ui_view2d_type == VIEW_2D_TYPE_NODE ? tr("Node")
|
||||
: ui_view2d_type == VIEW_2D_TYPE_FONT ? tr("Font")
|
||||
: tr("Layer");
|
||||
char *view_type = ui_view2d_type == VIEW_2D_TYPE_ASSET ? tr("Asset")
|
||||
: ui_view2d_type == VIEW_2D_TYPE_NODE ? tr("Node")
|
||||
: ui_view2d_type == VIEW_2D_TYPE_FONT ? tr("Font")
|
||||
: ui_view2d_type == VIEW_2D_TYPE_UVMAP ? tr("UVMap")
|
||||
: tr("Layer");
|
||||
|
||||
ui->_w = math_floor(ew * 0.5 + 3);
|
||||
ui_text(view_type, UI_ALIGN_LEFT, 0x00000000);
|
||||
|
||||
Reference in New Issue
Block a user