Mesh: Replace auto smooth with node group #108014
|
@ -592,10 +592,10 @@ set(BROTLI_HASH_TYPE SHA256)
|
|||
set(BROTLI_FILE brotli-v${BROTLI_VERSION}.tar.gz)
|
||||
set(BROTLI_CPE "cpe:2.3:a:google:brotli:${BROTLI_VERSION}:*:*:*:*:*:*:*")
|
||||
|
||||
set(OPENPGL_VERSION v0.4.1-beta)
|
||||
set(OPENPGL_SHORT_VERSION 0.4.1)
|
||||
set(OPENPGL_VERSION v0.5.0)
|
||||
set(OPENPGL_SHORT_VERSION 0.5.0)
|
||||
set(OPENPGL_URI https://github.com/OpenPathGuidingLibrary/openpgl/archive/refs/tags/${OPENPGL_VERSION}.tar.gz)
|
||||
set(OPENPGL_HASH db63f5dac5cfa8c110ede241f0c413f00db0c4748697381c4fa23e0f9e82a754)
|
||||
set(OPENPGL_HASH 1ec806d434d45e43e098f82ee9be0cb74928343898c57490b34ff80584e9805a)
|
||||
set(OPENPGL_HASH_TYPE SHA256)
|
||||
set(OPENPGL_FILE openpgl-${OPENPGL_VERSION}.tar.gz)
|
||||
|
||||
|
|
|
@ -43,10 +43,10 @@ ccl_device_inline float kernel_ies_interp(KernelGlobals kg, int slot, float h_an
|
|||
#define IES_LOOKUP_ANGLE_V(v) kernel_data_fetch(ies, ofs + h_num + (v))
|
||||
|
||||
/* Check whether the angle is within the bounds of the IES texture. */
|
||||
if (v_angle >= IES_LOOKUP_ANGLE_V(v_num - 1)) {
|
||||
if (v_angle < IES_LOOKUP_ANGLE_V(0) || v_angle >= IES_LOOKUP_ANGLE_V(v_num - 1)) {
|
||||
return 0.0f;
|
||||
}
|
||||
kernel_assert(v_angle >= IES_LOOKUP_ANGLE_V(0));
|
||||
|
||||
kernel_assert(h_angle >= IES_LOOKUP_ANGLE_H(0));
|
||||
kernel_assert(h_angle <= IES_LOOKUP_ANGLE_H(h_num - 1));
|
||||
|
||||
|
|
|
@ -64,8 +64,9 @@ class IESTextParser {
|
|||
public:
|
||||
vector<char> text;
|
||||
char *data;
|
||||
bool error;
|
||||
|
||||
IESTextParser(const string &str) : text(str.begin(), str.end())
|
||||
IESTextParser(const string &str) : text(str.begin(), str.end()), error(false)
|
||||
{
|
||||
std::replace(text.begin(), text.end(), ',', ' ');
|
||||
data = strstr(&text[0], "\nTILT=");
|
||||
|
@ -76,15 +77,22 @@ class IESTextParser {
|
|||
return (data == NULL) || (data[0] == '\0');
|
||||
}
|
||||
|
||||
bool has_error()
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
double get_double()
|
||||
{
|
||||
if (eof()) {
|
||||
error = true;
|
||||
return 0.0;
|
||||
}
|
||||
char *old_data = data;
|
||||
double val = strtod(data, &data);
|
||||
if (data == old_data) {
|
||||
data = NULL;
|
||||
error = true;
|
||||
return 0.0;
|
||||
}
|
||||
return val;
|
||||
|
@ -93,12 +101,14 @@ class IESTextParser {
|
|||
long get_long()
|
||||
{
|
||||
if (eof()) {
|
||||
error = true;
|
||||
return 0;
|
||||
}
|
||||
char *old_data = data;
|
||||
long val = strtol(data, &data, 10);
|
||||
if (data == old_data) {
|
||||
data = NULL;
|
||||
error = true;
|
||||
return 0;
|
||||
}
|
||||
return val;
|
||||
|
@ -191,7 +201,7 @@ bool IESFile::parse(const string &ies)
|
|||
}
|
||||
}
|
||||
|
||||
return !parser.eof();
|
||||
return !parser.has_error();
|
||||
}
|
||||
|
||||
bool IESFile::process_type_b()
|
||||
|
@ -340,13 +350,7 @@ bool IESFile::process_type_c()
|
|||
|
||||
float v_first = v_angles[0], v_last = v_angles[v_angles.size() - 1];
|
||||
if (v_first == 90.0f) {
|
||||
if (v_last == 180.0f) {
|
||||
/* Flip to ensure that vertical angles always start at 0°. */
|
||||
for (int i = 0; i < v_angles.size(); i++) {
|
||||
v_angles[i] = 180.0f - v_angles[i];
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (v_last != 180.0f) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -375,7 +379,7 @@ bool IESFile::process()
|
|||
}
|
||||
}
|
||||
|
||||
assert(v_angles[0] == 0.0f);
|
||||
assert(v_angles[0] == 0.0f || v_angles[0] == 90.0f);
|
||||
assert(h_angles[0] == 0.0f);
|
||||
assert(h_angles[h_angles.size() - 1] == 360.0f);
|
||||
|
||||
|
|
|
@ -40,7 +40,8 @@ def geometry_modifier_poll(context):
|
|||
|
||||
|
||||
def get_context_modifier(context):
|
||||
if context.area.type == 'PROPERTIES':
|
||||
area = context.area
|
||||
if (area is not None) and (area.type == 'PROPERTIES'):
|
||||
modifier = context.modifier
|
||||
else:
|
||||
ob = context.object
|
||||
|
|
|
@ -178,12 +178,8 @@ class ProjectApply(Operator):
|
|||
|
||||
def execute(self, _context):
|
||||
image_name = ProjectEdit._proj_hack[0] # TODO, deal with this nicer
|
||||
|
||||
try:
|
||||
image = bpy.data.images[image_name, None]
|
||||
except KeyError:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
image = bpy.data.images.get((image_name, None))
|
||||
if image is None:
|
||||
self.report({'ERROR'}, tip_("Could not find image '%s'") % image_name)
|
||||
return {'CANCELLED'}
|
||||
|
||||
|
|
|
@ -655,6 +655,11 @@ class IsolateTypeRender(Operator):
|
|||
bl_label = "Restrict Render Unselected"
|
||||
bl_options = {'REGISTER', 'UNDO'}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
ob = context.object
|
||||
return (ob is not None)
|
||||
|
||||
def execute(self, context):
|
||||
act_type = context.object.type
|
||||
|
||||
|
|
|
@ -157,7 +157,7 @@ def _get_context_attr(context, data_path):
|
|||
return context.path_resolve(data_path)
|
||||
|
||||
|
||||
def _set_context_attr(context, data_path, value) -> None:
|
||||
def _set_context_attr(context, data_path, value):
|
||||
"""Set the value of a context member based on its data path."""
|
||||
owner_path, attr_name = data_path.rsplit('.', 1)
|
||||
owner = context.path_resolve(owner_path)
|
||||
|
@ -172,10 +172,10 @@ class GenericUIListOperator:
|
|||
list_path: StringProperty()
|
||||
active_index_path: StringProperty()
|
||||
|
||||
def get_list(self, context) -> str:
|
||||
def get_list(self, context):
|
||||
return _get_context_attr(context, self.list_path)
|
||||
|
||||
def get_active_index(self, context) -> str:
|
||||
def get_active_index(self, context):
|
||||
return _get_context_attr(context, self.active_index_path)
|
||||
|
||||
def set_active_index(self, context, index):
|
||||
|
@ -226,9 +226,11 @@ class UILIST_OT_entry_move(GenericUIListOperator, Operator):
|
|||
|
||||
direction: EnumProperty(
|
||||
name="Direction",
|
||||
items=(('UP', 'UP', 'UP'),
|
||||
('DOWN', 'DOWN', 'DOWN')),
|
||||
default='UP'
|
||||
items=(
|
||||
('UP', 'UP', 'UP'),
|
||||
('DOWN', 'DOWN', 'DOWN'),
|
||||
),
|
||||
default='UP',
|
||||
)
|
||||
|
||||
def execute(self, context):
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
#include "BLI_math_vector_types.hh"
|
||||
#include "BLI_span.hh"
|
||||
|
||||
#include "BLT_translation.h"
|
||||
|
||||
#include "FN_field.hh"
|
||||
|
||||
#include "BLT_translation.h"
|
||||
|
@ -49,8 +51,8 @@ std::ostream &operator<<(std::ostream &stream, const AttributeIDRef &attribute_i
|
|||
return stream;
|
||||
}
|
||||
|
||||
const char *no_procedural_access_message =
|
||||
"This attribute can not be accessed in a procedural context";
|
||||
const char *no_procedural_access_message = N_(
|
||||
"This attribute can not be accessed in a procedural context");
|
||||
|
||||
bool allow_procedural_attribute_access(StringRef attribute_name)
|
||||
{
|
||||
|
|
|
@ -474,7 +474,9 @@ static int get_timecode(MovieClip *clip, int flag)
|
|||
return clip->proxy.tc;
|
||||
}
|
||||
|
||||
static void get_sequence_filepath(const MovieClip *clip, const int framenr, char *filepath)
|
||||
static void get_sequence_filepath(const MovieClip *clip,
|
||||
const int framenr,
|
||||
char filepath[FILE_MAX])
|
||||
{
|
||||
ushort numlen;
|
||||
char head[FILE_MAX], tail[FILE_MAX];
|
||||
|
@ -489,7 +491,7 @@ static void get_sequence_filepath(const MovieClip *clip, const int framenr, char
|
|||
|
||||
if (numlen) {
|
||||
BLI_path_sequence_encode(filepath,
|
||||
sizeof(filepath),
|
||||
FILE_MAX,
|
||||
head,
|
||||
tail,
|
||||
numlen,
|
||||
|
@ -503,8 +505,11 @@ static void get_sequence_filepath(const MovieClip *clip, const int framenr, char
|
|||
}
|
||||
|
||||
/* supposed to work with sequences only */
|
||||
static void get_proxy_filepath(
|
||||
const MovieClip *clip, int proxy_render_size, bool undistorted, int framenr, char *filepath)
|
||||
static void get_proxy_filepath(const MovieClip *clip,
|
||||
int proxy_render_size,
|
||||
bool undistorted,
|
||||
int framenr,
|
||||
char filepath[FILE_MAX])
|
||||
{
|
||||
int size = rendersize_to_number(proxy_render_size);
|
||||
char dir[FILE_MAX], clipdir[FILE_MAX], clipfile[FILE_MAX];
|
||||
|
@ -516,15 +521,26 @@ static void get_proxy_filepath(
|
|||
BLI_strncpy(dir, clip->proxy.dir, sizeof(dir));
|
||||
}
|
||||
else {
|
||||
BLI_snprintf(dir, FILE_MAX, "%s/BL_proxy", clipdir);
|
||||
BLI_snprintf(dir, sizeof(dir), "%s" SEP_STR "BL_proxy", clipdir);
|
||||
}
|
||||
|
||||
if (undistorted) {
|
||||
BLI_snprintf(
|
||||
filepath, FILE_MAX, "%s/%s/proxy_%d_undistorted/%08d", dir, clipfile, size, proxynr);
|
||||
BLI_snprintf(filepath,
|
||||
FILE_MAX,
|
||||
"%s" SEP_STR "%s" SEP_STR "proxy_%d_undistorted" SEP_STR "%08d",
|
||||
dir,
|
||||
clipfile,
|
||||
size,
|
||||
proxynr);
|
||||
}
|
||||
else {
|
||||
BLI_snprintf(filepath, FILE_MAX, "%s/%s/proxy_%d/%08d", dir, clipfile, size, proxynr);
|
||||
BLI_snprintf(filepath,
|
||||
FILE_MAX,
|
||||
"%s" SEP_STR "%s" SEP_STR "proxy_%d" SEP_STR "%08d",
|
||||
dir,
|
||||
clipfile,
|
||||
size,
|
||||
proxynr);
|
||||
}
|
||||
|
||||
BLI_path_abs(filepath, BKE_main_blendfile_path_from_global());
|
||||
|
|
|
@ -1463,6 +1463,10 @@ static bool vfont_to_curve(Object *ob,
|
|||
sb->x -= sinf(ct->rot) * font_select_y_offset;
|
||||
sb->y -= cosf(ct->rot) * font_select_y_offset;
|
||||
}
|
||||
else {
|
||||
/* Simple downward shift below baseline when not rotated. */
|
||||
sb->y -= font_select_y_offset;
|
||||
}
|
||||
sb->x *= font_size;
|
||||
sb->y *= font_size;
|
||||
selboxes[i - selstart].h = font_size;
|
||||
|
|
|
@ -142,7 +142,7 @@ class BitSpan {
|
|||
};
|
||||
|
||||
/**
|
||||
* Checks if the span fullfills the requirements for a bounded span. Bounded spans can often be
|
||||
* Checks if the span fulfills the requirements for a bounded span. Bounded spans can often be
|
||||
* processed more efficiently, because fewer cases have to be considered when aligning multiple
|
||||
* such spans.
|
||||
*
|
||||
|
@ -170,7 +170,7 @@ inline bool is_bounded_span(const BitSpan span)
|
|||
}
|
||||
|
||||
/**
|
||||
* Same as #BitSpan but fullfills the requirements mentioned on #is_bounded_span.
|
||||
* Same as #BitSpan but fulfills the requirements mentioned on #is_bounded_span.
|
||||
*/
|
||||
class BoundedBitSpan : public BitSpan {
|
||||
public:
|
||||
|
@ -315,7 +315,7 @@ class MutableBitSpan {
|
|||
};
|
||||
|
||||
/**
|
||||
* Same as #MutableBitSpan but fullfills the requirements mentioned on #is_bounded_span.
|
||||
* Same as #MutableBitSpan but fulfills the requirements mentioned on #is_bounded_span.
|
||||
*/
|
||||
class MutableBoundedBitSpan : public MutableBitSpan {
|
||||
public:
|
||||
|
|
|
@ -66,7 +66,7 @@ class ImplicitSharingInfo : NonCopyable, NonMovable {
|
|||
BLI_assert(weak_users_ == 0);
|
||||
}
|
||||
|
||||
/** Whether the resource can be modified inplace because there is only one owner. */
|
||||
/** Whether the resource can be modified in place because there is only one owner. */
|
||||
bool is_mutable() const
|
||||
{
|
||||
return strong_users_.load(std::memory_order_relaxed) == 1;
|
||||
|
|
|
@ -640,7 +640,7 @@ static bool seq_sound_proxy_update_cb(Sequence *seq, void *user_data)
|
|||
#define SEQ_USE_PROXY_CUSTOM_FILE (1 << 21)
|
||||
/* don't know, if anybody used that this way, but just in case, upgrade to new way... */
|
||||
if ((seq->flag & SEQ_USE_PROXY_CUSTOM_FILE) && !(seq->flag & SEQ_USE_PROXY_CUSTOM_DIR)) {
|
||||
BLI_snprintf(seq->strip->proxy->dir, FILE_MAXDIR, "%s/BL_proxy", seq->strip->dir);
|
||||
BLI_snprintf(seq->strip->proxy->dir, FILE_MAXDIR, "%s" SEP_STR "BL_proxy", seq->strip->dir);
|
||||
}
|
||||
#undef SEQ_USE_PROXY_CUSTOM_DIR
|
||||
#undef SEQ_USE_PROXY_CUSTOM_FILE
|
||||
|
|
|
@ -2016,7 +2016,9 @@ static int gpencil_blank_frame_add_exec(bContext *C, wmOperator *op)
|
|||
CTX_DATA_END;
|
||||
|
||||
/* notifiers */
|
||||
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
|
||||
if (gpd != NULL) {
|
||||
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
|
||||
}
|
||||
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
|
|
|
@ -522,9 +522,12 @@ bool ED_operator_objectmode(struct bContext *C);
|
|||
* to be displayed to the user explaining why the operator can't be used in current context.
|
||||
*/
|
||||
bool ED_operator_objectmode_poll_msg(struct bContext *C);
|
||||
bool ED_operator_objectmode_with_view3d_poll_msg(struct bContext *C);
|
||||
|
||||
bool ED_operator_view3d_active(struct bContext *C);
|
||||
bool ED_operator_region_view3d_active(struct bContext *C);
|
||||
bool ED_operator_region_gizmo_active(struct bContext *C);
|
||||
|
||||
/**
|
||||
* Generic for any view2d which uses anim_ops.
|
||||
*/
|
||||
|
|
|
@ -2231,6 +2231,8 @@ static void UI_OT_drop_color(wmOperatorType *ot)
|
|||
ot->description = "Drop colors to buttons";
|
||||
|
||||
ot->invoke = drop_color_invoke;
|
||||
ot->poll = ED_operator_regionactive;
|
||||
|
||||
ot->flag = OPTYPE_INTERNAL;
|
||||
|
||||
RNA_def_float_color(
|
||||
|
|
|
@ -2426,19 +2426,20 @@ PointerRNA *UI_panel_custom_data_get(const Panel *panel)
|
|||
PointerRNA *UI_region_panel_custom_data_under_cursor(const bContext *C, const wmEvent *event)
|
||||
{
|
||||
ARegion *region = CTX_wm_region(C);
|
||||
if (region) {
|
||||
LISTBASE_FOREACH (uiBlock *, block, ®ion->uiblocks) {
|
||||
Panel *panel = block->panel;
|
||||
if (panel == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
LISTBASE_FOREACH (uiBlock *, block, ®ion->uiblocks) {
|
||||
Panel *panel = block->panel;
|
||||
if (panel == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int mx = event->xy[0];
|
||||
int my = event->xy[1];
|
||||
ui_window_to_block(region, block, &mx, &my);
|
||||
const int mouse_state = ui_panel_mouse_state_get(block, panel, mx, my);
|
||||
if (ELEM(mouse_state, PANEL_MOUSE_INSIDE_CONTENT, PANEL_MOUSE_INSIDE_HEADER)) {
|
||||
return UI_panel_custom_data_get(panel);
|
||||
int mx = event->xy[0];
|
||||
int my = event->xy[1];
|
||||
ui_window_to_block(region, block, &mx, &my);
|
||||
const int mouse_state = ui_panel_mouse_state_get(block, panel, mx, my);
|
||||
if (ELEM(mouse_state, PANEL_MOUSE_INSIDE_CONTENT, PANEL_MOUSE_INSIDE_HEADER)) {
|
||||
return UI_panel_custom_data_get(panel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1684,7 +1684,7 @@ static std::optional<CollectionAddInfo> collection_add_info_get_from_op(bContext
|
|||
BLI_findlink(&bmain->collections, RNA_enum_get(op->ptr, "collection")));
|
||||
}
|
||||
|
||||
if (update_location_if_necessary) {
|
||||
if (update_location_if_necessary && CTX_wm_region_view3d(C)) {
|
||||
int mval[2];
|
||||
if (!RNA_property_is_set(op->ptr, prop_location) && object_add_drop_xy_get(C, op, &mval)) {
|
||||
ED_object_location_from_view(C, add_info.loc);
|
||||
|
@ -1928,11 +1928,13 @@ static int object_data_instance_add_exec(bContext *C, wmOperator *op)
|
|||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
int mval[2];
|
||||
if (!RNA_property_is_set(op->ptr, prop_location) && object_add_drop_xy_get(C, op, &mval)) {
|
||||
ED_object_location_from_view(C, loc);
|
||||
ED_view3d_cursor3d_position(C, mval, false, loc);
|
||||
RNA_property_float_set_array(op->ptr, prop_location, loc);
|
||||
if (CTX_wm_region_view3d(C)) {
|
||||
int mval[2];
|
||||
if (!RNA_property_is_set(op->ptr, prop_location) && object_add_drop_xy_get(C, op, &mval)) {
|
||||
ED_object_location_from_view(C, loc);
|
||||
ED_view3d_cursor3d_position(C, mval, false, loc);
|
||||
RNA_property_float_set_array(op->ptr, prop_location, loc);
|
||||
}
|
||||
}
|
||||
|
||||
if (!ED_object_add_generic_get_opts(
|
||||
|
@ -3927,7 +3929,7 @@ static int object_add_named_exec(bContext *C, wmOperator *op)
|
|||
|
||||
DEG_id_tag_update(&ob_add->id, ID_RECALC_TRANSFORM);
|
||||
}
|
||||
else {
|
||||
else if (CTX_wm_region_view3d(C)) {
|
||||
int mval[2];
|
||||
if (object_add_drop_xy_get(C, op, &mval)) {
|
||||
ED_object_location_from_view(C, basen->object->loc);
|
||||
|
@ -4029,7 +4031,7 @@ static int object_transform_to_mouse_exec(bContext *C, wmOperator *op)
|
|||
|
||||
MEM_freeN(objects);
|
||||
}
|
||||
else {
|
||||
else if (CTX_wm_region_view3d(C)) {
|
||||
int mval[2];
|
||||
if (object_add_drop_xy_get(C, op, &mval)) {
|
||||
float cursor[3];
|
||||
|
|
|
@ -1024,6 +1024,9 @@ static int time_segment_remove_exec(bContext *C, wmOperator *op)
|
|||
TimeGpencilModifierData *gpmd = (TimeGpencilModifierData *)gpencil_edit_modifier_property_get(
|
||||
op, ob, eGpencilModifierType_Time);
|
||||
|
||||
if (gpmd == NULL) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
if (gpmd->segment_active_index < 0 || gpmd->segment_active_index >= gpmd->segments_len) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
@ -1100,6 +1103,9 @@ static int time_segment_move_exec(bContext *C, wmOperator *op)
|
|||
TimeGpencilModifierData *gpmd = (TimeGpencilModifierData *)gpencil_edit_modifier_property_get(
|
||||
op, ob, eGpencilModifierType_Time);
|
||||
|
||||
if (gpmd == NULL) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
if (gpmd->segments_len < 2) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
|
|
@ -1733,8 +1733,13 @@ static int modifier_apply_exec_ex(bContext *C, wmOperator *op, int apply_as, boo
|
|||
Object *ob = ED_object_active_context(C);
|
||||
ModifierData *md = edit_modifier_property_get(op, ob, 0);
|
||||
const bool do_report = RNA_boolean_get(op->ptr, "report");
|
||||
const bool do_single_user = RNA_boolean_get(op->ptr, "single_user");
|
||||
const bool do_merge_customdata = RNA_boolean_get(op->ptr, "merge_customdata");
|
||||
|
||||
const bool do_single_user = (apply_as == MODIFIER_APPLY_DATA) ?
|
||||
RNA_boolean_get(op->ptr, "single_user") :
|
||||
false;
|
||||
const bool do_merge_customdata = (apply_as == MODIFIER_APPLY_DATA) ?
|
||||
RNA_boolean_get(op->ptr, "merge_customdata") :
|
||||
false;
|
||||
|
||||
if (md == nullptr) {
|
||||
return OPERATOR_CANCELLED;
|
||||
|
|
|
@ -2857,7 +2857,7 @@ void OBJECT_OT_drop_named_material(wmOperatorType *ot)
|
|||
|
||||
/* api callbacks */
|
||||
ot->invoke = drop_named_material_invoke;
|
||||
ot->poll = ED_operator_objectmode_poll_msg;
|
||||
ot->poll = ED_operator_objectmode_with_view3d_poll_msg;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
|
||||
|
|
|
@ -213,6 +213,17 @@ bool ED_operator_objectmode_poll_msg(bContext *C)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ED_operator_objectmode_with_view3d_poll_msg(bContext *C)
|
||||
{
|
||||
if (!ED_operator_objectmode_poll_msg(C)) {
|
||||
return false;
|
||||
}
|
||||
if (!ED_operator_region_view3d_active(C)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ed_spacetype_test(bContext *C, int type)
|
||||
{
|
||||
if (ED_operator_areaactive(C)) {
|
||||
|
@ -237,6 +248,19 @@ bool ED_operator_region_view3d_active(bContext *C)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool ED_operator_region_gizmo_active(bContext *C)
|
||||
{
|
||||
ARegion *region = CTX_wm_region(C);
|
||||
if (region == NULL) {
|
||||
return false;
|
||||
}
|
||||
wmGizmoMap *gzmap = region->gizmo_map;
|
||||
if (gzmap == NULL) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ED_operator_animview_active(bContext *C)
|
||||
{
|
||||
if (ED_operator_areaactive(C)) {
|
||||
|
@ -4354,23 +4378,25 @@ static int screen_context_menu_invoke(bContext *C,
|
|||
ed_screens_statusbar_menu_create(layout, NULL);
|
||||
UI_popup_menu_end(C, pup);
|
||||
}
|
||||
else if (ELEM(region->regiontype, RGN_TYPE_HEADER, RGN_TYPE_TOOL_HEADER)) {
|
||||
uiPopupMenu *pup = UI_popup_menu_begin(C, IFACE_("Header"), ICON_NONE);
|
||||
uiLayout *layout = UI_popup_menu_layout(pup);
|
||||
ED_screens_header_tools_menu_create(C, layout, NULL);
|
||||
UI_popup_menu_end(C, pup);
|
||||
}
|
||||
else if (region->regiontype == RGN_TYPE_FOOTER) {
|
||||
uiPopupMenu *pup = UI_popup_menu_begin(C, IFACE_("Footer"), ICON_NONE);
|
||||
uiLayout *layout = UI_popup_menu_layout(pup);
|
||||
ED_screens_footer_tools_menu_create(C, layout, NULL);
|
||||
UI_popup_menu_end(C, pup);
|
||||
}
|
||||
else if (region->regiontype == RGN_TYPE_NAV_BAR) {
|
||||
uiPopupMenu *pup = UI_popup_menu_begin(C, IFACE_("Navigation Bar"), ICON_NONE);
|
||||
uiLayout *layout = UI_popup_menu_layout(pup);
|
||||
ED_screens_navigation_bar_tools_menu_create(C, layout, NULL);
|
||||
UI_popup_menu_end(C, pup);
|
||||
else if (region) {
|
||||
if (ELEM(region->regiontype, RGN_TYPE_HEADER, RGN_TYPE_TOOL_HEADER)) {
|
||||
uiPopupMenu *pup = UI_popup_menu_begin(C, IFACE_("Header"), ICON_NONE);
|
||||
uiLayout *layout = UI_popup_menu_layout(pup);
|
||||
ED_screens_header_tools_menu_create(C, layout, NULL);
|
||||
UI_popup_menu_end(C, pup);
|
||||
}
|
||||
else if (region->regiontype == RGN_TYPE_FOOTER) {
|
||||
uiPopupMenu *pup = UI_popup_menu_begin(C, IFACE_("Footer"), ICON_NONE);
|
||||
uiLayout *layout = UI_popup_menu_layout(pup);
|
||||
ED_screens_footer_tools_menu_create(C, layout, NULL);
|
||||
UI_popup_menu_end(C, pup);
|
||||
}
|
||||
else if (region->regiontype == RGN_TYPE_NAV_BAR) {
|
||||
uiPopupMenu *pup = UI_popup_menu_begin(C, IFACE_("Navigation Bar"), ICON_NONE);
|
||||
uiLayout *layout = UI_popup_menu_layout(pup);
|
||||
ED_screens_navigation_bar_tools_menu_create(C, layout, NULL);
|
||||
UI_popup_menu_end(C, pup);
|
||||
}
|
||||
}
|
||||
|
||||
return OPERATOR_INTERFACE;
|
||||
|
|
|
@ -202,8 +202,9 @@ static void stroke_done(const bContext *C, PaintStroke *stroke)
|
|||
|
||||
static int sculpt_curves_stroke_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
{
|
||||
const Paint *paint = BKE_paint_get_active_from_context(C);
|
||||
const Brush *brush = BKE_paint_brush_for_read(paint);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
Paint *paint = BKE_paint_get_active_from_paintmode(scene, PAINT_MODE_SCULPT_CURVES);
|
||||
const Brush *brush = paint ? BKE_paint_brush_for_read(paint) : nullptr;
|
||||
if (brush == nullptr) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
|
|
@ -2049,7 +2049,7 @@ static void calc_area_normal_and_center_task_cb(void *__restrict userdata,
|
|||
bool use_original = false;
|
||||
bool normal_test_r, area_test_r;
|
||||
|
||||
if (ss->cache && ss->cache->original) {
|
||||
if (ss->cache && !ss->cache->accum) {
|
||||
unode = SCULPT_undo_push_node(data->ob, data->nodes[n], SCULPT_UNDO_COORDS);
|
||||
use_original = (unode->co || unode->bm_entry);
|
||||
}
|
||||
|
@ -3436,7 +3436,7 @@ static void sculpt_topology_update(Sculpt *sd,
|
|||
|
||||
/* Build a list of all nodes that are potentially within the brush's area of influence. */
|
||||
const bool use_original = sculpt_tool_needs_original(brush->sculpt_tool) ? true :
|
||||
ss->cache->original;
|
||||
!ss->cache->accum;
|
||||
const float radius_scale = 1.25f;
|
||||
Vector<PBVHNode *> nodes = sculpt_pbvh_gather_generic(ob, sd, brush, use_original, radius_scale);
|
||||
|
||||
|
@ -3547,7 +3547,7 @@ static void do_brush_action(Sculpt *sd,
|
|||
}
|
||||
|
||||
const bool use_original = sculpt_tool_needs_original(brush->sculpt_tool) ? true :
|
||||
ss->cache->original;
|
||||
!ss->cache->accum;
|
||||
const bool use_pixels = sculpt_needs_pbvh_pixels(paint_mode_settings, brush, ob);
|
||||
|
||||
if (sculpt_needs_pbvh_pixels(paint_mode_settings, brush, ob)) {
|
||||
|
@ -4546,26 +4546,24 @@ static void sculpt_update_cache_invariants(
|
|||
normalize_v3(cache->true_gravity_direction);
|
||||
}
|
||||
|
||||
cache->accum = true;
|
||||
|
||||
/* Make copies of the mesh vertex locations and normals for some tools. */
|
||||
if (brush->flag & BRUSH_ANCHORED) {
|
||||
cache->original = true;
|
||||
}
|
||||
|
||||
if (SCULPT_automasking_needs_original(sd, brush)) {
|
||||
cache->original = true;
|
||||
cache->accum = false;
|
||||
}
|
||||
|
||||
/* Draw sharp does not need the original coordinates to produce the accumulate effect, so it
|
||||
* should work the opposite way. */
|
||||
if (brush->sculpt_tool == SCULPT_TOOL_DRAW_SHARP) {
|
||||
cache->original = true;
|
||||
cache->accum = false;
|
||||
}
|
||||
|
||||
if (SCULPT_TOOL_HAS_ACCUMULATE(brush->sculpt_tool)) {
|
||||
if (!(brush->flag & BRUSH_ACCUMULATE)) {
|
||||
cache->original = true;
|
||||
cache->accum = false;
|
||||
if (brush->sculpt_tool == SCULPT_TOOL_DRAW_SHARP) {
|
||||
cache->original = false;
|
||||
cache->accum = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4574,7 +4572,7 @@ static void sculpt_update_cache_invariants(
|
|||
* for image brushes. It's also not necessary, just disable it. */
|
||||
if (brush && brush->sculpt_tool == SCULPT_TOOL_PAINT &&
|
||||
SCULPT_use_image_paint_brush(&tool_settings->paint_mode, ob)) {
|
||||
cache->original = false;
|
||||
cache->accum = true;
|
||||
}
|
||||
|
||||
cache->first_time = true;
|
||||
|
@ -5068,7 +5066,7 @@ float SCULPT_raycast_init(ViewContext *vc,
|
|||
float obimat[4][4];
|
||||
float dist;
|
||||
Object *ob = vc->obact;
|
||||
RegionView3D *rv3d = static_cast<RegionView3D *>(vc->region->regiondata);
|
||||
RegionView3D *rv3d = vc->rv3d;
|
||||
View3D *v3d = vc->v3d;
|
||||
|
||||
/* TODO: what if the segment is totally clipped? (return == 0). */
|
||||
|
@ -5117,7 +5115,7 @@ bool SCULPT_cursor_geometry_info_update(bContext *C,
|
|||
ob = vc.obact;
|
||||
ss = ob->sculpt;
|
||||
|
||||
if (!ss->pbvh) {
|
||||
if (!ss->pbvh || !vc.rv3d) {
|
||||
zero_v3(out->location);
|
||||
zero_v3(out->normal);
|
||||
zero_v3(out->active_vertex_co);
|
||||
|
@ -5253,7 +5251,7 @@ bool SCULPT_stroke_get_location_ex(bContext *C,
|
|||
|
||||
ss = ob->sculpt;
|
||||
cache = ss->cache;
|
||||
original = force_original || ((cache) ? cache->original : false);
|
||||
original = force_original || ((cache) ? !cache->accum : false);
|
||||
|
||||
const Brush *brush = BKE_paint_brush(BKE_paint_get_active_from_context(C));
|
||||
|
||||
|
|
|
@ -335,7 +335,6 @@ static int sculpt_color_filter_init(bContext *C, wmOperator *op)
|
|||
Object *ob = CTX_data_active_object(C);
|
||||
Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
|
||||
SculptSession *ss = ob->sculpt;
|
||||
PBVH *pbvh = ob->sculpt->pbvh;
|
||||
View3D *v3d = CTX_wm_view3d(C);
|
||||
|
||||
int mval[2];
|
||||
|
@ -360,6 +359,7 @@ static int sculpt_color_filter_init(bContext *C, wmOperator *op)
|
|||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
const PBVHType pbvh_type_prev = BKE_pbvh_type(ss->pbvh);
|
||||
SCULPT_undo_push_begin(ob, op);
|
||||
BKE_sculpt_color_layer_create_if_needed(ob);
|
||||
|
||||
|
@ -367,8 +367,7 @@ static int sculpt_color_filter_init(bContext *C, wmOperator *op)
|
|||
* earlier steps modifying the data. */
|
||||
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
|
||||
BKE_sculpt_update_object_for_edit(depsgraph, ob, true, false, true);
|
||||
|
||||
if (BKE_pbvh_type(pbvh) == PBVH_FACES && !ob->sculpt->pmap) {
|
||||
if (pbvh_type_prev == PBVH_FACES && !ob->sculpt->pmap) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
|
|
|
@ -613,7 +613,10 @@ struct StrokeCache {
|
|||
int radial_symmetry_pass;
|
||||
float symm_rot_mat[4][4];
|
||||
float symm_rot_mat_inv[4][4];
|
||||
bool original;
|
||||
|
||||
/* Accumulate mode. Note: inverted for SCULPT_TOOL_DRAW_SHARP. */
|
||||
bool accum;
|
||||
|
||||
float anchored_location[3];
|
||||
|
||||
/* Paint Brush. */
|
||||
|
|
|
@ -906,9 +906,12 @@ static int sculpt_mask_by_color_invoke(bContext *C, wmOperator *op, const wmEven
|
|||
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
|
||||
Object *ob = CTX_data_active_object(C);
|
||||
SculptSession *ss = ob->sculpt;
|
||||
View3D *v3d = CTX_wm_view3d(C);
|
||||
if (v3d->shading.type == OB_SOLID) {
|
||||
v3d->shading.color_type = V3D_SHADING_VERTEX_COLOR;
|
||||
|
||||
{
|
||||
View3D *v3d = CTX_wm_view3d(C);
|
||||
if (v3d && v3d->shading.type == OB_SOLID) {
|
||||
v3d->shading.color_type = V3D_SHADING_VERTEX_COLOR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Color data is not available in multi-resolution or dynamic topology. */
|
||||
|
|
|
@ -177,7 +177,8 @@ enum {
|
|||
};
|
||||
|
||||
struct FileListEntryPreview {
|
||||
char filepath[FILE_MAX];
|
||||
/** Use #FILE_MAX_LIBEXTRA as this is the size written into by #filelist_file_get_full_path. */
|
||||
char filepath[FILE_MAX_LIBEXTRA];
|
||||
uint flags;
|
||||
int index;
|
||||
int attributes; /* from FileDirEntry. */
|
||||
|
@ -3111,7 +3112,7 @@ static void filelist_readjob_list_lib_add_datablock(FileListReadJob *job_params,
|
|||
{
|
||||
FileListInternEntry *entry = MEM_cnew<FileListInternEntry>(__func__);
|
||||
if (prefix_relpath_with_group_name) {
|
||||
std::string datablock_path = StringRef(group_name) + "/" + datablock_info->name;
|
||||
std::string datablock_path = StringRef(group_name) + SEP_STR + datablock_info->name;
|
||||
entry->relpath = current_relpath_append(job_params, datablock_path.c_str());
|
||||
}
|
||||
else {
|
||||
|
@ -3791,7 +3792,7 @@ static void filelist_readjob_main_assets_add_items(FileListReadJob *job_params,
|
|||
const char *id_code_name = BKE_idtype_idcode_to_name(GS(id_iter->name));
|
||||
|
||||
entry = MEM_cnew<FileListInternEntry>(__func__);
|
||||
std::string datablock_path = StringRef(id_code_name) + "/" + (id_iter->name + 2);
|
||||
std::string datablock_path = StringRef(id_code_name) + SEP_STR + (id_iter->name + 2);
|
||||
entry->relpath = current_relpath_append(job_params, datablock_path.c_str());
|
||||
entry->name = id_iter->name + 2;
|
||||
entry->free_name = false;
|
||||
|
|
|
@ -847,7 +847,7 @@ static void create_inspection_string_for_generic_value(const bNodeSocket &socket
|
|||
return;
|
||||
}
|
||||
if (value_type.is<std::string>()) {
|
||||
ss << *static_cast<const std::string *>(buffer) << TIP_(" (String)");
|
||||
ss << *static_cast<const std::string *>(buffer) << " " << TIP_("(String)");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -864,22 +864,22 @@ static void create_inspection_string_for_generic_value(const bNodeSocket &socket
|
|||
BLI_SCOPED_DEFER([&]() { socket_type.destruct(socket_value); });
|
||||
|
||||
if (socket_type.is<int>()) {
|
||||
ss << *static_cast<int *>(socket_value) << TIP_(" (Integer)");
|
||||
ss << *static_cast<int *>(socket_value) << " " << TIP_("(Integer)");
|
||||
}
|
||||
else if (socket_type.is<float>()) {
|
||||
ss << *static_cast<float *>(socket_value) << TIP_(" (Float)");
|
||||
ss << *static_cast<float *>(socket_value) << " " << TIP_("(Float)");
|
||||
}
|
||||
else if (socket_type.is<blender::float3>()) {
|
||||
ss << *static_cast<blender::float3 *>(socket_value) << TIP_(" (Vector)");
|
||||
ss << *static_cast<blender::float3 *>(socket_value) << " " << TIP_("(Vector)");
|
||||
}
|
||||
else if (socket_type.is<blender::ColorGeometry4f>()) {
|
||||
const blender::ColorGeometry4f &color = *static_cast<blender::ColorGeometry4f *>(socket_value);
|
||||
ss << "(" << color.r << ", " << color.g << ", " << color.b << ", " << color.a << ")"
|
||||
<< TIP_(" (Color)");
|
||||
ss << "(" << color.r << ", " << color.g << ", " << color.b << ", " << color.a << ") "
|
||||
<< TIP_("(Color)");
|
||||
}
|
||||
else if (socket_type.is<bool>()) {
|
||||
ss << ((*static_cast<bool *>(socket_value)) ? TIP_("True") : TIP_("False"))
|
||||
<< TIP_(" (Boolean)");
|
||||
ss << ((*static_cast<bool *>(socket_value)) ? TIP_("True") : TIP_("False")) << " "
|
||||
<< TIP_("(Boolean)");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -893,32 +893,32 @@ static void create_inspection_string_for_field_info(const bNodeSocket &socket,
|
|||
if (input_tooltips.is_empty()) {
|
||||
/* Should have been logged as constant value. */
|
||||
BLI_assert_unreachable();
|
||||
ss << "Value has not been logged";
|
||||
ss << TIP_("Value has not been logged");
|
||||
}
|
||||
else {
|
||||
if (socket_type.is<int>()) {
|
||||
ss << TIP_("Integer field");
|
||||
ss << TIP_("Integer field based on:");
|
||||
}
|
||||
else if (socket_type.is<float>()) {
|
||||
ss << TIP_("Float field");
|
||||
ss << TIP_("Float field based on:");
|
||||
}
|
||||
else if (socket_type.is<blender::float3>()) {
|
||||
ss << TIP_("Vector field");
|
||||
ss << TIP_("Vector field based on:");
|
||||
}
|
||||
else if (socket_type.is<bool>()) {
|
||||
ss << TIP_("Boolean field");
|
||||
ss << TIP_("Boolean field based on:");
|
||||
}
|
||||
else if (socket_type.is<std::string>()) {
|
||||
ss << TIP_("String field");
|
||||
ss << TIP_("String field based on:");
|
||||
}
|
||||
else if (socket_type.is<blender::ColorGeometry4f>()) {
|
||||
ss << TIP_("Color field");
|
||||
ss << TIP_("Color field based on:");
|
||||
}
|
||||
ss << TIP_(" based on:\n");
|
||||
ss << "\n";
|
||||
|
||||
for (const int i : input_tooltips.index_range()) {
|
||||
const blender::StringRef tooltip = input_tooltips[i];
|
||||
ss << "\u2022 " << tooltip;
|
||||
ss << "\u2022 " << TIP_(tooltip.data());
|
||||
if (i < input_tooltips.size() - 1) {
|
||||
ss << ".\n";
|
||||
}
|
||||
|
@ -941,7 +941,7 @@ static void create_inspection_string_for_geometry_info(const geo_log::GeometryIn
|
|||
return std::string(str);
|
||||
};
|
||||
|
||||
ss << TIP_("Geometry:\n");
|
||||
ss << TIP_("Geometry:") << "\n";
|
||||
for (GeometryComponentType type : component_types) {
|
||||
switch (type) {
|
||||
case GEO_COMPONENT_TYPE_MESH: {
|
||||
|
@ -1865,7 +1865,7 @@ static char *named_attribute_tooltip(bContext * /*C*/, void *argN, const char *
|
|||
NamedAttributeTooltipArg &arg = *static_cast<NamedAttributeTooltipArg *>(argN);
|
||||
|
||||
std::stringstream ss;
|
||||
ss << TIP_("Accessed named attributes:\n");
|
||||
ss << TIP_("Accessed named attributes:") << "\n";
|
||||
|
||||
struct NameWithUsage {
|
||||
StringRefNull name;
|
||||
|
@ -1917,7 +1917,7 @@ static NodeExtraInfoRow row_from_used_named_attribute(
|
|||
|
||||
NodeExtraInfoRow row;
|
||||
row.text = std::to_string(attributes_num) +
|
||||
TIP_(attributes_num == 1 ? " Named Attribute" : " Named Attributes");
|
||||
(attributes_num == 1 ? TIP_(" Named Attribute") : TIP_(" Named Attributes"));
|
||||
row.icon = ICON_SPREADSHEET;
|
||||
row.tooltip_fn = named_attribute_tooltip;
|
||||
row.tooltip_fn_arg = new NamedAttributeTooltipArg{usage_by_attribute_name};
|
||||
|
|
|
@ -52,7 +52,7 @@ void SEQUENCER_OT_rename_channel(struct wmOperatorType *ot)
|
|||
|
||||
/* Api callbacks. */
|
||||
ot->invoke = sequencer_rename_channel_invoke;
|
||||
ot->poll = sequencer_edit_poll;
|
||||
ot->poll = sequencer_edit_with_channel_region_poll;
|
||||
|
||||
/* Flags. */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
|
||||
|
|
|
@ -175,6 +175,18 @@ bool sequencer_edit_poll(bContext *C)
|
|||
return (SEQ_editing_get(CTX_data_scene(C)) != NULL);
|
||||
}
|
||||
|
||||
bool sequencer_edit_with_channel_region_poll(bContext *C)
|
||||
{
|
||||
if (!sequencer_edit_poll(C)) {
|
||||
return false;
|
||||
}
|
||||
ARegion *region = CTX_wm_region(C);
|
||||
if (!(region && (region->regiontype == RGN_TYPE_CHANNELS))) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool sequencer_editing_initialized_and_active(bContext *C)
|
||||
{
|
||||
return ED_operator_sequencer_active(C) && sequencer_edit_poll(C);
|
||||
|
@ -1482,14 +1494,14 @@ static int sequencer_split_invoke(bContext *C, wmOperator *op, const wmEvent *ev
|
|||
}
|
||||
}
|
||||
float mouseloc[2];
|
||||
UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &mouseloc[0], &mouseloc[1]);
|
||||
if (RNA_boolean_get(op->ptr, "use_cursor_position")) {
|
||||
RNA_int_set(op->ptr, "frame", mouseloc[0]);
|
||||
if (v2d) {
|
||||
UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &mouseloc[0], &mouseloc[1]);
|
||||
if (RNA_boolean_get(op->ptr, "use_cursor_position")) {
|
||||
split_frame = mouseloc[0];
|
||||
}
|
||||
RNA_int_set(op->ptr, "channel", mouseloc[1]);
|
||||
}
|
||||
else {
|
||||
RNA_int_set(op->ptr, "frame", split_frame);
|
||||
}
|
||||
RNA_int_set(op->ptr, "channel", mouseloc[1]);
|
||||
RNA_int_set(op->ptr, "frame", split_frame);
|
||||
RNA_enum_set(op->ptr, "side", split_side);
|
||||
// RNA_enum_set(op->ptr, "type", split_hard);
|
||||
|
||||
|
@ -1711,16 +1723,17 @@ static int sequencer_delete_exec(bContext *C, wmOperator *op)
|
|||
|
||||
static int sequencer_delete_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
{
|
||||
ARegion *region = CTX_wm_region(C);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
ListBase *markers = &scene->markers;
|
||||
|
||||
if (region->regiontype == RGN_TYPE_WINDOW && !BLI_listbase_is_empty(markers)) {
|
||||
/* Bounding box of 30 pixels is used for markers shortcuts,
|
||||
* prevent conflict with markers shortcuts here.
|
||||
*/
|
||||
if (event->mval[1] <= 30) {
|
||||
return OPERATOR_PASS_THROUGH;
|
||||
if (!BLI_listbase_is_empty(markers)) {
|
||||
ARegion *region = CTX_wm_region(C);
|
||||
if (region && (region->regiontype == RGN_TYPE_WINDOW)) {
|
||||
/* Bounding box of 30 pixels is used for markers shortcuts,
|
||||
* prevent conflict with markers shortcuts here. */
|
||||
if (event->mval[1] <= 30) {
|
||||
return OPERATOR_PASS_THROUGH;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1731,9 +1744,9 @@ void SEQUENCER_OT_delete(wmOperatorType *ot)
|
|||
{
|
||||
|
||||
/* Identifiers. */
|
||||
ot->name = "Erase Strips";
|
||||
ot->name = "Delete Strips";
|
||||
ot->idname = "SEQUENCER_OT_delete";
|
||||
ot->description = "Erase selected strips from the sequencer";
|
||||
ot->description = "Delete selected strips from the sequencer";
|
||||
|
||||
/* Api callbacks. */
|
||||
ot->invoke = sequencer_delete_invoke;
|
||||
|
|
|
@ -141,6 +141,7 @@ int seq_effect_find_selected(struct Scene *scene,
|
|||
|
||||
/* Operator helpers. */
|
||||
bool sequencer_edit_poll(struct bContext *C);
|
||||
bool sequencer_edit_with_channel_region_poll(struct bContext *C);
|
||||
bool sequencer_editing_initialized_and_active(struct bContext *C);
|
||||
/* UNUSED */
|
||||
/* bool sequencer_strip_poll(struct bContext *C); */
|
||||
|
|
|
@ -41,14 +41,15 @@ using blender::MutableSpan;
|
|||
|
||||
static bool retiming_poll(bContext *C)
|
||||
{
|
||||
if (!sequencer_edit_poll(C)) {
|
||||
const Editing *ed = SEQ_editing_get(CTX_data_scene(C));
|
||||
if (ed == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const Editing *ed = SEQ_editing_get(CTX_data_scene(C));
|
||||
Sequence *seq = ed->act_seq;
|
||||
|
||||
if (seq != nullptr && !SEQ_retiming_is_allowed(seq)) {
|
||||
if (seq == nullptr) {
|
||||
return false;
|
||||
}
|
||||
if (!SEQ_retiming_is_allowed(seq)) {
|
||||
CTX_wm_operator_poll_msg_set(C, "This strip type can not be retimed");
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -568,7 +568,7 @@ static void spreadsheet_footer_region_draw(const bContext *C, ARegion *region)
|
|||
SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C);
|
||||
SpaceSpreadsheet_Runtime *runtime = sspreadsheet->runtime;
|
||||
std::stringstream ss;
|
||||
ss << "Rows: ";
|
||||
ss << IFACE_("Rows:") << " ";
|
||||
if (runtime->visible_rows != runtime->tot_rows) {
|
||||
char visible_rows_str[BLI_STR_FORMAT_INT32_GROUPED_SIZE];
|
||||
BLI_str_format_int_grouped(visible_rows_str, runtime->visible_rows);
|
||||
|
@ -576,7 +576,7 @@ static void spreadsheet_footer_region_draw(const bContext *C, ARegion *region)
|
|||
}
|
||||
char tot_rows_str[BLI_STR_FORMAT_INT32_GROUPED_SIZE];
|
||||
BLI_str_format_int_grouped(tot_rows_str, runtime->tot_rows);
|
||||
ss << tot_rows_str << " | Columns: " << runtime->tot_columns;
|
||||
ss << tot_rows_str << " | " << IFACE_("Columns:") << " " << runtime->tot_columns;
|
||||
std::string stats_str = ss.str();
|
||||
|
||||
UI_ThemeClearColor(TH_BACK);
|
||||
|
|
|
@ -102,6 +102,7 @@ static void SPREADSHEET_OT_change_spreadsheet_data_source(wmOperatorType *ot)
|
|||
ot->idname = "SPREADSHEET_OT_change_spreadsheet_data_source";
|
||||
|
||||
ot->invoke = select_component_domain_invoke;
|
||||
ot->poll = ED_operator_spreadsheet_active;
|
||||
|
||||
RNA_def_int(ot->srna, "component_type", 0, 0, INT16_MAX, "Component Type", "", 0, INT16_MAX);
|
||||
RNA_def_int(ot->srna,
|
||||
|
|
|
@ -860,7 +860,7 @@ static void gizmo_ruler_draw(const bContext *C, wmGizmo *gz)
|
|||
posit[0] = co_ss[1][0] - (numstr_size[0] / 2.0f);
|
||||
posit[1] = co_ss[1][1] - (numstr_size[1] / 2.0f);
|
||||
|
||||
/* Adjust text position to help readability. */
|
||||
/* Adjust text position to help readability. */
|
||||
sub_v2_v2v2(dir_ruler, co_ss[0], co_ss[1]);
|
||||
float rot_90_vec[2] = {-dir_ruler[1], dir_ruler[0]};
|
||||
normalize_v2(rot_90_vec);
|
||||
|
@ -941,7 +941,7 @@ static void gizmo_ruler_draw(const bContext *C, wmGizmo *gz)
|
|||
/* center text */
|
||||
posit -= numstr_size / 2.0f;
|
||||
|
||||
/* Adjust text position if this helps readability. */
|
||||
/* Adjust text position if this helps readability. */
|
||||
|
||||
const float len = len_v2v2(co_ss[0], co_ss[2]);
|
||||
|
||||
|
|
|
@ -494,7 +494,7 @@ bool view3d_orbit_calc_center(bContext *C, float r_dyn_ofs[3])
|
|||
static eViewOpsFlag viewops_flag_from_prefs(void)
|
||||
{
|
||||
const bool use_select = (U.uiflag & USER_ORBIT_SELECTION) != 0;
|
||||
const bool use_depth = (U.uiflag & VIEWOPS_FLAG_DEPTH_NAVIGATE) != 0;
|
||||
const bool use_depth = (U.uiflag & USER_DEPTH_NAVIGATE) != 0;
|
||||
const bool use_zoom_to_mouse = (U.uiflag & USER_ZOOM_TO_MOUSEPOS) != 0;
|
||||
|
||||
enum eViewOpsFlag flag = VIEWOPS_FLAG_NONE;
|
||||
|
|
|
@ -909,9 +909,12 @@ static void view3d_interactive_add_exit(bContext *C, wmOperator *op)
|
|||
struct InteractivePlaceData *ipd = op->customdata;
|
||||
ED_view3d_cursor_snap_deactive(ipd->snap_state);
|
||||
|
||||
ED_region_draw_cb_exit(ipd->region->type, ipd->draw_handle_view);
|
||||
|
||||
ED_region_tag_redraw(ipd->region);
|
||||
if (ipd->region != NULL) {
|
||||
if (ipd->draw_handle_view != NULL) {
|
||||
ED_region_draw_cb_exit(ipd->region->type, ipd->draw_handle_view);
|
||||
}
|
||||
ED_region_tag_redraw(ipd->region);
|
||||
}
|
||||
|
||||
MEM_freeN(ipd);
|
||||
}
|
||||
|
|
|
@ -778,7 +778,14 @@ static void drawLine(
|
|||
|
||||
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
|
||||
|
||||
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
|
||||
float viewport[4];
|
||||
GPU_viewport_size_get_f(viewport);
|
||||
GPU_blend(GPU_BLEND_ALPHA);
|
||||
|
||||
immBindBuiltinProgram(GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR);
|
||||
immUniform2fv("viewportSize", &viewport[2]);
|
||||
immUniform1f("lineWidth", U.pixelsize * 2.0f);
|
||||
|
||||
immUniformColor3ubv(col2);
|
||||
|
||||
immBegin(GPU_PRIM_LINES, 2);
|
||||
|
|
|
@ -1233,7 +1233,6 @@ static void uvedit_pack_islands_multi(const Scene *scene,
|
|||
MemArena *arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
|
||||
Heap *heap = BLI_heap_new();
|
||||
|
||||
float scale[2] = {1.0f, 1.0f};
|
||||
blender::Vector<blender::geometry::PackIsland *> pack_island_vector;
|
||||
for (int i = 0; i < island_vector.size(); i++) {
|
||||
FaceIsland *face_island = island_vector[i];
|
||||
|
@ -1264,7 +1263,7 @@ static void uvedit_pack_islands_multi(const Scene *scene,
|
|||
BLI_heap_free(heap, nullptr);
|
||||
BLI_memarena_free(arena);
|
||||
|
||||
pack_islands(pack_island_vector, *params, scale);
|
||||
const float scale = pack_islands(pack_island_vector, *params);
|
||||
|
||||
float base_offset[2] = {0.0f, 0.0f};
|
||||
copy_v2_v2(base_offset, params->udim_base_offset);
|
||||
|
@ -1306,7 +1305,7 @@ static void uvedit_pack_islands_multi(const Scene *scene,
|
|||
for (int64_t i : pack_island_vector.index_range()) {
|
||||
blender::geometry::PackIsland *pack_island = pack_island_vector[i];
|
||||
FaceIsland *island = island_vector[pack_island->caller_index];
|
||||
pack_island->build_transformation(scale[0], pack_island->angle, matrix);
|
||||
pack_island->build_transformation(scale, pack_island->angle, matrix);
|
||||
invert_m2_m2(matrix_inverse, matrix);
|
||||
|
||||
/* Add base_offset, post transform. */
|
||||
|
@ -1323,7 +1322,7 @@ static void uvedit_pack_islands_multi(const Scene *scene,
|
|||
const float rescale_x = (selection_max_co[0] - selection_min_co[0]) /
|
||||
params->target_aspect_y;
|
||||
const float rescale_y = (selection_max_co[1] - selection_min_co[1]);
|
||||
const float rescale = std::min(rescale_x, rescale_y);
|
||||
const float rescale = params->scale_to_fit ? std::min(rescale_x, rescale_y) : 1.0f;
|
||||
matrix[0][0] = rescale;
|
||||
matrix[0][1] = 0.0f;
|
||||
matrix[1][0] = 0.0f;
|
||||
|
@ -1396,6 +1395,7 @@ static int pack_islands_exec(bContext *C, wmOperator *op)
|
|||
blender::geometry::UVPackIsland_Params pack_island_params;
|
||||
pack_island_params.setFromUnwrapOptions(options);
|
||||
pack_island_params.rotate = RNA_boolean_get(op->ptr, "rotate");
|
||||
pack_island_params.scale_to_fit = RNA_boolean_get(op->ptr, "scale");
|
||||
pack_island_params.merge_overlap = RNA_boolean_get(op->ptr, "merge_overlap");
|
||||
pack_island_params.ignore_pinned = false;
|
||||
pack_island_params.margin_method = eUVPackIsland_MarginMethod(
|
||||
|
@ -1474,6 +1474,7 @@ void UV_OT_pack_islands(wmOperatorType *ot)
|
|||
/* properties */
|
||||
RNA_def_enum(ot->srna, "udim_source", pack_target, PACK_UDIM_SRC_CLOSEST, "Pack to", "");
|
||||
RNA_def_boolean(ot->srna, "rotate", true, "Rotate", "Rotate islands for best fit");
|
||||
RNA_def_boolean(ot->srna, "scale", true, "Scale", "Scale islands to fill unit square");
|
||||
RNA_def_boolean(
|
||||
ot->srna, "merge_overlap", false, "Merge Overlapped", "Overlapping islands stick together");
|
||||
RNA_def_enum(ot->srna,
|
||||
|
|
|
@ -48,6 +48,8 @@ class UVPackIsland_Params {
|
|||
|
||||
/** Islands can be rotated to improve packing. */
|
||||
bool rotate;
|
||||
/** Resize islands to fill the unit square. */
|
||||
bool scale_to_fit;
|
||||
/** (In UV Editor) only pack islands which have one or more selected UVs. */
|
||||
bool only_selected_uvs;
|
||||
/** (In 3D Viewport or UV Editor) only pack islands which have selected faces. */
|
||||
|
@ -110,18 +112,17 @@ class PackIsland {
|
|||
void place_(const float scale, const uv_phi phi);
|
||||
void finalize_geometry_(const UVPackIsland_Params ¶ms, MemArena *arena, Heap *heap);
|
||||
|
||||
blender::Vector<float2> triangle_vertices_;
|
||||
|
||||
private:
|
||||
void calculate_pivot_(); /* Calculate `pivot_` and `half_diagonal_` based on added triangles. */
|
||||
void calculate_pre_rotation_(const UVPackIsland_Params ¶ms);
|
||||
|
||||
blender::Vector<float2> triangle_vertices_;
|
||||
friend class Occupancy;
|
||||
friend class OverlapMerger;
|
||||
};
|
||||
|
||||
void pack_islands(const Span<PackIsland *> &islands,
|
||||
const UVPackIsland_Params ¶ms,
|
||||
float r_scale[2]);
|
||||
float pack_islands(const Span<PackIsland *> &islands, const UVPackIsland_Params ¶ms);
|
||||
|
||||
/** Compute `r = mat * (a + b)` with high precision. */
|
||||
void mul_v2_m2_add_v2v2(float r[2], const float mat[2][2], const float a[2], const float b[2]);
|
||||
|
|
|
@ -295,6 +295,7 @@ void PackIsland::place_(const float scale, const uv_phi phi)
|
|||
UVPackIsland_Params::UVPackIsland_Params()
|
||||
{
|
||||
rotate = false;
|
||||
scale_to_fit = true;
|
||||
only_selected_uvs = false;
|
||||
only_selected_faces = false;
|
||||
use_seams = false;
|
||||
|
@ -597,6 +598,7 @@ class Occupancy {
|
|||
Occupancy(const float initial_scale);
|
||||
|
||||
void increase_scale(); /* Resize the scale of the bitmap and clear it. */
|
||||
void clear(); /* Clear occupancy information. */
|
||||
|
||||
/* Write or Query a triangle on the bitmap. */
|
||||
float trace_triangle(const float2 &uv0,
|
||||
|
@ -637,6 +639,11 @@ void Occupancy::increase_scale()
|
|||
BLI_assert(bitmap_scale_reciprocal > 0.0f); /* TODO: Packing has failed, report error. */
|
||||
|
||||
bitmap_scale_reciprocal *= 0.5f;
|
||||
clear();
|
||||
}
|
||||
|
||||
void Occupancy::clear()
|
||||
{
|
||||
for (int i = 0; i < bitmap_radix * bitmap_radix; i++) {
|
||||
bitmap_[i] = terminal;
|
||||
}
|
||||
|
@ -728,33 +735,33 @@ float Occupancy::trace_triangle(const float2 &uv0,
|
|||
return -1.0f; /* Available. */
|
||||
}
|
||||
|
||||
float2 PackIsland::get_diagonal_support_d4(const float scale,
|
||||
const float rotation,
|
||||
const float margin) const
|
||||
float2 PackIsland::get_diagonal_support(const float scale,
|
||||
const float rotation,
|
||||
/* const bool reflection, */
|
||||
const float margin) const
|
||||
{
|
||||
if (rotation == 0.0f) {
|
||||
return half_diagonal_ * scale + margin; /* Fast path for common case. */
|
||||
/* Caution: Only "Dihedral Group D4" transforms are calculated exactly.
|
||||
* if the transform is Non-D4, an upper bound will be returned instead. */
|
||||
|
||||
if (rotation == DEG2RADF(-180.0f) || rotation == 0.0f || rotation == DEG2RADF(180.0f)) {
|
||||
return half_diagonal_ * scale + margin;
|
||||
}
|
||||
|
||||
if (rotation == DEG2RADF(180.0f)) {
|
||||
return get_diagonal_support_d4(scale, 0.0f, margin); /* Same as 0.0f */
|
||||
if (rotation == DEG2RADF(-90.0f) || rotation == DEG2RADF(90.0f) ||
|
||||
rotation == DEG2RADF(270.0f)) {
|
||||
return float2(half_diagonal_.y / aspect_y, half_diagonal_.x * aspect_y) * scale + margin;
|
||||
}
|
||||
|
||||
/* TODO: BLI_assert rotation is a "Dihedral Group D4" transform. */
|
||||
float matrix[2][2];
|
||||
build_transformation(scale, rotation, matrix);
|
||||
|
||||
/* TODO: Use convex hull to calculate support. */
|
||||
float diagonal_rotated[2];
|
||||
mul_v2_m2v2(diagonal_rotated, matrix, half_diagonal_);
|
||||
return float2(fabsf(diagonal_rotated[0]) + margin, fabsf(diagonal_rotated[1]) + margin);
|
||||
}
|
||||
float sx = fabsf(diagonal_rotated[0]);
|
||||
float sy = fabsf(diagonal_rotated[1]);
|
||||
|
||||
float2 PackIsland::get_diagonal_support(const float scale,
|
||||
const float rotation,
|
||||
const float margin) const
|
||||
{
|
||||
/* Only "D4" transforms are currently supported. */
|
||||
return get_diagonal_support_d4(scale, rotation, margin);
|
||||
return float2(sx + sy * 0.5f + margin, sx * 0.5f + sy + margin); /* Upper bound. */
|
||||
}
|
||||
|
||||
float Occupancy::trace_island(const PackIsland *island,
|
||||
|
@ -815,7 +822,7 @@ static uv_phi find_best_fit_for_island(const PackIsland *island,
|
|||
island->build_transformation(scale, phi.rotation, matrix);
|
||||
|
||||
/* Caution, margin is zero for support_diagonal as we're tracking the top-right corner. */
|
||||
float2 support_diagonal = island->get_diagonal_support_d4(scale, phi.rotation, 0.0f);
|
||||
float2 support_diagonal = island->get_diagonal_support(scale, phi.rotation, 0.0f);
|
||||
|
||||
/* Scan using an "Alpaca"-style search, first horizontally using "less-than". */
|
||||
int t = int(ceilf((2 * support_diagonal.x + margin) * occupancy.bitmap_scale_reciprocal));
|
||||
|
@ -855,6 +862,161 @@ static float guess_initial_scale(const Span<PackIsland *> islands,
|
|||
return sqrtf(sum) / 6.0f;
|
||||
}
|
||||
|
||||
/** Helper to find the minimum enclosing square. */
|
||||
class UVMinimumEnclosingSquareFinder {
|
||||
public:
|
||||
const float scale_;
|
||||
const float margin_;
|
||||
const UVPackIsland_Params *params_;
|
||||
|
||||
float best_quad;
|
||||
float best_angle;
|
||||
rctf best_bounds;
|
||||
|
||||
blender::Vector<float2> points;
|
||||
blender::Vector<int> indices;
|
||||
|
||||
UVMinimumEnclosingSquareFinder(const float scale,
|
||||
const float margin,
|
||||
const UVPackIsland_Params *params)
|
||||
: scale_(scale), margin_(margin), params_(params)
|
||||
{
|
||||
best_angle = 0.0f;
|
||||
best_quad = 0.0f;
|
||||
}
|
||||
|
||||
/** Calculates the square associated with a rotation of `angle`.
|
||||
* \return Size of square. */
|
||||
|
||||
float update(const float angle)
|
||||
{
|
||||
float2 dir(cosf(angle), sinf(angle));
|
||||
|
||||
/* TODO: Once convexhull_2d bugs are fixed, we can use "rotating calipers" to go faster. */
|
||||
rctf bounds;
|
||||
BLI_rctf_init_minmax(&bounds);
|
||||
for (const int64_t i : indices.index_range()) {
|
||||
const float2 &p = points[indices[i]];
|
||||
const float uv[2] = {p.x * dir.x + p.y * dir.y, -p.x * dir.y + p.y * dir.x};
|
||||
BLI_rctf_do_minmax_v(&bounds, uv);
|
||||
}
|
||||
bounds.xmin -= margin_;
|
||||
bounds.ymin -= margin_;
|
||||
bounds.xmax += margin_;
|
||||
bounds.ymax += margin_;
|
||||
const float current_quad = std::max(BLI_rctf_size_x(&bounds) / params_->target_aspect_y,
|
||||
BLI_rctf_size_y(&bounds));
|
||||
if (best_quad > current_quad) {
|
||||
best_quad = current_quad;
|
||||
best_angle = angle;
|
||||
best_bounds = bounds;
|
||||
}
|
||||
return current_quad;
|
||||
}
|
||||
|
||||
/** Search between `angle0` and `angle1`, looking for the smallest square. */
|
||||
void update_recursive(const float angle0,
|
||||
const float quad0,
|
||||
const float angle1,
|
||||
const float quad1)
|
||||
{
|
||||
const float angle_mid = (angle0 + angle1) * 0.5f;
|
||||
const float quad_mid = update(angle_mid);
|
||||
const float angle_separation = angle1 - angle0;
|
||||
|
||||
if (angle_separation < DEG2RADF(0.002f)) {
|
||||
return; /* Sufficient accuracy achieved. */
|
||||
}
|
||||
|
||||
bool search_mode = DEG2RADF(10.0f) < angle_separation; /* In linear search mode. */
|
||||
|
||||
/* TODO: Degenerate inputs could have poor performance here. */
|
||||
if (search_mode || (quad0 <= quad1)) {
|
||||
update_recursive(angle0, quad0, angle_mid, quad_mid);
|
||||
}
|
||||
if (search_mode || (quad1 <= quad0)) {
|
||||
update_recursive(angle_mid, quad_mid, angle1, quad1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Find the minimum bounding square that encloses the UVs as specified in `r_phis`.
|
||||
* If that square is smaller than `r_max_u` and `r_max_v`, then update `r_phis` accordingly.
|
||||
* \return True iff `r_phis`, `r_max_u` and `r_max_v` are modified.
|
||||
*/
|
||||
static bool rotate_inside_square(const Span<UVAABBIsland *> island_indices,
|
||||
const Span<PackIsland *> islands,
|
||||
const UVPackIsland_Params ¶ms,
|
||||
const float scale,
|
||||
const float margin,
|
||||
MutableSpan<uv_phi> r_phis,
|
||||
float *r_max_u,
|
||||
float *r_max_v)
|
||||
{
|
||||
if (!params.rotate) {
|
||||
return false; /* Unable to rotate. */
|
||||
}
|
||||
if (params.shape_method == ED_UVPACK_SHAPE_AABB) {
|
||||
return false; /* AABB margin calculations are not preserved under rotations. */
|
||||
}
|
||||
BLI_assert(islands.size() > 0);
|
||||
|
||||
UVMinimumEnclosingSquareFinder square_finder(scale, margin, ¶ms);
|
||||
square_finder.best_quad = std::max(*r_max_u / params.target_aspect_y, *r_max_v);
|
||||
|
||||
float matrix[2][2];
|
||||
|
||||
const float aspect_y = 1.0f; /* TODO: Use `islands[0]->aspect_y`. */
|
||||
for (const int64_t j : island_indices.index_range()) {
|
||||
const int64_t i = island_indices[j]->index;
|
||||
const PackIsland *island = islands[i];
|
||||
if (island->aspect_y != aspect_y) {
|
||||
return false; /* Aspect ratios are not preserved under rotation. */
|
||||
}
|
||||
|
||||
island->build_transformation(scale, r_phis[i].rotation, matrix);
|
||||
float2 pivot_transformed;
|
||||
mul_v2_m2v2(pivot_transformed, matrix, island->pivot_);
|
||||
float2 delta = r_phis[i].translation - pivot_transformed;
|
||||
|
||||
for (const int64_t k : island->triangle_vertices_.index_range()) {
|
||||
float2 p = island->triangle_vertices_[k];
|
||||
mul_m2_v2(matrix, p);
|
||||
square_finder.points.append(p + delta);
|
||||
}
|
||||
}
|
||||
|
||||
const float(*source)[2] = reinterpret_cast<const float(*)[2]>(square_finder.points.data());
|
||||
|
||||
square_finder.indices.resize(square_finder.points.size());
|
||||
int convex_size = BLI_convexhull_2d(
|
||||
source, static_cast<int>(square_finder.points.size()), square_finder.indices.data());
|
||||
square_finder.indices.resize(convex_size);
|
||||
|
||||
const float quad_180 = square_finder.update(DEG2RADF(-180.0f));
|
||||
square_finder.update_recursive(DEG2RADF(-180.0f), quad_180, DEG2RADF(180.0f), quad_180);
|
||||
|
||||
if (square_finder.best_angle == 0.0f) {
|
||||
return false; /* Nothing to do. */
|
||||
}
|
||||
|
||||
/* Can use islands[0] because all islands have the same aspect_ratio. */
|
||||
islands[0]->build_transformation(scale, square_finder.best_angle, matrix);
|
||||
|
||||
/* Transform phis. */
|
||||
for (const int64_t j : island_indices.index_range()) {
|
||||
const int64_t i = island_indices[j]->index;
|
||||
r_phis[i].rotation += square_finder.best_angle;
|
||||
mul_m2_v2(matrix, r_phis[i].translation);
|
||||
r_phis[i].translation.x -= square_finder.best_bounds.xmin;
|
||||
r_phis[i].translation.y -= square_finder.best_bounds.ymin;
|
||||
}
|
||||
*r_max_u = BLI_rctf_size_x(&square_finder.best_bounds);
|
||||
*r_max_v = BLI_rctf_size_y(&square_finder.best_bounds);
|
||||
return true; /* `r_phis` were modified. */
|
||||
}
|
||||
|
||||
/**
|
||||
* Pack irregular islands using the `xatlas` strategy, and optional D4 transforms.
|
||||
*
|
||||
|
@ -883,7 +1045,12 @@ static void pack_island_xatlas(const Span<UVAABBIsland *> island_indices,
|
|||
float max_u = 0.0f;
|
||||
float max_v = 0.0f;
|
||||
|
||||
int scan_line = 0;
|
||||
/* A heuristic to improve final layout efficiency by making an
|
||||
* intermediate call to #rotate_inside_square. */
|
||||
int64_t square_milestone = sqrt(island_indices.size()) / 4 + 2;
|
||||
|
||||
int scan_line = 0; /* Current "scan_line" of occupancy bitmap. */
|
||||
int traced_islands = 0; /* Which islands are currently traced in `occupancy`. */
|
||||
int i = 0;
|
||||
|
||||
/* The following `while` loop is setting up a three-way race:
|
||||
|
@ -893,10 +1060,21 @@ static void pack_island_xatlas(const Span<UVAABBIsland *> island_indices,
|
|||
*/
|
||||
|
||||
while (i < island_indices.size()) {
|
||||
|
||||
while (traced_islands < i) {
|
||||
/* Trace an island that's been solved. (Greedy.) */
|
||||
const int64_t island_index = island_indices[traced_islands]->index;
|
||||
occupancy.trace_island(islands[island_index], r_phis[island_index], scale, margin, true);
|
||||
traced_islands++;
|
||||
}
|
||||
|
||||
PackIsland *island = islands[island_indices[i]->index];
|
||||
uv_phi phi;
|
||||
|
||||
int max_90_multiple = params.rotate && (i < 50) ? 4 : 1;
|
||||
int max_90_multiple = 1;
|
||||
if (params.rotate && i && (i < 50)) {
|
||||
max_90_multiple = 4;
|
||||
}
|
||||
for (int angle_90_multiple = 0; angle_90_multiple < max_90_multiple; angle_90_multiple++) {
|
||||
phi = find_best_fit_for_island(
|
||||
island, scan_line, occupancy, scale, angle_90_multiple, margin, params.target_aspect_y);
|
||||
|
@ -929,19 +1107,29 @@ static void pack_island_xatlas(const Span<UVAABBIsland *> island_indices,
|
|||
/* Enlarge search parameters. */
|
||||
scan_line = 0;
|
||||
occupancy.increase_scale();
|
||||
|
||||
/* Redraw already placed islands. (Greedy.) */
|
||||
for (int j = 0; j < i; j++) {
|
||||
occupancy.trace_island(islands[island_indices[j]->index], r_phis[j], scale, margin, true);
|
||||
}
|
||||
traced_islands = 0; /* Will trigger a re-trace of previously solved islands. */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Place island. */
|
||||
r_phis[island_indices[i]->index] = phi;
|
||||
occupancy.trace_island(island, phi, scale, margin, true);
|
||||
i++; /* Next island. */
|
||||
|
||||
if (i == square_milestone) {
|
||||
if (rotate_inside_square(island_indices.take_front(i),
|
||||
islands,
|
||||
params,
|
||||
scale,
|
||||
margin,
|
||||
r_phis,
|
||||
&max_u,
|
||||
&max_v)) {
|
||||
scan_line = 0;
|
||||
traced_islands = 0;
|
||||
occupancy.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/* Update top-right corner. */
|
||||
float2 top_right = island->get_diagonal_support(scale, phi.rotation, margin) + phi.translation;
|
||||
max_u = std::max(top_right.x, max_u);
|
||||
|
@ -1083,6 +1271,8 @@ static float pack_islands_scale_margin(const Span<PackIsland *> islands,
|
|||
pack_islands_alpaca_turbo(max_box_pack, aabbs, params.target_aspect_y, r_phis, &max_u, &max_v);
|
||||
}
|
||||
|
||||
rotate_inside_square(aabbs, islands, params, scale, margin, r_phis, &max_u, &max_v);
|
||||
|
||||
return std::max(max_u / params.target_aspect_y, max_v);
|
||||
}
|
||||
|
||||
|
@ -1283,9 +1473,8 @@ class OverlapMerger {
|
|||
return result;
|
||||
}
|
||||
|
||||
static void pack_islands_overlap(const Span<PackIsland *> &islands,
|
||||
const UVPackIsland_Params ¶ms,
|
||||
float r_scale[2])
|
||||
static float pack_islands_overlap(const Span<PackIsland *> &islands,
|
||||
const UVPackIsland_Params ¶ms)
|
||||
{
|
||||
|
||||
/* Building the binary-tree of merges is complicated to do in a single pass if we proceed in
|
||||
|
@ -1316,7 +1505,7 @@ class OverlapMerger {
|
|||
/* Recursively call pack_islands with `merge_overlap = false`. */
|
||||
UVPackIsland_Params sub_params(params);
|
||||
sub_params.merge_overlap = false;
|
||||
pack_islands(sub_islands, sub_params, r_scale);
|
||||
const float result = pack_islands(sub_islands, sub_params);
|
||||
|
||||
/* Must loop backwards! */
|
||||
for (int64_t i = merge_trace.size() - 3; i >= 0; i -= 3) {
|
||||
|
@ -1331,6 +1520,8 @@ class OverlapMerger {
|
|||
sub_b->pre_rotate_ = merge->pre_rotate_;
|
||||
delete merge;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1347,31 +1538,25 @@ static void finalize_geometry(const Span<PackIsland *> &islands, const UVPackIsl
|
|||
BLI_memarena_free(arena);
|
||||
}
|
||||
|
||||
void pack_islands(const Span<PackIsland *> &islands,
|
||||
const UVPackIsland_Params ¶ms,
|
||||
float r_scale[2])
|
||||
float pack_islands(const Span<PackIsland *> &islands, const UVPackIsland_Params ¶ms)
|
||||
{
|
||||
BLI_assert(0.0f <= params.margin);
|
||||
BLI_assert(0.0f <= params.target_aspect_y);
|
||||
|
||||
if (islands.size() == 0) {
|
||||
r_scale[0] = 1.0f;
|
||||
r_scale[1] = 1.0f;
|
||||
return; /* Nothing to do, just create a safe default. */
|
||||
return 1.0f; /* Nothing to do, just create a safe default. */
|
||||
}
|
||||
|
||||
if (params.merge_overlap) {
|
||||
return OverlapMerger::pack_islands_overlap(islands, params, r_scale);
|
||||
return OverlapMerger::pack_islands_overlap(islands, params);
|
||||
}
|
||||
|
||||
finalize_geometry(islands, params);
|
||||
|
||||
if (params.margin_method == ED_UVPACK_MARGIN_FRACTION && params.margin > 0.0f) {
|
||||
if (params.margin_method == ED_UVPACK_MARGIN_FRACTION && params.margin > 0.0f &&
|
||||
params.scale_to_fit) {
|
||||
/* Uses a line search on scale. ~10x slower than other method. */
|
||||
const float scale = pack_islands_margin_fraction(islands, params.margin, params);
|
||||
r_scale[0] = scale;
|
||||
r_scale[1] = scale;
|
||||
return;
|
||||
return pack_islands_margin_fraction(islands, params.margin, params);
|
||||
}
|
||||
|
||||
float margin = params.margin;
|
||||
|
@ -1395,8 +1580,7 @@ void pack_islands(const Span<PackIsland *> &islands,
|
|||
for (const int64_t i : islands.index_range()) {
|
||||
islands[i]->place_(scale, phis[i]);
|
||||
}
|
||||
r_scale[0] = 1.0f / max_uv;
|
||||
r_scale[1] = r_scale[0];
|
||||
return params.scale_to_fit ? 1.0f / max_uv : 1.0f;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -4131,15 +4131,14 @@ void uv_parametrizer_pack(ParamHandle *handle, float margin, bool do_rotate, boo
|
|||
pack_island_vector.append(pack_island);
|
||||
}
|
||||
|
||||
float scale[2] = {1.0f, 1.0f};
|
||||
pack_islands(pack_island_vector, params, scale);
|
||||
const float scale = pack_islands(pack_island_vector, params);
|
||||
|
||||
for (const int64_t i : pack_island_vector.index_range()) {
|
||||
PackIsland *pack_island = pack_island_vector[i];
|
||||
PChart *chart = handle->charts[pack_island->caller_index];
|
||||
|
||||
float matrix[2][2];
|
||||
pack_island->build_transformation(scale[0], pack_island->angle, matrix);
|
||||
pack_island->build_transformation(scale, pack_island->angle, matrix);
|
||||
for (PVert *v = chart->verts; v; v = v->nextlink) {
|
||||
blender::geometry::mul_v2_m2_add_v2v2(v->uv, matrix, v->uv, pack_island->pre_translate);
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ void ensure_usd_plugin_path_registered()
|
|||
if (blender_usd_datafiles) {
|
||||
const std::string blender_usd_data_folder = blender_usd_datafiles;
|
||||
/* The trailing slash indicates to the USD library that the path is a directory. */
|
||||
pxr::PlugRegistry::GetInstance().RegisterPlugins(blender_usd_data_folder + "/");
|
||||
pxr::PlugRegistry::GetInstance().RegisterPlugins(blender_usd_data_folder + SEP_STR);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ class obj_mtl_parser_test : public testing::Test {
|
|||
BKE_tempdir_init(nullptr);
|
||||
std::string tmp_dir = BKE_tempdir_base();
|
||||
std::string tmp_file_name = "mtl_test.mtl";
|
||||
std::string tmp_file_path = tmp_dir + "/" + tmp_file_name;
|
||||
std::string tmp_file_path = tmp_dir + SEP_STR + tmp_file_name;
|
||||
FILE *tmp_file = BLI_fopen(tmp_file_path.c_str(), "wb");
|
||||
fputs(text, tmp_file);
|
||||
fclose(tmp_file);
|
||||
|
@ -29,7 +29,8 @@ class obj_mtl_parser_test : public testing::Test {
|
|||
}
|
||||
void check(const char *file, const MTLMaterial *expect, size_t expect_count)
|
||||
{
|
||||
std::string obj_dir = blender::tests::flags_test_asset_dir() + "/io_tests/obj/";
|
||||
std::string obj_dir = blender::tests::flags_test_asset_dir() +
|
||||
(SEP_STR "io_tests" SEP_STR "obj" SEP_STR);
|
||||
check_impl(file, obj_dir, expect, expect_count);
|
||||
}
|
||||
void check_impl(StringRefNull mtl_file_path,
|
||||
|
|
|
@ -15,25 +15,26 @@ NODE_STORAGE_FUNCS(NodeAccumulateField)
|
|||
|
||||
static void node_declare(NodeDeclarationBuilder &b)
|
||||
{
|
||||
std::string value_in_description = "The values to be accumulated";
|
||||
std::string leading_out_description =
|
||||
"The running total of values in the corresponding group, starting at the first value";
|
||||
std::string trailing_out_description =
|
||||
"The running total of values in the corresponding group, starting at zero";
|
||||
std::string total_out_description = "The total of all of the values in the corresponding group";
|
||||
std::string value_in_description = N_("The values to be accumulated");
|
||||
std::string leading_out_description = N_(
|
||||
"The running total of values in the corresponding group, starting at the first value");
|
||||
std::string trailing_out_description = N_(
|
||||
"The running total of values in the corresponding group, starting at zero");
|
||||
std::string total_out_description = N_(
|
||||
"The total of all of the values in the corresponding group");
|
||||
|
||||
b.add_input<decl::Vector>(N_("Value"), "Value Vector")
|
||||
.default_value({1.0f, 1.0f, 1.0f})
|
||||
.supports_field()
|
||||
.description(N_(value_in_description));
|
||||
.description(value_in_description);
|
||||
b.add_input<decl::Float>(N_("Value"), "Value Float")
|
||||
.default_value(1.0f)
|
||||
.supports_field()
|
||||
.description(N_(value_in_description));
|
||||
.description(value_in_description);
|
||||
b.add_input<decl::Int>(N_("Value"), "Value Int")
|
||||
.default_value(1)
|
||||
.supports_field()
|
||||
.description(N_(value_in_description));
|
||||
.description(value_in_description);
|
||||
b.add_input<decl::Int>(N_("Group ID"), "Group Index")
|
||||
.supports_field()
|
||||
.description(
|
||||
|
@ -41,33 +42,33 @@ static void node_declare(NodeDeclarationBuilder &b)
|
|||
|
||||
b.add_output<decl::Vector>(N_("Leading"), "Leading Vector")
|
||||
.field_source_reference_all()
|
||||
.description(N_(leading_out_description));
|
||||
.description(leading_out_description);
|
||||
b.add_output<decl::Float>(N_("Leading"), "Leading Float")
|
||||
.field_source_reference_all()
|
||||
.description(N_(leading_out_description));
|
||||
.description(leading_out_description);
|
||||
b.add_output<decl::Int>(N_("Leading"), "Leading Int")
|
||||
.field_source_reference_all()
|
||||
.description(N_(leading_out_description));
|
||||
.description(leading_out_description);
|
||||
|
||||
b.add_output<decl::Vector>(N_("Trailing"), "Trailing Vector")
|
||||
.field_source_reference_all()
|
||||
.description(N_(trailing_out_description));
|
||||
.description(trailing_out_description);
|
||||
b.add_output<decl::Float>(N_("Trailing"), "Trailing Float")
|
||||
.field_source_reference_all()
|
||||
.description(N_(trailing_out_description));
|
||||
.description(trailing_out_description);
|
||||
b.add_output<decl::Int>(N_("Trailing"), "Trailing Int")
|
||||
.field_source_reference_all()
|
||||
.description(N_(trailing_out_description));
|
||||
.description(trailing_out_description);
|
||||
|
||||
b.add_output<decl::Vector>(N_("Total"), "Total Vector")
|
||||
.field_source_reference_all()
|
||||
.description(N_(total_out_description));
|
||||
.description(total_out_description);
|
||||
b.add_output<decl::Float>(N_("Total"), "Total Float")
|
||||
.field_source_reference_all()
|
||||
.description(N_(total_out_description));
|
||||
.description(total_out_description);
|
||||
b.add_output<decl::Int>(N_("Total"), "Total Int")
|
||||
.field_source_reference_all()
|
||||
.description(N_(total_out_description));
|
||||
.description(total_out_description);
|
||||
}
|
||||
|
||||
static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
#include "UI_interface.h"
|
||||
#include "UI_resources.h"
|
||||
|
||||
#include "BLT_translation.h"
|
||||
|
||||
#include "node_geometry_util.hh"
|
||||
|
||||
namespace blender::nodes::node_geo_attribute_domain_size_cc {
|
||||
|
@ -10,22 +12,22 @@ namespace blender::nodes::node_geo_attribute_domain_size_cc {
|
|||
static void node_declare(NodeDeclarationBuilder &b)
|
||||
{
|
||||
b.add_input<decl::Geometry>("Geometry");
|
||||
b.add_output<decl::Int>("Point Count").make_available([](bNode &node) {
|
||||
b.add_output<decl::Int>(N_("Point Count")).make_available([](bNode &node) {
|
||||
node.custom1 = GEO_COMPONENT_TYPE_MESH;
|
||||
});
|
||||
b.add_output<decl::Int>("Edge Count").make_available([](bNode &node) {
|
||||
b.add_output<decl::Int>(N_("Edge Count")).make_available([](bNode &node) {
|
||||
node.custom1 = GEO_COMPONENT_TYPE_MESH;
|
||||
});
|
||||
b.add_output<decl::Int>("Face Count").make_available([](bNode &node) {
|
||||
b.add_output<decl::Int>(N_("Face Count")).make_available([](bNode &node) {
|
||||
node.custom1 = GEO_COMPONENT_TYPE_MESH;
|
||||
});
|
||||
b.add_output<decl::Int>("Face Corner Count").make_available([](bNode &node) {
|
||||
b.add_output<decl::Int>(N_("Face Corner Count")).make_available([](bNode &node) {
|
||||
node.custom1 = GEO_COMPONENT_TYPE_MESH;
|
||||
});
|
||||
b.add_output<decl::Int>("Spline Count").make_available([](bNode &node) {
|
||||
b.add_output<decl::Int>(N_("Spline Count")).make_available([](bNode &node) {
|
||||
node.custom1 = GEO_COMPONENT_TYPE_CURVE;
|
||||
});
|
||||
b.add_output<decl::Int>("Instance Count").make_available([](bNode &node) {
|
||||
b.add_output<decl::Int>(N_("Instance Count")).make_available([](bNode &node) {
|
||||
node.custom1 = GEO_COMPONENT_TYPE_INSTANCES;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -61,7 +61,7 @@ static void node_geo_exec(GeoNodeExecParams params)
|
|||
const bool is_recursive = BKE_collection_has_object_recursive_instanced(
|
||||
collection, const_cast<Object *>(self_object));
|
||||
if (is_recursive) {
|
||||
params.error_message_add(NodeWarningType::Error, "Collection contains current object");
|
||||
params.error_message_add(NodeWarningType::Error, TIP_("Collection contains current object"));
|
||||
params.set_default_remaining_outputs();
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -59,12 +59,15 @@ static void node_geo_exec(GeoNodeExecParams params)
|
|||
}
|
||||
|
||||
if (!attribute_exists) {
|
||||
params.error_message_add(NodeWarningType::Info,
|
||||
TIP_("Attribute does not exist: \"") + name + "\"");
|
||||
char *message = BLI_sprintfN(TIP_("Attribute does not exist: \"%s\""), name.c_str());
|
||||
params.error_message_add(NodeWarningType::Warning, message);
|
||||
MEM_freeN(message);
|
||||
}
|
||||
if (cannot_delete) {
|
||||
params.error_message_add(NodeWarningType::Warning,
|
||||
TIP_("Cannot delete built-in attribute with name \"") + name + "\"");
|
||||
char *message = BLI_sprintfN(TIP_("Cannot delete built-in attribute with name \"%s\""),
|
||||
name.c_str());
|
||||
params.error_message_add(NodeWarningType::Warning, message);
|
||||
MEM_freeN(message);
|
||||
}
|
||||
|
||||
params.set_output("Geometry", std::move(geometry_set));
|
||||
|
|
|
@ -168,7 +168,7 @@ static bool seq_proxy_get_fname(Scene *scene,
|
|||
BLI_strncpy(dir, seq->strip->proxy->dir, sizeof(dir));
|
||||
}
|
||||
else { /* Per strip default. */
|
||||
BLI_snprintf(dir, PROXY_MAXFILE, "%s/BL_proxy", seq->strip->dir);
|
||||
BLI_snprintf(dir, PROXY_MAXFILE, "%s" SEP_STR "BL_proxy", seq->strip->dir);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -380,6 +380,7 @@ void GIZMOGROUP_OT_gizmo_select(wmOperatorType *ot)
|
|||
|
||||
/* api callbacks */
|
||||
ot->invoke = gizmo_select_invoke;
|
||||
ot->poll = ED_operator_region_gizmo_active;
|
||||
|
||||
ot->flag = OPTYPE_UNDO;
|
||||
|
||||
|
@ -606,6 +607,7 @@ void GIZMOGROUP_OT_gizmo_tweak(wmOperatorType *ot)
|
|||
/* api callbacks */
|
||||
ot->invoke = gizmo_tweak_invoke;
|
||||
ot->modal = gizmo_tweak_modal;
|
||||
ot->poll = ED_operator_region_gizmo_active;
|
||||
|
||||
/* TODO(@ideasman42): This causes problems tweaking settings for operators,
|
||||
* need to find a way to support this. */
|
||||
|
|
|
@ -2079,11 +2079,18 @@ void WM_clipboard_text_set(const char *buf, bool selection)
|
|||
|
||||
bool WM_clipboard_image_available(void)
|
||||
{
|
||||
if (G.background) {
|
||||
return false;
|
||||
}
|
||||
return (bool)GHOST_hasClipboardImage();
|
||||
}
|
||||
|
||||
ImBuf *WM_clipboard_image_get(void)
|
||||
{
|
||||
if (G.background) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int width, height;
|
||||
|
||||
uint *rgba = GHOST_getClipboardImage(&width, &height);
|
||||
|
@ -2099,6 +2106,10 @@ ImBuf *WM_clipboard_image_get(void)
|
|||
|
||||
bool WM_clipboard_image_set(ImBuf *ibuf)
|
||||
{
|
||||
if (G.background) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool free_byte_buffer = false;
|
||||
if (ibuf->rect == NULL) {
|
||||
/* Add a byte buffer if it does not have one. */
|
||||
|
|
|
@ -42,6 +42,9 @@ op_blacklist = (
|
|||
"*.*_import",
|
||||
"ed.undo",
|
||||
"ed.undo_push",
|
||||
"image.external_edit", # just annoying - but harmless (opens an app).
|
||||
"image.project_edit", # just annoying - but harmless (opens an app).
|
||||
"object.quadriflow_remesh", # OK but slow.
|
||||
"preferences.studiolight_new",
|
||||
"script.autoexec_warn_clear",
|
||||
"screen.delete", # already used for random screens
|
||||
|
@ -75,6 +78,12 @@ op_blacklist = (
|
|||
"console.*", # just annoying - but harmless
|
||||
"wm.url_open_preset", # Annoying but harmless (opens web pages).
|
||||
|
||||
"render.cycles_integrator_preset_add",
|
||||
"render.cycles_performance_preset_add",
|
||||
"render.cycles_sampling_preset_add",
|
||||
"render.cycles_viewport_sampling_preset_add",
|
||||
"render.preset_add",
|
||||
|
||||
# FIXME:
|
||||
# Crashes with non-trivial fixes.
|
||||
#
|
||||
|
@ -245,29 +254,40 @@ if USE_ATTRSET:
|
|||
|
||||
|
||||
def run_ops(operators, setup_func=None, reset=True):
|
||||
from bpy import context
|
||||
print("\ncontext:", setup_func.__name__)
|
||||
|
||||
def temp_override_default_kwargs():
|
||||
return {
|
||||
"window": context.window_manager.windows[0],
|
||||
}
|
||||
|
||||
# first invoke
|
||||
for op_id, op in operators:
|
||||
if op.poll():
|
||||
print(" operator: %4d, %s" % (STATE["counter"], op_id))
|
||||
STATE["counter"] += 1
|
||||
sys.stdout.flush() # in case of crash
|
||||
with context.temp_override(window=context.window_manager.windows[0]):
|
||||
if not op.poll():
|
||||
continue
|
||||
|
||||
# disable will get blender in a bad state and crash easy!
|
||||
if reset:
|
||||
reset_test = True
|
||||
if USE_RANDOM:
|
||||
import random
|
||||
if random.random() < (1.0 - RANDOM_RESET):
|
||||
reset_test = False
|
||||
print(" operator: %4d, %s" % (STATE["counter"], op_id))
|
||||
STATE["counter"] += 1
|
||||
sys.stdout.flush() # in case of crash
|
||||
|
||||
if reset_test:
|
||||
if USE_FILES:
|
||||
reset_file()
|
||||
else:
|
||||
reset_blend()
|
||||
del reset_test
|
||||
# disable will get blender in a bad state and crash easy!
|
||||
if reset:
|
||||
reset_test = True
|
||||
if USE_RANDOM:
|
||||
import random
|
||||
if random.random() < (1.0 - RANDOM_RESET):
|
||||
reset_test = False
|
||||
|
||||
if reset_test:
|
||||
if USE_FILES:
|
||||
reset_file()
|
||||
else:
|
||||
reset_blend()
|
||||
del reset_test
|
||||
|
||||
with context.temp_override(**temp_override_default_kwargs()):
|
||||
|
||||
if USE_RANDOM:
|
||||
# we can't be sure it will work
|
||||
|
@ -293,14 +313,16 @@ def run_ops(operators, setup_func=None, reset=True):
|
|||
# run test
|
||||
if reset:
|
||||
reset_blend()
|
||||
if USE_RANDOM:
|
||||
# we can't be sure it will work
|
||||
try:
|
||||
|
||||
with context.temp_override(**temp_override_default_kwargs()):
|
||||
if USE_RANDOM:
|
||||
# we can't be sure it will work
|
||||
try:
|
||||
setup_func()
|
||||
except:
|
||||
pass
|
||||
else:
|
||||
setup_func()
|
||||
except:
|
||||
pass
|
||||
else:
|
||||
setup_func()
|
||||
|
||||
|
||||
# contexts
|
||||
|
|
Loading…
Reference in New Issue