Merge branch 'master' into sculpt-dev

This commit is contained in:
Pablo Dobarro 2021-01-09 17:56:44 +01:00
commit 38dce1d29d
85 changed files with 767 additions and 452 deletions

View File

@ -163,13 +163,13 @@ Now in the button's context menu select *Copy Data Path*, then paste the result
.. code-block:: python
bpy.context.active_object.modifiers["Subsurf"].levels
bpy.context.active_object.modifiers["Subdivision"].levels
Press :kbd:`Return` and you'll get the current value of 1. Now try changing the value to 2:
.. code-block:: python
bpy.context.active_object.modifiers["Subsurf"].levels = 2
bpy.context.active_object.modifiers["Subdivision"].levels = 2
You can see the value update in the Subdivision Surface modifier's UI as well as the cube.
@ -185,43 +185,31 @@ For example, if you want to access the texture of a brush via Python to adjust i
#. Start in the default scene and enable Sculpt Mode from the 3D Viewport header.
#. From the Sidebar expand the Brush Settings panel's *Texture* subpanel and add a new texture.
*Notice the texture data-block menu itself doesn't have very useful links (you can check the tooltips).*
#. The contrast setting isn't exposed in the Sidebar, so view the texture in the properties editor:
- In the properties editor select the Texture tab.
- Select brush texture.
- Expand the *Colors* panel to locate the *Contrast* number field.
#. The contrast setting isn't exposed in the Sidebar, so view the texture in the
:ref:`Properties Editor <blender_manual:bpy.types.Texture.contrast`
#. Open the context menu of the contrast field and select *Online Python Reference*.
This takes you to ``bpy.types.Texture.contrast``. Now you can see that ``contrast`` is a property of texture.
#. To find out how to access the texture from the brush check on the references at the bottom of the page.
Sometimes there are many references, and it may take some guesswork to find the right one,
but in this case it's ``Brush.texture``.
but in this case it's ``tool_settings.sculpt.brush.texture``.
#. Now you know that the texture can be accessed from ``bpy.data.brushes["BrushName"].texture``
but normally you *won't* want to access the brush by name, instead you want to access the active brush.
So the next step is to check on where brushes are accessed from via the references.
In this case there it is simply ``bpy.context.brush``.
Now you can use the Python console to form the nested properties needed to access brush textures contrast:
*Context -> Brush -> Texture -> Contrast*.
:menuselection:`Context --> Tool Settings --> Sculpt --> Brush --> Texture --> Contrast`.
Since the attribute for each is given along the way you can compose the data path in the Python console:
.. code-block:: python
bpy.context.brush.texture.contrast
There can be multiple ways to access the same data, which you choose often depends on the task.
An alternate path to access the same setting is:
.. code-block:: python
bpy.context.sculpt.brush.texture.contrast
bpy.context.tool_settings.sculpt.brush.texture.contrast
Or access the brush directly:
.. code-block:: python
bpy.data.brushes["BrushName"].texture.contrast
bpy.data.textures["Texture"].contrast
If you are writing a user tool normally you want to use the :mod:`bpy.context` since the user normally expects

View File

@ -35,12 +35,13 @@ but not to fully cover each topic.
A quick list of helpful things to know before starting:
- Blender uses Python 3.x; some online documentation still assumes version 2.x.
- The interactive console is great for testing one-liners.
It also has autocompletion so you can inspect the API quickly.
- Button tooltips show Python attributes and operator names.
- The context menu of buttons directly links to this API documentation.
- More operator examples can be found in the text editor's template menu.
- Enable :ref:`Developer Extra <blender_manual:prefs-interface-dev-extras`
and :ref:`Python Tooltips <blender_manual:prefs-interface-tooltips-python>`.
- The :ref:`Python Console <blender_manual:bpy.types.SpaceConsole>`
is great for testing one-liners; it has autocompletion so you can inspect the API quickly.
- Button tooltips show Python attributes and operator names (when enabled see above).
- The context menu of buttons directly links to this API documentation (when enabled see above).
- Many python examples can be found in the text editor's template menu.
- To examine further scripts distributed with Blender, see:
- ``scripts/startup/bl_ui`` for the user interface.

View File

@ -24,10 +24,9 @@ The three main use cases for the terminal are:
- If the script runs for too long or you accidentally enter an infinite loop,
:kbd:`Ctrl-C` in the terminal (:kbd:`Ctrl-Break` on Windows) will quit the script early.
.. note::
.. seealso::
For Linux and macOS users this means starting the terminal first, then running Blender from within it.
On Windows the terminal can be enabled from the Help menu.
:ref:`blender_manual:command_line-launch-index`.
Interface Tricks

View File

@ -1514,11 +1514,24 @@ class OptiXDevice : public CUDADevice {
}
else {
unsigned int num_instances = 0;
unsigned int max_num_instances = 0xFFFFFFFF;
bvh_optix->as_data.free();
bvh_optix->traversable_handle = 0;
bvh_optix->motion_transform_data.free();
optixDeviceContextGetProperty(context,
OPTIX_DEVICE_PROPERTY_LIMIT_MAX_INSTANCE_ID,
&max_num_instances,
sizeof(max_num_instances));
// Do not count first bit, which is used to distinguish instanced and non-instanced objects
max_num_instances >>= 1;
if (bvh->objects.size() > max_num_instances) {
progress.set_error(
"Failed to build OptiX acceleration structure because there are too many instances");
return;
}
// Fill instance descriptions
# if OPTIX_ABI_VERSION < 41
device_vector<OptixAabb> aabbs(this, "optix tlas aabbs", MEM_READ_ONLY);
@ -1572,8 +1585,8 @@ class OptiXDevice : public CUDADevice {
instance.transform[5] = 1.0f;
instance.transform[10] = 1.0f;
// Set user instance ID to object index
instance.instanceId = ob->get_device_index();
// Set user instance ID to object index (but leave low bit blank)
instance.instanceId = ob->get_device_index() << 1;
// Have to have at least one bit in the mask, or else instance would always be culled
instance.visibilityMask = 1;
@ -1679,9 +1692,9 @@ class OptiXDevice : public CUDADevice {
else {
// Disable instance transform if geometry already has it applied to vertex data
instance.flags = OPTIX_INSTANCE_FLAG_DISABLE_TRANSFORM;
// Non-instanced objects read ID from prim_object, so
// distinguish them from instanced objects with high bit set
instance.instanceId |= 0x800000;
// Non-instanced objects read ID from 'prim_object', so distinguish
// them from instanced objects with the low bit set
instance.instanceId |= 1;
}
}
}

View File

@ -45,13 +45,12 @@ template<bool always = false> ccl_device_forceinline uint get_object_id()
uint object = optixGetInstanceId();
#endif
// Choose between always returning object ID or only for instances
if (always)
// Can just remove the high bit since instance always contains object ID
return object & 0x7FFFFF;
// Set to OBJECT_NONE if this is not an instanced object
else if (object & 0x800000)
object = OBJECT_NONE;
return object;
if (always || (object & 1) == 0)
// Can just remove the low bit since instance always contains object ID
return object >> 1;
else
// Set to OBJECT_NONE if this is not an instanced object
return OBJECT_NONE;
}
extern "C" __global__ void __raygen__kernel_optix_path_trace()

View File

@ -17,7 +17,7 @@ inkscape_bin = os.environ.get("INKSCAPE_BIN", "inkscape")
blender_bin = os.environ.get("BLENDER_BIN", "blender")
if sys.platform == 'darwin':
inkscape_app_path = '/Applications/Inkscape.app/Contents/Resources/script'
inkscape_app_path = '/Applications/Inkscape.app/Contents/MacOS/inkscape'
if os.path.exists(inkscape_app_path):
inkscape_bin = inkscape_app_path
blender_app_path = '/Applications/Blender.app/Contents/MacOS/Blender'
@ -29,8 +29,8 @@ cmd = (
os.path.join(BASEDIR, "blender_icons.svg"),
"--export-width=602",
"--export-height=640",
"--without-gui",
"--export-png=" + os.path.join(BASEDIR, "blender_icons16.png"),
"--export-type=png",
"--export-filename=" + os.path.join(BASEDIR, "blender_icons16.png"),
)
run(cmd)
@ -39,8 +39,8 @@ cmd = (
os.path.join(BASEDIR, "blender_icons.svg"),
"--export-width=1204",
"--export-height=1280",
"--without-gui",
"--export-png=" + os.path.join(BASEDIR, "blender_icons32.png"),
"--export-type=png",
"--export-filename=" + os.path.join(BASEDIR, "blender_icons32.png"),
)
run(cmd)

View File

@ -10,7 +10,7 @@ BASEDIR = os.path.abspath(os.path.dirname(__file__))
inkscape_path = 'inkscape'
if sys.platform == 'darwin':
inkscape_app_path = '/Applications/Inkscape.app/Contents/Resources/script'
inkscape_app_path = '/Applications/Inkscape.app/Contents/MacOS/inkscape'
if os.path.exists(inkscape_app_path):
inkscape_path = inkscape_app_path
@ -19,7 +19,7 @@ cmd = (
os.path.join(BASEDIR, "prvicons.svg"),
"--export-width=1792",
"--export-height=256",
"--without-gui",
"--export-png=" + os.path.join(BASEDIR, "prvicons.png"),
"--export-type=png",
"--export-filename=" + os.path.join(BASEDIR, "prvicons.png"),
)
subprocess.check_call(cmd)

View File

@ -4566,7 +4566,7 @@ def km_mesh(params):
op_menu("VIEW3D_MT_edit_mesh_merge", {"type": 'M', "value": 'PRESS'}),
op_menu("VIEW3D_MT_edit_mesh_split", {"type": 'M', "value": 'PRESS', "alt": True}),
("transform.shrink_fatten", {"type": 'S', "value": 'PRESS', "alt": True}, None),
("mesh.edge_face_add", {"type": 'F', "value": 'PRESS'}, None),
("mesh.edge_face_add", {"type": 'F', "value": 'PRESS', "repeat": True}, None),
("mesh.duplicate_move", {"type": 'D', "value": 'PRESS', "shift": True}, None),
op_menu("VIEW3D_MT_mesh_add", {"type": 'A', "value": 'PRESS', "shift": True}),
("mesh.separate", {"type": 'P', "value": 'PRESS'}, None),

View File

@ -27,6 +27,9 @@ def geometry_node_group_empty_new(context):
output_node = group.nodes.new('NodeGroupOutput')
output_node.is_active_output = True
input_node.select = False
output_node.select = False
input_node.location.x = -200 - input_node.width
output_node.location.x = 200
@ -38,8 +41,8 @@ def geometry_node_group_empty_new(context):
def geometry_modifier_poll(context) -> bool:
ob = context.object
# Test object support for geometry node modifier (No volume or hair object support yet)
if not ob or ob.type not in {'MESH', 'CURVE', 'SURFACE', 'META', 'FONT', 'POINTCLOUD'}:
# Test object support for geometry node modifier (No volume, curve, or hair object support yet)
if not ob or ob.type not in {'MESH', 'POINTCLOUD'}:
return False
return True
@ -62,9 +65,6 @@ class NewGeometryNodesModifier(bpy.types.Operator):
if not modifier:
return {'CANCELLED'}
group = geometry_node_group_empty_new(context)
modifier.node_group = group
return {'FINISHED'}

View File

@ -969,9 +969,9 @@ class PREFERENCES_OT_app_template_install(Operator):
# Studio Light Operations
class PREFERENCES_OT_studiolight_install(Operator):
"""Install a user defined studio light"""
"""Install a user defined light"""
bl_idname = "preferences.studiolight_install"
bl_label = "Install Custom Studio Light"
bl_label = "Install Light"
files: CollectionProperty(
name="File Path",
@ -981,7 +981,7 @@ class PREFERENCES_OT_studiolight_install(Operator):
subtype='DIR_PATH',
)
filter_folder: BoolProperty(
name="Filter folders",
name="Filter Folders",
default=True,
options={'HIDDEN'},
)
@ -992,9 +992,9 @@ class PREFERENCES_OT_studiolight_install(Operator):
type: EnumProperty(
name="Type",
items=(
('MATCAP', "MatCap", ""),
('WORLD', "World", ""),
('STUDIO', "Studio", ""),
('MATCAP', "MatCap", "Install custom MatCaps"),
('WORLD', "World", "Install custom HDRIs"),
('STUDIO', "Studio", "Install custom Studio Lights"),
)
)

View File

@ -974,7 +974,7 @@ class WM_OT_path_open(Operator):
return {'FINISHED'}
def _wm_doc_get_id(doc_id, do_url=True, url_prefix=""):
def _wm_doc_get_id(doc_id, do_url=True, url_prefix="", report=None):
def operator_exists_pair(a, b):
# Not fast, this is only for docs.
@ -1025,6 +1025,11 @@ def _wm_doc_get_id(doc_id, do_url=True, url_prefix=""):
# Check class for dynamically registered types.
rna_class = bpy.types.PropertyGroup.bl_rna_get_subclass_py(class_name)
if rna_class is None:
if report is not None:
report({'ERROR'}, iface_("Type \"%s\" can not be found") % class_name)
return None
# Detect if this is a inherited member and use that name instead.
rna_parent = rna_class.bl_rna
rna_prop = rna_parent.properties.get(class_prop)
@ -1084,9 +1089,9 @@ class WM_OT_doc_view_manual(Operator):
return url
def execute(self, _context):
rna_id = _wm_doc_get_id(self.doc_id, do_url=False)
rna_id = _wm_doc_get_id(self.doc_id, do_url=False, report=self.report)
if rna_id is None:
return {'PASS_THROUGH'}
return {'CANCELLED'}
url = self._lookup_rna_url(rna_id)
@ -1118,9 +1123,9 @@ class WM_OT_doc_view(Operator):
_prefix = ("https://docs.blender.org/api/master")
def execute(self, _context):
url = _wm_doc_get_id(self.doc_id, do_url=True, url_prefix=self._prefix)
url = _wm_doc_get_id(self.doc_id, do_url=True, url_prefix=self._prefix, report=self.report)
if url is None:
return {'PASS_THROUGH'}
return {'CANCELLED'}
import webbrowser
webbrowser.open(url)

View File

@ -486,14 +486,12 @@ class RENDER_PT_eevee_film(RenderButtonsPanel, Panel):
col.prop(rd, "film_transparent", text="Transparent")
col = layout.column(align=False, heading="Overscan")
col.use_property_decorate = False
row = col.row(align=True)
sub = row.row(align=True)
sub.prop(props, "use_overscan", text="")
sub = sub.row(align=True)
sub.active = props.use_overscan
sub.prop(props, "overscan_size", text="")
row.prop_decorator(props, "overscan_size")
class RENDER_PT_eevee_hair(RenderButtonsPanel, Panel):

View File

