Cleanup: separate clipUVTransform into two different functions
No functional changes. Prep for D15420 / T98061.
This commit is contained in:
@@ -479,132 +479,6 @@ TransDataCurveHandleFlags *initTransDataCurveHandles(TransData *td, struct BezTr
|
|||||||
/** \name UV Coordinates
|
/** \name UV Coordinates
|
||||||
* \{ */
|
* \{ */
|
||||||
|
|
||||||
/**
|
|
||||||
* Find the correction for the scaling factor when "Constrain to Bounds" is active.
|
|
||||||
* \param numerator: How far the UV boundary (unit square) is from the origin of the scale.
|
|
||||||
* \param denominator: How far the AABB is from the origin of the scale.
|
|
||||||
* \param scale: Scale parameter to update.
|
|
||||||
*/
|
|
||||||
static void constrain_scale_to_boundary(const float numerator,
|
|
||||||
const float denominator,
|
|
||||||
float *scale)
|
|
||||||
{
|
|
||||||
if (denominator == 0.0f) {
|
|
||||||
/* The origin of the scale is on the edge of the boundary. */
|
|
||||||
if (numerator < 0.0f) {
|
|
||||||
/* Negative scale will wrap around and put us outside the boundary. */
|
|
||||||
*scale = 0.0f; /* Hold at the boundary instead. */
|
|
||||||
}
|
|
||||||
return; /* Nothing else we can do without more info. */
|
|
||||||
}
|
|
||||||
|
|
||||||
const float correction = numerator / denominator;
|
|
||||||
if (correction < 0.0f || !isfinite(correction)) {
|
|
||||||
/* TODO: Correction is negative or invalid, but we lack context to fix `*scale`. */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (denominator < 0.0f) {
|
|
||||||
/* Scale origin is outside boundary, only make scale bigger. */
|
|
||||||
if (*scale < correction) {
|
|
||||||
*scale = correction;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Scale origin is inside boundary, the "regular" case, limit maximum scale. */
|
|
||||||
if (*scale > correction) {
|
|
||||||
*scale = correction;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool clipUVTransform(TransInfo *t, float vec[2], const bool resize)
|
|
||||||
{
|
|
||||||
bool clipx = true, clipy = true;
|
|
||||||
float min[2], max[2];
|
|
||||||
|
|
||||||
/* Check if the current image in UV editor is a tiled image or not. */
|
|
||||||
const SpaceImage *sima = t->area->spacedata.first;
|
|
||||||
const Image *image = sima->image;
|
|
||||||
const bool is_tiled_image = image && (image->source == IMA_SRC_TILED);
|
|
||||||
/* Stores the coordinates of the closest UDIM tile.
|
|
||||||
* Also acts as an offset to the tile from the origin of UV space. */
|
|
||||||
float base_offset[2] = {0.0f, 0.0f};
|
|
||||||
|
|
||||||
/* If tiled image then constrain to correct/closest UDIM tile, else 0-1 UV space. */
|
|
||||||
if (is_tiled_image) {
|
|
||||||
int nearest_tile_index = BKE_image_find_nearest_tile(image, t->center_global);
|
|
||||||
if (nearest_tile_index != -1) {
|
|
||||||
nearest_tile_index -= 1001;
|
|
||||||
/* Getting coordinates of nearest tile from the tile index. */
|
|
||||||
base_offset[0] = nearest_tile_index % 10;
|
|
||||||
base_offset[1] = nearest_tile_index / 10;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
min[0] = min[1] = FLT_MAX;
|
|
||||||
max[0] = max[1] = FLT_MIN;
|
|
||||||
|
|
||||||
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
|
|
||||||
|
|
||||||
TransData *td;
|
|
||||||
int a;
|
|
||||||
|
|
||||||
for (a = 0, td = tc->data; a < tc->data_len; a++, td++) {
|
|
||||||
minmax_v2v2_v2(min, max, td->loc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (resize) {
|
|
||||||
/* Assume no change is required. */
|
|
||||||
float scalex = 1.0f;
|
|
||||||
float scaley = 1.0f;
|
|
||||||
|
|
||||||
/* Update U against the left border. */
|
|
||||||
constrain_scale_to_boundary(
|
|
||||||
t->center_global[0] - base_offset[0], t->center_global[0] - min[0], &scalex);
|
|
||||||
/* Now the right border, negated, because `-1.0 / -1.0 = 1.0` */
|
|
||||||
constrain_scale_to_boundary(base_offset[0] + t->aspect[0] - t->center_global[0],
|
|
||||||
max[0] - t->center_global[0],
|
|
||||||
&scalex);
|
|
||||||
|
|
||||||
/* Do the same for the V co-ordinate, which is called `y`. */
|
|
||||||
constrain_scale_to_boundary(
|
|
||||||
t->center_global[1] - base_offset[1], t->center_global[1] - min[1], &scaley);
|
|
||||||
constrain_scale_to_boundary(base_offset[1] + t->aspect[1] - t->center_global[1],
|
|
||||||
max[1] - t->center_global[1],
|
|
||||||
&scaley);
|
|
||||||
|
|
||||||
clipx = (scalex != 1.0f);
|
|
||||||
clipy = (scaley != 1.0f);
|
|
||||||
vec[0] *= scalex;
|
|
||||||
vec[1] *= scaley;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (min[0] < base_offset[0]) {
|
|
||||||
vec[0] += base_offset[0] - min[0];
|
|
||||||
}
|
|
||||||
else if (max[0] > base_offset[0] + t->aspect[0]) {
|
|
||||||
vec[0] -= max[0] - base_offset[0] - t->aspect[0];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
clipx = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (min[1] < base_offset[1]) {
|
|
||||||
vec[1] += base_offset[1] - min[1];
|
|
||||||
}
|
|
||||||
else if (max[1] > base_offset[1] + t->aspect[1]) {
|
|
||||||
vec[1] -= max[1] - base_offset[1] - t->aspect[1];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
clipy = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (clipx || clipy);
|
|
||||||
}
|
|
||||||
|
|
||||||
void clipUVData(TransInfo *t)
|
void clipUVData(TransInfo *t)
|
||||||
{
|
{
|
||||||
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
|
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ int special_transform_moving(TransInfo *t);
|
|||||||
void special_aftertrans_update(struct bContext *C, TransInfo *t);
|
void special_aftertrans_update(struct bContext *C, TransInfo *t);
|
||||||
void sort_trans_data_dist(TransInfo *t);
|
void sort_trans_data_dist(TransInfo *t);
|
||||||
void createTransData(struct bContext *C, TransInfo *t);
|
void createTransData(struct bContext *C, TransInfo *t);
|
||||||
bool clipUVTransform(TransInfo *t, float vec[2], bool resize);
|
|
||||||
void clipUVData(TransInfo *t);
|
void clipUVData(TransInfo *t);
|
||||||
void transform_convert_flush_handle2D(TransData *td, TransData2D *td2d, float y_fac);
|
void transform_convert_flush_handle2D(TransData *td, TransData2D *td2d, float y_fac);
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#include "BLI_task.h"
|
#include "BLI_task.h"
|
||||||
|
|
||||||
#include "BKE_context.h"
|
#include "BKE_context.h"
|
||||||
|
#include "BKE_image.h"
|
||||||
#include "BKE_unit.h"
|
#include "BKE_unit.h"
|
||||||
|
|
||||||
#include "ED_screen.h"
|
#include "ED_screen.h"
|
||||||
@@ -84,6 +85,102 @@ static void ApplySnapResize(TransInfo *t, float vec[3])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the correction for the scaling factor when "Constrain to Bounds" is active.
|
||||||
|
* \param numerator: How far the UV boundary (unit square) is from the origin of the scale.
|
||||||
|
* \param denominator: How far the AABB is from the origin of the scale.
|
||||||
|
* \param scale: Scale parameter to update.
|
||||||
|
*/
|
||||||
|
static void constrain_scale_to_boundary(const float numerator,
|
||||||
|
const float denominator,
|
||||||
|
float *scale)
|
||||||
|
{
|
||||||
|
if (denominator == 0.0f) {
|
||||||
|
/* The origin of the scale is on the edge of the boundary. */
|
||||||
|
if (numerator < 0.0f) {
|
||||||
|
/* Negative scale will wrap around and put us outside the boundary. */
|
||||||
|
*scale = 0.0f; /* Hold at the boundary instead. */
|
||||||
|
}
|
||||||
|
return; /* Nothing else we can do without more info. */
|
||||||
|
}
|
||||||
|
|
||||||
|
const float correction = numerator / denominator;
|
||||||
|
if (correction < 0.0f || !isfinite(correction)) {
|
||||||
|
/* TODO: Correction is negative or invalid, but we lack context to fix `*scale`. */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (denominator < 0.0f) {
|
||||||
|
/* Scale origin is outside boundary, only make scale bigger. */
|
||||||
|
if (*scale < correction) {
|
||||||
|
*scale = correction;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Scale origin is inside boundary, the "regular" case, limit maximum scale. */
|
||||||
|
if (*scale > correction) {
|
||||||
|
*scale = correction;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool clip_uv_transform_resize(TransInfo *t, float vec[2])
|
||||||
|
{
|
||||||
|
/* Assume no change is required. */
|
||||||
|
float scalex = 1.0f;
|
||||||
|
float scaley = 1.0f;
|
||||||
|
|
||||||
|
/* Check if the current image in UV editor is a tiled image or not. */
|
||||||
|
const SpaceImage *sima = t->area->spacedata.first;
|
||||||
|
const Image *image = sima->image;
|
||||||
|
const bool is_tiled_image = image && (image->source == IMA_SRC_TILED);
|
||||||
|
|
||||||
|
/* Stores the coordinates of the closest UDIM tile.
|
||||||
|
* Also acts as an offset to the tile from the origin of UV space. */
|
||||||
|
float base_offset[2] = {0.0f, 0.0f};
|
||||||
|
|
||||||
|
/* If tiled image then constrain to correct/closest UDIM tile, else 0-1 UV space. */
|
||||||
|
if (is_tiled_image) {
|
||||||
|
int nearest_tile_index = BKE_image_find_nearest_tile(image, t->center_global);
|
||||||
|
if (nearest_tile_index != -1) {
|
||||||
|
nearest_tile_index -= 1001;
|
||||||
|
/* Getting coordinates of nearest tile from the tile index. */
|
||||||
|
base_offset[0] = nearest_tile_index % 10;
|
||||||
|
base_offset[1] = nearest_tile_index / 10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float min[2], max[2];
|
||||||
|
min[0] = min[1] = FLT_MAX;
|
||||||
|
max[0] = max[1] = -FLT_MAX;
|
||||||
|
|
||||||
|
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
|
||||||
|
|
||||||
|
TransData *td;
|
||||||
|
int a;
|
||||||
|
for (a = 0, td = tc->data; a < tc->data_len; a++, td++) {
|
||||||
|
minmax_v2v2_v2(min, max, td->loc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update U against the left border. */
|
||||||
|
constrain_scale_to_boundary(
|
||||||
|
t->center_global[0] - base_offset[0], t->center_global[0] - min[0], &scalex);
|
||||||
|
/* Now the right border, negated, because `-1.0 / -1.0 = 1.0` */
|
||||||
|
constrain_scale_to_boundary(
|
||||||
|
base_offset[0] + t->aspect[0] - t->center_global[0], max[0] - t->center_global[0], &scalex);
|
||||||
|
|
||||||
|
/* Do the same for the V co-ordinate, which is called `y`. */
|
||||||
|
constrain_scale_to_boundary(
|
||||||
|
t->center_global[1] - base_offset[1], t->center_global[1] - min[1], &scaley);
|
||||||
|
constrain_scale_to_boundary(
|
||||||
|
base_offset[1] + t->aspect[1] - t->center_global[1], max[1] - t->center_global[1], &scaley);
|
||||||
|
|
||||||
|
vec[0] *= scalex;
|
||||||
|
vec[1] *= scaley;
|
||||||
|
return (scalex != 1.0f) || (scaley != 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
static void applyResize(TransInfo *t, const int UNUSED(mval[2]))
|
static void applyResize(TransInfo *t, const int UNUSED(mval[2]))
|
||||||
{
|
{
|
||||||
float mat[3][3];
|
float mat[3][3];
|
||||||
@@ -157,7 +254,7 @@ static void applyResize(TransInfo *t, const int UNUSED(mval[2]))
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Evil hack - redo resize if clipping needed. */
|
/* Evil hack - redo resize if clipping needed. */
|
||||||
if (t->flag & T_CLIP_UV && clipUVTransform(t, t->values_final, 1)) {
|
if (t->flag & T_CLIP_UV && clip_uv_transform_resize(t, t->values_final)) {
|
||||||
size_to_mat3(mat, t->values_final);
|
size_to_mat3(mat, t->values_final);
|
||||||
|
|
||||||
if (t->con.mode & CON_APPLY) {
|
if (t->con.mode & CON_APPLY) {
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
#include "BLI_task.h"
|
#include "BLI_task.h"
|
||||||
|
|
||||||
#include "BKE_context.h"
|
#include "BKE_context.h"
|
||||||
|
#include "BKE_image.h"
|
||||||
#include "BKE_report.h"
|
#include "BKE_report.h"
|
||||||
#include "BKE_unit.h"
|
#include "BKE_unit.h"
|
||||||
|
|
||||||
@@ -434,6 +435,60 @@ static void applyTranslationValue(TransInfo *t, const float vec[3])
|
|||||||
custom_data->prev.rotate_mode = rotate_mode;
|
custom_data->prev.rotate_mode = rotate_mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool clip_uv_transform_translation(TransInfo *t, float vec[2])
|
||||||
|
{
|
||||||
|
/* Check if the current image in UV editor is a tiled image or not. */
|
||||||
|
const SpaceImage *sima = t->area->spacedata.first;
|
||||||
|
const Image *image = sima->image;
|
||||||
|
const bool is_tiled_image = image && (image->source == IMA_SRC_TILED);
|
||||||
|
|
||||||
|
/* Stores the coordinates of the closest UDIM tile.
|
||||||
|
* Also acts as an offset to the tile from the origin of UV space. */
|
||||||
|
float base_offset[2] = {0.0f, 0.0f};
|
||||||
|
|
||||||
|
/* If tiled image then constrain to correct/closest UDIM tile, else 0-1 UV space. */
|
||||||
|
if (is_tiled_image) {
|
||||||
|
int nearest_tile_index = BKE_image_find_nearest_tile(image, t->center_global);
|
||||||
|
if (nearest_tile_index != -1) {
|
||||||
|
nearest_tile_index -= 1001;
|
||||||
|
/* Getting coordinates of nearest tile from the tile index. */
|
||||||
|
base_offset[0] = nearest_tile_index % 10;
|
||||||
|
base_offset[1] = nearest_tile_index / 10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float min[2], max[2];
|
||||||
|
min[0] = min[1] = FLT_MAX;
|
||||||
|
max[0] = max[1] = -FLT_MAX;
|
||||||
|
|
||||||
|
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
|
||||||
|
for (TransData *td = tc->data; td < tc->data + tc->data_len; td++) {
|
||||||
|
minmax_v2v2_v2(min, max, td->loc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool result = false;
|
||||||
|
if (min[0] < base_offset[0]) {
|
||||||
|
vec[0] += base_offset[0] - min[0];
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
else if (max[0] > base_offset[0] + t->aspect[0]) {
|
||||||
|
vec[0] -= max[0] - base_offset[0] - t->aspect[0];
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (min[1] < base_offset[1]) {
|
||||||
|
vec[1] += base_offset[1] - min[1];
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
else if (max[1] > base_offset[1] + t->aspect[1]) {
|
||||||
|
vec[1] -= max[1] - base_offset[1] - t->aspect[1];
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
static void applyTranslation(TransInfo *t, const int UNUSED(mval[2]))
|
static void applyTranslation(TransInfo *t, const int UNUSED(mval[2]))
|
||||||
{
|
{
|
||||||
char str[UI_MAX_DRAW_STR];
|
char str[UI_MAX_DRAW_STR];
|
||||||
@@ -498,7 +553,7 @@ static void applyTranslation(TransInfo *t, const int UNUSED(mval[2]))
|
|||||||
applyTranslationValue(t, global_dir);
|
applyTranslationValue(t, global_dir);
|
||||||
|
|
||||||
/* evil hack - redo translation if clipping needed */
|
/* evil hack - redo translation if clipping needed */
|
||||||
if (t->flag & T_CLIP_UV && clipUVTransform(t, global_dir, 0)) {
|
if (t->flag & T_CLIP_UV && clip_uv_transform_translation(t, global_dir)) {
|
||||||
applyTranslationValue(t, global_dir);
|
applyTranslationValue(t, global_dir);
|
||||||
|
|
||||||
/* In proportional edit it can happen that */
|
/* In proportional edit it can happen that */
|
||||||
|
|||||||
Reference in New Issue
Block a user