UV: add grid shape source to the uv editor, and add new "pixel" option

This change is part of a wider set of changes to implement Grid and Pixel
snapping in the UV Editor. This particular change adds a new third option,
`pixel grid`, to the previous grid options, `dynamic grid` and `fixed grid`.

Maniphest Tasks : T78391

Differential Revision: https://developer.blender.org/D16197
This commit is contained in:
Chris Blackbourn 2022-10-12 11:26:14 +13:00
parent c2256bf7f7
commit b7decab07e
7 changed files with 64 additions and 42 deletions

View File

@ -1528,36 +1528,23 @@ class IMAGE_PT_overlay_guides(Panel):
layout.active = overlay.show_overlays
row = layout.row()
row_el = row.column()
row_el.prop(overlay, "show_grid_background", text="Grid")
row.prop(overlay, "show_grid_background", text="Grid")
if overlay.show_grid_background:
layout.use_property_split = True
col = layout.column(align=False, heading="Grid Over Image")
col.use_property_decorate = False
row = col.row(align=True)
sub = row.row(align=True)
sub.prop(uvedit, "show_grid_over_image", text="")
sub = row.row()
sub.prop(uvedit, "show_grid_over_image", text="Over Image")
sub.active = sima.image is not None
col = layout.column(align=False, heading="Fixed Subdivisions")
col.use_property_decorate = False
layout.row().prop(uvedit, "grid_shape_source", expand=True)
row = col.row(align=True)
sub = row.row(align=True)
sub.prop(uvedit, "use_custom_grid", text="")
if uvedit.use_custom_grid:
row = layout.row()
row.use_property_split = True
row.use_property_decorate = False
sub = sub.row(align=True)
sub.prop(uvedit, "custom_grid_subdivisions", text="")
layout.use_property_split = True
layout.use_property_decorate = False
row = layout.row()
row.use_property_split = True
row.use_property_decorate = False
row.prop(uvedit, "tile_grid_shape", text="Tiles")
row.prop(uvedit, "custom_grid_subdivisions", text="Fixed Subdivisions")
row.active = uvedit.grid_shape_source == 'FIXED'
layout.prop(uvedit, "tile_grid_shape", text="Tiles")
class IMAGE_PT_overlay_uv_edit(Panel):

View File

@ -3379,7 +3379,7 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
SpaceImage *sima = (SpaceImage *)sl;
sima->flag &= ~(SI_FLAG_UNUSED_0 | SI_FLAG_UNUSED_1 | SI_FLAG_UNUSED_3 |
SI_FLAG_UNUSED_6 | SI_FLAG_UNUSED_7 | SI_FLAG_UNUSED_8 |
SI_FLAG_UNUSED_17 | SI_CUSTOM_GRID | SI_FLAG_UNUSED_23 |
SI_FLAG_UNUSED_17 | SI_FLAG_UNUSED_18 | SI_FLAG_UNUSED_23 |
SI_FLAG_UNUSED_24);
break;
}

View File

@ -3604,6 +3604,13 @@ void blo_do_versions_300(FileData *fd, Library * /*lib*/, Main *bmain)
v3d->overlay.flag |= V3D_OVERLAY_VIEWER_ATTRIBUTE;
v3d->overlay.viewer_attribute_opacity = 1.0f;
}
if (sl->spacetype == SPACE_IMAGE) {
SpaceImage *sima = (SpaceImage *)sl;
if (sima->flag & SI_FLAG_UNUSED_18) { /* Was #SI_CUSTOM_GRID. */
sima->grid_shape_source = SI_GRID_SHAPE_FIXED;
sima->flag &= ~SI_FLAG_UNUSED_18;
}
}
}
}
}

View File