@ -412,7 +412,19 @@ class SEQUENCER_MT_view(Menu):
layout.separator()
layout.prop(st, "show_seconds")
layout.prop(st, "show_markers")
layout.menu("SEQUENCER_MT_view_cache", text="Show Cache")
if context.preferences.view.show_developer_ui:
layout.menu("SEQUENCER_MT_view_cache", text="Show Cache")
if is_preview:
layout.separator()
if st.display_mode == 'IMAGE':
layout.prop(st, "use_zoom_to_fit")
layout.prop(ed, "show_overlay", text="Show Frame Overlay")
layout.prop(st, "show_safe_areas", text="Show Safe Areas")
layout.prop(st, "show_metadata", text="Show Metadata")
layout.prop(st, "show_annotation", text="Show Annotations")
elif st.display_mode == 'WAVEFORM':
layout.prop(st, "show_separate_color", text="Show Separate Color Channels")
layout.separator()
@ -1877,11 +1889,12 @@ class SEQUENCER_PT_adjust_color(SequencerButtonsPanel, Panel):
class SEQUENCER_PT_cache_settings(SequencerButtonsPanel, Panel):
bl_label = "Cache Settings"
bl_category = "Proxy & Cache"
bl_category = "Cache"
@classmethod
def poll(cls, context):
return cls.has_sequencer(context) and context.scene.sequence_editor
show_developer_ui = context.preferences.view.show_developer_ui
return cls.has_sequencer(context) and context.scene.sequence_editor and show_developer_ui
def draw(self, context):
layout = self.layout
@ -1900,7 +1913,7 @@ class SEQUENCER_PT_cache_settings(SequencerButtonsPanel, Panel):
class SEQUENCER_PT_proxy_settings(SequencerButtonsPanel, Panel):
bl_label = "Proxy Settings"
bl_category = "Proxy & Cache"
bl_category = "Proxy"
@classmethod
def poll(cls, context):
@ -1925,7 +1938,7 @@ class SEQUENCER_PT_proxy_settings(SequencerButtonsPanel, Panel):
class SEQUENCER_PT_strip_proxy(SequencerButtonsPanel, Panel):
bl_label = "Strip Proxy & Timecode"
bl_category = "Proxy & Cache"
bl_category = "Proxy"
@classmethod
def poll(cls, context):
@ -1987,14 +2000,15 @@ class SEQUENCER_PT_strip_proxy(SequencerButtonsPanel, Panel):
class SEQUENCER_PT_strip_cache(SequencerButtonsPanel, Panel):
bl_label = "Strip Cache"
bl_category = "Proxy & Cache"
bl_category = "Cache"
bl_options = {'DEFAULT_CLOSED'}
@classmethod
def poll(cls, context):
show_developer_ui = context.preferences.view.show_developer_ui
if not cls.has_sequencer(context):
return False
if act_strip(context) is not None:
if act_strip(context) is not None and show_developer_ui:
return True
return False

View File

@ -1547,12 +1547,22 @@ class _defs_weight_paint:
@ToolDef.from_fn
def sample_weight():
def draw_settings(context, layout, tool):
if context.tool_settings.unified_paint_settings.use_unified_weight:
weight = context.tool_settings.unified_paint_settings.weight
elif context.tool_settings.weight_paint.brush:
weight = context.tool_settings.weight_paint.brush.weight
else:
return
layout.label(text="Weight: %.3f" % weight)
return dict(
idname="builtin.sample_weight",
label="Sample Weight",
icon="ops.paint.weight_sample",
cursor='EYEDROPPER',
widget=None,
keymap=(),
draw_settings=draw_settings
)
@ToolDef.from_fn
@ -1561,6 +1571,7 @@ class _defs_weight_paint:
idname="builtin.sample_vertex_group",
label="Sample Vertex Group",
icon="ops.paint.weight_sample_group",
cursor='EYEDROPPER',
widget=None,
keymap=(),
)

View File

@ -39,7 +39,7 @@ extern "C" {
/* Blender file format version. */
#define BLENDER_FILE_VERSION BLENDER_VERSION
#define BLENDER_FILE_SUBVERSION 9
#define BLENDER_FILE_SUBVERSION 10
/* Minimum Blender version that supports reading file written with the current
* version. Older Blender versions will test this and show a warning if the file

View File

@ -49,6 +49,7 @@ int BKE_geometry_set_instances(const struct GeometrySet *geometry_set,
float (**r_positions)[3],
float (**r_rotations)[3],
float (**r_scales)[3],
int **r_ids,
struct InstancedData **r_instanced_data);
#ifdef __cplusplus

View File

@ -364,6 +364,7 @@ class InstancesComponent : public GeometryComponent {
blender::Vector<blender::float3> positions_;
blender::Vector<blender::float3> rotations_;
blender::Vector<blender::float3> scales_;
blender::Vector<int> ids_;
blender::Vector<InstancedData> instanced_data_;
public:
@ -375,20 +376,24 @@ class InstancesComponent : public GeometryComponent {
void add_instance(Object *object,
blender::float3 position,
blender::float3 rotation = {0, 0, 0},
blender::float3 scale = {1, 1, 1});
blender::float3 scale = {1, 1, 1},
const int id = -1);
void add_instance(Collection *collection,
blender::float3 position,
blender::float3 rotation = {0, 0, 0},
blender::float3 scale = {1, 1, 1});
blender::float3 scale = {1, 1, 1},
const int id = -1);
void add_instance(InstancedData data,
blender::float3 position,
blender::float3 rotation,
blender::float3 scale);
blender::float3 scale,
const int id = -1);
blender::Span<InstancedData> instanced_data() const;
blender::Span<blender::float3> positions() const;
blender::Span<blender::float3> rotations() const;
blender::Span<blender::float3> scales() const;
blender::Span<int> ids() const;
blender::MutableSpan<blender::float3> positions();
int instances_amount() const;

View File

@ -229,7 +229,7 @@ struct Mesh *BKE_mesh_create_derived_for_modifier(struct Depsgraph *depsgraph,
struct Scene *scene,
struct Object *ob_eval,
struct ModifierData *md_eval,
int build_shapekey_layers);
const bool build_shapekey_layers);
/* Copies a nomain-Mesh into an existing Mesh. */
void BKE_mesh_nomain_to_mesh(struct Mesh *mesh_src,

View File

@ -110,6 +110,8 @@ void BKE_toolsettings_free(struct ToolSettings *toolsettings);
struct Scene *BKE_scene_duplicate(struct Main *bmain, struct Scene *sce, eSceneCopyMethod type);
void BKE_scene_groups_relink(struct Scene *sce);
bool BKE_scene_can_be_removed(const struct Main *bmain, const struct Scene *scene);
bool BKE_scene_has_view_layer(const struct Scene *scene, const struct ViewLayer *layer);
struct Scene *BKE_scene_find_from_collection(const struct Main *bmain,
const struct Collection *collection);

View File

@ -140,11 +140,8 @@ typedef struct UndoType {
UndoTypeForEachIDRefFn foreach_ID_ref_fn,
void *user_data);
/**
* This undo type `encode` callback needs a valid context, it will fail otherwise.
* \note Callback is still supposed to properly deal with a NULL context pointer.
*/
bool use_context_for_encode;
/** Information for the generic undo system to refine handling of this specific undo type. */
uint flags;
/**
* The size of the undo struct 'inherited' from #UndoStep for that specific type. Used for
@ -152,6 +149,15 @@ typedef struct UndoType {
size_t step_size;
} UndoType;
/** #UndoType.flag bitflags. */
typedef enum UndoTypeFlags {
/**
* This undo type `encode` callback needs a valid context, it will fail otherwise.
* \note Callback is still supposed to properly deal with a NULL context pointer.
*/
UNDOTYPE_FLAG_NEED_CONTEXT_FOR_ENCODE = 1 << 0,
} UndoTypeFlags;
/* Expose since we need to perform operations on specific undo types (rarely). */
extern const UndoType *BKE_UNDOSYS_TYPE_IMAGE;
extern const UndoType *BKE_UNDOSYS_TYPE_MEMFILE;

View File

@ -417,7 +417,7 @@ void BKE_blender_atexit_unregister(void (*func)(void *user_data), const void *us
free(ae);
return;
}
ae_p = &ae;
ae_p = &ae->next;
ae = ae->next;
}
}

View File

