Geometry Node: Multi-input socket tooltip #104468

Merged
Jacques Lucke merged 33 commits from mod_moder/blender:multi_input_tooltip into main 2024-04-22 19:49:08 +02:00
46 changed files with 273 additions and 290 deletions
Showing only changes of commit ddaa411f0d - Show all commits

View File

@ -1399,13 +1399,12 @@ endif()
# Test SIMD support, before platform includes to determine if sse2neon is needed.
if(WITH_CPU_SIMD)
set(COMPILER_SSE_FLAG)
set(COMPILER_SSE2_FLAG)
set(COMPILER_SSE42_FLAG)
# Test Neon first since macOS Arm can compile and run x86-64 SSE binaries.
test_neon_support()
if(NOT SUPPORT_NEON_BUILD)
test_sse_support(COMPILER_SSE_FLAG COMPILER_SSE2_FLAG)
test_sse_support(COMPILER_SSE42_FLAG)
endif()
endif()
@ -1445,8 +1444,6 @@ endif()
# Enable SIMD support if detected by `test_sse_support()` or `test_neon_support()`.
#
# This is done globally, so that all modules can use it if available, and
# because these are used in headers used by many modules.
if(WITH_CPU_SIMD)
if(SUPPORT_NEON_BUILD)
# Neon
@ -1456,15 +1453,20 @@ if(WITH_CPU_SIMD)
endif()
else()
# SSE
if(SUPPORT_SSE_BUILD)
string(PREPEND PLATFORM_CFLAGS "${COMPILER_SSE_FLAG} ")
add_definitions(-D__SSE__ -D__MMX__)
endif()
if(SUPPORT_SSE2_BUILD)
string(APPEND PLATFORM_CFLAGS " ${COMPILER_SSE2_FLAG}")
add_definitions(-D__SSE2__)
if(NOT SUPPORT_SSE_BUILD) # don't double up
add_definitions(-D__MMX__)
if(SUPPORT_SSE42_BUILD)
string(APPEND CMAKE_CXX_FLAGS " ${COMPILER_SSE42_FLAG}")
string(APPEND CMAKE_C_FLAGS " ${COMPILER_SSE42_FLAG}")
# MSVC doesn't define any of these and only does the AVX and higher flags.
# For consistency we define these flags for MSVC.
if(WIN32)
add_compile_definitions(
__MMX__
__SSE__
__SSE2__
__SSE3__
__SSE4_1__
__SSE4_2__
)
endif()
endif()
endif()
@ -1479,10 +1481,8 @@ if(FIRST_RUN)
else()
message(STATUS "Neon SIMD instructions detected but unused, requires sse2neon")
endif()
elseif(SUPPORT_SSE2_BUILD)
message(STATUS "SSE2 SIMD instructions enabled")
elseif(SUPPORT_SSE_BUILD)
message(STATUS "SSE SIMD instructions enabled")
elseif(SUPPORT_SSE42_BUILD)
message(STATUS "SSE42 SIMD instructions enabled")
else()
message(STATUS "No SIMD instructions detected")
endif()

View File

@ -540,49 +540,37 @@ function(setup_platform_linker_libs
endfunction()
macro(TEST_SSE_SUPPORT
_sse_flags
_sse2_flags)
_sse42_flags)
include(CheckCSourceRuns)
# message(STATUS "Detecting SSE support")
if(CMAKE_COMPILER_IS_GNUCC OR (CMAKE_C_COMPILER_ID MATCHES "Clang"))
set(${_sse_flags} "-msse")
set(${_sse2_flags} "-msse2")
set(${_sse42_flags} "-march=x86-64-v2")
elseif(MSVC)
# x86_64 has this auto enabled
if("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
set(${_sse_flags} "")
set(${_sse2_flags} "")
else()
set(${_sse_flags} "/arch:SSE")
set(${_sse2_flags} "/arch:SSE2")
endif()
# msvc has no specific build flags for SSE42, but when using intrinsics it will
# generate the right instructions.
set(${_sse42_flags} "")
elseif(CMAKE_C_COMPILER_ID STREQUAL "Intel")
set(${_sse_flags} "") # icc defaults to -msse
set(${_sse2_flags} "") # icc defaults to -msse2
if(WIN32)
set(${_sse42_flags} "/QxSSE4.2")
else()
set(${_sse42_flags} "-xsse4.2")
endif()
else()
message(WARNING "SSE flags for this compiler: '${CMAKE_C_COMPILER_ID}' not known")
set(${_sse_flags})
set(${_sse2_flags})
set(${_sse42_flags})
endif()
set(CMAKE_REQUIRED_FLAGS "${${_sse_flags}} ${${_sse2_flags}}")
set(CMAKE_REQUIRED_FLAGS "${${_sse42_flags}}")
if(NOT DEFINED SUPPORT_SSE_BUILD)
# result cached
check_c_source_runs("
#include <xmmintrin.h>
int main(void) { __m128 v = _mm_setzero_ps(); return 0; }"
SUPPORT_SSE_BUILD)
endif()
if(NOT DEFINED SUPPORT_SSE2_BUILD)
if(NOT DEFINED SUPPORT_SSE42_BUILD)
# result cached
check_c_source_runs("
#include <nmmintrin.h>
#include <emmintrin.h>
int main(void) { __m128d v = _mm_setzero_pd(); return 0; }"
SUPPORT_SSE2_BUILD)
int main(void) { __m128i v = _mm_setzero_si128(); v = _mm_cmpgt_epi64(v,v); return 0; }"
SUPPORT_SSE42_BUILD)
endif()
unset(CMAKE_REQUIRED_FLAGS)

View File

@ -21,4 +21,4 @@ if "Cube" in bpy.data.meshes:
import os
with open(os.path.splitext(bpy.data.filepath)[0] + ".txt", 'w') as fs:
for image in bpy.data.images:
fs.write("%s %d x %d\n" % (image.filepath, image.size[0], image.size[1]))
fs.write("{:s} {:d} x {:d}\n".format(image.filepath, image.size[0], image.size[1]))

View File

