1
1

Merge branch 'master' into temp-image-engine

This commit is contained in:
2022-12-07 15:04:39 +01:00
48 changed files with 771 additions and 2568 deletions

View File

@@ -1670,7 +1670,7 @@ class CyclesPreferences(bpy.types.AddonPreferences):
col.label(text="and Windows driver version 101.3430 or newer", icon='BLANK1')
elif sys.platform.startswith("linux"):
col.label(text="Requires Intel GPU with Xe-HPG architecture and", icon='BLANK1')
col.label(text=" - Linux driver version xx.xx.23904 or newer", icon='BLANK1')
col.label(text=" - intel-level-zero-gpu version 1.3.23904 or newer", icon='BLANK1')
col.label(text=" - oneAPI Level-Zero Loader", icon='BLANK1')
elif device_type == 'METAL':
col.label(text="Requires Apple Silicon with macOS 12.2 or newer", icon='BLANK1')

View File

@@ -410,10 +410,10 @@ class CYCLES_RENDER_PT_sampling_lights(CyclesButtonsPanel, Panel):
cscene = scene.cycles
col = layout.column(align=True)
#col.prop(cscene, "use_light_tree")
col.prop(cscene, "use_light_tree")
sub = col.row()
sub.prop(cscene, "light_sampling_threshold", text="Light Threshold")
#sub.active = not cscene.use_light_tree
sub.active = not cscene.use_light_tree
class CYCLES_RENDER_PT_subdivision(CyclesButtonsPanel, Panel):

View File

@@ -347,7 +347,7 @@ void BlenderSync::sync_integrator(BL::ViewLayer &b_view_layer, bool background)
integrator->set_motion_blur(view_layer.use_motion_blur);
}
bool use_light_tree = false; // get_boolean(cscene, "use_light_tree");
bool use_light_tree = get_boolean(cscene, "use_light_tree");
integrator->set_use_light_tree(use_light_tree);
integrator->set_light_sampling_threshold(
(use_light_tree) ? 0.0f : get_float(cscene, "light_sampling_threshold"));

View File

@@ -117,6 +117,8 @@ class MetalDevice : public Device {
/* ------------------------------------------------------------------ */
/* low-level memory management */
bool max_working_set_exceeded(size_t safety_margin = 8 * 1024 * 1024) const;
MetalMem *generic_alloc(device_memory &mem);
void generic_copy_to(device_memory &mem);

View File

@@ -446,6 +446,14 @@ void MetalDevice::erase_allocation(device_memory &mem)
}
}
bool MetalDevice::max_working_set_exceeded(size_t safety_margin) const
{
/* We're allowed to allocate beyond the safe working set size, but then if all resources are made
* resident we will get command buffer failures at render time. */
size_t available = [mtlDevice recommendedMaxWorkingSetSize] - safety_margin;
return (stats.mem_used > available);
}
MetalDevice::MetalMem *MetalDevice::generic_alloc(device_memory &mem)
{
size_t size = mem.memory_size();
@@ -523,6 +531,11 @@ MetalDevice::MetalMem *MetalDevice::generic_alloc(device_memory &mem)
mmem->use_UMA = false;
}
if (max_working_set_exceeded()) {
set_error("System is out of GPU memory");
return nullptr;
}
return mmem;
}
@@ -921,9 +934,8 @@ void MetalDevice::tex_alloc(device_texture &mem)
<< string_human_readable_size(mem.memory_size()) << ")";
mtlTexture = [mtlDevice newTextureWithDescriptor:desc];
assert(mtlTexture);
if (!mtlTexture) {
set_error("System is out of GPU memory");
return;
}
@@ -955,7 +967,10 @@ void MetalDevice::tex_alloc(device_texture &mem)
<< string_human_readable_size(mem.memory_size()) << ")";
mtlTexture = [mtlDevice newTextureWithDescriptor:desc];
assert(mtlTexture);
if (!mtlTexture) {
set_error("System is out of GPU memory");
return;
}
[mtlTexture replaceRegion:MTLRegionMake2D(0, 0, mem.data_width, mem.data_height)
mipmapLevel:0
@@ -1017,6 +1032,10 @@ void MetalDevice::tex_alloc(device_texture &mem)
need_texture_info = true;
texture_info[slot].data = uint64_t(slot) | (sampler_index << 32);
if (max_working_set_exceeded()) {
set_error("System is out of GPU memory");
}
}
void MetalDevice::tex_free(device_texture &mem)
@@ -1077,6 +1096,10 @@ void MetalDevice::build_bvh(BVH *bvh, Progress &progress, bool refit)
}
}
}
if (max_working_set_exceeded()) {
set_error("System is out of GPU memory");
}
}
CCL_NAMESPACE_END

View File

@@ -8,7 +8,10 @@
#include "kernel/light/distribution.h"
#include "kernel/light/light.h"
#include "kernel/light/tree.h"
#ifdef __LIGHT_TREE__
# include "kernel/light/tree.h"
#endif
#include "kernel/sample/mapping.h"
#include "kernel/sample/mis.h"
@@ -522,7 +525,7 @@ ccl_device_inline bool light_sample_new_position(KernelGlobals kg,
else
#endif
{
/* Handled in triangle_light_sample for effeciency. */
/* Handled in triangle_light_sample for efficiency. */
}
return true;
}

View File