@ -1002,6 +1002,23 @@ static int cloth_selfcollision_response_static(ClothModifierData *clmd,
# pragma GCC diagnostic pop
#endif
static bool cloth_bvh_collision_is_active(const ClothModifierData *UNUSED(clmd),
const Cloth *cloth,
const MVertTri *tri_a)
{
const ClothVertex *verts = cloth->verts;
/* Fully pinned triangles don't need collision processing. */
const int flags_a = verts[tri_a->tri[0]].flags & verts[tri_a->tri[1]].flags &
verts[tri_a->tri[2]].flags;
if (flags_a & CLOTH_VERT_FLAG_PINNED) {
return false;
}
return true;
}
static void cloth_collision(void *__restrict userdata,
const int index,
const TaskParallelTLS *__restrict UNUSED(tls))
@ -1059,13 +1076,31 @@ static void cloth_collision(void *__restrict userdata,
}
}
static bool cloth_bvh_selfcollision_is_active(const Cloth *cloth,
static bool cloth_bvh_selfcollision_is_active(const ClothModifierData *clmd,
const Cloth *cloth,
const MVertTri *tri_a,
const MVertTri *tri_b,
bool sewing_active)
const MVertTri *tri_b)
{
const ClothVertex *verts = cloth->verts;
/* Skip when either triangle is excluded. */
const int flags_a = verts[tri_a->tri[0]].flags & verts[tri_a->tri[1]].flags &
verts[tri_a->tri[2]].flags;
const int flags_b = verts[tri_b->tri[0]].flags & verts[tri_b->tri[1]].flags &
verts[tri_b->tri[2]].flags;
if ((flags_a | flags_b) & CLOTH_VERT_FLAG_NOSELFCOLL) {
return false;
}
/* Skip when both triangles are pinned. */
if ((flags_a & flags_b) & CLOTH_VERT_FLAG_PINNED) {
return false;
}
/* Ignore overlap of neighboring triangles and triangles connected by a sewing edge. */
bool sewing_active = (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_SEW);
for (uint i = 0; i < 3; i++) {
for (uint j = 0; j < 3; j++) {
if (tri_a->tri[i] == tri_b->tri[j]) {
@ -1080,12 +1115,6 @@ static bool cloth_bvh_selfcollision_is_active(const Cloth *cloth,
}
}
if (((verts[tri_a->tri[0]].flags & verts[tri_a->tri[1]].flags & verts[tri_a->tri[2]].flags) |
(verts[tri_b->tri[0]].flags & verts[tri_b->tri[1]].flags & verts[tri_b->tri[2]].flags)) &
CLOTH_VERT_FLAG_NOSELFCOLL) {
return false;
}
return true;
}
@ -1106,10 +1135,7 @@ static void cloth_selfcollision(void *__restrict userdata,
tri_a = &clmd->clothObject->tri[data->overlap[index].indexA];
tri_b = &clmd->clothObject->tri[data->overlap[index].indexB];
#ifdef DEBUG
bool sewing_active = (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_SEW);
BLI_assert(cloth_bvh_selfcollision_is_active(clmd->clothObject, tri_a, tri_b, sewing_active));
#endif
BLI_assert(cloth_bvh_selfcollision_is_active(clmd, clmd->clothObject, tri_a, tri_b));
/* Compute distance and normal. */
distance = compute_collision_point_tri_tri(verts1[tri_a->tri[0]].tx,
@ -1508,6 +1534,18 @@ static int cloth_bvh_selfcollisions_resolve(ClothModifierData *clmd,
return ret;
}
static bool cloth_bvh_obj_overlap_cb(void *userdata,
int index_a,
int UNUSED(index_b),
int UNUSED(thread))
{
ClothModifierData *clmd = (ClothModifierData *)userdata;
struct Cloth *clothObject = clmd->clothObject;
const MVertTri *tri_a = &clothObject->tri[index_a];
return cloth_bvh_collision_is_active(clmd, clothObject, tri_a);
}
static bool cloth_bvh_self_overlap_cb(void *userdata, int index_a, int index_b, int UNUSED(thread))
{
/* No need for equal combinations (eg. (0,1) & (1,0)). */
@ -1518,9 +1556,7 @@ static bool cloth_bvh_self_overlap_cb(void *userdata, int index_a, int index_b,
tri_a = &clothObject->tri[index_a];
tri_b = &clothObject->tri[index_b];
bool sewing_active = (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_SEW);
if (cloth_bvh_selfcollision_is_active(clothObject, tri_a, tri_b, sewing_active)) {
if (cloth_bvh_selfcollision_is_active(clmd, clothObject, tri_a, tri_b)) {
return true;
}
}
@ -1578,8 +1614,11 @@ int cloth_bvh_collision(
/* Move object to position (step) in time. */
collision_move_object(collmd, step + dt, step, false);
overlap_obj[i] = BLI_bvhtree_overlap(
cloth_bvh, collmd->bvhtree, &coll_counts_obj[i], NULL, NULL);
overlap_obj[i] = BLI_bvhtree_overlap(cloth_bvh,
collmd->bvhtree,
&coll_counts_obj[i],
is_hair ? NULL : cloth_bvh_obj_overlap_cb,
clmd);
}
}
}

View File

@ -476,34 +476,38 @@ void InstancesComponent::clear()
void InstancesComponent::add_instance(Object *object,
blender::float3 position,
blender::float3 rotation,
blender::float3 scale)
blender::float3 scale,
const int id)
{
InstancedData data;
data.type = INSTANCE_DATA_TYPE_OBJECT;
data.data.object = object;
this->add_instance(data, position, rotation, scale);
this->add_instance(data, position, rotation, scale, id);
}
void InstancesComponent::add_instance(Collection *collection,
blender::float3 position,
blender::float3 rotation,
blender::float3 scale)
blender::float3 scale,
const int id)
{
InstancedData data;
data.type = INSTANCE_DATA_TYPE_COLLECTION;
data.data.collection = collection;
this->add_instance(data, position, rotation, scale);
this->add_instance(data, position, rotation, scale, id);
}
void InstancesComponent::add_instance(InstancedData data,
blender::float3 position,
blender::float3 rotation,
blender::float3 scale)
blender::float3 scale,
const int id)
{
instanced_data_.append(data);
positions_.append(position);
rotations_.append(rotation);
scales_.append(scale);
ids_.append(id);
}
Span<InstancedData> InstancesComponent::instanced_data() const
@ -516,16 +520,21 @@ Span<float3> InstancesComponent::positions() const
return positions_;
}
blender::Span<blender::float3> InstancesComponent::rotations() const
Span<float3> InstancesComponent::rotations() const
{
return rotations_;
}
blender::Span<blender::float3> InstancesComponent::scales() const
Span<float3> InstancesComponent::scales() const
{
return scales_;
}
Span<int> InstancesComponent::ids() const
{
return ids_;
}
MutableSpan<float3> InstancesComponent::positions()
{
return positions_;
@ -565,6 +574,7 @@ int BKE_geometry_set_instances(const GeometrySet *geometry_set,
float (**r_positions)[3],
float (**r_rotations)[3],
float (**r_scales)[3],
int **r_ids,
InstancedData **r_instanced_data)
{
const InstancesComponent *component = geometry_set->get_component_for_read<InstancesComponent>();
@ -574,6 +584,8 @@ int BKE_geometry_set_instances(const GeometrySet *geometry_set,
*r_positions = (float(*)[3])component->positions().data();
*r_rotations = (float(*)[3])component->rotations().data();
*r_scales = (float(*)[3])component->scales().data();
*r_ids = (int *)component->ids().data();
*r_instanced_data = (InstancedData *)component->instanced_data().data();
*r_instanced_data = (InstancedData *)component->instanced_data().data();
return component->instances_amount();
}

View File

@ -1407,7 +1407,7 @@ Mesh *BKE_mesh_create_derived_for_modifier(struct Depsgraph *depsgraph,
Scene *scene,
Object *ob_eval,
ModifierData *md_eval,
int build_shapekey_layers)
const bool build_shapekey_layers)
{
Mesh *me = ob_eval->runtime.data_orig ? ob_eval->runtime.data_orig : ob_eval->data;
const ModifierTypeInfo *mti = BKE_modifier_get_info(md_eval->type);

View File

@ -816,9 +816,14 @@ static void make_duplis_instances_component(const DupliContext *ctx)
float(*positions)[3];
float(*rotations)[3];
float(*scales)[3];
int *ids;
InstancedData *instanced_data;
const int amount = BKE_geometry_set_instances(
ctx->object->runtime.geometry_set_eval, &positions, &rotations, &scales, &instanced_data);
const int amount = BKE_geometry_set_instances(ctx->object->runtime.geometry_set_eval,
&positions,
&rotations,
&scales,
&ids,
&instanced_data);
for (int i = 0; i < amount; i++) {
InstancedData *data = &instanced_data[i];
@ -831,17 +836,19 @@ static void make_duplis_instances_component(const DupliContext *ctx)
mul_m4_m4m4(instance_offset_matrix, rotation_matrix, scale_matrix);
copy_v3_v3(instance_offset_matrix[3], positions[i]);
const int id = ids[i] != -1 ? ids[i] : i;
if (data->type == INSTANCE_DATA_TYPE_OBJECT) {
Object *object = data->data.object;
if (object != NULL) {
float matrix[4][4];
mul_m4_m4m4(matrix, ctx->object->obmat, instance_offset_matrix);
make_dupli(ctx, object, matrix, i);
make_dupli(ctx, object, matrix, id);
float space_matrix[4][4];
mul_m4_m4m4(space_matrix, instance_offset_matrix, object->imat);
mul_m4_m4_pre(space_matrix, ctx->object->obmat);
make_recursive_duplis(ctx, object, space_matrix, i);
make_recursive_duplis(ctx, object, space_matrix, id);
}
}
else if (data->type == INSTANCE_DATA_TYPE_COLLECTION) {
@ -862,8 +869,8 @@ static void make_duplis_instances_component(const DupliContext *ctx)
float instance_matrix[4][4];
mul_m4_m4m4(instance_matrix, collection_matrix, object->obmat);
make_dupli(ctx, object, instance_matrix, i);
make_recursive_duplis(ctx, object, collection_matrix, i);
make_dupli(ctx, object, instance_matrix, id);
make_recursive_duplis(ctx, object, collection_matrix, id);
}
FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_END;
}

View File

@ -1904,7 +1904,6 @@ Scene *BKE_scene_duplicate(Main *bmain, Scene *sce, eSceneCopyMethod type)
sce_copy->id.properties = IDP_CopyProperty(sce->id.properties);
}
MEM_freeN(sce_copy->toolsettings);
BKE_sound_destroy_scene(sce_copy);
/* copy color management settings */
@ -1929,6 +1928,7 @@ Scene *BKE_scene_duplicate(Main *bmain, Scene *sce, eSceneCopyMethod type)
sce_copy->display = sce->display;
/* tool settings */
BKE_toolsettings_free(sce_copy->toolsettings);
sce_copy->toolsettings = BKE_toolsettings_copy(sce->toolsettings, 0);
/* make a private copy of the avicodecdata */
@ -2032,6 +2032,21 @@ void BKE_scene_groups_relink(Scene *sce)
}
}
bool BKE_scene_can_be_removed(const Main *bmain, const Scene *scene)
{
/* Linked scenes can always be removed. */
if (ID_IS_LINKED(scene)) {
return true;
}
/* Local scenes can only be removed, when there is at least one local scene left. */
LISTBASE_FOREACH (Scene *, other_scene, &bmain->scenes) {
if (other_scene != scene && !ID_IS_LINKED(other_scene)) {
return true;
}
}
return false;
}
Scene *BKE_scene_add(Main *bmain, const char *name)
{
Scene *sce;

View File

@ -252,9 +252,8 @@ static void undosys_stack_validate(UndoStack *ustack, bool expect_non_empty)
}
}
#else
static void undosys_stack_validate(UndoStack *ustack, bool expect_non_empty)
static void undosys_stack_validate(UndoStack *UNUSED(ustack), bool UNUSED(expect_non_empty))
{
UNUSED_VARS(ustack, expect_non_empty);
}
#endif
@ -501,7 +500,7 @@ UndoPushReturn BKE_undosys_step_push_with_type(UndoStack *ustack,
const char *name,
const UndoType *ut)
{
BLI_assert(ut->use_context_for_encode == false || C != NULL);
BLI_assert((ut->flags & UNDOTYPE_FLAG_NEED_CONTEXT_FOR_ENCODE) == 0 || C != NULL);
UNDO_NESTED_ASSERT(false);
undosys_stack_validate(ustack, false);
@ -676,9 +675,11 @@ bool BKE_undosys_step_undo_with_data_ex(UndoStack *ustack,
bool use_skip)
{
UNDO_NESTED_ASSERT(false);
if (us) {
undosys_stack_validate(ustack, true);
if (us == NULL) {
return false;
}
undosys_stack_validate(ustack, true);
UndoStep *us_prev = us ? us->prev : NULL;
if (us) {
/* The current state is a copy, we need to load the previous state. */
@ -754,6 +755,11 @@ bool BKE_undosys_step_redo_with_data_ex(UndoStack *ustack,
bool use_skip)
{
UNDO_NESTED_ASSERT(false);
if (us == NULL) {
return false;
}
undosys_stack_validate(ustack, true);
UndoStep *us_next = us ? us->next : NULL;
/* Unlike undo accumulate, we always use the next. */
us = us_next;

View File

@ -699,6 +699,16 @@ static void do_versions_291_fcurve_handles_limit(FCurve *fcu)
}
}
static void do_versions_strip_cache_settings_recursive(const ListBase *seqbase)
{
LISTBASE_FOREACH (Sequence *, seq, seqbase) {
seq->cache_flag = 0;
if (seq->type == SEQ_TYPE_META) {
do_versions_strip_cache_settings_recursive(&seq->seqbase);
}
}
}
/* NOLINTNEXTLINE: readability-function-size */
void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain)
{
@ -1480,23 +1490,7 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
/**
* Versioning code until next subversion bump goes here.
*
* \note Be sure to check when bumping the version:
* - "versioning_userdef.c", #blo_do_versions_userdef
* - "versioning_userdef.c", #do_versions_theme
*
* \note Keep this message at the bottom of the function.
*/
{
/* Keep this block, even when empty. */
if (!DNA_struct_elem_find(fd->filesdna, "Brush", "CurveMapping", "*pressure_size_curve")) {
LISTBASE_FOREACH (Brush *, br, &bmain->brushes) {
BKE_brush_default_input_curves_set(br);
}
}
if (!MAIN_VERSION_ATLEAST(bmain, 292, 10)) {
if (!DNA_struct_find(fd->filesdna, "NodeSetAlpha")) {
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
bNodeTree *nodetree = scene->nodetree;
@ -1515,4 +1509,31 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
}
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
Editing *ed = SEQ_editing_get(scene, false);
if (ed == NULL) {
continue;
}
ed->cache_flag = (SEQ_CACHE_STORE_RAW | SEQ_CACHE_STORE_FINAL_OUT);
do_versions_strip_cache_settings_recursive(&ed->seqbase);
}
/**
* Versioning code until next subversion bump goes here.
*
* \note Be sure to check when bumping the version:
* - "versioning_userdef.c", #blo_do_versions_userdef
* - "versioning_userdef.c", #do_versions_theme
*
* \note Keep this message at the bottom of the function.
*/
{
/* Keep this block, even when empty. */
if (!DNA_struct_elem_find(fd->filesdna, "Brush", "CurveMapping", "*pressure_size_curve")) {
LISTBASE_FOREACH (Brush *, br, &bmain->brushes) {
BKE_brush_default_input_curves_set(br);
}
}
}
}

View File

@ -330,9 +330,17 @@ static DRWVolumeGrid *volume_grid_cache_get(Volume *volume,
format,
GPU_DATA_FLOAT,
dense_grid.voxels);
GPU_texture_swizzle_set(cache_grid->texture, (channels == 3) ? "rgb1" : "rrr1");
GPU_texture_wrap_mode(cache_grid->texture, false, false);
BKE_volume_dense_float_grid_clear(&dense_grid);
/* The texture can be null if the resolution along one axis is larger than
* GL_MAX_3D_TEXTURE_SIZE. */
if (cache_grid->texture != NULL) {
GPU_texture_swizzle_set(cache_grid->texture, (channels == 3) ? "rgb1" : "rrr1");
GPU_texture_wrap_mode(cache_grid->texture, false, false);
BKE_volume_dense_float_grid_clear(&dense_grid);
}
else {
MEM_freeN(dense_grid.voxels);
printf("Error: Could not allocate 3D texture for volume.\n");
}
}
/* Free grid from memory if it wasn't previously loaded. */

View File

@ -249,7 +249,7 @@ void ED_armature_undosys_type(UndoType *ut)
ut->step_foreach_ID_ref = armature_undosys_foreach_ID_ref;
ut->use_context_for_encode = true;
ut->flags = UNDOTYPE_FLAG_NEED_CONTEXT_FOR_ENCODE;
ut->step_size = sizeof(ArmatureUndoStep);
}

View File

@ -1779,7 +1779,7 @@ static void pose_propagate_fcurve(
float refVal = 0.0f;
bool keyExists;
int i, match;
short first = 1;
bool first = true;
/* skip if no keyframes to edit */
if ((fcu->bezt == NULL) || (fcu->totvert < 2)) {
@ -1826,7 +1826,7 @@ static void pose_propagate_fcurve(
}
else if (mode == POSE_PROPAGATE_NEXT_KEY) {
/* stop after the first keyframe has been processed */
if (first == 0) {
if (first == false) {
break;
}
}
@ -1865,7 +1865,7 @@ static void pose_propagate_fcurve(
/* select keyframe to indicate that it's been changed */
bezt->f2 |= SELECT;
first = 0;
first = false;
}
}

View File

@ -309,7 +309,7 @@ void ED_curve_undosys_type(UndoType *ut)
ut->step_foreach_ID_ref = curve_undosys_foreach_ID_ref;
ut->use_context_for_encode = true;
ut->flags = UNDOTYPE_FLAG_NEED_CONTEXT_FOR_ENCODE;
ut->step_size = sizeof(CurveUndoStep);
}

View File

@ -398,7 +398,7 @@ void ED_font_undosys_type(UndoType *ut)
ut->step_foreach_ID_ref = font_undosys_foreach_ID_ref;
ut->use_context_for_encode = true;
ut->flags = UNDOTYPE_FLAG_NEED_CONTEXT_FOR_ENCODE;
ut->step_size = sizeof(FontUndoStep);
}

View File

@ -424,11 +424,11 @@ bool ED_object_modifier_apply(struct Main *bmain,
struct ModifierData *md,
int mode,
bool keep_modifier);
int ED_object_modifier_copy(struct ReportList *reports,
struct Main *bmain,
struct Scene *scene,
struct Object *ob,
struct ModifierData *md);
bool ED_object_modifier_copy(struct ReportList *reports,
struct Main *bmain,
struct Scene *scene,
struct Object *ob,
struct ModifierData *md);
void ED_object_modifier_link(struct bContext *C, struct Object *ob_dst, struct Object *ob_src);
void ED_object_modifier_copy_to_object(struct bContext *C,
struct Object *ob_dst,

View File

@ -165,7 +165,6 @@ static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *region
float *alert_color = tip_colors[UI_TIP_LC_ALERT];
float background_color[3];
float tone_bg;
wmOrtho2_region_pixelspace(region);
@ -185,7 +184,7 @@ static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *region
/* find the brightness difference between background and text colors */
tone_bg = rgb_to_grayscale(background_color);
const float tone_bg = rgb_to_grayscale(background_color);
/* tone_fg = rgb_to_grayscale(main_color); */
/* mix the colors */
@ -272,9 +271,7 @@ static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *region
static void ui_tooltip_region_free_cb(ARegion *region)
{
uiTooltipData *data;
data = region->regiondata;
uiTooltipData *data = region->regiondata;
for (int i = 0; i < data->fields_len; i++) {
const uiTooltipField *field = &data->fields[i];
@ -1164,16 +1161,13 @@ static ARegion *ui_tooltip_create_with_data(bContext *C,
const int winx = WM_window_pixels_x(win);
const int winy = WM_window_pixels_y(win);
const uiStyle *style = UI_style_get();
static ARegionType type;
ARegion *region;
int fonth, fontw;
int h, i;
rcti rect_i;
int font_flag = 0;
/* create area region */
region = ui_region_temp_add(CTX_wm_screen(C));
ARegion *region = ui_region_temp_add(CTX_wm_screen(C));
static ARegionType type;
memset(&type, 0, sizeof(ARegionType));
type.draw = ui_tooltip_region_draw_cb;
type.free = ui_tooltip_region_free_cb;
@ -1201,8 +1195,9 @@ static ARegion *ui_tooltip_create_with_data(bContext *C,
#define TIP_BORDER_X (16.0f / aspect)
#define TIP_BORDER_Y (6.0f / aspect)
h = BLF_height_max(data->fstyle.uifont_id);
int h = BLF_height_max(data->fstyle.uifont_id);
int i, fonth, fontw;
for (i = 0, fontw = 0, fonth = 0; i < data->fields_len; i++) {
uiTooltipField *field = &data->fields[i];
uiTooltipField *field_next = (i + 1) != data->fields_len ? &data->fields[i + 1] : NULL;

View File

@ -41,9 +41,7 @@
ARegion *ui_region_temp_add(bScreen *screen)
{
ARegion *region;
region = MEM_callocN(sizeof(ARegion), "area region");
ARegion *region = MEM_callocN(sizeof(ARegion), __func__);
BLI_addtail(&screen->regionbase, region);
region->regiontype = RGN_TYPE_TEMPORARY;

View File

@ -2558,7 +2558,7 @@ static void widget_state(uiWidgetType *wt, int state, int drawflag, eUIEmbossTyp
wt->wcol_theme = &btheme->tui.wcol_list_item;
if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE | UI_SEARCH_FILTER_NO_MATCH)) {
ui_widget_color_disabled(wt, state & UI_SEARCH_FILTER_NO_MATCH);
ui_widget_color_disabled(wt, state);
}
}

View File

@ -439,10 +439,10 @@ void WM_OT_alembic_export(wmOperatorType *ot)
RNA_def_enum(ot->srna,
"ngon_method",
rna_enum_modifier_triangulate_quad_method_items,
rna_enum_modifier_triangulate_ngon_method_items,
MOD_TRIANGULATE_NGON_BEAUTY,
"Polygon Method",
"Method for splitting the polygons into triangles");
"N-gon Method",
"Method for splitting the n-gons into triangles");
RNA_def_boolean(ot->srna,
"export_hair",

View File

@ -283,7 +283,7 @@ void ED_lattice_undosys_type(UndoType *ut)
ut->step_foreach_ID_ref = lattice_undosys_foreach_ID_ref;
ut->use_context_for_encode = true;
ut->flags = UNDOTYPE_FLAG_NEED_CONTEXT_FOR_ENCODE;
ut->step_size = sizeof(LatticeUndoStep);
}

View File

@ -5340,8 +5340,8 @@ void MESH_OT_quads_convert_to_tris(wmOperatorType *ot)
"ngon_method",
rna_enum_modifier_triangulate_ngon_method_items,
MOD_TRIANGULATE_NGON_BEAUTY,
"Polygon Method",
"Method for splitting the polygons into triangles");
"N-gon Method",
"Method for splitting the n-gons into triangles");
}
/** \} */

View File

@ -819,7 +819,7 @@ void ED_mesh_undosys_type(UndoType *ut)
ut->step_foreach_ID_ref = mesh_undosys_foreach_ID_ref;
ut->use_context_for_encode = true;
ut->flags = UNDOTYPE_FLAG_NEED_CONTEXT_FOR_ENCODE;
ut->step_size = sizeof(MeshUndoStep);
}

View File

@ -258,7 +258,7 @@ void ED_mball_undosys_type(UndoType *ut)
ut->step_foreach_ID_ref = mball_undosys_foreach_ID_ref;
ut->use_context_for_encode = true;
ut->flags = UNDOTYPE_FLAG_NEED_CONTEXT_FOR_ENCODE;
ut->step_size = sizeof(MBallUndoStep);
}