@ -21,8 +21,9 @@ class OBJECT_OT_property_example(bpy.types.Operator):
def execute(self, context):
self.report(
{'INFO'}, 'F: %.2f B: %s S: %r' %
(self.my_float, self.my_bool, self.my_string)
{'INFO'}, "F: {:.2f} B: {:s} S: {!r}".format(
self.my_float, self.my_bool, self.my_string,
)
)
print('My float:', self.my_float)
print('My bool:', self.my_bool)

View File

@ -53,9 +53,9 @@ class OBJECT_OT_addon_prefs_example(Operator):
preferences = context.preferences
addon_prefs = preferences.addons[__name__].preferences
info = ("Path: %s, Number: %d, Boolean %r" %
(addon_prefs.filepath, addon_prefs.number, addon_prefs.boolean))
info = "Path: {:s}, Number: {:d}, Boolean {!r}".format(
addon_prefs.filepath, addon_prefs.number, addon_prefs.boolean,
)
self.report({'INFO'}, info)
print(info)

View File

@ -18,7 +18,7 @@ import bpy
def dump(obj, text):
for attr in dir(obj):
print("%r.%s = %s" % (obj, attr, getattr(obj, attr)))
print("{!r}.{:s} = {:s}".format(obj, attr, getattr(obj, attr)))
class WM_OT_button_context_test(bpy.types.Operator):

View File

@ -31,10 +31,10 @@ me = bpy.context.object.data
uv_layer = me.uv_layers.active.data
for poly in me.polygons:
print("Polygon index: %d, length: %d" % (poly.index, poly.loop_total))
print("Polygon index: {:d}, length: {:d}".format(poly.index, poly.loop_total))
# range is used here to show how the polygons reference loops,
# for convenience 'poly.loop_indices' can be used instead.
for loop_index in range(poly.loop_start, poly.loop_start + poly.loop_total):
print(" Vertex: %d" % me.loops[loop_index].vertex_index)
print(" UV: %r" % uv_layer[loop_index].uv)
print(" Vertex: {:d}".format(me.loops[loop_index].vertex_index))
print(" UV: {!r}".format(uv_layer[loop_index].uv))

View File

@ -34,7 +34,7 @@ class SimpleMouseOperator(bpy.types.Operator):
def execute(self, context):
# rather than printing, use the report function,
# this way the message appears in the header,
self.report({'INFO'}, "Mouse coords are %d %d" % (self.x, self.y))
self.report({'INFO'}, "Mouse coords are {:d} {:d}".format(self.x, self.y))
return {'FINISHED'}
def invoke(self, context, event):

View File