@@ -796,11 +796,11 @@ ccl_device float bits_to_01(uint bits)
ccl_device_inline uint popcount(uint x)
{
/* TODO(Stefan): pop-count intrinsic for Windows with fallback for older CPUs. */
uint i = x & 0xaaaaaaaa;
uint i = x;
i = i - ((i >> 1) & 0x55555555);
i = (i & 0x33333333) + ((i >> 2) & 0x33333333);
i = (((i + (i >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24;
return i & 1;
return i;
}
# endif
#elif defined(__KERNEL_ONEAPI__)

View File

@@ -58,7 +58,7 @@ ccl_device_inline float4 madd4(const float4 a, const float4 b, const float4 c)
ccl_device_inline int fast_rint(float x)
{
/* used by sin/cos/tan range reduction. */
#ifdef __KERNEL_SSE4__
#ifdef __KERNEL_SSE41__
/* Single `roundps` instruction on SSE4.1+ (for gcc/clang at least). */
return float_to_int(rintf(x));
#else

View File

@@ -27,7 +27,13 @@ typedef enum {
} NDOF_DeviceT;
/* NDOF device button event types */
/**
* NDOF device button event types.
*
* \note Button values are stored in DNA as part of key-map items.
* Existing values should not be changed. Otherwise, a mapping must be used,
* see #NDOF_BUTTON_INDEX_AS_EVENT.
*/
typedef enum {
/* Used internally, never sent or used as an index. */
NDOF_BUTTON_NONE = -1,
@@ -58,6 +64,11 @@ typedef enum {
NDOF_BUTTON_DOMINANT,
NDOF_BUTTON_PLUS,
NDOF_BUTTON_MINUS,
/* Store Views. */
NDOF_BUTTON_V1,
NDOF_BUTTON_V2,
NDOF_BUTTON_V3,
_NDOF_UNUSED_0,
/* General-purpose buttons.
* Users can assign functions via keymap editor. */
NDOF_BUTTON_1,
@@ -74,11 +85,8 @@ typedef enum {
NDOF_BUTTON_A,
NDOF_BUTTON_B,
NDOF_BUTTON_C,
/* Store Views. */
NDOF_BUTTON_V1,
NDOF_BUTTON_V2,
NDOF_BUTTON_V3,
/* Keyboard emulation. */
/* Keyboard emulation (keep last as they are mapped to regular keyboard events). */
NDOF_BUTTON_ESC,
NDOF_BUTTON_ENTER,
NDOF_BUTTON_DELETE,

View File

@@ -40,6 +40,25 @@
</screenshot>
</screenshots>
<releases>
<release version="3.4" date="2022-12-07">
<description>
<p>New features:</p>
<ul>
<li>Cycles Path Guiding</li>
<li>Sculpt geometry-based relax brush</li>
<li>Viewport overlay for Geometry Nodes Viewer Node</li>
<li>EEVEE headless rendering support on Linux</li>
</ul>
<p>Enhancements:</p>
<ul>
<li>Many new Geometry Nodes for meshes, curves and more</li>
<li>NLA editor usability improvements</li>
<li>FFmpeg AV1 codec encoding</li>
<li>Improved font thumbnails</li>
<li>Blender as a Python Module</li>
</ul>
</description>
</release>
<release version="3.3" date="2022-09-07">
<description>
<p>New features:</p>

View File

@@ -154,97 +154,14 @@ class DATA_PT_bone_groups(ArmatureButtonsPanel, Panel):
sub.operator("pose.group_deselect", text="Deselect")
class DATA_PT_pose_library(ArmatureButtonsPanel, Panel):
bl_label = "Pose Library (Legacy)"
bl_options = {'DEFAULT_CLOSED'}
@classmethod
def poll(cls, context):
return (context.object and context.object.type == 'ARMATURE' and context.object.pose)
@staticmethod
def get_manual_url():
url_fmt = "https://docs.blender.org/manual/en/%d.%d/animation/armatures/posing/editing/pose_library.html"
return url_fmt % bpy.app.version[:2]
def draw(self, context):
layout = self.layout
col = layout.column(align=True)
col.label(text="This panel is a remainder of the old pose library,")
col.label(text="which was replaced by the Asset Browser")
url = self.get_manual_url()
col.operator("wm.url_open", text="More Info", icon='URL').url = url
layout.separator()
ob = context.object
poselib = ob.pose_library
col = layout.column(align=True)
col.template_ID(ob, "pose_library", new="poselib.new", unlink="poselib.unlink")
if poselib:
if hasattr(bpy.types, "POSELIB_OT_convert_old_object_poselib"):
col.operator("poselib.convert_old_object_poselib",
text="Convert to Pose Assets", icon='ASSET_MANAGER')
else:
col.label(text="Enable the Pose Library add-on to convert", icon='ERROR')
col.label(text="this legacy pose library to pose assets", icon='BLANK1')
# Put the deprecated stuff in its own sub-layout.
dep_layout = layout.column()
dep_layout.active = False
# warning about poselib being in an invalid state
if poselib.fcurves and not poselib.pose_markers:
dep_layout.label(
icon='ERROR',
text="Error: Potentially corrupt library, run 'Sanitize' operator to fix",
)
# list of poses in pose library
row = dep_layout.row()
row.template_list("UI_UL_list", "pose_markers", poselib, "pose_markers",
poselib.pose_markers, "active_index", rows=3)
# column of operators for active pose
# - goes beside list
col = row.column(align=True)
# invoke should still be used for 'add', as it is needed to allow
# add/replace options to be used properly
col.operator("poselib.pose_add", icon='ADD', text="")
col.operator_context = 'EXEC_DEFAULT' # exec not invoke, so that menu doesn't need showing
pose_marker_active = poselib.pose_markers.active
if pose_marker_active is not None:
col.operator("poselib.pose_remove", icon='REMOVE', text="")
col.operator(
"poselib.apply_pose",
icon='ZOOM_SELECTED',
text="",
).pose_index = poselib.pose_markers.active_index
col.operator("poselib.action_sanitize", icon='HELP', text="") # XXX: put in menu?
if pose_marker_active is not None:
col.operator("poselib.pose_move", icon='TRIA_UP', text="").direction = 'UP'
col.operator("poselib.pose_move", icon='TRIA_DOWN', text="").direction = 'DOWN'
class DATA_PT_iksolver_itasc(ArmatureButtonsPanel, Panel):
bl_label = "Inverse Kinematics"
bl_options = {'DEFAULT_CLOSED'}
bl_options = {"DEFAULT_CLOSED"}
@classmethod
def poll(cls, context):
ob = context.object
return (ob and ob.pose)
return ob and ob.pose
def draw(self, context):
layout = self.layout
@@ -341,7 +258,6 @@ classes = (
DATA_PT_skeleton,
DATA_MT_bone_group_context_menu,
DATA_PT_bone_groups,
DATA_PT_pose_library,
DATA_PT_motion_paths,
DATA_PT_motion_paths_display,
DATA_PT_display,

View File

@@ -88,8 +88,16 @@ class CURVES_UL_attributes(UIList):
flags = []
indices = [i for i in range(len(attributes))]
for item in attributes:
flags.append(0 if item.is_internal else self.bitflag_filter_item)
# Filtering by name
if self.filter_name:
flags = bpy.types.UI_UL_list.filter_items_by_name(
self.filter_name, self.bitflag_filter_item, attributes, "name", reverse=self.use_filter_invert)
if not flags:
flags = [self.bitflag_filter_item] * len(attributes)
# Filtering internal attributes
for idx, item in enumerate(attributes):
flags[idx] = 0 if item.is_internal else flags[idx]
return flags, indices

View File

@@ -537,8 +537,16 @@ class MESH_UL_attributes(UIList):
flags = []
indices = [i for i in range(len(attributes))]
for item in attributes:
flags.append(0 if item.is_internal else self.bitflag_filter_item)
# Filtering by name
if self.filter_name:
flags = bpy.types.UI_UL_list.filter_items_by_name(
self.filter_name, self.bitflag_filter_item, attributes, "name", reverse=self.use_filter_invert)
if not flags:
flags = [self.bitflag_filter_item] * len(attributes)
# Filtering internal attributes
for idx, item in enumerate(attributes):
flags[idx] = 0 if item.is_internal else flags[idx]
return flags, indices
@@ -626,20 +634,26 @@ class ColorAttributesListBase():
}
def filter_items(self, _context, data, property):
attrs = getattr(data, property)
ret = []
idxs = []
attributes = getattr(data, property)
flags = []
indices = [i for i in range(len(attributes))]
for idx, item in enumerate(attrs):
# Filtering by name
if self.filter_name:
flags = bpy.types.UI_UL_list.filter_items_by_name(
self.filter_name, self.bitflag_filter_item, attributes, "name", reverse=self.use_filter_invert)
if not flags:
flags = [self.bitflag_filter_item] * len(attributes)
for idx, item in enumerate(attributes):
skip = (
(item.domain not in {"POINT", "CORNER"}) or
(item.data_type not in {"FLOAT_COLOR", "BYTE_COLOR"}) or
item.is_internal
)
ret.append(0 if skip else self.bitflag_filter_item)
idxs.append(idx)
flags[idx] = 0 if skip else flags[idx]
return ret, idxs
return flags, indices
class MESH_UL_color_attributes(UIList, ColorAttributesListBase):

View File

@@ -70,8 +70,16 @@ class POINTCLOUD_UL_attributes(UIList):
flags = []
indices = [i for i in range(len(attributes))]
for item in attributes:
flags.append(0 if item.is_internal else self.bitflag_filter_item)
# Filtering by name
if self.filter_name:
flags = bpy.types.UI_UL_list.filter_items_by_name(
self.filter_name, self.bitflag_filter_item, attributes, "name", reverse=self.use_filter_invert)
if not flags:
flags = [self.bitflag_filter_item] * len(attributes)
# Filtering internal attributes
for idx, item in enumerate(attributes):
flags[idx] = 0 if item.is_internal else flags[idx]
return flags, indices

View File

@@ -851,6 +851,8 @@ static void object_blend_read_lib(BlendLibReader *reader, ID *id)
BLO_read_id_address(reader, ob->id.lib, &ob->parent);
BLO_read_id_address(reader, ob->id.lib, &ob->track);
/* XXX deprecated - old pose library, deprecated in Blender 3.5. */
BLO_read_id_address(reader, ob->id.lib, &ob->poselib);
/* 2.8x drops support for non-empty dupli instances. */

View File

@@ -289,7 +289,11 @@ static void curves_batch_cache_ensure_data_edit_points(const Curves &curves_id,
const bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id.geometry);
static GPUVertFormat format_data = {0};
uint data = GPU_vertformat_attr_add(&format_data, "data", GPU_COMP_U8, 1, GPU_FETCH_INT);
static uint data;
if (format_data.attr_len == 0) {
data = GPU_vertformat_attr_add(&format_data, "data", GPU_COMP_U8, 1, GPU_FETCH_INT);
}
GPU_vertbuf_init_with_format(cache.data_edit_points, &format_data);
GPU_vertbuf_data_alloc(cache.data_edit_points, curves.points_num());

View File

@@ -21,6 +21,7 @@ namespace blender::editor::animation::tests {
const float KEYLIST_NEAR_ERROR = 0.1;
const float FRAME_STEP = 0.005;
/* Build FCurve with keys on frames 10, 20, and 30. */
static void build_fcurve(FCurve &fcurve)
{
fcurve.totvert = 3;
@@ -51,92 +52,88 @@ static void assert_act_key_column(const ActKeyColumn *column,
const std::optional<float> expected_frame)
{
if (expected_frame.has_value()) {
EXPECT_NE(column, nullptr);
ASSERT_NE(column, nullptr) << "Expected a frame to be found at " << *expected_frame;
EXPECT_NEAR(column->cfra, *expected_frame, KEYLIST_NEAR_ERROR);
}
else {
EXPECT_EQ(column, nullptr);
EXPECT_EQ(column, nullptr) << "Expected no frame to be found, but found " << column->cfra;
}
}
using KeylistFindFunction = std::function<const ActKeyColumn *(const AnimKeylist *, float)>;
static float check_keylist_find_range(const AnimKeylist *keylist,
KeylistFindFunction keylist_find_func,
const float frame_from,
const float frame_to,
const std::optional<float> expected_frame)
static void check_keylist_find_range(const AnimKeylist *keylist,
KeylistFindFunction keylist_find_func,
const float frame_from,
const float frame_to,
const std::optional<float> expected_frame)
{
float cfra = frame_from;
for (; cfra < frame_to; cfra += FRAME_STEP) {
const ActKeyColumn *found = keylist_find_func(keylist, cfra);
assert_act_key_column(found, expected_frame);
}
return cfra;
}
static float check_keylist_find_next_range(const AnimKeylist *keylist,
const float frame_from,
const float frame_to,
const std::optional<float> expected_frame)
static void check_keylist_find_next_range(const AnimKeylist *keylist,
const float frame_from,
const float frame_to,
const std::optional<float> expected_frame)
{
return check_keylist_find_range(
keylist, ED_keylist_find_next, frame_from, frame_to, expected_frame);
check_keylist_find_range(keylist, ED_keylist_find_next, frame_from, frame_to, expected_frame);
}
TEST(keylist, find_next)
{
AnimKeylist *keylist = create_test_keylist();
float cfra = check_keylist_find_next_range(keylist, 0.0f, 9.99f, 10.0f);
cfra = check_keylist_find_next_range(keylist, cfra, 19.99f, 20.0f);
cfra = check_keylist_find_next_range(keylist, cfra, 29.99f, 30.0f);
cfra = check_keylist_find_next_range(keylist, cfra, 39.99f, std::nullopt);
check_keylist_find_next_range(keylist, 0.0f, 9.99f, 10.0f);
check_keylist_find_next_range(keylist, 10.0f, 19.99f, 20.0f);
check_keylist_find_next_range(keylist, 20.0f, 29.99f, 30.0f);
check_keylist_find_next_range(keylist, 30.0f, 39.99f, std::nullopt);
ED_keylist_free(keylist);
}
static float check_keylist_find_prev_range(const AnimKeylist *keylist,
const float frame_from,
const float frame_to,
const std::optional<float> expected_frame)
static void check_keylist_find_prev_range(const AnimKeylist *keylist,
const float frame_from,
const float frame_to,
const std::optional<float> expected_frame)
{
return check_keylist_find_range(
keylist, ED_keylist_find_prev, frame_from, frame_to, expected_frame);
check_keylist_find_range(keylist, ED_keylist_find_prev, frame_from, frame_to, expected_frame);
}
TEST(keylist, find_prev)
{
AnimKeylist *keylist = create_test_keylist();
float cfra = check_keylist_find_prev_range(keylist, 0.0f, 10.01f, std::nullopt);
cfra = check_keylist_find_prev_range(keylist, cfra, 20.01f, 10.0f);
cfra = check_keylist_find_prev_range(keylist, cfra, 30.01f, 20.0f);
cfra = check_keylist_find_prev_range(keylist, cfra, 49.99f, 30.0f);
check_keylist_find_prev_range(keylist, 0.0f, 10.00f, std::nullopt);
check_keylist_find_prev_range(keylist, 10.01f, 20.00f, 10.0f);
check_keylist_find_prev_range(keylist, 20.01f, 30.00f, 20.0f);
check_keylist_find_prev_range(keylist, 30.01f, 49.99f, 30.0f);
ED_keylist_free(keylist);
}
static float check_keylist_find_exact_range(const AnimKeylist *keylist,
const float frame_from,
const float frame_to,
const std::optional<float> expected_frame)
static void check_keylist_find_exact_range(const AnimKeylist *keylist,
const float frame_from,
const float frame_to,
const std::optional<float> expected_frame)
{
return check_keylist_find_range(
keylist, ED_keylist_find_exact, frame_from, frame_to, expected_frame);
check_keylist_find_range(keylist, ED_keylist_find_exact, frame_from, frame_to, expected_frame);
}
TEST(keylist, find_exact)
{
AnimKeylist *keylist = create_test_keylist();
float cfra = check_keylist_find_exact_range(keylist, 0.0f, 9.99f, std::nullopt);
cfra = check_keylist_find_exact_range(keylist, cfra, 10.01f, 10.0f);
cfra = check_keylist_find_exact_range(keylist, cfra, 19.99f, std::nullopt);
cfra = check_keylist_find_exact_range(keylist, cfra, 20.01f, 20.0f);
cfra = check_keylist_find_exact_range(keylist, cfra, 29.99f, std::nullopt);
cfra = check_keylist_find_exact_range(keylist, cfra, 30.01f, 30.0f);
cfra = check_keylist_find_exact_range(keylist, cfra, 49.99f, std::nullopt);
check_keylist_find_exact_range(keylist, 0.0f, 9.99f, std::nullopt);
check_keylist_find_exact_range(keylist, 9.9901f, 10.01f, 10.0f);
check_keylist_find_exact_range(keylist, 10.01f, 19.99f, std::nullopt);
check_keylist_find_exact_range(keylist, 19.9901f, 20.01f, 20.0f);
check_keylist_find_exact_range(keylist, 20.01f, 29.99f, std::nullopt);
check_keylist_find_exact_range(keylist, 29.9901f, 30.01f, 30.0f);
check_keylist_find_exact_range(keylist, 30.01f, 49.99f, std::nullopt);
ED_keylist_free(keylist);
}

View File

@@ -33,7 +33,6 @@ set(SRC
pose_backup.cc
pose_edit.c
pose_group.c
pose_lib.c
pose_lib_2.c
pose_select.c
pose_slide.c

View File

@@ -201,21 +201,6 @@ LinkData *poseAnim_mapping_getNextFCurve(ListBase *fcuLinks, LinkData *prev, con
/** \name PoseLib
* \{ */
/* pose_lib.c */
void POSELIB_OT_new(struct wmOperatorType *ot);
void POSELIB_OT_unlink(struct wmOperatorType *ot);
void POSELIB_OT_action_sanitize(struct wmOperatorType *ot);
void POSELIB_OT_pose_add(struct wmOperatorType *ot);
void POSELIB_OT_pose_remove(struct wmOperatorType *ot);
void POSELIB_OT_pose_rename(struct wmOperatorType *ot);
void POSELIB_OT_pose_move(struct wmOperatorType *ot);
void POSELIB_OT_browse_interactive(struct wmOperatorType *ot);
void POSELIB_OT_apply_pose(struct wmOperatorType *ot);
/* pose_lib_2.c */
void POSELIB_OT_apply_pose_asset(struct wmOperatorType *ot);

View File

@@ -114,21 +114,9 @@ void ED_operatortypes_armature(void)
WM_operatortype_append(POSE_OT_propagate);
/* POSELIB */
WM_operatortype_append(POSELIB_OT_browse_interactive);
WM_operatortype_append(POSELIB_OT_apply_pose);
WM_operatortype_append(POSELIB_OT_apply_pose_asset);
WM_operatortype_append(POSELIB_OT_blend_pose_asset);
WM_operatortype_append(POSELIB_OT_pose_add);
WM_operatortype_append(POSELIB_OT_pose_remove);
WM_operatortype_append(POSELIB_OT_pose_rename);
WM_operatortype_append(POSELIB_OT_pose_move);
WM_operatortype_append(POSELIB_OT_new);
WM_operatortype_append(POSELIB_OT_unlink);
WM_operatortype_append(POSELIB_OT_action_sanitize);
/* POSE SLIDING */
WM_operatortype_append(POSE_OT_push);
WM_operatortype_append(POSE_OT_relax);

File diff suppressed because it is too large Load Diff

View File

@@ -332,12 +332,7 @@ struct UVMapUDIM_Params {
const struct Image *image;
/** Copied from #SpaceImage.tile_grid_shape */
int grid_shape[2];
bool use_target_udim;
int target_udim;
};
bool ED_uvedit_udim_params_from_image_space(const struct SpaceImage *sima,
bool use_active,
struct UVMapUDIM_Params *udim_params);
typedef enum {
ED_UVPACK_MARGIN_SCALED = 0, /* Use scale of existing UVs to multiply margin. */
@@ -356,6 +351,7 @@ struct UVPackIsland_Params {
bool pin_unselected; /* Treat unselected UVs as if they were pinned. */
eUVPackIsland_MarginMethod margin_method; /* Which formula to use when scaling island margin. */
float margin; /* Additional space to add around each island. */
float udim_base_offset[2]; /* Additional translation for bottom left corner. */
};
/**
@@ -382,7 +378,7 @@ void ED_uvedit_pack_islands_multi(const struct Scene *scene,
Object **objects,
uint objects_len,
struct BMesh **bmesh_override,
const struct UVMapUDIM_Params *udim_params,
const struct UVMapUDIM_Params *closest_udim,
const struct UVPackIsland_Params *params);
#ifdef __cplusplus

View File

@@ -910,13 +910,15 @@ static int sculpt_mask_by_color_invoke(bContext *C, wmOperator *op, const wmEven
v3d->shading.color_type = V3D_SHADING_VERTEX_COLOR;
}
BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true, false);
/* Color data is not available in multi-resolution or dynamic topology. */
if (!SCULPT_handles_colors_report(ss, op->reports)) {
return OPERATOR_CANCELLED;
}
MultiresModifierData *mmd = BKE_sculpt_multires_active(CTX_data_scene(C), ob);
BKE_sculpt_mask_layers_ensure(depsgraph, CTX_data_main(C), ob, mmd);
BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true, false);
SCULPT_vertex_random_access_ensure(ss);
/* Tools that are not brushes do not have the brush gizmo to update the vertex as the mouse move,

View File

@@ -667,35 +667,47 @@ static int image_view_zoom_modal(bContext *C, wmOperator *op, const wmEvent *eve
{
ViewZoomData *vpd = op->customdata;
short event_code = VIEW_PASS;
int ret = OPERATOR_RUNNING_MODAL;
/* execute the events */
if (event->type == TIMER && event->customdata == vpd->timer) {
/* continuous zoom */
/* Execute the events. */
if (event->type == MOUSEMOVE) {
event_code = VIEW_APPLY;
}
else if (event->type == MOUSEMOVE) {
event_code = VIEW_APPLY;
else if (event->type == TIMER) {
/* Continuous zoom. */
if (event->customdata == vpd->timer) {
event_code = VIEW_APPLY;
}
}
else if (event->type == vpd->launch_event && event->val == KM_RELEASE) {
event_code = VIEW_CONFIRM;
else if (event->type == vpd->launch_event) {
if (event->val == KM_RELEASE) {
event_code = VIEW_CONFIRM;
}
}
if (event_code == VIEW_APPLY) {
const bool use_cursor_init = RNA_boolean_get(op->ptr, "use_cursor_init");
image_zoom_apply(vpd,
op,
event->xy[0],
event->xy[1],
U.viewzoom,
(U.uiflag & USER_ZOOM_INVERT) != 0,
(use_cursor_init && (U.uiflag & USER_ZOOM_TO_MOUSEPOS)));
switch (event_code) {
case VIEW_APPLY: {
const bool use_cursor_init = RNA_boolean_get(op->ptr, "use_cursor_init");
image_zoom_apply(vpd,
op,
event->xy[0],
event->xy[1],
U.viewzoom,
(U.uiflag & USER_ZOOM_INVERT) != 0,
(use_cursor_init && (U.uiflag & USER_ZOOM_TO_MOUSEPOS)));
break;
}
case VIEW_CONFIRM: {
ret = OPERATOR_FINISHED;
break;
}
}
else if (event_code == VIEW_CONFIRM) {
if ((ret & OPERATOR_RUNNING_MODAL) == 0) {
image_view_zoom_exit(C, op, false);
return OPERATOR_FINISHED;
}
return OPERATOR_RUNNING_MODAL;
return ret;
}
static void image_view_zoom_cancel(bContext *C, wmOperator *op)

View File

@@ -278,9 +278,6 @@ static void outliner_add_object_contents(SpaceOutliner *space_outliner,
outliner_add_element(space_outliner, &te->subtree, ob, te, TSE_ANIM_DATA, 0);
}
/* FIXME: add a special type for this. */
outliner_add_element(space_outliner, &te->subtree, ob->poselib, te, TSE_SOME_ID, 0);
outliner_add_element(space_outliner, &te->subtree, ob->data, te, TSE_SOME_ID, 0);
if (ob->pose) {

View File

@@ -298,6 +298,7 @@ ViewOpsData *viewops_data_create(bContext *C, const wmEvent *event, enum eViewOp
else {
vod->use_dyn_ofs = false;
}
vod->init.persp = rv3d->persp;
if (viewops_flag & VIEWOPS_FLAG_PERSP_ENSURE) {
if (ED_view3d_persp_ensure(depsgraph, vod->v3d, vod->region)) {
@@ -311,7 +312,9 @@ ViewOpsData *viewops_data_create(bContext *C, const wmEvent *event, enum eViewOp
* we may want to make this optional but for now its needed always */
ED_view3d_camera_lock_init(depsgraph, vod->v3d, vod->rv3d);
vod->init.persp = rv3d->persp;
vod->init.persp_with_auto_persp_applied = rv3d->persp;
vod->init.view = rv3d->view;
vod->init.view_axis_roll = rv3d->view_axis_roll;
vod->init.dist = rv3d->dist;
vod->init.camzoom = rv3d->camzoom;
copy_qt_qt(vod->init.quat, rv3d->viewquat);
@@ -332,6 +335,10 @@ ViewOpsData *viewops_data_create(bContext *C, const wmEvent *event, enum eViewOp
copy_qt_qt(vod->curr.viewquat, rv3d->viewquat);
copy_v3_v3(vod->init.ofs_lock, rv3d->ofs_lock);
vod->init.camdx = rv3d->camdx;
vod->init.camdy = rv3d->camdy;
if (viewops_flag & VIEWOPS_FLAG_ORBIT_SELECT) {
float ofs[3];
if (view3d_orbit_calc_center(C, ofs) || (vod->use_dyn_ofs == false)) {
@@ -585,6 +592,23 @@ void viewmove_apply(ViewOpsData *vod, int x, int y)
ED_region_tag_redraw(vod->region);
}
void viewmove_apply_reset(ViewOpsData *vod)
{
if ((vod->rv3d->persp == RV3D_CAMOB) && !ED_view3d_camera_lock_check(vod->v3d, vod->rv3d)) {
vod->rv3d->camdx = vod->init.camdx;
vod->rv3d->camdy = vod->init.camdy;
}
else if (ED_view3d_offset_lock_check(vod->v3d, vod->rv3d)) {
copy_v2_v2(vod->rv3d->ofs_lock, vod->init.ofs_lock);
}
else {
copy_v3_v3(vod->rv3d->ofs, vod->init.ofs);
if (RV3D_LOCK_FLAGS(vod->rv3d) & RV3D_BOXVIEW) {
view3d_boxview_sync(vod->area, vod->region);
}
}
}
/** \} */
/* -------------------------------------------------------------------- */

View File

@@ -41,6 +41,8 @@ enum {
VIEW_PASS = 0,
VIEW_APPLY,
VIEW_CONFIRM,
/** Only supported by some viewport operators. */
VIEW_CANCEL,
};
/* NOTE: these defines are saved in keymap files, do not change values but just add new ones */
@@ -95,9 +97,14 @@ typedef struct ViewOpsData {
/** #wmEvent.type that triggered the operator. */
int event_type;
float ofs[3];
/** #RegionView3D.ofs_lock */
float ofs_lock[2];
/** Initial distance to 'ofs'. */
float zfac;
/** Camera offset. */
float camdx, camdy;
/** Trackball rotation only. */
float trackvec[3];
/** Dolly only. */
@@ -107,7 +114,13 @@ typedef struct ViewOpsData {
* #RegionView3D.persp set after auto-perspective is applied.
* If we want the value before running the operator, add a separate member.
*/
char persp_with_auto_persp_applied;
/** #RegionView3D.persp set after before auto-perspective is applied. */
char persp;
/** #RegionView3D.view */
char view;
/** #RegionView3D.view_axis_roll */
char view_axis_roll;
/** Used for roll */
struct Dial *dial;
@@ -145,6 +158,7 @@ bool view3d_zoom_or_dolly_poll(struct bContext *C);
enum eViewOpsFlag viewops_flag_from_prefs(void);
void calctrackballvec(const struct rcti *rect, const int event_xy[2], float r_dir[3]);
void viewmove_apply(ViewOpsData *vod, int x, int y);
void viewmove_apply_reset(ViewOpsData *vod);
void view3d_orbit_apply_dyn_ofs(float r_ofs[3],
const float ofs_old[3],
const float viewquat_old[4],

View File

@@ -142,11 +142,8 @@ static int viewdolly_modal(bContext *C, wmOperator *op, const wmEvent *event)
bool use_autokey = false;
int ret = OPERATOR_RUNNING_MODAL;
/* execute the events */
if (event->type == MOUSEMOVE) {
event_code = VIEW_APPLY;
}
else if (event->type == EVT_MODAL_MAP) {
/* Execute the events. */
if (event->type == EVT_MODAL_MAP) {
switch (event->val) {
case VIEW_MODAL_CONFIRM:
event_code = VIEW_CONFIRM;
@@ -161,27 +158,52 @@ static int viewdolly_modal(bContext *C, wmOperator *op, const wmEvent *event)
break;
}
}
else if (event->type == vod->init.event_type && event->val == KM_RELEASE) {
event_code = VIEW_CONFIRM;
}
if (event_code == VIEW_APPLY) {
viewdolly_apply(vod, event->xy, (U.uiflag & USER_ZOOM_INVERT) != 0);
if (ED_screen_animation_playing(CTX_wm_manager(C))) {
use_autokey = true;
else {
if (event->type == MOUSEMOVE) {
event_code = VIEW_APPLY;
}
else if (event->type == vod->init.event_type) {
if (event->val == KM_RELEASE) {
event_code = VIEW_CONFIRM;
}
}
else if (ELEM(event->type, EVT_ESCKEY, RIGHTMOUSE)) {
if (event->val == KM_PRESS) {
event_code = VIEW_CANCEL;
}
}
}
else if (event_code == VIEW_CONFIRM) {
use_autokey = true;
ret = OPERATOR_FINISHED;
switch (event_code) {
case VIEW_APPLY: {
viewdolly_apply(vod, event->xy, (U.uiflag & USER_ZOOM_INVERT) != 0);
if (ED_screen_animation_playing(CTX_wm_manager(C))) {
use_autokey = true;
}
break;
}
case VIEW_CONFIRM: {
use_autokey = true;
ret = OPERATOR_FINISHED;
break;
}
case VIEW_CANCEL: {
/* Note this does not remove auto-keys on locked cameras. */
copy_v3_v3(vod->rv3d->ofs, vod->init.ofs);
ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d);
ret = OPERATOR_CANCELLED;
break;
}
}
if (use_autokey) {
ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, false, true);
}
if (ret & OPERATOR_FINISHED) {
ED_view3d_camera_lock_undo_push(op->type->name, vod->v3d, vod->rv3d, C);
if ((ret & OPERATOR_RUNNING_MODAL) == 0) {
if (ret & OPERATOR_FINISHED) {
ED_view3d_camera_lock_undo_push(op->type->name, vod->v3d, vod->rv3d, C);
}
viewops_data_free(C, vod);
op->customdata = NULL;
}

View File

@@ -4,6 +4,8 @@
* \ingroup spview3d
*/
#include "BLI_math_vector.h"
#include "BKE_context.h"
#include "WM_api.h"
@@ -101,11 +103,8 @@ static int viewmove_modal(bContext *C, wmOperator *op, const wmEvent *event)
bool use_autokey = false;
int ret = OPERATOR_RUNNING_MODAL;
/* execute the events */
if (event->type == MOUSEMOVE) {
event_code = VIEW_APPLY;
}
else if (event->type == EVT_MODAL_MAP) {
/* Execute the events. */
if (event->type == EVT_MODAL_MAP) {
switch (event->val) {
case VIEW_MODAL_CONFIRM:
event_code = VIEW_CONFIRM;
@@ -120,27 +119,51 @@ static int viewmove_modal(bContext *C, wmOperator *op, const wmEvent *event)
break;
}
}
else if (event->type == vod->init.event_type && event->val == KM_RELEASE) {
event_code = VIEW_CONFIRM;
}
if (event_code == VIEW_APPLY) {
viewmove_apply(vod, event->xy[0], event->xy[1]);
if (ED_screen_animation_playing(CTX_wm_manager(C))) {
use_autokey = true;
else {
if (event->type == MOUSEMOVE) {
event_code = VIEW_APPLY;
}
else if (event->type == vod->init.event_type) {
if (event->val == KM_RELEASE) {
event_code = VIEW_CONFIRM;
}
}
else if (ELEM(event->type, EVT_ESCKEY, RIGHTMOUSE)) {
if (event->val == KM_PRESS) {
event_code = VIEW_CANCEL;
}
}
}
else if (event_code == VIEW_CONFIRM) {
use_autokey = true;
ret = OPERATOR_FINISHED;
switch (event_code) {
case VIEW_APPLY: {
viewmove_apply(vod, event->xy[0], event->xy[1]);
if (ED_screen_animation_playing(CTX_wm_manager(C))) {
use_autokey = true;
}
break;
}
case VIEW_CONFIRM: {
use_autokey = true;
ret = OPERATOR_FINISHED;
break;
}
case VIEW_CANCEL: {
viewmove_apply_reset(vod);
ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d);
ret = OPERATOR_CANCELLED;
break;
}
}
if (use_autokey) {
ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, false, true);
}
if (ret & OPERATOR_FINISHED) {
ED_view3d_camera_lock_undo_push(op->type->name, vod->v3d, vod->rv3d, C);
if ((ret & OPERATOR_RUNNING_MODAL) == 0) {
if (ret & OPERATOR_FINISHED) {
ED_view3d_camera_lock_undo_push(op->type->name, vod->v3d, vod->rv3d, C);
}
viewops_data_free(C, op->customdata);
op->customdata = NULL;
}

View File

@@ -87,11 +87,8 @@ static int viewroll_modal(bContext *C, wmOperator *op, const wmEvent *event)
bool use_autokey = false;
int ret = OPERATOR_RUNNING_MODAL;
/* execute the events */
if (event->type == MOUSEMOVE) {
event_code = VIEW_APPLY;
}
else if (event->type == EVT_MODAL_MAP) {
/* Execute the events. */
if (event->type == EVT_MODAL_MAP) {
switch (event->val) {
case VIEW_MODAL_CONFIRM:
event_code = VIEW_CONFIRM;
@@ -106,40 +103,51 @@ static int viewroll_modal(bContext *C, wmOperator *op, const wmEvent *event)
break;
}
}
else if (event->type == vod->init.event_type) {
/* Check `vod->init.event_type` first in case RMB was used to invoke.
* in this case confirming takes precedence over canceling, see: T102937. */
if (event->val == KM_RELEASE) {
event_code = VIEW_CONFIRM;
else {
if (event->type == MOUSEMOVE) {
event_code = VIEW_APPLY;
}
}
else if (ELEM(event->type, EVT_ESCKEY, RIGHTMOUSE)) {
if (event->val == KM_PRESS) {
/* Note this does not remove auto-keys on locked cameras. */
copy_qt_qt(vod->rv3d->viewquat, vod->init.quat);
ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d);
viewops_data_free(C, op->customdata);
op->customdata = NULL;
return OPERATOR_CANCELLED;
else if (event->type == vod->init.event_type) {
/* Check `vod->init.event_type` first in case RMB was used to invoke.
* in this case confirming takes precedence over canceling, see: T102937. */
if (event->val == KM_RELEASE) {
event_code = VIEW_CONFIRM;
}
}
else if (ELEM(event->type, EVT_ESCKEY, RIGHTMOUSE)) {
if (event->val == KM_PRESS) {
event_code = VIEW_CANCEL;
}
}
}
if (event_code == VIEW_APPLY) {
viewroll_apply(vod, event->xy[0], event->xy[1]);
if (ED_screen_animation_playing(CTX_wm_manager(C))) {
use_autokey = true;
switch (event_code) {
case VIEW_APPLY: {
viewroll_apply(vod, event->xy[0], event->xy[1]);
if (ED_screen_animation_playing(CTX_wm_manager(C))) {
use_autokey = true;
}
break;
}
case VIEW_CONFIRM: {
use_autokey = true;
ret = OPERATOR_FINISHED;
break;
}
case VIEW_CANCEL: {
/* Note this does not remove auto-keys on locked cameras. */
copy_qt_qt(vod->rv3d->viewquat, vod->init.quat);
ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d);
ret = OPERATOR_CANCELLED;
break;
}
}
else if (event_code == VIEW_CONFIRM) {
use_autokey = true;
ret = OPERATOR_FINISHED;
}
if (use_autokey) {
ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, true, false);
}
if (ret & OPERATOR_FINISHED) {
if ((ret & OPERATOR_RUNNING_MODAL) == 0) {
viewops_data_free(C, op->customdata);
op->customdata = NULL;
}

View File

@@ -182,7 +182,7 @@ static void viewrotate_apply_snap(ViewOpsData *vod)
}
}
else if (U.uiflag & USER_AUTOPERSP) {
rv3d->persp = vod->init.persp;
rv3d->persp = vod->init.persp_with_auto_persp_applied;
}
}
@@ -327,11 +327,8 @@ static int viewrotate_modal(bContext *C, wmOperator *op, const wmEvent *event)
bool use_autokey = false;
int ret = OPERATOR_RUNNING_MODAL;
/* execute the events */
if (event->type == MOUSEMOVE) {
event_code = VIEW_APPLY;
}
else if (event->type == EVT_MODAL_MAP) {
/* Execute the events. */
if (event->type == EVT_MODAL_MAP) {
switch (event->val) {
case VIEW_MODAL_CONFIRM:
event_code = VIEW_CONFIRM;
@@ -341,7 +338,7 @@ static int viewrotate_modal(bContext *C, wmOperator *op, const wmEvent *event)
event_code = VIEW_APPLY;
break;
case VIEWROT_MODAL_AXIS_SNAP_DISABLE:
vod->rv3d->persp = vod->init.persp;
vod->rv3d->persp = vod->init.persp_with_auto_persp_applied;
vod->axis_snap = false;
event_code = VIEW_APPLY;
break;
@@ -355,27 +352,64 @@ static int viewrotate_modal(bContext *C, wmOperator *op, const wmEvent *event)
break;
}
}
else if (event->type == vod->init.event_type && event->val == KM_RELEASE) {
event_code = VIEW_CONFIRM;
}
if (event_code == VIEW_APPLY) {
viewrotate_apply(vod, event->xy);
if (ED_screen_animation_playing(CTX_wm_manager(C))) {
use_autokey = true;
else {
if (event->type == MOUSEMOVE) {
event_code = VIEW_APPLY;
}
else if (event->type == vod->init.event_type) {
if (event->val == KM_RELEASE) {
event_code = VIEW_CONFIRM;
}
}
else if (ELEM(event->type, EVT_ESCKEY, RIGHTMOUSE)) {
if (event->val == KM_PRESS) {
event_code = VIEW_CANCEL;
}
}
}
else if (event_code == VIEW_CONFIRM) {
use_autokey = true;
ret = OPERATOR_FINISHED;
switch (event_code) {
case VIEW_APPLY: {
viewrotate_apply(vod, event->xy);
if (ED_screen_animation_playing(CTX_wm_manager(C))) {
use_autokey = true;
}
break;
}
case VIEW_CONFIRM: {
use_autokey = true;
ret = OPERATOR_FINISHED;
break;
}
case VIEW_CANCEL: {
/* Note this does not remove auto-keys on locked cameras. */
copy_qt_qt(vod->rv3d->viewquat, vod->init.quat);
/* The offset may have change when rotating around objects or last-brush. */
copy_v3_v3(vod->rv3d->ofs, vod->init.ofs);
/* The dist may have changed when orbiting from a camera view.
* In this case the `dist` is calculated based on the camera relative to the `ofs`. */
vod->rv3d->dist = vod->init.dist;
vod->rv3d->persp = vod->init.persp;
vod->rv3d->view = vod->init.view;
vod->rv3d->view_axis_roll = vod->init.view_axis_roll;
/* NOTE: there is no need to restore "last" values (as set by #ED_view3d_lastview_store). */
ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d);
ret = OPERATOR_CANCELLED;
break;
}
}
if (use_autokey) {
ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, true, true);
}
if (ret & OPERATOR_FINISHED) {
ED_view3d_camera_lock_undo_push(op->type->name, vod->v3d, vod->rv3d, C);
if ((ret & OPERATOR_RUNNING_MODAL) == 0) {
if (ret & OPERATOR_FINISHED) {
ED_view3d_camera_lock_undo_push(op->type->name, vod->v3d, vod->rv3d, C);
}
viewops_data_free(C, op->customdata);
op->customdata = NULL;
}

View File

@@ -377,15 +377,8 @@ static int viewzoom_modal(bContext *C, wmOperator *op, const wmEvent *event)
bool use_autokey = false;
int ret = OPERATOR_RUNNING_MODAL;
/* execute the events */
if (event->type == TIMER && event->customdata == vod->timer) {
/* continuous zoom */
event_code = VIEW_APPLY;
}
else if (event->type == MOUSEMOVE) {
event_code = VIEW_APPLY;
}
else if (event->type == EVT_MODAL_MAP) {
/* Execute the events. */
if (event->type == EVT_MODAL_MAP) {
switch (event->val) {
case VIEW_MODAL_CONFIRM:
event_code = VIEW_CONFIRM;
@@ -400,32 +393,70 @@ static int viewzoom_modal(bContext *C, wmOperator *op, const wmEvent *event)
break;
}
}
else if (event->type == vod->init.event_type && event->val == KM_RELEASE) {
event_code = VIEW_CONFIRM;
}
if (event_code == VIEW_APPLY) {
const bool use_cursor_init = RNA_boolean_get(op->ptr, "use_cursor_init");
viewzoom_apply(vod,
event->xy,
(eViewZoom_Style)U.viewzoom,
(U.uiflag & USER_ZOOM_INVERT) != 0,
(use_cursor_init && (U.uiflag & USER_ZOOM_TO_MOUSEPOS)));
if (ED_screen_animation_playing(CTX_wm_manager(C))) {
use_autokey = true;
else {
if (event->type == MOUSEMOVE) {
event_code = VIEW_APPLY;
}
else if (event->type == TIMER) {
if (event->customdata == vod->timer) {
/* Continuous zoom. */
event_code = VIEW_APPLY;
}
}
else if (event->type == vod->init.event_type) {
if (event->val == KM_RELEASE) {
event_code = VIEW_CONFIRM;
}
}
else if (ELEM(event->type, EVT_ESCKEY, RIGHTMOUSE)) {
if (event->val == KM_PRESS) {
event_code = VIEW_CANCEL;
}
}
}
else if (event_code == VIEW_CONFIRM) {
use_autokey = true;
ret = OPERATOR_FINISHED;
switch (event_code) {
case VIEW_APPLY: {
const bool use_cursor_init = RNA_boolean_get(op->ptr, "use_cursor_init");
viewzoom_apply(vod,
event->xy,
(eViewZoom_Style)U.viewzoom,
(U.uiflag & USER_ZOOM_INVERT) != 0,
(use_cursor_init && (U.uiflag & USER_ZOOM_TO_MOUSEPOS)));
if (ED_screen_animation_playing(CTX_wm_manager(C))) {
use_autokey = true;
}
break;
}
case VIEW_CONFIRM: {
use_autokey = true;
ret = OPERATOR_FINISHED;
break;
}
case VIEW_CANCEL: {
/* Note this does not remove auto-keys on locked cameras. */
vod->rv3d->dist = vod->init.dist;
/* The offset may have change when zooming to mouse position. */
copy_v3_v3(vod->rv3d->ofs, vod->init.ofs);
vod->rv3d->camzoom = vod->init.camzoom;
/* Zoom to mouse position in camera view changes these values. */
vod->rv3d->camdx = vod->init.camdx;
vod->rv3d->camdy = vod->init.camdy;
ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d);
ret = OPERATOR_CANCELLED;
break;
}
}
if (use_autokey) {
ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, false, true);
}
if (ret & OPERATOR_FINISHED) {
ED_view3d_camera_lock_undo_push(op->type->name, vod->v3d, vod->rv3d, C);
if ((ret & OPERATOR_RUNNING_MODAL) == 0) {
if (ret & OPERATOR_FINISHED) {
ED_view3d_camera_lock_undo_push(op->type->name, vod->v3d, vod->rv3d, C);
}
viewops_data_free(C, op->customdata);
op->customdata = NULL;
}

View File

@@ -647,7 +647,7 @@ void ED_uvedit_pack_islands_multi(const Scene *scene,
Object **objects,
const uint objects_len,
BMesh **bmesh_override,
const struct UVMapUDIM_Params *udim_params,
const struct UVMapUDIM_Params *closest_udim,
const struct UVPackIsland_Params *params)
{
blender::Vector<FaceIsland *> island_vector;
@@ -716,19 +716,12 @@ void ED_uvedit_pack_islands_multi(const Scene *scene,
for (int index = 0; index < island_vector.size(); index++) {
FaceIsland *island = island_vector[index];
/* Skip calculation if using specified UDIM option. */
if (udim_params && (udim_params->use_target_udim == false)) {
float bounds_min[2], bounds_max[2];
INIT_MINMAX2(bounds_min, bounds_max);
if (closest_udim) {
/* Only calculate selection bounding box if using closest_udim. */
for (int i = 0; i < island->faces_len; i++) {
BMFace *f = island->faces[i];
BM_face_uv_minmax(f, bounds_min, bounds_max, island->cd_loop_uv_offset);
BM_face_uv_minmax(f, selection_min_co, selection_max_co, island->cd_loop_uv_offset);
}
selection_min_co[0] = MIN2(bounds_min[0], selection_min_co[0]);
selection_min_co[1] = MIN2(bounds_min[1], selection_min_co[1]);
selection_max_co[0] = MAX2(bounds_max[0], selection_max_co[0]);
selection_max_co[1] = MAX2(bounds_max[1], selection_max_co[1]);
}
if (params->rotate) {
@@ -741,7 +734,7 @@ void ED_uvedit_pack_islands_multi(const Scene *scene,
/* Center of bounding box containing all selected UVs. */
float selection_center[2];
if (udim_params && (udim_params->use_target_udim == false)) {
if (closest_udim) {
selection_center[0] = (selection_min_co[0] + selection_max_co[0]) / 2.0f;
selection_center[1] = (selection_min_co[1] + selection_max_co[1]) / 2.0f;
}
@@ -749,25 +742,12 @@ void ED_uvedit_pack_islands_multi(const Scene *scene,
float scale[2] = {1.0f, 1.0f};
BoxPack *box_array = pack_islands_params(island_vector, *params, scale);
/* Tile offset. */
float base_offset[2] = {0.0f, 0.0f};
copy_v2_v2(base_offset, params->udim_base_offset);
/* CASE: ignore UDIM. */
if (udim_params == nullptr) {
/* pass */
}
/* CASE: Active/specified(smart uv project) UDIM. */
else if (udim_params->use_target_udim) {
/* Calculate offset based on specified_tile_index. */
base_offset[0] = (udim_params->target_udim - 1001) % 10;
base_offset[1] = (udim_params->target_udim - 1001) / 10;
}
/* CASE: Closest UDIM. */
else {
const Image *image = udim_params->image;
const int *udim_grid = udim_params->grid_shape;
if (closest_udim) {
const Image *image = closest_udim->image;
const int *udim_grid = closest_udim->grid_shape;
/* Check if selection lies on a valid UDIM grid tile. */
bool is_valid_udim = uv_coords_isect_udim(image, udim_grid, selection_center);
if (is_valid_udim) {

View File

@@ -134,54 +134,32 @@ static bool ED_uvedit_ensure_uvs(Object *obedit)
/** \name UDIM Access
* \{ */
bool ED_uvedit_udim_params_from_image_space(const SpaceImage *sima,
bool use_active,
struct UVMapUDIM_Params *udim_params)
static void ED_uvedit_udim_params_from_image_space(const SpaceImage *sima,
struct UVPackIsland_Params *r_params)
{
memset(udim_params, 0, sizeof(*udim_params));
udim_params->grid_shape[0] = 1;
udim_params->grid_shape[1] = 1;
udim_params->target_udim = 0;
udim_params->use_target_udim = false;
if (sima == NULL) {
return false;
if (!sima) {
return; /* Nothing to do. */
}
udim_params->image = sima->image;
udim_params->grid_shape[0] = sima->tile_grid_shape[0];
udim_params->grid_shape[1] = sima->tile_grid_shape[1];
if (use_active) {
int active_udim = 1001;
/* NOTE: Presently, when UDIM grid and tiled image are present together, only active tile for
* the tiled image is considered. */
const Image *image = sima->image;
if (image && image->source == IMA_SRC_TILED) {
ImageTile *active_tile = BLI_findlink(&image->tiles, image->active_tile_index);
if (active_tile) {
active_udim = active_tile->tile_number;
}
/* NOTE: Presently, when UDIM grid and tiled image are present together, only active tile for
* the tiled image is considered. */
const Image *image = sima->image;
if (image && image->source == IMA_SRC_TILED) {
ImageTile *active_tile = BLI_findlink(&image->tiles, image->active_tile_index);
if (active_tile) {
r_params->udim_base_offset[0] = (active_tile->tile_number - 1001) % 10;
r_params->udim_base_offset[1] = (active_tile->tile_number - 1001) / 10;
}
else {
/* TODO: Support storing an active UDIM when there are no tiles present.
* Until then, use 2D cursor to find the active tile index for the UDIM grid. */
if (uv_coords_isect_udim(sima->image, sima->tile_grid_shape, sima->cursor)) {
int tile_number = 1001;
tile_number += floorf(sima->cursor[1]) * 10;
tile_number += floorf(sima->cursor[0]);
active_udim = tile_number;
}
}
udim_params->target_udim = active_udim;
udim_params->use_target_udim = true;
return;
}
return true;
/* TODO: Support storing an active UDIM when there are no tiles present.
* Until then, use 2D cursor to find the active tile index for the UDIM grid. */
if (uv_coords_isect_udim(sima->image, sima->tile_grid_shape, sima->cursor)) {
r_params->udim_base_offset[0] = floorf(sima->cursor[0]);
r_params->udim_base_offset[1] = floorf(sima->cursor[1]);
}
}
/** \} */
/* -------------------------------------------------------------------- */
@@ -1088,12 +1066,7 @@ static int pack_islands_exec(bContext *C, wmOperator *op)
RNA_float_set(op->ptr, "margin", scene->toolsettings->uvcalc_margin);
}
struct UVMapUDIM_Params udim_params;
const bool use_active = (udim_source == PACK_UDIM_SRC_ACTIVE);
const bool use_udim_params = ED_uvedit_udim_params_from_image_space(
sima, use_active, &udim_params);
const struct UVPackIsland_Params pack_island_params = {
struct UVPackIsland_Params pack_island_params = {
.rotate = RNA_boolean_get(op->ptr, "rotate"),
.only_selected_uvs = options.only_selected_uvs,
.only_selected_faces = options.only_selected_faces,
@@ -1104,12 +1077,22 @@ static int pack_islands_exec(bContext *C, wmOperator *op)
.margin_method = RNA_enum_get(op->ptr, "margin_method"),
.margin = RNA_float_get(op->ptr, "margin"),
};
ED_uvedit_pack_islands_multi(scene,
objects,
objects_len,
NULL,
use_udim_params ? &udim_params : NULL,
&pack_island_params);
struct UVMapUDIM_Params closest_udim_buf;
struct UVMapUDIM_Params *closest_udim = NULL;
if (udim_source == PACK_UDIM_SRC_ACTIVE) {
ED_uvedit_udim_params_from_image_space(sima, &pack_island_params);
}
else if (sima) {
BLI_assert(udim_source == PACK_UDIM_SRC_CLOSEST);
closest_udim = &closest_udim_buf;
closest_udim->image = sima->image;
closest_udim->grid_shape[0] = sima->tile_grid_shape[0];
closest_udim->grid_shape[1] = sima->tile_grid_shape[1];
}
ED_uvedit_pack_islands_multi(
scene, objects, objects_len, NULL, closest_udim, &pack_island_params);
MEM_freeN(objects);
return OPERATOR_FINISHED;

View File

@@ -2215,8 +2215,8 @@ struct ImBuf *imb_load_filepath_thumbnail_openexr(const char *filepath,
float scale_factor = MIN2(float(max_thumb_size) / float(source_w),
float(max_thumb_size) / float(source_h));
int dest_w = int(source_w * scale_factor);
int dest_h = int(source_h * scale_factor);
int dest_w = MAX2(int(source_w * scale_factor), 1);
int dest_h = MAX2(int(source_h * scale_factor), 1);
struct ImBuf *ibuf = IMB_allocImBuf(dest_w, dest_h, 32, IB_rectfloat);

View File

@@ -112,8 +112,8 @@ struct ImBuf *imb_load_filepath_thumbnail_webp(const char *filepath,
*r_height = (size_t)config.input.height;
const float scale = (float)max_thumb_size / MAX2(config.input.width, config.input.height);
const int dest_w = (int)(config.input.width * scale);
const int dest_h = (int)(config.input.height * scale);
const int dest_w = MAX2((int)(config.input.width * scale), 1);
const int dest_h = MAX2((int)(config.input.height * scale), 1);
colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE);
struct ImBuf *ibuf = IMB_allocImBuf(dest_w, dest_h, 32, IB_rect);

View File

@@ -250,7 +250,7 @@ void OBJWriter::write_vertex_coords(FormatHandler &fh,
{
const int tot_count = obj_mesh_data.tot_vertices();
Mesh *mesh = obj_mesh_data.get_mesh();
const Mesh *mesh = obj_mesh_data.get_mesh();
const CustomDataLayer *colors_layer = nullptr;
if (write_colors) {
colors_layer = BKE_id_attributes_active_color_get(&mesh->id);

View File

@@ -33,21 +33,23 @@ OBJMesh::OBJMesh(Depsgraph *depsgraph, const OBJExportParams &export_params, Obj
/* We need to copy the object because it may be in temporary space. */
Object *obj_eval = DEG_get_evaluated_object(depsgraph, mesh_object);
export_object_eval_ = dna::shallow_copy(*obj_eval);
export_mesh_eval_ = export_params.apply_modifiers ?
BKE_object_get_evaluated_mesh(&export_object_eval_) :
BKE_object_get_pre_modified_mesh(&export_object_eval_);
mesh_eval_needs_free_ = false;
if (!export_mesh_eval_) {
export_mesh_ = export_params.apply_modifiers ?
BKE_object_get_evaluated_mesh(&export_object_eval_) :
BKE_object_get_pre_modified_mesh(&export_object_eval_);
if (export_mesh_) {
mesh_verts_ = export_mesh_->verts();
mesh_edges_ = export_mesh_->edges();
mesh_polys_ = export_mesh_->polys();
mesh_loops_ = export_mesh_->loops();
}
else {
/* Curves and NURBS surfaces need a new mesh when they're
* exported in the form of vertices and edges.
*/
export_mesh_eval_ = BKE_mesh_new_from_object(depsgraph, &export_object_eval_, true, true);
/* Since a new mesh been allocated, it needs to be freed in the destructor. */
mesh_eval_needs_free_ = true;
this->set_mesh(BKE_mesh_new_from_object(depsgraph, &export_object_eval_, true, true));
}
if (export_params.export_triangulated_mesh && export_object_eval_.type == OB_MESH) {
std::tie(export_mesh_eval_, mesh_eval_needs_free_) = triangulate_mesh_eval();
this->triangulate_mesh_eval();
}
set_world_axes_transform(export_params.forward_axis, export_params.up_axis);
}
@@ -60,18 +62,26 @@ OBJMesh::~OBJMesh()
clear();
}
void OBJMesh::free_mesh_if_needed()
void OBJMesh::set_mesh(Mesh *mesh)
{
if (mesh_eval_needs_free_ && export_mesh_eval_) {
BKE_id_free(nullptr, export_mesh_eval_);
export_mesh_eval_ = nullptr;
mesh_eval_needs_free_ = false;
if (owned_export_mesh_) {
BKE_id_free(nullptr, owned_export_mesh_);
}
owned_export_mesh_ = mesh;
export_mesh_ = owned_export_mesh_;
mesh_verts_ = mesh->verts();
mesh_edges_ = mesh->edges();
mesh_polys_ = mesh->polys();
mesh_loops_ = mesh->loops();
}
void OBJMesh::clear()
{
free_mesh_if_needed();
if (owned_export_mesh_) {
BKE_id_free(nullptr, owned_export_mesh_);
owned_export_mesh_ = nullptr;
}
export_mesh_ = nullptr;
uv_indices_.clear_and_make_inline();
uv_coords_.clear_and_make_inline();
loop_to_normal_index_.clear_and_make_inline();
@@ -83,10 +93,10 @@ void OBJMesh::clear()
}
}
std::pair<Mesh *, bool> OBJMesh::triangulate_mesh_eval()
void OBJMesh::triangulate_mesh_eval()
{
if (export_mesh_eval_->totpoly <= 0) {
return {export_mesh_eval_, false};
if (export_mesh_->totpoly <= 0) {
return;
}
const BMeshCreateParams bm_create_params = {false};
BMeshFromMeshParams bm_convert_params{};
@@ -99,7 +109,7 @@ std::pair<Mesh *, bool> OBJMesh::triangulate_mesh_eval()
* triangulated here. */
const int triangulate_min_verts = 4;
BMesh *bmesh = BKE_mesh_to_bmesh_ex(export_mesh_eval_, &bm_create_params, &bm_convert_params);
BMesh *bmesh = BKE_mesh_to_bmesh_ex(export_mesh_, &bm_create_params, &bm_convert_params);
BM_mesh_triangulate(bmesh,
MOD_TRIANGULATE_NGON_BEAUTY,
MOD_TRIANGULATE_QUAD_SHORTEDGE,
@@ -108,11 +118,9 @@ std::pair<Mesh *, bool> OBJMesh::triangulate_mesh_eval()
nullptr,
nullptr,
nullptr);
Mesh *triangulated = BKE_mesh_from_bmesh_for_eval_nomain(bmesh, nullptr, export_mesh_eval_);
Mesh *triangulated = BKE_mesh_from_bmesh_for_eval_nomain(bmesh, nullptr, export_mesh_);
BM_mesh_free(bmesh);
free_mesh_if_needed();
return {triangulated, true};
this->set_mesh(triangulated);
}
void OBJMesh::set_world_axes_transform(const eIOAxis forward, const eIOAxis up)
@@ -137,12 +145,12 @@ void OBJMesh::set_world_axes_transform(const eIOAxis forward, const eIOAxis up)
int OBJMesh::tot_vertices() const
{
return export_mesh_eval_->totvert;
return export_mesh_->totvert;
}
int OBJMesh::tot_polygons() const
{
return export_mesh_eval_->totpoly;
return export_mesh_->totpoly;
}
int OBJMesh::tot_uv_vertices() const
@@ -152,12 +160,12 @@ int OBJMesh::tot_uv_vertices() const
int OBJMesh::tot_edges() const
{
return export_mesh_eval_->totedge;
return export_mesh_->totedge;
}
int16_t OBJMesh::tot_materials() const
{
return export_mesh_eval_->totcol;
return export_mesh_->totcol;
}
int OBJMesh::tot_normal_indices() const
@@ -175,27 +183,25 @@ int OBJMesh::ith_smooth_group(const int poly_index) const
void OBJMesh::ensure_mesh_normals() const
{
BKE_mesh_calc_normals_split(export_mesh_eval_);
/* Const cast can be removed when calculating face corner normals lazily is possible. */
BKE_mesh_calc_normals_split(const_cast<Mesh *>(export_mesh_));
}
void OBJMesh::calc_smooth_groups(const bool use_bitflags)
{
const Span<MEdge> edges = export_mesh_eval_->edges();
const Span<MPoly> polys = export_mesh_eval_->polys();
const Span<MLoop> loops = export_mesh_eval_->loops();
poly_smooth_groups_ = BKE_mesh_calc_smoothgroups(edges.data(),
edges.size(),
polys.data(),
polys.size(),
loops.data(),
loops.size(),
poly_smooth_groups_ = BKE_mesh_calc_smoothgroups(mesh_edges_.data(),
mesh_edges_.size(),
mesh_polys_.data(),
mesh_polys_.size(),
mesh_loops_.data(),
mesh_loops_.size(),
&tot_smooth_groups_,
use_bitflags);
}
void OBJMesh::calc_poly_order()
{
const bke::AttributeAccessor attributes = export_mesh_eval_->attributes();
const bke::AttributeAccessor attributes = export_mesh_->attributes();
const VArray<int> material_indices = attributes.lookup_or_default<int>(
"material_index", ATTR_DOMAIN_FACE, 0);
if (material_indices.is_single() && material_indices.get_internal_single() == 0) {
@@ -234,8 +240,7 @@ const Material *OBJMesh::get_object_material(const int16_t mat_nr) const
bool OBJMesh::is_ith_poly_smooth(const int poly_index) const
{
const Span<MPoly> polys = export_mesh_eval_->polys();
return polys[poly_index].flag & ME_SMOOTH;
return mesh_polys_[poly_index].flag & ME_SMOOTH;
}
const char *OBJMesh::get_object_name() const
@@ -245,7 +250,7 @@ const char *OBJMesh::get_object_name() const
const char *OBJMesh::get_object_mesh_name() const
{
return export_mesh_eval_->id.name + 2;
return export_mesh_->id.name + 2;
}
const char *OBJMesh::get_object_material_name(const int16_t mat_nr) const
@@ -260,8 +265,7 @@ const char *OBJMesh::get_object_material_name(const int16_t mat_nr) const
float3 OBJMesh::calc_vertex_coords(const int vert_index, const float global_scale) const
{
float3 r_coords;
const Span<MVert> verts = export_mesh_eval_->verts();
copy_v3_v3(r_coords, verts[vert_index].co);
copy_v3_v3(r_coords, mesh_verts_[vert_index].co);
mul_m4_v3(world_and_axes_transform_, r_coords);
mul_v3_fl(r_coords, global_scale);
return r_coords;
@@ -269,10 +273,8 @@ float3 OBJMesh::calc_vertex_coords(const int vert_index, const float global_scal
Vector<int> OBJMesh::calc_poly_vertex_indices(const int poly_index) const
{
const Span<MPoly> polys = export_mesh_eval_->polys();
const Span<MLoop> loops = export_mesh_eval_->loops();
const MPoly &mpoly = polys[poly_index];
const MLoop *mloop = &loops[mpoly.loopstart];
const MPoly &mpoly = mesh_polys_[poly_index];
const MLoop *mloop = &mesh_loops_[mpoly.loopstart];
const int totloop = mpoly.totloop;
Vector<int> r_poly_vertex_indices(totloop);
for (int loop_index = 0; loop_index < totloop; loop_index++) {
@@ -283,29 +285,27 @@ Vector<int> OBJMesh::calc_poly_vertex_indices(const int poly_index) const
void OBJMesh::store_uv_coords_and_indices()
{
const Span<MPoly> polys = export_mesh_eval_->polys();
const Span<MLoop> loops = export_mesh_eval_->loops();
const int totvert = export_mesh_eval_->totvert;
const int totvert = export_mesh_->totvert;
const MLoopUV *mloopuv = static_cast<const MLoopUV *>(
CustomData_get_layer(&export_mesh_eval_->ldata, CD_MLOOPUV));
CustomData_get_layer(&export_mesh_->ldata, CD_MLOOPUV));
if (!mloopuv) {
tot_uv_vertices_ = 0;
return;
}
const float limit[2] = {STD_UV_CONNECT_LIMIT, STD_UV_CONNECT_LIMIT};
UvVertMap *uv_vert_map = BKE_mesh_uv_vert_map_create(polys.data(),
UvVertMap *uv_vert_map = BKE_mesh_uv_vert_map_create(mesh_polys_.data(),
nullptr,
nullptr,
loops.data(),
mesh_loops_.data(),
mloopuv,
polys.size(),
mesh_polys_.size(),
totvert,
limit,
false,
false);
uv_indices_.resize(polys.size());
uv_indices_.resize(mesh_polys_.size());
/* At least total vertices of a mesh will be present in its texture map. So
* reserve minimum space early. */
uv_coords_.reserve(totvert);
@@ -317,11 +317,11 @@ void OBJMesh::store_uv_coords_and_indices()
if (uv_vert->separate) {
tot_uv_vertices_ += 1;
}
const int verts_in_poly = polys[uv_vert->poly_index].totloop;
const int verts_in_poly = mesh_polys_[uv_vert->poly_index].totloop;
/* Store UV vertex coordinates. */
uv_coords_.resize(tot_uv_vertices_);
const int loopstart = polys[uv_vert->poly_index].loopstart;
const int loopstart = mesh_polys_[uv_vert->poly_index].loopstart;
Span<float> vert_uv_coords(mloopuv[loopstart + uv_vert->loop_of_poly_index].uv, 2);
uv_coords_[tot_uv_vertices_ - 1] = float2(vert_uv_coords[0], vert_uv_coords[1]);
@@ -339,7 +339,7 @@ Span<int> OBJMesh::calc_poly_uv_indices(const int poly_index) const
if (uv_indices_.size() <= 0) {
return {};
}
BLI_assert(poly_index < export_mesh_eval_->totpoly);
BLI_assert(poly_index < export_mesh_->totpoly);
BLI_assert(poly_index < uv_indices_.size());
return uv_indices_[poly_index];
}
@@ -347,11 +347,9 @@ Span<int> OBJMesh::calc_poly_uv_indices(const int poly_index) const
float3 OBJMesh::calc_poly_normal(const int poly_index) const
{
float3 r_poly_normal;
const Span<MVert> verts = export_mesh_eval_->verts();
const Span<MPoly> polys = export_mesh_eval_->polys();
const Span<MLoop> loops = export_mesh_eval_->loops();
const MPoly &poly = polys[poly_index];
BKE_mesh_calc_poly_normal(&poly, &loops[poly.loopstart], verts.data(), r_poly_normal);
const MPoly &poly = mesh_polys_[poly_index];
BKE_mesh_calc_poly_normal(
&poly, &mesh_loops_[poly.loopstart], mesh_verts_.data(), r_poly_normal);
mul_m3_v3(world_and_axes_normal_transform_, r_poly_normal);
normalize_v3(r_poly_normal);
return r_poly_normal;
@@ -375,8 +373,6 @@ static float3 round_float3_to_n_digits(const float3 &v, int round_digits)
void OBJMesh::store_normal_coords_and_indices()
{
const Span<MPoly> polys = export_mesh_eval_->polys();
/* We'll round normal components to 4 digits.
* This will cover up some minor differences
* between floating point calculations on different platforms.
@@ -386,19 +382,19 @@ void OBJMesh::store_normal_coords_and_indices()
int cur_normal_index = 0;
Map<float3, int> normal_to_index;
/* We don't know how many unique normals there will be, but this is a guess. */
normal_to_index.reserve(export_mesh_eval_->totpoly);
loop_to_normal_index_.resize(export_mesh_eval_->totloop);
normal_to_index.reserve(export_mesh_->totpoly);
loop_to_normal_index_.resize(export_mesh_->totloop);
loop_to_normal_index_.fill(-1);
const float(*lnors)[3] = static_cast<const float(*)[3]>(
CustomData_get_layer(&export_mesh_eval_->ldata, CD_NORMAL));
for (int poly_index = 0; poly_index < export_mesh_eval_->totpoly; ++poly_index) {
const MPoly &mpoly = polys[poly_index];
CustomData_get_layer(&export_mesh_->ldata, CD_NORMAL));
for (int poly_index = 0; poly_index < export_mesh_->totpoly; ++poly_index) {
const MPoly &mpoly = mesh_polys_[poly_index];
bool need_per_loop_normals = lnors != nullptr || (mpoly.flag & ME_SMOOTH);
if (need_per_loop_normals) {
for (int loop_of_poly = 0; loop_of_poly < mpoly.totloop; ++loop_of_poly) {
float3 loop_normal;
int loop_index = mpoly.loopstart + loop_of_poly;
BLI_assert(loop_index < export_mesh_eval_->totloop);
BLI_assert(loop_index < export_mesh_->totloop);
copy_v3_v3(loop_normal, lnors[loop_index]);
mul_m3_v3(world_and_axes_normal_transform_, loop_normal);
normalize_v3(loop_normal);
@@ -423,7 +419,7 @@ void OBJMesh::store_normal_coords_and_indices()
}
for (int i = 0; i < mpoly.totloop; ++i) {
int loop_index = mpoly.loopstart + i;
BLI_assert(loop_index < export_mesh_eval_->totloop);
BLI_assert(loop_index < export_mesh_->totloop);
loop_to_normal_index_[loop_index] = poly_norm_index;
}
}
@@ -436,8 +432,7 @@ Vector<int> OBJMesh::calc_poly_normal_indices(const int poly_index) const
if (loop_to_normal_index_.is_empty()) {
return {};
}
const Span<MPoly> polys = export_mesh_eval_->polys();
const MPoly &mpoly = polys[poly_index];
const MPoly &mpoly = mesh_polys_[poly_index];
const int totloop = mpoly.totloop;
Vector<int> r_poly_normal_indices(totloop);
for (int poly_loop_index = 0; poly_loop_index < totloop; poly_loop_index++) {
@@ -458,19 +453,17 @@ int OBJMesh::tot_deform_groups() const
int16_t OBJMesh::get_poly_deform_group_index(const int poly_index,
MutableSpan<float> group_weights) const
{
BLI_assert(poly_index < export_mesh_eval_->totpoly);
BLI_assert(poly_index < export_mesh_->totpoly);
BLI_assert(group_weights.size() == BKE_object_defgroup_count(&export_object_eval_));
const Span<MPoly> polys = export_mesh_eval_->polys();
const Span<MLoop> loops = export_mesh_eval_->loops();
const Span<MDeformVert> dverts = export_mesh_eval_->deform_verts();
const Span<MDeformVert> dverts = export_mesh_->deform_verts();
if (dverts.is_empty()) {
return NOT_FOUND;
}
group_weights.fill(0);
bool found_any_group = false;
const MPoly &mpoly = polys[poly_index];
const MLoop *mloop = &loops[mpoly.loopstart];
const MPoly &mpoly = mesh_polys_[poly_index];
const MLoop *mloop = &mesh_loops_[mpoly.loopstart];
for (int loop_i = 0; loop_i < mpoly.totloop; ++loop_i, ++mloop) {
const MDeformVert &dv = dverts[mloop->v];
for (int weight_i = 0; weight_i < dv.totweight; ++weight_i) {

View File

@@ -35,11 +35,15 @@ class OBJMesh : NonCopyable {
* sometimes builds an Object in a temporary space that doesn't persist.
*/
Object export_object_eval_;
Mesh *export_mesh_eval_;
/**
* For curves which are converted to mesh, and triangulated meshes, a new mesh is allocated.
*/
bool mesh_eval_needs_free_ = false;
/** A pointer to #owned_export_mesh_ or the object'ed evaluated/original mesh. */
const Mesh *export_mesh_;
/** A mesh owned here, if created or modified for the export. May be null. */
Mesh *owned_export_mesh_ = nullptr;
Span<MVert> mesh_verts_;
Span<MEdge> mesh_edges_;
Span<MPoly> mesh_polys_;
Span<MLoop> mesh_loops_;
/**
* Final transform of an object obtained from export settings (up_axis, forward_axis) and the
* object's world transform matrix.
@@ -216,23 +220,19 @@ class OBJMesh : NonCopyable {
return i < 0 || i >= poly_order_.size() ? i : poly_order_[i];
}
Mesh *get_mesh() const
const Mesh *get_mesh() const
{
return export_mesh_eval_;
return export_mesh_;
}
private:
/** Override the mesh from the export scene's object. Takes ownership of the mesh. */
void set_mesh(Mesh *mesh);
/**
* Free the mesh if _the exporter_ created it.
* Triangulate the mesh pointed to by this object, potentially replacing it with a newly created
* mesh.
*/
void free_mesh_if_needed();
/**
* Allocate a new Mesh with triangulated polygons.
*
* The returned mesh can be the same as the old one.
* \return Owning pointer to the new Mesh, and whether a new Mesh was created.
*/
std::pair<Mesh *, bool> triangulate_mesh_eval();
void triangulate_mesh_eval();
/**
* Set the final transform after applying axes settings and an Object's world transform.
*/

View File

@@ -266,8 +266,8 @@ typedef struct Object {
/** Old animation system, deprecated for 2.5. */
struct Ipo *ipo DNA_DEPRECATED;
/* struct Path *path; */
struct bAction *action DNA_DEPRECATED; /* XXX deprecated... old animation system */
struct bAction *poselib;
struct bAction *action DNA_DEPRECATED; /* XXX deprecated... old animation system */
struct bAction *poselib DNA_DEPRECATED; /* Pre-Blender 3.0 pose library, deprecated in 3.5. */
/** Pose data, armature objects only. */
struct bPose *pose;
/** Pointer to objects data - an 'ID' or NULL. */

View File

@@ -1033,6 +1033,7 @@ static void rna_def_tex_slot(BlenderRNA *brna)
RNA_def_property_string_funcs(
prop, "rna_TexPaintSlot_name_get", "rna_TexPaintSlot_name_length", NULL);
RNA_def_property_ui_text(prop, "Name", "Name of the slot");
RNA_def_struct_name_property(srna, prop);
prop = RNA_def_property(srna, "icon_value", PROP_INT, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);

View File

@@ -3750,15 +3750,6 @@ static void rna_def_object(BlenderRNA *brna)
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_GPencil_update");
/* pose */
prop = RNA_def_property(srna, "pose_library", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "poselib");
RNA_def_property_struct_type(prop, "Action");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT);
RNA_def_property_ui_text(prop,
"Pose Library",
"Deprecated, will be removed in Blender 3.3. "
"Action used as a pose library for armatures");
prop = RNA_def_property(srna, "pose", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "pose");
RNA_def_property_struct_type(prop, "Pose");

View File

@@ -99,6 +99,10 @@ static const EnumPropertyItem event_ndof_type_items[] = {
{NDOF_BUTTON_DOMINANT, "NDOF_BUTTON_DOMINANT", 0, "Dominant", ""},
{NDOF_BUTTON_PLUS, "NDOF_BUTTON_PLUS", 0, "Plus", ""},
{NDOF_BUTTON_MINUS, "NDOF_BUTTON_MINUS", 0, "Minus", ""},
/* View buttons. */
{NDOF_BUTTON_V1, "NDOF_BUTTON_V1", 0, "View 1", ""},
{NDOF_BUTTON_V2, "NDOF_BUTTON_V2", 0, "View 2", ""},
{NDOF_BUTTON_V3, "NDOF_BUTTON_V3", 0, "View 3", ""},
/* general-purpose buttons */
{NDOF_BUTTON_1, "NDOF_BUTTON_1", 0, "Button 1", ""},
{NDOF_BUTTON_2, "NDOF_BUTTON_2", 0, "Button 2", ""},
@@ -113,10 +117,6 @@ static const EnumPropertyItem event_ndof_type_items[] = {
{NDOF_BUTTON_A, "NDOF_BUTTON_A", 0, "Button A", ""},
{NDOF_BUTTON_B, "NDOF_BUTTON_B", 0, "Button B", ""},
{NDOF_BUTTON_C, "NDOF_BUTTON_C", 0, "Button C", ""},
/* View buttons. */
{NDOF_BUTTON_V1, "NDOF_BUTTON_V1", 0, "View 1", ""},
{NDOF_BUTTON_V2, "NDOF_BUTTON_V2", 0, "View 2", ""},
{NDOF_BUTTON_V3, "NDOF_BUTTON_V3", 0, "View 3", ""},
# if 0 /* Never used (converted to keyboard events by GHOST). */
/* keyboard emulation */
{NDOF_BUTTON_ESC, "NDOF_BUTTON_ESC", 0, "Esc"},
@@ -347,6 +347,10 @@ const EnumPropertyItem rna_enum_event_type_items[] = {
{NDOF_BUTTON_SHIFT, "NDOF_BUTTON_SHIFT", 0, "NDOF Shift", "NdofShift"},
{NDOF_BUTTON_CTRL, "NDOF_BUTTON_CTRL", 0, "NDOF Ctrl", "NdofCtrl"},
#endif
/* View buttons. */
{NDOF_BUTTON_V1, "NDOF_BUTTON_V1", 0, "NDOF View 1", ""},
{NDOF_BUTTON_V2, "NDOF_BUTTON_V2", 0, "NDOF View 2", ""},
{NDOF_BUTTON_V3, "NDOF_BUTTON_V3", 0, "NDOF View 3", ""},
/* general-purpose buttons */
{NDOF_BUTTON_1, "NDOF_BUTTON_1", 0, "NDOF Button 1", "NdofB1"},
{NDOF_BUTTON_2, "NDOF_BUTTON_2", 0, "NDOF Button 2", "NdofB2"},

View File

@@ -372,104 +372,110 @@ static void calculate_cone_faces(const ConeConfig &config,
MutableSpan<MLoop> loops,
MutableSpan<MPoly> polys)
{
int loop_index = 0;
int poly_index = 0;
int rings_poly_start;
int rings_loop_start;
if (config.top_has_center_vert) {
rings_poly_start = config.circle_segments;
rings_loop_start = config.circle_segments * 3;
/* Top cone tip or center triangle fan in the fill. */
const int top_center_vert = 0;
const int top_fan_edges_start = 0;
for (const int i : IndexRange(config.circle_segments)) {
MPoly &poly = polys[poly_index++];
poly.loopstart = loop_index;
const int loop_start = i * 3;
MPoly &poly = polys[i];
poly.loopstart = loop_start;
poly.totloop = 3;
MLoop &loop_a = loops[loop_index++];
loop_a.v = config.first_ring_verts_start + i;
loop_a.e = config.first_ring_edges_start + i;
MLoop &loop_b = loops[loop_index++];
loop_b.v = config.first_ring_verts_start + ((i + 1) % config.circle_segments);
loop_b.e = top_fan_edges_start + ((i + 1) % config.circle_segments);
MLoop &loop_c = loops[loop_index++];
loop_c.v = top_center_vert;
loop_c.e = top_fan_edges_start + i;
loops[loop_start + 0].v = config.first_ring_verts_start + i;
loops[loop_start + 0].e = config.first_ring_edges_start + i;
loops[loop_start + 1].v = config.first_ring_verts_start + ((i + 1) % config.circle_segments);
loops[loop_start + 1].e = top_fan_edges_start + ((i + 1) % config.circle_segments);
loops[loop_start + 2].v = top_center_vert;
loops[loop_start + 2].e = top_fan_edges_start + i;
}
}
else if (config.fill_type == GEO_NODE_MESH_CIRCLE_FILL_NGON) {
rings_poly_start = 1;
rings_loop_start = config.circle_segments;
/* Center n-gon in the fill. */
MPoly &poly = polys[poly_index++];
poly.loopstart = loop_index;
MPoly &poly = polys[0];
poly.loopstart = 0;
poly.totloop = config.circle_segments;
for (const int i : IndexRange(config.circle_segments)) {
MLoop &loop = loops[loop_index++];
loop.v = i;
loop.e = i;
loops[i].v = i;
loops[i].e = i;
}
}
/* Quads connect one edge ring to the next one. */
if (config.tot_quad_rings > 0) {
for (const int i : IndexRange(config.tot_quad_rings)) {
const int this_ring_vert_start = config.first_ring_verts_start +
(i * config.circle_segments);
const int next_ring_vert_start = this_ring_vert_start + config.circle_segments;
for (const int i : IndexRange(config.tot_quad_rings)) {
const int this_ring_poly_start = rings_poly_start + i * config.circle_segments;
const int this_ring_loop_start = rings_loop_start + i * config.circle_segments * 4;
const int this_ring_vert_start = config.first_ring_verts_start + (i * config.circle_segments);
const int next_ring_vert_start = this_ring_vert_start + config.circle_segments;
const int this_ring_edges_start = config.first_ring_edges_start +
(i * 2 * config.circle_segments);
const int next_ring_edges_start = this_ring_edges_start + (2 * config.circle_segments);
const int ring_connections_start = this_ring_edges_start + config.circle_segments;
const int this_ring_edges_start = config.first_ring_edges_start +
(i * 2 * config.circle_segments);
const int next_ring_edges_start = this_ring_edges_start + (2 * config.circle_segments);
const int ring_connections_start = this_ring_edges_start + config.circle_segments;
for (const int j : IndexRange(config.circle_segments)) {
MPoly &poly = polys[poly_index++];
poly.loopstart = loop_index;
poly.totloop = 4;
for (const int j : IndexRange(config.circle_segments)) {
const int loop_start = this_ring_loop_start + j * 4;
MPoly &poly = polys[this_ring_poly_start + j];
poly.loopstart = loop_start;
poly.totloop = 4;
MLoop &loop_a = loops[loop_index++];
loop_a.v = this_ring_vert_start + j;
loop_a.e = ring_connections_start + j;
MLoop &loop_b = loops[loop_index++];
loop_b.v = next_ring_vert_start + j;
loop_b.e = next_ring_edges_start + j;
MLoop &loop_c = loops[loop_index++];
loop_c.v = next_ring_vert_start + ((j + 1) % config.circle_segments);
loop_c.e = ring_connections_start + ((j + 1) % config.circle_segments);
MLoop &loop_d = loops[loop_index++];
loop_d.v = this_ring_vert_start + ((j + 1) % config.circle_segments);
loop_d.e = this_ring_edges_start + j;
}
loops[loop_start + 0].v = this_ring_vert_start + j;
loops[loop_start + 0].e = ring_connections_start + j;
loops[loop_start + 1].v = next_ring_vert_start + j;
loops[loop_start + 1].e = next_ring_edges_start + j;
loops[loop_start + 2].v = next_ring_vert_start + ((j + 1) % config.circle_segments);
loops[loop_start + 2].e = ring_connections_start + ((j + 1) % config.circle_segments);
loops[loop_start + 3].v = this_ring_vert_start + ((j + 1) % config.circle_segments);
loops[loop_start + 3].e = this_ring_edges_start + j;
}
}
const int bottom_poly_start = rings_poly_start + config.tot_quad_rings * config.circle_segments;
const int bottom_loop_start = rings_loop_start +
config.tot_quad_rings * config.circle_segments * 4;
if (config.bottom_has_center_vert) {
/* Bottom cone tip or center triangle fan in the fill. */
for (const int i : IndexRange(config.circle_segments)) {
MPoly &poly = polys[poly_index++];
poly.loopstart = loop_index;
const int loop_start = bottom_loop_start + i * 3;
MPoly &poly = polys[bottom_poly_start + i];
poly.loopstart = loop_start;
poly.totloop = 3;
MLoop &loop_a = loops[loop_index++];
loop_a.v = config.last_ring_verts_start + i;
loop_a.e = config.last_fan_edges_start + i;
MLoop &loop_b = loops[loop_index++];
loop_b.v = config.last_vert;
loop_b.e = config.last_fan_edges_start + (i + 1) % config.circle_segments;
MLoop &loop_c = loops[loop_index++];
loop_c.v = config.last_ring_verts_start + (i + 1) % config.circle_segments;
loop_c.e = config.last_ring_edges_start + i;
loops[loop_start + 0].v = config.last_ring_verts_start + i;
loops[loop_start + 0].e = config.last_fan_edges_start + i;
loops[loop_start + 1].v = config.last_vert;
loops[loop_start + 1].e = config.last_fan_edges_start + (i + 1) % config.circle_segments;
loops[loop_start + 2].v = config.last_ring_verts_start + (i + 1) % config.circle_segments;
loops[loop_start + 2].e = config.last_ring_edges_start + i;
}
}
else if (config.fill_type == GEO_NODE_MESH_CIRCLE_FILL_NGON) {
/* Center n-gon in the fill. */
MPoly &poly = polys[poly_index++];
poly.loopstart = loop_index;
MPoly &poly = polys[bottom_poly_start];
poly.loopstart = bottom_loop_start;
poly.totloop = config.circle_segments;
for (const int i : IndexRange(config.circle_segments)) {
/* Go backwards to reverse surface normal. */
MLoop &loop = loops[loop_index++];
loop.v = config.last_vert - i;
loop.e = config.last_edge - ((i + 1) % config.circle_segments);
loops[bottom_loop_start + i].v = config.last_vert - i;
loops[bottom_loop_start + i].e = config.last_edge - ((i + 1) % config.circle_segments);
}
}
}

View File

@@ -184,71 +184,74 @@ BLI_NOINLINE static void calculate_sphere_corners(MutableSpan<MLoop> loops,
const int segments,
const int rings)
{
int loop_index = 0;
auto segment_next_or_first = [&](const int segment) {
return segment == segments - 1 ? 0 : segment + 1;
};
/* Add the triangles connected to the top vertex. */
const int first_vert_ring_index_start = 1;
const int first_vert_ring_start = 1;
for (const int segment : IndexRange(segments)) {
const int loop_start = segment * 3;
const int segment_next = segment_next_or_first(segment);
MLoop &loop_a = loops[loop_index++];
loop_a.v = 0;
loop_a.e = segment;
MLoop &loop_b = loops[loop_index++];
loop_b.v = first_vert_ring_index_start + segment;
loop_b.e = segments + segment;
MLoop &loop_c = loops[loop_index++];
loop_c.v = first_vert_ring_index_start + segment_next;
loop_c.e = segment_next;
loops[loop_start + 0].v = 0;
loops[loop_start + 0].e = segment;
loops[loop_start + 1].v = first_vert_ring_start + segment;
loops[loop_start + 1].e = segments + segment;
loops[loop_start + 2].v = first_vert_ring_start + segment_next;
loops[loop_start + 2].e = segment_next;
}
int ring_vert_index_start = 1;
int ring_edge_index_start = segments;
for ([[maybe_unused]] const int ring : IndexRange(1, rings - 2)) {
const int next_ring_vert_index_start = ring_vert_index_start + segments;
const int next_ring_edge_index_start = ring_edge_index_start + segments * 2;
const int ring_vertical_edge_index_start = ring_edge_index_start + segments;
const int rings_vert_start = 1;
const int rings_edge_start = segments;
const int rings_loop_start = segments * 3;
for (const int ring : IndexRange(1, rings - 2)) {
const int ring_vert_start = rings_vert_start + (ring - 1) * segments;
const int ring_edge_start = rings_edge_start + (ring - 1) * segments * 2;
const int ring_loop_start = rings_loop_start + (ring - 1) * segments * 4;
const int next_ring_vert_start = ring_vert_start + segments;
const int next_ring_edge_start = ring_edge_start + segments * 2;
const int ring_vertical_edge_start = ring_edge_start + segments;
for (const int segment : IndexRange(segments)) {
const int loop_start = ring_loop_start + segment * 4;
const int segment_next = segment_next_or_first(segment);
MLoop &loop_a = loops[loop_index++];
loop_a.v = ring_vert_index_start + segment;
loop_a.e = ring_vertical_edge_index_start + segment;
MLoop &loop_b = loops[loop_index++];
loop_b.v = next_ring_vert_index_start + segment;
loop_b.e = next_ring_edge_index_start + segment;
MLoop &loop_c = loops[loop_index++];
loop_c.v = next_ring_vert_index_start + segment_next;
loop_c.e = ring_vertical_edge_index_start + segment_next;
MLoop &loop_d = loops[loop_index++];
loop_d.v = ring_vert_index_start + segment_next;
loop_d.e = ring_edge_index_start + segment;
loops[loop_start + 0].v = ring_vert_start + segment;
loops[loop_start + 0].e = ring_vertical_edge_start + segment;
loops[loop_start + 1].v = next_ring_vert_start + segment;
loops[loop_start + 1].e = next_ring_edge_start + segment;
loops[loop_start + 2].v = next_ring_vert_start + segment_next;
loops[loop_start + 2].e = ring_vertical_edge_start + segment_next;
loops[loop_start + 3].v = ring_vert_start + segment_next;
loops[loop_start + 3].e = ring_edge_start + segment;
}
ring_vert_index_start += segments;
ring_edge_index_start += segments * 2;
}
/* Add the triangles connected to the bottom vertex. */
const int bottom_loop_start = rings_loop_start + segments * (rings - 2) * 4;
const int last_edge_ring_start = segments * (rings - 2) * 2 + segments;
const int bottom_edge_fan_start = last_edge_ring_start + segments;
const int last_vert_index = sphere_vert_total(segments, rings) - 1;
const int last_vert_ring_start = last_vert_index - segments;
for (const int segment : IndexRange(segments)) {
const int loop_start = bottom_loop_start + segment * 3;
const int segment_next = segment_next_or_first(segment);
MLoop &loop_a = loops[loop_index++];
loop_a.v = last_vert_index;
loop_a.e = bottom_edge_fan_start + segment_next;
MLoop &loop_b = loops[loop_index++];
loop_b.v = last_vert_ring_start + segment_next;
loop_b.e = last_edge_ring_start + segment;
MLoop &loop_c = loops[loop_index++];
loop_c.v = last_vert_ring_start + segment;
loop_c.e = bottom_edge_fan_start + segment;
loops[loop_start + 0].v = last_vert_index;
loops[loop_start + 0].e = bottom_edge_fan_start + segment_next;
loops[loop_start + 1].v = last_vert_ring_start + segment_next;
loops[loop_start + 1].e = last_edge_ring_start + segment;
loops[loop_start + 2].v = last_vert_ring_start + segment;
loops[loop_start + 2].e = bottom_edge_fan_start + segment;
}
}
@@ -260,34 +263,39 @@ BLI_NOINLINE static void calculate_sphere_uvs(Mesh *mesh, const float segments,
"uv_map", ATTR_DOMAIN_CORNER);
MutableSpan<float2> uvs = uv_attribute.span;
int loop_index = 0;
const float dy = 1.0f / rings;
const float segments_inv = 1.0f / segments;
for (const int i_segment : IndexRange(segments)) {
const int loop_start = i_segment * 3;
const float segment = float(i_segment);
uvs[loop_index++] = float2((segment + 0.5f) * segments_inv, 0.0f);
uvs[loop_index++] = float2(segment * segments_inv, dy);
uvs[loop_index++] = float2((segment + 1.0f) * segments_inv, dy);
uvs[loop_start + 0] = float2((segment + 0.5f) * segments_inv, 0.0f);
uvs[loop_start + 1] = float2(segment * segments_inv, dy);
uvs[loop_start + 2] = float2((segment + 1.0f) * segments_inv, dy);
}
const int rings_loop_start = segments * 3;
for (const int i_ring : IndexRange(1, rings - 2)) {
const int ring_loop_start = rings_loop_start + (i_ring - 1) * segments * 4;
const float ring = float(i_ring);
for (const int i_segment : IndexRange(segments)) {
const int loop_start = ring_loop_start + i_segment * 4;
const float segment = float(i_segment);
uvs[loop_index++] = float2(segment * segments_inv, ring / rings);
uvs[loop_index++] = float2(segment * segments_inv, (ring + 1.0f) / rings);
uvs[loop_index++] = float2((segment + 1.0f) * segments_inv, (ring + 1.0f) / rings);
uvs[loop_index++] = float2((segment + 1.0f) * segments_inv, ring / rings);
uvs[loop_start + 0] = float2(segment * segments_inv, ring / rings);
uvs[loop_start + 1] = float2(segment * segments_inv, (ring + 1.0f) / rings);
uvs[loop_start + 2] = float2((segment + 1.0f) * segments_inv, (ring + 1.0f) / rings);
uvs[loop_start + 3] = float2((segment + 1.0f) * segments_inv, ring / rings);
}
}
const int bottom_loop_start = rings_loop_start + segments * (rings - 2) * 4;
for (const int i_segment : IndexRange(segments)) {
const int loop_start = bottom_loop_start + i_segment * 3;
const float segment = float(i_segment);
uvs[loop_index++] = float2((segment + 0.5f) * segments_inv, 1.0f);
uvs[loop_index++] = float2((segment + 1.0f) * segments_inv, 1.0f - dy);
uvs[loop_index++] = float2(segment * segments_inv, 1.0f - dy);
uvs[loop_start + 0] = float2((segment + 0.5f) * segments_inv, 1.0f);
uvs[loop_start + 1] = float2((segment + 1.0f) * segments_inv, 1.0f - dy);
uvs[loop_start + 2] = float2(segment * segments_inv, 1.0f - dy);
}
uv_attribute.finish();
@@ -321,6 +329,8 @@ static Mesh *create_uv_sphere_mesh(const float radius, const int segments, const
mesh->loose_edges_tag_none();
BLI_assert(BKE_mesh_is_valid(mesh));
return mesh;
}

View File

@@ -1052,10 +1052,10 @@ static void shader_node_disconnect_inactive_mix_branch(bNodeTree *ntree,
static void ntree_shader_disconnect_inactive_mix_branches(bNodeTree *ntree)
{
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
if (node->type == SH_NODE_MIX_SHADER) {
if (node->typeinfo->type == SH_NODE_MIX_SHADER) {
shader_node_disconnect_inactive_mix_branch(ntree, node, 0, 1, 2, true);
}
else if (node->type == SH_NODE_MIX) {
else if (node->typeinfo->type == SH_NODE_MIX) {
const NodeShaderMix *storage = static_cast<NodeShaderMix *>(node->storage);
if (storage->data_type == SOCK_FLOAT) {
shader_node_disconnect_inactive_mix_branch(ntree, node, 0, 2, 3, storage->clamp_factor);

View File

@@ -115,8 +115,8 @@ static const struct PyC_StringEnumItems pygpu_imagetype_items[] = {
{int(ImageType::FLOAT_1D), "FLOAT_1D"},
{int(ImageType::FLOAT_1D_ARRAY), "FLOAT_1D_ARRAY"},
{int(ImageType::FLOAT_2D), "FLOAT_2D"},
{int(ImageType::FLOAT_2D_ARRAY), "FLOAT"},
{int(ImageType::FLOAT_3D), "FLOAT_2D_ARRAY"},
{int(ImageType::FLOAT_2D_ARRAY), "FLOAT_2D_ARRAY"},
{int(ImageType::FLOAT_3D), "FLOAT_3D"},
{int(ImageType::FLOAT_CUBE), "FLOAT_CUBE"},
{int(ImageType::FLOAT_CUBE_ARRAY), "FLOAT_CUBE_ARRAY"},
{int(ImageType::INT_BUFFER), "INT_BUFFER"},

View File

@@ -279,25 +279,25 @@ enum {
NDOF_BUTTON_DOMINANT = 0x01a3, /* 419 */
NDOF_BUTTON_PLUS = 0x01a4, /* 420 */
NDOF_BUTTON_MINUS = 0x01a5, /* 421 */
/* General-purpose buttons. */
NDOF_BUTTON_1 = 0x01a6, /* 422 */
NDOF_BUTTON_2 = 0x01a7, /* 423 */
NDOF_BUTTON_3 = 0x01a8, /* 424 */
NDOF_BUTTON_4 = 0x01a9, /* 425 */
NDOF_BUTTON_5 = 0x01aa, /* 426 */
NDOF_BUTTON_6 = 0x01ab, /* 427 */
NDOF_BUTTON_7 = 0x01ac, /* 428 */
NDOF_BUTTON_8 = 0x01ad, /* 429 */
NDOF_BUTTON_9 = 0x01ae, /* 430 */
NDOF_BUTTON_10 = 0x01af, /* 431 */
/* more general-purpose buttons */
NDOF_BUTTON_A = 0x01b0, /* 432 */
NDOF_BUTTON_B = 0x01b1, /* 433 */
NDOF_BUTTON_C = 0x01b2, /* 434 */
/* Store/restore views. */
NDOF_BUTTON_V1 = 0x01b3, /* 435 */
NDOF_BUTTON_V2 = 0x01b4, /* 436 */
NDOF_BUTTON_V3 = 0x01b5, /* 437 */
NDOF_BUTTON_V1 = 0x01a6, /* 422 */
NDOF_BUTTON_V2 = 0x01a7, /* 423 */
NDOF_BUTTON_V3 = 0x01a8, /* 424 */
/* General-purpose buttons. */
NDOF_BUTTON_1 = 0x01aa, /* 426 */
NDOF_BUTTON_2 = 0x01ab, /* 427 */
NDOF_BUTTON_3 = 0x01ac, /* 428 */
NDOF_BUTTON_4 = 0x01ad, /* 429 */
NDOF_BUTTON_5 = 0x01ae, /* 430 */
NDOF_BUTTON_6 = 0x01af, /* 431 */
NDOF_BUTTON_7 = 0x01b0, /* 432 */
NDOF_BUTTON_8 = 0x01b1, /* 433 */
NDOF_BUTTON_9 = 0x01b2, /* 434 */
NDOF_BUTTON_10 = 0x01b3, /* 435 */
/* more general-purpose buttons */
NDOF_BUTTON_A = 0x01b4, /* 436 */
NDOF_BUTTON_B = 0x01b5, /* 437 */
NDOF_BUTTON_C = 0x01b6, /* 438 */
/* Disabled as GHOST converts these to keyboard events
* which use regular keyboard event handling logic. */
@@ -313,8 +313,8 @@ enum {
NDOF_BUTTON_CTRL = 0x01bd, /* 445 */
#endif
#define _NDOF_MAX NDOF_BUTTON_V3
#define _NDOF_BUTTON_MAX NDOF_BUTTON_V3
#define _NDOF_MAX NDOF_BUTTON_C
#define _NDOF_BUTTON_MAX NDOF_BUTTON_C
/* ********** End of Input devices. ********** */