UV: add pack to custom region option to "Pack Islands" operator
This commit implements the design task #78398 - Box region - Set Custom UV Region (Ctrl-B). - Disabled with Custom Region checkbox in the menu or (Ctrl-Alt-B). - Box Select (Pinned) changed to (Alt-B). - When the Custom Region enum is chosen the islands are packed into the bounding box of the drawn region. Ref !140020
This commit is contained in:
committed by
Campbell Barton
parent
e6c0a204f6
commit
a9a54c88b9
@@ -1395,7 +1395,7 @@ def km_uv_editor(params):
|
||||
("uv.select_box", {"type": 'B', "value": 'PRESS'},
|
||||
{"properties": [("pinned", False)]}),
|
||||
(op_tool, "builtin.select_box"), params),
|
||||
("uv.select_box", {"type": 'B', "value": 'PRESS', "ctrl": True},
|
||||
("uv.select_box", {"type": 'B', "value": 'PRESS', "alt": True},
|
||||
{"properties": [("pinned", True)]}),
|
||||
op_tool_optional(
|
||||
("uv.select_circle", {"type": 'C', "value": 'PRESS'}, None),
|
||||
@@ -1426,6 +1426,10 @@ def km_uv_editor(params):
|
||||
{"properties": [("clear", True)]}),
|
||||
("uv.copy", {"type": 'C', "value": 'PRESS', "ctrl": True}, None),
|
||||
("uv.paste", {"type": 'V', "value": 'PRESS', "ctrl": True}, None),
|
||||
("uv.custom_region_set", {"type": 'B', "value": 'PRESS', "ctrl": True}, None),
|
||||
("wm.context_toggle", {"type": 'B', "value": 'PRESS', "ctrl": True, "alt": True},
|
||||
{"properties": [("data_path", "tool_settings.use_uv_custom_region")]}),
|
||||
|
||||
op_menu("IMAGE_MT_uvs_unwrap", {"type": 'U', "value": 'PRESS'}),
|
||||
(
|
||||
op_menu_pie("IMAGE_MT_uvs_snap_pie", {"type": 'S', "value": 'PRESS', "shift": True})
|
||||
|
||||
@@ -471,6 +471,10 @@ class IMAGE_MT_uvs(Menu):
|
||||
layout.operator_context = 'EXEC_REGION_WIN'
|
||||
layout.operator("uv.average_islands_scale")
|
||||
layout.operator("uv.arrange_islands")
|
||||
layout.operator_context = 'INVOKE_REGION_WIN'
|
||||
layout.operator("uv.custom_region_set")
|
||||
layout.operator_context = 'EXEC_REGION_WIN'
|
||||
layout.prop(context.tool_settings, "use_uv_custom_region", text="Custom Region", toggle=True)
|
||||
|
||||
layout.separator()
|
||||
|
||||
|
||||
@@ -449,6 +449,14 @@ void draw_image_main_helpers(const bContext *C, ARegion *region)
|
||||
ED_space_image_get_zoom(sima, region, &zoomx, &zoomy);
|
||||
draw_render_info(C, sima->iuser.scene, ima, region, zoomx, zoomy);
|
||||
}
|
||||
|
||||
if (sima->mode == SI_MODE_UV) {
|
||||
const Scene *scene = CTX_data_scene(C);
|
||||
const ToolSettings *ts = scene->toolsettings;
|
||||
if (ts->uv_flag & UV_FLAG_CUSTOM_REGION) {
|
||||
draw_image_uv_custom_region(region, ts->uv_custom_region);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ED_space_image_show_cache(const SpaceImage *sima)
|
||||
@@ -606,3 +614,30 @@ float ED_space_image_increment_snap_value(const int grid_dimensions,
|
||||
/* Fallback */
|
||||
return grid_steps[0];
|
||||
}
|
||||
|
||||
void draw_image_uv_custom_region(const ARegion *region, const rctf &custom_region)
|
||||
{
|
||||
const uint shdr_pos = GPU_vertformat_attr_add(
|
||||
immVertexFormat(), "pos", blender::gpu::VertAttrType::SFLOAT_32_32);
|
||||
|
||||
GPU_line_width(1.0f);
|
||||
|
||||
immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR);
|
||||
|
||||
float viewport_size[4];
|
||||
GPU_viewport_size_get_f(viewport_size);
|
||||
immUniform2f("viewport_size", viewport_size[2] / UI_SCALE_FAC, viewport_size[3] / UI_SCALE_FAC);
|
||||
|
||||
immUniform1i("colors_len", 0); /* "simple" mode */
|
||||
immUniform4f("color", 1.0f, 0.25f, 0.25f, 1.0f);
|
||||
immUniform1f("dash_width", 6.0f);
|
||||
immUniform1f("udash_factor", 0.5f);
|
||||
rcti region_rect;
|
||||
|
||||
UI_view2d_view_to_region_rcti(®ion->v2d, &custom_region, ®ion_rect);
|
||||
|
||||
imm_draw_box_wire_2d(
|
||||
shdr_pos, region_rect.xmin, region_rect.ymin, region_rect.xmax, region_rect.ymax);
|
||||
|
||||
immUnbindProgram();
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ struct SpaceImage;
|
||||
struct bContext;
|
||||
struct bNodeTree;
|
||||
struct wmOperatorType;
|
||||
struct rctf;
|
||||
|
||||
/* `space_image.cc` */
|
||||
|
||||
@@ -28,6 +29,7 @@ extern const char *image_context_dir[]; /* doc access */
|
||||
void draw_image_main_helpers(const bContext *C, ARegion *region);
|
||||
void draw_image_cache(const bContext *C, ARegion *region);
|
||||
void draw_image_sample_line(SpaceImage *sima);
|
||||
void draw_image_uv_custom_region(const ARegion *region, const rctf &custom_region);
|
||||
|
||||
/* `image_ops.cc` */
|
||||
|
||||
|
||||
@@ -157,5 +157,7 @@ void UV_OT_select_more(wmOperatorType *ot);
|
||||
void UV_OT_select_less(wmOperatorType *ot);
|
||||
void UV_OT_select_overlap(wmOperatorType *ot);
|
||||
void UV_OT_select_similar(wmOperatorType *ot);
|
||||
void UV_OT_custom_region_set(wmOperatorType *ot);
|
||||
|
||||
/* Used only when UV sync select is disabled. */
|
||||
void UV_OT_select_mode(wmOperatorType *ot);
|
||||
|
||||
@@ -2547,6 +2547,7 @@ void ED_operatortypes_uvedit()
|
||||
WM_operatortype_append(UV_OT_select_less);
|
||||
WM_operatortype_append(UV_OT_select_overlap);
|
||||
WM_operatortype_append(UV_OT_select_mode);
|
||||
WM_operatortype_append(UV_OT_custom_region_set);
|
||||
|
||||
WM_operatortype_append(UV_OT_snap_cursor);
|
||||
WM_operatortype_append(UV_OT_snap_selected);
|
||||
|
||||
@@ -5873,4 +5873,38 @@ void UV_OT_select_mode(wmOperatorType *ot)
|
||||
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
|
||||
}
|
||||
|
||||
static wmOperatorStatus uv_custom_region_set_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
const Scene *scene = CTX_data_scene(C);
|
||||
const ARegion *region = CTX_wm_region(C);
|
||||
ToolSettings *ts = scene->toolsettings;
|
||||
|
||||
WM_operator_properties_border_to_rctf(op, &ts->uv_custom_region);
|
||||
UI_view2d_region_to_view_rctf(®ion->v2d, &ts->uv_custom_region, &ts->uv_custom_region);
|
||||
ts->uv_flag |= UV_FLAG_CUSTOM_REGION;
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void UV_OT_custom_region_set(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Set User Region";
|
||||
ot->description = "Set the boundaries of the user region";
|
||||
ot->idname = "UV_OT_custom_region_set";
|
||||
|
||||
/* API callbacks. */
|
||||
ot->invoke = WM_gesture_box_invoke;
|
||||
ot->exec = uv_custom_region_set_exec;
|
||||
ot->modal = WM_gesture_box_modal;
|
||||
ot->poll = ED_operator_uvedit_space_image;
|
||||
ot->cancel = WM_gesture_box_cancel;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
|
||||
/* properties */
|
||||
WM_operator_properties_gesture_box(ot);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
@@ -1438,6 +1438,7 @@ static void uvedit_pack_islands_multi(const Scene *scene,
|
||||
const SpaceImage *udim_source_closest,
|
||||
const bool original_selection,
|
||||
const bool notify_wm,
|
||||
const rctf *custom_region,
|
||||
blender::geometry::UVPackIsland_Params *params)
|
||||
{
|
||||
blender::Vector<FaceIsland *> island_vector;
|
||||
@@ -1526,6 +1527,17 @@ static void uvedit_pack_islands_multi(const Scene *scene,
|
||||
(selection_max_co[1] - selection_min_co[1]);
|
||||
}
|
||||
}
|
||||
else if (custom_region) {
|
||||
if (!BLI_rctf_is_empty(custom_region)) {
|
||||
const blender::float2 custom_region_size = {
|
||||
BLI_rctf_size_x(custom_region),
|
||||
BLI_rctf_size_y(custom_region),
|
||||
};
|
||||
ARRAY_SET_ITEMS(params->udim_base_offset, custom_region->xmin, custom_region->ymin);
|
||||
params->target_extent = custom_region_size.y;
|
||||
params->target_aspect_y = custom_region_size.x / custom_region_size.y;
|
||||
}
|
||||
}
|
||||
|
||||
MemArena *arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
|
||||
Heap *heap = BLI_heap_new();
|
||||
@@ -1656,6 +1668,7 @@ enum {
|
||||
PACK_UDIM_SRC_CLOSEST = 0,
|
||||
PACK_UDIM_SRC_ACTIVE,
|
||||
PACK_ORIGINAL_AABB,
|
||||
PACK_CUSTOM_REGION,
|
||||
};
|
||||
|
||||
struct UVPackIslandsData {
|
||||
@@ -1672,6 +1685,7 @@ struct UVPackIslandsData {
|
||||
bool use_job;
|
||||
|
||||
blender::geometry::UVPackIsland_Params pack_island_params;
|
||||
rctf custom_region;
|
||||
};
|
||||
|
||||
static void pack_islands_startjob(void *pidv, wmJobWorkerStatus *worker_status)
|
||||
@@ -1690,6 +1704,8 @@ static void pack_islands_startjob(void *pidv, wmJobWorkerStatus *worker_status)
|
||||
(pid->udim_source == PACK_UDIM_SRC_CLOSEST) ? pid->sima : nullptr,
|
||||
(pid->udim_source == PACK_ORIGINAL_AABB),
|
||||
!pid->use_job,
|
||||
(pid->udim_source == PACK_CUSTOM_REGION) ? &pid->custom_region :
|
||||
nullptr,
|
||||
&pid->pack_island_params);
|
||||
|
||||
worker_status->progress = 0.99f;
|
||||
@@ -1723,6 +1739,7 @@ static wmOperatorStatus pack_islands_exec(bContext *C, wmOperator *op)
|
||||
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||
const Scene *scene = CTX_data_scene(C);
|
||||
const SpaceImage *sima = CTX_wm_space_image(C);
|
||||
const ToolSettings *ts = scene->toolsettings;
|
||||
|
||||
UnwrapOptions options = unwrap_options_get(op, nullptr, scene->toolsettings);
|
||||
options.topology_from_uvs = true;
|
||||
@@ -1756,6 +1773,19 @@ static wmOperatorStatus pack_islands_exec(bContext *C, wmOperator *op)
|
||||
pid->udim_source = udim_source;
|
||||
pid->wm = CTX_wm_manager(C);
|
||||
|
||||
if (udim_source == PACK_CUSTOM_REGION) {
|
||||
if (ts->uv_flag & UV_FLAG_CUSTOM_REGION) {
|
||||
pid->custom_region = ts->uv_custom_region;
|
||||
}
|
||||
else {
|
||||
pid->custom_region.xmin = pid->custom_region.ymin = 0.0f;
|
||||
pid->custom_region.xmax = pid->custom_region.ymax = 1.0f;
|
||||
}
|
||||
}
|
||||
else {
|
||||
pid->custom_region = {0.0f};
|
||||
}
|
||||
|
||||
blender::geometry::UVPackIsland_Params &pack_island_params = pid->pack_island_params;
|
||||
{
|
||||
/* Call default constructor and copy the defaults. */
|
||||
@@ -1937,6 +1967,7 @@ void UV_OT_pack_islands(wmOperatorType *ot)
|
||||
0,
|
||||
"Original bounding box",
|
||||
"Pack to starting bounding box of islands"},
|
||||
{PACK_CUSTOM_REGION, "CUSTOM_REGION", 0, "Custom Region", "Pack islands to custom region"},
|
||||
{0, nullptr, 0, nullptr, nullptr},
|
||||
};
|
||||
/* identifiers */
|
||||
@@ -2763,7 +2794,8 @@ void ED_uvedit_live_unwrap(const Scene *scene, const Span<Object *> objects)
|
||||
pack_island_params.margin_method = ED_UVPACK_MARGIN_SCALED;
|
||||
pack_island_params.margin = scene->toolsettings->uvcalc_margin;
|
||||
|
||||
uvedit_pack_islands_multi(scene, objects, nullptr, nullptr, false, true, &pack_island_params);
|
||||
uvedit_pack_islands_multi(
|
||||
scene, objects, nullptr, nullptr, false, true, nullptr, &pack_island_params);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2864,7 +2896,8 @@ static wmOperatorStatus unwrap_exec(bContext *C, wmOperator *op)
|
||||
RNA_enum_get(op->ptr, "margin_method"));
|
||||
pack_island_params.margin = RNA_float_get(op->ptr, "margin");
|
||||
|
||||
uvedit_pack_islands_multi(scene, objects, nullptr, nullptr, false, true, &pack_island_params);
|
||||
uvedit_pack_islands_multi(
|
||||
scene, objects, nullptr, nullptr, false, true, nullptr, &pack_island_params);
|
||||
|
||||
if (count_failed == 0 && count_changed == 0) {
|
||||
BKE_report(op->reports,
|
||||
@@ -3323,7 +3356,8 @@ static wmOperatorStatus smart_project_exec(bContext *C, wmOperator *op)
|
||||
params.margin_method = eUVPackIsland_MarginMethod(RNA_enum_get(op->ptr, "margin_method"));
|
||||
params.margin = RNA_float_get(op->ptr, "island_margin");
|
||||
|
||||
uvedit_pack_islands_multi(scene, objects_changed, nullptr, nullptr, false, true, ¶ms);
|
||||
uvedit_pack_islands_multi(
|
||||
scene, objects_changed, nullptr, nullptr, false, true, nullptr, ¶ms);
|
||||
|
||||
/* #uvedit_pack_islands_multi only supports `per_face_aspect = false`. */
|
||||
const bool per_face_aspect = false;
|
||||
@@ -4302,7 +4336,7 @@ void ED_uvedit_add_simple_uvs(Main *bmain, const Scene *scene, Object *ob)
|
||||
params.margin_method = ED_UVPACK_MARGIN_SCALED;
|
||||
params.margin = 0.001f;
|
||||
|
||||
uvedit_pack_islands_multi(scene, {ob}, &bm, nullptr, false, true, ¶ms);
|
||||
uvedit_pack_islands_multi(scene, {ob}, &bm, nullptr, false, true, nullptr, ¶ms);
|
||||
|
||||
/* Write back from BMesh to Mesh. */
|
||||
BMeshToMeshParams bm_to_me_params{};
|
||||
|
||||
@@ -1684,6 +1684,8 @@ typedef struct ToolSettings {
|
||||
char uv_selectmode;
|
||||
char uv_sticky;
|
||||
|
||||
rctf uv_custom_region;
|
||||
|
||||
float uvcalc_margin;
|
||||
|
||||
int uvcalc_iterations;
|
||||
@@ -2800,6 +2802,7 @@ enum {
|
||||
* selection should be used - since not all combinations of options support it.
|
||||
*/
|
||||
UV_FLAG_ISLAND_SELECT = 1 << 2,
|
||||
UV_FLAG_CUSTOM_REGION = 1 << 3,
|
||||
};
|
||||
|
||||
/** #ToolSettings::uv_selectmode */
|
||||
|
||||
@@ -4224,6 +4224,12 @@ static void rna_def_tool_settings(BlenderRNA *brna)
|
||||
prop, "UV Local View", "Display only faces with the currently displayed image assigned");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, nullptr);
|
||||
|
||||
prop = RNA_def_property(srna, "use_uv_custom_region", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, nullptr, "uv_flag", UV_FLAG_CUSTOM_REGION);
|
||||
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
||||
RNA_def_property_ui_text(prop, "UV Custom Region", "Custom defined region");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, nullptr);
|
||||
|
||||
/* Mesh */
|
||||
prop = RNA_def_property(srna, "mesh_select_mode", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_bitset_array_sdna(prop, nullptr, "selectmode", 1 << 0, 3);
|
||||
|
||||
@@ -4364,6 +4364,7 @@ static void gesture_box_modal_keymap(wmKeyConfig *keyconf)
|
||||
WM_modalkeymap_assign(keymap, "SEQUENCER_OT_select_box");
|
||||
WM_modalkeymap_assign(keymap, "SEQUENCER_OT_view_ghost_border");
|
||||
WM_modalkeymap_assign(keymap, "UV_OT_select_box");
|
||||
WM_modalkeymap_assign(keymap, "UV_OT_custom_region_set");
|
||||
WM_modalkeymap_assign(keymap, "CLIP_OT_select_box");
|
||||
WM_modalkeymap_assign(keymap, "CLIP_OT_graph_select_box");
|
||||
WM_modalkeymap_assign(keymap, "MASK_OT_select_box");
|
||||
|
||||
Reference in New Issue
Block a user