@ -16,9 +16,8 @@ class DialogOperator(bpy.types.Operator):
my_string: bpy.props.StringProperty(name="String Value")
def execute(self, context):
message = (
"Popup Values: %f, %d, '%s'" %
(self.my_float, self.my_bool, self.my_string)
message = "Popup Values: {:f}, {:d}, '{:s}'".format(
self.my_float, self.my_bool, self.my_string,
)
self.report({'INFO'}, message)
return {'FINISHED'}

View File

@ -10,21 +10,21 @@ col.s *= 0.5
print("Color R:", col.r)
print("Color G:", col[1])
print("Color B:", col[-1])
print("Color HSV: %.2f, %.2f, %.2f", col[:])
print("Color HSV: {:.2f}, {:.2f}, {:.2f}".format(*col))
# components of an existing color can be set
col[:] = 0.0, 0.5, 1.0
# components of an existing color can use slice notation to get a tuple
print("Values: %f, %f, %f" % col[:])
print("Values: {:f}, {:f}, {:f}".format(*col))
# colors can be added and subtracted
col += mathutils.Color((0.25, 0.0, 0.0))
# Color can be multiplied, in this example color is scaled to 0-255
# can printed as integers
print("Color: %d, %d, %d" % (col * 255.0)[:])
print("Color: {:d}, {:d}, {:d}".format(*(int(c) for c in (col * 255.0))))
# This example prints the color as hexadecimal
print("Hexadecimal: %.2x%.2x%.2x" % (int(col.r * 255), int(col.g * 255), int(col.b * 255)))
print("Hexadecimal: {:02x}{:02x}{:02x}".format(int(col.r * 255), int(col.g * 255), int(col.b * 255)))

View File

@ -16,7 +16,7 @@ print("Euler Z", eul[-1])
eul[:] = 1.0, 2.0, 3.0
# components of an existing euler can use slice notation to get a tuple
print("Values: %f, %f, %f" % eul[:])
print("Values: {:f}, {:f}, {:f}".format(*eul))
# the order can be set at any time too
eul.order = 'ZYX'

View File

@ -18,9 +18,8 @@ quat_out = quat_a @ quat_b
# print the quat, euler degrees for mere mortals and (axis, angle)
print("Final Rotation:")
print(quat_out)
print("%.2f, %.2f, %.2f" % tuple(math.degrees(a) for a in quat_out.to_euler()))
print("(%.2f, %.2f, %.2f), %.2f" % (quat_out.axis[:] +
(math.degrees(quat_out.angle), )))
print("{:.2f}, {:.2f}, {:.2f}".format(*(math.degrees(a) for a in quat_out.to_euler())))
print("({:.2f}, {:.2f}, {:.2f}), {:.2f}".format(*quat_out.axis, math.degrees(quat_out.angle)))
# multiple rotations can be interpolated using the exponential map
quat_c = mathutils.Quaternion((1.0, 0.0, 0.0), math.radians(15.0))

View File

@ -21,7 +21,7 @@ class CyclesPresetPanel(PresetPanel, Panel):
preset_operator = "script.execute_preset"
@staticmethod
def post_cb(context):
def post_cb(context, _filepath):
# Modify an arbitrary built-in scene property to force a depsgraph
# update, because add-on properties don't. (see #62325)
render = context.scene.render

View File

@ -332,7 +332,7 @@ class InfoPropertyRNA:
self.default_str = "\"%s\"" % self.default
elif self.type == "enum":
if self.is_enum_flag:
# self.default_str = "%r" % self.default # repr or set()
# self.default_str = repr(self.default) # repr or set()
self.default_str = "{%s}" % repr(list(sorted(self.default)))[1:-1]
else:
self.default_str = "'%s'" % self.default

View File

@ -818,7 +818,7 @@ class TransformsToDeltasAnim(Operator):
if fcu.array_index in existingFCurves[dpath]:
# conflict
self.report({'ERROR'},
rpt_("Object '%r' already has '%r' F-Curve(s). "
rpt_("Object %r already has %r F-Curve(s). "
"Remove these before trying again") %
(obj.name, dpath))
return {'CANCELLED'}

View File

@ -30,6 +30,25 @@ WindowManager.preset_name = StringProperty(
)
def _call_preset_cb(fn, context, filepath):
# Allow "None" so the caller doesn't have to assign a variable and check it.
if fn is None:
return
# Support a `filepath` argument, optional for backwards compatibility.
fn_arg_count = getattr(getattr(fn, "__code__", None), "co_argcount", None)
if fn_arg_count == 2:
args = (context, filepath)
else:
print("Deprecated since Blender 4.2, a filepath argument should be included in:", fn)
args = (context, )
try:
fn(*args)
except BaseException as ex:
print("Internal error running", fn, str(ex))
class AddPresetBase:
"""Base preset class, only for subclassing
subclasses must define
@ -241,8 +260,7 @@ class ExecutePreset(Operator):
self.report({'ERROR'}, rpt_("Unknown file type: %r") % ext)
return {'CANCELLED'}
if hasattr(preset_class, "reset_cb"):
preset_class.reset_cb(context)
_call_preset_cb(getattr(preset_class, "reset_cb", None), context, filepath)
if ext == ".py":
try:
@ -254,8 +272,7 @@ class ExecutePreset(Operator):
import rna_xml
rna_xml.xml_file_run(context, filepath, preset_class.preset_xml_map)
if hasattr(preset_class, "post_cb"):
preset_class.post_cb(context)
_call_preset_cb(getattr(preset_class, "post_cb", None), context, filepath)
return {'FINISHED'}
@ -637,6 +654,8 @@ class SavePresetInterfaceTheme(AddPresetBase, Operator):
traceback.print_exc()
return {'CANCELLED'}
context.preferences.themes[0].filepath = filepath
return {'FINISHED'}
def invoke(self, context, event):

View File

@ -166,7 +166,7 @@ class PlayRenderedAnim(Operator):
opts = ["-fps", str(rd.fps), "-play"]
if scene.use_preview_range:
opts += [
"%s" % file.replace("#", "", file.count('#') - 1),
file.replace("#", "", file.count('#') - 1),
"%d-%d" % (frame_start, frame_end),
]
else:

View File

@ -66,7 +66,7 @@ class OUTLINER_HT_header(Header):
layout.operator("outliner.collection_new", text="", icon='COLLECTION_NEW').nested = True
elif display_mode == 'ORPHAN_DATA':
layout.operator("outliner.orphans_purge", text="Purge").do_recursive = True
layout.operator("outliner.orphans_purge", text="Purge")
elif space.display_mode == 'DATA_API':
layout.separator()

View File

@ -860,21 +860,37 @@ class USERPREF_MT_interface_theme_presets(Menu):
draw = Menu.draw_preset
@staticmethod
def reset_cb(context):
def reset_cb(_context, _filepath):
bpy.ops.preferences.reset_default_theme()
@staticmethod
def post_cb(context, filepath):
context.preferences.themes[0].filepath = filepath
class USERPREF_PT_theme(ThemePanel, Panel):
bl_label = "Themes"
bl_options = {'HIDE_HEADER'}
def draw(self, _context):
def draw(self, context):
import os
layout = self.layout
split = layout.split(factor=0.6)
row = split.row(align=True)
row.menu("USERPREF_MT_interface_theme_presets", text=USERPREF_MT_interface_theme_presets.bl_label)
# Unlike most presets (which use the classes bl_label),
# themes store the path, use this when set.
if filepath := context.preferences.themes[0].filepath:
preset_label = bpy.path.display_name(os.path.basename(filepath))
else:
preset_label = USERPREF_MT_interface_theme_presets.bl_label
row.menu("USERPREF_MT_interface_theme_presets", text=preset_label)
del filepath, preset_label
row.operator("wm.interface_theme_preset_add", text="", icon='ADD')
row.operator("wm.interface_theme_preset_remove", text="", icon='REMOVE')
row.operator("wm.interface_theme_preset_save", text="", icon='FILE_TICK')

View File

@ -108,7 +108,7 @@ class MyCustomShapeWidget(Gizmo):
delta /= 10.0
value = self.init_value - delta
self.target_set_value("offset", value)
context.area.header_text_set("My Gizmo: %.4f" % value)
context.area.header_text_set("My Gizmo: {:.4f}".format(value))
return {'RUNNING_MODAL'}

View File

@ -4,7 +4,7 @@ import bpy
def write_some_data(context, filepath, use_some_setting):
print("running write_some_data...")
f = open(filepath, 'w', encoding='utf-8')
f.write("Hello World %s" % use_some_setting)
f.write("Hello World {:s}".format(use_some_setting))
f.close()
return {'FINISHED'}

View File

@ -26,7 +26,7 @@ class ViewOperator(bpy.types.Operator):
if event.type == 'MOUSEMOVE':
self.offset = (self._initial_mouse - Vector((event.mouse_x, event.mouse_y, 0.0))) * 0.02
self.execute(context)
context.area.header_text_set("Offset %.4f %.4f %.4f" % tuple(self.offset))
context.area.header_text_set("Offset {:.4f} {:.4f} {:.4f}".format(*self.offset))
elif event.type == 'LEFTMOUSE':
context.area.header_text_set(None)

View File

@ -39,7 +39,7 @@ def enum_previews_from_directory_items(self, context):
if directory == pcoll.my_previews_dir:
return pcoll.my_previews
print("Scanning directory: %s" % directory)
print("Scanning directory:", directory)
if directory and os.path.exists(directory):
# Scan the directory for `*.png` files

View File

@ -181,3 +181,7 @@ endif()
if(WITH_FREESTYLE)
add_subdirectory(freestyle)
endif()
if(WITH_CPU_CHECK)
add_subdirectory(cpucheck)
endif()

View File

@ -29,7 +29,7 @@ extern "C" {
/* Blender file format version. */
#define BLENDER_FILE_VERSION BLENDER_VERSION
#define BLENDER_FILE_SUBVERSION 15
#define BLENDER_FILE_SUBVERSION 16
/* Minimum Blender version that supports reading file written with the current
* version. Older Blender versions will test this and cancel loading the file, showing a warning to

View File

@ -575,14 +575,6 @@ struct SculptSession {
blender::float3 cursor_sampled_normal;
blender::float3 cursor_view_normal;
/* For Sculpt trimming gesture tools, initial ray-cast data from the position of the mouse
* when
* the gesture starts (intersection with the surface and if they ray hit the surface or not).
*/
blender::float3 gesture_initial_location;
blender::float3 gesture_initial_normal;
bool gesture_initial_hit;
/* TODO(jbakker): Replace rv3d and v3d with ViewContext */
RegionView3D *rv3d;
View3D *v3d;

View File

@ -67,7 +67,7 @@ static void do_versions_theme(const UserDef *userdef, bTheme *btheme)
#define FROM_DEFAULT_V4_UCHAR(member) copy_v4_v4_uchar(btheme->member, U_theme_default.member)
if (!USER_VERSION_ATLEAST(300, 41)) {
memcpy(btheme, &U_theme_default, sizeof(*btheme));
MEMCPY_STRUCT_AFTER(btheme, &U_theme_default, name);
}
/* Again reset the theme, but only if stored with an early 3.1 alpha version. Some changes were
@ -76,7 +76,7 @@ static void do_versions_theme(const UserDef *userdef, bTheme *btheme)
* don't want to reset theme changes stored in the eventual 3.0 release once opened in a 3.1
* build. */
if (userdef->versionfile > 300 && !USER_VERSION_ATLEAST(301, 1)) {
memcpy(btheme, &U_theme_default, sizeof(*btheme));
MEMCPY_STRUCT_AFTER(btheme, &U_theme_default, name);
}
if (!USER_VERSION_ATLEAST(301, 2)) {
@ -145,7 +145,7 @@ static void do_versions_theme(const UserDef *userdef, bTheme *btheme)
FROM_DEFAULT_V4_UCHAR(space_console.console_cursor);
}
if (!USER_VERSION_ATLEAST(402, 14)) {
if (!USER_VERSION_ATLEAST(402, 16)) {
BLI_uniquename(
&userdef->themes, btheme, "Theme", '.', offsetof(bTheme, name), sizeof(btheme->name));
}
@ -515,7 +515,7 @@ void blo_do_versions_userdef(UserDef *userdef)
/* Reset theme, old themes will not be compatible with minor version updates from now on. */
LISTBASE_FOREACH (bTheme *, btheme, &userdef->themes) {
memcpy(btheme, &U_theme_default, sizeof(*btheme));
MEMCPY_STRUCT_AFTER(btheme, &U_theme_default, name);
}
/* Annotations - new layer color

View File

@ -0,0 +1,26 @@
# SPDX-FileCopyrightText: 2024 Blender Authors
#
# SPDX-License-Identifier: GPL-2.0-or-later
# The cpu check module cannot build with sse42 since it will be executed
# by cpus that may not support these instructions
if(COMPILER_SSE42_FLAG)
remove_cc_flag("${COMPILER_SSE42_FLAG}")
endif()
add_library(blender_cpu_check SHARED cpu_check.cc)
target_link_libraries(blender_cpu_check PRIVATE ${PLATFORM_LINKLIBS})
target_compile_definitions(blender_cpu_check PUBLIC WITH_CPU_CHECK)
if(NOT WIN32)
set(_LIB_SUB_FOLDER "lib/")
endif()
set_target_properties(blender_cpu_check
PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/${_LIB_SUB_FOLDER}"
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/${_LIB_SUB_FOLDER}"
)
unset(_LIB_SUB_FOLDER)

View File

@ -580,6 +580,30 @@ bool ANIM_animdata_can_have_greasepencil(const eAnimCont_Types type)
/* ----------- 'Private' Stuff --------------- */
/**
* Set `ale` so that it points to the top-most 'summary' channel of the given `adt`.
* So this is either the Animation or the Action, or empty.
*/
static void key_data_from_adt(bAnimListElem &ale, AnimData *adt)
{
ale.adt = adt;
if (!adt) {
ale.key_data = nullptr;
ale.datatype = ALE_NONE;
return;
}
if (adt->action) {
ale.key_data = adt->action;
ale.datatype = ALE_ACT;
return;
}
ale.key_data = nullptr;
ale.datatype = ALE_NONE;
}
/* this function allocates memory for a new bAnimListElem struct for the
* provided animation channel-data.
*/
@ -655,244 +679,125 @@ static bAnimListElem *make_new_animlistelem(void *data,
}
case ANIMTYPE_DSMAT: {
Material *ma = (Material *)data;
AnimData *adt = ma->adt;
ale->flag = FILTER_MAT_OBJD(ma);
ale->key_data = (adt) ? adt->action : nullptr;
ale->datatype = ALE_ACT;
ale->adt = BKE_animdata_from_id(static_cast<ID *>(data));
key_data_from_adt(*ale, ma->adt);
break;
}
case ANIMTYPE_DSLAM: {
Light *la = (Light *)data;
AnimData *adt = la->adt;
ale->flag = FILTER_LAM_OBJD(la);
ale->key_data = (adt) ? adt->action : nullptr;
ale->datatype = ALE_ACT;
ale->adt = BKE_animdata_from_id(static_cast<ID *>(data));
key_data_from_adt(*ale, la->adt);
break;
}
case ANIMTYPE_DSCAM: {
Camera *ca = (Camera *)data;
AnimData *adt = ca->adt;
ale->flag = FILTER_CAM_OBJD(ca);
ale->key_data = (adt) ? adt->action : nullptr;
ale->datatype = ALE_ACT;
ale->adt = BKE_animdata_from_id(static_cast<ID *>(data));
key_data_from_adt(*ale, ca->adt);
break;
}
case ANIMTYPE_DSCACHEFILE: {
CacheFile *cache_file = (CacheFile *)data;
AnimData *adt = cache_file->adt;
ale->flag = FILTER_CACHEFILE_OBJD(cache_file);
ale->key_data = (adt) ? adt->action : nullptr;
ale->datatype = ALE_ACT;
ale->adt = BKE_animdata_from_id(static_cast<ID *>(data));
key_data_from_adt(*ale, cache_file->adt);
break;
}
case ANIMTYPE_DSCUR: {
Curve *cu = (Curve *)data;
AnimData *adt = cu->adt;
ale->flag = FILTER_CUR_OBJD(cu);
ale->key_data = (adt) ? adt->action : nullptr;
ale->datatype = ALE_ACT;
ale->adt = BKE_animdata_from_id(static_cast<ID *>(data));
key_data_from_adt(*ale, cu->adt);
break;
}
case ANIMTYPE_DSARM: {
bArmature *arm = (bArmature *)data;
AnimData *adt = arm->adt;
ale->flag = FILTER_ARM_OBJD(arm);
ale->key_data = (adt) ? adt->action : nullptr;
ale->datatype = ALE_ACT;
ale->adt = BKE_animdata_from_id(static_cast<ID *>(data));
key_data_from_adt(*ale, arm->adt);
break;
}
case ANIMTYPE_DSMESH: {
Mesh *mesh = (Mesh *)data;
AnimData *adt = mesh->adt;
ale->flag = FILTER_MESH_OBJD(mesh);
ale->key_data = (adt) ? adt->action : nullptr;
ale->datatype = ALE_ACT;
ale->adt = BKE_animdata_from_id(static_cast<ID *>(data));
key_data_from_adt(*ale, mesh->adt);
break;
}
case ANIMTYPE_DSLAT: {
Lattice *lt = (Lattice *)data;
AnimData *adt = lt->adt;
ale->flag = FILTER_LATTICE_OBJD(lt);
ale->key_data = (adt) ? adt->action : nullptr;
ale->datatype = ALE_ACT;
ale->adt = BKE_animdata_from_id(static_cast<ID *>(data));
key_data_from_adt(*ale, lt->adt);
break;
}
case ANIMTYPE_DSSPK: {
Speaker *spk = (Speaker *)data;
AnimData *adt = spk->adt;
ale->flag = FILTER_SPK_OBJD(spk);
ale->key_data = (adt) ? adt->action : nullptr;
ale->datatype = ALE_ACT;
ale->adt = BKE_animdata_from_id(static_cast<ID *>(data));
key_data_from_adt(*ale, spk->adt);
break;
}
case ANIMTYPE_DSHAIR: {
Curves *curves = (Curves *)data;
AnimData *adt = curves->adt;
ale->flag = FILTER_CURVES_OBJD(curves);
ale->key_data = (adt) ? adt->action : nullptr;
ale->datatype = ALE_ACT;
ale->adt = BKE_animdata_from_id(static_cast<ID *>(data));
key_data_from_adt(*ale, curves->adt);
break;
}
case ANIMTYPE_DSPOINTCLOUD: {
PointCloud *pointcloud = (PointCloud *)data;
AnimData *adt = pointcloud->adt;
ale->flag = FILTER_POINTS_OBJD(pointcloud);
ale->key_data = (adt) ? adt->action : nullptr;
ale->datatype = ALE_ACT;
ale->adt = BKE_animdata_from_id(static_cast<ID *>(data));
key_data_from_adt(*ale, pointcloud->adt);
break;
}
case ANIMTYPE_DSVOLUME: {
Volume *volume = (Volume *)data;
AnimData *adt = volume->adt;
ale->flag = FILTER_VOLUME_OBJD(volume);
ale->key_data = (adt) ? adt->action : nullptr;
ale->datatype = ALE_ACT;
ale->adt = BKE_animdata_from_id(static_cast<ID *>(data));
key_data_from_adt(*ale, volume->adt);
break;
}
case ANIMTYPE_DSSKEY: {
Key *key = (Key *)data;
AnimData *adt = key->adt;
ale->flag = FILTER_SKE_OBJD(key);
ale->key_data = (adt) ? adt->action : nullptr;
ale->datatype = ALE_ACT;
ale->adt = BKE_animdata_from_id(static_cast<ID *>(data));
key_data_from_adt(*ale, key->adt);
break;
}
case ANIMTYPE_DSWOR: {
World *wo = (World *)data;
AnimData *adt = wo->adt;
ale->flag = FILTER_WOR_SCED(wo);
ale->key_data = (adt) ? adt->action : nullptr;
ale->datatype = ALE_ACT;
ale->adt = BKE_animdata_from_id(static_cast<ID *>(data));
key_data_from_adt(*ale, wo->adt);
break;
}
case ANIMTYPE_DSNTREE: {
bNodeTree *ntree = (bNodeTree *)data;
AnimData *adt = ntree->adt;
ale->flag = FILTER_NTREE_DATA(ntree);
ale->key_data = (adt) ? adt->action : nullptr;
ale->datatype = ALE_ACT;
ale->adt = BKE_animdata_from_id(static_cast<ID *>(data));
key_data_from_adt(*ale, ntree->adt);
break;
}
case ANIMTYPE_DSLINESTYLE: {
FreestyleLineStyle *linestyle = (FreestyleLineStyle *)data;
AnimData *adt = linestyle->adt;
ale->flag = FILTER_LS_SCED(linestyle);
ale->key_data = (adt) ? adt->action : nullptr;
ale->datatype = ALE_ACT;
ale->adt = BKE_animdata_from_id(static_cast<ID *>(data));
key_data_from_adt(*ale, linestyle->adt);
break;
}
case ANIMTYPE_DSPART: {
ParticleSettings *part = (ParticleSettings *)ale->data;
AnimData *adt = part->adt;
ale->flag = FILTER_PART_OBJD(part);
ale->key_data = (adt) ? adt->action : nullptr;
ale->datatype = ALE_ACT;
ale->adt = BKE_animdata_from_id(static_cast<ID *>(data));
key_data_from_adt(*ale, part->adt);
break;
}
case ANIMTYPE_DSTEX: {
Tex *tex = (Tex *)data;
AnimData *adt = tex->adt;
ale->flag = FILTER_TEX_DATA(tex);
ale->key_data = (adt) ? adt->action : nullptr;
ale->datatype = ALE_ACT;
ale->adt = BKE_animdata_from_id(static_cast<ID *>(data));
key_data_from_adt(*ale, tex->adt);
break;
}
case ANIMTYPE_DSGPENCIL: {
bGPdata *gpd = (bGPdata *)data;
AnimData *adt = gpd->adt;
/* NOTE: we just reuse the same expand filter for this case */
ale->flag = EXPANDED_GPD(gpd);
/* XXX: currently, this is only used for access to its animation data */
ale->key_data = (adt) ? adt->action : nullptr;
ale->datatype = ALE_ACT;
ale->adt = BKE_animdata_from_id(static_cast<ID *>(data));
key_data_from_adt(*ale, gpd->adt);
break;
}
case ANIMTYPE_DSMCLIP: {
MovieClip *clip = (MovieClip *)data;
AnimData *adt = clip->adt;
ale->flag = EXPANDED_MCLIP(clip);
ale->key_data = (adt) ? adt->action : nullptr;
ale->datatype = ALE_ACT;
ale->adt = BKE_animdata_from_id(static_cast<ID *>(data));
key_data_from_adt(*ale, clip->adt);
break;
}
case ANIMTYPE_NLACONTROLS: {

View File

@ -54,6 +54,8 @@ struct AssetItemTree {
assets_per_path;
/** Assets not added to a catalog, not part of #assets_per_path. */
Vector<asset_system::AssetRepresentation *> unassigned_assets;
/** True if the tree is out of date compared to asset libraries and must be rebuilt. */
bool dirty = true;
};
asset_system::AssetCatalogTree build_filtered_catalog_tree(

View File

@ -150,7 +150,8 @@ AssetItemTree build_filtered_all_catalog_tree(
return {std::move(catalogs_with_node_assets),
std::move(assets_per_path),
std::move(unassigned_assets)};
std::move(unassigned_assets),
false};
}
} // namespace blender::ed::asset

View File

@ -315,7 +315,7 @@ void AssetClearHelper::reportResults(const bContext *C, ReportList &reports) con
&reports, RPT_INFO, "Data-block '%s' is not an asset anymore", stats.last_id->name + 2);
}
else {
BKE_reportf(&reports, RPT_INFO, "%i data-blocks are no assets anymore", stats.tot_cleared);
BKE_reportf(&reports, RPT_INFO, "%i data-blocks are not assets anymore", stats.tot_cleared);
}
}

View File

@ -787,7 +787,7 @@ void clear_operator_asset_trees()
for (const ObjectType type : {OB_MESH, OB_CURVES, OB_POINTCLOUD}) {
for (const eObjectMode mode : {OB_MODE_OBJECT, OB_MODE_EDIT, OB_MODE_SCULPT_CURVES}) {
if (asset::AssetItemTree *tree = get_static_item_tree(type, mode)) {
*tree = {};
tree->dirty = true;
}
}
}
@ -1105,7 +1105,7 @@ void ui_template_node_operator_asset_root_items(uiLayout &layout, const bContext
if (!tree) {
return;
}
if (tree->assets_per_path.size() == 0) {
if (tree->dirty) {
*tree = build_catalog_tree(C, *active_object);
}

View File

@ -1071,6 +1071,7 @@ void UI_theme_init_default()
BLI_findstring(&U.themes, U_theme_default.name, offsetof(bTheme, name)));
if (btheme == nullptr) {
btheme = MEM_cnew<bTheme>(__func__);
STRNCPY(btheme->name, U_theme_default.name);
BLI_addhead(&U.themes, btheme);
}

View File

@ -38,6 +38,7 @@
#include "sculpt_intern.hh"
namespace blender::ed::sculpt_paint::trim {
enum class OperationType {
Intersect = 0,
Difference = 1,
@ -112,6 +113,10 @@ struct TrimOperation {
/* Operator properties. */
bool use_cursor_depth;
bool initial_hit;
blender::float3 initial_location;
blender::float3 initial_normal;
OperationType mode;
SolverMode solver_mode;
OrientationType orientation;
@ -166,17 +171,17 @@ static void get_origin_and_normal(gesture::GestureData &gesture_data,
case OrientationType::View:
mul_v3_m4v3(r_origin,
gesture_data.vc.obact->object_to_world().ptr(),
gesture_data.ss->gesture_initial_location);
trim_operation->initial_location);
copy_v3_v3(r_normal, gesture_data.world_space_view_normal);
negate_v3(r_normal);
break;
case OrientationType::Surface:
mul_v3_m4v3(r_origin,
gesture_data.vc.obact->object_to_world().ptr(),
gesture_data.ss->gesture_initial_location);
trim_operation->initial_location);
/* Transforming the normal does not take non uniform scaling into account. Sculpt mode is not
* expected to work on object with non uniform scaling. */
copy_v3_v3(r_normal, gesture_data.ss->gesture_initial_normal);
copy_v3_v3(r_normal, trim_operation->initial_normal);
mul_mat3_m4_v3(gesture_data.vc.obact->object_to_world().ptr(), r_normal);
break;
}
@ -221,11 +226,11 @@ static void calculate_depth(gesture::GestureData &gesture_data,
float world_space_gesture_initial_location[3];
mul_v3_m4v3(world_space_gesture_initial_location,
vc->obact->object_to_world().ptr(),
ss->gesture_initial_location);
trim_operation->initial_location);
float mid_point_depth;
if (trim_operation->orientation == OrientationType::View) {
mid_point_depth = ss->gesture_initial_hit ?
mid_point_depth = trim_operation->initial_hit ?
dist_signed_to_plane_v3(world_space_gesture_initial_location,
shape_plane) :
(depth_back + depth_front) * 0.5f;
@ -234,12 +239,12 @@ static void calculate_depth(gesture::GestureData &gesture_data,
/* When using normal orientation, if the stroke started over the mesh, position the mid point
* at 0 distance from the shape plane. This positions the trimming shape half inside of the
* surface. */
mid_point_depth = ss->gesture_initial_hit ? 0.0f : (depth_back + depth_front) * 0.5f;
mid_point_depth = trim_operation->initial_hit ? 0.0f : (depth_back + depth_front) * 0.5f;
}
float depth_radius;
if (ss->gesture_initial_hit) {
if (trim_operation->initial_hit) {
depth_radius = ss->cursor_radius;
}
else {
@ -254,7 +259,7 @@ static void calculate_depth(gesture::GestureData &gesture_data,
if (!BKE_brush_use_locked_size(scene, brush)) {
depth_radius = paint_calc_object_space_radius(
vc, ss->gesture_initial_location, BKE_brush_size_get(scene, brush));
vc, trim_operation->initial_location, BKE_brush_size_get(scene, brush));
}
else {
depth_radius = BKE_brush_unprojected_radius_get(scene, brush);
@ -609,13 +614,27 @@ static void init_operation(gesture::GestureData &gesture_data, wmOperator &op)
trim_operation->solver_mode = SolverMode(RNA_enum_get(op.ptr, "trim_solver"));
/* If the cursor was not over the mesh, force the orientation to view. */
if (!gesture_data.ss->gesture_initial_hit) {
if (!trim_operation->initial_hit) {
trim_operation->orientation = OrientationType::View;
}
}
static void operator_properties(wmOperatorType *ot)
{
PropertyRNA *prop;
prop = RNA_def_int_vector(ot->srna,
"location",
2,
nullptr,
INT_MIN,
INT_MAX,
"Location",
"Mouse location",
INT_MIN,
INT_MAX);
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
RNA_def_enum(ot->srna,
"trim_mode",
operation_types,
@ -672,21 +691,26 @@ static bool can_exec(const bContext &C)
return true;
}
static void initialize_cursor_info(bContext &C, const wmEvent *event)
static void initialize_cursor_info(bContext &C,
const wmOperator &op,
gesture::GestureData &gesture_data)
{
const Object &ob = *CTX_data_active_object(&C);
SculptSession &ss = *ob.sculpt;
SCULPT_vertex_random_access_ensure(&ss);
SculptCursorGeometryInfo sgi;
const float mval_fl[2] = {float(event->mval[0]), float(event->mval[1])};
int mval[2];
RNA_int_get_array(op.ptr, "location", mval);
/* TODO: Remove gesture_* properties from SculptSession */
ss.gesture_initial_hit = SCULPT_cursor_geometry_info_update(&C, &sgi, mval_fl, false);
if (ss.gesture_initial_hit) {
copy_v3_v3(ss.gesture_initial_location, sgi.location);
copy_v3_v3(ss.gesture_initial_normal, sgi.normal);
SculptCursorGeometryInfo sgi;
const float mval_fl[2] = {float(mval[0]), float(mval[1])};
TrimOperation *trim_operation = (TrimOperation *)gesture_data.operation;
trim_operation->initial_hit = SCULPT_cursor_geometry_info_update(&C, &sgi, mval_fl, false);
if (trim_operation->initial_hit) {
copy_v3_v3(trim_operation->initial_location, sgi.location);
copy_v3_v3(trim_operation->initial_normal, sgi.normal);
}
}
@ -701,7 +725,9 @@ static int gesture_box_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
initialize_cursor_info(*C, *op, *gesture_data);
init_operation(*gesture_data, *op);
gesture::apply(*C, *gesture_data, *op);
return OPERATOR_FINISHED;
}
@ -712,7 +738,7 @@ static int gesture_box_invoke(bContext *C, wmOperator *op, const wmEvent *event)
return OPERATOR_CANCELLED;
}
initialize_cursor_info(*C, event);
RNA_int_set_array(op->ptr, "location", event->mval);
return WM_gesture_box_invoke(C, op, event);
}
@ -727,7 +753,10 @@ static int gesture_lasso_exec(bContext *C, wmOperator *op)
if (!gesture_data) {
return OPERATOR_CANCELLED;
}
initialize_cursor_info(*C, *op, *gesture_data);
init_operation(*gesture_data, *op);
gesture::apply(*C, *gesture_data, *op);
return OPERATOR_FINISHED;
}
@ -738,7 +767,7 @@ static int gesture_lasso_invoke(bContext *C, wmOperator *op, const wmEvent *even
return OPERATOR_CANCELLED;
}
initialize_cursor_info(*C, event);
RNA_int_set_array(op->ptr, "location", event->mval);
return WM_gesture_lasso_invoke(C, op, event);
}

View File

@ -242,8 +242,10 @@ static void graph_main_region_draw(const bContext *C, ARegion *region)
graph_draw_curves(&ac, sipo, region, 1);
/* XXX(ton): the slow way to set tot rect... but for nice sliders needed. */
/* Excluding handles from the calculation to save performance. This cuts the time it takes for
* this function to run in half which is a major performance bottleneck on heavy scenes. */
get_graph_keyframe_extents(
&ac, &v2d->tot.xmin, &v2d->tot.xmax, &v2d->tot.ymin, &v2d->tot.ymax, false, true);
&ac, &v2d->tot.xmin, &v2d->tot.xmax, &v2d->tot.ymin, &v2d->tot.ymax, false, false);
/* extra offset so that these items are visible */
v2d->tot.xmin -= 10.0f;
v2d->tot.xmax += 10.0f;

View File

@ -2340,7 +2340,7 @@ void OUTLINER_OT_orphans_purge(wmOperatorType *ot)
RNA_def_boolean(ot->srna,
"do_recursive",
false,
true,
"Recursive Delete",
"Recursively check for indirectly unused data-blocks, ensuring that no orphaned "
"data-blocks remain after execution");

View File

@ -15,6 +15,7 @@
#include "BKE_report.hh"
#include "BLI_string.h"
#include "BLI_string_utils.hh"
#include "DEG_depsgraph_query.hh"
@ -72,14 +73,16 @@ void export_frame(Depsgraph *depsgraph,
/* If exporting in batch, create writer for each iteration over objects. */
if (export_params.use_batch) {
/* Get object name by skipping initial "OB" prefix. */
std::string object_name = (object->id.name + 2);
char object_name[sizeof(object->id.name) - 2];
STRNCPY(object_name, object->id.name + 2);
BLI_path_make_safe_filename(object_name);
/* Replace spaces with underscores. */
std::replace(object_name.begin(), object_name.end(), ' ', '_');
BLI_string_replace_char(object_name, ' ', '_');
/* Include object name in the exported file name. */
char filepath[FILE_MAX];
STRNCPY(filepath, export_params.filepath);
BLI_path_suffix(filepath, FILE_MAX, object_name.c_str(), "");
BLI_path_suffix(filepath, FILE_MAX, object_name, "");
/* Make sure we have .stl extension (case insensitive). */
if (!BLI_path_extension_check(filepath, ".stl")) {
BLI_path_extension_ensure(filepath, FILE_MAX, ".stl");

View File

@ -493,6 +493,16 @@ typedef struct bTheme {
/* NOTE: Values after `name` are copied when resetting the default theme. */
/**
* The file-path for the preset that was loaded into this theme.
*
* This is needed so it's possible to know if updating or removing a theme preset
* should apply changes to the current theme.
*
* #FILE_MAX.
*/
char filepath[1024];
ThemeUI tui;
/**

View File

@ -6333,7 +6333,7 @@ static void rna_def_scene_ffmpeg_settings(BlenderRNA *brna)
{AV_CODEC_ID_MPEG2VIDEO, "MPEG2", 0, "MPEG-2", ""},
{AV_CODEC_ID_MPEG4, "MPEG4", 0, "MPEG-4 (divx)", ""},
{AV_CODEC_ID_PNG, "PNG", 0, "PNG", ""},
{AV_CODEC_ID_QTRLE, "QTRLE", 0, "QT rle / QT Animation", ""},
{AV_CODEC_ID_QTRLE, "QTRLE", 0, "QuickTime Animation", ""},
{AV_CODEC_ID_THEORA, "THEORA", 0, "Theora", ""},
{AV_CODEC_ID_VP9, "WEBM", 0, "WebM / VP9", ""},
{AV_CODEC_ID_AV1, "AV1", 0, "AV1", ""},

View File

@ -4301,6 +4301,11 @@ static void rna_def_userdef_themes(BlenderRNA *brna)
/* XXX: for now putting this in presets is silly - its just Default */
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
prop = RNA_def_property(srna, "filepath", PROP_STRING, PROP_FILEPATH);
RNA_def_property_string_sdna(prop, nullptr, "filepath");
RNA_def_property_ui_text(
prop, "File Path", "The path to the preset loaded into this theme (if any)");
prop = RNA_def_property(srna, "theme_area", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, nullptr, "active_theme_area");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);

View File

@ -333,29 +333,10 @@ if(WITH_PYTHON_MODULE)
else()
add_executable(blender ${EXETYPE} ${SRC})
if(WITH_CPU_CHECK)
target_compile_definitions(blender PRIVATE WITH_CPU_CHECK)
# we cannot directly link against any blender libraries for the cpu_check module
# as they may have been build for an ISA that is unsupported by the CPU
# running this code.
add_library(blender_cpu_check SHARED
creator_cpu_check.cc
)
target_link_libraries(blender_cpu_check
PRIVATE ${PLATFORM_LINKLIBS}
)
# blender_cpu_check *NEEDS* to be linked first, there can be no exceptions
# to this, this is to ensure this will be the first code to run once the
# blender binary has been loaded by the OS.
target_link_libraries(blender PRIVATE blender_cpu_check)
if(NOT WIN32)
set(_LIB_SUB_FOLDER "lib/")
endif()
set_target_properties(blender_cpu_check
PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/${_LIB_SUB_FOLDER}"
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/${_LIB_SUB_FOLDER}"
)
unset(_LIB_SUB_FOLDER)
endif()
if(WIN32)
add_executable(blender-launcher WIN32

View File

@ -107,7 +107,7 @@ class MeshExportTest4(AbstractColladaTest):
outfile = tempdir / Path("%s_out.dae" % test)
bpy.ops.wm.collada_export(
filepath="%s" % str(outfile),
filepath=str(outfile),
check_existing=True,
filemode=8,
display_type='DEFAULT',
@ -151,7 +151,7 @@ class MeshExportTest3(AbstractColladaTest):
outfile = tempdir / Path("%s_out.dae" % test)
bpy.ops.wm.collada_export(
filepath="%s" % str(outfile),
filepath=str(outfile),
check_existing=True,
filemode=8,
display_type='DEFAULT',
@ -195,7 +195,7 @@ class MeshExportTest2(AbstractColladaTest):
outfile = tempdir / Path("%s_out.dae" % test)
bpy.ops.wm.collada_export(
filepath="%s" % str(outfile),
filepath=str(outfile),
check_existing=True,
filemode=8,
display_type='DEFAULT',
@ -239,7 +239,7 @@ class MeshExportTest1(AbstractColladaTest):
outfile = tempdir / Path("%s_out.dae" % test)
bpy.ops.wm.collada_export(
filepath="%s" % str(outfile),
filepath=str(outfile),
check_existing=True,
filemode=8,
display_type='DEFAULT',

View File

@ -107,7 +107,7 @@ class MeshExportTest(AbstractColladaTest):
outfile = tempdir / Path("%s_out.dae" % test)
bpy.ops.wm.collada_export(
filepath="%s" % str(outfile),
filepath=str(outfile),
check_existing=True,
filemode=8,
display_type="DEFAULT",

View File

@ -1638,7 +1638,7 @@ class edit_generators:
):
edits.append(Edit(
span=match.span(),
content='%s' % match.group(2),
content=match.group(2),
content_fail='__ALWAYS_FAIL__',
))