View File

@ -2411,7 +2411,7 @@ static const EnumPropertyItem convert_target_items[] = {
ICON_OUTLINER_OB_MESH,
"Mesh",
#ifdef WITH_POINT_CLOUD
"Mesh from Curve, Surface, Metaball, Text, or Pointcloud objects"},
"Mesh from Curve, Surface, Metaball, Text, or Point Cloud objects"},
#else
"Mesh from Curve, Surface, Metaball, or Text objects"},
#endif
@ -2424,8 +2424,8 @@ static const EnumPropertyItem convert_target_items[] = {
{OB_POINTCLOUD,
"POINTCLOUD",
ICON_OUTLINER_OB_POINTCLOUD,
"Pointcloud",
"Pointcloud from Mesh objects"},
"Point Cloud",
"Point Cloud from Mesh objects"},
#endif
{0, NULL, 0, NULL, NULL},
};

View File

@ -441,13 +441,24 @@ static bool bake_object_check(ViewLayer *view_layer,
}
Mesh *me = (Mesh *)ob->data;
if (CustomData_get_active_layer_index(&me->ldata, CD_MLOOPUV) == -1) {
BKE_reportf(
reports, RPT_ERROR, "No active UV layer found in the object \"%s\"", ob->id.name + 2);
return false;
if (target == R_BAKE_TARGET_VERTEX_COLORS) {
MPropCol *mcol = CustomData_get_layer(&me->vdata, CD_PROP_COLOR);
MLoopCol *mloopcol = CustomData_get_layer(&me->ldata, CD_MLOOPCOL);
if (mcol == NULL && mloopcol == NULL) {
BKE_reportf(reports,
RPT_ERROR,
"No vertex colors layer found in the object \"%s\"",
ob->id.name + 2);
return false;
}
}
else if (target == R_BAKE_TARGET_IMAGE_TEXTURES) {
if (CustomData_get_active_layer_index(&me->ldata, CD_MLOOPUV) == -1) {
BKE_reportf(
reports, RPT_ERROR, "No active UV layer found in the object \"%s\"", ob->id.name + 2);
return false;
}
if (target == R_BAKE_TARGET_IMAGE_TEXTURES) {
for (int i = 0; i < ob->totcol; i++) {
bNodeTree *ntree = NULL;
bNode *node = NULL;

View File

@ -504,7 +504,7 @@ static bool mesh_needs_keyindex(Main *bmain, const Mesh *me)
return false; /* will be added */
}
for (const Object *ob = bmain->objects.first; ob; ob = ob->id.next) {
LISTBASE_FOREACH (const Object *, ob, &bmain->objects) {
if ((ob->parent) && (ob->parent->data == me) && ELEM(ob->partype, PARVERT1, PARVERT3)) {
return true;
}
@ -650,12 +650,10 @@ bool ED_object_editmode_exit_ex(Main *bmain, Scene *scene, Object *obedit, int f
/* freedata only 0 now on file saves and render */
if (freedata) {
ListBase pidlist;
PTCacheID *pid;
/* flag object caches as outdated */
ListBase pidlist;
BKE_ptcache_ids_from_object(&pidlist, obedit, scene, 0);
for (pid = pidlist.first; pid; pid = pid->next) {
LISTBASE_FOREACH (PTCacheID *, pid, &pidlist) {
/* particles don't need reset on geometry change */
if (pid->type != PTCACHE_TYPE_PARTICLES) {
pid->cache->flag |= PTCACHE_OUTDATED;
@ -1398,7 +1396,7 @@ static int shade_smooth_exec(bContext *C, wmOperator *op)
CTX_data_selected_editable_objects(C, &ctx_objects);
}
for (CollectionPointerLink *ctx_ob = ctx_objects.first; ctx_ob; ctx_ob = ctx_ob->next) {
LISTBASE_FOREACH (CollectionPointerLink *, ctx_ob, &ctx_objects) {
Object *ob = ctx_ob->ptr.data;
ID *data = ob->data;
if (data != NULL) {
@ -1406,7 +1404,7 @@ static int shade_smooth_exec(bContext *C, wmOperator *op)
}
}
for (CollectionPointerLink *ctx_ob = ctx_objects.first; ctx_ob; ctx_ob = ctx_ob->next) {
LISTBASE_FOREACH (CollectionPointerLink *, ctx_ob, &ctx_objects) {
/* Always un-tag all object data-blocks irrespective of our ability to operate on them. */
Object *ob = ctx_ob->ptr.data;
ID *data = ob->data;
@ -1817,11 +1815,9 @@ struct MoveToCollectionData {
static int move_to_collection_menus_create(wmOperator *op, MoveToCollectionData *menu)
{
int index = menu->index;
for (CollectionChild *child = menu->collection->children.first; child != NULL;
child = child->next) {
LISTBASE_FOREACH (CollectionChild *, child, &menu->collection->children) {
Collection *collection = child->collection;
MoveToCollectionData *submenu = MEM_callocN(sizeof(MoveToCollectionData),
"MoveToCollectionData submenu - expected memleak");
MoveToCollectionData *submenu = MEM_callocN(sizeof(MoveToCollectionData), __func__);
BLI_addtail(&menu->submenus, submenu);
submenu->collection = collection;
submenu->index = ++index;
@ -1833,8 +1829,7 @@ static int move_to_collection_menus_create(wmOperator *op, MoveToCollectionData
static void move_to_collection_menus_free_recursive(MoveToCollectionData *menu)
{
for (MoveToCollectionData *submenu = menu->submenus.first; submenu != NULL;
submenu = submenu->next) {
LISTBASE_FOREACH (MoveToCollectionData *, submenu, &menu->submenus) {
move_to_collection_menus_free_recursive(submenu);
}
BLI_freelistN(&menu->submenus);
@ -1873,8 +1868,7 @@ static void move_to_collection_menu_create(bContext *C, uiLayout *layout, void *
UI_icon_color_from_collection(menu->collection);
uiItemIntO(layout, name, icon, menu->ot->idname, "collection_index", menu->index);
for (MoveToCollectionData *submenu = menu->submenus.first; submenu != NULL;
submenu = submenu->next) {
LISTBASE_FOREACH (MoveToCollectionData *, submenu, &menu->submenus) {
move_to_collection_menus_items(layout, submenu);
}
}

View File

@ -346,7 +346,7 @@ static bool object_modifier_remove(
* get called twice on same modifier, so make
* sure it is in list. */
if (BLI_findindex(&ob->modifiers, md) == -1) {
return 0;
return false;
}
/* special cases */
@ -393,7 +393,7 @@ static bool object_modifier_remove(
BKE_modifier_free(md);
BKE_object_free_derived_caches(ob);
return 1;
return true;
}
bool ED_object_modifier_remove(
@ -674,18 +674,18 @@ static Mesh *modifier_apply_create_mesh_for_modifier(Depsgraph *depsgraph,
return mesh_applied;
}
static int modifier_apply_shape(Main *bmain,
ReportList *reports,
Depsgraph *depsgraph,
Scene *scene,
Object *ob,
ModifierData *md_eval)
static bool modifier_apply_shape(Main *bmain,
ReportList *reports,
Depsgraph *depsgraph,
Scene *scene,
Object *ob,
ModifierData *md_eval)
{
const ModifierTypeInfo *mti = BKE_modifier_get_info(md_eval->type);
if (mti->isDisabled && mti->isDisabled(scene, md_eval, 0)) {
BKE_report(reports, RPT_ERROR, "Modifier is disabled, skipping apply");
return 0;
return false;
}
/* We could investigate using the #CD_ORIGINDEX layer
@ -699,19 +699,18 @@ static int modifier_apply_shape(Main *bmain,
* we can look into supporting them. */
if (ob->type == OB_MESH) {
Mesh *mesh_applied;
Mesh *me = ob->data;
Key *key = me->key;
if (!BKE_modifier_is_same_topology(md_eval) || mti->type == eModifierTypeType_NonGeometrical) {
BKE_report(reports, RPT_ERROR, "Only deforming modifiers can be applied to shapes");
return 0;
return false;
}
mesh_applied = modifier_apply_create_mesh_for_modifier(depsgraph, ob, md_eval, false);
Mesh *mesh_applied = modifier_apply_create_mesh_for_modifier(depsgraph, ob, md_eval, false);
if (!mesh_applied) {
BKE_report(reports, RPT_ERROR, "Modifier is disabled or returned error, skipping apply");
return 0;
return false;
}
if (key == NULL) {
@ -731,29 +730,28 @@ static int modifier_apply_shape(Main *bmain,
else {
/* TODO: implement for hair, point-clouds and volumes. */
BKE_report(reports, RPT_ERROR, "Cannot apply modifier for this object type");
return 0;
return false;
}
return 1;
return true;
}
static int modifier_apply_obdata(
static bool modifier_apply_obdata(
ReportList *reports, Depsgraph *depsgraph, Scene *scene, Object *ob, ModifierData *md_eval)
{
const ModifierTypeInfo *mti = BKE_modifier_get_info(md_eval->type);
if (mti->isDisabled && mti->isDisabled(scene, md_eval, 0)) {
BKE_report(reports, RPT_ERROR, "Modifier is disabled, skipping apply");
return 0;
return false;
}
if (ob->type == OB_MESH) {
Mesh *mesh_applied;
Mesh *me = ob->data;
MultiresModifierData *mmd = find_multires_modifier_before(scene, md_eval);
if (me->key && mti->type != eModifierTypeType_NonGeometrical) {
BKE_report(reports, RPT_ERROR, "Modifier cannot be applied to a mesh with shape keys");
return 0;
return false;
}
/* Multires: ensure that recent sculpting is applied */
@ -764,14 +762,14 @@ static int modifier_apply_obdata(
if (mmd && mmd->totlvl && mti->type == eModifierTypeType_OnlyDeform) {
if (!multiresModifier_reshapeFromDeformModifier(depsgraph, ob, mmd, md_eval)) {
BKE_report(reports, RPT_ERROR, "Multires modifier returned error, skipping apply");
return 0;
return false;
}
}
else {
mesh_applied = modifier_apply_create_mesh_for_modifier(depsgraph, ob, md_eval, true);
Mesh *mesh_applied = modifier_apply_create_mesh_for_modifier(depsgraph, ob, md_eval, true);
if (!mesh_applied) {
BKE_report(reports, RPT_ERROR, "Modifier returned error, skipping apply");
return 0;
return false;
}
BKE_mesh_nomain_to_mesh(mesh_applied, me, ob, &CD_MASK_MESH, true);
@ -790,7 +788,7 @@ static int modifier_apply_obdata(
if (ELEM(mti->type, eModifierTypeType_Constructive, eModifierTypeType_Nonconstructive)) {
BKE_report(
reports, RPT_ERROR, "Transform curve to mesh in order to apply constructive modifiers");
return 0;
return false;
}
BKE_report(reports,
@ -813,7 +811,7 @@ static int modifier_apply_obdata(
if (ELEM(mti->type, eModifierTypeType_Constructive, eModifierTypeType_Nonconstructive)) {
BKE_report(reports, RPT_ERROR, "Constructive modifiers cannot be applied");
return 0;
return false;
}
int numVerts;
@ -828,7 +826,7 @@ static int modifier_apply_obdata(
else {
/* TODO: implement for hair, point-clouds and volumes. */
BKE_report(reports, RPT_ERROR, "Cannot apply modifier for this object type");
return 0;
return false;
}
/* lattice modifier can be applied to particle system too */
@ -842,7 +840,7 @@ static int modifier_apply_obdata(
}
}
return 1;
return true;
}
bool ED_object_modifier_apply(Main *bmain,
@ -908,20 +906,19 @@ bool ED_object_modifier_apply(Main *bmain,
return true;
}
int ED_object_modifier_copy(
bool ED_object_modifier_copy(
ReportList *UNUSED(reports), Main *bmain, Scene *scene, Object *ob, ModifierData *md)
{
ModifierData *nmd;
if (md->type == eModifierType_ParticleSystem) {
nmd = object_copy_particle_system(bmain, scene, ob, ((ParticleSystemModifierData *)md)->psys);
ModifierData *nmd = object_copy_particle_system(
bmain, scene, ob, ((ParticleSystemModifierData *)md)->psys);
BLI_remlink(&ob->modifiers, nmd);
BLI_insertlinkafter(&ob->modifiers, md, nmd);
BKE_object_modifier_set_active(ob, nmd);
return true;
}
nmd = BKE_modifier_new(md->type);
ModifierData *nmd = BKE_modifier_new(md->type);
BKE_modifier_copydata(md, nmd);
BLI_insertlinkafter(&ob->modifiers, md, nmd);
BKE_modifier_unique_name(&ob->modifiers, nmd);
@ -929,7 +926,7 @@ int ED_object_modifier_copy(
nmd->flag |= eModifierFlag_OverrideLibrary_Local;
return 1;
return true;
}
/** \} */

View File

@ -1567,7 +1567,11 @@ static bool allow_make_links_data(const int type, Object *ob_src, Object *ob_dst
}
break;
case MAKE_LINKS_MATERIALS:
if (OB_TYPE_SUPPORT_MATERIAL(ob_src->type) && OB_TYPE_SUPPORT_MATERIAL(ob_dst->type)) {
if (OB_TYPE_SUPPORT_MATERIAL(ob_src->type) && OB_TYPE_SUPPORT_MATERIAL(ob_dst->type) &&
/* Linking non-grease-pencil materials to a grease-pencil object causes issues.
* We make sure that if one of the objects is a grease-pencil object, the other must be
* as well. */
((ob_src->type == OB_GPENCIL) == (ob_dst->type == OB_GPENCIL))) {
return true;
}
break;

View File

@ -3496,6 +3496,21 @@ static int mirror_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_FINISHED;
}
static bool mirror_poll(bContext *C)
{
if (!PE_hair_poll(C)) {
return false;
}
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
Scene *scene = CTX_data_scene(C);
Object *ob = CTX_data_active_object(C);
PTCacheEdit *edit = PE_get_current(depsgraph, scene, ob);
/* The operator only works for hairs emitted from faces. */
return edit->psys->part->from == PART_FROM_FACE;
}
void PARTICLE_OT_mirror(wmOperatorType *ot)
{
/* identifiers */
@ -3505,7 +3520,7 @@ void PARTICLE_OT_mirror(wmOperatorType *ot)
/* api callbacks */
ot->exec = mirror_exec;
ot->poll = PE_hair_poll;
ot->poll = mirror_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;

View File

@ -299,7 +299,7 @@ void ED_particle_undosys_type(UndoType *ut)
ut->step_foreach_ID_ref = particle_undosys_foreach_ID_ref;
ut->use_context_for_encode = true;
ut->flags = UNDOTYPE_FLAG_NEED_CONTEXT_FOR_ENCODE;
ut->step_size = sizeof(ParticleUndoStep);
}

View File

@ -240,8 +240,9 @@ static void SCENE_OT_new(wmOperatorType *ot)
static bool scene_delete_poll(bContext *C)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
return (scene->id.prev || scene->id.next);
return BKE_scene_can_be_removed(bmain, scene);
}
static int scene_delete_exec(bContext *C, wmOperator *UNUSED(op))

View File

@ -159,7 +159,7 @@ void ED_paintcurve_undosys_type(UndoType *ut)
ut->step_foreach_ID_ref = paintcurve_undosys_foreach_ID_ref;
ut->use_context_for_encode = false;
ut->flags = 0;
ut->step_size = sizeof(PaintCurveUndoStep);
}

View File

@ -91,7 +91,7 @@ typedef struct BrushPainter {
Scene *scene;
Brush *brush;
short firsttouch; /* first paint op */
bool firsttouch; /* first paint op */
struct ImagePool *pool; /* image pool */
rctf tex_mapping; /* texture coordinate mapping */
@ -132,8 +132,6 @@ typedef struct ImagePaintState {
SpaceImage *sima;
View2D *v2d;
Scene *scene;
bScreen *screen;
struct ImagePool *image_pool;
Brush *brush;
short tool, blend;
@ -142,11 +140,6 @@ typedef struct ImagePaintState {
bool do_masking;
/* viewport texture paint only, but _not_ project paint */
Object *ob;
int faceindex;
float uv[2];
int do_facesel;
int symmetry;
ImagePaintTile *tiles;
@ -161,7 +154,7 @@ static BrushPainter *brush_painter_2d_new(Scene *scene, Brush *brush, bool inver
painter->brush = brush;
painter->scene = scene;
painter->firsttouch = 1;
painter->firsttouch = true;
painter->cache_invert = invert;
return painter;
@ -1659,7 +1652,7 @@ void paint_2d_stroke(void *ps,
}
}
painter->firsttouch = 0;
painter->firsttouch = false;
}
void *paint_2d_new_stroke(bContext *C, wmOperator *op, int mode)
@ -1674,7 +1667,6 @@ void *paint_2d_new_stroke(bContext *C, wmOperator *op, int mode)
s->sima = CTX_wm_space_image(C);
s->v2d = &CTX_wm_region(C)->v2d;
s->scene = scene;
s->screen = CTX_wm_screen(C);
s->brush = brush;
s->tool = brush->imagepaint_tool;

View File

@ -1576,7 +1576,7 @@ void ED_sculpt_undosys_type(UndoType *ut)
ut->step_decode = sculpt_undosys_step_decode;
ut->step_free = sculpt_undosys_step_free;
ut->use_context_for_encode = false;
ut->flags = 0;
ut->step_size = sizeof(SculptUndoStep);
}

View File

@ -543,7 +543,7 @@ static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, const wm
/* we need to find the active island here */
if (do_island_optimization) {
UvElement *element;
UvNearestHit hit = UV_NEAREST_HIT_INIT;
UvNearestHit hit = UV_NEAREST_HIT_INIT_MAX(&region->v2d);
uv_find_nearest_vert(scene, obedit, co, 0.0f, &hit);
element = BM_uv_element_get(data->elementMap, hit.efa, hit.l);

View File

@ -171,6 +171,8 @@ static GHash *fsmenu_xdg_user_dirs_parse(const char *home)
}
}
}
fclose(fp);
return xdg_map;
}

View File

@ -997,8 +997,10 @@ void ED_image_undosys_type(UndoType *ut)
ut->step_foreach_ID_ref = image_undosys_foreach_ID_ref;
/* NOTE this is actually a confusing case, since it expects a valid context, but only in a
* specific case, see `image_undosys_step_encode` code. */
ut->use_context_for_encode = false;
* specific case, see `image_undosys_step_encode` code. We cannot specify
* `UNDOTYPE_FLAG_NEED_CONTEXT_FOR_ENCODE` though, as it can be called with a NULL context by
* current code. */
ut->flags = 0;
ut->step_size = sizeof(ImageUndoStep);
}

View File

@ -347,17 +347,15 @@ static void outliner_layer_or_collection_pointer_create(Scene *scene,
}
/** Create either a RNA_ObjectBase or a RNA_Object pointer. */
static void outliner_base_or_object_pointer_create(ViewLayer *view_layer,
Collection *collection,
Object *ob,
PointerRNA *ptr)
static void outliner_base_or_object_pointer_create(
Scene *scene, ViewLayer *view_layer, Collection *collection, Object *ob, PointerRNA *ptr)
{
if (collection) {
RNA_id_pointer_create(&ob->id, ptr);
}
else {
Base *base = BKE_view_layer_base_find(view_layer, ob);
RNA_pointer_create(&base->object->id, &RNA_ObjectBase, base, ptr);
RNA_pointer_create(&scene->id, &RNA_ObjectBase, base, ptr);
}
}
@ -384,7 +382,7 @@ static void outliner_collection_set_flag_recursive(Scene *scene,
* otherwise we would not take collection exclusion into account. */
LISTBASE_FOREACH (CollectionObject *, cob, &layer_collection->collection->gobject) {
outliner_base_or_object_pointer_create(view_layer, collection, cob->ob, &ptr);
outliner_base_or_object_pointer_create(scene, view_layer, collection, cob->ob, &ptr);
RNA_property_boolean_set(&ptr, base_or_object_prop, value);
if (collection) {
@ -1116,7 +1114,7 @@ static void outliner_draw_restrictbuts(uiBlock *block,
BKE_view_layer_base_find(view_layer, ob);
if (base) {
PointerRNA base_ptr;
RNA_pointer_create(&ob->id, &RNA_ObjectBase, base, &base_ptr);
RNA_pointer_create(&scene->id, &RNA_ObjectBase, base, &base_ptr);
bt = uiDefIconButR_prop(block,
UI_BTYPE_ICON_TOGGLE,
0,

View File

@ -196,7 +196,7 @@ static void outliner_main_region_listener(wmWindow *UNUSED(win),
}
break;
case NC_ID:
if (wmn->action == NA_RENAME) {
if (ELEM(wmn->action, NA_RENAME, NA_ADDED)) {
ED_region_tag_redraw(region);
}
break;

View File

@ -260,7 +260,7 @@ void ED_text_undosys_type(UndoType *ut)
ut->step_foreach_ID_ref = text_undosys_foreach_ID_ref;
ut->use_context_for_encode = true;
ut->flags = UNDOTYPE_FLAG_NEED_CONTEXT_FOR_ENCODE;
ut->step_size = sizeof(TextUndoStep);
}

View File

@ -197,9 +197,10 @@ void createTransCurveVerts(TransInfo *t)
TransData *td = tc->data;
ListBase *nurbs = BKE_curve_editNurbs_get(cu);
LISTBASE_FOREACH (Nurb *, nu, nurbs) {
TransData *head, *tail;
head = tail = td;
bool has_any_selected = false;
if (nu->type == CU_BEZIER) {
TransData *head, *tail;
head = tail = td;
for (a = 0, bezt = nu->bezt; a < nu->pntsu; a++, bezt++) {
if (bezt->hide == 0) {
TransDataCurveHandleFlags *hdata = NULL;
@ -223,6 +224,7 @@ void createTransCurveVerts(TransInfo *t)
/* Elements that will be transform (not always a match to selection). */
const int bezt_tx = bezt_select_to_transform_triple_flag(bezt, hide_handles);
has_any_selected |= bezt_tx != 0;
if (is_prop_edit || bezt_tx & SEL_F1) {
copy_v3_v3(td->iloc, bezt->vec[0]);
@ -350,28 +352,9 @@ void createTransCurveVerts(TransInfo *t)
(void)hdata; /* quiet warning */
}
else if (is_prop_edit && head != tail) {
tail->flag |= TD_NOTCONNECTED;
td++;
tail++;
}
}
if (is_prop_edit && head != tail) {
bool cyclic = (nu->flagu & CU_NURB_CYCLIC) != 0;
calc_distanceCurveVerts(head, tail - 1, cyclic);
}
/* TODO - in the case of tilt and radius we can also avoid allocating the
* initTransDataCurveHandles but for now just don't change handle types */
if (ELEM(t->mode, TFM_CURVE_SHRINKFATTEN, TFM_TILT, TFM_DUMMY) == 0) {
/* sets the handles based on their selection,
* do this after the data is copied to the TransData */
BKE_nurb_handles_test(nu, !hide_handles, use_around_origins_for_handles_test);
}
}
else {
TransData *head, *tail;
head = tail = td;
for (a = nu->pntsu * nu->pntsv, bp = nu->bp; a > 0; a--, bp++) {
if (bp->hide == 0) {
if (is_prop_edit || (bp->f1 & SELECT)) {
@ -400,6 +383,7 @@ void createTransCurveVerts(TransInfo *t)
copy_v3_v3(td->center, td->loc);
if (bp->f1 & SELECT) {
td->flag = TD_SELECTED;
has_any_selected |= true;
}
else {
td->flag = 0;
@ -427,16 +411,26 @@ void createTransCurveVerts(TransInfo *t)
tail++;
}
}
else if (is_prop_edit && head != tail) {
tail->flag |= TD_NOTCONNECTED;
td++;
tail++;
}
}
if (is_prop_edit && head != tail) {
tail -= 1;
if (!has_any_selected) {
for (td = head; td <= tail; td++) {
td->flag |= TD_NOTCONNECTED;
}
}
if (is_prop_edit && head != tail) {
bool cyclic = (nu->flagu & CU_NURB_CYCLIC) != 0;
calc_distanceCurveVerts(head, tail - 1, cyclic);
}
bool cyclic = (nu->flagu & CU_NURB_CYCLIC) != 0;
calc_distanceCurveVerts(head, tail, cyclic);
}
/* TODO - in the case of tilt and radius we can also avoid allocating the
* initTransDataCurveHandles but for now just don't change handle types */
if ((nu->type == CU_BEZIER) &&
ELEM(t->mode, TFM_CURVE_SHRINKFATTEN, TFM_TILT, TFM_DUMMY) == 0) {
/* sets the handles based on their selection,
* do this after the data is copied to the TransData */
BKE_nurb_handles_test(nu, !hide_handles, use_around_origins_for_handles_test);
}
}
}

View File

@ -282,7 +282,7 @@ void ED_memfile_undosys_type(UndoType *ut)
ut->step_decode = memfile_undosys_step_decode;
ut->step_free = memfile_undosys_step_free;
ut->use_context_for_encode = false;
ut->flags = 0;
ut->step_size = sizeof(MemFileUndoStep);
}

View File

@ -41,13 +41,34 @@ typedef struct UvNearestHit {
/** Always set if we have a hit. */
struct BMFace *efa;
struct BMLoop *l;
/** Needs to be set before calling nearest functions. */
/**
* Needs to be set before calling nearest functions.
*
* \note When #UV_NEAREST_HIT_INIT_DIST_PX or #UV_NEAREST_HIT_INIT_MAX are used,
* this value is pixels squared.
*/
float dist_sq;
/** Scale the UV's to account for aspect ratio from the image view. */
float scale[2];
} UvNearestHit;
#define UV_NEAREST_HIT_INIT \
#define UV_NEAREST_HIT_INIT_DIST_PX(v2d, dist_px) \
{ \
.dist_sq = square_f(U.pixelsize * dist_px), \
.scale = { \
UI_view2d_scale_get_x(v2d), \
UI_view2d_scale_get_y(v2d), \
}, \
}
#define UV_NEAREST_HIT_INIT_MAX(v2d) \
{ \
.dist_sq = FLT_MAX, \
.scale = { \
UI_view2d_scale_get_x(v2d), \
UI_view2d_scale_get_y(v2d), \
}, \
}
bool uv_find_nearest_vert(struct Scene *scene,
@ -96,7 +117,6 @@ BMLoop *uv_find_nearest_loop_from_edge(struct Scene *scene,
void uvedit_live_unwrap_update(struct SpaceImage *sima,
struct Scene *scene,
struct Object *obedit);
void uvedit_pixel_to_float(struct SpaceImage *sima, float pixeldist, float r_dist[2]);
/* operators */

View File

@ -186,28 +186,6 @@ void ED_object_assign_active_image(Main *bmain, Object *ob, int mat_nr, Image *i
/** \} */
/* -------------------------------------------------------------------- */
/** \name Space Conversion
* \{ */
void uvedit_pixel_to_float(SpaceImage *sima, float pixeldist, float r_dist[2])
{
int width, height;
if (sima) {
ED_space_image_get_size(sima, &width, &height);
}
else {
width = IMG_SIZE_FALLBACK;
height = IMG_SIZE_FALLBACK;
}
r_dist[0] = pixeldist / width;
r_dist[1] = pixeldist / height;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Live Unwrap Utilities
* \{ */
@ -1473,7 +1451,7 @@ static int uv_hide_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
const ToolSettings *ts = scene->toolsettings;
const bool swap = RNA_boolean_get(op->ptr, "unselected");
const int use_face_center = (ts->uv_selectmode == UV_SELECT_FACE);
const bool use_face_center = (ts->uv_selectmode == UV_SELECT_FACE);
uint objects_len = 0;
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
@ -1605,8 +1583,8 @@ static int uv_reveal_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
const ToolSettings *ts = scene->toolsettings;
const int use_face_center = (ts->uv_selectmode == UV_SELECT_FACE);
const int stickymode = sima ? (sima->sticky != SI_STICKY_DISABLE) : 1;
const bool use_face_center = (ts->uv_selectmode == UV_SELECT_FACE);
const bool stickymode = sima ? (sima->sticky != SI_STICKY_DISABLE) : 1;
const bool select = RNA_boolean_get(op->ptr, "select");
uint objects_len = 0;

View File

@ -574,7 +574,7 @@ static bool uv_shortest_path_pick_ex(const SpaceImage *sima,
static int uv_shortest_path_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
const SpaceImage *sima = CTX_wm_space_image(C);
SpaceImage *sima = CTX_wm_space_image(C);
Scene *scene = CTX_data_scene(C);
const ToolSettings *ts = scene->toolsettings;
const char uv_selectmode = ED_uvedit_select_mode_get(scene);
@ -613,7 +613,7 @@ static int uv_shortest_path_pick_invoke(bContext *C, wmOperator *op, const wmEve
BMElem *ele_src = NULL, *ele_dst = NULL;
if (uv_selectmode == UV_SELECT_FACE) {
UvNearestHit hit = UV_NEAREST_HIT_INIT;
UvNearestHit hit = UV_NEAREST_HIT_INIT_MAX(&region->v2d);
if (!uv_find_nearest_face(scene, obedit, co, &hit)) {
return OPERATOR_CANCELLED;
}
@ -626,7 +626,7 @@ static int uv_shortest_path_pick_invoke(bContext *C, wmOperator *op, const wmEve
}
else if (uv_selectmode & UV_SELECT_EDGE) {
UvNearestHit hit = UV_NEAREST_HIT_INIT;
UvNearestHit hit = UV_NEAREST_HIT_INIT_MAX(&region->v2d);
if (!uv_find_nearest_edge(scene, obedit, co, &hit)) {
return OPERATOR_CANCELLED;
}
@ -652,7 +652,7 @@ static int uv_shortest_path_pick_invoke(bContext *C, wmOperator *op, const wmEve
ele_dst = (BMElem *)hit.l;
}
else {
UvNearestHit hit = UV_NEAREST_HIT_INIT;
UvNearestHit hit = UV_NEAREST_HIT_INIT_MAX(&region->v2d);
if (!uv_find_nearest_vert(scene, obedit, co, 0.0f, &hit)) {
return OPERATOR_CANCELLED;
}

View File

@ -201,21 +201,6 @@ void ED_uvedit_select_sync_flush(const ToolSettings *ts, BMEditMesh *em, const b
}
}
/**
* Apply a penalty to elements that are already selected
* so elements that aren't already selected are prioritized.
*
* \note This is calculated in screen-space otherwise zooming in on a uv-vert and
* shift-selecting can consider an adjacent point close enough to add to
* the selection rather than de-selecting the closest.
*/
static float uv_select_penalty_default(SpaceImage *sima)
{
float penalty[2];
uvedit_pixel_to_float(sima, 5.0f / (sima ? sima->zoom : 1.0f), penalty);
return len_v2(penalty);
}
static void uvedit_vertex_select_tagged(BMEditMesh *em,
Scene *scene,
bool select,
@ -680,6 +665,7 @@ static BMLoop *uvedit_loop_find_other_boundary_loop_with_visible_face(const Scen
bool uv_find_nearest_edge(Scene *scene, Object *obedit, const float co[2], UvNearestHit *hit)
{
BLI_assert((hit->scale[0] > 0.0f) && (hit->scale[1] > 0.0f));
BMEditMesh *em = BKE_editmesh_from_object(obedit);
BMFace *efa;
BMLoop *l;
@ -700,7 +686,13 @@ bool uv_find_nearest_edge(Scene *scene, Object *obedit, const float co[2], UvNea
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
luv_next = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset);
const float dist_test_sq = dist_squared_to_line_segment_v2(co, luv->uv, luv_next->uv);
float delta[2];
closest_to_line_segment_v2(delta, co, luv->uv, luv_next->uv);
sub_v2_v2(delta, co);
mul_v2_v2(delta, hit->scale);
const float dist_test_sq = len_squared_v2(delta);
if (dist_test_sq < hit->dist_sq) {
hit->efa = efa;
@ -734,6 +726,7 @@ bool uv_find_nearest_edge_multi(Scene *scene,
bool uv_find_nearest_face(Scene *scene, Object *obedit, const float co[2], UvNearestHit *hit_final)
{
BLI_assert((hit_final->scale[0] > 0.0f) && (hit_final->scale[1] > 0.0f));
BMEditMesh *em = BKE_editmesh_from_object(obedit);
bool found = false;
@ -757,7 +750,11 @@ bool uv_find_nearest_face(Scene *scene, Object *obedit, const float co[2], UvNea
float cent[2];
BM_face_uv_calc_center_median(efa, cd_loop_uv_offset, cent);
const float dist_test_sq = len_squared_v2v2(co, cent);
float delta[2];
sub_v2_v2v2(delta, co, cent);
mul_v2_v2(delta, hit.scale);
const float dist_test_sq = len_squared_v2(delta);
if (dist_test_sq < hit.dist_sq) {
hit.efa = efa;
@ -805,9 +802,10 @@ bool uv_find_nearest_vert(Scene *scene,
const float penalty_dist,
UvNearestHit *hit_final)
{
BLI_assert((hit_final->scale[0] > 0.0f) && (hit_final->scale[1] > 0.0f));
bool found = false;
/* this will fill in hit.vert1 and hit.vert2 */
/* This will fill in `hit.l`. */
float dist_sq_init = hit_final->dist_sq;
UvNearestHit hit = *hit_final;
if (uv_find_nearest_edge(scene, obedit, co, &hit)) {
@ -832,14 +830,17 @@ bool uv_find_nearest_vert(Scene *scene,
BMLoop *l;
int i;
BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
float dist_test_sq;
MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
if (penalty_dist != 0.0f && uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
dist_test_sq = len_v2v2(co, luv->uv) + penalty_dist;
dist_test_sq = square_f(dist_test_sq);
}
else {
dist_test_sq = len_squared_v2v2(co, luv->uv);
float delta[2];
sub_v2_v2v2(delta, co, luv->uv);
mul_v2_v2(delta, hit.scale);
float dist_test_sq = len_squared_v2(delta);
if ((penalty_dist != 0.0f) && uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
dist_test_sq = square_f(sqrtf(dist_test_sq) + penalty_dist);
}
if (dist_test_sq <= hit.dist_sq) {
@ -1912,15 +1913,18 @@ static int uv_mouse_select_multi(bContext *C,
{
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
SpaceImage *sima = CTX_wm_space_image(C);
const ARegion *region = CTX_wm_region(C);
Scene *scene = CTX_data_scene(C);
const ToolSettings *ts = scene->toolsettings;
UvNearestHit hit = UV_NEAREST_HIT_INIT;
UvNearestHit hit = UV_NEAREST_HIT_INIT_DIST_PX(&region->v2d, 75.0f);
int selectmode, sticky;
bool found_item = false;
/* 0 == don't flush, 1 == sel, -1 == desel; only use when selection sync is enabled */
int flush = 0;
const float penalty_dist = uv_select_penalty_default(sima);
/* Penalty (in pixels) applied to elements that are already selected
* so elements that aren't already selected are prioritized. */
const float penalty_dist = 3.0f * U.pixelsize;
/* retrieve operation mode */
if (ts->uv_flag & UV_SYNC_SELECTION) {
@ -1945,8 +1949,6 @@ static int uv_mouse_select_multi(bContext *C,
if (selectmode == UV_SELECT_VERTEX) {
/* find vertex */
found_item = uv_find_nearest_vert_multi(scene, objects, objects_len, co, penalty_dist, &hit);
found_item = found_item && (!deselect_all || hit.dist_sq < penalty_dist);
if (found_item) {
if ((ts->uv_flag & UV_SYNC_SELECTION) == 0) {
BMesh *bm = BKE_editmesh_from_object(hit.ob)->bm;
@ -1957,8 +1959,6 @@ static int uv_mouse_select_multi(bContext *C,
else if (selectmode == UV_SELECT_EDGE) {
/* find edge */
found_item = uv_find_nearest_edge_multi(scene, objects, objects_len, co, &hit);
found_item = found_item && (!deselect_all || hit.dist_sq < penalty_dist);
if (found_item) {
if ((ts->uv_flag & UV_SYNC_SELECTION) == 0) {
BMesh *bm = BKE_editmesh_from_object(hit.ob)->bm;
@ -1969,8 +1969,6 @@ static int uv_mouse_select_multi(bContext *C,
else if (selectmode == UV_SELECT_FACE) {
/* find face */
found_item = uv_find_nearest_face_multi(scene, objects, objects_len, co, &hit);
found_item = found_item && (!deselect_all || hit.dist_sq < penalty_dist);
if (found_item) {
BMesh *bm = BKE_editmesh_from_object(hit.ob)->bm;
BM_mesh_active_face_set(bm, hit.efa);
@ -1978,7 +1976,6 @@ static int uv_mouse_select_multi(bContext *C,
}
else if (selectmode == UV_SELECT_ISLAND) {
found_item = uv_find_nearest_edge_multi(scene, objects, objects_len, co, &hit);
found_item = found_item && (!deselect_all || hit.dist_sq < penalty_dist);
}
if (!found_item) {
@ -2173,10 +2170,11 @@ static int uv_mouse_select_loop_generic_multi(bContext *C,
enum eUVLoopGenericType loop_type)
{
SpaceImage *sima = CTX_wm_space_image(C);
const ARegion *region = CTX_wm_region(C);
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
Scene *scene = CTX_data_scene(C);
const ToolSettings *ts = scene->toolsettings;
UvNearestHit hit = UV_NEAREST_HIT_INIT;
UvNearestHit hit = UV_NEAREST_HIT_INIT_MAX(&region->v2d);
bool found_item = false;
/* 0 == don't flush, 1 == sel, -1 == desel; only use when selection sync is enabled */
int flush = 0;
@ -2367,6 +2365,7 @@ void UV_OT_select_edge_ring(wmOperatorType *ot)
static int uv_select_linked_internal(bContext *C, wmOperator *op, const wmEvent *event, bool pick)
{
const ARegion *region = CTX_wm_region(C);
Scene *scene = CTX_data_scene(C);
const ToolSettings *ts = scene->toolsettings;
ViewLayer *view_layer = CTX_data_view_layer(C);
@ -2374,7 +2373,7 @@ static int uv_select_linked_internal(bContext *C, wmOperator *op, const wmEvent
bool deselect = false;
bool select_faces = (ts->uv_flag & UV_SYNC_SELECTION) && (ts->selectmode & SCE_SELECT_FACE);
UvNearestHit hit = UV_NEAREST_HIT_INIT;
UvNearestHit hit = UV_NEAREST_HIT_INIT_MAX(&region->v2d);
if (pick) {
extend = RNA_boolean_get(op->ptr, "extend");
@ -2390,8 +2389,6 @@ static int uv_select_linked_internal(bContext *C, wmOperator *op, const wmEvent
if (event) {
/* invoke */
const ARegion *region = CTX_wm_region(C);
UI_view2d_region_to_view(&region->v2d, event->mval[0], event->mval[1], &co[0], &co[1]);
RNA_float_set_array(op->ptr, "location", co);
}

View File

@ -2539,8 +2539,8 @@ static StitchState *stitch_select(bContext *C,
{
/* add uv under mouse to processed uv's */
float co[2];
UvNearestHit hit = UV_NEAREST_HIT_INIT;
ARegion *region = CTX_wm_region(C);
UvNearestHit hit = UV_NEAREST_HIT_INIT_MAX(&region->v2d);
UI_view2d_region_to_view(&region->v2d, event->mval[0], event->mval[1], &co[0], &co[1]);

View File

@ -2229,7 +2229,7 @@ void UV_OT_smart_project(wmOperatorType *ot)
0.0f,
1.0f,
"Area Weight",
"Weight projections vector by faces with larger areas",
"Weight projection's vector by faces with larger areas",
0.0f,
1.0f);

View File

@ -34,6 +34,28 @@
namespace blender::gpu {
/* See T82856: AMD drivers since 20.11 running on a polaris architecture doesn't support the
* `GL_INT_2_10_10_10_REV` data type correctly. This data type is used to pack normals and flags.
* The work around uses `GPU_RGBA16I` but that is only possible for loop normals.
*
* Vertex and Face normals would still render resulting in undefined behavior during selection and
* rendering. */
static bool is_faulty_T82856_platform(const char *version, const char *renderer)
{
/* On Linux the driver does not report its version. Test the OpenGL version in stead. */
if (strstr(version, "4.5.14756") || strstr(version, "4.5.14757")) {
if (strstr(renderer, " RX 460 ") || strstr(renderer, " RX 470 ") ||
strstr(renderer, " RX 480 ") || strstr(renderer, " RX 490 ") ||
strstr(renderer, " RX 560 ") || strstr(renderer, " RX 560X ") ||
strstr(renderer, " RX 570 ") || strstr(renderer, " RX 580 ") ||
strstr(renderer, " RX 590 ") || strstr(renderer, " RX550/550 ") ||
strstr(renderer, " (TM) 520 ") || strstr(renderer, " (TM) 530 ") ||
strstr(renderer, " R5 ") || strstr(renderer, " R7 ") || strstr(renderer, " R9 ")) {
return true;
}
}
return false;
}
/* -------------------------------------------------------------------- */
/** \name Platform
* \{ */
@ -137,6 +159,11 @@ void GLBackend::platform_init()
GPG.support_level = GPU_SUPPORT_LEVEL_LIMITED;
}
}
if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_OFFICIAL)) {
if (is_faulty_T82856_platform(version, renderer)) {
GPG.support_level = GPU_SUPPORT_LEVEL_LIMITED;
}
}
}
GPG.create_key(GPG.support_level, vendor, renderer, version);
GPG.create_gpu_name(vendor, renderer, version);
@ -272,20 +299,10 @@ static void detect_workarounds()
GCaps.broken_amd_driver = true;
}
/* See T82856: AMD drivers since 20.11 running on a polaris architecture doesn't support the
* `GL_INT_2_10_10_10_REV` data type. This data type is used to pack normals. The work around
* uses `GPU_RGBA16I`.*/
* `GL_INT_2_10_10_10_REV` data type. */
if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_OFFICIAL)) {
if (strstr(version, " 20.11.2") || strstr(version, " 20.11.3 ") ||
strstr(version, " 20.12.")) {
if (strstr(renderer, " RX 460 ") || strstr(renderer, " RX 470 ") ||
strstr(renderer, " RX 480 ") || strstr(renderer, " RX 490 ") ||
strstr(renderer, " RX 560 ") || strstr(renderer, " RX 560X ") ||
strstr(renderer, " RX 570 ") || strstr(renderer, " RX 580 ") ||
strstr(renderer, " RX 590 ") || strstr(renderer, " RX550/550 ") ||
strstr(renderer, " (TM) 520 ") || strstr(renderer, " (TM) 530 ") ||
strstr(renderer, " R5 ") || strstr(renderer, " R7 ") || strstr(renderer, " R9 ")) {
GCaps.use_hq_normals_workaround = true;
}
if (is_faulty_T82856_platform(version, renderer)) {
GCaps.use_hq_normals_workaround = true;
}
}
/* There is an issue with the #glBlitFramebuffer on MacOS with radeon pro graphics.
@ -378,7 +395,7 @@ static void detect_workarounds()
if (GLContext::debug_layer_support == false) {
GLContext::debug_layer_workaround = true;
}
}
} // namespace blender::gpu
/** Internal capabilities. */
GLint GLContext::max_cubemap_size = 0;

View File

@ -314,6 +314,20 @@ typedef struct ID {
*/
struct ID *orig_id;
/**
* Holds the #PyObject reference to the ID (initialized on demand).
*
* This isn't essential, it could be removed however it gives some advantages:
*
* - Every time the #ID is accessed a #BPy_StructRNA doesn't have to be created & destroyed
* (consider all the polling and drawing functions that access ID's).
*
* - When this #ID is deleted, the #BPy_StructRNA can be invalidated
* so accessing it from Python raises an exception instead of crashing.
*
* This is of limited benefit though, as it doesn't apply to non #ID data
* that references this ID (the bones of an armature or the modifiers of an object for e.g.).
*/
void *py_instance;
void *_pad1;
} ID;

View File

@ -77,7 +77,7 @@ const EnumPropertyItem rna_enum_id_type_items[] = {
{ID_TXT, "TEXT", ICON_TEXT, "Text", ""},
{ID_TE, "TEXTURE", ICON_TEXTURE_DATA, "Texture", ""},
{ID_HA, "HAIR", ICON_HAIR_DATA, "Hair", ""},
{ID_PT, "POINTCLOUD", ICON_POINTCLOUD_DATA, "PointCloud", ""},
{ID_PT, "POINTCLOUD", ICON_POINTCLOUD_DATA, "Point Cloud", ""},
{ID_VO, "VOLUME", ICON_VOLUME_DATA, "Volume", ""},
{ID_WM, "WINDOWMANAGER", ICON_WINDOW, "Window Manager", ""},
{ID_WO, "WORLD", ICON_WORLD_DATA, "World", ""},

View File

@ -545,6 +545,17 @@ struct StructRNA {
/* function to register/unregister subclasses */
StructRegisterFunc reg;
StructUnregisterFunc unreg;
/**
* Optionally support reusing Python instances for this type.
*
* Without this, an operator class created for #wmOperatorType.invoke (for example)
* would have a different instance passed to the #wmOperatorType.modal callback.
* So any variables assigned to `self` from Python would not be available to other callbacks.
*
* Being able to access the instance also has the advantage that we can invalidate
* the Python instance when the data has been removed, see: #BPY_DECREF_RNA_INVALIDATE
* so accessing the variables from Python raises an exception instead of crashing.
*/
StructInstanceFunc instance;
/* callback to get id properties */

View File

@ -172,6 +172,9 @@ static Camera *rna_Main_cameras_new(Main *bmain, const char *name)
ID *id = BKE_camera_add(bmain, safe_name);
id_us_min(id);
WM_main_add_notifier(NC_ID | NA_ADDED, NULL);
return (Camera *)id;
}
@ -180,16 +183,20 @@ static Scene *rna_Main_scenes_new(Main *bmain, const char *name)
char safe_name[MAX_ID_NAME - 2];
rna_idname_validate(name, safe_name);
return BKE_scene_add(bmain, safe_name);
Scene *scene = BKE_scene_add(bmain, safe_name);
WM_main_add_notifier(NC_ID | NA_ADDED, NULL);
return scene;
}
static void rna_Main_scenes_remove(
Main *bmain, bContext *C, ReportList *reports, PointerRNA *scene_ptr, bool do_unlink)
{
/* don't call BKE_id_free(...) directly */
Scene *scene = scene_ptr->data;
Scene *scene_new;
if ((scene_new = scene->id.prev) || (scene_new = scene->id.next)) {
if (BKE_scene_can_be_removed(bmain, scene)) {
Scene *scene_new = scene->id.prev ? scene->id.prev : scene->id.next;
if (do_unlink) {
wmWindow *win = CTX_wm_window(C);
@ -209,8 +216,10 @@ static void rna_Main_scenes_remove(
rna_Main_ID_remove(bmain, reports, scene_ptr, do_unlink, true, true);
}
else {
BKE_reportf(
reports, RPT_ERROR, "Scene '%s' is the last, cannot be removed", scene->id.name + 2);
BKE_reportf(reports,
RPT_ERROR,
"Scene '%s' is the last local one, cannot be removed",
scene->id.name + 2);
}
}
@ -249,6 +258,8 @@ static Object *rna_Main_objects_new(Main *bmain, ReportList *reports, const char
ob->data = data;
BKE_object_materials_test(bmain, ob, ob->data);
WM_main_add_notifier(NC_ID | NA_ADDED, NULL);
return ob;
}
@ -259,6 +270,9 @@ static Material *rna_Main_materials_new(Main *bmain, const char *name)
ID *id = (ID *)BKE_material_add(bmain, safe_name);
id_us_min(id);
WM_main_add_notifier(NC_ID | NA_ADDED, NULL);
return (Material *)id;
}
@ -309,6 +323,9 @@ static Mesh *rna_Main_meshes_new(Main *bmain, const char *name)
Mesh *me = BKE_mesh_add(bmain, safe_name);
id_us_min(&me->id);
WM_main_add_notifier(NC_ID | NA_ADDED, NULL);
return me;
}
@ -331,7 +348,12 @@ static Mesh *rna_Main_meshes_new_from_object(Main *bmain,
return NULL;
}
return BKE_mesh_new_from_object_to_bmain(bmain, depsgraph, object, preserve_all_data_layers);
Mesh *mesh = BKE_mesh_new_from_object_to_bmain(
bmain, depsgraph, object, preserve_all_data_layers);
WM_main_add_notifier(NC_ID | NA_ADDED, NULL);
return mesh;
}
static Light *rna_Main_lights_new(Main *bmain, const char *name, int type)
@ -342,6 +364,9 @@ static Light *rna_Main_lights_new(Main *bmain, const char *name, int type)
Light *lamp = BKE_light_add(bmain, safe_name);
lamp->type = type;
id_us_min(&lamp->id);
WM_main_add_notifier(NC_ID | NA_ADDED, NULL);
return lamp;
}
@ -371,6 +396,9 @@ static Image *rna_Main_images_new(Main *bmain,
is_data,
tiled);
id_us_min(&image->id);
WM_main_add_notifier(NC_ID | NA_ADDED, NULL);
return image;
}
static Image *rna_Main_images_load(Main *bmain,
@ -397,6 +425,9 @@ static Image *rna_Main_images_load(Main *bmain,
}
id_us_min((ID *)ima);
WM_main_add_notifier(NC_ID | NA_ADDED, NULL);
return ima;
}
@ -407,6 +438,9 @@ static Lattice *rna_Main_lattices_new(Main *bmain, const char *name)
Lattice *lt = BKE_lattice_add(bmain, safe_name);
id_us_min(&lt->id);
WM_main_add_notifier(NC_ID | NA_ADDED, NULL);
return lt;
}
@ -417,6 +451,9 @@ static Curve *rna_Main_curves_new(Main *bmain, const char *name, int type)
Curve *cu = BKE_curve_add(bmain, safe_name, type);
id_us_min(&cu->id);
WM_main_add_notifier(NC_ID | NA_ADDED, NULL);
return cu;
}
@ -427,6 +464,9 @@ static MetaBall *rna_Main_metaballs_new(Main *bmain, const char *name)
MetaBall *mb = BKE_mball_add(bmain, safe_name);
id_us_min(&mb->id);
WM_main_add_notifier(NC_ID | NA_ADDED, NULL);
return mb;
}
@ -452,6 +492,9 @@ static VFont *rna_Main_fonts_load(Main *bmain,
filepath,
errno ? strerror(errno) : TIP_("unsupported font format"));
}
WM_main_add_notifier(NC_ID | NA_ADDED, NULL);
return font;
}
@ -463,6 +506,9 @@ static Tex *rna_Main_textures_new(Main *bmain, const char *name, int type)
Tex *tex = BKE_texture_add(bmain, safe_name);
BKE_texture_type_set(tex, type);
id_us_min(&tex->id);
WM_main_add_notifier(NC_ID | NA_ADDED, NULL);
return tex;
}
@ -473,6 +519,9 @@ static Brush *rna_Main_brushes_new(Main *bmain, const char *name, int mode)
Brush *brush = BKE_brush_add(bmain, safe_name, mode);
id_us_min(&brush->id);
WM_main_add_notifier(NC_ID | NA_ADDED, NULL);
return brush;
}
@ -490,6 +539,9 @@ static World *rna_Main_worlds_new(Main *bmain, const char *name)
World *world = BKE_world_add(bmain, safe_name);
id_us_min(&world->id);
WM_main_add_notifier(NC_ID | NA_ADDED, NULL);
return world;
}
@ -498,7 +550,11 @@ static Collection *rna_Main_collections_new(Main *bmain, const char *name)
char safe_name[MAX_ID_NAME - 2];
rna_idname_validate(name, safe_name);
return BKE_collection_add(bmain, NULL, safe_name);
Collection *collection = BKE_collection_add(bmain, NULL, safe_name);
WM_main_add_notifier(NC_ID | NA_ADDED, NULL);
return collection;
}
static Speaker *rna_Main_speakers_new(Main *bmain, const char *name)
@ -508,6 +564,9 @@ static Speaker *rna_Main_speakers_new(Main *bmain, const char *name)
Speaker *speaker = BKE_speaker_add(bmain, safe_name);
id_us_min(&speaker->id);
WM_main_add_notifier(NC_ID | NA_ADDED, NULL);
return speaker;
}
@ -523,6 +582,9 @@ static bSound *rna_Main_sounds_load(Main *bmain, const char *name, bool check_ex
}
id_us_min(&sound->id);
WM_main_add_notifier(NC_ID | NA_ADDED, NULL);
return sound;
}
@ -531,7 +593,11 @@ static Text *rna_Main_texts_new(Main *bmain, const char *name)
char safe_name[MAX_ID_NAME - 2];
rna_idname_validate(name, safe_name);
return BKE_text_add(bmain, safe_name);
Text *text = BKE_text_add(bmain, safe_name);
WM_main_add_notifier(NC_ID | NA_ADDED, NULL);
return text;
}
static Text *rna_Main_texts_load(Main *bmain,
@ -551,6 +617,9 @@ static Text *rna_Main_texts_load(Main *bmain,
filepath,
errno ? strerror(errno) : TIP_("unable to load text"));
}
WM_main_add_notifier(NC_ID | NA_ADDED, NULL);
return txt;
}
@ -561,6 +630,9 @@ static bArmature *rna_Main_armatures_new(Main *bmain, const char *name)
bArmature *arm = BKE_armature_add(bmain, safe_name);
id_us_min(&arm->id);
WM_main_add_notifier(NC_ID | NA_ADDED, NULL);
return arm;
}
@ -571,6 +643,9 @@ static bAction *rna_Main_actions_new(Main *bmain, const char *name)
bAction *act = BKE_action_add(bmain, safe_name);
id_fake_user_clear(&act->id);
WM_main_add_notifier(NC_ID | NA_ADDED, NULL);
return act;
}
@ -581,6 +656,9 @@ static ParticleSettings *rna_Main_particles_new(Main *bmain, const char *name)
ParticleSettings *part = BKE_particlesettings_add(bmain, safe_name);
id_us_min(&part->id);
WM_main_add_notifier(NC_ID | NA_ADDED, NULL);
return part;
}
@ -591,6 +669,9 @@ static Palette *rna_Main_palettes_new(Main *bmain, const char *name)
Palette *palette = BKE_palette_add(bmain, safe_name);
id_us_min(&palette->id);
WM_main_add_notifier(NC_ID | NA_ADDED, NULL);
return (Palette *)palette;
}
@ -622,6 +703,9 @@ static MovieClip *rna_Main_movieclip_load(Main *bmain,
}
id_us_min((ID *)clip);
WM_main_add_notifier(NC_ID | NA_ADDED, NULL);
return clip;
}
@ -630,7 +714,11 @@ static Mask *rna_Main_mask_new(Main *bmain, const char *name)
char safe_name[MAX_ID_NAME - 2];
rna_idname_validate(name, safe_name);
return BKE_mask_new(bmain, safe_name);
Mask *mask = BKE_mask_new(bmain, safe_name);
WM_main_add_notifier(NC_ID | NA_ADDED, NULL);
return mask;
}
static FreestyleLineStyle *rna_Main_linestyles_new(Main *bmain, const char *name)
@ -640,6 +728,9 @@ static FreestyleLineStyle *rna_Main_linestyles_new(Main *bmain, const char *name
FreestyleLineStyle *linestyle = BKE_linestyle_new(bmain, safe_name);
id_us_min(&linestyle->id);
WM_main_add_notifier(NC_ID | NA_ADDED, NULL);
return linestyle;
}
@ -653,6 +744,9 @@ static LightProbe *rna_Main_lightprobe_new(Main *bmain, const char *name, int ty
BKE_lightprobe_type_set(probe, type);
id_us_min(&probe->id);
WM_main_add_notifier(NC_ID | NA_ADDED, NULL);
return probe;
}
@ -663,6 +757,9 @@ static bGPdata *rna_Main_gpencils_new(Main *bmain, const char *name)
bGPdata *gpd = BKE_gpencil_data_addnew(bmain, safe_name);
id_us_min(&gpd->id);
WM_main_add_notifier(NC_ID | NA_ADDED, NULL);
return gpd;
}
@ -674,6 +771,9 @@ static Hair *rna_Main_hairs_new(Main *bmain, const char *name)
Hair *hair = BKE_hair_add(bmain, safe_name);
id_us_min(&hair->id);
WM_main_add_notifier(NC_ID | NA_ADDED, NULL);
return hair;
}
# endif
@ -686,6 +786,9 @@ static PointCloud *rna_Main_pointclouds_new(Main *bmain, const char *name)
PointCloud *pointcloud = BKE_pointcloud_add(bmain, safe_name);
id_us_min(&pointcloud->id);
WM_main_add_notifier(NC_ID | NA_ADDED, NULL);
return pointcloud;
}
# endif
@ -697,6 +800,9 @@ static Volume *rna_Main_volumes_new(Main *bmain, const char *name)
Volume *volume = BKE_volume_add(bmain, safe_name);
id_us_min(&volume->id);
WM_main_add_notifier(NC_ID | NA_ADDED, NULL);
return volume;
}
@ -708,6 +814,9 @@ static Simulation *rna_Main_simulations_new(Main *bmain, const char *name)
Simulation *simulation = BKE_simulation_add(bmain, safe_name);
id_us_min(&simulation->id);
WM_main_add_notifier(NC_ID | NA_ADDED, NULL);
return simulation;
}
# endif

View File

@ -5900,8 +5900,7 @@ static void rna_def_modifier_triangulate(BlenderRNA *brna)
prop = RNA_def_property(srna, "ngon_method", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "ngon_method");
RNA_def_property_enum_items(prop, rna_enum_modifier_triangulate_ngon_method_items);
RNA_def_property_ui_text(
prop, "Polygon Method", "Method for splitting the polygons into triangles");
RNA_def_property_ui_text(prop, "N-gon Method", "Method for splitting the n-gons into triangles");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
prop = RNA_def_property(srna, "min_vertices", PROP_INT, PROP_UNSIGNED);

View File

@ -3245,6 +3245,7 @@ static void rna_NodeGroup_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *
}
ED_node_tag_update_nodetree(bmain, ntree, node);
DEG_relations_tag_update(bmain);
}
static void rna_NodeGroup_node_tree_set(PointerRNA *ptr,
@ -8432,8 +8433,7 @@ static void def_geo_triangulate(StructRNA *srna)
RNA_def_property_enum_sdna(prop, NULL, "custom2");
RNA_def_property_enum_items(prop, rna_node_geometry_triangulate_ngon_method_items);
RNA_def_property_enum_default(prop, GEO_NODE_TRIANGULATE_NGON_BEAUTY);
RNA_def_property_ui_text(
prop, "Polygon Method", "Method for splitting the polygons into triangles");
RNA_def_property_ui_text(prop, "N-gon Method", "Method for splitting the n-gons into triangles");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
}

View File

@ -135,7 +135,7 @@ static void rna_def_pointcloud(BlenderRNA *brna)
PropertyRNA *prop;
srna = RNA_def_struct(brna, "PointCloud", "ID");
RNA_def_struct_ui_text(srna, "PointCloud", "Point cloud data-block");
RNA_def_struct_ui_text(srna, "Point Cloud", "Point cloud data-block");
RNA_def_struct_ui_icon(srna, ICON_POINTCLOUD_DATA);
/* geometry */

View File

@ -2821,6 +2821,7 @@ static void rna_def_view3d_cursor(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "View3DCursor");
RNA_def_struct_path_func(srna, "rna_View3DCursor_path");
RNA_def_struct_ui_text(srna, "3D Cursor", "");
RNA_def_struct_ui_icon(srna, ICON_CURSOR);
prop = RNA_def_property(srna, "location", PROP_FLOAT, PROP_XYZ_LENGTH);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);

View File

@ -420,10 +420,10 @@ void RNA_api_scene(StructRNA *srna)
"Method for splitting the quads into triangles");
RNA_def_enum(func,
"ngon_method",
rna_enum_modifier_triangulate_quad_method_items,
rna_enum_modifier_triangulate_ngon_method_items,
0,
"Polygon Method",
"Method for splitting the polygons into triangles");
"N-gon Method",
"Method for splitting the n-gons into triangles");
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
# endif

View File

@ -754,6 +754,9 @@ void MOD_nodes_init(Main *bmain, NodesModifierData *nmd)
bNode *group_input_node = nodeAddStaticNode(nullptr, ntree, NODE_GROUP_INPUT);
bNode *group_output_node = nodeAddStaticNode(nullptr, ntree, NODE_GROUP_OUTPUT);
nodeSetSelected(group_input_node, false);
nodeSetSelected(group_output_node, false);
group_input_node->locx = -200 - group_input_node->width;
group_output_node->locx = 200;
group_output_node->flag |= NODE_DO_OUTPUT;

View File

@ -20,6 +20,7 @@
* \ingroup modifiers
*/
#include "BLI_alloca.h"
#include "BLI_math.h"
#include "BLI_math_geom.h"
#include "BLI_task.h"
@ -160,7 +161,9 @@ typedef struct SDefDeformData {
const SDefVert *const bind_verts;
float (*const targetCos)[3];
float (*const vertexCos)[3];
float *const weights;
const MDeformVert *const dvert;
int const defgrp_index;
bool const invert_vgroup;
float const strength;
} SDefDeformData;
@ -1191,7 +1194,17 @@ static void deformVert(void *__restrict userdata,
const int num_binds = data->bind_verts[index].numbinds;
float *const vertexCos = data->vertexCos[index];
float norm[3], temp[3], offset[3];
const float weight = (data->weights != NULL) ? data->weights[index] : 1.0f;
/* Retrieve the value of the weight vertex group if specified. */
float weight = 1.0f;
if (data->dvert && data->defgrp_index != -1) {
weight = BKE_defvert_find_weight(&data->dvert[index], data->defgrp_index);
if (data->invert_vgroup) {
weight = 1.0f - weight;
}
}
/* Check if this vertex will be deformed. If it is not deformed we return and avoid
* unnecessary calculations. */
@ -1206,7 +1219,16 @@ static void deformVert(void *__restrict userdata,
for (int j = 0; j < num_binds; j++) {
max_verts = MAX2(max_verts, sdbind[j].numverts);
}
float(*coords_buffer)[3] = MEM_malloc_arrayN(max_verts, sizeof(*coords_buffer), __func__);
const bool big_buffer = max_verts > 256;
float(*coords_buffer)[3];
if (UNLIKELY(big_buffer)) {
coords_buffer = MEM_malloc_arrayN(max_verts, sizeof(*coords_buffer), __func__);
}
else {
coords_buffer = BLI_array_alloca(coords_buffer, max_verts);
}
for (int j = 0; j < num_binds; j++, sdbind++) {
for (int k = 0; k < sdbind->numverts; k++) {
@ -1216,28 +1238,32 @@ static void deformVert(void *__restrict userdata,
normal_poly_v3(norm, coords_buffer, sdbind->numverts);
zero_v3(temp);
/* ---------- looptri mode ---------- */
if (sdbind->mode == MOD_SDEF_MODE_LOOPTRI) {
madd_v3_v3fl(temp, data->targetCos[sdbind->vert_inds[0]], sdbind->vert_weights[0]);
madd_v3_v3fl(temp, data->targetCos[sdbind->vert_inds[1]], sdbind->vert_weights[1]);
madd_v3_v3fl(temp, data->targetCos[sdbind->vert_inds[2]], sdbind->vert_weights[2]);
}
else {
switch (sdbind->mode) {
/* ---------- looptri mode ---------- */
case MOD_SDEF_MODE_LOOPTRI: {
madd_v3_v3fl(temp, data->targetCos[sdbind->vert_inds[0]], sdbind->vert_weights[0]);
madd_v3_v3fl(temp, data->targetCos[sdbind->vert_inds[1]], sdbind->vert_weights[1]);
madd_v3_v3fl(temp, data->targetCos[sdbind->vert_inds[2]], sdbind->vert_weights[2]);
break;
}
/* ---------- ngon mode ---------- */
if (sdbind->mode == MOD_SDEF_MODE_NGON) {
case MOD_SDEF_MODE_NGON: {
for (int k = 0; k < sdbind->numverts; k++) {
madd_v3_v3fl(temp, coords_buffer[k], sdbind->vert_weights[k]);
}
break;
}
/* ---------- centroid mode ---------- */
else if (sdbind->mode == MOD_SDEF_MODE_CENTROID) {
case MOD_SDEF_MODE_CENTROID: {
float cent[3];
mid_v3_v3_array(cent, coords_buffer, sdbind->numverts);
madd_v3_v3fl(temp, data->targetCos[sdbind->vert_inds[0]], sdbind->vert_weights[0]);
madd_v3_v3fl(temp, data->targetCos[sdbind->vert_inds[1]], sdbind->vert_weights[1]);
madd_v3_v3fl(temp, cent, sdbind->vert_weights[2]);
break;
}
}
@ -1251,7 +1277,10 @@ static void deformVert(void *__restrict userdata,
/* Add the offset to start coord multiplied by the strength and weight values. */
madd_v3_v3fl(vertexCos, offset, data->strength * weight);
MEM_freeN(coords_buffer);
if (UNLIKELY(big_buffer)) {
MEM_freeN(coords_buffer);
}
}
static void surfacedeformModifier_do(ModifierData *md,
@ -1332,33 +1361,16 @@ static void surfacedeformModifier_do(ModifierData *md,
int defgrp_index;
MDeformVert *dvert;
MOD_get_vgroup(ob, mesh, smd->defgrp_name, &dvert, &defgrp_index);
float *weights = NULL;
const bool invert_group = (smd->flags & MOD_SDEF_INVERT_VGROUP) != 0;
if (defgrp_index != -1) {
dvert = CustomData_duplicate_referenced_layer(&mesh->vdata, CD_MDEFORMVERT, mesh->totvert);
/* If no vertices were ever added to an object's vgroup, dvert might be NULL. */
if (dvert == NULL) {
/* Add a valid data layer! */
dvert = CustomData_add_layer(&mesh->vdata, CD_MDEFORMVERT, CD_CALLOC, NULL, mesh->totvert);
}
if (dvert) {
weights = MEM_calloc_arrayN((size_t)numverts, sizeof(*weights), __func__);
MDeformVert *dv = dvert;
for (uint i = 0; i < numverts; i++, dv++) {
weights[i] = invert_group ? (1.0f - BKE_defvert_find_weight(dv, defgrp_index)) :
BKE_defvert_find_weight(dv, defgrp_index);
}
}
}
const bool invert_vgroup = (smd->flags & MOD_SDEF_INVERT_VGROUP) != 0;
/* Actual vertex location update starts here */
SDefDeformData data = {
.bind_verts = smd->verts,
.targetCos = MEM_malloc_arrayN(tnumverts, sizeof(float[3]), "SDefTargetVertArray"),
.vertexCos = vertexCos,
.weights = weights,
.dvert = dvert,
.defgrp_index = defgrp_index,
.invert_vgroup = invert_vgroup,
.strength = smd->strength,
};
@ -1372,8 +1384,6 @@ static void surfacedeformModifier_do(ModifierData *md,
MEM_freeN(data.targetCos);
}
MEM_SAFE_FREE(weights);
}
static void deformVerts(ModifierData *md,
@ -1449,9 +1459,9 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel)
col = uiLayoutColumn(layout, false);
uiLayoutSetActive(col, !is_bound);
uiItemR(col, ptr, "target", 0, NULL, ICON_NONE);
uiItemR(col, ptr, "falloff", 0, NULL, ICON_NONE);
uiItemR(col, ptr, "strength", 0, NULL, ICON_NONE);
uiItemR(layout, ptr, "strength", 0, NULL, ICON_NONE);
modifier_vgroup_ui(layout, ptr, &ob_ptr, "vertex_group", "invert_vertex_group", NULL);

View File

@ -161,10 +161,11 @@ static void add_instances_from_geometry_component(InstancesComponent &instances,
"rotation", domain, {0, 0, 0});
Float3ReadAttribute scales = src_geometry.attribute_get_for_read<float3>(
"scale", domain, {1, 1, 1});
Int32ReadAttribute ids = src_geometry.attribute_get_for_read<int>("id", domain, -1);
for (const int i : IndexRange(domain_size)) {
if (instances_data[i].has_value()) {
instances.add_instance(*instances_data[i], positions[i], rotations[i], scales[i]);
instances.add_instance(*instances_data[i], positions[i], rotations[i], scales[i], ids[i]);
}
}
}

View File

@ -195,10 +195,14 @@ void BPY_context_dict_clear_members_array(void **dict_p,
PyObject *dict = *dict_p;
BLI_assert(PyDict_Check(dict));
/* Use #PyDict_Pop instead of #PyDict_DelItemString to avoid setting the exception,
* while supported it's good to avoid for low level functions like this that run often. */
for (uint i = 0; i < context_members_len; i++) {
if (PyDict_DelItemString(dict, context_members[i])) {
PyErr_Clear();
}
PyObject *key = PyUnicode_FromString(context_members[i]);
PyObject *item = _PyDict_Pop(dict, key, Py_None);
Py_DECREF(key);
Py_DECREF(item);
}
if (use_gil) {
@ -532,7 +536,7 @@ void BPY_DECREF(void *pyob_ptr)
void BPY_DECREF_RNA_INVALIDATE(void *pyob_ptr)
{
const PyGILState_STATE gilstate = PyGILState_Ensure();
const int do_invalidate = (Py_REFCNT((PyObject *)pyob_ptr) > 1);
const bool do_invalidate = (Py_REFCNT((PyObject *)pyob_ptr) > 1);
Py_DECREF((PyObject *)pyob_ptr);
if (do_invalidate) {
pyrna_invalidate(pyob_ptr);

View File

@ -204,7 +204,7 @@ void RE_engine_update_memory_stats(RenderEngine *engine, float mem_used, float m
void RE_engine_report(RenderEngine *engine, int type, const char *msg);
void RE_engine_set_error_message(RenderEngine *engine, const char *msg);
int RE_engine_render(struct Render *re, int do_all);
bool RE_engine_render(struct Render *re, bool do_all);
bool RE_engine_is_external(const struct Render *re);

View File

@ -803,23 +803,23 @@ static void engine_render_view_layer(Render *re,
engine_depsgraph_free(engine);
}
int RE_engine_render(Render *re, int do_all)
bool RE_engine_render(Render *re, bool do_all)
{
RenderEngineType *type = RE_engines_find(re->r.engine);
bool persistent_data = (re->r.mode & R_PERSISTENT_DATA) != 0;
/* verify if we can render */
if (!type->render) {
return 0;
return false;
}
if ((re->r.scemode & R_BUTS_PREVIEW) && !(type->flag & RE_USE_PREVIEW)) {
return 0;
return false;
}
if (do_all && !(type->flag & RE_USE_POSTPROCESS)) {
return 0;
return false;
}
if (!do_all && (type->flag & RE_USE_POSTPROCESS)) {
return 0;
return false;
}
/* Lock drawing in UI during data phase. */
@ -859,7 +859,7 @@ int RE_engine_render(Render *re, int do_all)
*/
BKE_report(re->reports, RPT_ERROR, "Failed allocate render result, out of memory");
G.is_break = true;
return 1;
return true;
}
/* set render info */
@ -977,7 +977,7 @@ int RE_engine_render(Render *re, int do_all)
}
#endif
return 1;
return true;
}
void RE_engine_update_render_passes(struct RenderEngine *engine,

View File

@ -1130,7 +1130,7 @@ void RE_AddObject(Render *UNUSED(re), Object *UNUSED(ob))
static void do_render_3d(Render *re)
{
re->current_scene_update(re->suh, re->scene);
RE_engine_render(re, 0);
RE_engine_render(re, false);
}
/* make sure disprect is not affected by the render border */
@ -1599,7 +1599,7 @@ static void do_render_all_options(Render *re)
BKE_image_all_free_anim_ibufs(re->main, re->r.cfra);
SEQ_relations_free_all_anim_ibufs(re->scene, re->r.cfra);
if (RE_engine_render(re, 1)) {
if (RE_engine_render(re, true)) {
/* in this case external render overrides all */
}
else if (RE_seq_render_active(re->scene, &re->r)) {

View File

@ -133,7 +133,6 @@ Sequence *SEQ_sequence_alloc(ListBase *lb, int timeline_frame, int machine, int
seq->strip = seq_strip_alloc(type);
seq->stereo3d_format = MEM_callocN(sizeof(Stereo3dFormat), "Sequence Stereo Format");
seq->cache_flag = SEQ_CACHE_STORE_RAW | SEQ_CACHE_STORE_PREPROCESSED | SEQ_CACHE_STORE_COMPOSITE;
SEQ_relations_session_uuid_generate(seq);
@ -247,8 +246,7 @@ Editing *SEQ_editing_ensure(Scene *scene)
ed->seqbasep = &ed->seqbase;
ed->cache = NULL;
ed->cache_flag = SEQ_CACHE_STORE_FINAL_OUT;
ed->cache_flag |= SEQ_CACHE_VIEW_FINAL_OUT;
ed->cache_flag |= SEQ_CACHE_VIEW_ENABLE;
ed->cache_flag |= SEQ_CACHE_STORE_RAW;
}
return scene->ed;