Curves: initial surface collision for curves sculpt mode #104469
|
@ -2,15 +2,19 @@
|
|||
path = release/scripts/addons
|
||||
url = ../blender-addons.git
|
||||
branch = main
|
||||
ignore = all
|
||||
[submodule "release/scripts/addons_contrib"]
|
||||
path = release/scripts/addons_contrib
|
||||
url = ../blender-addons-contrib.git
|
||||
branch = main
|
||||
ignore = all
|
||||
[submodule "release/datafiles/locale"]
|
||||
path = release/datafiles/locale
|
||||
url = ../blender-translations.git
|
||||
branch = main
|
||||
ignore = all
|
||||
[submodule "source/tools"]
|
||||
path = source/tools
|
||||
url = ../blender-dev-tools.git
|
||||
branch = main
|
||||
ignore = all
|
||||
|
|
|
@ -12,6 +12,7 @@ from bpy.props import (
|
|||
PointerProperty,
|
||||
StringProperty,
|
||||
)
|
||||
from bpy.app.translations import pgettext_iface as iface_
|
||||
|
||||
from math import pi
|
||||
|
||||
|
@ -1664,30 +1665,48 @@ class CyclesPreferences(bpy.types.AddonPreferences):
|
|||
col.label(text="No compatible GPUs found for Cycles", icon='INFO')
|
||||
|
||||
if device_type == 'CUDA':
|
||||
col.label(text="Requires NVIDIA GPU with compute capability 3.0", icon='BLANK1')
|
||||
compute_capability = "3.0"
|
||||
col.label(text=iface_("Requires NVIDIA GPU with compute capability %s") % compute_capability,
|
||||
icon='BLANK1', translate=False)
|
||||
elif device_type == 'OPTIX':
|
||||
col.label(text="Requires NVIDIA GPU with compute capability 5.0", icon='BLANK1')
|
||||
col.label(text="and NVIDIA driver version 470 or newer", icon='BLANK1')
|
||||
compute_capability = "5.0"
|
||||
driver_version = "470"
|
||||
col.label(text=iface_("Requires NVIDIA GPU with compute capability %s") % compute_capability,
|
||||
icon='BLANK1', translate=False)
|
||||
col.label(text="and NVIDIA driver version %s or newer" % driver_version,
|
||||
icon='BLANK1', translate=False)
|
||||
elif device_type == 'HIP':
|
||||
import sys
|
||||
if sys.platform[:3] == "win":
|
||||
driver_version = "21.Q4"
|
||||
col.label(text="Requires AMD GPU with RDNA architecture", icon='BLANK1')
|
||||
col.label(text="and AMD Radeon Pro 21.Q4 driver or newer", icon='BLANK1')
|
||||
col.label(text=iface_("and AMD Radeon Pro %s driver or newer") % driver_version,
|
||||
icon='BLANK1', translate=False)
|
||||
elif sys.platform.startswith("linux"):
|
||||
driver_version = "22.10"
|
||||
col.label(text="Requires AMD GPU with RDNA architecture", icon='BLANK1')
|
||||
col.label(text="and AMD driver version 22.10 or newer", icon='BLANK1')
|
||||
col.label(text=iface_("and AMD driver version %s or newer") % driver_version, icon='BLANK1',
|
||||
translate=False)
|
||||
elif device_type == 'ONEAPI':
|
||||
import sys
|
||||
if sys.platform.startswith("win"):
|
||||
driver_version = "101.4032"
|
||||
col.label(text="Requires Intel GPU with Xe-HPG architecture", icon='BLANK1')
|
||||
col.label(text="and Windows driver version 101.4032 or newer", icon='BLANK1')
|
||||
col.label(text=iface_("and Windows driver version %s or newer") % driver_version,
|
||||
icon='BLANK1', translate=False)
|
||||
elif sys.platform.startswith("linux"):
|
||||
driver_version = "1.3.24931"
|
||||
col.label(text="Requires Intel GPU with Xe-HPG architecture and", icon='BLANK1')
|
||||
col.label(text=" - intel-level-zero-gpu version 1.3.24931 or newer", icon='BLANK1')
|
||||
col.label(text=iface_(" - intel-level-zero-gpu version %s or newer") % driver_version,
|
||||
icon='BLANK1', translate=False)
|
||||
col.label(text=" - oneAPI Level-Zero Loader", icon='BLANK1')
|
||||
elif device_type == 'METAL':
|
||||
col.label(text="Requires Apple Silicon with macOS 12.2 or newer", icon='BLANK1')
|
||||
col.label(text="or AMD with macOS 12.3 or newer", icon='BLANK1')
|
||||
silicon_mac_version = "12.2"
|
||||
amd_mac_version = "12.3"
|
||||
col.label(text=iface_("Requires Apple Silicon with macOS %s or newer") % silicon_mac_version,
|
||||
icon='BLANK1', translate=False)
|
||||
col.label(text=iface_("or AMD with macOS %s or newer") % amd_mac_version, icon='BLANK1',
|
||||
translate=False)
|
||||
return
|
||||
|
||||
for device in devices:
|
||||
|
|
|
@ -105,6 +105,7 @@ MetalDevice::MetalDevice(const DeviceInfo &info, Stats &stats, Profiler &profile
|
|||
}
|
||||
case METAL_GPU_AMD: {
|
||||
max_threads_per_threadgroup = 128;
|
||||
use_metalrt = info.use_metalrt;
|
||||
break;
|
||||
}
|
||||
case METAL_GPU_APPLE: {
|
||||
|
|
|
@ -341,7 +341,7 @@ bool GHOST_NDOFManager::setDevice(ushort vendor_id, ushort product_id)
|
|||
hid_map_button_mask_ = int(~(UINT_MAX << hid_map_button_num_));
|
||||
}
|
||||
|
||||
CLOG_INFO(LOG, 2, "%d buttons -> hex:%X", hid_map_button_num_, (uint)hid_map_button_mask_);
|
||||
CLOG_INFO(LOG, 2, "%d buttons -> hex:%X", hid_map_button_num_, uint(hid_map_button_mask_));
|
||||
|
||||
return device_type_ != NDOF_UnknownDevice;
|
||||
}
|
||||
|
@ -445,14 +445,14 @@ void GHOST_NDOFManager::updateButton(int button_number, bool press, uint64_t tim
|
|||
2,
|
||||
"button=%d, press=%d (out of range %d, ignoring!)",
|
||||
button_number,
|
||||
(int)press,
|
||||
int(press),
|
||||
hid_map_button_num_);
|
||||
return;
|
||||
}
|
||||
const NDOF_ButtonT button = hid_map_[button_number];
|
||||
if (button == NDOF_BUTTON_NONE) {
|
||||
CLOG_INFO(
|
||||
LOG, 2, "button=%d, press=%d (mapped to none, ignoring!)", button_number, (int)press);
|
||||
LOG, 2, "button=%d, press=%d (mapped to none, ignoring!)", button_number, int(press));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -460,7 +460,7 @@ void GHOST_NDOFManager::updateButton(int button_number, bool press, uint64_t tim
|
|||
2,
|
||||
"button=%d, press=%d, name=%s",
|
||||
button_number,
|
||||
(int)press,
|
||||
int(press),
|
||||
ndof_button_names[button]);
|
||||
|
||||
GHOST_IWindow *window = system_.getWindowManager()->getActiveWindow();
|
||||
|
|
|
@ -424,10 +424,9 @@ bool GHOST_SystemWin32::processEvents(bool waitForEvent)
|
|||
|
||||
processTrackpad();
|
||||
|
||||
/* PeekMessage above is allowed to dispatch messages to the wndproc without us
|
||||
/* `PeekMessage` above is allowed to dispatch messages to the `wndproc` without us
|
||||
* noticing, so we need to check the event manager here to see if there are
|
||||
* events waiting in the queue.
|
||||
*/
|
||||
* events waiting in the queue. */
|
||||
hasEventHandled |= this->m_eventManager->getNumEvents() > 0;
|
||||
|
||||
} while (waitForEvent && !hasEventHandled);
|
||||
|
|
|
@ -487,7 +487,7 @@ def disable_all():
|
|||
|
||||
|
||||
def _blender_manual_url_prefix():
|
||||
return "https://docs.blender.org/manual/en/%d.%d" % _bpy.app.version[:2]
|
||||
return "https://docs.blender.org/manual/%s/%d.%d" % (_bpy.utils.manual_language_code(), *_bpy.app.version[:2])
|
||||
|
||||
|
||||
def module_bl_info(mod, *, info_basis=None):
|
||||
|
|
|
@ -26,6 +26,7 @@ __all__ = (
|
|||
"register_tool",
|
||||
"make_rna_paths",
|
||||
"manual_map",
|
||||
"manual_language_code",
|
||||
"previews",
|
||||
"resource_path",
|
||||
"script_path_user",
|
||||
|
@ -1035,6 +1036,53 @@ def manual_map():
|
|||
yield prefix, url_manual_mapping
|
||||
|
||||
|
||||
# Languages which are supported by the user manual (commented when there is no translation).
|
||||
_manual_language_codes = {
|
||||
"ar_EG": "ar", # Arabic
|
||||
# "bg_BG": "bg", # Bulgarian
|
||||
# "ca_AD": "ca", # Catalan
|
||||
# "cs_CZ": "cz", # Czech
|
||||
"de_DE": "de", # German
|
||||
# "el_GR": "el", # Greek
|
||||
"es": "es", # Spanish
|
||||
"fi_FI": "fi", # Finnish
|
||||
"fr_FR": "fr", # French
|
||||
"id_ID": "id", # Indonesian
|
||||
"it_IT": "it", # Italian
|
||||
"ja_JP": "ja", # Japanese
|
||||
"ko_KR": "ko", # Korean
|
||||
# "nb": "nb", # Norwegian
|
||||
# "nl_NL": "nl", # Dutch
|
||||
# "pl_PL": "pl", # Polish
|
||||
"pt_PT": "pt", # Portuguese
|
||||
# Portuguese - Brazil, for until we have a pt_BR version.
|
||||
"pt_BR": "pt",
|
||||
"ru_RU": "ru", # Russian
|
||||
"sk_SK": "sk", # Slovak
|
||||
# "sl": "sl", # Slovenian
|
||||
"sr_RS": "sr", # Serbian
|
||||
# "sv_SE": "sv", # Swedish
|
||||
# "tr_TR": "th", # Thai
|
||||
"uk_UA": "uk", # Ukrainian
|
||||
"vi_VN": "vi", # Vietnamese
|
||||
"zh_CN": "zh-hans", # Simplified Chinese
|
||||
"zh_TW": "zh-hant", # Traditional Chinese
|
||||
}
|
||||
|
||||
|
||||
def manual_language_code(default="en"):
|
||||
"""
|
||||
:return:
|
||||
The language code used for user manual URL component based on the current language user-preference,
|
||||
falling back to the ``default`` when unavailable.
|
||||
:rtype: str
|
||||
"""
|
||||
language = _bpy.context.preferences.view.language
|
||||
if language == 'DEFAULT':
|
||||
language = _os.getenv("LANG", "").split(".")[0]
|
||||
return _manual_language_codes.get(language, default)
|
||||
|
||||
|
||||
# Build an RNA path from struct/property/enum names.
|
||||
def make_rna_paths(struct_name, prop_name, enum_name):
|
||||
"""
|
||||
|
|
|
@ -4,38 +4,10 @@
|
|||
# autopep8: off
|
||||
import bpy
|
||||
|
||||
manual_version = '%d.%d' % bpy.app.version[:2]
|
||||
|
||||
url_manual_prefix = "https://docs.blender.org/manual/en/" + manual_version + "/"
|
||||
|
||||
language = bpy.context.preferences.view.language
|
||||
if language == 'DEFAULT':
|
||||
import os
|
||||
language = os.getenv('LANG', '').split('.')[0]
|
||||
|
||||
LANG = {
|
||||
"ar_EG": "ar",
|
||||
"de_DE": "de",
|
||||
"es": "es",
|
||||
"fi_FI": "fi",
|
||||
"fr_FR": "fr",
|
||||
"id_ID": "id",
|
||||
"it_IT": "it",
|
||||
"ja_JP": "ja",
|
||||
"ko_KR": "ko",
|
||||
"pt_PT": "pt",
|
||||
"pt_BR": "pt",
|
||||
"ru_RU": "ru",
|
||||
"sk_SK": "sk",
|
||||
"sr_RS": "sr",
|
||||
"uk_UA": "uk",
|
||||
"vi_VN": "vi",
|
||||
"zh_CN": "zh-hans",
|
||||
"zh_TW": "zh-hant",
|
||||
}.get(language)
|
||||
|
||||
if LANG is not None:
|
||||
url_manual_prefix = url_manual_prefix.replace("manual/en", "manual/" + LANG)
|
||||
url_manual_prefix = "https://docs.blender.org/manual/%s/%d.%d/" % (
|
||||
bpy.utils.manual_language_code(),
|
||||
*bpy.app.version[:2],
|
||||
)
|
||||
|
||||
url_manual_mapping = (
|
||||
("bpy.types.movietrackingsettings.refine_intrinsics_tangential_distortion*", "movie_clip/tracking/clip/toolbar/solve.html#bpy-types-movietrackingsettings-refine-intrinsics-tangential-distortion"),
|
||||
|
@ -641,7 +613,6 @@ url_manual_mapping = (
|
|||
("bpy.types.volumedisplay.interpolation_method*", "modeling/volumes/properties.html#bpy-types-volumedisplay-interpolation-method"),
|
||||
("bpy.ops.geometry.color_attribute_render_set*", "modeling/meshes/properties/object_data.html#bpy-ops-geometry-color-attribute-render-set"),
|
||||
("bpy.ops.mesh.customdata_crease_vertex_clear*", "modeling/meshes/properties/custom_data.html#bpy-ops-mesh-customdata-crease-vertex-clear"),
|
||||
("bpy.types.brush.html#bpy.types.brush.jitter*", "sculpt_paint/brush/stroke.html#bpy-types-brush-html-bpy-types-brush-jitter"),
|
||||
("bpy.types.brushgpencilsettings.angle_factor*", "grease_pencil/modes/draw/tools/draw.html#bpy-types-brushgpencilsettings-angle-factor"),
|
||||
("bpy.types.brushgpencilsettings.pen_strength*", "grease_pencil/modes/draw/tools/erase.html#bpy-types-brushgpencilsettings-pen-strength"),
|
||||
("bpy.types.clothcollisionsettings.collection*", "physics/cloth/settings/collisions.html#bpy-types-clothcollisionsettings-collection"),
|
||||
|
@ -672,7 +643,7 @@ url_manual_mapping = (
|
|||
("bpy.types.geometrynodeinputmeshedgevertices*", "modeling/geometry_nodes/mesh/read/edge_vertices.html#bpy-types-geometrynodeinputmeshedgevertices"),
|
||||
("bpy.types.geometrynodeinputmeshfaceisplanar*", "modeling/geometry_nodes/mesh/read/face_is_planar.html#bpy-types-geometrynodeinputmeshfaceisplanar"),
|
||||
("bpy.types.geometrynodeinputsplineresolution*", "modeling/geometry_nodes/curve/read/spline_resolution.html#bpy-types-geometrynodeinputsplineresolution"),
|
||||
("bpy.types.geometrynodemeshfacesetboundaries*", "modeling/geometry_nodes/mesh/read/face_set_boundaries.html#bpy-types-geometrynodemeshfacesetboundaries"),
|
||||
("bpy.types.geometrynodemeshfacesetboundaries*", "modeling/geometry_nodes/mesh/read/face_group_boundaries.html#bpy-types-geometrynodemeshfacesetboundaries"),
|
||||
("bpy.types.greasepencil.curve_edit_threshold*", "grease_pencil/modes/edit/curve_editing.html#bpy-types-greasepencil-curve-edit-threshold"),
|
||||
("bpy.types.lineartgpencilmodifier.use_crease*", "grease_pencil/modifiers/generate/line_art.html#bpy-types-lineartgpencilmodifier-use-crease"),
|
||||
("bpy.types.lineartgpencilmodifier.use_shadow*", "grease_pencil/modifiers/generate/line_art.html#bpy-types-lineartgpencilmodifier-use-shadow"),
|
||||
|
@ -1417,6 +1388,7 @@ url_manual_mapping = (
|
|||
("bpy.types.functionnodereplacestring*", "modeling/geometry_nodes/utilities/text/replace_string.html#bpy-types-functionnodereplacestring"),
|
||||
("bpy.types.functionnodeseparatecolor*", "modeling/geometry_nodes/utilities/color/separate_color.html#bpy-types-functionnodeseparatecolor"),
|
||||
("bpy.types.functionnodevaluetostring*", "modeling/geometry_nodes/utilities/text/value_to_string.html#bpy-types-functionnodevaluetostring"),
|
||||
("bpy.types.geometrynodeblurattribute*", "modeling/geometry_nodes/attribute/blur_attribute.html#bpy-types-geometrynodeblurattribute"),
|
||||
("bpy.types.geometrynodecurvetopoints*", "modeling/geometry_nodes/curve/operations/curve_to_points.html#bpy-types-geometrynodecurvetopoints"),
|
||||
("bpy.types.geometrynodeedgesofcorner*", "modeling/geometry_nodes/mesh/topology/edges_of_corner.html#bpy-types-geometrynodeedgesofcorner"),
|
||||
("bpy.types.geometrynodeedgesofvertex*", "modeling/geometry_nodes/mesh/topology/edges_of_vertex.html#bpy-types-geometrynodeedgesofvertex"),
|
||||
|
@ -2055,7 +2027,6 @@ url_manual_mapping = (
|
|||
("bpy.ops.graph.equalize_handles*", "editors/graph_editor/fcurves/editing.html#bpy-ops-graph-equalize-handles"),
|
||||
("bpy.ops.mball.delete_metaelems*", "modeling/metas/editing.html#bpy-ops-mball-delete-metaelems"),
|
||||
("bpy.ops.mball.reveal_metaelems*", "modeling/metas/properties.html#bpy-ops-mball-reveal-metaelems"),
|
||||
("bpy.ops.mesh.bridge-edge-loops*", "modeling/meshes/editing/edge/bridge_edge_loops.html#bpy-ops-mesh-bridge-edge-loops"),
|
||||
("bpy.ops.mesh.intersect_boolean*", "modeling/meshes/editing/face/intersect_boolean.html#bpy-ops-mesh-intersect-boolean"),
|
||||
("bpy.ops.mesh.loop_multi_select*", "modeling/meshes/selecting/loops.html#bpy-ops-mesh-loop-multi-select"),
|
||||
("bpy.ops.mesh.vert_connect_path*", "modeling/meshes/editing/vertex/connect_vertex_path.html#bpy-ops-mesh-vert-connect-path"),
|
||||
|
@ -2111,7 +2082,6 @@ url_manual_mapping = (
|
|||
("bpy.types.geometrynodeboundbox*", "modeling/geometry_nodes/geometry/operations/bounding_box.html#bpy-types-geometrynodeboundbox"),
|
||||
("bpy.types.geometrynodecurvearc*", "modeling/geometry_nodes/curve/primitives/arc.html#bpy-types-geometrynodecurvearc"),
|
||||
("bpy.types.geometrynodedualmesh*", "modeling/geometry_nodes/mesh/operations/dual_mesh.html#bpy-types-geometrynodedualmesh"),
|
||||
("bpy.types.geometrynodematerial*", "-1"),
|
||||
("bpy.types.geometrynodemeshcone*", "modeling/geometry_nodes/mesh/primitives/cone.html#bpy-types-geometrynodemeshcone"),
|
||||
("bpy.types.geometrynodemeshcube*", "modeling/geometry_nodes/mesh/primitives/cube.html#bpy-types-geometrynodemeshcube"),
|
||||
("bpy.types.geometrynodemeshgrid*", "modeling/geometry_nodes/mesh/primitives/grid.html#bpy-types-geometrynodemeshgrid"),
|
||||
|
|
|
@ -3478,7 +3478,8 @@ def km_animation_channels(params):
|
|||
# Selection.
|
||||
*_template_items_select_actions(params, "anim.channels_select_all"),
|
||||
("anim.channels_select_box", {"type": 'B', "value": 'PRESS'}, None),
|
||||
("anim.channels_select_box", {"type": 'LEFTMOUSE', "value": 'CLICK_DRAG'}, None),
|
||||
("anim.channels_select_box", {"type": 'LEFTMOUSE', "value": 'CLICK_DRAG'},
|
||||
{"properties": [("extend", False)]}),
|
||||
("anim.channels_select_box", {"type": 'LEFTMOUSE', "value": 'CLICK_DRAG', "shift": True},
|
||||
{"properties": [("extend", True)]}),
|
||||
("anim.channels_select_box", {"type": 'LEFTMOUSE', "value": 'CLICK_DRAG', "ctrl": True},
|
||||
|
@ -5627,6 +5628,7 @@ def km_curves(params):
|
|||
("curves.disable_selection", {"type": 'ONE', "value": 'PRESS', "alt": True}, None),
|
||||
("curves.disable_selection", {"type": 'TWO', "value": 'PRESS', "alt": True}, None),
|
||||
*_template_items_select_actions(params, "curves.select_all"),
|
||||
("curves.select_linked", {"type": 'L', "value": 'PRESS', "ctrl": True}, None),
|
||||
])
|
||||
|
||||
return keymap
|
||||
|
|
|
@ -1056,7 +1056,7 @@ class WM_OT_url_open_preset(Operator):
|
|||
return "https://www.blender.org/download/releases/%d-%d/" % bpy.app.version[:2]
|
||||
|
||||
def _url_from_manual(self, _context):
|
||||
return "https://docs.blender.org/manual/en/%d.%d/" % bpy.app.version[:2]
|
||||
return "https://docs.blender.org/manual/%s/%d.%d/" % (bpy.utils.manual_language_code(), *bpy.app.version[:2])
|
||||
|
||||
def _url_from_api(self, _context):
|
||||
return "https://docs.blender.org/api/%d.%d/" % bpy.app.version[:2]
|
||||
|
|
|
@ -35,19 +35,10 @@ def draw_node_group_add_menu(context, layout):
|
|||
if node_tree:
|
||||
from nodeitems_builtins import node_tree_group_type
|
||||
|
||||
def contains_group(nodetree, group):
|
||||
if nodetree == group:
|
||||
return True
|
||||
for node in nodetree.nodes:
|
||||
if node.bl_idname in node_tree_group_type.values() and node.node_tree is not None:
|
||||
if contains_group(node.node_tree, group):
|
||||
return True
|
||||
return False
|
||||
|
||||
groups = [
|
||||
group for group in context.blend_data.node_groups
|
||||
if (group.bl_idname == node_tree.bl_idname and
|
||||
not contains_group(group, node_tree) and
|
||||
not group.contains_tree(node_tree) and
|
||||
not group.name.startswith('.'))
|
||||
]
|
||||
if groups:
|
||||
|
|
|
@ -338,6 +338,7 @@ class NODE_MT_geometry_node_GEO_MESH_READ(Menu):
|
|||
node_add_menu.add_node_type(layout, "GeometryNodeInputMeshEdgeAngle")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeInputMeshEdgeNeighbors")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeInputMeshEdgeVertices")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeEdgesToFaceGroups")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeInputMeshFaceArea")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeInputMeshFaceNeighbors")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeMeshFaceSetBoundaries")
|
||||
|
|
|
@ -485,7 +485,6 @@ class DATA_PT_customdata(MeshButtonsPanel, Panel):
|
|||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
obj = context.object
|
||||
me = context.mesh
|
||||
col = layout.column()
|
||||
|
||||
|
|
|
@ -62,7 +62,6 @@ class PARTICLE_MT_context_menu(Menu):
|
|||
def draw(self, context):
|
||||
layout = self.layout
|
||||
psys = context.particle_system
|
||||
experimental = context.preferences.experimental
|
||||
|
||||
props = layout.operator(
|
||||
"particle.copy_particle_systems",
|
||||
|
@ -508,7 +507,7 @@ class PARTICLE_PT_hair_dynamics_structure(ParticleButtonsPanel, Panel):
|
|||
sub.prop(psys.settings, "bending_random", text="Random")
|
||||
col.prop(cloth, "bending_damping", text="Damping")
|
||||
# XXX has no noticeable effect with stiff hair structure springs
|
||||
#col.prop(cloth, "spring_damping", text="Damping")
|
||||
# col.prop(cloth, "spring_damping", text="Damping")
|
||||
|
||||
|
||||
class PARTICLE_PT_hair_dynamics_volume(ParticleButtonsPanel, Panel):
|
||||
|
@ -1100,7 +1099,7 @@ class PARTICLE_PT_physics_relations(ParticleButtonsPanel, Panel):
|
|||
if part.physics_type == 'KEYED':
|
||||
col = layout.column()
|
||||
# doesn't work yet
|
||||
#col.alert = key.valid
|
||||
# col.alert = key.valid
|
||||
col.prop(key, "object")
|
||||
col.prop(key, "system", text="System")
|
||||
sub = col.column(align=True)
|
||||
|
@ -1110,7 +1109,7 @@ class PARTICLE_PT_physics_relations(ParticleButtonsPanel, Panel):
|
|||
elif part.physics_type == 'BOIDS':
|
||||
sub = layout.column()
|
||||
# doesn't work yet
|
||||
#sub.alert = key.valid
|
||||
# sub.alert = key.valid
|
||||
sub.prop(key, "object")
|
||||
sub.prop(key, "system", text="System")
|
||||
layout.prop(key, "alliance")
|
||||
|
@ -1157,7 +1156,7 @@ class PARTICLE_PT_physics_fluid_interaction(ParticleButtonsPanel, Panel):
|
|||
if key:
|
||||
sub = layout.column()
|
||||
# doesn't work yet
|
||||
#sub.alert = key.valid
|
||||
# sub.alert = key.valid
|
||||
sub.prop(key, "object")
|
||||
sub.prop(key, "system", text="System")
|
||||
|
||||
|
|
|
@ -641,7 +641,6 @@ class RENDER_PT_eevee_next_film(RenderButtonsPanel, Panel):
|
|||
|
||||
scene = context.scene
|
||||
rd = scene.render
|
||||
props = scene.eevee
|
||||
|
||||
col = layout.column()
|
||||
col.prop(rd, "filter_size")
|
||||
|
|
|
@ -1996,7 +1996,7 @@ class SEQUENCER_PT_adjust_sound(SequencerButtonsPanel, Panel):
|
|||
|
||||
split = col.split(factor=0.4)
|
||||
split.alignment = 'RIGHT'
|
||||
split.label(text="Pan", heading_ctxt=i18n_contexts.id_sound)
|
||||
split.label(text="Pan", text_ctxt=i18n_contexts.id_sound)
|
||||
split.prop(strip, "pan", text="")
|
||||
split.enabled = pan_enabled
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -2329,6 +2329,9 @@ class USERPREF_PT_experimental_new_features(ExperimentalPanel, Panel):
|
|||
({"property": "use_override_templates"},
|
||||
("blender/blender/issues/73318",
|
||||
"Milestone 4")),
|
||||
({"property": "use_new_volume_nodes"},
|
||||
("blender/blender/issues/103248",
|
||||
"#103248")),
|
||||
),
|
||||
)
|
||||
|
||||
|
|
|
@ -2054,6 +2054,7 @@ class VIEW3D_MT_select_edit_curves(Menu):
|
|||
layout.operator("curves.select_all", text="Invert").action = 'INVERT'
|
||||
layout.operator("curves.select_random", text="Random")
|
||||
layout.operator("curves.select_end", text="Endpoints")
|
||||
layout.operator("curves.select_linked", text="Linked")
|
||||
|
||||
|
||||
class VIEW3D_MT_select_sculpt_curves(Menu):
|
||||
|
@ -6708,13 +6709,12 @@ class VIEW3D_PT_overlay_sculpt(Panel):
|
|||
def poll(cls, context):
|
||||
return (
|
||||
context.mode == 'SCULPT' and
|
||||
(context.sculpt_object and context.tool_settings.sculpt)
|
||||
context.sculpt_object
|
||||
)
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
tool_settings = context.tool_settings
|
||||
sculpt = tool_settings.sculpt
|
||||
|
||||
view = context.space_data
|
||||
overlay = view.overlay
|
||||
|
|
|
@ -76,21 +76,11 @@ def node_group_items(context):
|
|||
|
||||
yield NodeItemCustom(draw=lambda self, layout, context: layout.separator())
|
||||
|
||||
def contains_group(nodetree, group):
|
||||
if nodetree == group:
|
||||
return True
|
||||
else:
|
||||
for node in nodetree.nodes:
|
||||
if node.bl_idname in node_tree_group_type.values() and node.node_tree is not None:
|
||||
if contains_group(node.node_tree, group):
|
||||
return True
|
||||
return False
|
||||
|
||||
for group in context.blend_data.node_groups:
|
||||
if group.bl_idname != ntree.bl_idname:
|
||||
continue
|
||||
# filter out recursive groups
|
||||
if contains_group(group, ntree):
|
||||
if group.contains_tree(ntree):
|
||||
continue
|
||||
# filter out hidden nodetrees
|
||||
if group.name.startswith('.'):
|
||||
|
|
|
@ -25,7 +25,7 @@ extern "C" {
|
|||
|
||||
/* Blender file format version. */
|
||||
#define BLENDER_FILE_VERSION BLENDER_VERSION
|
||||
#define BLENDER_FILE_SUBVERSION 8
|
||||
#define BLENDER_FILE_SUBVERSION 9
|
||||
|
||||
/* 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
|
||||
|
|
|
@ -63,7 +63,7 @@ typedef struct FModifierTypeInfo {
|
|||
/** #eFMI_Action_Types. */
|
||||
short acttype;
|
||||
/** #eFMI_Requirement_Flags. */
|
||||
short requires;
|
||||
short requires_flag;
|
||||
/** name of modifier in interface. */
|
||||
char name[64];
|
||||
/** name of struct for SDNA. */
|
||||
|
|
|
@ -229,11 +229,6 @@ void BKE_mesh_material_remap(struct Mesh *me, const unsigned int *remap, unsigne
|
|||
void BKE_mesh_smooth_flag_set(struct Mesh *me, bool use_smooth);
|
||||
void BKE_mesh_auto_smooth_flag_set(struct Mesh *me, bool use_auto_smooth, float auto_smooth_angle);
|
||||
|
||||
/**
|
||||
* Needed after converting a mesh with subsurf optimal display to mesh.
|
||||
*/
|
||||
void BKE_mesh_edges_set_draw_render(struct Mesh *me);
|
||||
|
||||
/**
|
||||
* Used for unit testing; compares two meshes, checking only
|
||||
* differences we care about. should be usable with leaf's
|
||||
|
|
|
@ -145,10 +145,7 @@ void BKE_mesh_convert_mfaces_to_mpolys(struct Mesh *mesh);
|
|||
*/
|
||||
void BKE_mesh_do_versions_convert_mfaces_to_mpolys(struct Mesh *mesh);
|
||||
|
||||
/**
|
||||
* Convert legacy #MFace.edcode to edge #ME_EDGEDRAW.
|
||||
*/
|
||||
void BKE_mesh_calc_edges_legacy(struct Mesh *me, bool use_old);
|
||||
void BKE_mesh_calc_edges_legacy(struct Mesh *me);
|
||||
|
||||
void BKE_mesh_do_versions_cd_flag_init(struct Mesh *mesh);
|
||||
|
||||
|
|
|
@ -170,7 +170,6 @@ void BKE_mesh_vert_edge_vert_map_create(
|
|||
*/
|
||||
void BKE_mesh_edge_loop_map_create(MeshElemMap **r_map,
|
||||
int **r_mem,
|
||||
const struct MEdge *medge,
|
||||
int totedge,
|
||||
const struct MPoly *mpoly,
|
||||
int totpoly,
|
||||
|
@ -183,7 +182,6 @@ void BKE_mesh_edge_loop_map_create(MeshElemMap **r_map,
|
|||
*/
|
||||
void BKE_mesh_edge_poly_map_create(MeshElemMap **r_map,
|
||||
int **r_mem,
|
||||
const struct MEdge *medge,
|
||||
int totedge,
|
||||
const struct MPoly *mpoly,
|
||||
int totpoly,
|
||||
|
@ -317,8 +315,7 @@ bool BKE_mesh_calc_islands_loop_poly_uvmap(float (*vert_positions)[3],
|
|||
* starting at 1 (0 being used as 'invalid' flag).
|
||||
* Note it's callers's responsibility to MEM_freeN returned array.
|
||||
*/
|
||||
int *BKE_mesh_calc_smoothgroups(const struct MEdge *medge,
|
||||
int totedge,
|
||||
int *BKE_mesh_calc_smoothgroups(int totedge,
|
||||
const struct MPoly *mpoly,
|
||||
int totpoly,
|
||||
const struct MLoop *mloop,
|
||||
|
@ -353,6 +350,7 @@ Array<Vector<int>> build_vert_to_edge_map(Span<MEdge> edges, int verts_num);
|
|||
Array<Vector<int>> build_vert_to_poly_map(Span<MPoly> polys, Span<MLoop> loops, int verts_num);
|
||||
Array<Vector<int>> build_vert_to_loop_map(Span<MLoop> loops, int verts_num);
|
||||
Array<Vector<int>> build_edge_to_loop_map(Span<MLoop> loops, int edges_num);
|
||||
Array<Vector<int, 2>> build_edge_to_poly_map(Span<MPoly> polys, Span<MLoop> loops, int edges_num);
|
||||
Vector<Vector<int>> build_edge_to_loop_map_resizable(Span<MLoop> loops, int edges_num);
|
||||
|
||||
inline int poly_loop_prev(const MPoly &poly, int loop_i)
|
||||
|
|
|
@ -174,6 +174,13 @@ struct MeshRuntime {
|
|||
*/
|
||||
BitVector<> subsurf_face_dot_tags;
|
||||
|
||||
/**
|
||||
* A bit vector the size of the number of edges, set to true for edges that should be drawn in
|
||||
* the viewport. Created by the "Optimal Display" feature of the subdivision surface modifier.
|
||||
* Otherwise it will be empty.
|
||||
*/
|
||||
BitVector<> subsurf_optimal_display_edges;
|
||||
|
||||
MeshRuntime() = default;
|
||||
~MeshRuntime();
|
||||
|
||||
|
|
|
@ -504,7 +504,13 @@ struct bNodeTree *ntreeFromID(struct ID *id);
|
|||
void ntreeFreeLocalNode(struct bNodeTree *ntree, struct bNode *node);
|
||||
void ntreeFreeLocalTree(struct bNodeTree *ntree);
|
||||
struct bNode *ntreeFindType(struct bNodeTree *ntree, int type);
|
||||
bool ntreeHasTree(const struct bNodeTree *ntree, const struct bNodeTree *lookup);
|
||||
|
||||
/**
|
||||
* Check recursively if a node tree contains another.
|
||||
*/
|
||||
bool ntreeContainsTree(const struct bNodeTree *tree_to_search_in,
|
||||
const struct bNodeTree *tree_to_search_for);
|
||||
|
||||
void ntreeUpdateAllNew(struct Main *main);
|
||||
void ntreeUpdateAllUsers(struct Main *main, struct ID *id);
|
||||
|
||||
|
@ -1534,6 +1540,7 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, i
|
|||
#define GEO_NODE_BLUR_ATTRIBUTE 1190
|
||||
#define GEO_NODE_IMAGE 1191
|
||||
#define GEO_NODE_INTERPOLATE_CURVES 1192
|
||||
#define GEO_NODE_EDGES_TO_FACE_GROUPS 1193
|
||||
|
||||
/** \} */
|
||||
|
||||
|
|
|
@ -62,7 +62,6 @@ static void fill_mesh_topology(const int vert_offset,
|
|||
MEdge &edge = edges[profile_edge_offset + i_ring];
|
||||
edge.v1 = ring_vert_offset + i_profile;
|
||||
edge.v2 = next_ring_vert_offset + i_profile;
|
||||
edge.flag = ME_EDGEDRAW;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -78,7 +77,6 @@ static void fill_mesh_topology(const int vert_offset,
|
|||
MEdge &edge = edges[ring_edge_offset + i_profile];
|
||||
edge.v1 = ring_vert_offset + i_profile;
|
||||
edge.v2 = ring_vert_offset + i_next_profile;
|
||||
edge.flag = ME_EDGEDRAW;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2289,26 +2289,12 @@ bool CustomData_merge(const CustomData *source,
|
|||
return changed;
|
||||
}
|
||||
|
||||
static bool attribute_stored_in_bmesh_flag(const StringRef name)
|
||||
{
|
||||
return ELEM(name,
|
||||
"position",
|
||||
".hide_vert",
|
||||
".hide_edge",
|
||||
".hide_poly",
|
||||
".select_vert",
|
||||
".select_edge",
|
||||
".select_poly",
|
||||
"material_index",
|
||||
"sharp_edge");
|
||||
}
|
||||
|
||||
CustomData CustomData_shallow_copy_remove_non_bmesh_attributes(const CustomData *src,
|
||||
const eCustomDataMask mask)
|
||||
{
|
||||
Vector<CustomDataLayer> dst_layers;
|
||||
for (const CustomDataLayer &layer : Span<CustomDataLayer>{src->layers, src->totlayer}) {
|
||||
if (attribute_stored_in_bmesh_flag(layer.name)) {
|
||||
if (BM_attribute_stored_in_bmesh_builtin(layer.name)) {
|
||||
continue;
|
||||
}
|
||||
if (!(mask & CD_TYPE_AS_MASK(layer.type))) {
|
||||
|
|
|
@ -772,7 +772,7 @@ bool get_effector_data(EffectorCache *eff,
|
|||
if (eff->pd->forcefield == PFIELD_VORTEX || eff->pd->shape == PFIELD_SHAPE_LINE) {
|
||||
add_v3_v3v3(efd->loc, ob->object_to_world[3], translate);
|
||||
}
|
||||
else { /* normally efd->loc is closest point on effector xy-plane */
|
||||
else { /* Normally `efd->loc` is closest point on effector XY-plane. */
|
||||
sub_v3_v3v3(efd->loc, point->loc, translate);
|
||||
}
|
||||
}
|
||||
|
@ -1125,31 +1125,31 @@ void BKE_effectors_apply(ListBase *effectors,
|
|||
/* WARNING(@ideasman42): historic comment?
|
||||
* Many of these parameters don't exist!
|
||||
*
|
||||
* scene = scene where it runs in, for time and stuff.
|
||||
* lb = listbase with objects that take part in effecting.
|
||||
* opco = global coord, as input.
|
||||
* force = accumulator for force.
|
||||
* wind_force = accumulator for force only acting perpendicular to a surface.
|
||||
* speed = actual current speed which can be altered.
|
||||
* cur_time = "external" time in frames, is constant for static particles.
|
||||
* loc_time = "local" time in frames, range <0-1> for the lifetime of particle.
|
||||
* par_layer = layer the caller is in.
|
||||
* flags = only used for soft-body wind now.
|
||||
* guide = old speed of particle.
|
||||
* `scene` = scene where it runs in, for time and stuff.
|
||||
* `lb` = listbase with objects that take part in effecting.
|
||||
* `opco` = global coord, as input.
|
||||
* `force` = accumulator for force.
|
||||
* `wind_force` = accumulator for force only acting perpendicular to a surface.
|
||||
* `speed` = actual current speed which can be altered.
|
||||
* `cur_time` = "external" time in frames, is constant for static particles.
|
||||
* `loc_time` = "local" time in frames, range <0-1> for the lifetime of particle.
|
||||
* `par_layer` = layer the caller is in.
|
||||
* `flags` = only used for soft-body wind now.
|
||||
* `guide` = old speed of particle.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modifies the force on a particle according to its
|
||||
* relation with the effector object
|
||||
* Different kind of effectors include:
|
||||
* Force-fields: Gravity-like attractor
|
||||
* (force power is related to the inverse of distance to the power of a falloff value)
|
||||
* Vortex fields: swirling effectors
|
||||
* (particles rotate around Z-axis of the object. otherwise, same relation as)
|
||||
* (Force-fields, but this is not done through a force/acceleration)
|
||||
* Guide: particles on a path
|
||||
* (particles are guided along a curve bezier or old nurbs)
|
||||
* (is independent of other effectors)
|
||||
* - Force-fields: Gravity-like attractor
|
||||
* (force power is related to the inverse of distance to the power of a falloff value)
|
||||
* - Vortex fields: swirling effectors
|
||||
* (particles rotate around Z-axis of the object. otherwise, same relation as)
|
||||
* (Force-fields, but this is not done through a force/acceleration)
|
||||
* - Guide: particles on a path
|
||||
* (particles are guided along a curve bezier or old nurbs)
|
||||
* (is independent of other effectors)
|
||||
*/
|
||||
EffectorCache *eff;
|
||||
EffectorData efd;
|
||||
|
|
|
@ -64,7 +64,7 @@ static FModifierTypeInfo FMI_MODNAME = {
|
|||
/*type*/ FMODIFIER_TYPE_MODNAME,
|
||||
/*size*/ sizeof(FMod_ModName),
|
||||
/*acttype*/ FMI_TYPE_SOME_ACTION,
|
||||
/*requires*/ FMI_REQUIRES_SOME_REQUIREMENT,
|
||||
/*requires_flag*/ FMI_REQUIRES_SOME_REQUIREMENT,
|
||||
/*name*/ "Modifier Name",
|
||||
/*structName*/ "FMod_ModName",
|
||||
/*storage_size*/ 0,
|
||||
|
@ -228,7 +228,7 @@ static FModifierTypeInfo FMI_GENERATOR = {
|
|||
/*type*/ FMODIFIER_TYPE_GENERATOR,
|
||||
/*size*/ sizeof(FMod_Generator),
|
||||
/*acttype*/ FMI_TYPE_GENERATE_CURVE,
|
||||
/*requires*/ FMI_REQUIRES_NOTHING,
|
||||
/*requires_flag*/ FMI_REQUIRES_NOTHING,
|
||||
/*name*/ N_("Generator"),
|
||||
/*structName*/ "FMod_Generator",
|
||||
/*storage_size*/ 0,
|
||||
|
@ -358,7 +358,7 @@ static FModifierTypeInfo FMI_FN_GENERATOR = {
|
|||
/*type*/ FMODIFIER_TYPE_FN_GENERATOR,
|
||||
/*size*/ sizeof(FMod_FunctionGenerator),
|
||||
/*acttype*/ FMI_TYPE_GENERATE_CURVE,
|
||||
/*requires*/ FMI_REQUIRES_NOTHING,
|
||||
/*requires_flag*/ FMI_REQUIRES_NOTHING,
|
||||
/*name*/ N_("Built-In Function"),
|
||||
/*structName*/ "FMod_FunctionGenerator",
|
||||
/*storage_size*/ 0,
|
||||
|
@ -471,7 +471,7 @@ static FModifierTypeInfo FMI_ENVELOPE = {
|
|||
/*type*/ FMODIFIER_TYPE_ENVELOPE,
|
||||
/*size*/ sizeof(FMod_Envelope),
|
||||
/*acttype*/ FMI_TYPE_REPLACE_VALUES,
|
||||
/*requires*/ 0,
|
||||
/*requires_flag*/ 0,
|
||||
/*name*/ N_("Envelope"),
|
||||
/*structName*/ "FMod_Envelope",
|
||||
/*storage_size*/ 0,
|
||||
|
@ -770,7 +770,7 @@ static FModifierTypeInfo FMI_CYCLES = {
|
|||
/*type*/ FMODIFIER_TYPE_CYCLES,
|
||||
/*size*/ sizeof(FMod_Cycles),
|
||||
/*acttype*/ FMI_TYPE_EXTRAPOLATION,
|
||||
/*requires*/ FMI_REQUIRES_ORIGINAL_DATA,
|
||||
/*requires_flag*/ FMI_REQUIRES_ORIGINAL_DATA,
|
||||
/*name*/ CTX_N_(BLT_I18NCONTEXT_ID_ACTION, "Cycles"),
|
||||
/*structName*/ "FMod_Cycles",
|
||||
/*storage_size*/ sizeof(tFCMED_Cycles),
|
||||
|
@ -832,7 +832,7 @@ static FModifierTypeInfo FMI_NOISE = {
|
|||
/*type*/ FMODIFIER_TYPE_NOISE,
|
||||
/*size*/ sizeof(FMod_Noise),
|
||||
/*acttype*/ FMI_TYPE_REPLACE_VALUES,
|
||||
/*requires*/ 0,
|
||||
/*requires_flag*/ 0,
|
||||
/*name*/ N_("Noise"),
|
||||
/*structName*/ "FMod_Noise",
|
||||
/*storage_size*/ 0,
|
||||
|
@ -890,7 +890,7 @@ static FModifierTypeInfo FMI_PYTHON = {
|
|||
/*type*/ FMODIFIER_TYPE_PYTHON,
|
||||
/*size*/ sizeof(FMod_Python),
|
||||
/*acttype*/ FMI_TYPE_GENERATE_CURVE,
|
||||
/*requires*/ FMI_REQUIRES_RUNTIME_CHECK,
|
||||
/*requires_flag*/ FMI_REQUIRES_RUNTIME_CHECK,
|
||||
/*name*/ N_("Python"),
|
||||
/*structName*/ "FMod_Python",
|
||||
/*storage_size*/ 0,
|
||||
|
@ -945,7 +945,7 @@ static FModifierTypeInfo FMI_LIMITS = {
|
|||
/*type*/ FMODIFIER_TYPE_LIMITS,
|
||||
/*size*/ sizeof(FMod_Limits),
|
||||
/*acttype*/ FMI_TYPE_GENERATE_CURVE,
|
||||
/*requires*/ FMI_REQUIRES_RUNTIME_CHECK, /* XXX... err... */
|
||||
/*requires_flag*/ FMI_REQUIRES_RUNTIME_CHECK, /* XXX... err... */
|
||||
/*name*/ N_("Limits"),
|
||||
/*structName*/ "FMod_Limits",
|
||||
/*storage_size*/ 0,
|
||||
|
@ -1005,7 +1005,7 @@ static FModifierTypeInfo FMI_STEPPED = {
|
|||
/*type*/ FMODIFIER_TYPE_STEPPED,
|
||||
/*size*/ sizeof(FMod_Limits),
|
||||
/*acttype*/ FMI_TYPE_GENERATE_CURVE,
|
||||
/*requires*/ FMI_REQUIRES_RUNTIME_CHECK, /* XXX... err... */
|
||||
/*requires_flag*/ FMI_REQUIRES_RUNTIME_CHECK, /* XXX... err... */
|
||||
/*name*/ N_("Stepped"),
|
||||
/*structName*/ "FMod_Stepped",
|
||||
/*storage_size*/ 0,
|
||||
|
|
|
@ -1261,7 +1261,9 @@ bGPDframe *BKE_gpencil_layer_frame_get(bGPDlayer *gpl, int cframe, eGP_GetFrame_
|
|||
found = true;
|
||||
break;
|
||||
}
|
||||
if ((gpf->next) && (gpf->next->framenum > cframe)) {
|
||||
/* If this is the last frame or the next frame is at a later time, we found the right
|
||||
* frame. */
|
||||
if (!(gpf->next) || (gpf->next->framenum > cframe)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -107,10 +107,12 @@ static void mesh_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int
|
|||
mesh_dst->runtime->wrapper_type_finalize = mesh_src->runtime->wrapper_type_finalize;
|
||||
mesh_dst->runtime->subsurf_runtime_data = mesh_src->runtime->subsurf_runtime_data;
|
||||
mesh_dst->runtime->cd_mask_extra = mesh_src->runtime->cd_mask_extra;
|
||||
/* Copy face dot tags, since meshes may be duplicated after a subsurf modifier or node, but we
|
||||
* still need to be able to draw face center vertices. The tags may be cleared explicitly when
|
||||
* the topology is changed. */
|
||||
/* Copy face dot tags and edge tags, since meshes may be duplicated after a subsurf modifier or
|
||||
* node, but we still need to be able to draw face center vertices and "optimal edges"
|
||||
* differently. The tags may be cleared explicitly when the topology is changed. */
|
||||
mesh_dst->runtime->subsurf_face_dot_tags = mesh_src->runtime->subsurf_face_dot_tags;
|
||||
mesh_dst->runtime->subsurf_optimal_display_edges =
|
||||
mesh_src->runtime->subsurf_optimal_display_edges;
|
||||
if ((mesh_src->id.tag & LIB_TAG_NO_MAIN) == 0) {
|
||||
/* This is a direct copy of a main mesh, so for now it has the same topology. */
|
||||
mesh_dst->runtime->deformed_only = true;
|
||||
|
|
|
@ -146,7 +146,6 @@ static void serialize_and_initialize_deduplicated_edges(MutableSpan<EdgeMap> edg
|
|||
/* Initialize new edge. */
|
||||
new_edge.v1 = item.key.v_low;
|
||||
new_edge.v2 = item.key.v_high;
|
||||
new_edge.flag = ME_EDGEDRAW;
|
||||
}
|
||||
item.value.index = new_edge_index;
|
||||
new_edge_index++;
|
||||
|
|
|
@ -121,7 +121,7 @@ static void make_edges_mdata_extend(Mesh &mesh)
|
|||
BLI_edgehashIterator_getKey(ehi, &medge->v1, &medge->v2);
|
||||
BLI_edgehashIterator_setValue(ehi, POINTER_FROM_UINT(e_index));
|
||||
|
||||
medge->flag = ME_EDGEDRAW;
|
||||
medge->flag = 0;
|
||||
}
|
||||
BLI_edgehashIterator_free(ehi);
|
||||
|
||||
|
@ -223,7 +223,6 @@ static Mesh *mesh_nurbs_displist_to_mesh(const Curve *cu, const ListBase *dispba
|
|||
for (b = 1; b < dl->nr; b++) {
|
||||
edges[dst_edge].v1 = startvert + ofs + b - 1;
|
||||
edges[dst_edge].v2 = startvert + ofs + b;
|
||||
edges[dst_edge].flag = ME_EDGEDRAW;
|
||||
|
||||
dst_edge++;
|
||||
}
|
||||
|
@ -250,7 +249,6 @@ static Mesh *mesh_nurbs_displist_to_mesh(const Curve *cu, const ListBase *dispba
|
|||
else {
|
||||
edges[dst_edge].v2 = startvert + ofs + b + 1;
|
||||
}
|
||||
edges[dst_edge].flag = ME_EDGEDRAW;
|
||||
dst_edge++;
|
||||
}
|
||||
}
|
||||
|
@ -662,14 +660,6 @@ void BKE_mesh_from_pointcloud(const PointCloud *pointcloud, Mesh *me)
|
|||
&pointcloud->pdata, &me->vdata, CD_MASK_PROP_ALL, CD_DUPLICATE, pointcloud->totpoint);
|
||||
}
|
||||
|
||||
void BKE_mesh_edges_set_draw_render(Mesh *mesh)
|
||||
{
|
||||
MutableSpan<MEdge> edges = mesh->edges_for_write();
|
||||
for (int i = 0; i < mesh->totedge; i++) {
|
||||
edges[i].flag |= ME_EDGEDRAW;
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_pointcloud_to_mesh(Main *bmain, Depsgraph *depsgraph, Scene * /*scene*/, Object *ob)
|
||||
{
|
||||
BLI_assert(ob->type == OB_POINTCLOUD);
|
||||
|
|
|
@ -89,7 +89,6 @@ static void mesh_calc_edges_mdata(const MVert * /*allvert*/,
|
|||
int totface,
|
||||
int /*totloop*/,
|
||||
int totpoly,
|
||||
const bool use_old,
|
||||
MEdge **r_medge,
|
||||
int *r_totedge)
|
||||
{
|
||||
|
@ -156,9 +155,6 @@ static void mesh_calc_edges_mdata(const MVert * /*allvert*/,
|
|||
if (ed->v1 != (ed + 1)->v1 || ed->v2 != (ed + 1)->v2) {
|
||||
med->v1 = ed->v1;
|
||||
med->v2 = ed->v2;
|
||||
if (use_old == false || ed->is_draw) {
|
||||
med->flag = ME_EDGEDRAW;
|
||||
}
|
||||
|
||||
/* order is swapped so extruding this edge as a surface won't flip face normals
|
||||
* with cyclic curves */
|
||||
|
@ -175,7 +171,6 @@ static void mesh_calc_edges_mdata(const MVert * /*allvert*/,
|
|||
/* last edge */
|
||||
med->v1 = ed->v1;
|
||||
med->v2 = ed->v2;
|
||||
med->flag = ME_EDGEDRAW;
|
||||
|
||||
MEM_freeN(edsort);
|
||||
|
||||
|
@ -206,7 +201,7 @@ static void mesh_calc_edges_mdata(const MVert * /*allvert*/,
|
|||
*r_totedge = totedge_final;
|
||||
}
|
||||
|
||||
void BKE_mesh_calc_edges_legacy(Mesh *me, const bool use_old)
|
||||
void BKE_mesh_calc_edges_legacy(Mesh *me)
|
||||
{
|
||||
using namespace blender;
|
||||
MEdge *medge;
|
||||
|
@ -224,7 +219,6 @@ void BKE_mesh_calc_edges_legacy(Mesh *me, const bool use_old)
|
|||
me->totface,
|
||||
loops.size(),
|
||||
polys.size(),
|
||||
use_old,
|
||||
&medge,
|
||||
&totedge);
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "BLI_array.hh"
|
||||
#include "BLI_bitmap.h"
|
||||
#include "BLI_buffer.h"
|
||||
#include "BLI_function_ref.hh"
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_task.hh"
|
||||
#include "BLI_utildefines.h"
|
||||
|
@ -385,7 +386,6 @@ void BKE_mesh_vert_edge_vert_map_create(
|
|||
|
||||
void BKE_mesh_edge_loop_map_create(MeshElemMap **r_map,
|
||||
int **r_mem,
|
||||
const MEdge * /*medge*/,
|
||||
const int totedge,
|
||||
const MPoly *mpoly,
|
||||
const int totpoly,
|
||||
|
@ -438,7 +438,6 @@ void BKE_mesh_edge_loop_map_create(MeshElemMap **r_map,
|
|||
|
||||
void BKE_mesh_edge_poly_map_create(MeshElemMap **r_map,
|
||||
int **r_mem,
|
||||
const MEdge * /*medge*/,
|
||||
const int totedge,
|
||||
const MPoly *mpoly,
|
||||
const int totpoly,
|
||||
|
@ -610,6 +609,20 @@ Array<Vector<int>> build_edge_to_loop_map(const Span<MLoop> loops, const int edg
|
|||
return map;
|
||||
}
|
||||
|
||||
Array<Vector<int, 2>> build_edge_to_poly_map(const Span<MPoly> polys,
|
||||
const Span<MLoop> loops,
|
||||
const int edges_num)
|
||||
{
|
||||
Array<Vector<int, 2>> map(edges_num);
|
||||
for (const int64_t i : polys.index_range()) {
|
||||
const MPoly &poly = polys[i];
|
||||
for (const MLoop &loop : loops.slice(poly.loopstart, poly.totloop)) {
|
||||
map[loop.e].append(int(i));
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
Vector<Vector<int>> build_edge_to_loop_map_resizable(const Span<MLoop> loops, const int edges_num)
|
||||
{
|
||||
Vector<Vector<int>> map(edges_num);
|
||||
|
@ -631,27 +644,19 @@ Vector<Vector<int>> build_edge_to_loop_map_resizable(const Span<MLoop> loops, co
|
|||
/**
|
||||
* Callback deciding whether the given poly/loop/edge define an island boundary or not.
|
||||
*/
|
||||
using MeshRemap_CheckIslandBoundary = bool (*)(const MPoly *mpoly,
|
||||
const MLoop *mloop,
|
||||
const MEdge *medge,
|
||||
const int edge_index,
|
||||
const bool *sharp_edges,
|
||||
const int edge_user_count,
|
||||
const MPoly *mpoly_array,
|
||||
const MeshElemMap *edge_poly_map,
|
||||
void *user_data);
|
||||
using MeshRemap_CheckIslandBoundary =
|
||||
blender::FunctionRef<bool(int poly_index,
|
||||
int loop_index,
|
||||
int edge_index,
|
||||
int edge_user_count,
|
||||
const MeshElemMap &edge_poly_map_elem)>;
|
||||
|
||||
static void poly_edge_loop_islands_calc(const MEdge *medge,
|
||||
const int totedge,
|
||||
const MPoly *mpoly,
|
||||
const int totpoly,
|
||||
const MLoop *mloop,
|
||||
const int totloop,
|
||||
const bool *sharp_edges,
|
||||
static void poly_edge_loop_islands_calc(const int totedge,
|
||||
const blender::Span<MPoly> polys,
|
||||
const blender::Span<MLoop> loops,
|
||||
MeshElemMap *edge_poly_map,
|
||||
const bool use_bitflags,
|
||||
MeshRemap_CheckIslandBoundary edge_boundary_check,
|
||||
void *edge_boundary_check_data,
|
||||
int **r_poly_groups,
|
||||
int *r_totgroup,
|
||||
BLI_bitmap **r_edge_borders,
|
||||
|
@ -675,7 +680,7 @@ static void poly_edge_loop_islands_calc(const MEdge *medge,
|
|||
/* map vars */
|
||||
int *edge_poly_mem = nullptr;
|
||||
|
||||
if (totpoly == 0) {
|
||||
if (polys.size() == 0) {
|
||||
*r_totgroup = 0;
|
||||
*r_poly_groups = nullptr;
|
||||
if (r_edge_borders) {
|
||||
|
@ -691,12 +696,17 @@ static void poly_edge_loop_islands_calc(const MEdge *medge,
|
|||
}
|
||||
|
||||
if (!edge_poly_map) {
|
||||
BKE_mesh_edge_poly_map_create(
|
||||
&edge_poly_map, &edge_poly_mem, medge, totedge, mpoly, totpoly, mloop, totloop);
|
||||
BKE_mesh_edge_poly_map_create(&edge_poly_map,
|
||||
&edge_poly_mem,
|
||||
totedge,
|
||||
polys.data(),
|
||||
int(polys.size()),
|
||||
loops.data(),
|
||||
int(loops.size()));
|
||||
}
|
||||
|
||||
poly_groups = static_cast<int *>(MEM_callocN(sizeof(int) * size_t(totpoly), __func__));
|
||||
poly_stack = static_cast<int *>(MEM_mallocN(sizeof(int) * size_t(totpoly), __func__));
|
||||
poly_groups = static_cast<int *>(MEM_callocN(sizeof(int) * size_t(polys.size()), __func__));
|
||||
poly_stack = static_cast<int *>(MEM_mallocN(sizeof(int) * size_t(polys.size()), __func__));
|
||||
|
||||
while (true) {
|
||||
int poly;
|
||||
|
@ -704,13 +714,13 @@ static void poly_edge_loop_islands_calc(const MEdge *medge,
|
|||
int poly_group_id;
|
||||
int ps_curr_idx = 0, ps_end_idx = 0; /* stack indices */
|
||||
|
||||
for (poly = poly_prev; poly < totpoly; poly++) {
|
||||
for (poly = poly_prev; poly < int(polys.size()); poly++) {
|
||||
if (poly_groups[poly] == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (poly == totpoly) {
|
||||
if (poly == int(polys.size())) {
|
||||
/* all done */
|
||||
break;
|
||||
}
|
||||
|
@ -724,23 +734,16 @@ static void poly_edge_loop_islands_calc(const MEdge *medge,
|
|||
poly_stack[ps_end_idx++] = poly;
|
||||
|
||||
while (ps_curr_idx != ps_end_idx) {
|
||||
const MPoly *mp;
|
||||
const MLoop *ml;
|
||||
int j;
|
||||
|
||||
poly = poly_stack[ps_curr_idx++];
|
||||
BLI_assert(poly_groups[poly] == poly_group_id);
|
||||
|
||||
mp = &mpoly[poly];
|
||||
for (ml = &mloop[mp->loopstart], j = mp->totloop; j--; ml++) {
|
||||
for (const int64_t loop : blender::IndexRange(polys[poly].loopstart, polys[poly].totloop)) {
|
||||
const int edge = int(loops[loop].e);
|
||||
/* loop over poly users */
|
||||
const int me_idx = int(ml->e);
|
||||
const MEdge *me = &medge[me_idx];
|
||||
const MeshElemMap *map_ele = &edge_poly_map[me_idx];
|
||||
const int *p = map_ele->indices;
|
||||
int i = map_ele->count;
|
||||
if (!edge_boundary_check(
|
||||
mp, ml, me, me_idx, sharp_edges, i, mpoly, map_ele, edge_boundary_check_data)) {
|
||||
const MeshElemMap &map_ele = edge_poly_map[edge];
|
||||
const int *p = map_ele.indices;
|
||||
int i = map_ele.count;
|
||||
if (!edge_boundary_check(poly, int(loop), edge, i, map_ele)) {
|
||||
for (; i--; p++) {
|
||||
/* if we meet other non initialized its a bug */
|
||||
BLI_assert(ELEM(poly_groups[*p], 0, poly_group_id));
|
||||
|
@ -752,8 +755,8 @@ static void poly_edge_loop_islands_calc(const MEdge *medge,
|
|||
}
|
||||
}
|
||||
else {
|
||||
if (edge_borders && !BLI_BITMAP_TEST(edge_borders, me_idx)) {
|
||||
BLI_BITMAP_ENABLE(edge_borders, me_idx);
|
||||
if (edge_borders && !BLI_BITMAP_TEST(edge_borders, edge)) {
|
||||
BLI_BITMAP_ENABLE(edge_borders, edge);
|
||||
num_edgeborders++;
|
||||
}
|
||||
if (use_bitflags) {
|
||||
|
@ -814,7 +817,7 @@ static void poly_edge_loop_islands_calc(const MEdge *medge,
|
|||
}
|
||||
|
||||
if (UNLIKELY(group_id_overflow)) {
|
||||
int i = totpoly, *gid = poly_groups;
|
||||
int i = int(polys.size()), *gid = poly_groups;
|
||||
for (; i--; gid++) {
|
||||
if (*gid == poly_group_id_overflowed) {
|
||||
*gid = 0;
|
||||
|
@ -838,31 +841,7 @@ static void poly_edge_loop_islands_calc(const MEdge *medge,
|
|||
}
|
||||
}
|
||||
|
||||
static bool poly_is_island_boundary_smooth_cb(const MPoly *mp,
|
||||
const MLoop * /*ml*/,
|
||||
const MEdge * /*me*/,
|
||||
const int edge_index,
|
||||
const bool *sharp_edges,
|
||||
const int edge_user_count,
|
||||
const MPoly *mpoly_array,
|
||||
const MeshElemMap *edge_poly_map,
|
||||
void * /*user_data*/)
|
||||
{
|
||||
/* Edge is sharp if one of its polys is flat, or edge itself is sharp,
|
||||
* or edge is not used by exactly two polygons. */
|
||||
if ((mp->flag & ME_SMOOTH) && !(sharp_edges && sharp_edges[edge_index]) &&
|
||||
(edge_user_count == 2)) {
|
||||
/* In that case, edge appears to be smooth, but we need to check its other poly too. */
|
||||
const MPoly *mp_other = (mp == &mpoly_array[edge_poly_map->indices[0]]) ?
|
||||
&mpoly_array[edge_poly_map->indices[1]] :
|
||||
&mpoly_array[edge_poly_map->indices[0]];
|
||||
return (mp_other->flag & ME_SMOOTH) == 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int *BKE_mesh_calc_smoothgroups(const MEdge *medge,
|
||||
const int totedge,
|
||||
int *BKE_mesh_calc_smoothgroups(const int totedge,
|
||||
const MPoly *mpoly,
|
||||
const int totpoly,
|
||||
const MLoop *mloop,
|
||||
|
@ -873,17 +852,30 @@ int *BKE_mesh_calc_smoothgroups(const MEdge *medge,
|
|||
{
|
||||
int *poly_groups = nullptr;
|
||||
|
||||
poly_edge_loop_islands_calc(medge,
|
||||
totedge,
|
||||
mpoly,
|
||||
totpoly,
|
||||
mloop,
|
||||
totloop,
|
||||
sharp_edges,
|
||||
auto poly_is_island_boundary_smooth = [&](const int poly_index,
|
||||
const int /*loop_index*/,
|
||||
const int edge_index,
|
||||
const int edge_user_count,
|
||||
const MeshElemMap &edge_poly_map_elem) {
|
||||
/* Edge is sharp if one of its polys is flat, or edge itself is sharp,
|
||||
* or edge is not used by exactly two polygons. */
|
||||
if ((mpoly[poly_index].flag & ME_SMOOTH) && !(sharp_edges && sharp_edges[edge_index]) &&
|
||||
(edge_user_count == 2)) {
|
||||
/* In that case, edge appears to be smooth, but we need to check its other poly too. */
|
||||
const int other_poly_index = (poly_index == edge_poly_map_elem.indices[0]) ?
|
||||
edge_poly_map_elem.indices[1] :
|
||||
edge_poly_map_elem.indices[0];
|
||||
return (mpoly[other_poly_index].flag & ME_SMOOTH) == 0;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
poly_edge_loop_islands_calc(totedge,
|
||||
{mpoly, totpoly},
|
||||
{mloop, totloop},
|
||||
nullptr,
|
||||
use_bitflags,
|
||||
poly_is_island_boundary_smooth_cb,
|
||||
nullptr,
|
||||
poly_is_island_boundary_smooth,
|
||||
&poly_groups,
|
||||
r_totgroup,
|
||||
nullptr,
|
||||
|
@ -1007,64 +999,6 @@ void BKE_mesh_loop_islands_add(MeshIslandStore *island_store,
|
|||
sizeof(*innrcut->indices) * size_t(num_innercut_items));
|
||||
}
|
||||
|
||||
/* TODO: I'm not sure edge seam flag is enough to define UV islands?
|
||||
* Maybe we should also consider UV-maps values
|
||||
* themselves (i.e. different UV-edges for a same mesh-edge => boundary edge too?).
|
||||
* Would make things much more complex though,
|
||||
* and each UVMap would then need its own mesh mapping, not sure we want that at all!
|
||||
*/
|
||||
struct MeshCheckIslandBoundaryUv {
|
||||
const MLoop *loops;
|
||||
const float (*luvs)[2];
|
||||
const MeshElemMap *edge_loop_map;
|
||||
};
|
||||
|
||||
static bool mesh_check_island_boundary_uv(const MPoly * /*mp*/,
|
||||
const MLoop *ml,
|
||||
const MEdge *me,
|
||||
const int /*edge_index*/,
|
||||
const bool * /*sharp_edges*/,
|
||||
const int /*edge_user_count*/,
|
||||
const MPoly * /*mpoly_array*/,
|
||||
const MeshElemMap * /*edge_poly_map*/,
|
||||
void *user_data)
|
||||
{
|
||||
if (user_data) {
|
||||
const MeshCheckIslandBoundaryUv *data = static_cast<const MeshCheckIslandBoundaryUv *>(
|
||||
user_data);
|
||||
const MLoop *loops = data->loops;
|
||||
const float(*luvs)[2] = data->luvs;
|
||||
const MeshElemMap *edge_to_loops = &data->edge_loop_map[ml->e];
|
||||
|
||||
BLI_assert(edge_to_loops->count >= 2 && (edge_to_loops->count % 2) == 0);
|
||||
|
||||
const uint v1 = loops[edge_to_loops->indices[0]].v;
|
||||
const uint v2 = loops[edge_to_loops->indices[1]].v;
|
||||
const float *uvco_v1 = luvs[edge_to_loops->indices[0]];
|
||||
const float *uvco_v2 = luvs[edge_to_loops->indices[1]];
|
||||
for (int i = 2; i < edge_to_loops->count; i += 2) {
|
||||
if (loops[edge_to_loops->indices[i]].v == v1) {
|
||||
if (!equals_v2v2(uvco_v1, luvs[edge_to_loops->indices[i]]) ||
|
||||
!equals_v2v2(uvco_v2, luvs[edge_to_loops->indices[i + 1]])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
BLI_assert(loops[edge_to_loops->indices[i]].v == v2);
|
||||
UNUSED_VARS_NDEBUG(v2);
|
||||
if (!equals_v2v2(uvco_v2, luvs[edge_to_loops->indices[i]]) ||
|
||||
!equals_v2v2(uvco_v1, luvs[edge_to_loops->indices[i + 1]])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Edge is UV boundary if tagged as seam. */
|
||||
return (me->flag & ME_SEAM) != 0;
|
||||
}
|
||||
|
||||
static bool mesh_calc_islands_loop_poly_uv(const MEdge *edges,
|
||||
const int totedge,
|
||||
const MPoly *polys,
|
||||
|
@ -1084,8 +1018,6 @@ static bool mesh_calc_islands_loop_poly_uv(const MEdge *edges,
|
|||
MeshElemMap *edge_loop_map;
|
||||
int *edge_loop_mem;
|
||||
|
||||
MeshCheckIslandBoundaryUv edge_boundary_check_data;
|
||||
|
||||
int *poly_indices;
|
||||
int *loop_indices;
|
||||
int num_pidx, num_lidx;
|
||||
|
@ -1106,27 +1038,62 @@ static bool mesh_calc_islands_loop_poly_uv(const MEdge *edges,
|
|||
r_island_store, MISLAND_TYPE_LOOP, totloop, MISLAND_TYPE_POLY, MISLAND_TYPE_EDGE);
|
||||
|
||||
BKE_mesh_edge_poly_map_create(
|
||||
&edge_poly_map, &edge_poly_mem, edges, totedge, polys, totpoly, loops, totloop);
|
||||
&edge_poly_map, &edge_poly_mem, totedge, polys, totpoly, loops, totloop);
|
||||
|
||||
if (luvs) {
|
||||
BKE_mesh_edge_loop_map_create(
|
||||
&edge_loop_map, &edge_loop_mem, edges, totedge, polys, totpoly, loops, totloop);
|
||||
edge_boundary_check_data.loops = loops;
|
||||
edge_boundary_check_data.luvs = luvs;
|
||||
edge_boundary_check_data.edge_loop_map = edge_loop_map;
|
||||
&edge_loop_map, &edge_loop_mem, totedge, polys, totpoly, loops, totloop);
|
||||
}
|
||||
|
||||
poly_edge_loop_islands_calc(edges,
|
||||
totedge,
|
||||
polys,
|
||||
totpoly,
|
||||
loops,
|
||||
totloop,
|
||||
nullptr,
|
||||
/* TODO: I'm not sure edge seam flag is enough to define UV islands?
|
||||
* Maybe we should also consider UV-maps values
|
||||
* themselves (i.e. different UV-edges for a same mesh-edge => boundary edge too?).
|
||||
* Would make things much more complex though,
|
||||
* and each UVMap would then need its own mesh mapping, not sure we want that at all!
|
||||
*/
|
||||
auto mesh_check_island_boundary_uv = [&](const int /*poly_index*/,
|
||||
const int loop_index,
|
||||
const int edge_index,
|
||||
const int /*edge_user_count*/,
|
||||
const MeshElemMap & /*edge_poly_map_elem*/) -> bool {
|
||||
if (luvs) {
|
||||
const MeshElemMap &edge_to_loops = edge_loop_map[loops[loop_index].e];
|
||||
|
||||
BLI_assert(edge_to_loops.count >= 2 && (edge_to_loops.count % 2) == 0);
|
||||
|
||||
const uint v1 = loops[edge_to_loops.indices[0]].v;
|
||||
const uint v2 = loops[edge_to_loops.indices[1]].v;
|
||||
const float *uvco_v1 = luvs[edge_to_loops.indices[0]];
|
||||
const float *uvco_v2 = luvs[edge_to_loops.indices[1]];
|
||||
for (int i = 2; i < edge_to_loops.count; i += 2) {
|
||||
if (loops[edge_to_loops.indices[i]].v == v1) {
|
||||
if (!equals_v2v2(uvco_v1, luvs[edge_to_loops.indices[i]]) ||
|
||||
!equals_v2v2(uvco_v2, luvs[edge_to_loops.indices[i + 1]])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
BLI_assert(loops[edge_to_loops.indices[i]].v == v2);
|
||||
UNUSED_VARS_NDEBUG(v2);
|
||||
if (!equals_v2v2(uvco_v2, luvs[edge_to_loops.indices[i]]) ||
|
||||
!equals_v2v2(uvco_v1, luvs[edge_to_loops.indices[i + 1]])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Edge is UV boundary if tagged as seam. */
|
||||
return (edges[edge_index].flag & ME_SEAM) != 0;
|
||||
};
|
||||
|
||||
poly_edge_loop_islands_calc(totedge,
|
||||
{polys, totpoly},
|
||||
{loops, totloop},
|
||||
edge_poly_map,
|
||||
false,
|
||||
mesh_check_island_boundary_uv,
|
||||
luvs ? &edge_boundary_check_data : nullptr,
|
||||
&poly_groups,
|
||||
&num_poly_groups,
|
||||
&edge_borders,
|
||||
|
|
|
@ -1424,7 +1424,6 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
|
|||
/* Needed for islands (or plain mesh) to AStar graph conversion. */
|
||||
BKE_mesh_edge_poly_map_create(&edge_to_poly_map_src,
|
||||
&edge_to_poly_map_src_buff,
|
||||
edges_src,
|
||||
num_edges_src,
|
||||
polys_src,
|
||||
num_polys_src,
|
||||
|
|
|
@ -230,6 +230,7 @@ void BKE_mesh_runtime_clear_geometry(Mesh *mesh)
|
|||
mesh->runtime->loose_edges_cache.tag_dirty();
|
||||
mesh->runtime->looptris_cache.tag_dirty();
|
||||
mesh->runtime->subsurf_face_dot_tags.clear_and_shrink();
|
||||
mesh->runtime->subsurf_optimal_display_edges.clear_and_shrink();
|
||||
if (mesh->runtime->shrinkwrap_data) {
|
||||
BKE_shrinkwrap_boundary_data_free(mesh->runtime->shrinkwrap_data);
|
||||
}
|
||||
|
@ -245,6 +246,7 @@ void BKE_mesh_tag_edges_split(struct Mesh *mesh)
|
|||
free_subdiv_ccg(*mesh->runtime);
|
||||
mesh->runtime->loose_edges_cache.tag_dirty();
|
||||
mesh->runtime->subsurf_face_dot_tags.clear_and_shrink();
|
||||
mesh->runtime->subsurf_optimal_display_edges.clear_and_shrink();
|
||||
if (mesh->runtime->shrinkwrap_data) {
|
||||
BKE_shrinkwrap_boundary_data_free(mesh->runtime->shrinkwrap_data);
|
||||
}
|
||||
|
|
|
@ -1356,8 +1356,6 @@ void BKE_mesh_calc_edges_tessface(Mesh *mesh)
|
|||
for (int i = 0; BLI_edgesetIterator_isDone(ehi) == false;
|
||||
BLI_edgesetIterator_step(ehi), i++, med++, index++) {
|
||||
BLI_edgesetIterator_getKey(ehi, &med->v1, &med->v2);
|
||||
|
||||
med->flag = ME_EDGEDRAW;
|
||||
*index = ORIGINDEX_NONE;
|
||||
}
|
||||
BLI_edgesetIterator_free(ehi);
|
||||
|
|
|
@ -350,7 +350,7 @@ static Mesh *mesh_wrapper_ensure_subdivision(Mesh *me)
|
|||
BKE_mesh_calc_normals_split(subdiv_mesh);
|
||||
}
|
||||
|
||||
if (subdiv != runtime_data->subdiv_cpu && subdiv != runtime_data->subdiv_gpu) {
|
||||
if (!ELEM(subdiv, runtime_data->subdiv_cpu, runtime_data->subdiv_gpu)) {
|
||||
BKE_subdiv_free(subdiv);
|
||||
}
|
||||
|
||||
|
|
|
@ -2342,8 +2342,10 @@ bNode *node_copy_with_mapping(bNodeTree *dst_tree,
|
|||
node_dst->typeinfo->copyfunc_api(&ptr, &node_src);
|
||||
}
|
||||
|
||||
/* Reset the declaration of the new node. */
|
||||
nodeDeclarationEnsure(dst_tree, node_dst);
|
||||
/* Reset the declaration of the new node in real tree. */
|
||||
if (dst_tree != nullptr) {
|
||||
nodeDeclarationEnsure(dst_tree, node_dst);
|
||||
}
|
||||
|
||||
return node_dst;
|
||||
}
|
||||
|
@ -3455,21 +3457,41 @@ bNode *ntreeFindType(bNodeTree *ntree, int type)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
bool ntreeHasTree(const bNodeTree *ntree, const bNodeTree *lookup)
|
||||
static bool ntree_contains_tree_exec(const bNodeTree *tree_to_search_in,
|
||||
const bNodeTree *tree_to_search_for,
|
||||
Set<const bNodeTree *> &already_passed)
|
||||
{
|
||||
if (ntree == lookup) {
|
||||
if (tree_to_search_in == tree_to_search_for) {
|
||||
return true;
|
||||
}
|
||||
for (const bNode *node : ntree->all_nodes()) {
|
||||
if (ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP) && node->id) {
|
||||
if (ntreeHasTree((bNodeTree *)node->id, lookup)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
tree_to_search_in->ensure_topology_cache();
|
||||
for (const bNode *node_group : tree_to_search_in->group_nodes()) {
|
||||
const bNodeTree *sub_tree_search_in = reinterpret_cast<const bNodeTree *>(node_group->id);
|
||||
if (!sub_tree_search_in) {
|
||||
continue;
|
||||
}
|
||||
if (!already_passed.add(sub_tree_search_in)) {
|
||||
continue;
|
||||
}
|
||||
if (ntree_contains_tree_exec(sub_tree_search_in, tree_to_search_for, already_passed)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ntreeContainsTree(const bNodeTree *tree_to_search_in, const bNodeTree *tree_to_search_for)
|
||||
{
|
||||
if (tree_to_search_in == tree_to_search_for) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Set<const bNodeTree *> already_passed;
|
||||
return ntree_contains_tree_exec(tree_to_search_in, tree_to_search_for, already_passed);
|
||||
}
|
||||
|
||||
bNodeLink *nodeFindLink(bNodeTree *ntree, const bNodeSocket *from, const bNodeSocket *to)
|
||||
{
|
||||
LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) {
|
||||
|
@ -3617,6 +3639,8 @@ bool nodeDeclarationEnsureOnOutdatedNode(bNodeTree *ntree, bNode *node)
|
|||
return false;
|
||||
}
|
||||
if (node->typeinfo->declare_dynamic) {
|
||||
BLI_assert(ntree != nullptr);
|
||||
BLI_assert(node != nullptr);
|
||||
node->runtime->declaration = new blender::nodes::NodeDeclaration();
|
||||
blender::nodes::build_node_declaration_dynamic(*ntree, *node, *node->runtime->declaration);
|
||||
return true;
|
||||
|
|
|
@ -117,7 +117,7 @@ struct DupliContext {
|
|||
* decisions. However, new code uses geometry instances in places that weren't using the dupli
|
||||
* system previously. To fix this, keep track of the last dupli generator type that wasn't a
|
||||
* geometry set instance.
|
||||
* */
|
||||
*/
|
||||
Vector<short> *dupli_gen_type_stack;
|
||||
|
||||
int persistent_id[MAX_DUPLI_RECUR];
|
||||
|
|
|
@ -222,9 +222,9 @@ void BKE_ocean_eval_uv(struct Ocean *oc, struct OceanResult *ocr, float u, float
|
|||
j1 = j1 % oc->_N;
|
||||
|
||||
# define BILERP(m) \
|
||||
(interpf(interpf(m[i1 * oc->_N + j1], m[i0 * oc->_N + j1], frac_x), \
|
||||
interpf(m[i1 * oc->_N + j0], m[i0 * oc->_N + j0], frac_x), \
|
||||
frac_z))
|
||||
interpf(interpf(m[i1 * oc->_N + j1], m[i0 * oc->_N + j1], frac_x), \
|
||||
interpf(m[i1 * oc->_N + j0], m[i0 * oc->_N + j0], frac_x), \
|
||||
frac_z)
|
||||
|
||||
{
|
||||
if (oc->_do_disp_y) {
|
||||
|
|
|
@ -590,7 +590,7 @@ static void initialize_all_particles(ParticleSimulationData *sim)
|
|||
{
|
||||
ParticleSystem *psys = sim->psys;
|
||||
ParticleSettings *part = psys->part;
|
||||
/* Grid distributionsets UNEXIST flag, need to take care of
|
||||
/* Grid distribution-sets UNEXIST flag, need to take care of
|
||||
* it here because later this flag is being reset.
|
||||
*
|
||||
* We can't do it for any distribution, because it'll then
|
||||
|
@ -1931,7 +1931,7 @@ static void sphclassical_density_accum_cb(void *userdata,
|
|||
return;
|
||||
}
|
||||
|
||||
/* Smoothing factor. Utilize the Wendland kernel. gnuplot:
|
||||
/* Smoothing factor. Utilize the Wendland kernel. `gnuplot`:
|
||||
* q1(x) = (2.0 - x)**4 * ( 1.0 + 2.0 * x)
|
||||
* plot [0:2] q1(x) */
|
||||
q = qfac / pow3f(pfr->h) * pow4f(2.0f - rij_h) * (1.0f + 2.0f * rij_h);
|
||||
|
@ -2021,7 +2021,7 @@ static void sphclassical_force_cb(void *sphdata_v,
|
|||
NULL, psys, state->co, &pfr, interaction_radius, sphclassical_neighbor_accum_cb);
|
||||
pressure = stiffness * (pow7f(pa->sphdensity / rest_density) - 1.0f);
|
||||
|
||||
/* multiply by mass so that we return a force, not accel */
|
||||
/* Multiply by mass so that we return a force, not acceleration. */
|
||||
qfac2 *= sphdata->mass / pow3f(pfr.h);
|
||||
|
||||
pfn = pfr.neighbors;
|
||||
|
@ -2047,7 +2047,7 @@ static void sphclassical_force_cb(void *sphdata_v,
|
|||
npressure = stiffness * (pow7f(npa->sphdensity / rest_density) - 1.0f);
|
||||
|
||||
/* First derivative of smoothing factor. Utilize the Wendland kernel.
|
||||
* gnuplot:
|
||||
* `gnuplot`:
|
||||
* q2(x) = 2.0 * (2.0 - x)**4 - 4.0 * (2.0 - x)**3 * (1.0 + 2.0 * x)
|
||||
* plot [0:2] q2(x)
|
||||
* Particles > 2h away are excluded above. */
|
||||
|
@ -2438,15 +2438,17 @@ static float nr_distance_to_vert(float *p,
|
|||
{
|
||||
return len_v3v3(p, pce->x0) - radius;
|
||||
}
|
||||
/**
|
||||
* \param t: is the current time for newton rhapson.
|
||||
* \param fac: is the starting factor for current collision iteration.
|
||||
* \param col: The particle collision, `col->fac's` are factors for the
|
||||
* particle sub-frame step start and end during collision modifier step.
|
||||
*/
|
||||
static void collision_interpolate_element(ParticleCollisionElement *pce,
|
||||
float t,
|
||||
float fac,
|
||||
ParticleCollision *col)
|
||||
{
|
||||
/* t is the current time for newton rhapson */
|
||||
/* fac is the starting factor for current collision iteration */
|
||||
/* The col->fac's are factors for the particle subframe step start
|
||||
* and end during collision modifier step. */
|
||||
float f = fac + t * (1.0f - fac);
|
||||
float mul = col->fac1 + f * (col->fac2 - col->fac1);
|
||||
if (pce->tot > 0) {
|
||||
|
@ -3598,19 +3600,21 @@ static void save_hair(ParticleSimulationData *sim, float UNUSED(cfra))
|
|||
psys_sim_data_free(sim);
|
||||
}
|
||||
|
||||
/* Code for an adaptive time step based on the Courant-Friedrichs-Lewy
|
||||
* condition. */
|
||||
/** Code for an adaptive time step based on the Courant-Friedrichs-Lewy condition. */
|
||||
static const float MIN_TIMESTEP = 1.0f / 101.0f;
|
||||
/* Tolerance of 1.5 means the last subframe neither favors growing nor
|
||||
* shrinking (e.g if it were 1.3, the last subframe would tend to be too
|
||||
* small). */
|
||||
/**
|
||||
* Tolerance of 1.5 means the last sub-frame neither favors growing nor shrinking
|
||||
* (e.g if it were 1.3, the last sub-frame would tend to be too small).
|
||||
*/
|
||||
static const float TIMESTEP_EXPANSION_FACTOR = 0.1f;
|
||||
static const float TIMESTEP_EXPANSION_TOLERANCE = 1.5f;
|
||||
|
||||
/* Calculate the speed of the particle relative to the local scale of the
|
||||
/**
|
||||
* Calculate the speed of the particle relative to the local scale of the
|
||||
* simulation. This should be called once per particle during a simulation
|
||||
* step, after the velocity has been updated. element_size defines the scale of
|
||||
* the simulation, and is typically the distance to neighboring particles. */
|
||||
* the simulation, and is typically the distance to neighboring particles.
|
||||
*/
|
||||
static void update_courant_num(
|
||||
ParticleSimulationData *sim, ParticleData *pa, float dtime, SPHData *sphdata, SpinLock *spin)
|
||||
{
|
||||
|
|
|
@ -738,7 +738,7 @@ struct EdgeQueueContext {
|
|||
|
||||
/* Only tagged edges are in the queue. */
|
||||
#ifdef USE_EDGEQUEUE_TAG
|
||||
# define EDGE_QUEUE_TEST(e) (BM_elem_flag_test((CHECK_TYPE_INLINE(e, BMEdge *), e), BM_ELEM_TAG))
|
||||
# define EDGE_QUEUE_TEST(e) BM_elem_flag_test((CHECK_TYPE_INLINE(e, BMEdge *), e), BM_ELEM_TAG)
|
||||
# define EDGE_QUEUE_ENABLE(e) \
|
||||
BM_elem_flag_enable((CHECK_TYPE_INLINE(e, BMEdge *), e), BM_ELEM_TAG)
|
||||
# define EDGE_QUEUE_DISABLE(e) \
|
||||
|
|
|
@ -49,7 +49,7 @@ static int primitive_get_other_uv_vertex(const MeshData &mesh_data,
|
|||
mesh_loops[looptri.tri[2]].v));
|
||||
for (const int loop : looptri.tri) {
|
||||
const int vert = mesh_loops[loop].v;
|
||||
if (vert != v1 && vert != v2) {
|
||||
if (!ELEM(vert, v1, v2)) {
|
||||
return vert;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3133,10 +3133,10 @@ static void ptcache_dt_to_str(char *str, double dtime)
|
|||
if (dtime > 60.0) {
|
||||
if (dtime > 3600.0) {
|
||||
BLI_sprintf(
|
||||
str, "%ih %im %is", (int)(dtime / 3600), ((int)(dtime / 60)) % 60, ((int)dtime) % 60);
|
||||
str, "%ih %im %is", (int)(dtime / 3600), (int)(dtime / 60) % 60, ((int)dtime) % 60);
|
||||
}
|
||||
else {
|
||||
BLI_sprintf(str, "%im %is", ((int)(dtime / 60)) % 60, ((int)dtime) % 60);
|
||||
BLI_sprintf(str, "%im %is", (int)(dtime / 60) % 60, ((int)dtime) % 60);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -536,6 +536,10 @@ static bool subdiv_mesh_topology_info(const SubdivForeachContext *foreach_contex
|
|||
subdiv_mesh_prepare_accumulator(subdiv_context, num_vertices);
|
||||
subdiv_context->subdiv_mesh->runtime->subsurf_face_dot_tags.clear();
|
||||
subdiv_context->subdiv_mesh->runtime->subsurf_face_dot_tags.resize(num_vertices);
|
||||
if (subdiv_context->settings->use_optimal_display) {
|
||||
subdiv_context->subdiv_mesh->runtime->subsurf_optimal_display_edges.clear();
|
||||
subdiv_context->subdiv_mesh->runtime->subsurf_optimal_display_edges.resize(num_edges);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -784,15 +788,10 @@ static void subdiv_mesh_vertex_inner(const SubdivForeachContext *foreach_context
|
|||
* \{ */
|
||||
|
||||
static void subdiv_copy_edge_data(SubdivMeshContext *ctx,
|
||||
MEdge *subdiv_edge,
|
||||
const int subdiv_edge_index,
|
||||
const int coarse_edge_index)
|
||||
{
|
||||
const int subdiv_edge_index = subdiv_edge - ctx->subdiv_edges;
|
||||
if (coarse_edge_index == ORIGINDEX_NONE) {
|
||||
subdiv_edge->flag = 0;
|
||||
if (!ctx->settings->use_optimal_display) {
|
||||
subdiv_edge->flag |= ME_EDGEDRAW;
|
||||
}
|
||||
if (ctx->edge_origindex != nullptr) {
|
||||
ctx->edge_origindex[subdiv_edge_index] = ORIGINDEX_NONE;
|
||||
}
|
||||
|
@ -800,7 +799,9 @@ static void subdiv_copy_edge_data(SubdivMeshContext *ctx,
|
|||
}
|
||||
CustomData_copy_data(
|
||||
&ctx->coarse_mesh->edata, &ctx->subdiv_mesh->edata, coarse_edge_index, subdiv_edge_index, 1);
|
||||
subdiv_edge->flag |= ME_EDGEDRAW;
|
||||
if (ctx->settings->use_optimal_display) {
|
||||
ctx->subdiv_mesh->runtime->subsurf_optimal_display_edges[subdiv_edge_index].set();
|
||||
}
|
||||
}
|
||||
|
||||
static void subdiv_mesh_edge(const SubdivForeachContext *foreach_context,
|
||||
|
@ -814,7 +815,7 @@ static void subdiv_mesh_edge(const SubdivForeachContext *foreach_context,
|
|||
SubdivMeshContext *ctx = static_cast<SubdivMeshContext *>(foreach_context->user_data);
|
||||
MEdge *subdiv_medge = ctx->subdiv_edges;
|
||||
MEdge *subdiv_edge = &subdiv_medge[subdiv_edge_index];
|
||||
subdiv_copy_edge_data(ctx, subdiv_edge, coarse_edge_index);
|
||||
subdiv_copy_edge_data(ctx, subdiv_edge_index, coarse_edge_index);
|
||||
subdiv_edge->v1 = subdiv_v1;
|
||||
subdiv_edge->v2 = subdiv_v2;
|
||||
}
|
||||
|
|
|
@ -928,7 +928,6 @@ static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge)
|
|||
int edgeSize = ccgSubSurf_getEdgeSize(ss);
|
||||
uint i = 0;
|
||||
short *edgeFlags = ccgdm->edgeFlags;
|
||||
const short ed_interior_flag = ccgdm->drawInteriorEdges ? ME_EDGEDRAW : 0;
|
||||
|
||||
totface = ccgSubSurf_getNumFaces(ss);
|
||||
for (index = 0; index < totface; index++) {
|
||||
|
@ -940,7 +939,7 @@ static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge)
|
|||
ccgDM_to_MEdge(&medge[i++],
|
||||
getFaceIndex(ss, f, S, x, 0, edgeSize, gridSize),
|
||||
getFaceIndex(ss, f, S, x + 1, 0, edgeSize, gridSize),
|
||||
ed_interior_flag);
|
||||
0);
|
||||
}
|
||||
|
||||
for (x = 1; x < gridSize - 1; x++) {
|
||||
|
@ -948,11 +947,11 @@ static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge)
|
|||
ccgDM_to_MEdge(&medge[i++],
|
||||
getFaceIndex(ss, f, S, x, y, edgeSize, gridSize),
|
||||
getFaceIndex(ss, f, S, x, y + 1, edgeSize, gridSize),
|
||||
ed_interior_flag);
|
||||
0);
|
||||
ccgDM_to_MEdge(&medge[i++],
|
||||
getFaceIndex(ss, f, S, y, x, edgeSize, gridSize),
|
||||
getFaceIndex(ss, f, S, y + 1, x, edgeSize, gridSize),
|
||||
ed_interior_flag);
|
||||
0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -967,12 +966,9 @@ static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge)
|
|||
|
||||
if (edgeFlags) {
|
||||
if (edgeIdx != -1) {
|
||||
ed_flag |= ((edgeFlags[index] & ME_SEAM) | ME_EDGEDRAW);
|
||||
ed_flag |= (edgeFlags[index] & ME_SEAM);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ed_flag |= ME_EDGEDRAW;
|
||||
}
|
||||
|
||||
for (x = 0; x < edgeSize - 1; x++) {
|
||||
ccgDM_to_MEdge(&medge[i++],
|
||||
|
@ -1367,7 +1363,7 @@ static void ccgdm_create_grids(DerivedMesh *dm)
|
|||
gridFlagMats = static_cast<DMFlagMat *>(
|
||||
MEM_mallocN(sizeof(DMFlagMat) * numGrids, "ccgdm.gridFlagMats"));
|
||||
|
||||
ccgdm->gridHidden = static_cast<unsigned int **>(
|
||||
ccgdm->gridHidden = static_cast<uint **>(
|
||||
MEM_callocN(sizeof(*ccgdm->gridHidden) * numGrids, "ccgdm.gridHidden"));
|
||||
|
||||
for (gIndex = 0, index = 0; index < numFaces; index++) {
|
||||
|
|
|
@ -527,7 +527,7 @@ static const AVCodec *get_av1_encoder(
|
|||
if (context->ffmpeg_crf >= 0) {
|
||||
/* librav1e does not use `-crf`, but uses `-qp` in the range of 0-255.
|
||||
* Calculates the roughly equivalent float, and truncates it to an integer. */
|
||||
unsigned int qp_value = ((float)context->ffmpeg_crf) * 255.0F / 51.0F;
|
||||
uint qp_value = ((float)context->ffmpeg_crf) * 255.0f / 51.0f;
|
||||
if (qp_value > 255) {
|
||||
qp_value = 255;
|
||||
}
|
||||
|
|
|
@ -82,7 +82,7 @@ typedef struct BLI_memiter {
|
|||
|
||||
BLI_INLINE uint data_offset_from_size(uint size)
|
||||
{
|
||||
return (PADUP(size, (uint)sizeof(data_t))) / (uint)sizeof(data_t);
|
||||
return PADUP(size, (uint)sizeof(data_t)) / (uint)sizeof(data_t);
|
||||
}
|
||||
|
||||
static void memiter_set_rewind_offset(BLI_memiter *mi)
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace blender::lazy_threading {
|
|||
* deadlocks.
|
||||
*/
|
||||
using HintReceivers = RawStack<RawVector<FunctionRef<void()>, 0>, 0>;
|
||||
thread_local HintReceivers hint_receivers = []() {
|
||||
static thread_local HintReceivers hint_receivers = []() {
|
||||
HintReceivers receivers;
|
||||
/* Make sure there is always at least one vector. */
|
||||
receivers.push_as();
|
||||
|
|
|
@ -257,7 +257,7 @@ void shuffle_m4(float R[4][4], const int index[4])
|
|||
|
||||
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
|
||||
{
|
||||
if (R == A || R == B) {
|
||||
if (ELEM(R, A, B)) {
|
||||
float T[4][4];
|
||||
mul_m4_m4m4(T, A, B);
|
||||
copy_m4_m4(R, T);
|
||||
|
@ -359,7 +359,7 @@ void mul_m3_m3_post(float R[3][3], const float B[3][3])
|
|||
|
||||
void mul_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3])
|
||||
{
|
||||
if (R == A || R == B) {
|
||||
if (ELEM(R, A, B)) {
|
||||
float T[3][3];
|
||||
mul_m3_m3m3(T, A, B);
|
||||
copy_m3_m3(R, T);
|
||||
|
|
|
@ -3779,15 +3779,6 @@ void blo_do_versions_300(FileData *fd, Library * /*lib*/, Main *bmain)
|
|||
}
|
||||
}
|
||||
|
||||
if (!MAIN_VERSION_ATLEAST(bmain, 305, 1)) {
|
||||
/* Reset edge visibility flag, since the base is meant to be "true" for original meshes. */
|
||||
LISTBASE_FOREACH (Mesh *, mesh, &bmain->meshes) {
|
||||
for (MEdge &edge : mesh->edges_for_write()) {
|
||||
edge.flag |= ME_EDGEDRAW;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!MAIN_VERSION_ATLEAST(bmain, 305, 2)) {
|
||||
LISTBASE_FOREACH (MovieClip *, clip, &bmain->movieclips) {
|
||||
MovieTracking *tracking = &clip->tracking;
|
||||
|
@ -3901,6 +3892,21 @@ void blo_do_versions_300(FileData *fd, Library * /*lib*/, Main *bmain)
|
|||
}
|
||||
}
|
||||
|
||||
if (!MAIN_VERSION_ATLEAST(bmain, 305, 9)) {
|
||||
/* Enable legacy normal and rotation outputs in Distribute Points on Faces node. */
|
||||
LISTBASE_FOREACH (bNodeTree *, ntree, &bmain->nodetrees) {
|
||||
if (ntree->type != NTREE_GEOMETRY) {
|
||||
continue;
|
||||
}
|
||||
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
|
||||
if (node->type != GEO_NODE_DISTRIBUTE_POINTS_ON_FACES) {
|
||||
continue;
|
||||
}
|
||||
node->custom2 = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Versioning code until next subversion bump goes here.
|
||||
*
|
||||
|
|
|
@ -1467,7 +1467,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *bmain)
|
|||
|
||||
for (me = bmain->meshes.first; me; me = me->id.next) {
|
||||
if (!me->medge) {
|
||||
BKE_mesh_calc_edges_legacy(me, true); /* true = use #MFace.edcode. */
|
||||
BKE_mesh_calc_edges_legacy(me);
|
||||
}
|
||||
else {
|
||||
BKE_mesh_strip_loose_faces(me);
|
||||
|
|
|
@ -113,7 +113,7 @@ using blender::StringRef;
|
|||
|
||||
static char bm_edge_flag_from_mflag(const short mflag)
|
||||
{
|
||||
return ((mflag & ME_SEAM) ? BM_ELEM_SEAM : 0) | ((mflag & ME_EDGEDRAW) ? BM_ELEM_DRAW : 0);
|
||||
return ((mflag & ME_SEAM) ? BM_ELEM_SEAM : 0) | BM_ELEM_DRAW;
|
||||
}
|
||||
static char bm_face_flag_from_mflag(const char mflag)
|
||||
{
|
||||
|
@ -124,7 +124,7 @@ static short bm_edge_flag_to_mflag(const BMEdge *e)
|
|||
{
|
||||
const char hflag = e->head.hflag;
|
||||
|
||||
return ((hflag & BM_ELEM_SEAM) ? ME_SEAM : 0) | ((hflag & BM_ELEM_DRAW) ? ME_EDGEDRAW : 0);
|
||||
return (hflag & BM_ELEM_SEAM) ? ME_SEAM : 0;
|
||||
}
|
||||
static char bm_face_flag_to_mflag(const BMFace *f)
|
||||
{
|
||||
|
@ -133,6 +133,20 @@ static char bm_face_flag_to_mflag(const BMFace *f)
|
|||
return ((hflag & BM_ELEM_SMOOTH) ? ME_SMOOTH : 0);
|
||||
}
|
||||
|
||||
bool BM_attribute_stored_in_bmesh_builtin(const StringRef name)
|
||||
{
|
||||
return ELEM(name,
|
||||
"position",
|
||||
".hide_vert",
|
||||
".hide_edge",
|
||||
".hide_poly",
|
||||
".select_vert",
|
||||
".select_edge",
|
||||
".select_poly",
|
||||
"material_index",
|
||||
"sharp_edge");
|
||||
}
|
||||
|
||||
/* Static function for alloc (duplicate in modifiers_bmesh.c) */
|
||||
static BMFace *bm_face_create_from_mpoly(BMesh &bm,
|
||||
Span<MLoop> loops,
|
||||
|
@ -1420,15 +1434,6 @@ static void bm_to_mesh_edges(const BMesh &bm,
|
|||
dst_edge.v1 = BM_elem_index_get(src_edge.v1);
|
||||
dst_edge.v2 = BM_elem_index_get(src_edge.v2);
|
||||
dst_edge.flag = bm_edge_flag_to_mflag(&src_edge);
|
||||
|
||||
/* Handle this differently to editmode switching; only enable draw for single user
|
||||
* edges rather than calculating angle. */
|
||||
if ((dst_edge.flag & ME_EDGEDRAW) == 0) {
|
||||
if (src_edge.l && src_edge.l == src_edge.l->radial_next) {
|
||||
dst_edge.flag |= ME_EDGEDRAW;
|
||||
}
|
||||
}
|
||||
|
||||
CustomData_from_bmesh_block(&bm.edata, &mesh.edata, src_edge.head.data, edge_i);
|
||||
}
|
||||
if (!select_edge.is_empty()) {
|
||||
|
|
|
@ -9,6 +9,16 @@
|
|||
|
||||
#include "bmesh.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
# include "BLI_string_ref.hh"
|
||||
|
||||
/**
|
||||
* \return Whether attributes with the given name are stored in special flags or fields in BMesh
|
||||
* rather than in the regular custom data blocks.
|
||||
*/
|
||||
bool BM_attribute_stored_in_bmesh_builtin(const blender::StringRef name);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -82,7 +92,6 @@ void BM_mesh_bm_to_me(struct Main *bmain,
|
|||
* - Ignore shape-keys.
|
||||
* - Ignore vertex-parents.
|
||||
* - Ignore selection history.
|
||||
* - Uses simpler method to calculate #ME_EDGEDRAW
|
||||
* - Uses #CD_MASK_DERIVEDMESH instead of #CD_MASK_MESH.
|
||||
*
|
||||
* \note Was `cddm_from_bmesh_ex` in 2.7x, removed `MFace` support.
|
||||
|
|
|
@ -1235,7 +1235,7 @@ void BM_face_splits_check_legal(BMesh *bm, BMFace *f, BMLoop *(*loops)[2], int l
|
|||
}
|
||||
|
||||
#define EDGE_SHARE_VERT(e1, e2) \
|
||||
((ELEM((e1)[0], (e2)[0], (e2)[1])) || (ELEM((e1)[1], (e2)[0], (e2)[1])))
|
||||
(ELEM((e1)[0], (e2)[0], (e2)[1]) || ELEM((e1)[1], (e2)[0], (e2)[1]))
|
||||
|
||||
/* do line crossing tests */
|
||||
for (i = 0, i_prev = f->len - 1; i < f->len; i_prev = i++) {
|
||||
|
|
|
@ -1062,7 +1062,7 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op)
|
|||
matched = 1;
|
||||
for (j = 0; j < pat->len; j++) {
|
||||
a = (j + i) % pat->len;
|
||||
if ((!!BMO_edge_flag_test(bm, edges[a], SUBD_SPLIT)) != (!!pat->seledges[j])) {
|
||||
if (!!BMO_edge_flag_test(bm, edges[a], SUBD_SPLIT) != (!!pat->seledges[j])) {
|
||||
matched = 0;
|
||||
break;
|
||||
}
|
||||
|
@ -1095,7 +1095,7 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op)
|
|||
matched = 1;
|
||||
for (b = 0; b < pat->len; b++) {
|
||||
j = (b + a) % pat->len;
|
||||
if ((!!BMO_edge_flag_test(bm, edges[j], SUBD_SPLIT)) != (!!pat->seledges[b])) {
|
||||
if (!!BMO_edge_flag_test(bm, edges[j], SUBD_SPLIT) != (!!pat->seledges[b])) {
|
||||
matched = 0;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -2265,7 +2265,7 @@ static void snap_to_superellipsoid(float co[3], const float super_r, bool midlin
|
|||
co[2] = z;
|
||||
}
|
||||
|
||||
#define BEV_EXTEND_EDGE_DATA_CHECK(eh, flag) (BM_elem_flag_test(eh->e, flag))
|
||||
#define BEV_EXTEND_EDGE_DATA_CHECK(eh, flag) BM_elem_flag_test(eh->e, flag)
|
||||
|
||||
static void check_edge_data_seam_sharp_edges(BevVert *bv, int flag, bool neg)
|
||||
{
|
||||
|
|
|
@ -507,7 +507,7 @@ void EEVEE_motion_blur_cache_finish(EEVEE_Data *vedata)
|
|||
if (!GPU_batch_vertbuf_has(batch, vbo)) {
|
||||
/* Currently, the code assumes that all objects that share the same mesh in the
|
||||
* current frame also share the same mesh on other frames. */
|
||||
GPU_batch_vertbuf_add_ex(batch, vbo, false);
|
||||
GPU_batch_vertbuf_add(batch, vbo, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -449,7 +449,7 @@ void ShadowDirectional::cascade_tilemaps_distribution(Light &light, const Camera
|
|||
}
|
||||
|
||||
/************************************************************************
|
||||
* Clipmap Distribution *
|
||||
* Clip-map Distribution *
|
||||
************************************************************************/
|
||||
|
||||
IndexRange ShadowDirectional::clipmap_level_range(const Camera &camera)
|
||||
|
@ -593,7 +593,7 @@ void ShadowDirectional::end_sync(Light &light, const Camera &camera, float lod_b
|
|||
for (int64_t i = 0; i < before_range; i++) {
|
||||
tilemaps_.append(tilemap_pool.acquire());
|
||||
}
|
||||
/* Keep cached lods. */
|
||||
/* Keep cached LOD's. */
|
||||
tilemaps_.extend(cached_tilemaps);
|
||||
for (int64_t i = 0; i < after_range; i++) {
|
||||
tilemaps_.append(tilemap_pool.acquire());
|
||||
|
@ -1044,7 +1044,7 @@ void ShadowModule::debug_end_sync()
|
|||
|
||||
debug_draw_ps_.state_set(state);
|
||||
debug_draw_ps_.shader_set(inst_.shaders.static_shader_get(SHADOW_DEBUG));
|
||||
debug_draw_ps_.push_constant("debug_mode", (int)inst_.debug_mode);
|
||||
debug_draw_ps_.push_constant("debug_mode", int(inst_.debug_mode));
|
||||
debug_draw_ps_.push_constant("debug_tilemap_index", light.tilemap_index);
|
||||
debug_draw_ps_.bind_ssbo("tilemaps_buf", &tilemap_pool.tilemaps_data);
|
||||
debug_draw_ps_.bind_ssbo("tiles_buf", &tilemap_pool.tiles_data);
|
||||
|
|
|
@ -268,7 +268,7 @@ class ShadowModule {
|
|||
/** \name Debugging
|
||||
* \{ */
|
||||
|
||||
/** Display informations about the virtual shadows. */
|
||||
/** Display information about the virtual shadows. */
|
||||
PassSimple debug_draw_ps_ = {"Shadow.Debug"};
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -904,10 +904,10 @@ static void gpencil_edit_batches_ensure(Object *ob, GpencilBatchCache *cache, in
|
|||
|
||||
/* Create the batches */
|
||||
cache->edit_points_batch = GPU_batch_create(GPU_PRIM_POINTS, cache->vbo, nullptr);
|
||||
GPU_batch_vertbuf_add(cache->edit_points_batch, cache->edit_vbo);
|
||||
GPU_batch_vertbuf_add(cache->edit_points_batch, cache->edit_vbo, false);
|
||||
|
||||
cache->edit_lines_batch = GPU_batch_create(GPU_PRIM_LINE_STRIP, cache->vbo, nullptr);
|
||||
GPU_batch_vertbuf_add(cache->edit_lines_batch, cache->edit_vbo);
|
||||
GPU_batch_vertbuf_add(cache->edit_lines_batch, cache->edit_vbo, false);
|
||||
}
|
||||
|
||||
/* Curve Handles and Points for Editing. */
|
||||
|
@ -941,11 +941,11 @@ static void gpencil_edit_batches_ensure(Object *ob, GpencilBatchCache *cache, in
|
|||
|
||||
cache->edit_curve_handles_batch = GPU_batch_create(
|
||||
GPU_PRIM_LINES, cache->edit_curve_vbo, nullptr);
|
||||
GPU_batch_vertbuf_add(cache->edit_curve_handles_batch, cache->edit_curve_vbo);
|
||||
GPU_batch_vertbuf_add(cache->edit_curve_handles_batch, cache->edit_curve_vbo, false);
|
||||
|
||||
cache->edit_curve_points_batch = GPU_batch_create(
|
||||
GPU_PRIM_POINTS, cache->edit_curve_vbo, nullptr);
|
||||
GPU_batch_vertbuf_add(cache->edit_curve_points_batch, cache->edit_curve_vbo);
|
||||
GPU_batch_vertbuf_add(cache->edit_curve_points_batch, cache->edit_curve_vbo, false);
|
||||
}
|
||||
|
||||
gpd->flag &= ~GP_DATA_CACHE_IS_DIRTY;
|
||||
|
|
|
@ -197,7 +197,7 @@ static void drw_volume_wireframe_cb(
|
|||
GPU_PRIM_LINES, cache->face_wire.pos_nor_in_order, ibo, GPU_BATCH_OWNS_INDEX);
|
||||
}
|
||||
|
||||
GPU_batch_vertbuf_add_ex(cache->face_wire.batch, vbo_wiredata, true);
|
||||
GPU_batch_vertbuf_add(cache->face_wire.batch, vbo_wiredata, true);
|
||||
}
|
||||
|
||||
GPUBatch *DRW_volume_batch_cache_get_wireframes_face(Volume *volume)
|
||||
|
|
|
@ -71,7 +71,7 @@ BLI_INLINE void DRW_vbo_request(GPUBatch *batch, GPUVertBuf **vbo)
|
|||
}
|
||||
if (batch != NULL) {
|
||||
/* HACK we set VBO's that may not yet be valid. */
|
||||
GPU_batch_vertbuf_add(batch, *vbo);
|
||||
GPU_batch_vertbuf_add(batch, *vbo, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -226,11 +226,11 @@ void DRW_instance_buffer_finish(DRWInstanceDataList *idatalist)
|
|||
GPU_batch_copy(batch, geom);
|
||||
if (inst_batch != NULL) {
|
||||
for (int i = 0; i < GPU_BATCH_INST_VBO_MAX_LEN && inst_batch->verts[i]; i++) {
|
||||
GPU_batch_instbuf_add_ex(batch, inst_batch->verts[i], false);
|
||||
GPU_batch_instbuf_add(batch, inst_batch->verts[i], false);
|
||||
}
|
||||
}
|
||||
else {
|
||||
GPU_batch_instbuf_add_ex(batch, inst_buf, false);
|
||||
GPU_batch_instbuf_add(batch, inst_buf, false);
|
||||
}
|
||||
/* Add reference to avoid comparing pointers (in DRW_temp_batch_request) that could
|
||||
* potentially be the same. This will delay the freeing of the GPUVertBuf itself. */
|
||||
|
|
|
@ -1184,7 +1184,7 @@ static void drw_engines_enable_from_engine(const RenderEngineType *engine_type,
|
|||
case OB_WIRE:
|
||||
case OB_SOLID:
|
||||
if (U.experimental.enable_workbench_next &&
|
||||
strcmp(engine_type->idname, "BLENDER_WORKBENCH_NEXT") == 0) {
|
||||
STREQ(engine_type->idname, "BLENDER_WORKBENCH_NEXT")) {
|
||||
use_drw_engine(DRW_engine_viewport_workbench_next_type.draw_engine);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -1303,10 +1303,10 @@ struct PBVHBatches {
|
|||
int vbo_i = get_vbo_index(vbo);
|
||||
|
||||
batch.vbos.append(vbo_i);
|
||||
GPU_batch_vertbuf_add_ex(batch.tris, vbo->vert_buf, false);
|
||||
GPU_batch_vertbuf_add(batch.tris, vbo->vert_buf, false);
|
||||
|
||||
if (batch.lines) {
|
||||
GPU_batch_vertbuf_add_ex(batch.lines, vbo->vert_buf, false);
|
||||
GPU_batch_vertbuf_add(batch.lines, vbo->vert_buf, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -60,15 +60,8 @@ static void extract_edge_fac_init(const MeshRenderData *mr,
|
|||
|
||||
if (mr->extract_type == MR_EXTRACT_MESH) {
|
||||
data->edge_loop_count = MEM_cnew_array<uint8_t>(mr->edge_len, __func__);
|
||||
|
||||
/* HACK(@fclem): Detecting the need for edge render.
|
||||
* We could have a flag in the mesh instead or check the modifier stack. */
|
||||
const MEdge *med = mr->medge;
|
||||
for (int e_index = 0; e_index < mr->edge_len; e_index++, med++) {
|
||||
if ((med->flag & ME_EDGEDRAW) == 0) {
|
||||
data->use_edge_render = true;
|
||||
break;
|
||||
}
|
||||
if (!mr->me->runtime->subsurf_optimal_display_edges.is_empty()) {
|
||||
data->use_edge_render = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -109,6 +102,7 @@ static void extract_edge_fac_iter_poly_mesh(const MeshRenderData *mr,
|
|||
void *_data)
|
||||
{
|
||||
MeshExtract_EdgeFac_Data *data = static_cast<MeshExtract_EdgeFac_Data *>(_data);
|
||||
const BitVector<> &optimal_display_edges = mr->me->runtime->subsurf_optimal_display_edges;
|
||||
|
||||
const MLoop *mloop = mr->mloop;
|
||||
const int ml_index_end = mp->loopstart + mp->totloop;
|
||||
|
@ -116,8 +110,7 @@ static void extract_edge_fac_iter_poly_mesh(const MeshRenderData *mr,
|
|||
const MLoop *ml = &mloop[ml_index];
|
||||
|
||||
if (data->use_edge_render) {
|
||||
const MEdge *med = &mr->medge[ml->e];
|
||||
data->vbo_data[ml_index] = (med->flag & ME_EDGEDRAW) ? 255 : 0;
|
||||
data->vbo_data[ml_index] = optimal_display_edges[ml->e] ? 255 : 0;
|
||||
}
|
||||
else {
|
||||
|
||||
|
|
|
@ -4373,6 +4373,53 @@ static bool achannel_is_being_renamed(const bAnimContext *ac,
|
|||
return false;
|
||||
}
|
||||
|
||||
float ANIM_UI_get_keyframe_scale_factor(void)
|
||||
{
|
||||
bTheme *btheme = UI_GetTheme();
|
||||
const float yscale_fac = btheme->space_action.keyframe_scale_fac;
|
||||
|
||||
/* clamp to avoid problems with uninitialized values... */
|
||||
if (yscale_fac < 0.1f) {
|
||||
return 1.0f;
|
||||
}
|
||||
return yscale_fac;
|
||||
}
|
||||
|
||||
float ANIM_UI_get_channel_height(void)
|
||||
{
|
||||
return 0.8f * ANIM_UI_get_keyframe_scale_factor() * U.widget_unit;
|
||||
}
|
||||
|
||||
float ANIM_UI_get_channel_skip(void)
|
||||
{
|
||||
return 0.1f * U.widget_unit;
|
||||
}
|
||||
|
||||
float ANIM_UI_get_first_channel_top(View2D *v2d)
|
||||
{
|
||||
return UI_view2d_scale_get_y(v2d) * -UI_TIME_SCRUB_MARGIN_Y - ANIM_UI_get_channel_skip();
|
||||
}
|
||||
|
||||
float ANIM_UI_get_channel_step(void)
|
||||
{
|
||||
return ANIM_UI_get_channel_height() + ANIM_UI_get_channel_skip();
|
||||
}
|
||||
|
||||
float ANIM_UI_get_channels_total_height(View2D *v2d, const int item_count)
|
||||
{
|
||||
return -ANIM_UI_get_first_channel_top(v2d) + ANIM_UI_get_channel_step() * (item_count + 1);
|
||||
}
|
||||
|
||||
float ANIM_UI_get_channel_name_width(void)
|
||||
{
|
||||
return 10 * U.widget_unit;
|
||||
}
|
||||
|
||||
float ANIM_UI_get_channel_button_width(void)
|
||||
{
|
||||
return 0.8f * U.widget_unit;
|
||||
}
|
||||
|
||||
void ANIM_channel_draw(
|
||||
bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc, size_t channel_index)
|
||||
{
|
||||
|
@ -4566,7 +4613,8 @@ void ANIM_channel_draw(
|
|||
}
|
||||
|
||||
/* check if there's enough space for the toggles if the sliders are drawn too */
|
||||
if (!(draw_sliders) || (BLI_rcti_size_x(&v2d->mask) > ACHANNEL_BUTTON_WIDTH / 2)) {
|
||||
if (!(draw_sliders) ||
|
||||
(BLI_rcti_size_x(&v2d->mask) > ANIM_UI_get_channel_button_width() / 2)) {
|
||||
/* protect... */
|
||||
if (acf->has_setting(ac, ale, ACHANNEL_SETTING_PROTECT)) {
|
||||
offset += ICON_WIDTH;
|
||||
|
@ -5279,7 +5327,8 @@ void ANIM_channel_draw_widgets(const bContext *C,
|
|||
}
|
||||
|
||||
/* check if there's enough space for the toggles if the sliders are drawn too */
|
||||
if (!(draw_sliders) || (BLI_rcti_size_x(&v2d->mask) > ACHANNEL_BUTTON_WIDTH / 2)) {
|
||||
if (!(draw_sliders) ||
|
||||
(BLI_rcti_size_x(&v2d->mask) > ANIM_UI_get_channel_button_width() / 2)) {
|
||||
/* protect... */
|
||||
if (acf->has_setting(ac, ale, ACHANNEL_SETTING_PROTECT)) {
|
||||
offset -= ICON_WIDTH;
|
||||
|
|
|
@ -2718,7 +2718,7 @@ static void box_select_anim_channels(bAnimContext *ac, rcti *rect, short selectm
|
|||
ymax = NLACHANNEL_FIRST_TOP(ac);
|
||||
}
|
||||
else {
|
||||
ymax = ACHANNEL_FIRST_TOP(ac);
|
||||
ymax = ANIM_UI_get_first_channel_top(v2d);
|
||||
}
|
||||
|
||||
/* loop over data, doing box select */
|
||||
|
@ -2726,7 +2726,7 @@ static void box_select_anim_channels(bAnimContext *ac, rcti *rect, short selectm
|
|||
float ymin;
|
||||
|
||||
if (ale->type == ANIMTYPE_GPDATABLOCK) {
|
||||
ymax -= ACHANNEL_STEP(ac);
|
||||
ymax -= ANIM_UI_get_channel_step();
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -2734,7 +2734,7 @@ static void box_select_anim_channels(bAnimContext *ac, rcti *rect, short selectm
|
|||
ymin = ymax - NLACHANNEL_STEP(snla);
|
||||
}
|
||||
else {
|
||||
ymin = ymax - ACHANNEL_STEP(ac);
|
||||
ymin = ymax - ANIM_UI_get_channel_step();
|
||||
}
|
||||
|
||||
/* if channel is within border-select region, alter it */
|
||||
|
@ -2948,10 +2948,10 @@ static int animchannels_channel_get(bAnimContext *ac, const int mval[2])
|
|||
&channel_index);
|
||||
}
|
||||
else {
|
||||
UI_view2d_listview_view_to_cell(ACHANNEL_NAMEWIDTH,
|
||||
ACHANNEL_STEP(ac),
|
||||
UI_view2d_listview_view_to_cell(ANIM_UI_get_channel_name_width(),
|
||||
ANIM_UI_get_channel_step(),
|
||||
0,
|
||||
ACHANNEL_FIRST_TOP(ac),
|
||||
ANIM_UI_get_first_channel_top(v2d),
|
||||
x,
|
||||
y,
|
||||
NULL,
|
||||
|
@ -3484,10 +3484,10 @@ static int animchannels_mouseclick_invoke(bContext *C, wmOperator *op, const wmE
|
|||
|
||||
/* figure out which channel user clicked in */
|
||||
UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &x, &y);
|
||||
UI_view2d_listview_view_to_cell(ACHANNEL_NAMEWIDTH,
|
||||
ACHANNEL_STEP(&ac),
|
||||
UI_view2d_listview_view_to_cell(ANIM_UI_get_channel_name_width(),
|
||||
ANIM_UI_get_channel_step(),
|
||||
0,
|
||||
ACHANNEL_FIRST_TOP(&ac),
|
||||
ANIM_UI_get_first_channel_top(v2d),
|
||||
x,
|
||||
y,
|
||||
NULL,
|
||||
|
@ -3499,7 +3499,8 @@ static int animchannels_mouseclick_invoke(bContext *C, wmOperator *op, const wmE
|
|||
/* set notifier that things have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION | notifierFlags, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
return WM_operator_flag_only_pass_through_on_press(OPERATOR_FINISHED | OPERATOR_PASS_THROUGH,
|
||||
event);
|
||||
}
|
||||
|
||||
static void ANIM_OT_channels_click(wmOperatorType *ot)
|
||||
|
|
|
@ -92,26 +92,6 @@
|
|||
/* ************************************************************ */
|
||||
/* Blender Context <-> Animation Context mapping */
|
||||
|
||||
/* ----------- Private Stuff - General -------------------- */
|
||||
|
||||
/* Get vertical scaling factor (i.e. typically used for keyframe size) */
|
||||
static void animedit_get_yscale_factor(bAnimContext *ac)
|
||||
{
|
||||
bTheme *btheme = UI_GetTheme();
|
||||
|
||||
/* grab scale factor directly from action editor setting
|
||||
* NOTE: This theme setting doesn't have an ID, as it cannot be accessed normally
|
||||
* since it is a float, and the theme settings methods can only handle chars.
|
||||
*/
|
||||
ac->yscale_fac = btheme->space_action.keyframe_scale_fac;
|
||||
|
||||
/* clamp to avoid problems with uninitialized values... */
|
||||
if (ac->yscale_fac < 0.1f) {
|
||||
ac->yscale_fac = 1.0f;
|
||||
}
|
||||
// printf("yscale_fac = %f\n", ac->yscale_fac);
|
||||
}
|
||||
|
||||
/* ----------- Private Stuff - Action Editor ------------- */
|
||||
|
||||
/* Get shapekey data being edited (for Action Editor -> ShapeKey mode) */
|
||||
|
@ -408,9 +388,6 @@ bool ANIM_animdata_get_context(const bContext *C, bAnimContext *ac)
|
|||
ac->spacetype = (area) ? area->spacetype : 0;
|
||||
ac->regiontype = (region) ? region->regiontype : 0;
|
||||
|
||||
/* Initialize default y-scale factor. */
|
||||
animedit_get_yscale_factor(ac);
|
||||
|
||||
/* get data context info */
|
||||
/* XXX: if the below fails, try to grab this info from context instead...
|
||||
* (to allow for scripting). */
|
||||
|
|
|
@ -103,7 +103,7 @@ static void fmodifier_reorder(bContext *C, Panel *panel, int new_index)
|
|||
const FModifierTypeInfo *fmi = get_fmodifier_typeinfo(fcm->type);
|
||||
|
||||
/* Cycles modifier has to be the first, so make sure it's kept that way. */
|
||||
if (fmi->requires & FMI_REQUIRES_ORIGINAL_DATA) {
|
||||
if (fmi->requires_flag & FMI_REQUIRES_ORIGINAL_DATA) {
|
||||
WM_report(RPT_ERROR, "Modifier requires original data");
|
||||
return;
|
||||
}
|
||||
|
@ -113,7 +113,7 @@ static void fmodifier_reorder(bContext *C, Panel *panel, int new_index)
|
|||
/* Again, make sure we don't move a modifier before a cycles modifier. */
|
||||
FModifier *fcm_first = modifiers->first;
|
||||
const FModifierTypeInfo *fmi_first = get_fmodifier_typeinfo(fcm_first->type);
|
||||
if (fmi_first->requires & FMI_REQUIRES_ORIGINAL_DATA && new_index == 0) {
|
||||
if (fmi_first->requires_flag & FMI_REQUIRES_ORIGINAL_DATA && new_index == 0) {
|
||||
WM_report(RPT_ERROR, "Modifier requires original data");
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -25,8 +25,11 @@ struct AssetMetaData *ED_asset_handle_get_metadata(const struct AssetHandle *ass
|
|||
struct ID *ED_asset_handle_get_local_id(const struct AssetHandle *asset);
|
||||
ID_Type ED_asset_handle_get_id_type(const struct AssetHandle *asset);
|
||||
int ED_asset_handle_get_preview_icon_id(const struct AssetHandle *asset);
|
||||
void ED_asset_handle_get_full_library_path(const struct AssetHandle *asset,
|
||||
char r_full_lib_path[]);
|
||||
void ED_asset_handle_get_full_library_path(
|
||||
const struct AssetHandle *asset,
|
||||
/* `1090` for #FILE_MAX_LIBEXTRA,
|
||||
* rely on warnings to let us know if this gets out of sync. */
|
||||
char r_full_lib_path[1090]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -157,6 +157,19 @@ bool curves_poll(bContext *C)
|
|||
return curves_poll_impl(C, false, false, false);
|
||||
}
|
||||
|
||||
static bool editable_curves_point_domain_poll(bContext *C)
|
||||
{
|
||||
if (!curves::editable_curves_poll(C)) {
|
||||
return false;
|
||||
}
|
||||
const Curves *curves_id = static_cast<const Curves *>(CTX_data_active_object(C)->data);
|
||||
if (curves_id->selection_domain != ATTR_DOMAIN_POINT) {
|
||||
CTX_wm_operator_poll_msg_set(C, "Only available in point selection mode");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
using bke::CurvesGeometry;
|
||||
|
||||
namespace convert_to_particle_system {
|
||||
|
@ -931,19 +944,6 @@ static void CURVES_OT_select_random(wmOperatorType *ot)
|
|||
1.0f);
|
||||
}
|
||||
|
||||
static bool select_end_poll(bContext *C)
|
||||
{
|
||||
if (!curves::editable_curves_poll(C)) {
|
||||
return false;
|
||||
}
|
||||
const Curves *curves_id = static_cast<const Curves *>(CTX_data_active_object(C)->data);
|
||||
if (curves_id->selection_domain != ATTR_DOMAIN_POINT) {
|
||||
CTX_wm_operator_poll_msg_set(C, "Only available in point selection mode");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static int select_end_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
VectorSet<Curves *> unique_curves = curves::get_unique_editable_curves(*C);
|
||||
|
@ -952,7 +952,7 @@ static int select_end_exec(bContext *C, wmOperator *op)
|
|||
|
||||
for (Curves *curves_id : unique_curves) {
|
||||
CurvesGeometry &curves = curves_id->geometry.wrap();
|
||||
select_ends(curves, eAttrDomain(curves_id->selection_domain), amount, end_points);
|
||||
select_ends(curves, amount, end_points);
|
||||
|
||||
/* Use #ID_RECALC_GEOMETRY instead of #ID_RECALC_SELECT because it is handled as a generic
|
||||
* attribute for now. */
|
||||
|
@ -970,7 +970,7 @@ static void CURVES_OT_select_end(wmOperatorType *ot)
|
|||
ot->description = "Select end points of curves";
|
||||
|
||||
ot->exec = select_end_exec;
|
||||
ot->poll = select_end_poll;
|
||||
ot->poll = editable_curves_point_domain_poll;
|
||||
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
|
||||
|
@ -983,6 +983,33 @@ static void CURVES_OT_select_end(wmOperatorType *ot)
|
|||
ot->srna, "amount", 1, 0, INT32_MAX, "Amount", "Number of points to select", 0, INT32_MAX);
|
||||
}
|
||||
|
||||
static int select_linked_exec(bContext *C, wmOperator * /*op*/)
|
||||
{
|
||||
VectorSet<Curves *> unique_curves = get_unique_editable_curves(*C);
|
||||
for (Curves *curves_id : unique_curves) {
|
||||
CurvesGeometry &curves = curves_id->geometry.wrap();
|
||||
select_linked(curves);
|
||||
/* Use #ID_RECALC_GEOMETRY instead of #ID_RECALC_SELECT because it is handled as a generic
|
||||
* attribute for now. */
|
||||
DEG_id_tag_update(&curves_id->id, ID_RECALC_GEOMETRY);
|
||||
WM_event_add_notifier(C, NC_GEOM | ND_DATA, curves_id);
|
||||
}
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static void CURVES_OT_select_linked(wmOperatorType *ot)
|
||||
{
|
||||
ot->name = "Select Linked";
|
||||
ot->idname = __func__;
|
||||
ot->description = "Select all points in curves with any point selection";
|
||||
|
||||
ot->exec = select_linked_exec;
|
||||
ot->poll = editable_curves_point_domain_poll;
|
||||
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
namespace surface_set {
|
||||
|
||||
static bool surface_set_poll(bContext *C)
|
||||
|
@ -1078,6 +1105,7 @@ void ED_operatortypes_curves()
|
|||
WM_operatortype_append(CURVES_OT_select_all);
|
||||
WM_operatortype_append(CURVES_OT_select_random);
|
||||
WM_operatortype_append(CURVES_OT_select_end);
|
||||
WM_operatortype_append(CURVES_OT_select_linked);
|
||||
WM_operatortype_append(CURVES_OT_surface_set);
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,9 @@
|
|||
|
||||
#include "BLI_array_utils.hh"
|
||||
#include "BLI_index_mask_ops.hh"
|
||||
#include "BLI_lasso_2d.h"
|
||||
#include "BLI_rand.hh"
|
||||
#include "BLI_rect.h"
|
||||
|
||||
#include "BKE_attribute.hh"
|
||||
#include "BKE_crazyspace.hh"
|
||||
|
@ -163,6 +165,21 @@ bool has_anything_selected(const bke::CurvesGeometry &curves)
|
|||
return !selection || contains(selection, true);
|
||||
}
|
||||
|
||||
bool has_anything_selected(const GSpan selection)
|
||||
{
|
||||
if (selection.type().is<bool>()) {
|
||||
return selection.typed<bool>().contains(true);
|
||||
}
|
||||
else if (selection.type().is<float>()) {
|
||||
for (const float elem : selection.typed<float>()) {
|
||||
if (elem > 0.0f) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void invert_selection(MutableSpan<float> selection)
|
||||
{
|
||||
threading::parallel_for(selection.index_range(), 2048, [&](IndexRange range) {
|
||||
|
@ -202,14 +219,12 @@ void select_all(bke::CurvesGeometry &curves, const eAttrDomain selection_domain,
|
|||
}
|
||||
}
|
||||
|
||||
void select_ends(bke::CurvesGeometry &curves,
|
||||
const eAttrDomain selection_domain,
|
||||
int amount,
|
||||
bool end_points)
|
||||
void select_ends(bke::CurvesGeometry &curves, int amount, bool end_points)
|
||||
{
|
||||
const bool was_anything_selected = has_anything_selected(curves);
|
||||
const OffsetIndices points_by_curve = curves.points_by_curve();
|
||||
bke::GSpanAttributeWriter selection = ensure_selection_attribute(
|
||||
curves, selection_domain, CD_PROP_BOOL);
|
||||
curves, ATTR_DOMAIN_POINT, CD_PROP_BOOL);
|
||||
if (!was_anything_selected) {
|
||||
fill_selection_true(selection.span);
|
||||
}
|
||||
|
@ -222,7 +237,6 @@ void select_ends(bke::CurvesGeometry &curves,
|
|||
MutableSpan<T> selection_typed = selection.span.typed<T>();
|
||||
threading::parallel_for(curves.curves_range(), 256, [&](const IndexRange range) {
|
||||
for (const int curve_i : range) {
|
||||
const OffsetIndices points_by_curve = curves.points_by_curve();
|
||||
if (end_points) {
|
||||
selection_typed.slice(points_by_curve[curve_i].drop_back(amount)).fill(T(0));
|
||||
}
|
||||
|
@ -236,6 +250,23 @@ void select_ends(bke::CurvesGeometry &curves,
|
|||
selection.finish();
|
||||
}
|
||||
|
||||
void select_linked(bke::CurvesGeometry &curves)
|
||||
{
|
||||
const OffsetIndices points_by_curve = curves.points_by_curve();
|
||||
bke::GSpanAttributeWriter selection = ensure_selection_attribute(
|
||||
curves, ATTR_DOMAIN_POINT, CD_PROP_BOOL);
|
||||
|
||||
threading::parallel_for(curves.curves_range(), 256, [&](const IndexRange range) {
|
||||
for (const int curve_i : range) {
|
||||
GMutableSpan selection_curve = selection.span.slice(points_by_curve[curve_i]);
|
||||
if (has_anything_selected(selection_curve)) {
|
||||
fill_selection_true(selection_curve);
|
||||
}
|
||||
}
|
||||
});
|
||||
selection.finish();
|
||||
}
|
||||
|
||||
void select_random(bke::CurvesGeometry &curves,
|
||||
const eAttrDomain selection_domain,
|
||||
uint32_t random_seed,
|
||||
|
@ -285,6 +316,46 @@ void select_random(bke::CurvesGeometry &curves,
|
|||
selection.finish();
|
||||
}
|
||||
|
||||
static void apply_selection_operation_at_index(GMutableSpan selection,
|
||||
const int index,
|
||||
const eSelectOp sel_op)
|
||||
{
|
||||
if (selection.type().is<bool>()) {
|
||||
MutableSpan<bool> selection_typed = selection.typed<bool>();
|
||||
switch (sel_op) {
|
||||
case SEL_OP_ADD:
|
||||
case SEL_OP_SET:
|
||||
selection_typed[index] = true;
|
||||
break;
|
||||
case SEL_OP_SUB:
|
||||
selection_typed[index] = false;
|
||||
break;
|
||||
case SEL_OP_XOR:
|
||||
selection_typed[index] ^= selection_typed[index];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (selection.type().is<float>()) {
|
||||
MutableSpan<float> selection_typed = selection.typed<float>();
|
||||
switch (sel_op) {
|
||||
case SEL_OP_ADD:
|
||||
case SEL_OP_SET:
|
||||
selection_typed[index] = 1.0f;
|
||||
break;
|
||||
case SEL_OP_SUB:
|
||||
selection_typed[index] = 0.0f;
|
||||
break;
|
||||
case SEL_OP_XOR:
|
||||
selection_typed[index] = 1.0f - selection_typed[index];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper struct for `find_closest_point_to_screen_co`.
|
||||
*/
|
||||
|
@ -356,7 +427,7 @@ bool select_pick(const ViewContext &vc,
|
|||
bke::CurvesGeometry &curves,
|
||||
const eAttrDomain selection_domain,
|
||||
const SelectPick_Params ¶ms,
|
||||
const int2 mval)
|
||||
const int2 coord)
|
||||
{
|
||||
FindClosestPointData closest_point;
|
||||
bool found = find_closest_point_to_screen_co(*vc.depsgraph,
|
||||
|
@ -364,7 +435,7 @@ bool select_pick(const ViewContext &vc,
|
|||
vc.rv3d,
|
||||
*vc.obact,
|
||||
curves,
|
||||
float2(mval),
|
||||
float2(coord),
|
||||
ED_view3d_select_dist_px(),
|
||||
closest_point);
|
||||
|
||||
|
@ -392,33 +463,188 @@ bool select_pick(const ViewContext &vc,
|
|||
elem_index = std::distance(curves.offsets().begin(), it) - 1;
|
||||
}
|
||||
|
||||
selection.span.type().to_static_type_tag<bool, float>([&](auto type_tag) {
|
||||
using T = typename decltype(type_tag)::type;
|
||||
if constexpr (std::is_void_v<T>) {
|
||||
BLI_assert_unreachable();
|
||||
}
|
||||
else {
|
||||
MutableSpan<T> selection_typed = selection.span.typed<T>();
|
||||
switch (params.sel_op) {
|
||||
case SEL_OP_ADD:
|
||||
case SEL_OP_SET:
|
||||
selection_typed[elem_index] = T(1);
|
||||
break;
|
||||
case SEL_OP_SUB:
|
||||
selection_typed[elem_index] = T(0);
|
||||
break;
|
||||
case SEL_OP_XOR:
|
||||
selection_typed[elem_index] = T(1 - selection_typed[elem_index]);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
apply_selection_operation_at_index(selection.span, elem_index, params.sel_op);
|
||||
selection.finish();
|
||||
}
|
||||
|
||||
return changed || found;
|
||||
}
|
||||
|
||||
bool select_box(const ViewContext &vc,
|
||||
bke::CurvesGeometry &curves,
|
||||
const eAttrDomain selection_domain,
|
||||
const rcti &rect,
|
||||
const eSelectOp sel_op)
|
||||
{
|
||||
bke::GSpanAttributeWriter selection = ensure_selection_attribute(
|
||||
curves, selection_domain, CD_PROP_BOOL);
|
||||
|
||||
bool changed = false;
|
||||
if (sel_op == SEL_OP_SET) {
|
||||
fill_selection_false(selection.span);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
float4x4 projection;
|
||||
ED_view3d_ob_project_mat_get(vc.rv3d, vc.obact, projection.ptr());
|
||||
|
||||
const bke::crazyspace::GeometryDeformation deformation =
|
||||
bke::crazyspace::get_evaluated_curves_deformation(*vc.depsgraph, *vc.obact);
|
||||
const OffsetIndices points_by_curve = curves.points_by_curve();
|
||||
if (selection_domain == ATTR_DOMAIN_POINT) {
|
||||
threading::parallel_for(curves.points_range(), 1024, [&](const IndexRange point_range) {
|
||||
for (const int point_i : point_range) {
|
||||
float2 pos_proj;
|
||||
ED_view3d_project_float_v2_m4(
|
||||
vc.region, deformation.positions[point_i], pos_proj, projection.ptr());
|
||||
if (BLI_rcti_isect_pt_v(&rect, int2(pos_proj))) {
|
||||
apply_selection_operation_at_index(selection.span, point_i, sel_op);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
else if (selection_domain == ATTR_DOMAIN_CURVE) {
|
||||
threading::parallel_for(curves.curves_range(), 512, [&](const IndexRange curves_range) {
|
||||
for (const int curve_i : curves_range) {
|
||||
for (const int point_i : points_by_curve[curve_i]) {
|
||||
float2 pos_proj;
|
||||
ED_view3d_project_float_v2_m4(
|
||||
vc.region, deformation.positions[point_i], pos_proj, projection.ptr());
|
||||
if (BLI_rcti_isect_pt_v(&rect, int2(pos_proj))) {
|
||||
apply_selection_operation_at_index(selection.span, curve_i, sel_op);
|
||||
changed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
selection.finish();
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
bool select_lasso(const ViewContext &vc,
|
||||
bke::CurvesGeometry &curves,
|
||||
const eAttrDomain selection_domain,
|
||||
const Span<int2> coords,
|
||||
const eSelectOp sel_op)
|
||||
{
|
||||
rcti bbox;
|
||||
const int(*coord_array)[2] = reinterpret_cast<const int(*)[2]>(coords.data());
|
||||
BLI_lasso_boundbox(&bbox, coord_array, coords.size());
|
||||
|
||||
bke::GSpanAttributeWriter selection = ensure_selection_attribute(
|
||||
curves, selection_domain, CD_PROP_BOOL);
|
||||
|
||||
bool changed = false;
|
||||
if (sel_op == SEL_OP_SET) {
|
||||
fill_selection_false(selection.span);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
float4x4 projection;
|
||||
ED_view3d_ob_project_mat_get(vc.rv3d, vc.obact, projection.ptr());
|
||||
|
||||
const bke::crazyspace::GeometryDeformation deformation =
|
||||
bke::crazyspace::get_evaluated_curves_deformation(*vc.depsgraph, *vc.obact);
|
||||
const OffsetIndices points_by_curve = curves.points_by_curve();
|
||||
if (selection_domain == ATTR_DOMAIN_POINT) {
|
||||
threading::parallel_for(curves.points_range(), 1024, [&](const IndexRange point_range) {
|
||||
for (const int point_i : point_range) {
|
||||
float2 pos_proj;
|
||||
ED_view3d_project_float_v2_m4(
|
||||
vc.region, deformation.positions[point_i], pos_proj, projection.ptr());
|
||||
/* Check the lasso bounding box first as an optimization. */
|
||||
if (BLI_rcti_isect_pt_v(&bbox, int2(pos_proj)) &&
|
||||
BLI_lasso_is_point_inside(
|
||||
coord_array, coords.size(), int(pos_proj.x), int(pos_proj.y), IS_CLIPPED)) {
|
||||
apply_selection_operation_at_index(selection.span, point_i, sel_op);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
else if (selection_domain == ATTR_DOMAIN_CURVE) {
|
||||
threading::parallel_for(curves.curves_range(), 512, [&](const IndexRange curves_range) {
|
||||
for (const int curve_i : curves_range) {
|
||||
for (const int point_i : points_by_curve[curve_i]) {
|
||||
float2 pos_proj;
|
||||
ED_view3d_project_float_v2_m4(
|
||||
vc.region, deformation.positions[point_i], pos_proj, projection.ptr());
|
||||
/* Check the lasso bounding box first as an optimization. */
|
||||
if (BLI_rcti_isect_pt_v(&bbox, int2(pos_proj)) &&
|
||||
BLI_lasso_is_point_inside(
|
||||
coord_array, coords.size(), int(pos_proj.x), int(pos_proj.y), IS_CLIPPED)) {
|
||||
apply_selection_operation_at_index(selection.span, curve_i, sel_op);
|
||||
changed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
selection.finish();
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
bool select_circle(const ViewContext &vc,
|
||||
bke::CurvesGeometry &curves,
|
||||
const eAttrDomain selection_domain,
|
||||
const int2 coord,
|
||||
const float radius,
|
||||
const eSelectOp sel_op)
|
||||
{
|
||||
const float radius_sq = pow2f(radius);
|
||||
bke::GSpanAttributeWriter selection = ensure_selection_attribute(
|
||||
curves, selection_domain, CD_PROP_BOOL);
|
||||
|
||||
bool changed = false;
|
||||
if (sel_op == SEL_OP_SET) {
|
||||
fill_selection_false(selection.span);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
float4x4 projection;
|
||||
ED_view3d_ob_project_mat_get(vc.rv3d, vc.obact, projection.ptr());
|
||||
|
||||
const bke::crazyspace::GeometryDeformation deformation =
|
||||
bke::crazyspace::get_evaluated_curves_deformation(*vc.depsgraph, *vc.obact);
|
||||
const OffsetIndices points_by_curve = curves.points_by_curve();
|
||||
if (selection_domain == ATTR_DOMAIN_POINT) {
|
||||
threading::parallel_for(curves.points_range(), 1024, [&](const IndexRange point_range) {
|
||||
for (const int point_i : point_range) {
|
||||
float2 pos_proj;
|
||||
ED_view3d_project_float_v2_m4(
|
||||
vc.region, deformation.positions[point_i], pos_proj, projection.ptr());
|
||||
if (math::distance_squared(pos_proj, float2(coord)) <= radius_sq) {
|
||||
apply_selection_operation_at_index(selection.span, point_i, sel_op);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
else if (selection_domain == ATTR_DOMAIN_CURVE) {
|
||||
threading::parallel_for(curves.curves_range(), 512, [&](const IndexRange curves_range) {
|
||||
for (const int curve_i : curves_range) {
|
||||
for (const int point_i : points_by_curve[curve_i]) {
|
||||
float2 pos_proj;
|
||||
ED_view3d_project_float_v2_m4(
|
||||
vc.region, deformation.positions[point_i], pos_proj, projection.ptr());
|
||||
if (math::distance_squared(pos_proj, float2(coord)) <= radius_sq) {
|
||||
apply_selection_operation_at_index(selection.span, curve_i, sel_op);
|
||||
changed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
selection.finish();
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
} // namespace blender::ed::curves
|
||||
|
|
|
@ -735,7 +735,7 @@ static void gpencil_create_extensions_radius(tGPDfill *tgpf)
|
|||
float tan2[3];
|
||||
float d1;
|
||||
float d2;
|
||||
float total_length = 0.f;
|
||||
float total_length = 0.0f;
|
||||
for (int i = 1; i < gps->totpoints; i++) {
|
||||
if (i > 1) {
|
||||
copy_v3_v3(tan1, tan2);
|
||||
|
@ -751,7 +751,7 @@ static void gpencil_create_extensions_radius(tGPDfill *tgpf)
|
|||
sub_v3_v3v3(curvature, tan2, tan1);
|
||||
float k = normalize_v3(curvature);
|
||||
k /= min_ff(d1, d2);
|
||||
float radius = 1.f / k;
|
||||
float radius = 1.0f / k;
|
||||
/*
|
||||
* The smaller the radius of curvature, the sharper the corner.
|
||||
* The thicker the line, the larger the radius of curvature it
|
||||
|
|
|
@ -3327,6 +3327,14 @@ void ED_gpencil_layer_merge(bGPdata *gpd,
|
|||
gpf_dst->key_type = gpf_src->key_type;
|
||||
BLI_ghash_insert(gh_frames_dst, POINTER_FROM_INT(gpf_src->framenum), gpf_dst);
|
||||
}
|
||||
|
||||
/* Copy current source frame to further frames
|
||||
* that are keyframes in destination layer and not in source layer
|
||||
* to keep the image equals. */
|
||||
if (gpf_dst->next && (!gpf_src->next || (gpf_dst->next->framenum < gpf_src->next->framenum))) {
|
||||
gpf_dst = gpf_dst->next;
|
||||
BKE_gpencil_layer_frame_get(gpl_src, gpf_dst->framenum, GP_GETFRAME_ADD_COPY);
|
||||
}
|
||||
}
|
||||
|
||||
/* Read all frames from merge layer and add strokes. */
|
||||
|
|
|
@ -94,8 +94,6 @@ typedef struct bAnimContext {
|
|||
/** pointer to current reports list */
|
||||
struct ReportList *reports;
|
||||
|
||||
/** Scale factor for height of channels (i.e. based on the size of keyframes). */
|
||||
float yscale_fac;
|
||||
} bAnimContext;
|
||||
|
||||
/* Main Data container types */
|
||||
|
@ -430,28 +428,6 @@ ENUM_OPERATORS(eAnimFilter_Flags, ANIMFILTER_TMP_IGNORE_ONLYSEL);
|
|||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Channel Defines
|
||||
* \{ */
|
||||
|
||||
/** Channel heights. */
|
||||
#define ACHANNEL_FIRST_TOP(ac) \
|
||||
(UI_view2d_scale_get_y(&(ac)->region->v2d) * -UI_TIME_SCRUB_MARGIN_Y - ACHANNEL_SKIP)
|
||||
#define ACHANNEL_HEIGHT(ac) (0.8f * (ac)->yscale_fac * U.widget_unit)
|
||||
#define ACHANNEL_SKIP (0.1f * U.widget_unit)
|
||||
#define ACHANNEL_STEP(ac) (ACHANNEL_HEIGHT(ac) + ACHANNEL_SKIP)
|
||||
/** Additional offset to give some room at the end. */
|
||||
#define ACHANNEL_TOT_HEIGHT(ac, item_amount) \
|
||||
(-ACHANNEL_FIRST_TOP(ac) + ACHANNEL_STEP(ac) * (item_amount + 1))
|
||||
|
||||
/** Channel widths. */
|
||||
#define ACHANNEL_NAMEWIDTH (10 * U.widget_unit)
|
||||
|
||||
/** Channel toggle-buttons. */
|
||||
#define ACHANNEL_BUTTON_WIDTH (0.8f * U.widget_unit)
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name NLA Channel Defines
|
||||
* \{ */
|
||||
|
@ -612,6 +588,20 @@ typedef struct bAnimChannelType {
|
|||
void *(*setting_ptr)(bAnimListElem *ale, eAnimChannel_Settings setting, short *type);
|
||||
} bAnimChannelType;
|
||||
|
||||
/** \} */
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Channel dimensions API
|
||||
* \{ */
|
||||
|
||||
float ANIM_UI_get_keyframe_scale_factor(void);
|
||||
float ANIM_UI_get_channel_height(void);
|
||||
float ANIM_UI_get_channel_skip(void);
|
||||
float ANIM_UI_get_first_channel_top(View2D *v2d);
|
||||
float ANIM_UI_get_channel_step(void);
|
||||
float ANIM_UI_get_channels_total_height(View2D *v2d, int item_count);
|
||||
float ANIM_UI_get_channel_name_width(void);
|
||||
float ANIM_UI_get_channel_button_width(void);
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
|
|
@ -11,6 +11,7 @@ struct Curves;
|
|||
struct UndoType;
|
||||
struct SelectPick_Params;
|
||||
struct ViewContext;
|
||||
struct rcti;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -46,6 +47,8 @@ float (*ED_curves_point_normals_array_create(const struct Curves *curves_id))[3]
|
|||
|
||||
# include "BKE_curves.hh"
|
||||
|
||||
# include "ED_select_utils.h"
|
||||
|
||||
namespace blender::ed::curves {
|
||||
|
||||
bool object_has_editable_curves(const Main &bmain, const Object &object);
|
||||
|
@ -86,6 +89,11 @@ void fill_selection_true(GMutableSpan span);
|
|||
*/
|
||||
bool has_anything_selected(const bke::CurvesGeometry &curves);
|
||||
|
||||
/**
|
||||
* Return true if any element in the span is selected, on either domain with either type.
|
||||
*/
|
||||
bool has_anything_selected(GSpan selection);
|
||||
|
||||
/**
|
||||
* Find curves that have any point selected (a selection factor greater than zero),
|
||||
* or curves that have their own selection factor greater than zero.
|
||||
|
@ -120,10 +128,12 @@ void select_all(bke::CurvesGeometry &curves, const eAttrDomain selection_domain,
|
|||
* \param amount: The amount of points to select from the front or back.
|
||||
* \param end_points: If true, select the last point(s), if false, select the first point(s).
|
||||
*/
|
||||
void select_ends(bke::CurvesGeometry &curves,
|
||||
const eAttrDomain selection_domain,
|
||||
int amount,
|
||||
bool end_points);
|
||||
void select_ends(bke::CurvesGeometry &curves, int amount, bool end_points);
|
||||
|
||||
/**
|
||||
* Select the points of all curves that have at least one point selected.
|
||||
*/
|
||||
void select_linked(bke::CurvesGeometry &curves);
|
||||
|
||||
/**
|
||||
* Select random points or curves.
|
||||
|
@ -138,14 +148,41 @@ void select_random(bke::CurvesGeometry &curves,
|
|||
float probability);
|
||||
|
||||
/**
|
||||
* Select point or curve under the cursor.
|
||||
* Select point or curve at a (screen-space) point.
|
||||
*/
|
||||
bool select_pick(const ViewContext &vc,
|
||||
bke::CurvesGeometry &curves,
|
||||
const eAttrDomain selection_domain,
|
||||
const SelectPick_Params ¶ms,
|
||||
const int2 mval);
|
||||
const int2 coord);
|
||||
|
||||
/**
|
||||
* Select points or curves in a (screen-space) rectangle.
|
||||
*/
|
||||
bool select_box(const ViewContext &vc,
|
||||
bke::CurvesGeometry &curves,
|
||||
const eAttrDomain selection_domain,
|
||||
const rcti &rect,
|
||||
const eSelectOp sel_op);
|
||||
|
||||
/**
|
||||
* Select points or curves in a (screen-space) poly shape.
|
||||
*/
|
||||
bool select_lasso(const ViewContext &vc,
|
||||
bke::CurvesGeometry &curves,
|
||||
eAttrDomain selection_domain,
|
||||
Span<int2> coords,
|
||||
eSelectOp sel_op);
|
||||
|
||||
/**
|
||||
* Select points or curves in a (screen-space) circle.
|
||||
*/
|
||||
bool select_circle(const ViewContext &vc,
|
||||
bke::CurvesGeometry &curves,
|
||||
eAttrDomain selection_domain,
|
||||
int2 coord,
|
||||
float radius,
|
||||
eSelectOp sel_op);
|
||||
/** \} */
|
||||
|
||||
} // namespace blender::ed::curves
|
||||
|
|
|
@ -241,6 +241,9 @@ void ED_object_parent(struct Object *ob, struct Object *parent, int type, const
|
|||
char *ED_object_ot_drop_named_material_tooltip(struct bContext *C,
|
||||
const char *name,
|
||||
const int mval[2]);
|
||||
char *ED_object_ot_drop_geometry_nodes_tooltip(struct bContext *C,
|
||||
struct PointerRNA *properties,
|
||||
const int mval[2]);
|
||||
|
||||
/* bitflags for enter/exit editmode */
|
||||
enum {
|
||||
|
@ -475,7 +478,7 @@ void ED_object_constraint_copy_for_pose(struct Main *bmain,
|
|||
struct bPoseChannel *pchan,
|
||||
struct bConstraint *con);
|
||||
|
||||
/* object_modes.c */
|
||||
/* object_modes.cc */
|
||||
|
||||
/**
|
||||
* Checks the mode to be set is compatible with the object
|
||||
|
|
|
@ -24,7 +24,7 @@ struct wmKeyConfig;
|
|||
struct wmOperator;
|
||||
typedef struct PaintTileMap PaintTileMap;
|
||||
|
||||
/* paint_ops.c */
|
||||
/* paint_ops.cc */
|
||||
|
||||
void ED_operatortypes_paint(void);
|
||||
void ED_operatormacros_paint(void);
|
||||
|
|
|
@ -19,7 +19,13 @@ struct bContext;
|
|||
void ED_sequencer_select_sequence_single(struct Scene *scene,
|
||||
struct Sequence *seq,
|
||||
bool deselect_all);
|
||||
void ED_sequencer_deselect_all(struct Scene *scene);
|
||||
/**
|
||||
* Iterates over a scene's sequences and deselects all of them.
|
||||
*
|
||||
* \param scene: scene containing sequences to be deselected.
|
||||
* \return true if any sequences were deselected; false otherwise.
|
||||
*/
|
||||
bool ED_sequencer_deselect_all(struct Scene *scene);
|
||||
|
||||
bool ED_space_sequencer_maskedit_mask_poll(struct bContext *C);
|
||||
bool ED_space_sequencer_check_show_maskedit(struct SpaceSeq *sseq, struct Scene *scene);
|
||||
|
|
|
@ -18,7 +18,7 @@ struct IDRemapper;
|
|||
struct Main;
|
||||
struct bContext;
|
||||
|
||||
/* ed_util.c */
|
||||
/* ed_util.cc */
|
||||
|
||||
void ED_editors_init_for_undo(struct Main *bmain);
|
||||
void ED_editors_init(struct bContext *C);
|
||||
|
|
|
@ -1630,7 +1630,7 @@ static void icon_draw_cache_texture_flush_ex(GPUTexture *texture,
|
|||
|
||||
GPUBatch *quad = GPU_batch_preset_quad();
|
||||
GPU_batch_set_shader(quad, shader);
|
||||
GPU_batch_draw_instanced(quad, texture_draw_calls->calls);
|
||||
GPU_batch_draw_instance_range(quad, 0, texture_draw_calls->calls);
|
||||
|
||||
GPU_texture_unbind(texture);
|
||||
GPU_uniformbuf_unbind(ubo);
|
||||
|
|
|
@ -1157,7 +1157,7 @@ void UI_widgetbase_draw_cache_flush()
|
|||
MAX_WIDGET_PARAMETERS * MAX_WIDGET_BASE_BATCH,
|
||||
(float(*)[4])g_widget_base_batch.params);
|
||||
GPU_batch_uniform_3fv(batch, "checkerColorAndSize", checker_params);
|
||||
GPU_batch_draw_instanced(batch, g_widget_base_batch.count);
|
||||
GPU_batch_draw_instance_range(batch, 0, g_widget_base_batch.count);
|
||||
}
|
||||
g_widget_base_batch.count = 0;
|
||||
}
|
||||
|
|
|
@ -1260,11 +1260,6 @@ static void mesh_add_edges(Mesh *mesh, int len)
|
|||
|
||||
mesh->totedge = totedge;
|
||||
|
||||
MutableSpan<MEdge> edges = mesh->edges_for_write();
|
||||
for (MEdge &edge : edges.take_back(len)) {
|
||||
edge.flag = ME_EDGEDRAW;
|
||||
}
|
||||
|
||||
bke::MutableAttributeAccessor attributes = mesh->attributes_for_write();
|
||||
bke::SpanAttributeWriter<bool> select_edge = attributes.lookup_or_add_for_write_span<bool>(
|
||||
".select_edge", ATTR_DOMAIN_EDGE);
|
||||
|
|
|
@ -44,7 +44,7 @@ set(SRC
|
|||
object_facemap_ops.c
|
||||
object_gpencil_modifier.c
|
||||
object_hook.c
|
||||
object_modes.c
|
||||
object_modes.cc
|
||||
object_modifier.cc
|
||||
object_ops.c
|
||||
object_random.c
|
||||
|
|
|
@ -3154,8 +3154,6 @@ static int object_convert_exec(bContext *C, wmOperator *op)
|
|||
Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
|
||||
Mesh *me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_eval, &CD_MASK_MESH);
|
||||
me_eval = BKE_mesh_copy_for_eval(me_eval, false);
|
||||
/* Full (edge-angle based) draw calculation should ideally be performed. */
|
||||
BKE_mesh_edges_set_draw_render(me_eval);
|
||||
BKE_object_material_from_eval_data(bmain, newob, &me_eval->id);
|
||||
Mesh *new_mesh = (Mesh *)newob->data;
|
||||
BKE_mesh_nomain_to_mesh(me_eval, new_mesh, newob);
|
||||
|
|
|
@ -62,6 +62,11 @@ void OBJECT_OT_clear_override_library(struct wmOperatorType *ot);
|
|||
* Assigns to object under cursor, only first material slot.
|
||||
*/
|
||||
void OBJECT_OT_drop_named_material(struct wmOperatorType *ot);
|
||||
/**
|
||||
* Used for drop-box.
|
||||
* Assigns to object under cursor, creates a new geometry nodes modifier.
|
||||
*/
|
||||
void OBJECT_OT_drop_geometry_nodes(struct wmOperatorType *ot);
|
||||
/**
|
||||
* \note Only for empty-image objects, this operator is needed
|
||||
*/
|
||||
|
|
|
@ -97,7 +97,7 @@ static const char *object_mode_op_string(eObjectMode mode)
|
|||
if (mode == OB_MODE_SCULPT_CURVES) {
|
||||
return "CURVES_OT_sculptmode_toggle";
|
||||
}
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool ED_object_mode_compat_test(const Object *ob, eObjectMode mode)
|
||||
|
@ -160,9 +160,9 @@ bool ED_object_mode_compat_set(bContext *C, Object *ob, eObjectMode mode, Report
|
|||
{
|
||||
bool ok;
|
||||
if (!ELEM(ob->mode, mode, OB_MODE_OBJECT)) {
|
||||
const char *opstring = object_mode_op_string(ob->mode);
|
||||
const char *opstring = object_mode_op_string(eObjectMode(ob->mode));
|
||||
|
||||
WM_operator_name_call(C, opstring, WM_OP_EXEC_REGION_WIN, NULL, NULL);
|
||||
WM_operator_name_call(C, opstring, WM_OP_EXEC_REGION_WIN, nullptr, nullptr);
|
||||
ok = ELEM(ob->mode, mode, OB_MODE_OBJECT);
|
||||
if (!ok) {
|
||||
wmOperatorType *ot = WM_operatortype_find(opstring, false);
|
||||
|
@ -194,7 +194,7 @@ bool ED_object_mode_set_ex(bContext *C, eObjectMode mode, bool use_undo, ReportL
|
|||
|
||||
BKE_view_layer_synced_ensure(scene, view_layer);
|
||||
Object *ob = BKE_view_layer_active_object_get(view_layer);
|
||||
if (ob == NULL) {
|
||||
if (ob == nullptr) {
|
||||
return (mode == OB_MODE_OBJECT);
|
||||
}
|
||||
|
||||
|
@ -210,13 +210,14 @@ bool ED_object_mode_set_ex(bContext *C, eObjectMode mode, bool use_undo, ReportL
|
|||
return false;
|
||||
}
|
||||
|
||||
const char *opstring = object_mode_op_string((mode == OB_MODE_OBJECT) ? ob->mode : mode);
|
||||
const char *opstring = object_mode_op_string((mode == OB_MODE_OBJECT) ? eObjectMode(ob->mode) :
|
||||
mode);
|
||||
wmOperatorType *ot = WM_operatortype_find(opstring, false);
|
||||
|
||||
if (!use_undo) {
|
||||
wm->op_undo_depth++;
|
||||
}
|
||||
WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_REGION_WIN, NULL, NULL);
|
||||
WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_REGION_WIN, nullptr, nullptr);
|
||||
if (!use_undo) {
|
||||
wm->op_undo_depth--;
|
||||
}
|
||||
|
@ -232,20 +233,17 @@ bool ED_object_mode_set_ex(bContext *C, eObjectMode mode, bool use_undo, ReportL
|
|||
bool ED_object_mode_set(bContext *C, eObjectMode mode)
|
||||
{
|
||||
/* Don't do undo push by default, since this may be called by lower level code. */
|
||||
return ED_object_mode_set_ex(C, mode, true, NULL);
|
||||
return ED_object_mode_set_ex(C, mode, true, nullptr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use for changing works-paces or changing active object.
|
||||
* Caller can check #OB_MODE_ALL_MODE_DATA to test if this needs to be run.
|
||||
*/
|
||||
static bool ed_object_mode_generic_exit_ex(struct Main *bmain,
|
||||
struct Depsgraph *depsgraph,
|
||||
struct Scene *scene,
|
||||
struct Object *ob,
|
||||
bool only_test)
|
||||
static bool ed_object_mode_generic_exit_ex(
|
||||
Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *ob, bool only_test)
|
||||
{
|
||||
BLI_assert((bmain == NULL) == only_test);
|
||||
BLI_assert((bmain == nullptr) == only_test);
|
||||
if (ob->mode & OB_MODE_EDIT) {
|
||||
if (BKE_object_is_in_editmode(ob)) {
|
||||
if (only_test) {
|
||||
|
@ -279,7 +277,7 @@ static bool ed_object_mode_generic_exit_ex(struct Main *bmain,
|
|||
}
|
||||
}
|
||||
else if (ob->mode & OB_MODE_POSE) {
|
||||
if (ob->pose != NULL) {
|
||||
if (ob->pose != nullptr) {
|
||||
if (only_test) {
|
||||
return true;
|
||||
}
|
||||
|
@ -332,7 +330,7 @@ static void ed_object_posemode_set_for_weight_paint_ex(bContext *C,
|
|||
const Scene *scene = CTX_data_scene(C);
|
||||
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||
|
||||
if (ob_arm != NULL) {
|
||||
if (ob_arm != nullptr) {
|
||||
BKE_view_layer_synced_ensure(scene, view_layer);
|
||||
const Base *base_arm = BKE_view_layer_base_find(view_layer, ob_arm);
|
||||
if (base_arm && BASE_VISIBLE(v3d, base_arm)) {
|
||||
|
@ -387,17 +385,14 @@ void ED_object_posemode_set_for_weight_paint(bContext *C,
|
|||
}
|
||||
}
|
||||
|
||||
void ED_object_mode_generic_exit(struct Main *bmain,
|
||||
struct Depsgraph *depsgraph,
|
||||
struct Scene *scene,
|
||||
struct Object *ob)
|
||||
void ED_object_mode_generic_exit(Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *ob)
|
||||
{
|
||||
ed_object_mode_generic_exit_ex(bmain, depsgraph, scene, ob, false);
|
||||
}
|
||||
|
||||
bool ED_object_mode_generic_has_data(struct Depsgraph *depsgraph, const struct Object *ob)
|
||||
bool ED_object_mode_generic_has_data(Depsgraph *depsgraph, const Object *ob)
|
||||
{
|
||||
return ed_object_mode_generic_exit_ex(NULL, depsgraph, NULL, (Object *)ob, true);
|
||||
return ed_object_mode_generic_exit_ex(nullptr, depsgraph, nullptr, (Object *)ob, true);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
@ -425,7 +420,7 @@ static void object_transfer_mode_reposition_view_pivot(bContext *C, const int mv
|
|||
Scene *scene = CTX_data_scene(C);
|
||||
|
||||
float global_loc[3];
|
||||
if (!ED_view3d_autodist_simple(region, mval, global_loc, 0, NULL)) {
|
||||
if (!ED_view3d_autodist_simple(region, mval, global_loc, 0, nullptr)) {
|
||||
return;
|
||||
}
|
||||
UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
|
||||
|
@ -446,7 +441,7 @@ static bool object_transfer_mode_to_base(bContext *C, wmOperator *op, Base *base
|
|||
Scene *scene = CTX_data_scene(C);
|
||||
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||
|
||||
if (base_dst == NULL) {
|
||||
if (base_dst == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -675,7 +675,6 @@ bool ED_object_modifier_convert_psys_to_mesh(ReportList * /*reports*/,
|
|||
if (k) {
|
||||
medge->v1 = cvert - 1;
|
||||
medge->v2 = cvert;
|
||||
medge->flag = ME_EDGEDRAW;
|
||||
medge++;
|
||||
}
|
||||
else {
|
||||
|
@ -694,7 +693,6 @@ bool ED_object_modifier_convert_psys_to_mesh(ReportList * /*reports*/,
|
|||
if (k) {
|
||||
medge->v1 = cvert - 1;
|
||||
medge->v2 = cvert;
|
||||
medge->flag = ME_EDGEDRAW;
|
||||
medge++;
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -262,6 +262,7 @@ void ED_operatortypes_object(void)
|
|||
WM_operatortype_append(OBJECT_OT_bake_image);
|
||||
WM_operatortype_append(OBJECT_OT_bake);
|
||||
WM_operatortype_append(OBJECT_OT_drop_named_material);
|
||||
WM_operatortype_append(OBJECT_OT_drop_geometry_nodes);
|
||||
WM_operatortype_append(OBJECT_OT_unlink_data);
|
||||
WM_operatortype_append(OBJECT_OT_laplaciandeform_bind);
|
||||
|
||||
|
|
|
@ -99,6 +99,8 @@
|
|||
#include "ED_screen.h"
|
||||
#include "ED_view3d.h"
|
||||
|
||||
#include "MOD_nodes.h"
|
||||
|
||||
#include "object_intern.h"
|
||||
|
||||
/* ------------------------------------------------------------------- */
|
||||
|
@ -2867,6 +2869,119 @@ void OBJECT_OT_drop_named_material(wmOperatorType *ot)
|
|||
|
||||
/** \} */
|
||||
|
||||
/* ------------------------------------------------------------------- */
|
||||
/** \name Drop Geometry Nodes on Object Operator
|
||||
* \{ */
|
||||
|
||||
char *ED_object_ot_drop_geometry_nodes_tooltip(bContext *C,
|
||||
PointerRNA *properties,
|
||||
const int mval[2])
|
||||
{
|
||||
const Object *ob = ED_view3d_give_object_under_cursor(C, mval);
|
||||
if (ob == NULL) {
|
||||
return BLI_strdup("");
|
||||
}
|
||||
|
||||
const uint32_t session_uuid = RNA_int_get(properties, "session_uuid");
|
||||
const ID *id = BKE_libblock_find_session_uuid(CTX_data_main(C), ID_NT, session_uuid);
|
||||
if (!id) {
|
||||
return BLI_strdup("");
|
||||
}
|
||||
|
||||
const char *tooltip = TIP_("Add modifier with node group \"%s\" on object \"%s\"");
|
||||
return BLI_sprintfN(tooltip, id->name, ob->id.name);
|
||||
}
|
||||
|
||||
static bool check_geometry_node_group_sockets(wmOperator *op, const bNodeTree *tree)
|
||||
{
|
||||
const bNodeSocket *first_input = (const bNodeSocket *)tree->inputs.first;
|
||||
if (!first_input) {
|
||||
BKE_report(op->reports, RPT_ERROR, "The node group must have a geometry input socket");
|
||||
return false;
|
||||
}
|
||||
if (first_input->type != SOCK_GEOMETRY) {
|
||||
BKE_report(op->reports, RPT_ERROR, "The first input must be a geometry socket");
|
||||
return false;
|
||||
}
|
||||
const bNodeSocket *first_output = (const bNodeSocket *)tree->outputs.first;
|
||||
if (!first_output) {
|
||||
BKE_report(op->reports, RPT_ERROR, "The node group must have a geometry output socket");
|
||||
return false;
|
||||
}
|
||||
if (first_output->type != SOCK_GEOMETRY) {
|
||||
BKE_report(op->reports, RPT_ERROR, "The first output must be a geometry socket");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static int drop_geometry_nodes_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
{
|
||||
Object *ob = ED_view3d_give_object_under_cursor(C, event->mval);
|
||||
if (!ob) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
Main *bmain = CTX_data_main(C);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
|
||||
const uint32_t uuid = RNA_int_get(op->ptr, "session_uuid");
|
||||
bNodeTree *node_tree = (bNodeTree *)BKE_libblock_find_session_uuid(bmain, ID_NT, uuid);
|
||||
if (!node_tree) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
if (node_tree->type != NTREE_GEOMETRY) {
|
||||
BKE_report(op->reports, RPT_ERROR, "Node group must be a geometry node tree");
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
if (!check_geometry_node_group_sockets(op, node_tree)) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
NodesModifierData *nmd = (NodesModifierData *)ED_object_modifier_add(
|
||||
op->reports, bmain, scene, ob, node_tree->id.name + 2, eModifierType_Nodes);
|
||||
if (!nmd) {
|
||||
BKE_report(op->reports, RPT_ERROR, "Could not add geometry nodes modifier");
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
nmd->node_group = node_tree;
|
||||
id_us_plus(&node_tree->id);
|
||||
MOD_nodes_update_interface(ob, nmd);
|
||||
|
||||
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
|
||||
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
void OBJECT_OT_drop_geometry_nodes(wmOperatorType *ot)
|
||||
{
|
||||
ot->name = "Drop Geometry Node Group on Object";
|
||||
ot->idname = "OBJECT_OT_drop_geometry_nodes";
|
||||
|
||||
ot->invoke = drop_geometry_nodes_invoke;
|
||||
ot->poll = ED_operator_view3d_active;
|
||||
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
|
||||
|
||||
PropertyRNA *prop = RNA_def_int(ot->srna,
|
||||
"session_uuid",
|
||||
0,
|
||||
INT32_MIN,
|
||||
INT32_MAX,
|
||||
"Session UUID",
|
||||
"Session UUID of the geometry node group being dropped",
|
||||
INT32_MIN,
|
||||
INT32_MAX);
|
||||
RNA_def_property_flag(prop, (PropertyFlag)(PROP_HIDDEN | PROP_SKIP_SAVE));
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* ------------------------------------------------------------------- */
|
||||
/** \name Unlink Object Operator
|
||||
* \{ */
|
||||
|
|
|
@ -45,15 +45,15 @@ set(SRC
|
|||
paint_cursor.cc
|
||||
paint_curve.c
|
||||
paint_curve_undo.c
|
||||
paint_hide.c
|
||||
paint_hide.cc
|
||||
paint_image.cc
|
||||
paint_image_2d.c
|
||||
paint_image_2d_curve_mask.cc
|
||||
paint_image_ops_paint.cc
|
||||
paint_image_proj.cc
|
||||
paint_mask.cc
|
||||
paint_ops.c
|
||||
paint_stroke.c
|
||||
paint_ops.cc
|
||||
paint_stroke.cc
|
||||
paint_utils.c
|
||||
paint_vertex.cc
|
||||
paint_vertex_color_ops.cc
|
||||
|
@ -88,7 +88,7 @@ set(SRC
|
|||
curves_sculpt_intern.h
|
||||
curves_sculpt_intern.hh
|
||||
paint_intern.h
|
||||
sculpt_intern.h
|
||||
sculpt_intern.hh
|
||||
)
|
||||
|
||||
set(LIB
|
||||
|
|
|
@ -55,7 +55,7 @@
|
|||
#include "paint_intern.h"
|
||||
/* still needed for sculpt_stroke_get_location, should be
|
||||
* removed eventually (TODO) */
|
||||
#include "sculpt_intern.h"
|
||||
#include "sculpt_intern.hh"
|
||||
|
||||
/* TODOs:
|
||||
*
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
#include "paint_intern.h"
|
||||
|
||||
/* For undo push. */
|
||||
#include "sculpt_intern.h"
|
||||
#include "sculpt_intern.hh"
|
||||
|
||||
/* Return true if the element should be hidden/shown. */
|
||||
static bool is_effected(PartialVisArea area,
|
||||
|
@ -67,21 +67,21 @@ static void partialvis_update_mesh(Object *ob,
|
|||
PartialVisArea area,
|
||||
float planes[4][4])
|
||||
{
|
||||
Mesh *me = ob->data;
|
||||
Mesh *me = static_cast<Mesh *>(ob->data);
|
||||
const float(*positions)[3] = BKE_pbvh_get_vert_positions(pbvh);
|
||||
const float *paint_mask;
|
||||
int totvert, i;
|
||||
bool any_changed = false, any_visible = false;
|
||||
|
||||
BKE_pbvh_node_num_verts(pbvh, node, NULL, &totvert);
|
||||
BKE_pbvh_node_num_verts(pbvh, node, nullptr, &totvert);
|
||||
const int *vert_indices = BKE_pbvh_node_get_vert_indices(node);
|
||||
paint_mask = CustomData_get_layer(&me->vdata, CD_PAINT_MASK);
|
||||
paint_mask = static_cast<const float *>(CustomData_get_layer(&me->vdata, CD_PAINT_MASK));
|
||||
|
||||
bool *hide_vert = CustomData_get_layer_named_for_write(
|
||||
&me->vdata, CD_PROP_BOOL, ".hide_vert", me->totvert);
|
||||
if (hide_vert == NULL) {
|
||||
hide_vert = CustomData_add_layer_named(
|
||||
&me->vdata, CD_PROP_BOOL, CD_SET_DEFAULT, NULL, me->totvert, ".hide_vert");
|
||||
bool *hide_vert = static_cast<bool *>(
|
||||
CustomData_get_layer_named_for_write(&me->vdata, CD_PROP_BOOL, ".hide_vert", me->totvert));
|
||||
if (hide_vert == nullptr) {
|
||||
hide_vert = static_cast<bool *>(CustomData_add_layer_named(
|
||||
&me->vdata, CD_PROP_BOOL, CD_SET_DEFAULT, nullptr, me->totvert, ".hide_vert"));
|
||||
}
|
||||
|
||||
SCULPT_undo_push_node(ob, node, SCULPT_UNDO_HIDDEN);
|
||||
|
@ -122,7 +122,7 @@ static void partialvis_update_grids(Depsgraph *depsgraph,
|
|||
bool any_changed = false, any_visible = false;
|
||||
|
||||
/* Get PBVH data. */
|
||||
BKE_pbvh_node_get_grids(pbvh, node, &grid_indices, &totgrid, NULL, NULL, &grids);
|
||||
BKE_pbvh_node_get_grids(pbvh, node, &grid_indices, &totgrid, nullptr, nullptr, &grids);
|
||||
grid_hidden = BKE_pbvh_grid_hidden(pbvh);
|
||||
CCGKey key = *BKE_pbvh_get_grid_key(pbvh);
|
||||
|
||||
|
@ -147,7 +147,7 @@ static void partialvis_update_grids(Depsgraph *depsgraph,
|
|||
else if (action == PARTIALVIS_SHOW && area == PARTIALVIS_ALL) {
|
||||
/* Special case if we're showing all, just free the grid. */
|
||||
MEM_freeN(gh);
|
||||
grid_hidden[g] = NULL;
|
||||
grid_hidden[g] = nullptr;
|
||||
any_changed = true;
|
||||
any_visible = true;
|
||||
continue;
|
||||
|
@ -180,7 +180,7 @@ static void partialvis_update_grids(Depsgraph *depsgraph,
|
|||
/* If everything in the grid is now visible, free the grid flags. */
|
||||
if (!any_hidden) {
|
||||
MEM_freeN(gh);
|
||||
grid_hidden[g] = NULL;
|
||||
grid_hidden[g] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -203,8 +203,9 @@ static void partialvis_update_bmesh_verts(BMesh *bm,
|
|||
GSetIterator gs_iter;
|
||||
|
||||
GSET_ITER (gs_iter, verts) {
|
||||
BMVert *v = BLI_gsetIterator_getKey(&gs_iter);
|
||||
float *vmask = CustomData_bmesh_get(&bm->vdata, v->head.data, CD_PAINT_MASK);
|
||||
BMVert *v = static_cast<BMVert *>(BLI_gsetIterator_getKey(&gs_iter));
|
||||
float *vmask = static_cast<float *>(
|
||||
CustomData_bmesh_get(&bm->vdata, v->head.data, CD_PAINT_MASK));
|
||||
|
||||
/* Hide vertex if in the hide volume. */
|
||||
if (is_effected(area, planes, v->co, *vmask)) {
|
||||
|
@ -228,7 +229,7 @@ static void partialvis_update_bmesh_faces(GSet *faces)
|
|||
GSetIterator gs_iter;
|
||||
|
||||
GSET_ITER (gs_iter, faces) {
|
||||
BMFace *f = BLI_gsetIterator_getKey(&gs_iter);
|
||||
BMFace *f = static_cast<BMFace *>(BLI_gsetIterator_getKey(&gs_iter));
|
||||
|
||||
if (paint_is_bmesh_face_hidden(f)) {
|
||||
BM_elem_flag_enable(f, BM_ELEM_HIDDEN);
|
||||
|
@ -298,7 +299,7 @@ static void clip_planes_from_rect(bContext *C,
|
|||
static void get_pbvh_nodes(
|
||||
PBVH *pbvh, PBVHNode ***nodes, int *totnode, float clip_planes[4][4], PartialVisArea mode)
|
||||
{
|
||||
BKE_pbvh_SearchCallback cb = NULL;
|
||||
BKE_pbvh_SearchCallback cb = nullptr;
|
||||
|
||||
/* Select search callback. */
|
||||
switch (mode) {
|
||||
|
@ -313,7 +314,9 @@ static void get_pbvh_nodes(
|
|||
break;
|
||||
}
|
||||
|
||||
PBVHFrustumPlanes frustum = {.planes = clip_planes, .num_planes = 4};
|
||||
PBVHFrustumPlanes frustum{};
|
||||
frustum.planes = clip_planes;
|
||||
frustum.num_planes = 4;
|
||||
BKE_pbvh_search_gather(pbvh, cb, &frustum, nodes, totnode);
|
||||
}
|
||||
|
||||
|
@ -322,7 +325,7 @@ static int hide_show_exec(bContext *C, wmOperator *op)
|
|||
ARegion *region = CTX_wm_region(C);
|
||||
Object *ob = CTX_data_active_object(C);
|
||||
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
|
||||
Mesh *me = ob->data;
|
||||
Mesh *me = static_cast<Mesh *>(ob->data);
|
||||
PartialVisAction action;
|
||||
PartialVisArea area;
|
||||
PBVH *pbvh;
|
||||
|
@ -333,8 +336,8 @@ static int hide_show_exec(bContext *C, wmOperator *op)
|
|||
int totnode;
|
||||
|
||||
/* Read operator properties. */
|
||||
action = RNA_enum_get(op->ptr, "action");
|
||||
area = RNA_enum_get(op->ptr, "area");
|
||||
action = PartialVisAction(RNA_enum_get(op->ptr, "action"));
|
||||
area = PartialVisArea(RNA_enum_get(op->ptr, "area"));
|
||||
rect_from_props(&rect, op->ptr);
|
||||
|
||||
clip_planes_from_rect(C, depsgraph, clip_planes, &rect);
|
||||
|
@ -395,7 +398,7 @@ static int hide_show_exec(bContext *C, wmOperator *op)
|
|||
|
||||
static int hide_show_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
{
|
||||
PartialVisArea area = RNA_enum_get(op->ptr, "area");
|
||||
PartialVisArea area = PartialVisArea(RNA_enum_get(op->ptr, "area"));
|
||||
|
||||
if (!ELEM(area, PARTIALVIS_ALL, PARTIALVIS_MASKED)) {
|
||||
return WM_gesture_box_invoke(C, op, event);
|
||||
|
@ -403,12 +406,12 @@ static int hide_show_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
|||
return op->type->exec(C, op);
|
||||
}
|
||||
|
||||
void PAINT_OT_hide_show(struct wmOperatorType *ot)
|
||||
void PAINT_OT_hide_show(wmOperatorType *ot)
|
||||
{
|
||||
static const EnumPropertyItem action_items[] = {
|
||||
{PARTIALVIS_HIDE, "HIDE", 0, "Hide", "Hide vertices"},
|
||||
{PARTIALVIS_SHOW, "SHOW", 0, "Show", "Show vertices"},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
{0, nullptr, 0, nullptr, nullptr},
|
||||
};
|
||||
|
||||
static const EnumPropertyItem area_items[] = {
|
||||
|
@ -420,7 +423,7 @@ void PAINT_OT_hide_show(struct wmOperatorType *ot)
|
|||
0,
|
||||
"Masked",
|
||||
"Hide or show vertices that are masked (minimum mask value of 0.5)"},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
{0, nullptr, 0, nullptr, nullptr},
|
||||
};
|
||||
|
||||
/* Identifiers. */
|
|
@ -46,7 +46,7 @@ typedef struct CoNo {
|
|||
float no[3];
|
||||
} CoNo;
|
||||
|
||||
/* paint_stroke.c */
|
||||
/* paint_stroke.cc */
|
||||
|
||||
typedef bool (*StrokeGetLocation)(struct bContext *C,
|
||||
float location[3],
|
||||
|
@ -87,7 +87,7 @@ bool paint_supports_texture(enum ePaintMode mode);
|
|||
bool paint_supports_jitter(enum ePaintMode mode);
|
||||
|
||||
/**
|
||||
* Called in paint_ops.c, on each regeneration of key-maps.
|
||||
* Called in paint_ops.cc, on each regeneration of key-maps.
|
||||
*/
|
||||
struct wmKeyMap *paint_stroke_modal_keymap(struct wmKeyConfig *keyconf);
|
||||
int paint_stroke_modal(struct bContext *C,
|
||||
|
@ -457,7 +457,7 @@ typedef enum BrushStrokeMode {
|
|||
BRUSH_STROKE_SMOOTH,
|
||||
} BrushStrokeMode;
|
||||
|
||||
/* paint_hide.c */
|
||||
/* paint_hide.cc */
|
||||
|
||||
typedef enum {
|
||||
PARTIALVIS_HIDE,
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue