WIP: Experiment: Drop import operator helper and file drop type #111242

Closed
Guillermo Venegas wants to merge 23 commits from guishe/blender:drop-helper into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
181 changed files with 2466 additions and 2260 deletions
Showing only changes of commit 2b45a1ae4b - Show all commits

View File

@ -1638,7 +1638,7 @@ class CyclesPreferences(bpy.types.AddonPreferences):
elif device_type == 'ONEAPI':
import sys
if sys.platform.startswith("win"):
driver_version = "XX.X.101.4314"
driver_version = "XX.X.101.4644"
col.label(text="Requires Intel GPU with Xe-HPG architecture", icon='BLANK1')
col.label(text=iface_("and Windows driver version %s or newer") % driver_version,
icon='BLANK1', translate=False)

View File

@ -147,13 +147,14 @@ static inline void colorramp_to_array(BL::ColorRamp &ramp,
array<float> &ramp_alpha,
int size)
{
ramp_color.resize(size);
ramp_alpha.resize(size);
const int full_size = size + 1;
ramp_color.resize(full_size);
ramp_alpha.resize(full_size);
for (int i = 0; i < size; i++) {
for (int i = 0; i < full_size; i++) {
float color[4];
ramp.evaluate((float)i / (float)(size - 1), color);
ramp.evaluate(float(i) / float(size), color);
ramp_color[i] = make_float3(color[0], color[1], color[2]);
ramp_alpha[i] = color[3];
}
@ -183,9 +184,10 @@ static inline void curvemapping_to_array(BL::CurveMapping &cumap, array<float> &
{
cumap.update();
BL::CurveMap curve = cumap.curves[0];
data.resize(size);
for (int i = 0; i < size; i++) {
float t = (float)i / (float)(size - 1);
const int full_size = size + 1;
data.resize(full_size);
for (int i = 0; i < full_size; i++) {
float t = float(i) / float(size);
data[i] = cumap.evaluate(curve, t);
}
}
@ -204,10 +206,11 @@ static inline void curvemapping_float_to_array(BL::CurveMapping &cumap,
BL::CurveMap map = cumap.curves[0];
data.resize(size);
const int full_size = size + 1;
data.resize(full_size);
for (int i = 0; i < size; i++) {
float t = min + (float)i / (float)(size - 1) * range;
for (int i = 0; i < full_size; i++) {
float t = min + float(i) / float(size) * range;
data[i] = cumap.evaluate(map, t);
}
}
@ -241,20 +244,21 @@ static inline void curvemapping_color_to_array(BL::CurveMapping &cumap,
BL::CurveMap mapG = cumap.curves[1];
BL::CurveMap mapB = cumap.curves[2];
data.resize(size);
const int full_size = size + 1;
data.resize(full_size);
if (rgb_curve) {
BL::CurveMap mapI = cumap.curves[3];
for (int i = 0; i < size; i++) {
const float t = min_x + (float)i / (float)(size - 1) * range_x;
for (int i = 0; i < full_size; i++) {
const float t = min_x + float(i) / float(size) * range_x;
data[i] = make_float3(cumap.evaluate(mapR, cumap.evaluate(mapI, t)),
cumap.evaluate(mapG, cumap.evaluate(mapI, t)),
cumap.evaluate(mapB, cumap.evaluate(mapI, t)));
}
}
else {
for (int i = 0; i < size; i++) {
float t = min_x + (float)i / (float)(size - 1) * range_x;
for (int i = 0; i < full_size; i++) {
float t = min_x + float(i) / float(size) * range_x;
data[i] = make_float3(
cumap.evaluate(mapR, t), cumap.evaluate(mapG, t), cumap.evaluate(mapB, t));
}

View File

@ -853,10 +853,14 @@ void OneapiDevice::get_adjusted_global_and_local_sizes(SyclQueue *queue,
/* Compute-runtime (ie. NEO) version is what gets returned by sycl/L0 on Windows
* since Windows driver 101.3268. */
/* The same min compute-runtime version is currently used across Windows and Linux.
* For Windows driver 101.4314, compute-runtime version is 25977. */
static const int lowest_supported_driver_version_win = 1014314;
static const int lowest_supported_driver_version_win = 1014644;
# ifdef _WIN32
/* For Windows driver 101.4644, compute-runtime version is 26771.
* This information is returned by `ocloc query OCL_DRIVER_VERSION`.*/
static const int lowest_supported_driver_version_neo = 26771;
# else
static const int lowest_supported_driver_version_neo = 25812;
# endif
int OneapiDevice::parse_driver_build_version(const sycl::device &device)
{

View File

@ -857,8 +857,13 @@ if(WITH_CYCLES_DEVICE_ONEAPI)
-fsycl-max-parallel-link-jobs=${SYCL_OFFLINE_COMPILER_PARALLEL_JOBS}
-shared
-DWITH_ONEAPI
-ffast-math
-O2
-fno-fast-math
-ffp-contract=fast
-fassociative-math
-freciprocal-math
-fno-signed-zeros
-ffinite-math-only
-D__KERNEL_LOCAL_ATOMIC_SORT__
-o"${cycles_kernel_oneapi_lib}"
-I"${CMAKE_CURRENT_SOURCE_DIR}/.."

View File

@ -222,15 +222,9 @@ ccl_device_forceinline int __float_as_int(float x)
#define fmodf(x, y) sycl::fmod((x), (y))
#define lgammaf(x) sycl::lgamma((x))
/* `sycl::native::cos` precision is not sufficient and `-ffast-math` lets
* the current DPC++ compiler overload `sycl::cos` with it.
* We work around this issue by directly calling the SPIRV implementation which
* provides greater precision. */
#if defined(__SYCL_DEVICE_ONLY__) && defined(__SPIR__)
# define cosf(x) __spirv_ocl_cos(((float)(x)))
#else
# define cosf(x) sycl::cos(((float)(x)))
#endif
/* sycl::native::cos precision is not sufficient when using Nishita Sky node
* with a small sun size. */
#define cosf(x) sycl::cos(((float)(x)))
#define sinf(x) sycl::native::sin(((float)(x)))
#define powf(x, y) sycl::native::powr(((float)(x)), ((float)(y)))
#define tanf(x) sycl::native::tan(((float)(x)))

View File

@ -9,6 +9,8 @@
#define vector3 point
/* The fractalization logic is the same as for fBM Noise, except that some additions are replaced
* by lerps. */
#define FRACTAL_VORONOI_X_FX(T) \
VoronoiOutput fractal_voronoi_x_fx(VoronoiParams params, T coord) \
{ \
@ -20,7 +22,7 @@
Output.Distance = 0.0; \
Output.Color = color(0.0, 0.0, 0.0); \
Output.Position = vector4(0.0, 0.0, 0.0, 0.0); \
int zero_input = params.detail == 0.0 || params.roughness == 0.0 || params.lacunarity == 0.0; \
int zero_input = params.detail == 0.0 || params.roughness == 0.0; \
\
for (int i = 0; i <= ceil(params.detail); ++i) { \
VoronoiOutput octave; \
@ -71,6 +73,8 @@
return Output; \
}
/* The fractalization logic is the same as for fBM Noise, except that some additions are replaced
* by lerps. */
#define FRACTAL_VORONOI_DISTANCE_TO_EDGE_FUNCTION(T) \
float fractal_voronoi_distance_to_edge(VoronoiParams params, T coord) \
{ \
@ -79,7 +83,7 @@
float scale = 1.0; \
float distance = 8.0; \
\
int zero_input = params.detail == 0.0 || params.roughness == 0.0 || params.lacunarity == 0.0; \
int zero_input = params.detail == 0.0 || params.roughness == 0.0; \
\
for (int i = 0; i <= ceil(params.detail); ++i) { \
float octave_distance = voronoi_distance_to_edge(params, coord * scale); \

View File

@ -880,6 +880,8 @@ ccl_device float voronoi_n_sphere_radius(ccl_private const VoronoiParams &params
/* **** Fractal Voronoi **** */
/* The fractalization logic is the same as for fBM Noise, except that some additions are replaced
* by lerps. */
template<typename T>
ccl_device VoronoiOutput fractal_voronoi_x_fx(ccl_private const VoronoiParams &params,
const T coord)
@ -889,8 +891,7 @@ ccl_device VoronoiOutput fractal_voronoi_x_fx(ccl_private const VoronoiParams &p
float scale = 1.0f;
VoronoiOutput output;
const bool zero_input = params.detail == 0.0f || params.roughness == 0.0f ||
params.lacunarity == 0.0f;
const bool zero_input = params.detail == 0.0f || params.roughness == 0.0f;
for (int i = 0; i <= ceilf(params.detail); ++i) {
VoronoiOutput octave = (params.feature == NODE_VORONOI_F2) ?
@ -936,6 +937,8 @@ ccl_device VoronoiOutput fractal_voronoi_x_fx(ccl_private const VoronoiParams &p
return output;
}
/* The fractalization logic is the same as for fBM Noise, except that some additions are replaced
* by lerps. */
template<typename T>
ccl_device float fractal_voronoi_distance_to_edge(ccl_private const VoronoiParams &params,
const T coord)
@ -945,8 +948,7 @@ ccl_device float fractal_voronoi_distance_to_edge(ccl_private const VoronoiParam
float scale = 1.0f;
float distance = 8.0f;
const bool zero_input = params.detail == 0.0f || params.roughness == 0.0f ||
params.lacunarity == 0.0f;
const bool zero_input = params.detail == 0.0f || params.roughness == 0.0f;
for (int i = 0; i <= ceilf(params.detail); ++i) {
const float octave_distance = voronoi_distance_to_edge(params, coord * scale);

View File

@ -285,6 +285,13 @@ def load_scripts(*, reload_scripts=False, refresh_scripts=False):
del _global_loaded_modules[:]
# Update key-maps to account for operators no longer existing.
# Typically unloading operators would refresh the event system (such as disabling an add-on)
# however reloading scripts re-enable all add-ons immediately (which may inspect key-maps).
# For this reason it's important to update key-maps which will have been tagged to update.
# Without this, add-on register functions accessing key-map properties can crash, see: #111702.
_bpy.context.window_manager.keyconfigs.update()
from bpy_restrict_state import RestrictBlend
with RestrictBlend():

View File

@ -5,41 +5,79 @@
import bpy
from bpy.types import Menu
from bl_ui import node_add_menu
from bpy.app.translations import (
pgettext_iface as iface_,
)
class NODE_MT_category_COMP_INPUT(Menu):
bl_idname = "NODE_MT_category_COMP_INPUT"
bl_label = "Input"
def draw(self, _context):
def draw(self, context):
snode = context.space_data
is_group = (len(snode.path) > 1)
layout = self.layout
layout.menu("NODE_MT_category_COMP_INPUT_CONSTANT")
layout.separator()
node_add_menu.add_node_type(layout, "CompositorNodeBokehImage")
node_add_menu.add_node_type(layout, "CompositorNodeImage")
node_add_menu.add_node_type(layout, "CompositorNodeMask")
node_add_menu.add_node_type(layout, "CompositorNodeMovieClip")
node_add_menu.add_node_type(layout, "CompositorNodeRLayers")
node_add_menu.add_node_type(layout, "CompositorNodeRGB")
node_add_menu.add_node_type(layout, "CompositorNodeSceneTime")
node_add_menu.add_node_type(layout, "CompositorNodeTexture")
node_add_menu.add_node_type(layout, "CompositorNodeTime")
node_add_menu.add_node_type(layout, "CompositorNodeTrackPos")
if is_group:
layout.separator()
node_add_menu.add_node_type(layout, "NodeGroupInput")
layout.separator()
layout.menu("NODE_MT_category_COMP_INPUT_SCENE")
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
class NODE_MT_category_COMP_INPUT_CONSTANT(Menu):
bl_idname = "NODE_MT_category_COMP_INPUT_CONSTANT"
bl_label = "Constant"
def draw(self, _context):
layout = self.layout
node_add_menu.add_node_type(layout, "CompositorNodeRGB")
node_add_menu.add_node_type(layout, "CompositorNodeValue")
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
class NODE_MT_category_COMP_INPUT_SCENE(Menu):
bl_idname = "NODE_MT_category_COMP_INPUT_SCENE"
bl_label = "Scene"
def draw(self, _context):
layout = self.layout
node_add_menu.add_node_type(layout, "CompositorNodeRLayers")
node_add_menu.add_node_type(layout, "CompositorNodeSceneTime")
node_add_menu.add_node_type(layout, "CompositorNodeTime")
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
class NODE_MT_category_COMP_OUTPUT(Menu):
bl_idname = "NODE_MT_category_COMP_OUTPUT"
bl_label = "Output"
def draw(self, _context):
layout = self.layout
def draw(self, context):
snode = context.space_data
is_group = (len(snode.path) > 1)
layout = self.layout
node_add_menu.add_node_type(layout, "CompositorNodeComposite")
node_add_menu.add_node_type(layout, "CompositorNodeOutputFile")
node_add_menu.add_node_type(layout, "CompositorNodeLevels")
node_add_menu.add_node_type(layout, "CompositorNodeSplitViewer")
node_add_menu.add_node_type(layout, "CompositorNodeViewer")
layout.separator()
node_add_menu.add_node_type(layout, "CompositorNodeOutputFile")
if is_group:
layout.separator()
node_add_menu.add_node_type(layout, "NodeGroupOutput")
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
@ -50,7 +88,27 @@ class NODE_MT_category_COMP_COLOR(Menu):
def draw(self, _context):
layout = self.layout
node_add_menu.add_node_type(layout, "CompositorNodeAlphaOver")
layout.menu("NODE_MT_category_COMP_COLOR_ADJUST")
layout.separator()
layout.menu("NODE_MT_category_COMP_COLOR_MIX")
layout.separator()
node_add_menu.add_node_type(layout, "CompositorNodePremulKey")
node_add_menu.add_node_type(layout, "CompositorNodeValToRGB")
node_add_menu.add_node_type(layout, "CompositorNodeConvertColorSpace")
node_add_menu.add_node_type(layout, "CompositorNodeSetAlpha")
layout.separator()
node_add_menu.add_node_type(layout, "CompositorNodeInvert")
node_add_menu.add_node_type(layout, "CompositorNodeRGBToBW")
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
class NODE_MT_category_COMP_COLOR_ADJUST(Menu):
bl_idname = "NODE_MT_category_COMP_COLOR_ADJUST"
bl_label = "Adjust"
def draw(self, _context):
layout = self.layout
node_add_menu.add_node_type(layout, "CompositorNodeBrightContrast")
node_add_menu.add_node_type(layout, "CompositorNodeColorBalance")
node_add_menu.add_node_type(layout, "CompositorNodeColorCorrection")
@ -58,35 +116,27 @@ class NODE_MT_category_COMP_COLOR(Menu):
node_add_menu.add_node_type(layout, "CompositorNodeGamma")
node_add_menu.add_node_type(layout, "CompositorNodeHueCorrect")
node_add_menu.add_node_type(layout, "CompositorNodeHueSat")
node_add_menu.add_node_type(layout, "CompositorNodeInvert")
node_add_menu.add_node_type(layout, "CompositorNodeMixRGB")
node_add_menu.add_node_type(layout, "CompositorNodePosterize")
node_add_menu.add_node_type(layout, "CompositorNodeCurveRGB")
node_add_menu.add_node_type(layout, "CompositorNodeTonemap")
node_add_menu.add_node_type(layout, "CompositorNodeZcombine")
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
class NODE_MT_category_COMP_CONVERTER(Menu):
bl_idname = "NODE_MT_category_COMP_CONVERTER"
bl_label = "Converter"
class NODE_MT_category_COMP_COLOR_MIX(Menu):
bl_idname = "NODE_MT_category_COMP_COLOR_MIX"
bl_label = "Mix"
def draw(self, _context):
layout = self.layout
node_add_menu.add_node_type(layout, "CompositorNodePremulKey")
node_add_menu.add_node_type(layout, "CompositorNodeValToRGB")
node_add_menu.add_node_type(layout, "CompositorNodeAlphaOver")
layout.separator()
node_add_menu.add_node_type(layout, "CompositorNodeCombineColor")
node_add_menu.add_node_type(layout, "CompositorNodeCombineXYZ")
node_add_menu.add_node_type(layout, "CompositorNodeConvertColorSpace")
node_add_menu.add_node_type(layout, "CompositorNodeIDMask")
node_add_menu.add_node_type(layout, "CompositorNodeMath")
node_add_menu.add_node_type(layout, "CompositorNodeRGBToBW")
node_add_menu.add_node_type(layout, "CompositorNodeSeparateColor")
node_add_menu.add_node_type(layout, "CompositorNodeSeparateXYZ")
node_add_menu.add_node_type(layout, "CompositorNodeSetAlpha")
node_add_menu.add_node_type(layout, "CompositorNodeSwitchView")
layout.separator()
node_add_menu.add_node_type(
layout, "CompositorNodeMixRGB",
label=iface_("Mix Color"))
node_add_menu.add_node_type(layout, "CompositorNodeZcombine")
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
@ -96,91 +146,41 @@ class NODE_MT_category_COMP_FILTER(Menu):
def draw(self, _context):
layout = self.layout
layout.menu("NODE_MT_category_COMP_FILTER_BLUR")
layout.separator()
node_add_menu.add_node_type(layout, "CompositorNodeAntiAliasing")
node_add_menu.add_node_type(layout, "CompositorNodeDenoise")
node_add_menu.add_node_type(layout, "CompositorNodeDespeckle")
layout.separator()
node_add_menu.add_node_type(layout, "CompositorNodeDilateErode")
node_add_menu.add_node_type(layout, "CompositorNodeInpaint")
layout.separator()
node_add_menu.add_node_type(layout, "CompositorNodeFilter")
node_add_menu.add_node_type(layout, "CompositorNodeGlare")
node_add_menu.add_node_type(layout, "CompositorNodeKuwahara")
node_add_menu.add_node_type(layout, "CompositorNodePixelate")
node_add_menu.add_node_type(layout, "CompositorNodePosterize")
node_add_menu.add_node_type(layout, "CompositorNodeSunBeams")
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
class NODE_MT_category_COMP_FILTER_BLUR(Menu):
bl_idname = "NODE_MT_category_COMP_FILTER_BLUR"
bl_label = "Blur"
def draw(self, _context):
layout = self.layout
node_add_menu.add_node_type(layout, "CompositorNodeBilateralblur")
node_add_menu.add_node_type(layout, "CompositorNodeBlur")
node_add_menu.add_node_type(layout, "CompositorNodeBokehBlur")
node_add_menu.add_node_type(layout, "CompositorNodeDefocus")
node_add_menu.add_node_type(layout, "CompositorNodeDenoise")
node_add_menu.add_node_type(layout, "CompositorNodeDespeckle")
node_add_menu.add_node_type(layout, "CompositorNodeDilateErode")
node_add_menu.add_node_type(layout, "CompositorNodeDBlur")
node_add_menu.add_node_type(layout, "CompositorNodeFilter")
node_add_menu.add_node_type(layout, "CompositorNodeGlare")
node_add_menu.add_node_type(layout, "CompositorNodeInpaint")
node_add_menu.add_node_type(layout, "CompositorNodeKuwahara")
node_add_menu.add_node_type(layout, "CompositorNodePixelate")
node_add_menu.add_node_type(layout, "CompositorNodeSunBeams")
node_add_menu.add_node_type(layout, "CompositorNodeVecBlur")
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
class NODE_MT_category_COMP_VECTOR(Menu):
bl_idname = "NODE_MT_category_COMP_VECTOR"
bl_label = "Vector"
def draw(self, _context):
layout = self.layout
node_add_menu.add_node_type(layout, "CompositorNodeMapRange")
node_add_menu.add_node_type(layout, "CompositorNodeMapValue")
node_add_menu.add_node_type(layout, "CompositorNodeNormal")
node_add_menu.add_node_type(layout, "CompositorNodeNormalize")
node_add_menu.add_node_type(layout, "CompositorNodeCurveVec")
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
class NODE_MT_category_COMP_MATTE(Menu):
bl_idname = "NODE_MT_category_COMP_MATTE"
bl_label = "Matte"
def draw(self, _context):
layout = self.layout
node_add_menu.add_node_type(layout, "CompositorNodeBoxMask")
node_add_menu.add_node_type(layout, "CompositorNodeChannelMatte")
node_add_menu.add_node_type(layout, "CompositorNodeChromaMatte")
node_add_menu.add_node_type(layout, "CompositorNodeColorMatte")
node_add_menu.add_node_type(layout, "CompositorNodeColorSpill")
node_add_menu.add_node_type(layout, "CompositorNodeCryptomatteV2")
node_add_menu.add_node_type(layout, "CompositorNodeCryptomatte")
node_add_menu.add_node_type(layout, "CompositorNodeDiffMatte")
node_add_menu.add_node_type(layout, "CompositorNodeDistanceMatte")
node_add_menu.add_node_type(layout, "CompositorNodeDoubleEdgeMask")
node_add_menu.add_node_type(layout, "CompositorNodeEllipseMask")
node_add_menu.add_node_type(layout, "CompositorNodeKeying")
node_add_menu.add_node_type(layout, "CompositorNodeKeyingScreen")
node_add_menu.add_node_type(layout, "CompositorNodeLumaMatte")
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
class NODE_MT_category_COMP_DISTORT(Menu):
bl_idname = "NODE_MT_category_COMP_DISTORT"
bl_label = "Distort"
def draw(self, _context):
layout = self.layout
node_add_menu.add_node_type(layout, "CompositorNodeCornerPin")
node_add_menu.add_node_type(layout, "CompositorNodeCrop")
node_add_menu.add_node_type(layout, "CompositorNodeDisplace")
node_add_menu.add_node_type(layout, "CompositorNodeFlip")
node_add_menu.add_node_type(layout, "CompositorNodeLensdist")
node_add_menu.add_node_type(layout, "CompositorNodeMapUV")
node_add_menu.add_node_type(layout, "CompositorNodeMovieDistortion")
node_add_menu.add_node_type(layout, "CompositorNodePlaneTrackDeform")
node_add_menu.add_node_type(layout, "CompositorNodeRotate")
node_add_menu.add_node_type(layout, "CompositorNodeScale")
node_add_menu.add_node_type(layout, "CompositorNodeStabilize")
node_add_menu.add_node_type(layout, "CompositorNodeTransform")
node_add_menu.add_node_type(layout, "CompositorNodeTranslate")
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
class NODE_MT_category_COMP_GROUP(Menu):
bl_idname = "NODE_MT_category_COMP_GROUP"
bl_label = "Group"
@ -191,6 +191,116 @@ class NODE_MT_category_COMP_GROUP(Menu):
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
class NODE_MT_category_COMP_KEYING(Menu):
bl_idname = "NODE_MT_category_COMP_KEYING"
bl_label = "Keying"
def draw(self, _context):
layout = self.layout
node_add_menu.add_node_type(layout, "CompositorNodeChannelMatte")
node_add_menu.add_node_type(layout, "CompositorNodeChromaMatte")
node_add_menu.add_node_type(layout, "CompositorNodeColorMatte")
node_add_menu.add_node_type(layout, "CompositorNodeColorSpill")
node_add_menu.add_node_type(layout, "CompositorNodeDiffMatte")
node_add_menu.add_node_type(layout, "CompositorNodeDistanceMatte")
node_add_menu.add_node_type(layout, "CompositorNodeKeying")
node_add_menu.add_node_type(layout, "CompositorNodeKeyingScreen")
node_add_menu.add_node_type(layout, "CompositorNodeLumaMatte")
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
class NODE_MT_category_COMP_MASK(Menu):
bl_idname = "NODE_MT_category_COMP_MASK"
bl_label = "Mask"
def draw(self, _context):
layout = self.layout
node_add_menu.add_node_type(layout, "CompositorNodeCryptomatteV2")
node_add_menu.add_node_type(layout, "CompositorNodeCryptomatte")
layout.separator()
node_add_menu.add_node_type(layout, "CompositorNodeBoxMask")
node_add_menu.add_node_type(layout, "CompositorNodeEllipseMask")
layout.separator()
node_add_menu.add_node_type(layout, "CompositorNodeDoubleEdgeMask")
node_add_menu.add_node_type(layout, "CompositorNodeIDMask")
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
class NODE_MT_category_COMP_TRACKING(Menu):
bl_idname = "NODE_MT_category_COMP_TRACKING"
bl_label = "Tracking"
def draw(self, _context):
layout = self.layout
node_add_menu.add_node_type(layout, "CompositorNodePlaneTrackDeform")
node_add_menu.add_node_type(layout, "CompositorNodeStabilize")
node_add_menu.add_node_type(layout, "CompositorNodeTrackPos")
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
class NODE_MT_category_COMP_TRANSFORM(Menu):
bl_idname = "NODE_MT_category_COMP_TRANSFORM"
bl_label = "Transform"
def draw(self, _context):
layout = self.layout
node_add_menu.add_node_type(layout, "CompositorNodeRotate")
node_add_menu.add_node_type(layout, "CompositorNodeScale")
node_add_menu.add_node_type(layout, "CompositorNodeTransform")
node_add_menu.add_node_type(layout, "CompositorNodeTranslate")
layout.separator()
node_add_menu.add_node_type(layout, "CompositorNodeCornerPin")
node_add_menu.add_node_type(layout, "CompositorNodeCrop")
layout.separator()
node_add_menu.add_node_type(layout, "CompositorNodeDisplace")
node_add_menu.add_node_type(layout, "CompositorNodeFlip")
node_add_menu.add_node_type(layout, "CompositorNodeMapUV")
layout.separator()
node_add_menu.add_node_type(layout, "CompositorNodeLensdist")
node_add_menu.add_node_type(layout, "CompositorNodeMovieDistortion")
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
class NODE_MT_category_COMP_UTIL(Menu):
bl_idname = "NODE_MT_category_COMP_UTIL"
bl_label = "Utilities"
def draw(self, _context):
layout = self.layout
node_add_menu.add_node_type(layout, "CompositorNodeMapRange")
node_add_menu.add_node_type(layout, "CompositorNodeMapValue")
node_add_menu.add_node_type(layout, "CompositorNodeMath")
layout.separator()
node_add_menu.add_node_type(layout, "CompositorNodeLevels")
node_add_menu.add_node_type(layout, "CompositorNodeNormalize")
layout.separator()
node_add_menu.add_node_type(layout, "CompositorNodeSwitch")
node_add_menu.add_node_type(
layout, "CompositorNodeSwitchView",
label=iface_("Switch Stereo View"))
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
class NODE_MT_category_COMP_VECTOR(Menu):
bl_idname = "NODE_MT_category_COMP_VECTOR"
bl_label = "Vector"
def draw(self, _context):
layout = self.layout
node_add_menu.add_node_type(layout, "CompositorNodeCombineXYZ")
node_add_menu.add_node_type(layout, "CompositorNodeSeparateXYZ")
layout.separator()
node_add_menu.add_node_type(layout, "CompositorNodeNormal")
node_add_menu.add_node_type(layout, "CompositorNodeCurveVec")
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
class NODE_MT_category_COMP_LAYOUT(Menu):
bl_idname = "NODE_MT_category_COMP_LAYOUT"
bl_label = "Layout"
@ -213,10 +323,15 @@ class NODE_MT_compositing_node_add_all(Menu):
layout.menu("NODE_MT_category_COMP_OUTPUT")
layout.separator()
layout.menu("NODE_MT_category_COMP_COLOR")
layout.menu("NODE_MT_category_COMP_CONVERTER")
layout.menu("NODE_MT_category_COMP_DISTORT")
layout.menu("NODE_MT_category_COMP_FILTER")
layout.menu("NODE_MT_category_COMP_MATTE")
layout.separator()
layout.menu("NODE_MT_category_COMP_KEYING")
layout.menu("NODE_MT_category_COMP_MASK")
layout.separator()
layout.menu("NODE_MT_category_COMP_TRACKING")
layout.separator()
layout.menu("NODE_MT_category_COMP_TRANSFORM")
layout.menu("NODE_MT_category_COMP_UTIL")
layout.menu("NODE_MT_category_COMP_VECTOR")
layout.separator()
layout.menu("NODE_MT_category_COMP_GROUP")
@ -228,13 +343,20 @@ class NODE_MT_compositing_node_add_all(Menu):
classes = (
NODE_MT_compositing_node_add_all,
NODE_MT_category_COMP_INPUT,
NODE_MT_category_COMP_INPUT_CONSTANT,
NODE_MT_category_COMP_INPUT_SCENE,
NODE_MT_category_COMP_OUTPUT,
NODE_MT_category_COMP_COLOR,
NODE_MT_category_COMP_CONVERTER,
NODE_MT_category_COMP_COLOR_ADJUST,
NODE_MT_category_COMP_COLOR_MIX,
NODE_MT_category_COMP_FILTER,
NODE_MT_category_COMP_FILTER_BLUR,
NODE_MT_category_COMP_KEYING,
NODE_MT_category_COMP_MASK,
NODE_MT_category_COMP_TRACKING,
NODE_MT_category_COMP_TRANSFORM,
NODE_MT_category_COMP_UTIL,
NODE_MT_category_COMP_VECTOR,
NODE_MT_category_COMP_MATTE,
NODE_MT_category_COMP_DISTORT,
NODE_MT_category_COMP_GROUP,
NODE_MT_category_COMP_LAYOUT,
)

View File

@ -224,12 +224,6 @@ class BONE_PT_relations(BoneButtonsPanel, Panel):
bone = context.edit_bone
col = layout.column()
col.use_property_split = False
col.prop(bone, "layers", text="")
col.use_property_split = True
col = layout.column()
col.separator()
if context.bone:
col.prop(bone, "parent")

View File

@ -302,6 +302,7 @@ class GRAPH_MT_key_blending(Menu):
layout.operator("graph.blend_offset", text="Blend Offset")
layout.operator("graph.blend_to_ease", text="Blend to Ease")
layout.operator("graph.match_slope", text="Match Slope")
layout.operator("graph.shear", text="Shear Keys")
class GRAPH_MT_key_smoothing(Menu):

View File

@ -2593,14 +2593,20 @@ class SEQUENCER_PT_modifiers(SequencerButtonsPanel, Panel):
col = flow.column()
box = col.box()
split = box.split(factor=0.4)
split.label(text = "{:.2f}".format(soundEq.curve_mapping.clip_min_x))
split.label(text = "Hz")
split.label(text="{:.2f}".format(soundEq.curve_mapping.clip_min_x))
split.label(text="Hz")
split.alignment = "RIGHT"
split.label(text = "{:.2f}".format(soundEq.curve_mapping.clip_max_x))
box.template_curve_mapping(soundEq, "curve_mapping",
type='NONE', levels=False, brush=True, use_negative_slope=True, show_tone=False)
split.label(text="{:.2f}".format(soundEq.curve_mapping.clip_max_x))
box.template_curve_mapping(
soundEq,
"curve_mapping",
type='NONE',
levels=False,
brush=True,
use_negative_slope=True,
show_tone=False)
second_row = col.row()
second_row.label(text = "dB")
second_row.label(text="dB")
second_row.alignment = "CENTER"

View File

@ -123,21 +123,13 @@ class TIME_MT_view(Menu):
scene = context.scene
st = context.space_data
layout.prop(st, "show_region_hud")
layout.menu("INFO_MT_area")
layout.separator()
layout.prop(st, "show_seconds")
layout.prop(st, "show_locked_time")
layout.separator()
layout.prop(st, "show_markers")
layout.separator()
layout.prop(scene, "show_keys_from_selected_only")
layout.prop(st.dopesheet, "show_only_errors")
# NOTE: "action" now, since timeline is in the dopesheet editor, instead of as own editor
layout.operator("action.view_frame")
layout.operator("action.view_all")
layout.separator()
@ -145,13 +137,21 @@ class TIME_MT_view(Menu):
layout.separator()
# NOTE: "action" now, since timeline is in the dopesheet editor, instead of as own editor
layout.operator("action.view_all")
layout.operator("action.view_frame")
layout.prop(st.dopesheet, "show_only_errors")
layout.prop(scene, "show_keys_from_selected_only")
layout.separator()
layout.menu("INFO_MT_area")
layout.prop(st, "show_markers")
layout.separator()
layout.prop(st, "show_locked_time")
layout.prop(st, "show_seconds")
layout.separator()
layout.prop(st, "show_region_hud")
class TIME_MT_cache(Menu):
@ -182,27 +182,14 @@ def marker_menu_generic(layout, context):
# layout.operator_context = 'EXEC_REGION_WIN'
layout.column()
layout.operator("marker.add", text="Add Marker")
layout.operator("marker.duplicate", text="Duplicate Marker")
if len(bpy.data.scenes) > 10:
layout.operator_context = 'INVOKE_DEFAULT'
layout.operator("marker.make_links_scene", text="Duplicate Marker to Scene...", icon='OUTLINER_OB_EMPTY')
else:
layout.operator_menu_enum("marker.make_links_scene", "scene", text="Duplicate Marker to Scene")
layout.operator("marker.delete", text="Delete Marker")
tool_settings = context.tool_settings
layout.prop(tool_settings, "lock_markers")
layout.separator()
props = layout.operator("wm.call_panel", text="Rename Marker")
props.name = "TOPBAR_PT_name_marker"
props.keep_open = False
layout.operator("marker.move", text="Move Marker")
layout.separator()
layout.menu('NLA_MT_marker_select')
layout.operator("screen.marker_jump", text="Jump to Previous Marker").next = False
layout.operator("screen.marker_jump", text="Jump to Next Marker").next = True
layout.separator()
@ -210,12 +197,28 @@ def marker_menu_generic(layout, context):
layout.separator()
layout.operator("screen.marker_jump", text="Jump to Next Marker").next = True
layout.operator("screen.marker_jump", text="Jump to Previous Marker").next = False
layout.menu('NLA_MT_marker_select')
layout.separator()
tool_settings = context.tool_settings
layout.prop(tool_settings, "lock_markers")
layout.operator("marker.move", text="Move Marker")
props = layout.operator("wm.call_panel", text="Rename Marker")
props.name = "TOPBAR_PT_name_marker"
props.keep_open = False
layout.separator()
layout.operator("marker.delete", text="Delete Marker")
if len(bpy.data.scenes) > 10:
layout.operator_context = 'INVOKE_DEFAULT'
layout.operator("marker.make_links_scene", text="Duplicate Marker to Scene...", icon='OUTLINER_OB_EMPTY')
else:
layout.operator_menu_enum("marker.make_links_scene", "scene", text="Duplicate Marker to Scene")
layout.operator("marker.duplicate", text="Duplicate Marker")
layout.operator("marker.add", text="Add Marker")
###################################

View File

@ -923,23 +923,23 @@ class USERPREF_PT_theme_interface_state(ThemePanel, CenterAlignMixIn, Panel):
col = flow.column(align=True)
col.prop(ui_state, "inner_anim")
col.prop(ui_state, "inner_anim_sel")
col.prop(ui_state, "inner_anim_sel", text="Selected")
col = flow.column(align=True)
col.prop(ui_state, "inner_driven")
col.prop(ui_state, "inner_driven_sel")
col.prop(ui_state, "inner_driven_sel", text="Selected")
col = flow.column(align=True)
col.prop(ui_state, "inner_key")
col.prop(ui_state, "inner_key_sel")
col.prop(ui_state, "inner_key_sel", text="Selected")
col = flow.column(align=True)
col.prop(ui_state, "inner_overridden")
col.prop(ui_state, "inner_overridden_sel")
col.prop(ui_state, "inner_overridden_sel", text="Selected")
col = flow.column(align=True)
col.prop(ui_state, "inner_changed")
col.prop(ui_state, "inner_changed_sel")
col.prop(ui_state, "inner_changed_sel", text="Selected")
col = flow.column(align=True)
col.prop(ui_state, "blend")
@ -956,14 +956,19 @@ class USERPREF_PT_theme_interface_styles(ThemePanel, CenterAlignMixIn, Panel):
flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
flow.prop(ui, "menu_shadow_fac")
flow.prop(ui, "menu_shadow_width")
flow.prop(ui, "icon_alpha")
flow.prop(ui, "icon_saturation")
flow.prop(ui, "editor_outline")
flow.prop(ui, "widget_text_cursor")
flow.prop(ui, "widget_emboss")
flow.prop(ui, "panel_roundness")
col = flow.column(align=True)
col.prop(ui, "menu_shadow_fac")
col.prop(ui, "menu_shadow_width", text="Shadow Width")
col = flow.column(align=True)
col.prop(ui, "icon_alpha")
col.prop(ui, "icon_saturation", text="Saturation")
col = flow.column()
col.prop(ui, "widget_text_cursor")
col.prop(ui, "editor_outline")
col.prop(ui, "widget_emboss")
col.prop(ui, "panel_roundness")
class USERPREF_PT_theme_interface_transparent_checker(ThemePanel, CenterAlignMixIn, Panel):
@ -978,9 +983,12 @@ class USERPREF_PT_theme_interface_transparent_checker(ThemePanel, CenterAlignMix
flow = layout.grid_flow(
row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
flow.prop(ui, "transparent_checker_primary")
flow.prop(ui, "transparent_checker_secondary")
flow.prop(ui, "transparent_checker_size")
col = flow.column(align=True)
col.prop(ui, "transparent_checker_primary")
col.prop(ui, "transparent_checker_secondary")
col = flow.column()
col.prop(ui, "transparent_checker_size")
class USERPREF_PT_theme_interface_gizmos(ThemePanel, CenterAlignMixIn, Panel):
@ -1001,12 +1009,12 @@ class USERPREF_PT_theme_interface_gizmos(ThemePanel, CenterAlignMixIn, Panel):
col = flow.column()
col.prop(ui, "gizmo_primary")
col.prop(ui, "gizmo_secondary")
col.prop(ui, "gizmo_view_align")
col.prop(ui, "gizmo_secondary", text="Secondary")
col.prop(ui, "gizmo_view_align", text="View Align")
col = flow.column()
col.prop(ui, "gizmo_a")
col.prop(ui, "gizmo_b")
col.prop(ui, "gizmo_b", text="B")
class USERPREF_PT_theme_interface_icons(ThemePanel, CenterAlignMixIn, Panel):
@ -1037,7 +1045,7 @@ class USERPREF_PT_theme_text_style(ThemePanel, CenterAlignMixIn, Panel):
@staticmethod
def _ui_font_style(layout, font_style):
layout.use_property_split = True
flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=True)
flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
col = flow.column()
col.prop(font_style, "points")
@ -1046,10 +1054,10 @@ class USERPREF_PT_theme_text_style(ThemePanel, CenterAlignMixIn, Panel):
col.prop(font_style, "shadow_offset_x", text="Shadow Offset X")
col.prop(font_style, "shadow_offset_y", text="Y")
col = flow.column()
col = flow.column(align=True)
col.prop(font_style, "shadow")
col.prop(font_style, "shadow_alpha")
col.prop(font_style, "shadow_value")
col.prop(font_style, "shadow_alpha", text="Alpha")
col.prop(font_style, "shadow_value", text="Brightness")
def draw_header(self, _context):
layout = self.layout
@ -1090,10 +1098,10 @@ class USERPREF_PT_theme_bone_color_sets(ThemePanel, CenterAlignMixIn, Panel):
for i, ui in enumerate(theme.bone_color_sets, 1):
layout.label(text=iface_("Color Set %d") % i, translate=False)
flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=True)
flow.prop(ui, "normal")
flow.prop(ui, "select")
flow.prop(ui, "select", text="Selected")
flow.prop(ui, "active")
flow.prop(ui, "show_colored_constraints")
@ -1112,7 +1120,7 @@ class USERPREF_PT_theme_collection_colors(ThemePanel, CenterAlignMixIn, Panel):
layout.use_property_split = True
flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
flow = layout.grid_flow(row_major=False, columns=2, even_columns=True, even_rows=False, align=False)
for i, ui in enumerate(theme.collection_color, 1):
flow.prop(ui, "color", text=iface_("Color %d") % i, translate=False)
@ -1131,7 +1139,7 @@ class USERPREF_PT_theme_strip_colors(ThemePanel, CenterAlignMixIn, Panel):
layout.use_property_split = True
flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
flow = layout.grid_flow(row_major=False, columns=2, even_columns=True, even_rows=False, align=False)
for i, ui in enumerate(theme.strip_color, 1):
flow.prop(ui, "color", text=iface_("Color %d") % i, translate=False)
@ -1217,28 +1225,28 @@ class ThemeGenericClassGenerator:
@staticmethod
def generate_panel_classes_for_wcols():
wcols = [
("Box", "wcol_box"),
("List Item", "wcol_list_item"),
("Menu", "wcol_menu"),
("Menu Background", "wcol_menu_back"),
("Menu Item", "wcol_menu_item"),
("Number Field", "wcol_num"),
("Option", "wcol_option"),
("Pie Menu", "wcol_pie_menu"),
("Progress Bar", "wcol_progress"),
("Pulldown", "wcol_pulldown"),
("Radio Buttons", "wcol_radio"),
("Regular", "wcol_regular"),
("Scroll Bar", "wcol_scroll"),
("Tab", "wcol_tab"),
("Text", "wcol_text"),
("Toggle", "wcol_toggle"),
("Tool", "wcol_tool"),
("Toolbar Item", "wcol_toolbar_item"),
("Radio Buttons", "wcol_radio"),
("Text", "wcol_text"),
("Option", "wcol_option"),
("Toggle", "wcol_toggle"),
("Number Field", "wcol_num"),
("Value Slider", "wcol_numslider"),
("Box", "wcol_box"),
("Menu", "wcol_menu"),
("Pie Menu", "wcol_pie_menu"),
("Pulldown", "wcol_pulldown"),
("Menu Back", "wcol_menu_back"),
("Tooltip", "wcol_tooltip"),
("Menu Item", "wcol_menu_item"),
("Scroll Bar", "wcol_scroll"),
("Progress Bar", "wcol_progress"),
("List Item", "wcol_list_item"),
("Value Slider", "wcol_numslider"),
# Not used yet, so hide this from the UI.
# ("Data-View Item", "wcol_view_item"),
("Tab", "wcol_tab"),
]
for (name, wcol) in wcols:
@ -2588,11 +2596,11 @@ classes = (
USERPREF_MT_interface_theme_presets,
USERPREF_PT_theme,
USERPREF_PT_theme_interface_gizmos,
USERPREF_PT_theme_interface_icons,
USERPREF_PT_theme_interface_state,
USERPREF_PT_theme_interface_styles,
USERPREF_PT_theme_interface_gizmos,
USERPREF_PT_theme_interface_transparent_checker,
USERPREF_PT_theme_interface_icons,
USERPREF_PT_theme_text_style,
USERPREF_PT_theme_bone_color_sets,
USERPREF_PT_theme_collection_colors,

View File

@ -92,7 +92,7 @@ static void bonecoll_ensure_name_unique(bArmature *armature, BoneCollection *bco
{
BLI_uniquename(&armature->collections,
bcoll,
bcoll->name,
"Bones",
'.',
offsetof(BoneCollection, name),
sizeof(bcoll->name));

View File

@ -0,0 +1,43 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
#include <optional>
#include <string>
#include "BLI_string_ref.hh"
#include "BLI_sub_frame.hh"
#include "BLI_vector.hh"
namespace blender::bke::bake_paths {
struct MetaFile {
SubFrame frame;
std::string path;
};
struct BakePath {
/** Path to the directory containing the meta data per frame. */
std::string meta_dir;
/**
* Path to the directory that contains the binary data. Could be shared between multiple bakes
* to reduce memory consumption.
*/
std::string bdata_dir;
/**
* Folder that is allowed to be deleted when the bake is deleted and it doesn't contain anything
* else. Typically, this contains the meta and bdata directories.
*/
std::optional<std::string> bake_dir;
static BakePath from_single_root(StringRefNull root_dir);
};
std::string frame_to_file_name(const SubFrame &frame);
std::optional<SubFrame> file_name_to_frame(const StringRefNull file_name);
Vector<MetaFile> find_sorted_meta_files(const StringRefNull meta_dir);
} // namespace blender::bke::bake_paths

View File

@ -98,9 +98,6 @@ struct bContextStoreEntry {
};
struct bContextStore {
bContextStore *next = nullptr;
bContextStore *prev = nullptr;
blender::Vector<bContextStoreEntry> entries;
bool used = false;
};
@ -152,17 +149,16 @@ bContext *CTX_copy(const bContext *C);
/* Stored Context */
bContextStore *CTX_store_add(ListBase *contexts,
bContextStore *CTX_store_add(blender::Vector<std::unique_ptr<bContextStore>> &contexts,
blender::StringRefNull name,
const PointerRNA *ptr);
bContextStore *CTX_store_add_all(ListBase *contexts, bContextStore *context);
bContextStore *CTX_store_get(bContext *C);
void CTX_store_set(bContext *C, bContextStore *store);
bContextStore *CTX_store_add_all(blender::Vector<std::unique_ptr<bContextStore>> &contexts,
const bContextStore *context);
const bContextStore *CTX_store_get(const bContext *C);
void CTX_store_set(bContext *C, const bContextStore *store);
const PointerRNA *CTX_store_ptr_lookup(const bContextStore *store,
blender::StringRefNull name,
const StructRNA *type = nullptr);
bContextStore *CTX_store_copy(const bContextStore *store);
void CTX_store_free(bContextStore *store);
#endif

View File

@ -235,6 +235,11 @@ void BKE_lib_override_library_main_hierarchy_root_ensure(Main *bmain);
* \param view_layer: the active view layer to search instantiated collections in, can be NULL (in
* which case \a scene's master collection children hierarchy is used instead).
* \param id_root: The root liboverride ID to resync from.
* \param do_hierarchy_enforce: If `true`, enforce the liboverride hierarchy of dependencies to
* match the one from the reference linked data (i.e. if some manually
* override were applied to some ID pointers, they will be reset to
* the default reference value).
*
* \return true if override was successfully resynced.
*/
bool BKE_lib_override_library_resync(Main *bmain,

View File

@ -321,16 +321,10 @@ void BKE_mesh_recalc_looptri(const int *corner_verts,
/* *** mesh_normals.cc *** */
/**
* Return true if the mesh vertex normals either are not stored or are dirty.
* This can be used to help decide whether to transfer them when copying a mesh.
*/
/** Return true if the mesh vertex normals either are not stored or are dirty. */
bool BKE_mesh_vert_normals_are_dirty(const struct Mesh *mesh);
/**
* Return true if the mesh face normals either are not stored or are dirty.
* This can be used to help decide whether to transfer them when copying a mesh.
*/
/** Return true if the mesh face normals either are not stored or are dirty. */
bool BKE_mesh_face_normals_are_dirty(const struct Mesh *mesh);
/**

View File

@ -288,7 +288,7 @@ class bNodeRuntime : NonCopyable, NonMovable {
/** Update flags. */
int update = 0;
/** Offset that will be added to locx for insert offset animation. */
/** Offset that will be added to #bNote::locx for insert offset animation. */
float anim_ofsx;
/** List of cached internal links (input to output), for muted nodes and operators. */

View File

@ -210,7 +210,7 @@ void BKE_pbvh_build_grids(PBVH *pbvh,
CCGElem **grids,
int totgrid,
CCGKey *key,
void **gridfaces,
blender::Span<int> grid_to_face_map,
DMFlagMat *flagmats,
unsigned int **grid_hidden,
Mesh *me,
@ -445,7 +445,7 @@ void BKE_pbvh_redraw_BB(PBVH *pbvh, float bb_min[3], float bb_max[3]);
void BKE_pbvh_get_grid_updates(PBVH *pbvh, bool clear, void ***r_gridfaces, int *r_totface);
void BKE_pbvh_grids_update(PBVH *pbvh,
CCGElem **grids,
void **gridfaces,
blender::Span<int> grid_to_face_map,
DMFlagMat *flagmats,
unsigned int **grid_hidden,
CCGKey *key);

View File

@ -417,6 +417,12 @@ typedef struct MenuType {
void (*draw)(const struct bContext *C, struct Menu *menu);
void (*listener)(const wmRegionListenerParams *params);
/**
* True if the menu depends on data retrieved via #CTX_data_pointer_get. If it is context
* dependent, menu search has to scan it in different contexts.
*/
bool context_dependent;
/* RNA integration */
ExtensionRNA rna_ext;
} MenuType;

View File

@ -4,6 +4,7 @@
#pragma once
#include "BKE_bake_items_paths.hh"
#include "BKE_bake_items_serialize.hh"
#include "BKE_geometry_set.hh"
@ -11,65 +12,11 @@
#include "BLI_sub_frame.hh"
struct bNodeTree;
struct NodesModifierData;
struct Main;
namespace blender::bke::sim {
class ModifierSimulationCache;
/**
* Storage of values for a single simulation input and output node pair.
* Used as a cache to allow random access in time, and as an intermediate form before data is
* baked.
*/
class SimulationZoneState {
public:
Map<int, std::unique_ptr<BakeItem>> item_by_identifier;
};
/** Identifies a simulation zone (input and output node pair) used by a modifier. */
struct SimulationZoneID {
/** ID of the #bNestedNodeRef that references the output node of the zone. */
int32_t nested_node_id;
uint64_t hash() const
{
return this->nested_node_id;
}
friend bool operator==(const SimulationZoneID &a, const SimulationZoneID &b)
{
return a.nested_node_id == b.nested_node_id;
}
};
/**
* Stores a single frame of simulation states for all simulation zones in a modifier's node
* hierarchy.
*/
class ModifierSimulationState {
private:
mutable bool bake_loaded_;
public:
ModifierSimulationCache *owner_;
mutable std::mutex mutex_;
Map<SimulationZoneID, std::unique_ptr<SimulationZoneState>> zone_states_;
/** File path to folder containing baked meta-data. */
std::optional<std::string> meta_path_;
/** File path to folder containing baked data. */
std::optional<std::string> bdata_dir_;
SimulationZoneState *get_zone_state(const SimulationZoneID &zone_id);
const SimulationZoneState *get_zone_state(const SimulationZoneID &zone_id) const;
SimulationZoneState &get_zone_state_for_write(const SimulationZoneID &zone_id);
void ensure_bake_loaded(const bNodeTree &ntree) const;
};
struct ModifierSimulationStateAtFrame {
SubFrame frame;
ModifierSimulationState state;
};
enum class CacheState {
/** The cache is up-to-date with the inputs. */
Valid,
@ -82,56 +29,34 @@ enum class CacheState {
Baked,
};
struct StatesAroundFrame {
const ModifierSimulationStateAtFrame *prev = nullptr;
const ModifierSimulationStateAtFrame *current = nullptr;
const ModifierSimulationStateAtFrame *next = nullptr;
struct SimulationZoneFrameCache {
SubFrame frame;
Map<int, std::unique_ptr<BakeItem>> items;
/** Used when the baked data is loaded lazily. */
std::optional<std::string> meta_path;
};
struct ModifierSimulationCacheRealtime {
std::unique_ptr<ModifierSimulationState> prev_state;
std::unique_ptr<ModifierSimulationState> current_state;
SubFrame prev_frame;
SubFrame current_frame;
struct SimulationZonePrevState {
Map<int, std::unique_ptr<BakeItem>> items;
SubFrame frame;
};
struct SimulationZoneCache {
Vector<std::unique_ptr<SimulationZoneFrameCache>> frame_caches;
std::optional<SimulationZonePrevState> prev_state;
std::optional<std::string> bdata_dir;
std::unique_ptr<BDataSharing> bdata_sharing;
bool failed_finding_bake = false;
CacheState cache_state = CacheState::Valid;
void reset();
};
class ModifierSimulationCache {
private:
mutable std::mutex states_at_frames_mutex_;
/**
* All simulation states, sorted by frame.
*/
Vector<std::unique_ptr<ModifierSimulationStateAtFrame>> states_at_frames_;
/**
* Used for baking to deduplicate arrays when writing and writing from storage. Sharing info
* must be kept alive for multiple frames to detect if each data array's version has changed.
*/
std::unique_ptr<BDataSharing> bdata_sharing_;
friend ModifierSimulationState;
bool failed_finding_bake_ = false;
public:
CacheState cache_state = CacheState::Valid;
/** A non-persistent cache used only to pass simulation state data from one frame to the next. */
ModifierSimulationCacheRealtime realtime_cache;
void try_discover_bake(StringRefNull absolute_bake_dir);
bool has_state_at_frame(const SubFrame &frame) const;
bool has_states() const;
const ModifierSimulationState *get_state_at_exact_frame(const SubFrame &frame) const;
ModifierSimulationState &get_state_at_frame_for_write(const SubFrame &frame);
StatesAroundFrame get_states_around_frame(const SubFrame &frame) const;
void invalidate()
{
this->cache_state = CacheState::Invalid;
}
void reset();
mutable std::mutex mutex;
Map<int, std::unique_ptr<SimulationZoneCache>> cache_by_zone_id;
};
/**
@ -140,4 +65,12 @@ class ModifierSimulationCache {
*/
void scene_simulation_states_reset(Scene &scene);
std::optional<bake_paths::BakePath> get_simulation_zone_bake_path(const Main &bmain,
const Object &object,
const NodesModifierData &nmd,
int zone_id);
std::optional<std::string> get_modifier_simulation_bake_path(const Main &bmain,
const Object &object,
const NodesModifierData &nmd);
} // namespace blender::bke::sim

View File

@ -29,22 +29,6 @@ std::string get_default_modifier_bake_directory(const Main &bmain,
const Object &object,
const ModifierData &md);
/**
* Encode the simulation state in a #DictionaryValue which also contains references to external
* binary data that has been written using #bdata_writer.
*/
void serialize_modifier_simulation_state(const ModifierSimulationState &state,
BDataWriter &bdata_writer,
BDataSharing &bdata_sharing,
DictionaryValue &r_io_root);
/**
* Fill the simulation state by parsing the provided #DictionaryValue which also contains
* references to external binary data that is read using #bdata_reader.
*/
void deserialize_modifier_simulation_state(const bNodeTree &ntree,
const DictionaryValue &io_root,
const BDataReader &bdata_reader,
const BDataSharing &bdata_sharing,
ModifierSimulationState &r_state);
constexpr int simulation_file_storage_version = 3;
} // namespace blender::bke::sim

View File

@ -160,7 +160,7 @@ struct SubdivCCG {
int num_faces = -1;
SubdivCCGFace *faces = nullptr;
/* Indexed by grid index, points to corresponding face from `faces`. */
SubdivCCGFace **grid_faces = nullptr;
blender::Array<int> grid_to_face_map;
/* Edges which are adjacent to faces.
* Used for faster grid stitching, in the cost of extra memory.

View File

@ -73,6 +73,7 @@ set(SRC
intern/attribute_math.cc
intern/autoexec.cc
intern/bake_items.cc
intern/bake_items_paths.cc
intern/bake_items_serialize.cc
intern/bake_items_socket.cc
intern/blender.cc
@ -333,6 +334,7 @@ set(SRC
BKE_attribute_math.hh
BKE_autoexec.h
BKE_bake_items.hh
BKE_bake_items_paths.hh
BKE_bake_items_serialize.hh
BKE_bake_items_socket.hh
BKE_blender.h

View File

@ -87,6 +87,7 @@ static void armature_init_data(ID *id)
/* Give the Armature its default bone collection. */
BoneCollection *default_bonecoll = ANIM_bonecoll_new("");
BLI_addhead(&armature->collections, default_bonecoll);
ANIM_armature_bonecoll_active_set(armature, default_bonecoll);
}
/**

View File

@ -0,0 +1,76 @@
/* SPDX-FileCopyrightText: 2023 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "BKE_bake_items_paths.hh"
#include "BLI_fileops.hh"
#include "BLI_path_util.h"
#include "BLI_string.h"
#include "BLI_string_utils.h"
namespace blender::bke::bake_paths {
std::string frame_to_file_name(const SubFrame &frame)
{
char file_name_c[FILE_MAX];
SNPRINTF(file_name_c, "%011.5f", double(frame));
BLI_string_replace_char(file_name_c, '.', '_');
return file_name_c;
}
std::optional<SubFrame> file_name_to_frame(const StringRefNull file_name)
{
char modified_file_name[FILE_MAX];
STRNCPY(modified_file_name, file_name.c_str());
BLI_string_replace_char(modified_file_name, '_', '.');
const SubFrame frame = std::stof(modified_file_name);
return frame;
}
Vector<MetaFile> find_sorted_meta_files(const StringRefNull meta_dir)
{
if (!BLI_is_dir(meta_dir.c_str())) {
return {};
}
direntry *dir_entries = nullptr;
const int dir_entries_num = BLI_filelist_dir_contents(meta_dir.c_str(), &dir_entries);
BLI_SCOPED_DEFER([&]() { BLI_filelist_free(dir_entries, dir_entries_num); });
Vector<MetaFile> meta_files;
for (const int i : IndexRange(dir_entries_num)) {
const direntry &dir_entry = dir_entries[i];
const StringRefNull dir_entry_path = dir_entry.path;
if (!dir_entry_path.endswith(".json")) {
continue;
}
const std::optional<SubFrame> frame = file_name_to_frame(dir_entry.relname);
if (!frame) {
continue;
}
meta_files.append({*frame, dir_entry_path});
}
std::sort(meta_files.begin(), meta_files.end(), [](const MetaFile &a, const MetaFile &b) {
return a.frame < b.frame;
});
return meta_files;
}
BakePath BakePath::from_single_root(StringRefNull root_dir)
{
char meta_dir[FILE_MAX];
BLI_path_join(meta_dir, sizeof(meta_dir), root_dir.c_str(), "meta");
char bdata_dir[FILE_MAX];
BLI_path_join(bdata_dir, sizeof(bdata_dir), root_dir.c_str(), "bdata");
BakePath bake_path;
bake_path.meta_dir = meta_dir;
bake_path.bdata_dir = bdata_dir;
bake_path.bake_dir = root_dir;
return bake_path;
}
} // namespace blender::bke::bake_paths

View File

@ -68,7 +68,7 @@ struct bContext {
ARegion *region;
ARegion *menu;
wmGizmoGroup *gizmo_group;
bContextStore *store;
const bContextStore *store;
/* Operator poll. */
/**
@ -128,60 +128,51 @@ void CTX_free(bContext *C)
/* store */
bContextStore *CTX_store_add(ListBase *contexts,
bContextStore *CTX_store_add(blender::Vector<std::unique_ptr<bContextStore>> &contexts,
const blender::StringRefNull name,
const PointerRNA *ptr)
{
/* ensure we have a context to put the entry in, if it was already used
* we have to copy the context to ensure */
bContextStore *ctx = static_cast<bContextStore *>(contexts->last);
if (!ctx || ctx->used) {
if (ctx) {
ctx = MEM_new<bContextStore>(__func__, *ctx);
}
else {
ctx = MEM_new<bContextStore>(__func__);
}
BLI_addtail(contexts, ctx);
if (contexts.is_empty()) {
contexts.append(std::make_unique<bContextStore>());
}
else if (contexts.last()->used) {
auto new_ctx = std::make_unique<bContextStore>(bContextStore{contexts.last()->entries, false});
contexts.append(std::move(new_ctx));
}
bContextStore *ctx = contexts.last().get();
ctx->entries.append(bContextStoreEntry{name, *ptr});
return ctx;
}
bContextStore *CTX_store_add_all(ListBase *contexts, bContextStore *context)
bContextStore *CTX_store_add_all(blender::Vector<std::unique_ptr<bContextStore>> &contexts,
const bContextStore *context)
{
/* ensure we have a context to put the entries in, if it was already used
/* ensure we have a context to put the entry in, if it was already used
* we have to copy the context to ensure */
bContextStore *ctx = static_cast<bContextStore *>(contexts->last);
if (!ctx || ctx->used) {
if (ctx) {
ctx = MEM_new<bContextStore>(__func__, *ctx);
}
else {
ctx = MEM_new<bContextStore>(__func__);
}
BLI_addtail(contexts, ctx);
if (contexts.is_empty()) {
contexts.append(std::make_unique<bContextStore>());
}
else if (contexts.last()->used) {
auto new_ctx = std::make_unique<bContextStore>(bContextStore{contexts.last()->entries, false});
contexts.append(std::move(new_ctx));
}
bContextStore *ctx = contexts.last().get();
for (const bContextStoreEntry &src_entry : context->entries) {
ctx->entries.append(src_entry);
}
return ctx;
}
bContextStore *CTX_store_get(bContext *C)
const bContextStore *CTX_store_get(const bContext *C)
{
return C->wm.store;
}
void CTX_store_set(bContext *C, bContextStore *store)
void CTX_store_set(bContext *C, const bContextStore *store)
{
C->wm.store = store;
}
@ -200,16 +191,6 @@ const PointerRNA *CTX_store_ptr_lookup(const bContextStore *store,
return nullptr;
}
bContextStore *CTX_store_copy(const bContextStore *store)
{
return MEM_new<bContextStore>(__func__, *store);
}
void CTX_store_free(bContextStore *store)
{
MEM_delete(store);
}
/* is python initialized? */
bool CTX_py_init_get(bContext *C)

View File

@ -1058,9 +1058,6 @@ Mesh *BKE_mesh_new_nomain_from_template_ex(const Mesh *me_src,
CustomData_add_layer(&me_dst->fdata_legacy, CD_MFACE, CD_SET_DEFAULT, me_dst->totface_legacy);
}
/* Expect that normals aren't copied at all, since the destination mesh is new. */
BLI_assert(BKE_mesh_vert_normals_are_dirty(me_dst));
return me_dst;
}

View File

@ -758,7 +758,7 @@ int bNodeTreeInterfacePanel::find_valid_insert_position_for_item(
break;
}
if (items[test_pos]->item_type == NODE_INTERFACE_PANEL) {
/* Found valid position, insering moves the first panel. */
/* Found valid position, inserting moves the first panel. */
pos = test_pos;
break;
}

View File

@ -2215,7 +2215,7 @@ static PBVH *build_pbvh_from_ccg(Object *ob, SubdivCCG *subdiv_ccg)
subdiv_ccg->grids,
subdiv_ccg->num_grids,
&key,
(void **)subdiv_ccg->grid_faces,
subdiv_ccg->grid_to_face_map,
subdiv_ccg->grid_flag_mats,
subdiv_ccg->grid_hidden,
base_mesh,
@ -2304,7 +2304,7 @@ void BKE_sculpt_bvh_update_from_ccg(PBVH *pbvh, SubdivCCG *subdiv_ccg)
BKE_pbvh_grids_update(pbvh,
subdiv_ccg->grids,
(void **)subdiv_ccg->grid_faces,
subdiv_ccg->grid_to_face_map,
subdiv_ccg->grid_flag_mats,
subdiv_ccg->grid_hidden,
&key);

View File

@ -914,7 +914,7 @@ void BKE_pbvh_build_grids(PBVH *pbvh,
CCGElem **grids,
int totgrid,
CCGKey *key,
void **gridfaces,
blender::Span<int> grid_to_face_map,
DMFlagMat *flagmats,
BLI_bitmap **grid_hidden,
Mesh *me,
@ -924,7 +924,7 @@ void BKE_pbvh_build_grids(PBVH *pbvh,
pbvh->header.type = PBVH_GRIDS;
pbvh->grids = grids;
pbvh->gridfaces = gridfaces;
pbvh->grid_to_face_map = grid_to_face_map;
pbvh->grid_flag_mats = flagmats;
pbvh->totgrid = totgrid;
pbvh->gridkey = *key;
@ -1715,10 +1715,11 @@ void BKE_pbvh_get_grid_updates(PBVH *pbvh, bool clear, void ***r_gridfaces, int
pbvh_iter_begin(&iter, pbvh, {});
SubdivCCGFace *all_faces = pbvh->subdiv_ccg->faces;
while ((node = pbvh_iter_next(&iter, PBVH_Leaf))) {
if (node->flag & PBVH_UpdateNormals) {
for (const int grid : node->prim_indices) {
void *face = pbvh->gridfaces[grid];
void *face = &all_faces[pbvh->grid_to_face_map[grid]];
BLI_gset_add(face_set, face);
}
@ -2944,14 +2945,14 @@ void BKE_pbvh_draw_debug_cb(PBVH *pbvh,
void BKE_pbvh_grids_update(PBVH *pbvh,
CCGElem **grids,
void **gridfaces,
blender::Span<int> grid_to_face_map,
DMFlagMat *flagmats,
BLI_bitmap **grid_hidden,
CCGKey *key)
{
pbvh->gridkey = *key;
pbvh->grids = grids;
pbvh->gridfaces = gridfaces;
pbvh->grid_to_face_map = grid_to_face_map;
if (flagmats != pbvh->grid_flag_mats || pbvh->grid_hidden != grid_hidden) {
pbvh->grid_flag_mats = flagmats;

View File

@ -175,7 +175,7 @@ struct PBVH {
/* Grid Data */
CCGKey gridkey;
CCGElem **grids;
void **gridfaces;
blender::Span<int> grid_to_face_map;
const DMFlagMat *grid_flag_mats;
int totgrid;
BLI_bitmap **grid_hidden;

View File

@ -4,6 +4,7 @@
#include "BKE_collection.h"
#include "BKE_curves.hh"
#include "BKE_main.h"
#include "BKE_simulation_state.hh"
#include "BKE_simulation_state_serialize.hh"
@ -21,213 +22,13 @@
namespace blender::bke::sim {
void ModifierSimulationCache::try_discover_bake(const StringRefNull absolute_bake_dir)
void SimulationZoneCache::reset()
{
if (failed_finding_bake_) {
return;
}
char meta_dir[FILE_MAX];
BLI_path_join(meta_dir, sizeof(meta_dir), absolute_bake_dir.c_str(), "meta");
char bdata_dir[FILE_MAX];
BLI_path_join(bdata_dir, sizeof(bdata_dir), absolute_bake_dir.c_str(), "bdata");
if (!BLI_is_dir(meta_dir) || !BLI_is_dir(bdata_dir)) {
failed_finding_bake_ = true;
return;
}
direntry *dir_entries = nullptr;
const int dir_entries_num = BLI_filelist_dir_contents(meta_dir, &dir_entries);
BLI_SCOPED_DEFER([&]() { BLI_filelist_free(dir_entries, dir_entries_num); });
if (dir_entries_num == 0) {
failed_finding_bake_ = true;
return;
}
this->reset();
{
std::lock_guard lock(states_at_frames_mutex_);
for (const int i : IndexRange(dir_entries_num)) {
const direntry &dir_entry = dir_entries[i];
const StringRefNull dir_entry_path = dir_entry.path;
if (!dir_entry_path.endswith(".json")) {
continue;
}
char modified_file_name[FILE_MAX];
STRNCPY(modified_file_name, dir_entry.relname);
BLI_string_replace_char(modified_file_name, '_', '.');
const SubFrame frame = std::stof(modified_file_name);
auto new_state_at_frame = std::make_unique<ModifierSimulationStateAtFrame>();
new_state_at_frame->frame = frame;
new_state_at_frame->state.bdata_dir_ = bdata_dir;
new_state_at_frame->state.meta_path_ = dir_entry.path;
new_state_at_frame->state.owner_ = this;
states_at_frames_.append(std::move(new_state_at_frame));
}
bdata_sharing_ = std::make_unique<BDataSharing>();
this->cache_state = CacheState::Baked;
}
}
static int64_t find_state_at_frame(
const Span<std::unique_ptr<ModifierSimulationStateAtFrame>> states, const SubFrame &frame)
{
const int64_t i = binary_search::find_predicate_begin(
states, [&](const auto &item) { return item->frame >= frame; });
if (i == states.size()) {
return -1;
}
return i;
}
static int64_t find_state_at_frame_exact(
const Span<std::unique_ptr<ModifierSimulationStateAtFrame>> states, const SubFrame &frame)
{
const int64_t i = find_state_at_frame(states, frame);
if (i == -1) {
return -1;
}
if (states[i]->frame != frame) {
return -1;
}
return i;
}
bool ModifierSimulationCache::has_state_at_frame(const SubFrame &frame) const
{
std::lock_guard lock(states_at_frames_mutex_);
return find_state_at_frame_exact(states_at_frames_, frame) != -1;
}
bool ModifierSimulationCache::has_states() const
{
std::lock_guard lock(states_at_frames_mutex_);
return !states_at_frames_.is_empty();
}
const ModifierSimulationState *ModifierSimulationCache::get_state_at_exact_frame(
const SubFrame &frame) const
{
std::lock_guard lock(states_at_frames_mutex_);
const int64_t i = find_state_at_frame_exact(states_at_frames_, frame);
if (i == -1) {
return nullptr;
}
return &states_at_frames_[i]->state;
}
ModifierSimulationState &ModifierSimulationCache::get_state_at_frame_for_write(
const SubFrame &frame)
{
std::lock_guard lock(states_at_frames_mutex_);
const int64_t i = find_state_at_frame_exact(states_at_frames_, frame);
if (i != -1) {
return states_at_frames_[i]->state;
}
if (!states_at_frames_.is_empty()) {
BLI_assert(frame > states_at_frames_.last()->frame);
}
states_at_frames_.append(std::make_unique<ModifierSimulationStateAtFrame>());
states_at_frames_.last()->frame = frame;
states_at_frames_.last()->state.owner_ = this;
return states_at_frames_.last()->state;
}
StatesAroundFrame ModifierSimulationCache::get_states_around_frame(const SubFrame &frame) const
{
std::lock_guard lock(states_at_frames_mutex_);
const int64_t i = find_state_at_frame(states_at_frames_, frame);
StatesAroundFrame states_around_frame{};
if (i == -1) {
if (!states_at_frames_.is_empty() && states_at_frames_.last()->frame < frame) {
states_around_frame.prev = states_at_frames_.last().get();
}
return states_around_frame;
}
if (states_at_frames_[i]->frame == frame) {
states_around_frame.current = states_at_frames_[i].get();
}
if (i > 0) {
states_around_frame.prev = states_at_frames_[i - 1].get();
}
if (i < states_at_frames_.size() - 2) {
states_around_frame.next = states_at_frames_[i + 1].get();
}
return states_around_frame;
}
SimulationZoneState *ModifierSimulationState::get_zone_state(const SimulationZoneID &zone_id)
{
std::lock_guard lock{mutex_};
if (auto *ptr = zone_states_.lookup_ptr(zone_id)) {
return ptr->get();
}
return nullptr;
}
const SimulationZoneState *ModifierSimulationState::get_zone_state(
const SimulationZoneID &zone_id) const
{
std::lock_guard lock{mutex_};
if (auto *ptr = zone_states_.lookup_ptr(zone_id)) {
return ptr->get();
}
return nullptr;
}
SimulationZoneState &ModifierSimulationState::get_zone_state_for_write(
const SimulationZoneID &zone_id)
{
std::lock_guard lock{mutex_};
return *zone_states_.lookup_or_add_cb(zone_id,
[]() { return std::make_unique<SimulationZoneState>(); });
}
void ModifierSimulationState::ensure_bake_loaded(const bNodeTree &ntree) const
{
std::scoped_lock lock{mutex_};
if (bake_loaded_) {
return;
}
if (!meta_path_ || !bdata_dir_) {
return;
}
const std::shared_ptr<io::serialize::Value> io_root_value = io::serialize::read_json_file(
*meta_path_);
if (!io_root_value) {
return;
}
const DictionaryValue *io_root = io_root_value->as_dictionary_value();
if (!io_root) {
return;
}
const DiskBDataReader bdata_reader{*bdata_dir_};
deserialize_modifier_simulation_state(ntree,
*io_root,
bdata_reader,
*owner_->bdata_sharing_,
const_cast<ModifierSimulationState &>(*this));
bake_loaded_ = true;
}
void ModifierSimulationCache::reset()
{
std::lock_guard lock(states_at_frames_mutex_);
states_at_frames_.clear();
bdata_sharing_.reset();
this->realtime_cache.current_state.reset();
this->realtime_cache.prev_state.reset();
this->frame_caches.clear();
this->prev_state.reset();
this->bdata_dir.reset();
this->bdata_sharing.reset();
this->failed_finding_bake = false;
this->cache_state = CacheState::Valid;
}
@ -239,10 +40,52 @@ void scene_simulation_states_reset(Scene &scene)
continue;
}
NodesModifierData *nmd = reinterpret_cast<NodesModifierData *>(md);
nmd->runtime->simulation_cache->reset();
if (!nmd->runtime->simulation_cache) {
continue;
}
for (auto item : nmd->runtime->simulation_cache->cache_by_zone_id.items()) {
item.value->reset();
}
}
}
FOREACH_SCENE_OBJECT_END;
}
std::optional<std::string> get_modifier_simulation_bake_path(const Main &bmain,
const Object &object,
const NodesModifierData &nmd)
{
const StringRefNull bmain_path = BKE_main_blendfile_path(&bmain);
if (bmain_path.is_empty()) {
return std::nullopt;
}
if (StringRef(nmd.simulation_bake_directory).is_empty()) {
return std::nullopt;
}
const char *base_path = ID_BLEND_PATH(&bmain, &object.id);
char absolute_bake_dir[FILE_MAX];
STRNCPY(absolute_bake_dir, nmd.simulation_bake_directory);
BLI_path_abs(absolute_bake_dir, base_path);
return absolute_bake_dir;
}
std::optional<bake_paths::BakePath> get_simulation_zone_bake_path(const Main &bmain,
const Object &object,
const NodesModifierData &nmd,
int zone_id)
{
const std::optional<std::string> modifier_bake_path = get_modifier_simulation_bake_path(
bmain, object, nmd);
if (!modifier_bake_path) {
return std::nullopt;
}
char zone_bake_dir[FILE_MAX];
BLI_path_join(zone_bake_dir,
sizeof(zone_bake_dir),
modifier_bake_path->c_str(),
std::to_string(zone_id).c_str());
return bake_paths::BakePath::from_single_root(zone_bake_dir);
}
} // namespace blender::bke::sim

View File

@ -83,111 +83,4 @@ std::string get_default_modifier_bake_directory(const Main &bmain,
return dir;
}
/**
* Version written to the baked data.
*/
static constexpr int serialize_format_version = 2;
void serialize_modifier_simulation_state(const ModifierSimulationState &state,
BDataWriter &bdata_writer,
BDataSharing &bdata_sharing,
DictionaryValue &r_io_root)
{
r_io_root.append_int("version", serialize_format_version);
auto io_zones = r_io_root.append_array("zones");
for (const auto item : state.zone_states_.items()) {
const SimulationZoneID &zone_id = item.key;
const SimulationZoneState &zone_state = *item.value;
auto io_zone = io_zones->append_dict();
io_zone->append_int("state_id", zone_id.nested_node_id);
auto io_state_items = io_zone->append_array("state_items");
for (const MapItem<int, std::unique_ptr<BakeItem>> &state_item_with_id :
zone_state.item_by_identifier.items())
{
auto io_state_item = io_state_items->append_dict();
io_state_item->append_int("id", state_item_with_id.key);
serialize_bake_item(*state_item_with_id.value, bdata_writer, bdata_sharing, *io_state_item);
}
}
}
void deserialize_modifier_simulation_state(const bNodeTree &ntree,
const DictionaryValue &io_root,
const BDataReader &bdata_reader,
const BDataSharing &bdata_sharing,
ModifierSimulationState &r_state)
{
io::serialize::JsonFormatter formatter;
const std::optional<int> version = io_root.lookup_int("version");
if (!version) {
return;
}
if (*version > serialize_format_version) {
return;
}
const io::serialize::ArrayValue *io_zones = io_root.lookup_array("zones");
if (!io_zones) {
return;
}
for (const auto &io_zone_value : io_zones->elements()) {
const DictionaryValue *io_zone = io_zone_value->as_dictionary_value();
if (!io_zone) {
continue;
}
bke::sim::SimulationZoneID zone_id;
if (const std::optional<int> state_id = io_zone->lookup_int("state_id")) {
zone_id.nested_node_id = *state_id;
}
else if (const io::serialize::ArrayValue *io_zone_id = io_zone->lookup_array("zone_id")) {
/* In the initial release of simulation nodes, the entire node id path was written to the
* baked data. For backward compatibility the node ids are read here and then the nested node
* id is looked up. */
Vector<int> node_ids;
for (const auto &io_zone_id_element : io_zone_id->elements()) {
const io::serialize::IntValue *io_node_id = io_zone_id_element->as_int_value();
if (!io_node_id) {
continue;
}
node_ids.append(io_node_id->value());
}
const bNestedNodeRef *nested_node_ref = ntree.nested_node_ref_from_node_id_path(node_ids);
if (!nested_node_ref) {
continue;
}
zone_id.nested_node_id = nested_node_ref->id;
}
const io::serialize::ArrayValue *io_state_items = io_zone->lookup_array("state_items");
if (!io_state_items) {
continue;
}
auto zone_state = std::make_unique<bke::sim::SimulationZoneState>();
for (const auto &io_state_item_value : io_state_items->elements()) {
const DictionaryValue *io_state_item = io_state_item_value->as_dictionary_value();
if (!io_state_item) {
continue;
}
const std::optional<int> state_item_id = io_state_item->lookup_int("id");
if (!state_item_id) {
continue;
}
std::unique_ptr<BakeItem> new_state_item = deserialize_bake_item(
*io_state_item, bdata_reader, bdata_sharing);
BLI_assert(new_state_item);
zone_state->item_by_identifier.add(*state_item_id, std::move(new_state_item));
}
r_state.zone_states_.add_overwrite(zone_id, std::move(zone_state));
}
}
} // namespace blender::bke::sim

View File

@ -155,8 +155,7 @@ static void subdiv_ccg_alloc_elements(SubdivCCG *subdiv_ccg, Subdiv *subdiv)
if (num_faces) {
subdiv_ccg->faces = static_cast<SubdivCCGFace *>(
MEM_calloc_arrayN(num_faces, sizeof(SubdivCCGFace), "Subdiv CCG faces"));
subdiv_ccg->grid_faces = static_cast<SubdivCCGFace **>(
MEM_calloc_arrayN(num_grids, sizeof(SubdivCCGFace *), "Subdiv CCG grid faces"));
subdiv_ccg->grid_to_face_map.reinitialize(num_grids);
}
}
@ -235,7 +234,7 @@ static void subdiv_ccg_eval_regular_grid(CCGEvalGridsData *data, const int face_
const float grid_size_1_inv = 1.0f / (grid_size - 1);
const int element_size = element_size_bytes_get(subdiv_ccg);
SubdivCCGFace *faces = subdiv_ccg->faces;
SubdivCCGFace **grid_faces = subdiv_ccg->grid_faces;
blender::MutableSpan<int> grid_to_face_map = subdiv_ccg->grid_to_face_map;
const SubdivCCGFace *face = &faces[face_index];
for (int corner = 0; corner < face->num_grids; corner++) {
const int grid_index = face->start_grid_index + corner;
@ -252,7 +251,7 @@ static void subdiv_ccg_eval_regular_grid(CCGEvalGridsData *data, const int face_
}
}
/* Assign grid's face. */
grid_faces[grid_index] = &faces[face_index];
grid_to_face_map[grid_index] = face_index;
/* Assign material flags. */
subdiv_ccg->grid_flag_mats[grid_index] = data->material_flags_evaluator->eval_material_flags(
data->material_flags_evaluator, face_index);
@ -266,7 +265,7 @@ static void subdiv_ccg_eval_special_grid(CCGEvalGridsData *data, const int face_
const float grid_size_1_inv = 1.0f / (grid_size - 1);
const int element_size = element_size_bytes_get(subdiv_ccg);
SubdivCCGFace *faces = subdiv_ccg->faces;
SubdivCCGFace **grid_faces = subdiv_ccg->grid_faces;
blender::MutableSpan<int> grid_to_face_map = subdiv_ccg->grid_to_face_map;
const SubdivCCGFace *face = &faces[face_index];
for (int corner = 0; corner < face->num_grids; corner++) {
const int grid_index = face->start_grid_index + corner;
@ -282,7 +281,7 @@ static void subdiv_ccg_eval_special_grid(CCGEvalGridsData *data, const int face_
}
}
/* Assign grid's face. */
grid_faces[grid_index] = &faces[face_index];
grid_to_face_map[grid_index] = face_index;
/* Assign material flags. */
subdiv_ccg->grid_flag_mats[grid_index] = data->material_flags_evaluator->eval_material_flags(
data->material_flags_evaluator, face_index);
@ -596,7 +595,6 @@ void BKE_subdiv_ccg_destroy(SubdivCCG *subdiv_ccg)
BKE_subdiv_free(subdiv_ccg->subdiv);
}
MEM_SAFE_FREE(subdiv_ccg->faces);
MEM_SAFE_FREE(subdiv_ccg->grid_faces);
/* Free map of adjacent edges. */
for (int i = 0; i < subdiv_ccg->num_adjacent_edges; i++) {
SubdivCCGAdjacentEdge *adjacent_edge = &subdiv_ccg->adjacent_edges[i];
@ -1452,7 +1450,7 @@ static SubdivCCGCoord coord_step_inside_from_boundary(const SubdivCCG *subdiv_cc
BLI_INLINE
int next_grid_index_from_coord(const SubdivCCG *subdiv_ccg, const SubdivCCGCoord *coord)
{
SubdivCCGFace *face = subdiv_ccg->grid_faces[coord->grid_index];
const SubdivCCGFace *face = &subdiv_ccg->faces[subdiv_ccg->grid_to_face_map[coord->grid_index]];
const int face_grid_index = coord->grid_index;
int next_face_grid_index = face_grid_index + 1 - face->start_grid_index;
if (next_face_grid_index == face->num_grids) {
@ -1462,7 +1460,7 @@ int next_grid_index_from_coord(const SubdivCCG *subdiv_ccg, const SubdivCCGCoord
}
BLI_INLINE int prev_grid_index_from_coord(const SubdivCCG *subdiv_ccg, const SubdivCCGCoord *coord)
{
SubdivCCGFace *face = subdiv_ccg->grid_faces[coord->grid_index];
const SubdivCCGFace *face = &subdiv_ccg->faces[subdiv_ccg->grid_to_face_map[coord->grid_index]];
const int face_grid_index = coord->grid_index;
int prev_face_grid_index = face_grid_index - 1 - face->start_grid_index;
if (prev_face_grid_index < 0) {
@ -1478,7 +1476,7 @@ static void neighbor_coords_corner_center_get(const SubdivCCG *subdiv_ccg,
const bool include_duplicates,
SubdivCCGNeighbors *r_neighbors)
{
SubdivCCGFace *face = subdiv_ccg->grid_faces[coord->grid_index];
const SubdivCCGFace *face = &subdiv_ccg->faces[subdiv_ccg->grid_to_face_map[coord->grid_index]];
const int num_adjacent_grids = face->num_grids;
subdiv_ccg_neighbors_init(
@ -1506,7 +1504,7 @@ static int adjacent_vertex_index_from_coord(const SubdivCCG *subdiv_ccg,
Subdiv *subdiv = subdiv_ccg->subdiv;
OpenSubdiv_TopologyRefiner *topology_refiner = subdiv->topology_refiner;
const SubdivCCGFace *face = subdiv_ccg->grid_faces[coord->grid_index];
const SubdivCCGFace *face = &subdiv_ccg->faces[subdiv_ccg->grid_to_face_map[coord->grid_index]];
const int face_index = face - subdiv_ccg->faces;
const int face_grid_index = coord->grid_index - face->start_grid_index;
const int num_face_grids = face->num_grids;
@ -1583,7 +1581,7 @@ static int adjacent_edge_index_from_coord(const SubdivCCG *subdiv_ccg, const Sub
{
Subdiv *subdiv = subdiv_ccg->subdiv;
OpenSubdiv_TopologyRefiner *topology_refiner = subdiv->topology_refiner;
SubdivCCGFace *face = subdiv_ccg->grid_faces[coord->grid_index];
const SubdivCCGFace *face = &subdiv_ccg->faces[subdiv_ccg->grid_to_face_map[coord->grid_index]];
const int face_grid_index = coord->grid_index - face->start_grid_index;
const int face_index = face - subdiv_ccg->faces;
@ -1876,9 +1874,7 @@ void BKE_subdiv_ccg_neighbor_coords_get(const SubdivCCG *subdiv_ccg,
int BKE_subdiv_ccg_grid_to_face_index(const SubdivCCG *subdiv_ccg, const int grid_index)
{
const SubdivCCGFace *face = subdiv_ccg->grid_faces[grid_index];
const int face_index = face - subdiv_ccg->faces;
return face_index;
return subdiv_ccg->grid_to_face_map[grid_index];
}
const int *BKE_subdiv_ccg_start_face_grid_index_ensure(SubdivCCG *subdiv_ccg)

View File

@ -1196,6 +1196,11 @@ Mesh *BKE_subdiv_to_mesh(Subdiv *subdiv,
BKE_subdiv_stats_end(&subdiv->stats, SUBDIV_STATS_SUBDIV_TO_MESH_GEOMETRY);
Mesh *result = subdiv_context.subdiv_mesh;
/* NOTE: Using normals from the limit surface gives different results than Blender's vertex
* normal calculation. Since vertex normals are supposed to be a consistent cache, don't bother
* calculating them here. The work may have been pointless anyway if the mesh is deformed or
* changed afterwards. */
/* Move the optimal display edge array to the final bit vector. */
if (!subdiv_context.subdiv_display_edges.is_empty()) {
const Span<bool> span = subdiv_context.subdiv_display_edges;
@ -1224,12 +1229,6 @@ Mesh *BKE_subdiv_to_mesh(Subdiv *subdiv,
// BKE_mesh_validate(result, true, true);
BKE_subdiv_stats_end(&subdiv->stats, SUBDIV_STATS_SUBDIV_TO_MESH);
/* Using normals from the limit surface gives different results than Blender's vertex normal
* calculation. Since vertex normals are supposed to be a consistent cache, don't bother
* calculating them here. The work may have been pointless anyway if the mesh is deformed or
* changed afterwards. */
BLI_assert(BKE_mesh_vert_normals_are_dirty(result) || BKE_mesh_face_normals_are_dirty(result));
/* Free used memory. */
subdiv_mesh_context_free(&subdiv_context);
return result;
}

View File

@ -85,11 +85,6 @@ struct SubFrame {
{
return a.frame_ >= b.frame_ || (a.frame_ == b.frame_ && a.subframe_ >= b.subframe_);
}
friend std::ostream &operator<<(std::ostream &stream, const SubFrame &a)
{
return stream << float(a);
}
};
} // namespace blender

View File

@ -2309,6 +2309,8 @@ float voronoi_n_sphere_radius(const VoronoiParams &params, const float4 coord)
/* **** Fractal Voronoi **** */
/* The fractalization logic is the same as for fBM Noise, except that some additions are replaced
* by lerps. */
template<typename T>
VoronoiOutput fractal_voronoi_x_fx(const VoronoiParams &params,
const T coord,
@ -2319,8 +2321,7 @@ VoronoiOutput fractal_voronoi_x_fx(const VoronoiParams &params,
float scale = 1.0f;
VoronoiOutput output;
const bool zero_input = params.detail == 0.0f || params.roughness == 0.0f ||
params.lacunarity == 0.0f;
const bool zero_input = params.detail == 0.0f || params.roughness == 0.0f;
for (int i = 0; i <= ceilf(params.detail); ++i) {
VoronoiOutput octave = (params.feature == NOISE_SHD_VORONOI_F2) ?
@ -2367,6 +2368,8 @@ VoronoiOutput fractal_voronoi_x_fx(const VoronoiParams &params,
return output;
}
/* The fractalization logic is the same as for fBM Noise, except that some additions are replaced
* by lerps. */
template<typename T>
float fractal_voronoi_distance_to_edge(const VoronoiParams &params, const T coord)
{
@ -2375,8 +2378,7 @@ float fractal_voronoi_distance_to_edge(const VoronoiParams &params, const T coor
float scale = 1.0f;
float distance = 8.0f;
const bool zero_input = params.detail == 0.0f || params.roughness == 0.0f ||
params.lacunarity == 0.0f;
const bool zero_input = params.detail == 0.0f || params.roughness == 0.0f;
for (int i = 0; i <= ceilf(params.detail); ++i) {
const float octave_distance = voronoi_distance_to_edge(params, coord * scale);

View File

@ -984,7 +984,7 @@ void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain)
FOREACH_NODETREE_END;
}
else {
/* Legacy node tree sockets are created for forward compatibilty,
/* Legacy node tree sockets are created for forward compatibility,
* but have to be freed after loading and versioning. */
FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
/* Clear legacy sockets after conversion.

View File

@ -871,6 +871,9 @@ void blo_do_versions_userdef(UserDef *userdef)
*/
{
/* Keep this block, even when empty. */
/* Clear deprecated USER_MENUFIXEDORDER user flag for reuse. */
userdef->uiflag &= ~USER_UIFLAG_UNUSED_4;
}
LISTBASE_FOREACH (bTheme *, btheme, &userdef->themes) {

View File

@ -292,9 +292,15 @@ void AntiAliasingPass::draw(Manager &manager,
draw_overlay_depth(sample0_depth_tx_);
GPU_texture_copy(sample0_depth_in_front_tx_, resources.depth_in_front_tx);
}
/* Copy back the saved depth buffer for correct overlays. */
GPU_texture_copy(depth_tx, sample0_depth_tx_);
GPU_texture_copy(depth_in_front_tx, sample0_depth_in_front_tx_);
if (!DRW_state_is_scene_render()) {
/* Copy back the saved depth buffer for correct overlays. */
GPU_texture_copy(depth_tx, sample0_depth_tx_);
GPU_texture_copy(depth_in_front_tx, sample0_depth_in_front_tx_);
}
else if (last_sample) {
GPU_texture_copy(depth_tx, sample0_depth_tx_);
/* There's no depth_in_front_tx in scene image renders. */
}
if (!DRW_state_is_image_render() || last_sample) {
smaa_weight_tx_.acquire(

View File

@ -826,6 +826,42 @@ bool match_slope_fcurve_segment(FCurve *fcu, FCurveSegment *segment, const float
/* ---------------- */
void shear_fcurve_segment(FCurve *fcu,
FCurveSegment *segment,
const float factor,
tShearDirection direction)
{
const BezTriple *left_key = fcurve_segment_start_get(fcu, segment->start_index);
const BezTriple *right_key = fcurve_segment_end_get(fcu, segment->start_index + segment->length);
const float key_x_range = right_key->vec[1][0] - left_key->vec[1][0];
const float key_y_range = right_key->vec[1][1] - left_key->vec[1][1];
/* Happens if there is only 1 key on the FCurve. Needs to be skipped because it
* would be a divide by 0. */
if (IS_EQF(key_x_range, 0.0f)) {
return;
}
for (int i = segment->start_index; i < segment->start_index + segment->length; i++) {
/* For easy calculation of the curve, the values are normalized. */
float normalized_x;
if (direction == SHEAR_FROM_LEFT) {
normalized_x = (fcu->bezt[i].vec[1][0] - left_key->vec[1][0]) / key_x_range;
}
else {
normalized_x = (right_key->vec[1][0] - fcu->bezt[i].vec[1][0]) / key_x_range;
}
const float y_delta = key_y_range * normalized_x;
const float key_y_value = fcu->bezt[i].vec[1][1] + y_delta * factor;
BKE_fcurve_keyframe_move_value_with_handles(&fcu->bezt[i], key_y_value);
}
}
/* ---------------- */
void breakdown_fcurve_segment(FCurve *fcu, FCurveSegment *segment, const float factor)
{
const BezTriple *left_bezt = fcurve_segment_start_get(fcu, segment->start_index);

View File

@ -87,7 +87,8 @@ static int bone_collection_add_exec(bContext *C, wmOperator * /* op */)
}
bArmature *armature = static_cast<bArmature *>(ob->data);
ANIM_armature_bonecoll_new(armature, nullptr);
BoneCollection *bcoll = ANIM_armature_bonecoll_new(armature, nullptr);
ANIM_armature_bonecoll_active_set(armature, bcoll);
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
return OPERATOR_FINISHED;
@ -465,13 +466,7 @@ static void bone_collection_select(bContext *C,
if (!editbone_is_member(ebone, bcoll)) {
continue;
}
if (select) {
ebone->flag |= BONE_SELECTED;
}
else {
ebone->flag &= ~BONE_SELECTED;
}
ED_armature_ebone_select_set(ebone, select);
}
}
else {
@ -494,7 +489,12 @@ static void bone_collection_select(bContext *C,
}
DEG_id_tag_update(&armature->id, ID_RECALC_SELECT);
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
if (is_editmode) {
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
}
else {
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
}
if (is_editmode) {
ED_outliner_select_sync_from_edit_bone_tag(C);

View File

@ -749,6 +749,7 @@ MenuType node_group_operator_assets_menu()
type.poll = asset_menu_poll;
type.draw = node_add_catalog_assets_draw;
type.listener = asset::asset_reading_region_listen_fn;
type.context_dependent = true;
return type;
}

View File

@ -458,6 +458,14 @@ void smooth_fcurve_segment(FCurve *fcu,
int kernel_size,
double *kernel);
void ease_fcurve_segment(FCurve *fcu, FCurveSegment *segment, float factor);
enum tShearDirection {
SHEAR_FROM_LEFT = 1,
SHEAR_FROM_RIGHT,
};
void shear_fcurve_segment(struct FCurve *fcu,
struct FCurveSegment *segment,
float factor,
tShearDirection direction);
/**
* Shift the FCurve segment up/down so that it aligns with the key before/after
* the segment.

View File

@ -36,12 +36,22 @@ void ED_operatortypes_uvedit();
void ED_operatormacros_uvedit();
void ED_keymap_uvedit(wmKeyConfig *keyconf);
bool ED_uvedit_minmax(const Scene *scene, Object *obedit, float min[2], float max[2]);
/**
* Be careful when using this, it bypasses all synchronization options.
*/
void ED_uvedit_select_all(BMesh *bm);
void ED_uvedit_foreach_uv(const Scene *scene,
BMesh *bm,
const bool skip_invisible,
const bool selected,
blender::FunctionRef<void(float[2])> user_fn);
void ED_uvedit_foreach_uv_multi(const Scene *scene,
Object **objects_edit,
uint objects_len,
const bool skip_invisible,
const bool skip_nonselected,
blender::FunctionRef<void(float[2])> user_fn);
bool ED_uvedit_minmax_multi(
const Scene *scene, Object **objects_edit, uint objects_len, float r_min[2], float r_max[2]);
bool ED_uvedit_center_multi(
@ -53,8 +63,6 @@ bool ED_uvedit_center_from_pivot_ex(SpaceImage *sima,
float r_center[2],
char mode,
bool *r_has_select);
bool ED_uvedit_center_from_pivot(
SpaceImage *sima, Scene *scene, ViewLayer *view_layer, float r_center[2], char mode);
bool ED_object_get_active_image(Object *ob,
int mat_nr,

View File

@ -145,23 +145,19 @@ enum {
/** #uiBlock.flag (controls) */
enum {
UI_BLOCK_LOOP = 1 << 0,
/** Indicate that items in a popup are drawn with inverted order. Used for arrow key navigation
* so that it knows to invert the navigation direction to match the drawing order. */
UI_BLOCK_IS_FLIP = 1 << 1,
UI_BLOCK_NO_FLIP = 1 << 2,
UI_BLOCK_NUMSELECT = 1 << 3,
UI_BLOCK_NUMSELECT = 1 << 1,
/** Don't apply window clipping. */
UI_BLOCK_NO_WIN_CLIP = 1 << 4,
UI_BLOCK_CLIPBOTTOM = 1 << 5,
UI_BLOCK_CLIPTOP = 1 << 6,
UI_BLOCK_MOVEMOUSE_QUIT = 1 << 7,
UI_BLOCK_KEEP_OPEN = 1 << 8,
UI_BLOCK_POPUP = 1 << 9,
UI_BLOCK_OUT_1 = 1 << 10,
UI_BLOCK_SEARCH_MENU = 1 << 11,
UI_BLOCK_POPUP_MEMORY = 1 << 12,
UI_BLOCK_NO_WIN_CLIP = 1 << 2,
UI_BLOCK_CLIPBOTTOM = 1 << 3,
UI_BLOCK_CLIPTOP = 1 << 4,
UI_BLOCK_MOVEMOUSE_QUIT = 1 << 5,
UI_BLOCK_KEEP_OPEN = 1 << 6,
UI_BLOCK_POPUP = 1 << 7,
UI_BLOCK_OUT_1 = 1 << 8,
UI_BLOCK_SEARCH_MENU = 1 << 9,
UI_BLOCK_POPUP_MEMORY = 1 << 10,
/** Stop handling mouse events. */
UI_BLOCK_CLIP_EVENTS = 1 << 13,
UI_BLOCK_CLIP_EVENTS = 1 << 11,
/* #uiBlock::flags bits 14-17 are identical to #uiBut::drawflag bits. */
@ -874,7 +870,6 @@ void UI_block_direction_set(uiBlock *block, char direction);
/**
* This call escapes if there's alignment flags.
*/
void UI_block_order_flip(uiBlock *block);
void UI_block_flag_enable(uiBlock *block, int flag);
void UI_block_flag_disable(uiBlock *block, int flag);
void UI_block_translate(uiBlock *block, int x, int y);
@ -1365,7 +1360,7 @@ void UI_but_context_ptr_set(uiBlock *block, uiBut *but, const char *name, const
const PointerRNA *UI_but_context_ptr_get(const uiBut *but,
const char *name,
const StructRNA *type CPP_ARG_DEFAULT(nullptr));
bContextStore *UI_but_context_get(const uiBut *but);
const bContextStore *UI_but_context_get(const uiBut *but);
void UI_but_unit_type_set(uiBut *but, int unit_type);
int UI_but_unit_type_get(const uiBut *but);
@ -2111,7 +2106,7 @@ uiBlock *uiLayoutGetBlock(uiLayout *layout);
void uiLayoutSetFunc(uiLayout *layout, uiMenuHandleFunc handlefunc, void *argv);
void uiLayoutSetContextPointer(uiLayout *layout, const char *name, PointerRNA *ptr);
bContextStore *uiLayoutGetContextStore(uiLayout *layout);
void uiLayoutContextCopy(uiLayout *layout, bContextStore *context);
void uiLayoutContextCopy(uiLayout *layout, const bContextStore *context);
/**
* Set tooltip function for all buttons in the layout.

View File

@ -3523,10 +3523,6 @@ void UI_block_free(const bContext *C, uiBlock *block)
MEM_freeN(block->func_argN);
}
LISTBASE_FOREACH_MUTABLE (bContextStore *, store, &block->contexts) {
CTX_store_free(store);
}
BLI_freelistN(&block->saferct);
BLI_freelistN(&block->color_pickers.list);
BLI_freelistN(&block->dynamic_listeners);
@ -4315,7 +4311,6 @@ static void ui_def_but_rna__menu(bContext * /*C*/, uiLayout *layout, void *but_p
if (!item->identifier[0]) {
/* inconsistent, but menus with categories do not look good flipped */
if (item->name) {
block->flag |= UI_BLOCK_NO_FLIP;
categories++;
entries_nosepr_count++;
}
@ -4347,8 +4342,8 @@ static void ui_def_but_rna__menu(bContext * /*C*/, uiLayout *layout, void *but_p
const char *title = RNA_property_ui_name(but->rnaprop);
if (title[0] && (categories == 0) && (block->flag & UI_BLOCK_NO_FLIP)) {
/* Title at the top for menus with categories. */
if (title[0] && !but->str[0] && (categories == 0)) {
/* Show title when no categories and calling button has no text. */
uiDefBut(block,
UI_BTYPE_LABEL,
0,
@ -4472,32 +4467,11 @@ static void ui_def_but_rna__menu(bContext * /*C*/, uiLayout *layout, void *but_p
}
}
if (title[0] && (categories == 0) && !(block->flag & UI_BLOCK_NO_FLIP)) {
/* Title at the bottom for menus without categories. */
uiItemS(layout);
uiDefBut(block,
UI_BTYPE_LABEL,
0,
title,
0,
0,
UI_UNIT_X * 5,
UI_UNIT_Y,
nullptr,
0.0,
0.0,
0,
0,
"");
}
UI_block_layout_set_current(block, layout);
if (free) {
MEM_freeN((void *)item_array);
}
BLI_assert((block->flag & UI_BLOCK_IS_FLIP) == 0);
block->flag |= UI_BLOCK_IS_FLIP;
}
static void ui_def_but_rna__panel_type(bContext *C, uiLayout *layout, void *but_p)
@ -4739,7 +4713,7 @@ static uiBut *ui_def_but_rna(uiBlock *block,
* access it. */
const PointerRNA pptr = RNA_property_pointer_get(ptr, prop);
if (pptr.data && RNA_struct_is_ID(pptr.type)) {
but->context = CTX_store_add(&block->contexts, "id", &pptr);
but->context = CTX_store_add(block->contexts, "id", &pptr);
}
}
@ -5852,39 +5826,6 @@ void UI_block_direction_set(uiBlock *block, char direction)
block->direction = direction;
}
void UI_block_order_flip(uiBlock *block)
{
float centy, miny = 10000, maxy = -10000;
if (U.uiflag & USER_MENUFIXEDORDER) {
return;
}
if (block->flag & UI_BLOCK_NO_FLIP) {
return;
}
LISTBASE_FOREACH (uiBut *, but, &block->buttons) {
if (but->drawflag & UI_BUT_ALIGN) {
return;
}
if (but->rect.ymin < miny) {
miny = but->rect.ymin;
}
if (but->rect.ymax > maxy) {
maxy = but->rect.ymax;
}
}
/* mirror trick */
centy = (miny + maxy) / 2.0f;
LISTBASE_FOREACH (uiBut *, but, &block->buttons) {
but->rect.ymin = centy - (but->rect.ymin - centy);
but->rect.ymax = centy - (but->rect.ymax - centy);
std::swap(but->rect.ymin, but->rect.ymax);
}
block->flag ^= UI_BLOCK_IS_FLIP;
}
void UI_block_flag_enable(uiBlock *block, int flag)
{
block->flag |= flag;
@ -5967,8 +5908,9 @@ PointerRNA *UI_but_operator_ptr_get(uiBut *but)
void UI_but_context_ptr_set(uiBlock *block, uiBut *but, const char *name, const PointerRNA *ptr)
{
but->context = CTX_store_add(&block->contexts, name, ptr);
but->context->used = true;
bContextStore *ctx = CTX_store_add(block->contexts, name, ptr);
ctx->used = true;
but->context = ctx;
}
const PointerRNA *UI_but_context_ptr_get(const uiBut *but, const char *name, const StructRNA *type)
@ -5976,7 +5918,7 @@ const PointerRNA *UI_but_context_ptr_get(const uiBut *but, const char *name, con
return CTX_store_ptr_lookup(but->context, name, type);
}
bContextStore *UI_but_context_get(const uiBut *but)
const bContextStore *UI_but_context_get(const uiBut *but)
{
return but->context;
}
@ -6666,7 +6608,7 @@ void UI_but_string_info_get(bContext *C, uiBut *but, ...)
tmp = BLI_strdup(WM_operatortype_name(but->optype, opptr).c_str());
}
else {
bContextStore *previous_ctx = CTX_store_get(C);
const bContextStore *previous_ctx = CTX_store_get(C);
CTX_store_set(C, but->context);
tmp = BLI_strdup(WM_operatortype_description(C, but->optype, opptr).c_str());
CTX_store_set(C, previous_ctx);

View File

@ -489,7 +489,7 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but, const wmEvent *ev
uiPopupMenu *pup;
uiLayout *layout;
bContextStore *previous_ctx = CTX_store_get(C);
const bContextStore *previous_ctx = CTX_store_get(C);
{
uiStringInfo label = {BUT_GET_LABEL, nullptr};
@ -946,7 +946,7 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but, const wmEvent *ev
if (view_item_but) {
BLI_assert(view_item_but->type == UI_BTYPE_VIEW_ITEM);
bContextStore *prev_ctx = CTX_store_get(C);
const bContextStore *prev_ctx = CTX_store_get(C);
/* Sub-layout for context override. */
uiLayout *sub = uiLayoutColumn(layout, false);
set_layout_context_from_button(C, sub, view_item_but);

View File

@ -503,7 +503,7 @@ struct uiAfterFunc {
uiBlockInteraction_CallbackData custom_interaction_callbacks;
uiBlockInteraction_Handle *custom_interaction_handle;
bContextStore *context;
std::optional<bContextStore> context;
char undostr[BKE_UNDO_STR_MAX];
char drawstr[UI_MAX_DRAW_STR];
@ -789,7 +789,7 @@ static void ui_handle_afterfunc_add_operator_ex(wmOperatorType *ot,
}
if (context_but && context_but->context) {
after->context = CTX_store_copy(context_but->context);
after->context = *context_but->context;
}
if (context_but) {
@ -905,7 +905,7 @@ static void ui_apply_but_func(bContext *C, uiBut *but)
}
if (but->context) {
after->context = CTX_store_copy(but->context);
after->context = *but->context;
}
ui_but_drawstr_without_sep_char(but, after->drawstr, sizeof(after->drawstr));
@ -1020,7 +1020,7 @@ static void ui_apply_but_funcs_after(bContext *C)
MEM_delete(afterf);
if (after.context) {
CTX_store_set(C, after.context);
CTX_store_set(C, &after.context.value());
}
if (after.popup_op) {
@ -1053,7 +1053,6 @@ static void ui_apply_but_funcs_after(bContext *C)
if (after.context) {
CTX_store_set(C, nullptr);
CTX_store_free(after.context);
}
if (after.func) {
@ -10483,19 +10482,18 @@ static int ui_handle_menu_event(bContext *C,
if (val == KM_PRESS) {
/* Determine scroll operation. */
uiMenuScrollType scrolltype;
const bool ui_block_flipped = (block->flag & UI_BLOCK_IS_FLIP) != 0;
if (ELEM(type, EVT_PAGEUPKEY, EVT_HOMEKEY)) {
scrolltype = ui_block_flipped ? MENU_SCROLL_TOP : MENU_SCROLL_BOTTOM;
scrolltype = MENU_SCROLL_TOP;
}
else if (ELEM(type, EVT_PAGEDOWNKEY, EVT_ENDKEY)) {
scrolltype = ui_block_flipped ? MENU_SCROLL_BOTTOM : MENU_SCROLL_TOP;
scrolltype = MENU_SCROLL_BOTTOM;
}
else if (ELEM(type, EVT_UPARROWKEY, WHEELUPMOUSE)) {
scrolltype = ui_block_flipped ? MENU_SCROLL_UP : MENU_SCROLL_DOWN;
scrolltype = MENU_SCROLL_UP;
}
else {
scrolltype = ui_block_flipped ? MENU_SCROLL_DOWN : MENU_SCROLL_UP;
scrolltype = MENU_SCROLL_DOWN;
}
if (ui_menu_pass_event_to_parent_if_nonactive(

View File

@ -202,7 +202,7 @@ struct uiBut {
uiButHandleNFunc funcN = nullptr;
void *func_argN = nullptr;
bContextStore *context = nullptr;
const bContextStore *context = nullptr;
uiButCompleteFunc autocomplete_func = nullptr;
void *autofunc_arg = nullptr;
@ -487,7 +487,7 @@ struct uiBlock {
ListBase layouts;
uiLayout *curlayout;
ListBase contexts;
blender::Vector<std::unique_ptr<bContextStore>> contexts;
/** A block can store "views" on data-sets. Currently tree-views (#AbstractTreeView) only.
* Others are imaginable, e.g. table-views, grid-views, etc. These are stored here to support

View File

@ -1290,7 +1290,6 @@ static void ui_item_menu_hold(bContext *C, ARegion *butregion, uiBut *but)
UI_popup_menu_but_set(pup, butregion, but);
block->flag |= UI_BLOCK_POPUP_HOLD;
block->flag |= UI_BLOCK_IS_FLIP;
char direction = UI_DIR_DOWN;
if (!but->drawstr[0]) {
@ -1554,9 +1553,6 @@ void uiItemsFullEnumO_items(uiLayout *layout,
if (item->name) {
if (item != item_array && !radial && split != nullptr) {
target = uiLayoutColumn(split, layout->align);
/* inconsistent, but menus with labels do not look good flipped */
block->flag |= UI_BLOCK_NO_FLIP;
}
uiBut *but;
@ -1647,7 +1643,7 @@ void uiItemsFullEnumO(uiLayout *layout,
}
else {
bContext *C = static_cast<bContext *>(block->evil_C);
bContextStore *previous_ctx = CTX_store_get(C);
const bContextStore *previous_ctx = CTX_store_get(C);
CTX_store_set(C, layout->context);
RNA_property_enum_items_gettexted(C, &ptr, prop, &item_array, &totitem, &free);
CTX_store_set(C, previous_ctx);
@ -1659,9 +1655,6 @@ void uiItemsFullEnumO(uiLayout *layout,
if (free) {
MEM_freeN((void *)item_array);
}
/* intentionally don't touch UI_BLOCK_IS_FLIP here,
* we don't know the context this is called in */
}
else if (prop && RNA_property_type(prop) != PROP_ENUM) {
RNA_warning("%s.%s, not an enum type", RNA_struct_identifier(ptr.type), propname);
@ -2723,8 +2716,6 @@ void uiItemsEnumR(uiLayout *layout, PointerRNA *ptr, const char *propname)
if (item[i].name) {
if (i != 0) {
column = uiLayoutColumn(split, false);
/* inconsistent, but menus with labels do not look good flipped */
block->flag |= UI_BLOCK_NO_FLIP;
}
uiItemL(column, item[i].name, ICON_NONE);
@ -2742,9 +2733,6 @@ void uiItemsEnumR(uiLayout *layout, PointerRNA *ptr, const char *propname)
if (free) {
MEM_freeN((void *)item);
}
/* intentionally don't touch UI_BLOCK_IS_FLIP here,
* we don't know the context this is called in */
}
/* Pointer RNA button with search */
@ -2955,20 +2943,13 @@ void uiItemPointerR(uiLayout *layout,
void ui_item_menutype_func(bContext *C, uiLayout *layout, void *arg_mt)
{
MenuType *mt = (MenuType *)arg_mt;
UI_menutype_draw(C, mt, layout);
/* Menus are created flipped (from event handling point of view). */
layout->root->block->flag ^= UI_BLOCK_IS_FLIP;
}
void ui_item_paneltype_func(bContext *C, uiLayout *layout, void *arg_pt)
{
PanelType *pt = (PanelType *)arg_pt;
UI_paneltype_draw(C, pt, layout);
/* Panels are created flipped (from event handling POV). */
layout->root->block->flag ^= UI_BLOCK_IS_FLIP;
}
static uiBut *ui_item_menu(uiLayout *layout,
@ -3096,7 +3077,7 @@ void uiItemMContents(uiLayout *layout, const char *menuname)
return;
}
bContextStore *previous_ctx = CTX_store_get(C);
const bContextStore *previous_ctx = CTX_store_get(C);
UI_menutype_draw(C, mt, layout);
/* Restore context that was cleared by `UI_menutype_draw`. */
@ -3576,8 +3557,6 @@ static void menu_item_enum_opname_menu(bContext * /*C*/, uiLayout *layout, void
uiLayoutSetOperatorContext(layout, lvl->opcontext);
uiItemsFullEnumO(layout, lvl->opname, lvl->propname, op_props, lvl->opcontext, UI_ITEM_NONE);
layout->root->block->flag |= UI_BLOCK_IS_FLIP;
/* override default, needed since this was assumed pre 2.70 */
UI_block_direction_set(layout->root->block, UI_DIR_DOWN);
}
@ -3668,7 +3647,6 @@ static void menu_item_enum_rna_menu(bContext * /*C*/, uiLayout *layout, void *ar
uiLayoutSetOperatorContext(layout, lvl->opcontext);
uiItemsEnumR(layout, &lvl->rnapoin, lvl->propname);
layout->root->block->flag |= UI_BLOCK_IS_FLIP;
}
void uiItemMenuEnumR_prop(
@ -5703,7 +5681,7 @@ void ui_layout_add_but(uiLayout *layout, uiBut *but)
if (layout->context) {
but->context = layout->context;
but->context->used = true;
layout->context->used = true;
}
if (layout->emboss != UI_EMBOSS_UNDEFINED) {
@ -5832,7 +5810,7 @@ bool UI_block_layout_needs_resolving(const uiBlock *block)
void uiLayoutSetContextPointer(uiLayout *layout, const char *name, PointerRNA *ptr)
{
uiBlock *block = layout->root->block;
layout->context = CTX_store_add(&block->contexts, name, ptr);
layout->context = CTX_store_add(block->contexts, name, ptr);
}
bContextStore *uiLayoutGetContextStore(uiLayout *layout)
@ -5840,10 +5818,10 @@ bContextStore *uiLayoutGetContextStore(uiLayout *layout)
return layout->context;
}
void uiLayoutContextCopy(uiLayout *layout, bContextStore *context)
void uiLayoutContextCopy(uiLayout *layout, const bContextStore *context)
{
uiBlock *block = layout->root->block;
layout->context = CTX_store_add_all(&block->contexts, context);
layout->context = CTX_store_add_all(block->contexts, context);
}
void uiLayoutSetTooltipFunc(uiLayout *layout,

View File

@ -188,9 +188,7 @@ static void ui_popup_menu_create_block(bContext *C,
const uiStyle *style = UI_style_get_dpi();
pup->block = UI_block_begin(C, nullptr, block_name, UI_EMBOSS_PULLDOWN);
if (!pup->but) {
pup->block->flag |= UI_BLOCK_NO_FLIP;
}
/* A title is only provided when a Menu has a label, this is not always the case, see e.g.
* `VIEW3D_MT_edit_mesh_context_menu` -- this specifies its own label inside the draw function
* depending on vertex/edge/face mode. We still want to flag the uiBlock (but only insert into
@ -360,7 +358,6 @@ static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, voi
if (RGN_TYPE_IS_HEADER_ANY(region->regiontype)) {
if (RGN_ALIGN_ENUM_FROM_MASK(region->alignment) == RGN_ALIGN_BOTTOM) {
UI_block_direction_set(block, UI_DIR_UP);
UI_block_order_flip(block);
}
}
}
@ -408,20 +405,6 @@ static uiPopupBlockHandle *ui_popup_menu_create(
pup->my = window->eventstate->xy[1];
pup->popup = true;
}
/* some enums reversing is strange, currently we have no good way to
* reverse some enum's but not others, so reverse all so the first menu
* items are always close to the mouse cursor */
else {
#if 0
/* if this is an rna button then we can assume its an enum
* flipping enums is generally not good since the order can be
* important #28786. */
if (but->rnaprop && RNA_property_type(but->rnaprop) == PROP_ENUM) {
pup->block->flag |= UI_BLOCK_NO_FLIP;
}
#endif
}
uiPopupBlockHandle *handle = ui_popup_block_create(
C, butregion, but, nullptr, ui_block_func_POPUP, pup, ui_block_free_func_POPUP);
@ -492,8 +475,6 @@ uiPopupMenu *UI_popup_menu_begin_ex(bContext *C,
pup->title = title;
ui_popup_menu_create_block(C, pup, title, block_name);
/* Further buttons will be laid out top to bottom by default. */
pup->block->flag |= UI_BLOCK_IS_FLIP;
/* create in advance so we can let buttons point to retval already */
pup->block->handle = MEM_cnew<uiPopupBlockHandle>(__func__);

View File

@ -107,8 +107,6 @@ static void ui_popover_create_block(bContext *C,
uiLayoutContextCopy(pup->layout, pup->but->context);
}
}
pup->block->flag |= UI_BLOCK_NO_FLIP;
}
static uiBlock *ui_block_func_POPOVER(bContext *C, uiPopupBlockHandle *handle, void *arg_pup)
@ -415,9 +413,6 @@ void UI_popover_end(bContext *C, uiPopover *pup, wmKeyMap *keymap)
* The begin/end stype of calling popups doesn't allow 'can_refresh' to be set.
* For now close this style of popovers when accessed. */
UI_block_flag_disable(pup->block, UI_BLOCK_KEEP_OPEN);
/* Panels are created flipped (from event handling POV). */
pup->block->flag ^= UI_BLOCK_IS_FLIP;
}
uiLayout *UI_popover_layout(uiPopover *pup)

View File

@ -253,11 +253,6 @@ static void ui_popup_block_position(wmWindow *window,
else {
offset_x = butrct.xmin - block->rect.xmin - center_x;
}
/* changed direction? */
if ((dir1 & block->direction) == 0) {
/* TODO: still do */
UI_block_order_flip(block);
}
}
else if (dir1 == UI_DIR_DOWN) {
offset_y = (butrct.ymin - block->rect.ymax) + offset_overlap;
@ -276,11 +271,6 @@ static void ui_popup_block_position(wmWindow *window,
else {
offset_x = butrct.xmin - block->rect.xmin - center_x;
}
/* changed direction? */
if ((dir1 & block->direction) == 0) {
/* TODO: still do */
UI_block_order_flip(block);
}
}
/* Center over popovers for eg. */

View File

@ -22,13 +22,14 @@
#include "DNA_shader_fx_types.h"
#include "DNA_texture_types.h"
#include "BLI_alloca.h"
#include "BLI_dynstr.h"
#include "BLI_ghash.h"
#include "BLI_linklist.h"
#include "BLI_listbase.h"
#include "BLI_map.hh"
#include "BLI_math_matrix.h"
#include "BLI_memarena.h"
#include "BLI_set.hh"
#include "BLI_stack.hh"
#include "BLI_string.h"
#include "BLI_string_search.hh"
#include "BLI_string_utils.h"
@ -75,7 +76,6 @@ struct MenuSearch_Context {
struct MenuSearch_Parent {
MenuSearch_Parent *parent;
MenuType *parent_mt;
const char *drawstr;
/** Set while writing menu items only. */
@ -86,8 +86,6 @@ struct MenuSearch_Item {
MenuSearch_Item *next, *prev;
const char *drawstr;
const char *drawwstr_full;
/** Support a single level sub-menu nesting (for operator buttons that expand). */
const char *drawstr_submenu;
int icon;
int state;
@ -105,7 +103,7 @@ struct MenuSearch_Item {
wmOperatorType *type;
PointerRNA *opptr;
wmOperatorCallContext opcontext;
bContextStore *context;
const bContextStore *context;
} op;
/** Property (only for check-box/boolean). */
@ -161,9 +159,9 @@ static const char *strdup_memarena_from_dynstr(MemArena *memarena, DynStr *dyn_s
static bool menu_items_from_ui_create_item_from_button(MenuSearch_Data *data,
MemArena *memarena,
MenuType *mt,
const char *drawstr_submenu,
uiBut *but,
MenuSearch_Context *wm_context)
MenuSearch_Context *wm_context,
MenuSearch_Parent *menu_parent)
{
MenuSearch_Item *item = nullptr;
@ -184,7 +182,7 @@ static bool menu_items_from_ui_create_item_from_button(MenuSearch_Data *data,
item->op.type = but->optype;
item->op.opcontext = but->opcontext;
item->op.context = but->context;
item->op.context = but->context ? MEM_new<bContextStore>(__func__, *but->context) : nullptr;
item->op.opptr = but->opptr;
but->opptr = nullptr;
}
@ -250,9 +248,9 @@ static bool menu_items_from_ui_create_item_from_button(MenuSearch_Data *data,
item->state = (but->flag &
(UI_BUT_DISABLED | UI_BUT_INACTIVE | UI_BUT_REDALERT | UI_BUT_HAS_SEP_CHAR));
item->mt = mt;
item->drawstr_submenu = drawstr_submenu ? strdup_memarena(memarena, drawstr_submenu) : nullptr;
item->wm_context = wm_context;
item->menu_parent = menu_parent;
BLI_addtail(&data->items, item);
return true;
@ -306,6 +304,14 @@ static bool menu_items_to_ui_button(MenuSearch_Item *item, uiBut *but)
return changed;
}
struct MenuStackEntry {
MenuType *mt = nullptr;
/** Used as parent in submenus. */
MenuSearch_Parent *self_as_parent = nullptr;
/** The menu might be context dependent. */
std::optional<bContextStore> context;
};
/**
* Populate \a menu_stack with menus from inspecting active key-maps for this context.
*/
@ -313,9 +319,9 @@ static void menu_types_add_from_keymap_items(bContext *C,
wmWindow *win,
ScrArea *area,
ARegion *region,
LinkNode **menuid_stack_p,
GHash *menu_to_kmi,
GSet *menu_tagged)
blender::Stack<MenuStackEntry> &menu_stack,
blender::Map<MenuType *, wmKeyMapItem *> &menu_to_kmi,
blender::Set<MenuType *> &menu_tagged)
{
wmWindowManager *wm = CTX_wm_manager(C);
ListBase *handlers[] = {
@ -353,14 +359,10 @@ static void menu_types_add_from_keymap_items(bContext *C,
RNA_string_get(kmi->ptr, "name", menu_idname);
MenuType *mt = WM_menutype_find(menu_idname, false);
if (mt && BLI_gset_add(menu_tagged, mt)) {
if (mt && menu_tagged.add(mt)) {
/* Unlikely, but possible this will be included twice. */
BLI_linklist_prepend(menuid_stack_p, mt);
void **kmi_p;
if (!BLI_ghash_ensure_p(menu_to_kmi, mt, &kmi_p)) {
*kmi_p = kmi;
}
menu_stack.push({mt});
menu_to_kmi.add(mt, kmi);
}
}
}
@ -430,9 +432,7 @@ static MenuSearch_Data *menu_items_from_ui_create(
bContext *C, wmWindow *win, ScrArea *area_init, ARegion *region_init, bool include_all_areas)
{
MemArena *memarena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
/** Map (#MenuType to #MenuSearch_Parent) */
GHash *menu_parent_map = BLI_ghash_ptr_new(__func__);
GHash *menu_display_name_map = BLI_ghash_ptr_new(__func__);
blender::Map<MenuType *, const char *> menu_display_name_map;
const uiStyle *style = UI_style_get_dpi();
/* Convert into non-ui structure. */
@ -441,14 +441,12 @@ static MenuSearch_Data *menu_items_from_ui_create(
DynStr *dyn_str = BLI_dynstr_new_memarena();
/* Use a stack of menus to handle and discover new menus in passes. */
LinkNode *menu_stack = nullptr;
blender::Stack<MenuStackEntry> menu_stack;
/* Tag menu types not to add, either because they have already been added
* or they have been blacklisted.
* Set of #MenuType. */
GSet *menu_tagged = BLI_gset_ptr_new(__func__);
/** Map (#MenuType -> #wmKeyMapItem). */
GHash *menu_to_kmi = BLI_ghash_ptr_new(__func__);
* or they have been blacklisted. */
blender::Set<MenuType *> menu_tagged;
blender::Map<MenuType *, wmKeyMapItem *> menu_to_kmi;
/* Blacklist menus we don't want to show. */
{
@ -462,7 +460,7 @@ static MenuSearch_Data *menu_items_from_ui_create(
for (int i = 0; i < ARRAY_SIZE(idname_array); i++) {
MenuType *mt = WM_menutype_find(idname_array[i], false);
if (mt != nullptr) {
BLI_gset_add(menu_tagged, mt);
menu_tagged.add(mt);
}
}
}
@ -479,7 +477,7 @@ static MenuSearch_Data *menu_items_from_ui_create(
for (WM_menutype_iter(&iter); !BLI_ghashIterator_done(&iter); BLI_ghashIterator_step(&iter)) {
MenuType *mt = (MenuType *)BLI_ghashIterator_getValue(&iter);
if (BLI_str_endswith(mt->idname, "_context_menu")) {
BLI_gset_add(menu_tagged, mt);
menu_tagged.add(mt);
}
}
const char *idname_array[] = {
@ -489,7 +487,7 @@ static MenuSearch_Data *menu_items_from_ui_create(
for (int i = 0; i < ARRAY_SIZE(idname_array); i++) {
MenuType *mt = WM_menutype_find(idname_array[i], false);
if (mt != nullptr) {
BLI_gset_remove(menu_tagged, mt, nullptr);
menu_tagged.remove(mt);
}
}
}
@ -562,8 +560,6 @@ static MenuSearch_Data *menu_items_from_ui_create(
global_menu_prefix = CTX_IFACE_(RNA_property_translation_context(prop_ui_type), "Top Bar");
}
GHashIterator iter;
for (int space_type_ui_index = -1; space_type_ui_index < space_type_ui_items_len;
space_type_ui_index += 1)
{
@ -653,8 +649,8 @@ static MenuSearch_Data *menu_items_from_ui_create(
MenuType *mt = WM_menutype_find(idname_array[i], false);
if (mt != nullptr) {
/* Check if this exists because of 'include_all_areas'. */
if (BLI_gset_add(menu_tagged, mt)) {
BLI_linklist_prepend(&menu_stack, mt);
if (menu_tagged.add(mt)) {
menu_stack.push({mt});
}
}
}
@ -664,8 +660,9 @@ static MenuSearch_Data *menu_items_from_ui_create(
bool has_keymap_menu_items = false;
while (menu_stack != nullptr) {
MenuType *mt = (MenuType *)BLI_linklist_pop(&menu_stack);
while (!menu_stack.is_empty()) {
MenuStackEntry current_menu = menu_stack.pop();
MenuType *mt = current_menu.mt;
if (!WM_menutype_poll(C, mt)) {
continue;
}
@ -676,6 +673,9 @@ static MenuSearch_Data *menu_items_from_ui_create(
UI_block_flag_enable(block, UI_BLOCK_SHOW_SHORTCUT_ALWAYS);
if (current_menu.context.has_value()) {
uiLayoutContextCopy(layout, &*current_menu.context);
}
uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_REGION_WIN);
UI_menutype_draw(C, mt, layout);
@ -694,21 +694,20 @@ static MenuSearch_Data *menu_items_from_ui_create(
}
if (but_test == nullptr) {
BLI_ghash_insert(
menu_display_name_map, mt, (void *)strdup_memarena(memarena, but->drawstr));
menu_display_name_map.add(mt, strdup_memarena(memarena, but->drawstr));
}
}
else if (menu_items_from_ui_create_item_from_button(
data, memarena, mt, nullptr, but, wm_context)) {
data, memarena, mt, but, wm_context, current_menu.self_as_parent))
{
/* pass */
}
else if ((mt_from_but = UI_but_menutype_get(but))) {
const bool uses_context = but->context && mt_from_but->context_dependent;
const bool tagged_first_time = menu_tagged.add(mt_from_but);
const bool scan_submenu = tagged_first_time || uses_context;
if (BLI_gset_add(menu_tagged, mt_from_but)) {
BLI_linklist_prepend(&menu_stack, mt_from_but);
}
if (!BLI_ghash_haskey(menu_parent_map, mt_from_but)) {
if (scan_submenu) {
MenuSearch_Parent *menu_parent = (MenuSearch_Parent *)BLI_memarena_calloc(
memarena, sizeof(*menu_parent));
/* Use brackets for menu key shortcuts,
@ -747,20 +746,23 @@ static MenuSearch_Data *menu_items_from_ui_create(
}
menu_parent->drawstr = strdup_memarena(memarena, drawstr);
}
menu_parent->parent_mt = mt;
BLI_ghash_insert(menu_parent_map, mt_from_but, menu_parent);
menu_parent->parent = current_menu.self_as_parent;
if (drawstr_is_empty) {
printf("Warning: '%s' menu has empty 'bl_label'.\n", mt_from_but->idname);
}
if (uses_context) {
menu_stack.push({mt_from_but, menu_parent, *but->context});
}
else {
menu_stack.push({mt_from_but, menu_parent});
}
}
}
else if (but->menu_create_func != nullptr) {
/* A non 'MenuType' menu button. */
/* Only expand one level deep, this is mainly for expanding operator menus. */
const char *drawstr_submenu = but->drawstr;
/* +1 to avoid overlap with the current 'block'. */
uiBlock *sub_block = UI_block_begin(C, region, __func__ + 1, UI_EMBOSS);
uiLayout *sub_layout = UI_block_layout(
@ -774,9 +776,14 @@ static MenuSearch_Data *menu_items_from_ui_create(
UI_block_end(C, sub_block);
MenuSearch_Parent *menu_parent = (MenuSearch_Parent *)BLI_memarena_calloc(
memarena, sizeof(*menu_parent));
menu_parent->drawstr = strdup_memarena(memarena, but->drawstr);
menu_parent->parent = current_menu.self_as_parent;
LISTBASE_FOREACH (uiBut *, sub_but, &sub_block->buttons) {
menu_items_from_ui_create_item_from_button(
data, memarena, mt, drawstr_submenu, sub_but, wm_context);
data, memarena, mt, sub_but, wm_context, menu_parent);
}
if (region) {
@ -794,24 +801,14 @@ static MenuSearch_Data *menu_items_from_ui_create(
/* Add key-map items as a second pass,
* so all menus are accessed from the header & top-bar before key shortcuts are expanded. */
if ((menu_stack == nullptr) && (has_keymap_menu_items == false)) {
if (menu_stack.is_empty() && (has_keymap_menu_items == false)) {
has_keymap_menu_items = true;
menu_types_add_from_keymap_items(
C, win, area, region, &menu_stack, menu_to_kmi, menu_tagged);
C, win, area, region, menu_stack, menu_to_kmi, menu_tagged);
}
}
}
LISTBASE_FOREACH (MenuSearch_Item *, item, &data->items) {
item->menu_parent = (MenuSearch_Parent *)BLI_ghash_lookup(menu_parent_map, item->mt);
}
GHASH_ITER (iter, menu_parent_map) {
MenuSearch_Parent *menu_parent = (MenuSearch_Parent *)BLI_ghashIterator_getValue(&iter);
menu_parent->parent = (MenuSearch_Parent *)BLI_ghash_lookup(menu_parent_map,
menu_parent->parent_mt);
}
/* NOTE: currently this builds the full path for each menu item,
* that could be moved into the parent menu. */
@ -841,13 +838,13 @@ static MenuSearch_Data *menu_items_from_ui_create(
}
}
else {
const char *drawstr = (const char *)BLI_ghash_lookup(menu_display_name_map, item->mt);
const char *drawstr = menu_display_name_map.lookup_default(item->mt, nullptr);
if (drawstr == nullptr) {
drawstr = CTX_IFACE_(item->mt->translation_context, item->mt->label);
}
BLI_dynstr_append(dyn_str, drawstr);
wmKeyMapItem *kmi = (wmKeyMapItem *)BLI_ghash_lookup(menu_to_kmi, item->mt);
wmKeyMapItem *kmi = menu_to_kmi.lookup_default(item->mt, nullptr);
if (kmi != nullptr) {
char kmi_str[128];
WM_keymap_item_to_string(kmi, false, kmi_str, sizeof(kmi_str));
@ -857,12 +854,6 @@ static MenuSearch_Data *menu_items_from_ui_create(
BLI_dynstr_append(dyn_str, " " UI_MENU_ARROW_SEP " ");
}
/* Optional nested menu. */
if (item->drawstr_submenu != nullptr) {
BLI_dynstr_append(dyn_str, item->drawstr_submenu);
BLI_dynstr_append(dyn_str, " " UI_MENU_ARROW_SEP " ");
}
BLI_dynstr_append(dyn_str, item->drawstr);
item->drawwstr_full = strdup_memarena_from_dynstr(memarena, dyn_str);
@ -875,13 +866,6 @@ static MenuSearch_Data *menu_items_from_ui_create(
* NOTE: we might want to keep the in-menu order, for now sort all. */
BLI_listbase_sort(&data->items, menu_item_sort_by_drawstr_full);
BLI_ghash_free(menu_parent_map, nullptr, nullptr);
BLI_ghash_free(menu_display_name_map, nullptr, nullptr);
BLI_ghash_free(menu_to_kmi, nullptr, nullptr);
BLI_gset_free(menu_tagged, nullptr);
data->memarena = memarena;
if (include_all_areas) {
@ -921,6 +905,7 @@ static void menu_search_arg_free_fn(void *data_v)
WM_operator_properties_free(item->op.opptr);
MEM_freeN(item->op.opptr);
}
MEM_delete(item->op.context);
break;
}
case MenuSearch_Item::Type::RNA: {

View File

@ -2986,8 +2986,6 @@ static void constraint_ops_extra_draw(bContext *C, uiLayout *layout, void *con_v
uiLayoutSetUnitsX(layout, 4.0f);
UI_block_flag_enable(uiLayoutGetBlock(layout), UI_BLOCK_IS_FLIP);
/* Apply. */
uiItemO(layout,
CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Apply"),
@ -3863,7 +3861,7 @@ static uiBlock *ui_icon_view_menu_cb(bContext *C, ARegion *region, void *arg_lit
const int h = UI_UNIT_X * (args.icon_scale + args.show_labels);
uiBlock *block = UI_block_begin(C, region, "_popup", UI_EMBOSS_PULLDOWN);
UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_NO_FLIP);
UI_block_flag_enable(block, UI_BLOCK_LOOP);
UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP);
bool free;

View File

@ -36,9 +36,9 @@
# include "DEG_depsgraph.h"
# include "IO_orientation.h"
# include "IO_path_util_types.h"
# include "IO_wavefront_obj.h"
# include "IO_orientation.hh"
# include "IO_path_util_types.hh"
# include "IO_wavefront_obj.hh"
# include "io_obj.hh"
# include "io_utils.hh"
@ -83,8 +83,9 @@ static int wm_obj_export_exec(bContext *C, wmOperator *op)
export_params.start_frame = RNA_int_get(op->ptr, "start_frame");
export_params.end_frame = RNA_int_get(op->ptr, "end_frame");
export_params.forward_axis = eIOAxis(RNA_enum_get(op->ptr, "forward_axis"));
export_params.up_axis = eIOAxis(RNA_enum_get(op->ptr, "up_axis"));
export_params.forward_axis = blender::math::AxisSigned::from_int(
RNA_enum_get(op->ptr, "forward_axis"));
export_params.up_axis = blender::math::AxisSigned::from_int(RNA_enum_get(op->ptr, "up_axis"));
export_params.global_scale = RNA_float_get(op->ptr, "global_scale");
export_params.apply_modifiers = RNA_boolean_get(op->ptr, "apply_modifiers");
export_params.export_eval_mode = eEvaluationMode(RNA_enum_get(op->ptr, "export_eval_mode"));
@ -287,11 +288,7 @@ void WM_OT_obj_export(wmOperatorType *ot)
INT_MIN,
INT_MAX);
/* Object transform options. */
prop = RNA_def_enum(
ot->srna, "forward_axis", io_transform_axis, IO_AXIS_NEGATIVE_Z, "Forward Axis", "");
RNA_def_property_update_runtime(prop, io_ui_forward_axis_update);
prop = RNA_def_enum(ot->srna, "up_axis", io_transform_axis, IO_AXIS_Y, "Up Axis", "");
RNA_def_property_update_runtime(prop, io_ui_up_axis_update);
io_ui_axes_register(*ot->srna);
RNA_def_float(
ot->srna,
"global_scale",
@ -393,8 +390,9 @@ static int wm_obj_import_exec(bContext *C, wmOperator *op)
RNA_string_get(op->ptr, "filepath", import_params.filepath);
import_params.global_scale = RNA_float_get(op->ptr, "global_scale");
import_params.clamp_size = RNA_float_get(op->ptr, "clamp_size");
import_params.forward_axis = eIOAxis(RNA_enum_get(op->ptr, "forward_axis"));
import_params.up_axis = eIOAxis(RNA_enum_get(op->ptr, "up_axis"));
import_params.forward_axis = blender::math::AxisSigned::from_int(
RNA_enum_get(op->ptr, "forward_axis"));
import_params.up_axis = blender::math::AxisSigned::from_int(RNA_enum_get(op->ptr, "up_axis"));
import_params.use_split_objects = RNA_boolean_get(op->ptr, "use_split_objects");
import_params.use_split_groups = RNA_boolean_get(op->ptr, "use_split_groups");
import_params.import_vertex_groups = RNA_boolean_get(op->ptr, "import_vertex_groups");
@ -517,11 +515,7 @@ void WM_OT_obj_import(wmOperatorType *ot)
"Resize the objects to keep bounding box under this value. Value 0 disables clamping",
0.0f,
1000.0f);
prop = RNA_def_enum(
ot->srna, "forward_axis", io_transform_axis, IO_AXIS_NEGATIVE_Z, "Forward Axis", "");
RNA_def_property_update_runtime(prop, io_ui_forward_axis_update);
prop = RNA_def_enum(ot->srna, "up_axis", io_transform_axis, IO_AXIS_Y, "Up Axis", "");
RNA_def_property_update_runtime(prop, io_ui_up_axis_update);
io_ui_axes_register(*ot->srna);
RNA_def_boolean(ot->srna,
"use_split_objects",
true,

View File

@ -32,10 +32,10 @@
# include "DEG_depsgraph.h"
# include "IO_orientation.h"
# include "IO_path_util_types.h"
# include "IO_orientation.hh"
# include "IO_path_util_types.hh"
# include "IO_ply.h"
# include "IO_ply.hh"
# include "io_ply_ops.hh"
# include "io_utils.hh"
@ -72,8 +72,9 @@ static int wm_ply_export_exec(bContext *C, wmOperator *op)
RNA_string_get(op->ptr, "filepath", export_params.filepath);
export_params.blen_filepath = CTX_data_main(C)->filepath;
export_params.forward_axis = eIOAxis(RNA_enum_get(op->ptr, "forward_axis"));
export_params.up_axis = eIOAxis(RNA_enum_get(op->ptr, "up_axis"));
export_params.forward_axis = blender::math::AxisSigned::from_int(
RNA_enum_get(op->ptr, "forward_axis"));
export_params.up_axis = blender::math::AxisSigned::from_int(RNA_enum_get(op->ptr, "up_axis"));
export_params.global_scale = RNA_float_get(op->ptr, "global_scale");
export_params.apply_modifiers = RNA_boolean_get(op->ptr, "apply_modifiers");
@ -178,10 +179,7 @@ void WM_OT_ply_export(wmOperatorType *ot)
FILE_SORT_DEFAULT);
/* Object transform options. */
prop = RNA_def_enum(ot->srna, "forward_axis", io_transform_axis, IO_AXIS_Y, "Forward Axis", "");
RNA_def_property_update_runtime(prop, io_ui_forward_axis_update);
prop = RNA_def_enum(ot->srna, "up_axis", io_transform_axis, IO_AXIS_Z, "Up Axis", "");
RNA_def_property_update_runtime(prop, io_ui_up_axis_update);
io_ui_axes_register(*ot->srna);
RNA_def_float(
ot->srna,
"global_scale",
@ -235,8 +233,8 @@ void WM_OT_ply_export(wmOperatorType *ot)
static int wm_ply_import_exec(bContext *C, wmOperator *op)
{
PLYImportParams params{};
params.forward_axis = eIOAxis(RNA_enum_get(op->ptr, "forward_axis"));
params.up_axis = eIOAxis(RNA_enum_get(op->ptr, "up_axis"));
params.forward_axis = blender::math::AxisSigned::from_int(RNA_enum_get(op->ptr, "forward_axis"));
params.up_axis = blender::math::AxisSigned::from_int(RNA_enum_get(op->ptr, "up_axis"));
params.use_scene_unit = RNA_boolean_get(op->ptr, "use_scene_unit");
params.global_scale = RNA_float_get(op->ptr, "global_scale");
params.merge_verts = RNA_boolean_get(op->ptr, "merge_verts");
@ -330,10 +328,7 @@ void WM_OT_ply_import(wmOperatorType *ot)
false,
"Scene Unit",
"Apply current scene's unit (as defined by unit scale) to imported data");
prop = RNA_def_enum(ot->srna, "forward_axis", io_transform_axis, IO_AXIS_Y, "Forward Axis", "");
RNA_def_property_update_runtime(prop, io_ui_forward_axis_update);
prop = RNA_def_enum(ot->srna, "up_axis", io_transform_axis, IO_AXIS_Z, "Up Axis", "");
RNA_def_property_update_runtime(prop, io_ui_up_axis_update);
io_ui_axes_register(*ot->srna);
RNA_def_boolean(ot->srna, "merge_verts", false, "Merge Vertices", "Merges vertices by distance");
RNA_def_enum(ot->srna,
"import_colors",

View File

@ -26,15 +26,19 @@
# include "UI_interface.hh"
# include "UI_resources.hh"
# include "IO_stl.h"
# include "UI_interface.hh"
# include "UI_resources.hh"
# include "IO_orientation.hh"
# include "IO_stl.hh"
# include "io_stl_ops.hh"
# include "io_utils.hh"
static int wm_stl_import_exec(bContext *C, wmOperator *op)
{
STLImportParams params{};
params.forward_axis = eIOAxis(RNA_enum_get(op->ptr, "forward_axis"));
params.up_axis = eIOAxis(RNA_enum_get(op->ptr, "up_axis"));
params.forward_axis = blender::math::AxisSigned::from_int(RNA_enum_get(op->ptr, "forward_axis"));
params.up_axis = blender::math::AxisSigned::from_int(RNA_enum_get(op->ptr, "up_axis"));
params.use_facet_normal = RNA_boolean_get(op->ptr, "use_facet_normal");
params.use_scene_unit = RNA_boolean_get(op->ptr, "use_scene_unit");
params.global_scale = RNA_float_get(op->ptr, "global_scale");
@ -146,8 +150,7 @@ void WM_OT_stl_import(wmOperatorType *ot)
false,
"Facet Normals",
"Use (import) facet normals (note that this will still give flat shading)");
RNA_def_enum(ot->srna, "forward_axis", io_transform_axis, IO_AXIS_Y, "Forward Axis", "");
RNA_def_enum(ot->srna, "up_axis", io_transform_axis, IO_AXIS_Z, "Up Axis", "");
io_ui_axes_register(*ot->srna);
RNA_def_boolean(ot->srna,
"use_mesh_validate",
false,

View File

@ -825,10 +825,6 @@ static void undomesh_to_editmesh(UndoMesh *um, Object *ob, BMEditMesh *em)
em_tmp = BKE_editmesh_create(bm);
*em = *em_tmp;
/* Normals should not be stored in the undo mesh, so recalculate them. The edit
* mesh is expected to have valid normals and there is no tracked dirty state. */
BLI_assert(BKE_mesh_vert_normals_are_dirty(&um->me));
/* Calculate face normals and tessellation at once since it's multi-threaded. */
BKE_editmesh_looptri_and_normals_calc(em);

View File

@ -36,6 +36,7 @@
#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_mesh.hh"
#include "BKE_node_runtime.hh"
#include "BKE_object.h"
#include "BKE_pointcloud.h"
#include "BKE_report.h"
@ -98,7 +99,14 @@ static void calculate_simulation_job_startjob(void *customdata,
LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) {
if (md->type == eModifierType_Nodes) {
NodesModifierData *nmd = reinterpret_cast<NodesModifierData *>(md);
nmd->runtime->simulation_cache->reset();
if (!nmd->runtime->simulation_cache) {
continue;
}
for (auto item : nmd->runtime->simulation_cache->cache_by_zone_id.items()) {
if (item.value->cache_state != CacheState::Baked) {
item.value->reset();
}
}
}
}
objects_to_calc.append(object);
@ -214,10 +222,15 @@ static bool bake_simulation_poll(bContext *C)
return true;
}
struct ZoneBakeData {
int zone_id;
bke::bake_paths::BakePath path;
std::unique_ptr<bke::BDataSharing> bdata_sharing;
};
struct ModifierBakeData {
NodesModifierData *nmd;
std::string absolute_bake_dir;
std::unique_ptr<bke::BDataSharing> bdata_sharing;
Vector<ZoneBakeData> zones;
};
struct ObjectBakeData {
@ -251,19 +264,38 @@ static void bake_simulation_job_startjob(void *customdata,
continue;
}
const char *base_path = ID_BLEND_PATH(job.bmain, &object->id);
ObjectBakeData bake_data;
bake_data.object = object;
LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) {
if (md->type == eModifierType_Nodes) {
NodesModifierData *nmd = reinterpret_cast<NodesModifierData *>(md);
nmd->runtime->simulation_cache->reset();
char absolute_bake_dir[FILE_MAX];
STRNCPY(absolute_bake_dir, nmd->simulation_bake_directory);
BLI_path_abs(absolute_bake_dir, base_path);
bake_data.modifiers.append(
{nmd, absolute_bake_dir, std::make_unique<bke::BDataSharing>()});
if (!nmd->node_group) {
continue;
}
if (!nmd->runtime->simulation_cache) {
continue;
}
ModifierBakeData modifier_bake_data;
modifier_bake_data.nmd = nmd;
for (auto item : nmd->runtime->simulation_cache->cache_by_zone_id.items()) {
item.value->reset();
}
for (const bNestedNodeRef &nested_node_ref : nmd->node_group->nested_node_refs_span()) {
ZoneBakeData zone_bake_data;
zone_bake_data.zone_id = nested_node_ref.id;
zone_bake_data.bdata_sharing = std::make_unique<bke::BDataSharing>();
if (std::optional<bke::bake_paths::BakePath> path =
bke::sim::get_simulation_zone_bake_path(
*job.bmain, *object, *nmd, nested_node_ref.id))
{
zone_bake_data.path = std::move(*path);
modifier_bake_data.zones.append(std::move(zone_bake_data));
}
}
bake_data.modifiers.append(std::move(modifier_bake_data));
}
}
objects_to_bake.append(std::move(bake_data));
@ -288,51 +320,56 @@ static void bake_simulation_job_startjob(void *customdata,
job.scene->r.cfra = frame.frame();
job.scene->r.subframe = frame.subframe();
char frame_file_c_str[64];
SNPRINTF(frame_file_c_str, "%011.5f", double(frame));
BLI_string_replace_char(frame_file_c_str, '.', '_');
const StringRefNull frame_file_str = frame_file_c_str;
BKE_scene_graph_update_for_newframe(job.depsgraph);
const std::string frame_file_name = bke::bake_paths::frame_to_file_name(frame);
for (ObjectBakeData &object_bake_data : objects_to_bake) {
for (ModifierBakeData &modifier_bake_data : object_bake_data.modifiers) {
NodesModifierData &nmd = *modifier_bake_data.nmd;
if (!nmd.runtime->simulation_cache) {
continue;
const ModifierSimulationCache &simulation_cache = *nmd.runtime->simulation_cache;
for (ZoneBakeData &zone_bake_data : modifier_bake_data.zones) {
if (!simulation_cache.cache_by_zone_id.contains(zone_bake_data.zone_id)) {
continue;
}
const SimulationZoneCache &zone_cache = *simulation_cache.cache_by_zone_id.lookup(
zone_bake_data.zone_id);
if (zone_cache.frame_caches.is_empty()) {
continue;
}
const SimulationZoneFrameCache &frame_cache = *zone_cache.frame_caches.last();
if (frame_cache.frame != frame) {
continue;
}
const bke::bake_paths::BakePath path = zone_bake_data.path;
const std::string bdata_file_name = frame_file_name + ".bdata";
char bdata_path[FILE_MAX];
BLI_path_join(
bdata_path, sizeof(bdata_path), path.bdata_dir.c_str(), bdata_file_name.c_str());
char meta_path[FILE_MAX];
BLI_path_join(meta_path,
sizeof(meta_path),
path.meta_dir.c_str(),
(frame_file_name + ".json").c_str());
BLI_file_ensure_parent_dir_exists(meta_path);
BLI_file_ensure_parent_dir_exists(bdata_path);
fstream bdata_file{bdata_path, std::ios::out | std::ios::binary};
bke::DiskBDataWriter bdata_writer{bdata_file_name, bdata_file, 0};
io::serialize::DictionaryValue io_root;
io_root.append_int("version", simulation_file_storage_version);
io::serialize::DictionaryValue &io_items = *io_root.append_dict("items");
for (auto item : frame_cache.items.items()) {
io::serialize::DictionaryValue &io_item = *io_items.append_dict(
std::to_string(item.key));
bke::serialize_bake_item(
*item.value, bdata_writer, *zone_bake_data.bdata_sharing, io_item);
}
io::serialize::write_json_file(meta_path, io_root);
}
ModifierSimulationCache &sim_cache = *nmd.runtime->simulation_cache;
const ModifierSimulationState *sim_state = sim_cache.get_state_at_exact_frame(frame);
if (sim_state == nullptr || sim_state->zone_states_.is_empty()) {
continue;
}
const std::string bdata_file_name = frame_file_str + ".bdata";
const std::string meta_file_name = frame_file_str + ".json";
char bdata_path[FILE_MAX];
BLI_path_join(bdata_path,
sizeof(bdata_path),
modifier_bake_data.absolute_bake_dir.c_str(),
"bdata",
bdata_file_name.c_str());
char meta_path[FILE_MAX];
BLI_path_join(meta_path,
sizeof(meta_path),
modifier_bake_data.absolute_bake_dir.c_str(),
"meta",
meta_file_name.c_str());
BLI_file_ensure_parent_dir_exists(bdata_path);
fstream bdata_file{bdata_path, std::ios::out | std::ios::binary};
bke::DiskBDataWriter bdata_writer{bdata_file_name, bdata_file, 0};
io::serialize::DictionaryValue io_root;
bke::sim::serialize_modifier_simulation_state(
*sim_state, bdata_writer, *modifier_bake_data.bdata_sharing, io_root);
BLI_file_ensure_parent_dir_exists(meta_path);
io::serialize::write_json_file(meta_path, io_root);
}
}
@ -343,9 +380,13 @@ static void bake_simulation_job_startjob(void *customdata,
for (ObjectBakeData &object_bake_data : objects_to_bake) {
for (ModifierBakeData &modifier_bake_data : object_bake_data.modifiers) {
NodesModifierData &nmd = *modifier_bake_data.nmd;
if (nmd.runtime->simulation_cache) {
/* Tag the caches as being baked so that they are not changed anymore. */
nmd.runtime->simulation_cache->cache_state = CacheState::Baked;
for (ZoneBakeData &zone_bake_data : modifier_bake_data.zones) {
if (std::unique_ptr<SimulationZoneCache> &zone_cache =
nmd.runtime->simulation_cache->cache_by_zone_id.lookup(zone_bake_data.zone_id))
{
/* Tag the caches as being baked so that they are not changed anymore. */
zone_cache->cache_state = CacheState::Baked;
}
}
}
DEG_id_tag_update(&object_bake_data.object->id, ID_RECALC_GEOMETRY);
@ -593,40 +634,45 @@ static int delete_baked_simulation_exec(bContext *C, wmOperator *op)
}
for (Object *object : objects) {
const char *base_path = ID_BLEND_PATH(bmain, &object->id);
LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) {
if (md->type == eModifierType_Nodes) {
NodesModifierData *nmd = reinterpret_cast<NodesModifierData *>(md);
nmd->runtime->simulation_cache->reset();
if (StringRef(nmd->simulation_bake_directory).is_empty()) {
if (!nmd->runtime->simulation_cache) {
continue;
}
char absolute_bake_dir[FILE_MAX];
STRNCPY(absolute_bake_dir, nmd->simulation_bake_directory);
BLI_path_abs(absolute_bake_dir, base_path);
for (auto item : nmd->runtime->simulation_cache->cache_by_zone_id.items()) {
item.value->reset();
char meta_dir[FILE_MAX];
BLI_path_join(meta_dir, sizeof(meta_dir), absolute_bake_dir, "meta");
char bdata_dir[FILE_MAX];
BLI_path_join(bdata_dir, sizeof(bdata_dir), absolute_bake_dir, "bdata");
const std::optional<bke::bake_paths::BakePath> bake_path =
bke::sim::get_simulation_zone_bake_path(*bmain, *object, *nmd, item.key);
if (!bake_path) {
continue;
}
if (BLI_exists(absolute_bake_dir)) {
const char *meta_dir = bake_path->meta_dir.c_str();
if (BLI_exists(meta_dir)) {
if (BLI_delete(meta_dir, true, true)) {
BKE_reportf(op->reports, RPT_ERROR, "Failed to remove meta directory %s", meta_dir);
}
}
const char *bdata_dir = bake_path->bdata_dir.c_str();
if (BLI_exists(bdata_dir)) {
if (BLI_delete(bdata_dir, true, true)) {
BKE_reportf(
op->reports, RPT_ERROR, "Failed to remove bdata directory %s", bdata_dir);
}
}
/* Delete the folder if it's empty. */
BLI_delete(absolute_bake_dir, true, false);
if (bake_path->bake_dir.has_value()) {
const char *zone_bake_dir = bake_path->bake_dir->c_str();
/* Try to delete zone bake directory if it is empty. */
BLI_delete(zone_bake_dir, true, false);
}
}
else {
BKE_reportf(op->reports, RPT_ERROR, "Bake directory %s not found", absolute_bake_dir);
if (const std::optional<std::string> modifier_bake_dir =
bke::sim::get_modifier_simulation_bake_path(*bmain, *object, *nmd))
{
/* Try to delete modifier bake directory if it is empty. */
BLI_delete(modifier_bake_dir->c_str(), true, false);
}
}
}

View File

@ -2062,8 +2062,6 @@ static void move_to_collection_menu_create(bContext *C, uiLayout *layout, void *
MoveToCollectionData *menu = static_cast<MoveToCollectionData *>(menu_v);
const char *name = BKE_collection_ui_name_get(menu->collection);
UI_block_flag_enable(uiLayoutGetBlock(layout), UI_BLOCK_IS_FLIP);
WM_operator_properties_create_ptr(&menu->ptr, menu->ot);
RNA_int_set(&menu->ptr, "collection_index", menu->index);
RNA_boolean_set(&menu->ptr, "is_new", true);

View File

@ -473,8 +473,6 @@ static void workspace_add_menu(bContext * /*C*/, uiLayout *layout, void *templat
WorkspaceConfigFileData *startup_config = workspace_config_file_read(app_template);
WorkspaceConfigFileData *builtin_config = workspace_system_file_read(app_template);
UI_block_flag_enable(uiLayoutGetBlock(layout), UI_BLOCK_IS_FLIP);
if (startup_config) {
LISTBASE_FOREACH (WorkSpace *, workspace, &startup_config->workspaces) {
uiLayout *row = uiLayoutRow(layout, false);

View File

@ -748,19 +748,30 @@ static void timeline_cache_draw_single(PTCacheID *pid, float y_offset, float hei
}
static void timeline_cache_draw_simulation_nodes(
const Scene &scene,
const blender::bke::sim::ModifierSimulationCache &cache,
const float y_offset,
const float height,
const uint pos_id)
{
std::lock_guard lock{cache.mutex};
if (cache.cache_by_zone_id.is_empty()) {
return;
}
/* Draw the state if one of the simulation zones. This is fine for now, because there is no ui
* that allows caching zones independently. */
const blender::bke::sim::SimulationZoneCache &zone_cache =
**cache.cache_by_zone_id.values().begin();
if (zone_cache.frame_caches.is_empty()) {
return;
}
GPU_matrix_push();
GPU_matrix_translate_2f(0.0, float(V2D_SCROLL_HANDLE_HEIGHT) + y_offset);
GPU_matrix_scale_2f(1.0, height);
float color[4];
UI_GetThemeColor4fv(TH_SIMULATED_FRAMES, color);
switch (cache.cache_state) {
switch (zone_cache.cache_state) {
case blender::bke::sim::CacheState::Invalid: {
color[3] = 0.4f;
break;
@ -777,16 +788,13 @@ static void timeline_cache_draw_simulation_nodes(
immUniformColor4fv(color);
const int start_frame = scene.r.sfra;
const int end_frame = scene.r.efra;
const int frames_num = end_frame - start_frame + 1;
const blender::IndexRange frames_range(start_frame, frames_num);
immBeginAtMost(GPU_PRIM_TRIS, zone_cache.frame_caches.size() * 6);
immBeginAtMost(GPU_PRIM_TRIS, frames_num * 6);
for (const int frame : frames_range) {
if (cache.has_state_at_frame(frame)) {
immRectf_fast(pos_id, frame - 0.5f, 0, frame + 0.5f, 1.0f);
}
for (const std::unique_ptr<blender::bke::sim::SimulationZoneFrameCache> &frame_cache :
zone_cache.frame_caches.as_span())
{
const int frame = frame_cache->frame.frame();
immRectf_fast(pos_id, frame - 0.5f, 0, frame + 0.5f, 1.0f);
}
immEnd();
@ -840,7 +848,7 @@ void timeline_draw_cache(const SpaceAction *saction, const Object *ob, const Sce
continue;
}
timeline_cache_draw_simulation_nodes(
*scene, *nmd->runtime->simulation_cache, y_offset, cache_draw_height, pos_id);
*nmd->runtime->simulation_cache, y_offset, cache_draw_height, pos_id);
y_offset += cache_draw_height;
}
}

View File

@ -533,8 +533,6 @@ static void template_texture_user_menu(bContext *C, uiLayout *layout, void * /*a
last_category = user->category;
}
UI_block_flag_enable(block, UI_BLOCK_NO_FLIP);
}
void uiTemplateTextureUser(uiLayout *layout, bContext *C)

View File

@ -122,6 +122,7 @@ void GRAPH_OT_ease(struct wmOperatorType *ot);
void GRAPH_OT_blend_offset(struct wmOperatorType *ot);
void GRAPH_OT_blend_to_ease(struct wmOperatorType *ot);
void GRAPH_OT_match_slope(struct wmOperatorType *ot);
void GRAPH_OT_shear(struct wmOperatorType *ot);
void GRAPH_OT_decimate(struct wmOperatorType *ot);
void GRAPH_OT_blend_to_default(struct wmOperatorType *ot);
void GRAPH_OT_butterworth_smooth(struct wmOperatorType *ot);

View File

@ -469,6 +469,7 @@ void graphedit_operatortypes()
WM_operatortype_append(GRAPH_OT_blend_to_neighbor);
WM_operatortype_append(GRAPH_OT_breakdown);
WM_operatortype_append(GRAPH_OT_ease);
WM_operatortype_append(GRAPH_OT_shear);
WM_operatortype_append(GRAPH_OT_blend_offset);
WM_operatortype_append(GRAPH_OT_blend_to_ease);
WM_operatortype_append(GRAPH_OT_match_slope);

View File

@ -1162,8 +1162,8 @@ void GRAPH_OT_blend_to_ease(wmOperatorType *ot)
0.0f,
-FLT_MAX,
FLT_MAX,
"Curve Bend",
"Control the bend of the curve",
"Blend",
"Favor either original data or ease curve",
-1.0f,
1.0f);
}
@ -1290,6 +1290,176 @@ void GRAPH_OT_match_slope(wmOperatorType *ot)
1.0f);
}
/* -------------------------------------------------------------------- */
/** \name Shear Operator
* \{ */
static const EnumPropertyItem shear_direction_items[] = {
{SHEAR_FROM_LEFT, "FROM_LEFT", 0, "From Left", "foo"},
{SHEAR_FROM_RIGHT, "FROM_RIGHT", 0, "From Right", "foo"},
{0, nullptr, 0, nullptr, nullptr},
};
static void shear_graph_keys(bAnimContext *ac, const float factor, tShearDirection direction)
{
ListBase anim_data = {nullptr, nullptr};
ANIM_animdata_filter(
ac, &anim_data, OPERATOR_DATA_FILTER, ac->data, eAnimCont_Types(ac->datatype));
LISTBASE_FOREACH (bAnimListElem *, ale, &anim_data) {
FCurve *fcu = (FCurve *)ale->key_data;
ListBase segments = find_fcurve_segments(fcu);
LISTBASE_FOREACH (FCurveSegment *, segment, &segments) {
shear_fcurve_segment(fcu, segment, factor, direction);
}
ale->update |= ANIM_UPDATE_DEFAULT;
BLI_freelistN(&segments);
}
ANIM_animdata_update(ac, &anim_data);
ANIM_animdata_freelist(&anim_data);
}
static void shear_draw_status_header(bContext *C, tGraphSliderOp *gso)
{
char status_str[UI_MAX_DRAW_STR];
char mode_str[32];
char slider_string[UI_MAX_DRAW_STR];
ED_slider_status_string_get(gso->slider, slider_string, UI_MAX_DRAW_STR);
STRNCPY(mode_str, TIP_("Shear Keys"));
if (hasNumInput(&gso->num)) {
char str_ofs[NUM_STR_REP_LEN];
outputNumInput(&gso->num, str_ofs, &gso->scene->unit);
SNPRINTF(status_str, "%s: %s", mode_str, str_ofs);
}
else {
const char *operator_string = "D - Toggle Direction";
SNPRINTF(status_str, "%s: %s | %s", mode_str, slider_string, operator_string);
}
ED_workspace_status_text(C, status_str);
}
static void shear_modal_update(bContext *C, wmOperator *op)
{
tGraphSliderOp *gso = static_cast<tGraphSliderOp *>(op->customdata);
shear_draw_status_header(C, gso);
/* Reset keyframes to the state at invoke. */
reset_bezts(gso);
const float factor = slider_factor_get_and_remember(op);
const tShearDirection direction = tShearDirection(RNA_enum_get(op->ptr, "direction"));
shear_graph_keys(&gso->ac, factor, direction);
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
}
static int shear_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
if (event->val != KM_PRESS) {
return graph_slider_modal(C, op, event);
}
switch (event->type) {
{
case EVT_DKEY: {
tShearDirection direction = tShearDirection(RNA_enum_get(op->ptr, "direction"));
RNA_enum_set(op->ptr,
"direction",
(direction == SHEAR_FROM_LEFT) ? SHEAR_FROM_RIGHT : SHEAR_FROM_LEFT);
shear_modal_update(C, op);
break;
}
default:
return graph_slider_modal(C, op, event);
break;
}
}
return OPERATOR_RUNNING_MODAL;
}
static int shear_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
const int invoke_result = graph_slider_invoke(C, op, event);
if (invoke_result == OPERATOR_CANCELLED) {
return invoke_result;
}
tGraphSliderOp *gso = static_cast<tGraphSliderOp *>(op->customdata);
gso->modal_update = shear_modal_update;
gso->factor_prop = RNA_struct_find_property(op->ptr, "factor");
shear_draw_status_header(C, gso);
ED_slider_factor_bounds_set(gso->slider, -1, 1);
ED_slider_factor_set(gso->slider, 0.0f);
return invoke_result;
}
static int shear_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
/* Get editor data. */
if (ANIM_animdata_get_context(C, &ac) == 0) {
return OPERATOR_CANCELLED;
}
const float factor = RNA_float_get(op->ptr, "factor");
const tShearDirection direction = tShearDirection(RNA_enum_get(op->ptr, "direction"));
shear_graph_keys(&ac, factor, direction);
/* Set notifier that keyframes have changed. */
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
return OPERATOR_FINISHED;
}
void GRAPH_OT_shear(wmOperatorType *ot)
{
/* Identifiers. */
ot->name = "Shear Keyframes";
ot->idname = "GRAPH_OT_shear";
ot->description =
"Affects the value of the keys linearly keeping the same \n\
relationship between them using either the left or the right key as reference";
/* API callbacks. */
ot->invoke = shear_invoke;
ot->modal = shear_modal;
ot->exec = shear_exec;
ot->poll = graphop_editable_keyframes_poll;
/* Flags. */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
RNA_def_float_factor(ot->srna,
"factor",
0.0f,
-FLT_MAX,
FLT_MAX,
"Shear Factor",
"The amount of shear to apply",
-1.0f,
1.0f);
RNA_def_enum(ot->srna,
"direction",
shear_direction_items,
SHEAR_FROM_LEFT,
"Direction",
"Which end of the segment to use as a reference to shear from");
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Gauss Smooth Operator

View File

@ -200,6 +200,7 @@ MenuType add_catalog_assets_menu_type()
type.poll = node_add_menu_poll;
type.draw = node_add_catalog_assets_draw;
type.listener = asset::asset_reading_region_listen_fn;
type.context_dependent = true;
return type;
}

View File

@ -87,16 +87,14 @@ static void add_reroute_node_fn(nodes::LinkSearchOpParams &params)
static void add_group_input_node_fn(nodes::LinkSearchOpParams &params)
{
/* Add a group input based on the connected socket, and add a new group input node. */
const eNodeSocketInOut in_out = eNodeSocketInOut(params.socket.in_out);
NodeTreeInterfaceSocketFlag flag = NodeTreeInterfaceSocketFlag(0);
SET_FLAG_FROM_TEST(flag, in_out & SOCK_IN, NODE_INTERFACE_SOCKET_INPUT);
SET_FLAG_FROM_TEST(flag, in_out & SOCK_OUT, NODE_INTERFACE_SOCKET_OUTPUT);
bNodeTreeInterfaceSocket *socket_iface = params.node_tree.tree_interface.add_socket(
params.socket.name,
params.socket.description,
params.socket.typeinfo->idname,
flag,
NODE_INTERFACE_SOCKET_INPUT,
nullptr);
BKE_ntree_update_tag_interface(&params.node_tree);
bNode &group_input = params.add_node("NodeGroupInput");
/* This is necessary to create the new sockets in the other input nodes. */
@ -105,7 +103,8 @@ static void add_group_input_node_fn(nodes::LinkSearchOpParams &params)
/* Hide the new input in all other group input nodes, to avoid making them taller. */
for (bNode *node : params.node_tree.all_nodes()) {
if (node->type == NODE_GROUP_INPUT) {
bNodeSocket *new_group_input_socket = nodeFindSocket(node, in_out, socket_iface->identifier);
bNodeSocket *new_group_input_socket = nodeFindSocket(
node, SOCK_OUT, socket_iface->identifier);
if (new_group_input_socket) {
new_group_input_socket->flag |= SOCK_HIDDEN;
}
@ -117,7 +116,7 @@ static void add_group_input_node_fn(nodes::LinkSearchOpParams &params)
socket->flag |= SOCK_HIDDEN;
}
bNodeSocket *socket = nodeFindSocket(&group_input, in_out, socket_iface->identifier);
bNodeSocket *socket = nodeFindSocket(&group_input, SOCK_OUT, socket_iface->identifier);
if (socket) {
/* Unhide the socket for the new input in the new node and make a connection to it. */
socket->flag &= ~SOCK_HIDDEN;

View File

@ -148,7 +148,7 @@ static bNode *node_under_mouse_select(const SpaceNode &snode, const float2 mouse
static bool node_under_mouse_tweak(const SpaceNode &snode, const float2 &mouse)
{
const bNodeTree ntree = *snode.edittree;
const bNodeTree &ntree = *snode.edittree;
LISTBASE_FOREACH_BACKWARD (const bNode *, node, &ntree.nodes) {
switch (node->type) {
case NODE_REROUTE: {

View File

@ -651,7 +651,6 @@ static void ui_template_node_link_menu(bContext *C, uiLayout *layout, void *but_
bNodeSocket *sock = arg->sock;
bNodeTreeType *ntreetype = arg->ntree->typeinfo;
UI_block_flag_enable(block, UI_BLOCK_NO_FLIP | UI_BLOCK_IS_FLIP);
UI_block_layout_set_current(block, layout);
split = uiLayoutSplit(layout, 0.0f, false);

View File

@ -1910,7 +1910,7 @@ static void outliner_draw_overrides_rna_buts(uiBlock *block,
if (const TreeElementOverridesPropertyOperation *override_op_elem =
tree_element_cast<TreeElementOverridesPropertyOperation>(te))
{
StringRefNull op_label = override_op_elem->getOverrideOperationLabel();
StringRefNull op_label = override_op_elem->get_override_operation_label();
if (!op_label.is_empty()) {
uiDefBut(block,
UI_BTYPE_LABEL,
@ -2058,8 +2058,8 @@ static void outliner_draw_rnabuts(uiBlock *block,
}
if (TreeElementRNAProperty *te_rna_prop = tree_element_cast<TreeElementRNAProperty>(te)) {
ptr = te_rna_prop->getPointerRNA();
prop = te_rna_prop->getPropertyRNA();
ptr = te_rna_prop->get_pointer_rna();
prop = te_rna_prop->get_property_rna();
if (!TSELEM_OPEN(tselem, space_outliner)) {
if (RNA_property_type(prop) == PROP_POINTER) {
@ -2104,8 +2104,8 @@ static void outliner_draw_rnabuts(uiBlock *block,
else if (TreeElementRNAArrayElement *te_rna_array_elem =
tree_element_cast<TreeElementRNAArrayElement>(te))
{
ptr = te_rna_array_elem->getPointerRNA();
prop = te_rna_array_elem->getPropertyRNA();
ptr = te_rna_array_elem->get_pointer_rna();
prop = te_rna_array_elem->get_property_rna();
uiDefAutoButR(block,
&ptr,
@ -2295,7 +2295,7 @@ static StringRefNull outliner_draw_get_warning_tree_element_subtree(const TreeEl
{
LISTBASE_FOREACH (const TreeElement *, sub_te, &parent_te->subtree) {
const AbstractTreeElement *abstract_te = tree_element_cast<AbstractTreeElement>(sub_te);
StringRefNull warning_msg = abstract_te ? abstract_te->getWarning() : "";
StringRefNull warning_msg = abstract_te ? abstract_te->get_warning() : "";
if (!warning_msg.is_empty()) {
return warning_msg;
@ -2314,7 +2314,7 @@ static StringRefNull outliner_draw_get_warning_tree_element(const SpaceOutliner
const TreeElement *te)
{
const AbstractTreeElement *abstract_te = tree_element_cast<AbstractTreeElement>(te);
const StringRefNull warning_msg = abstract_te ? abstract_te->getWarning() : "";
const StringRefNull warning_msg = abstract_te ? abstract_te->get_warning() : "";
if (!warning_msg.is_empty()) {
return warning_msg;
@ -2824,7 +2824,7 @@ TreeElementIcon tree_element_get_icon(TreeStoreElem *tselem, TreeElement *te)
break;
case TSE_SEQUENCE: {
const TreeElementSequence *te_seq = tree_element_cast<TreeElementSequence>(te);
switch (te_seq->getSequenceType()) {
switch (te_seq->get_sequence_type()) {
case SEQ_TYPE_SCENE:
data.icon = ICON_SCENE_DATA;
break;
@ -2886,7 +2886,7 @@ TreeElementIcon tree_element_get_icon(TreeStoreElem *tselem, TreeElement *te)
break;
case TSE_RNA_STRUCT: {
const TreeElementRNAStruct *te_rna_struct = tree_element_cast<TreeElementRNAStruct>(te);
const PointerRNA &ptr = te_rna_struct->getPointerRNA();
const PointerRNA &ptr = te_rna_struct->get_pointer_rna();
if (RNA_struct_is_ID(ptr.type)) {
data.drag_id = static_cast<ID *>(ptr.data);
@ -2943,7 +2943,7 @@ TreeElementIcon tree_element_get_icon(TreeStoreElem *tselem, TreeElement *te)
if (!te->abstract_element) {
/* Pass */
}
else if (auto icon = te->abstract_element->getIcon()) {
else if (auto icon = te->abstract_element->get_icon()) {
data.icon = *icon;
}
@ -3470,7 +3470,7 @@ static void outliner_draw_tree_element(bContext *C,
const TreeElementRNAStruct *te_rna_struct = tree_element_cast<TreeElementRNAStruct>(te);
if (ELEM(tselem->type, TSE_SOME_ID, TSE_LAYER_COLLECTION) ||
(te_rna_struct && RNA_struct_is_ID(te_rna_struct->getPointerRNA().type)))
(te_rna_struct && RNA_struct_is_ID(te_rna_struct->get_pointer_rna().type)))
{
const BIFIconID lib_icon = UI_icon_from_library(tselem->id);
if (lib_icon != ICON_NONE) {

View File

@ -1656,7 +1656,7 @@ static void tree_element_to_path(TreeElement *te,
/* get data */
TreeElement *tem = (TreeElement *)ld->data;
TreeElementRNACommon *tem_rna = tree_element_cast<TreeElementRNACommon>(tem);
PointerRNA ptr = tem_rna->getPointerRNA();
PointerRNA ptr = tem_rna->get_pointer_rna();
/* check if we're looking for first ID, or appending to path */
if (*id) {
@ -1665,7 +1665,7 @@ static void tree_element_to_path(TreeElement *te,
* then free old path + swap them.
*/
if (TreeElementRNAProperty *tem_rna_prop = tree_element_cast<TreeElementRNAProperty>(tem)) {
PropertyRNA *prop = tem_rna_prop->getPropertyRNA();
PropertyRNA *prop = tem_rna_prop->get_property_rna();
if (RNA_property_type(prop) == PROP_POINTER) {
/* for pointer we just append property name */
@ -1675,7 +1675,7 @@ static void tree_element_to_path(TreeElement *te,
char buf[128], *name;
TreeElement *temnext = (TreeElement *)(ld->next->data);
PointerRNA nextptr = tree_element_cast<TreeElementRNACommon>(temnext)->getPointerRNA();
PointerRNA nextptr = tree_element_cast<TreeElementRNACommon>(temnext)->get_pointer_rna();
name = RNA_struct_name_get_alloc(&nextptr, buf, sizeof(buf), nullptr);
if (name) {
@ -1733,7 +1733,7 @@ static void tree_element_to_path(TreeElement *te,
/* step 3: if we've got an ID, add the current item to the path */
if (*id) {
/* add the active property to the path */
PropertyRNA *prop = tree_element_cast<TreeElementRNACommon>(te)->getPropertyRNA();
PropertyRNA *prop = tree_element_cast<TreeElementRNACommon>(te)->get_property_rna();
/* array checks */
if (tselem->type == TSE_RNA_ARRAY_ELEM) {
@ -1794,8 +1794,8 @@ static void do_outliner_drivers_editop(SpaceOutliner *space_outliner,
short groupmode = KSP_GROUP_KSNAME;
TreeElementRNACommon *te_rna = tree_element_cast<TreeElementRNACommon>(te);
PointerRNA ptr = te_rna ? te_rna->getPointerRNA() : PointerRNA_NULL;
PropertyRNA *prop = te_rna ? te_rna->getPropertyRNA() : nullptr;
PointerRNA ptr = te_rna ? te_rna->get_pointer_rna() : PointerRNA_NULL;
PropertyRNA *prop = te_rna ? te_rna->get_property_rna() : nullptr;
/* check if RNA-property described by this selected element is an animatable prop */
if (prop && RNA_property_animateable(&ptr, prop)) {
@ -1987,9 +1987,10 @@ static void do_outliner_keyingset_editop(SpaceOutliner *space_outliner,
/* check if RNA-property described by this selected element is an animatable prop */
const TreeElementRNACommon *te_rna = tree_element_cast<TreeElementRNACommon>(te);
PointerRNA ptr = te_rna->getPointerRNA();
if (te_rna && te_rna->getPropertyRNA() &&
RNA_property_animateable(&ptr, te_rna->getPropertyRNA())) {
PointerRNA ptr = te_rna->get_pointer_rna();
if (te_rna && te_rna->get_property_rna() &&
RNA_property_animateable(&ptr, te_rna->get_property_rna()))
{
/* get id + path + index info from the selected element */
tree_element_to_path(te, tselem, &id, &path, &array_index, &flag, &groupmode);
}

View File

@ -21,7 +21,7 @@ bool outliner_shows_mode_column(const SpaceOutliner &space_outliner)
{
const AbstractTreeDisplay &tree_display = *space_outliner.runtime->tree_display;
return tree_display.supportsModeColumn() && (space_outliner.flag & SO_MODE_COLUMN);
return tree_display.supports_mode_column() && (space_outliner.flag & SO_MODE_COLUMN);
}
/**
@ -34,7 +34,7 @@ bool outliner_has_element_warnings(const SpaceOutliner &space_outliner)
recursive_fn = [&](const ListBase &lb) {
LISTBASE_FOREACH (const TreeElement *, te, &lb) {
if (te->abstract_element && !te->abstract_element->getWarning().is_empty()) {
if (te->abstract_element && !te->abstract_element->get_warning().is_empty()) {
return true;
}

View File

@ -719,7 +719,7 @@ static void tree_element_sequence_activate(bContext *C,
const eOLSetState set)
{
const TreeElementSequence *te_seq = tree_element_cast<TreeElementSequence>(te);
Sequence *seq = &te_seq->getSequence();
Sequence *seq = &te_seq->get_sequence();
Editing *ed = SEQ_editing_get(scene);
if (BLI_findindex(ed->seqbasep, seq) != -1) {
@ -1010,7 +1010,7 @@ static eOLDrawState tree_element_posegroup_state_get(const Scene *scene,
static eOLDrawState tree_element_sequence_state_get(const Scene *scene, const TreeElement *te)
{
const TreeElementSequence *te_seq = tree_element_cast<TreeElementSequence>(te);
const Sequence *seq = &te_seq->getSequence();
const Sequence *seq = &te_seq->get_sequence();
const Editing *ed = scene->ed;
if (ed && ed->act_seq == seq && seq->flag & SELECT) {
@ -1023,7 +1023,7 @@ static eOLDrawState tree_element_sequence_dup_state_get(const TreeElement *te)
{
const TreeElementSequenceStripDuplicate *te_dup =
tree_element_cast<TreeElementSequenceStripDuplicate>(te);
const Sequence *seq = &te_dup->getSequence();
const Sequence *seq = &te_dup->get_sequence();
if (seq->flag & SELECT) {
return OL_DRAWSEL_NORMAL;
}

View File

@ -297,7 +297,7 @@ static void outliner_select_sync_to_sequence(Scene *scene, const TreeElement *te
const TreeStoreElem *tselem = TREESTORE(te);
const TreeElementSequence *te_sequence = tree_element_cast<TreeElementSequence>(te);
Sequence *seq = &te_sequence->getSequence();
Sequence *seq = &te_sequence->get_sequence();
if (tselem->flag & TSE_ACTIVE) {
SEQ_select_active_set(scene, seq);
@ -476,7 +476,7 @@ static void outliner_select_sync_from_sequence(Sequence *sequence_active, const
TreeStoreElem *tselem = TREESTORE(te);
const TreeElementSequence *te_sequence = tree_element_cast<TreeElementSequence>(te);
const Sequence *seq = &te_sequence->getSequence();
const Sequence *seq = &te_sequence->get_sequence();
if (seq == sequence_active) {
tselem->flag |= TSE_ACTIVE;

View File

@ -2163,7 +2163,7 @@ static void ebone_fn(int event, TreeElement *te, TreeStoreElem * /*tselem*/, voi
static void sequence_fn(int event, TreeElement *te, TreeStoreElem * /*tselem*/, void *scene_ptr)
{
TreeElementSequence *te_seq = tree_element_cast<TreeElementSequence>(te);
Sequence *seq = &te_seq->getSequence();
Sequence *seq = &te_seq->get_sequence();
Scene *scene = (Scene *)scene_ptr;
Editing *ed = SEQ_editing_get(scene);
if (BLI_findindex(ed->seqbasep, seq) != -1) {
@ -2241,7 +2241,7 @@ static void data_select_linked_fn(int event,
}
if (event == OL_DOP_SELECT_LINKED) {
const PointerRNA &ptr = te_rna_struct->getPointerRNA();
const PointerRNA &ptr = te_rna_struct->get_pointer_rna();
if (RNA_struct_is_ID(ptr.type)) {
bContext *C = (bContext *)C_v;
ID *id = static_cast<ID *>(ptr.data);

View File

@ -311,7 +311,7 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner,
/* New inheritance based element representation. Not all element types support this yet,
* eventually it should replace #TreeElement entirely. */
te->abstract_element = AbstractTreeElement::createFromType(type, *te, idv);
te->abstract_element = AbstractTreeElement::create_from_type(type, *te, idv);
if (te->abstract_element) {
/* Element types ported to the new design are expected to have their name set at this point! */
BLI_assert(te->name != nullptr);
@ -366,29 +366,26 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner,
/* pass */
}
else if (type == TSE_SOME_ID) {
if (!te->abstract_element) {
BLI_assert_msg(0, "Expected this ID type to be ported to new Outliner tree-element design");
}
BLI_assert_msg(te->abstract_element != nullptr,
"Expected this ID type to be ported to new Outliner tree-element design");
}
else if (ELEM(type,
TSE_LIBRARY_OVERRIDE_BASE,
TSE_LIBRARY_OVERRIDE,
TSE_LIBRARY_OVERRIDE_OPERATION))
{
if (!te->abstract_element) {
BLI_assert_msg(0,
"Expected override types to be ported to new Outliner tree-element design");
}
BLI_assert_msg(te->abstract_element != nullptr,
"Expected override types to be ported to new Outliner tree-element design");
}
else {
/* Other cases must be caught above. */
BLI_assert(TSE_IS_REAL_ID(tselem));
BLI_assert_msg(te->abstract_element != nullptr,
"Element type should use `AbstractTreeElement` to for correct initialization "
"of its `TreeElement` data");
/* The new type design sets the name already, don't override that here. We need to figure out
* how to deal with the idcode for non-TSE_SOME_ID types still. Some rely on it... */
if (!te->abstract_element) {
te->name = id->name + 2; /* Default, can be overridden by Library or non-ID data. */
}
te->idcode = GS(id->name);
}
@ -398,43 +395,9 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner,
else if (te->abstract_element) {
tree_element_expand(*te->abstract_element, *space_outliner);
}
else if (ELEM(type,
TSE_ANIM_DATA,
TSE_BONE,
TSE_DRIVER_BASE,
TSE_EBONE,
TSE_LINKED_PSYS,
TSE_NLA,
TSE_NLA_ACTION,
TSE_NLA_TRACK,
TSE_GP_LAYER,
TSE_RNA_STRUCT,
TSE_RNA_PROPERTY,
TSE_RNA_ARRAY_ELEM,
TSE_SEQUENCE,
TSE_SEQ_STRIP,
TSE_SEQUENCE_DUP,
TSE_GENERIC_LABEL) ||
ELEM(type,
TSE_DEFGROUP,
TSE_DEFGROUP_BASE,
TSE_GPENCIL_EFFECT,
TSE_GPENCIL_EFFECT_BASE,
TSE_CONSTRAINT,
TSE_CONSTRAINT_BASE,
TSE_POSE_BASE,
TSE_POSE_CHANNEL,
TSE_POSEGRP,
TSE_POSEGRP_BASE,
TSE_R_LAYER,
TSE_R_LAYER_BASE,
TSE_MODIFIER,
TSE_MODIFIER_BASE,
TSE_GREASE_PENCIL_NODE,
TSE_LINKED_OB) ||
ELEM(type, TSE_LAYER_COLLECTION, TSE_VIEW_COLLECTION_BASE))
{
BLI_assert_msg(false, "Element type should already use new AbstractTreeElement design");
/* Only #TSE_ID_BASE isn't ported to use the abstract elements design yet. */
else if (!ELEM(type, TSE_ID_BASE)) {
BLI_assert_msg(false, "Element type should use `AbstractTreeElement`");
}
return te;
@ -1229,14 +1192,14 @@ void outliner_build_tree(Main *mainvar,
outliner_free_tree(&space_outliner->tree);
outliner_storage_cleanup(space_outliner);
space_outliner->runtime->tree_display = AbstractTreeDisplay::createFromDisplayMode(
space_outliner->runtime->tree_display = AbstractTreeDisplay::create_from_display_mode(
space_outliner->outlinevis, *space_outliner);
/* All tree displays should be created as sub-classes of AbstractTreeDisplay. */
BLI_assert(space_outliner->runtime->tree_display != nullptr);
TreeSourceData source_data{*mainvar, *scene, *view_layer};
space_outliner->tree = space_outliner->runtime->tree_display->buildTree(source_data);
space_outliner->tree = space_outliner->runtime->tree_display->build_tree(source_data);
if ((space_outliner->flag & SO_SKIP_SORT_ALPHA) == 0) {
outliner_sort(&space_outliner->tree);

View File

@ -17,7 +17,7 @@ using namespace blender::ed::outliner;
namespace blender::ed::outliner {
std::unique_ptr<AbstractTreeDisplay> AbstractTreeDisplay::createFromDisplayMode(
std::unique_ptr<AbstractTreeDisplay> AbstractTreeDisplay::create_from_display_mode(
int /*eSpaceOutliner_Mode*/ mode, SpaceOutliner &space_outliner)
{
switch ((eSpaceOutliner_Mode)mode) {
@ -47,7 +47,7 @@ std::unique_ptr<AbstractTreeDisplay> AbstractTreeDisplay::createFromDisplayMode(
return nullptr;
}
bool AbstractTreeDisplay::supportsModeColumn() const
bool AbstractTreeDisplay::supports_mode_column() const
{
return false;
}

View File

@ -11,7 +11,7 @@
* tree-display class with the #AbstractTreeDisplay interface.
*
* Their main responsibility is building the Outliner tree for a display mode. For that, they
* implement the #buildTree() function, which based on Blender data (#TreeSourceData), builds a
* implement the #build_tree() function, which based on Blender data (#TreeSourceData), builds a
* custom tree of whatever data it wants to visualize.
* Further, they can implement display mode dependent queries and general operations using the
* #AbstractTreeDisplay abstraction as common interface.
@ -66,14 +66,14 @@ class AbstractTreeDisplay {
AbstractTreeDisplay(SpaceOutliner &space_outliner) : space_outliner_(space_outliner) {}
virtual ~AbstractTreeDisplay() = default;
static std::unique_ptr<AbstractTreeDisplay> createFromDisplayMode(
static std::unique_ptr<AbstractTreeDisplay> create_from_display_mode(
int /*eSpaceOutliner_Mode*/ mode, SpaceOutliner &space_outliner);
/**
* Build a tree for this display mode with the Blender context data given in \a source_data and
* the view settings in \a space_outliner.
*/
virtual ListBase buildTree(const TreeSourceData &source_data) = 0;
virtual ListBase build_tree(const TreeSourceData &source_data) = 0;
/**
* Define if the display mode should be allowed to show a mode column on the left. This column
@ -82,7 +82,7 @@ class AbstractTreeDisplay {
*
* Returns false by default.
*/
virtual bool supportsModeColumn() const;
virtual bool supports_mode_column() const;
/**
* Some trees may want to skip building children of collapsed parents. This should be done if the
@ -112,9 +112,9 @@ class TreeDisplayViewLayer final : public AbstractTreeDisplay {
public:
TreeDisplayViewLayer(SpaceOutliner &space_outliner);
ListBase buildTree(const TreeSourceData &source_data) override;
ListBase build_tree(const TreeSourceData &source_data) override;
bool supportsModeColumn() const override;
bool supports_mode_column() const override;
private:
void add_view_layer(Scene &, ListBase &, TreeElement *);
@ -133,7 +133,7 @@ class TreeDisplayLibraries final : public AbstractTreeDisplay {
public:
TreeDisplayLibraries(SpaceOutliner &space_outliner);
ListBase buildTree(const TreeSourceData &source_data) override;
ListBase build_tree(const TreeSourceData &source_data) override;
private:
TreeElement *add_library_contents(Main &, ListBase &, Library *);
@ -151,7 +151,7 @@ class TreeDisplayOverrideLibraryProperties final : public AbstractTreeDisplay {
public:
TreeDisplayOverrideLibraryProperties(SpaceOutliner &space_outliner);
ListBase buildTree(const TreeSourceData &source_data) override;
ListBase build_tree(const TreeSourceData &source_data) override;
private:
ListBase add_library_contents(Main &);
@ -165,7 +165,7 @@ class TreeDisplayOverrideLibraryHierarchies final : public AbstractTreeDisplay {
public:
TreeDisplayOverrideLibraryHierarchies(SpaceOutliner &space_outliner);
ListBase buildTree(const TreeSourceData &source_data) override;
ListBase build_tree(const TreeSourceData &source_data) override;
bool is_lazy_built() const override;
@ -191,7 +191,7 @@ class TreeDisplaySequencer final : public AbstractTreeDisplay {
public:
TreeDisplaySequencer(SpaceOutliner &space_outliner);
ListBase buildTree(const TreeSourceData &source_data) override;
ListBase build_tree(const TreeSourceData &source_data) override;
private:
TreeElement *add_sequencer_contents() const;
@ -212,7 +212,7 @@ class TreeDisplayIDOrphans final : public AbstractTreeDisplay {
public:
TreeDisplayIDOrphans(SpaceOutliner &space_outliner);
ListBase buildTree(const TreeSourceData &source_data) override;
ListBase build_tree(const TreeSourceData &source_data) override;
private:
bool datablock_has_orphans(ListBase &) const;
@ -228,9 +228,9 @@ class TreeDisplayScenes final : public AbstractTreeDisplay {
public:
TreeDisplayScenes(SpaceOutliner &space_outliner);
ListBase buildTree(const TreeSourceData &source_data) override;
ListBase build_tree(const TreeSourceData &source_data) override;
bool supportsModeColumn() const override;
bool supports_mode_column() const override;
};
/* -------------------------------------------------------------------- */
@ -243,7 +243,7 @@ class TreeDisplayDataAPI final : public AbstractTreeDisplay {
public:
TreeDisplayDataAPI(SpaceOutliner &space_outliner);
ListBase buildTree(const TreeSourceData &source_data) override;
ListBase build_tree(const TreeSourceData &source_data) override;
bool is_lazy_built() const override;
};

View File

@ -24,7 +24,7 @@ TreeDisplayDataAPI::TreeDisplayDataAPI(SpaceOutliner &space_outliner)
{
}
ListBase TreeDisplayDataAPI::buildTree(const TreeSourceData &source_data)
ListBase TreeDisplayDataAPI::build_tree(const TreeSourceData &source_data)
{
ListBase tree = {nullptr};

View File

@ -31,7 +31,7 @@ TreeDisplayLibraries::TreeDisplayLibraries(SpaceOutliner &space_outliner)
{
}
ListBase TreeDisplayLibraries::buildTree(const TreeSourceData &source_data)
ListBase TreeDisplayLibraries::build_tree(const TreeSourceData &source_data)
{
ListBase tree = {nullptr};

View File

@ -29,7 +29,7 @@ TreeDisplayIDOrphans::TreeDisplayIDOrphans(SpaceOutliner &space_outliner)
{
}
ListBase TreeDisplayIDOrphans::buildTree(const TreeSourceData &source_data)
ListBase TreeDisplayIDOrphans::build_tree(const TreeSourceData &source_data)
{
ListBase tree = {nullptr};
ListBase *lbarray[INDEX_ID_MAX];

View File

@ -35,7 +35,7 @@ TreeDisplayOverrideLibraryHierarchies::TreeDisplayOverrideLibraryHierarchies(
{
}
ListBase TreeDisplayOverrideLibraryHierarchies::buildTree(const TreeSourceData &source_data)
ListBase TreeDisplayOverrideLibraryHierarchies::build_tree(const TreeSourceData &source_data)
{
ListBase tree = {nullptr};

View File

@ -33,7 +33,7 @@ TreeDisplayOverrideLibraryProperties::TreeDisplayOverrideLibraryProperties(
{
}
ListBase TreeDisplayOverrideLibraryProperties::buildTree(const TreeSourceData &source_data)
ListBase TreeDisplayOverrideLibraryProperties::build_tree(const TreeSourceData &source_data)
{
ListBase tree = add_library_contents(*source_data.bmain);

View File

@ -28,12 +28,12 @@ TreeDisplayScenes::TreeDisplayScenes(SpaceOutliner &space_outliner)
{
}
bool TreeDisplayScenes::supportsModeColumn() const
bool TreeDisplayScenes::supports_mode_column() const
{
return true;
}
ListBase TreeDisplayScenes::buildTree(const TreeSourceData &source_data)
ListBase TreeDisplayScenes::build_tree(const TreeSourceData &source_data)
{
/* On first view we open scenes. */
const int show_opened = !space_outliner_.treestore ||

View File

@ -30,7 +30,7 @@ TreeDisplaySequencer::TreeDisplaySequencer(SpaceOutliner &space_outliner)
{
}
ListBase TreeDisplaySequencer::buildTree(const TreeSourceData &source_data)
ListBase TreeDisplaySequencer::build_tree(const TreeSourceData &source_data)
{
ListBase tree = {nullptr};

View File

@ -57,12 +57,12 @@ TreeDisplayViewLayer::TreeDisplayViewLayer(SpaceOutliner &space_outliner)
{
}
bool TreeDisplayViewLayer::supportsModeColumn() const
bool TreeDisplayViewLayer::supports_mode_column() const
{
return true;
}
ListBase TreeDisplayViewLayer::buildTree(const TreeSourceData &source_data)
ListBase TreeDisplayViewLayer::build_tree(const TreeSourceData &source_data)
{
ListBase tree = {nullptr};
Scene *scene = source_data.scene;

View File

@ -49,9 +49,9 @@
namespace blender::ed::outliner {
std::unique_ptr<AbstractTreeElement> AbstractTreeElement::createFromType(const int type,
TreeElement &legacy_te,
void *idv)
std::unique_ptr<AbstractTreeElement> AbstractTreeElement::create_from_type(const int type,
TreeElement &legacy_te,
void *idv)
{
if (idv == nullptr) {
return nullptr;
@ -71,7 +71,7 @@ std::unique_ptr<AbstractTreeElement> AbstractTreeElement::createFromType(const i
switch (type) {
case TSE_SOME_ID:
return TreeElementID::createFromID(legacy_te, *static_cast<ID *>(idv));
return TreeElementID::create_from_id(legacy_te, *static_cast<ID *>(idv));
case TSE_GENERIC_LABEL:
return std::make_unique<TreeElementLabel>(legacy_te, static_cast<const char *>(idv));
case TSE_ANIM_DATA:
@ -198,12 +198,12 @@ std::unique_ptr<AbstractTreeElement> AbstractTreeElement::createFromType(const i
return nullptr;
}
StringRefNull AbstractTreeElement::getWarning() const
StringRefNull AbstractTreeElement::get_warning() const
{
return "";
}
std::optional<BIFIconID> AbstractTreeElement::getIcon() const
std::optional<BIFIconID> AbstractTreeElement::get_icon() const
{
return {};
}
@ -231,7 +231,7 @@ void tree_element_expand(const AbstractTreeElement &tree_element, SpaceOutliner
/* Most types can just expand. IDs optionally expand (hence the poll) and do additional, common
* expanding. Could be done nicer, we could request a small "expander" helper object from the
* element type, that the IDs have a more advanced implementation for. */
if (!tree_element.expandPoll(space_outliner)) {
if (!tree_element.expand_poll(space_outliner)) {
return;
}
tree_element.expand(space_outliner);

View File

@ -36,19 +36,19 @@ class AbstractTreeElement {
public:
virtual ~AbstractTreeElement() = default;
static std::unique_ptr<AbstractTreeElement> createFromType(int type,
TreeElement &legacy_te,
void *idv);
static std::unique_ptr<AbstractTreeElement> create_from_type(int type,
TreeElement &legacy_te,
void *idv);
/**
* Check if the type is expandable in current context.
*/
virtual bool expandPoll(const SpaceOutliner &) const
virtual bool expand_poll(const SpaceOutliner &) const
{
return true;
}
TreeElement &getLegacyElement()
TreeElement &get_legacy_element()
{
return legacy_te_;
}
@ -57,7 +57,7 @@ class AbstractTreeElement {
* By letting this return a warning message, the tree element will display a warning icon with
* the message in the tooltip.
*/
virtual StringRefNull getWarning() const;
virtual StringRefNull get_warning() const;
/**
* Define the icon to be displayed for this element. If this returns an icon, this will be
@ -66,7 +66,7 @@ class AbstractTreeElement {
*
* All elements should be ported to use this over #tree_element_get_icon().
*/
virtual std::optional<BIFIconID> getIcon() const;
virtual std::optional<BIFIconID> get_icon() const;
/**
* Debugging helper: Print effective path of this tree element, constructed out of the

View File

@ -38,7 +38,7 @@
namespace blender::ed::outliner {
std::unique_ptr<TreeElementID> TreeElementID::createFromID(TreeElement &legacy_te, ID &id)
std::unique_ptr<TreeElementID> TreeElementID::create_from_id(TreeElement &legacy_te, ID &id)
{
if (ID_TYPE_IS_DEPRECATED(GS(id.name))) {
BLI_assert_msg(0, "Outliner trying to build tree-element for deprecated ID type");
@ -120,7 +120,7 @@ TreeElementID::TreeElementID(TreeElement &legacy_te, ID &id)
legacy_te_.idcode = GS(id.name);
}
bool TreeElementID::expandPoll(const SpaceOutliner &space_outliner) const
bool TreeElementID::expand_poll(const SpaceOutliner &space_outliner) const
{
const TreeStoreElem *tsepar = legacy_te_.parent ? TREESTORE(legacy_te_.parent) : nullptr;
return (tsepar == nullptr || tsepar->type != TSE_ID_BASE || space_outliner.filter_id_type);

View File

@ -24,9 +24,9 @@ class TreeElementID : public AbstractTreeElement {
public:
TreeElementID(TreeElement &legacy_te, ID &id);
static std::unique_ptr<TreeElementID> createFromID(TreeElement &legacy_te, ID &id);
static std::unique_ptr<TreeElementID> create_from_id(TreeElement &legacy_te, ID &id);
bool expandPoll(const SpaceOutliner &) const override;
bool expand_poll(const SpaceOutliner &) const override;
void expand(SpaceOutliner &) const override;

View File

@ -23,7 +23,7 @@ TreeElementIDLibrary::TreeElementIDLibrary(TreeElement &legacy_te, Library &libr
legacy_te.name = library.filepath;
}
StringRefNull TreeElementIDLibrary::getWarning() const
StringRefNull TreeElementIDLibrary::get_warning() const
{
Library &library = reinterpret_cast<Library &>(id_);

View File

@ -18,7 +18,7 @@ class TreeElementIDLibrary final : public TreeElementID {
public:
TreeElementIDLibrary(TreeElement &legacy_te, Library &library);
blender::StringRefNull getWarning() const override;
blender::StringRefNull get_warning() const override;
};
} // namespace blender::ed::outliner

View File

@ -25,12 +25,12 @@ TreeElementLabel::TreeElementLabel(TreeElement &legacy_te, const char *label)
legacy_te_.name = label_.c_str();
}
void TreeElementLabel::setIcon(const BIFIconID icon)
void TreeElementLabel::set_icon(const BIFIconID icon)
{
icon_ = icon;
}
std::optional<BIFIconID> TreeElementLabel::getIcon() const
std::optional<BIFIconID> TreeElementLabel::get_icon() const
{
return icon_;
}

View File

@ -31,8 +31,8 @@ class TreeElementLabel final : public AbstractTreeElement {
public:
TreeElementLabel(TreeElement &legacy_te, const char *label);
void setIcon(BIFIconID icon);
std::optional<BIFIconID> getIcon() const override;
void set_icon(BIFIconID icon);
std::optional<BIFIconID> get_icon() const override;
};
} // namespace blender::ed::outliner

Some files were not shown because too many files have changed in this diff Show More