@ -59,8 +59,10 @@ void OVERLAY_grid_init(OVERLAY_Data *vedata)
const bool draw_grid = is_uv_edit || !ED_space_image_has_buffer(sima);
if (background_enabled && draw_grid) {
grid_flag |= SHOW_GRID;
if (is_uv_edit && (sima->flag & SI_CUSTOM_GRID) != 0) {
grid_flag |= CUSTOM_GRID;
if (is_uv_edit) {
if (sima->grid_shape_source != SI_GRID_SHAPE_DYNAMIC) {
grid_flag |= CUSTOM_GRID;
}
}
}

View File

@ -589,15 +589,27 @@ void ED_space_image_grid_steps(SpaceImage *sima,
float grid_steps_y[SI_GRID_STEPS_LEN],
const int grid_dimension)
{
const int flag = sima->flag;
const eSpaceImage_GridShapeSource grid_shape_source = sima->grid_shape_source;
for (int step = 0; step < SI_GRID_STEPS_LEN; step++) {
if (flag & SI_CUSTOM_GRID) {
grid_steps_x[step] = 1.0f / sima->custom_grid_subdiv[0];
grid_steps_y[step] = 1.0f / sima->custom_grid_subdiv[1];
}
else {
grid_steps_x[step] = powf(grid_dimension, step - SI_GRID_STEPS_LEN);
grid_steps_y[step] = powf(grid_dimension, step - SI_GRID_STEPS_LEN);
switch (grid_shape_source) {
case SI_GRID_SHAPE_DYNAMIC:
grid_steps_x[step] = powf(grid_dimension, step - SI_GRID_STEPS_LEN);
grid_steps_y[step] = powf(grid_dimension, step - SI_GRID_STEPS_LEN);
break;
case SI_GRID_SHAPE_FIXED:
grid_steps_x[step] = 1.0f / sima->custom_grid_subdiv[0];
grid_steps_y[step] = 1.0f / sima->custom_grid_subdiv[1];
break;
case SI_GRID_SHAPE_PIXEL: {
int pixel_width = IMG_SIZE_FALLBACK;
int pixel_height = IMG_SIZE_FALLBACK;
ED_space_image_get_size(sima, &pixel_width, &pixel_height);
BLI_assert(pixel_width > 0 && pixel_height > 0);
grid_steps_x[step] = 1.0f / pixel_width;
grid_steps_y[step] = 1.0f / pixel_height;
} break;
default:
BLI_assert_unreachable();
}
}
}

View File

@ -1184,6 +1184,12 @@ typedef struct SpaceImageOverlay {
char _pad[4];
} SpaceImageOverlay;
typedef enum eSpaceImage_GridShapeSource {
SI_GRID_SHAPE_DYNAMIC = 0,
SI_GRID_SHAPE_FIXED = 1,
SI_GRID_SHAPE_PIXEL = 2,
} eSpaceImage_GridShapeSource;
typedef struct SpaceImage {
SpaceLink *next, *prev;
/** Storage of regions for inactive spaces. */
@ -1230,7 +1236,9 @@ typedef struct SpaceImage {
char around;
char gizmo_flag;
char _pad1[3];
char grid_shape_source;
char _pad1[2];
int flag;
@ -1239,7 +1247,7 @@ typedef struct SpaceImage {
int tile_grid_shape[2];
/**
* UV editor custom-grid. Value of `{M,N}` will produce `MxN` grid.
* Use when #SI_CUSTOM_GRID is set.
* Use when `custom_grid_shape == SI_GRID_SHAPE_FIXED`.
*/
int custom_grid_subdiv[2];
@ -1266,7 +1274,7 @@ typedef enum eSpaceImage_PixelRoundMode {
SI_PIXEL_ROUND_DISABLED = 0,
SI_PIXEL_ROUND_CENTER = 1,
SI_PIXEL_ROUND_CORNER = 2,
} eSpaceImage_Round_Mode;
} eSpaceImage_PixelRoundMode;
/** #SpaceImage.mode */
typedef enum eSpaceImage_Mode {
@ -1300,7 +1308,7 @@ typedef enum eSpaceImage_Flag {
SI_FULLWINDOW = (1 << 16),
SI_FLAG_UNUSED_17 = (1 << 17),
SI_CUSTOM_GRID = (1 << 18),
SI_FLAG_UNUSED_18 = (1 << 18),
/**
* This means that the image is drawn until it reaches the view edge,

View File

@ -3510,6 +3510,13 @@ static void rna_def_space_image_uv(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem grid_shape_source_items[] = {
{SI_GRID_SHAPE_DYNAMIC, "DYNAMIC", 0, "Dynamic", "Dynamic grid"},
{SI_GRID_SHAPE_FIXED, "FIXED", 0, "Fixed", "Manually set grid divisions"},
{SI_GRID_SHAPE_PIXEL, "PIXEL", 0, "Pixel", "Grid aligns with pixels from image"},
{0, NULL, 0, NULL, NULL},
};
srna = RNA_def_struct(brna, "SpaceUVEditor", NULL);
RNA_def_struct_sdna(srna, "SpaceImage");
RNA_def_struct_nested(brna, srna, "SpaceImageEditor");
@ -3583,10 +3590,9 @@ static void rna_def_space_image_uv(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Grid Over Image", "Show the grid over the image");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, NULL);
prop = RNA_def_property(srna, "use_custom_grid", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SI_CUSTOM_GRID);
RNA_def_property_boolean_default(prop, true);
RNA_def_property_ui_text(prop, "Custom Grid", "Use a grid with a user-defined number of steps");
prop = RNA_def_property(srna, "grid_shape_source", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, grid_shape_source_items);
RNA_def_property_ui_text(prop, "Grid Shape Source", "Specify source for the grid shape");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, NULL);
prop = RNA_def_property(srna, "custom_grid_subdivisions", PROP_INT, PROP_XYZ);