Mesh: Replace auto smooth with node group #108014
|
@ -37,7 +37,18 @@ find_path(FFTW3_INCLUDE_DIR
|
|||
include
|
||||
)
|
||||
|
||||
find_library(FFTW3_LIBRARY
|
||||
set(_FFTW3_LIBRARIES)
|
||||
|
||||
find_library(FFTW3_LIBRARY_F
|
||||
NAMES
|
||||
fftw3f
|
||||
HINTS
|
||||
${_fftw3_SEARCH_DIRS}
|
||||
PATH_SUFFIXES
|
||||
lib64 lib
|
||||
)
|
||||
|
||||
find_library(FFTW3_LIBRARY_D
|
||||
NAMES
|
||||
fftw3
|
||||
HINTS
|
||||
|
@ -46,17 +57,22 @@ find_library(FFTW3_LIBRARY
|
|||
lib64 lib
|
||||
)
|
||||
|
||||
list(APPEND _FFTW3_LIBRARIES "${FFTW3_LIBRARY_F}")
|
||||
list(APPEND _FFTW3_LIBRARIES "${FFTW3_LIBRARY_D}")
|
||||
|
||||
# handle the QUIETLY and REQUIRED arguments and set FFTW3_FOUND to TRUE if
|
||||
# all listed variables are TRUE
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(Fftw3 DEFAULT_MSG
|
||||
FFTW3_LIBRARY FFTW3_INCLUDE_DIR)
|
||||
_FFTW3_LIBRARIES FFTW3_INCLUDE_DIR)
|
||||
|
||||
if(FFTW3_FOUND)
|
||||
set(FFTW3_LIBRARIES ${FFTW3_LIBRARY})
|
||||
set(FFTW3_LIBRARIES ${_FFTW3_LIBRARIES})
|
||||
set(FFTW3_INCLUDE_DIRS ${FFTW3_INCLUDE_DIR})
|
||||
endif()
|
||||
|
||||
unset(_FFTW3_LIBRARIES)
|
||||
|
||||
mark_as_advanced(
|
||||
FFTW3_INCLUDE_DIR
|
||||
FFTW3_LIBRARY
|
||||
|
|
|
@ -7,7 +7,12 @@ set(SHARED_LIBRARY FALSE) # "Build Shared Library"
|
|||
set(WITH_C TRUE) # "Build C Module"
|
||||
set(WITH_DOCS FALSE) # "Build C++ HTML Documentation with Doxygen"
|
||||
set(WITH_FFMPEG ${WITH_CODEC_FFMPEG}) # "Build With FFMPEG"
|
||||
set(WITH_FFTW FALSE) # "Build With FFTW"
|
||||
if(DEFINED WITH_FFTW3) # "Build With FFTW"
|
||||
set(FFTW_FOUND TRUE)
|
||||
set(WITH_FFTW ${WITH_FFTW3})
|
||||
set(FFTW_INCLUDE_DIR ${FFTW3_INCLUDE_DIRS})
|
||||
set(FFTW_LIBRARY ${FFTW3_LIBRARIES})
|
||||
endif()
|
||||
set(WITH_LIBSNDFILE ${WITH_CODEC_SNDFILE}) # "Build With LibSndFile"
|
||||
set(SEPARATE_C FALSE) # "Build C Binding as separate library"
|
||||
set(PLUGIN_COREAUDIO FALSE) # "Build CoreAudio Plugin"
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -148,13 +148,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];
|
||||
}
|
||||
|
@ -184,9 +185,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);
|
||||
}
|
||||
}
|
||||
|
@ -205,10 +207,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);
|
||||
}
|
||||
}
|
||||
|
@ -242,20 +245,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));
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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}/.."
|
||||
|
|
|
@ -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)))
|
||||
|
|
|
@ -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); \
|
||||
|
|
|
@ -880,6 +880,8 @@ ccl_device float voronoi_n_sphere_radius(ccl_private const VoronoiParams ¶ms
|
|||
|
||||
/* **** 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 ¶ms,
|
||||
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 ¶ms,
|
||||
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);
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
*/
|
||||
|
||||
#include "GHOST_SystemWayland.hh"
|
||||
#include "GHOST_Context.hh"
|
||||
#include "GHOST_Event.hh"
|
||||
#include "GHOST_EventButton.hh"
|
||||
#include "GHOST_EventCursor.hh"
|
||||
|
|
|
@ -932,13 +932,15 @@ static void xdg_toplevel_handle_configure(void *data,
|
|||
std::lock_guard lock_frame_guard{win->frame_pending_mutex};
|
||||
#endif
|
||||
|
||||
if (win->frame.fractional_scale) {
|
||||
win->frame_pending.size[0] = gwl_window_fractional_to_viewport_round(win->frame, width);
|
||||
win->frame_pending.size[1] = gwl_window_fractional_to_viewport_round(win->frame, height);
|
||||
}
|
||||
else {
|
||||
win->frame_pending.size[0] = width * win->frame.buffer_scale;
|
||||
win->frame_pending.size[1] = height * win->frame.buffer_scale;
|
||||
const int32_t size[2] = {width, height};
|
||||
for (int i = 0; i < 2; i++) {
|
||||
if (size[i] == 0) {
|
||||
/* Values may be zero, in this case the client should choose. */
|
||||
continue;
|
||||
}
|
||||
win->frame_pending.size[i] = win->frame.fractional_scale ?
|
||||
gwl_window_fractional_to_viewport_round(win->frame, size[i]) :
|
||||
(size[i] * win->frame.buffer_scale);
|
||||
}
|
||||
|
||||
win->frame_pending.is_maximised = false;
|
||||
|
@ -1059,9 +1061,9 @@ static const wp_fractional_scale_v1_listener wp_fractional_scale_listener = {
|
|||
static CLG_LogRef LOG_WL_LIBDECOR_FRAME = {"ghost.wl.handle.libdecor_frame"};
|
||||
# define LOG (&LOG_WL_LIBDECOR_FRAME)
|
||||
|
||||
static void frame_handle_configure(libdecor_frame *frame,
|
||||
libdecor_configuration *configuration,
|
||||
void *data)
|
||||
static void libdecor_frame_handle_configure(libdecor_frame *frame,
|
||||
libdecor_configuration *configuration,
|
||||
void *data)
|
||||
{
|
||||
CLOG_INFO(LOG, 2, "configure");
|
||||
|
||||
|
@ -1133,7 +1135,7 @@ static void frame_handle_configure(libdecor_frame *frame,
|
|||
}
|
||||
}
|
||||
|
||||
static void frame_handle_close(libdecor_frame * /*frame*/, void *data)
|
||||
static void libdecor_frame_handle_close(libdecor_frame * /*frame*/, void *data)
|
||||
{
|
||||
CLOG_INFO(LOG, 2, "close");
|
||||
|
||||
|
@ -1142,7 +1144,7 @@ static void frame_handle_close(libdecor_frame * /*frame*/, void *data)
|
|||
win->ghost_window->close();
|
||||
}
|
||||
|
||||
static void frame_handle_commit(libdecor_frame * /*frame*/, void *data)
|
||||
static void libdecor_frame_handle_commit(libdecor_frame * /*frame*/, void *data)
|
||||
{
|
||||
CLOG_INFO(LOG, 2, "commit");
|
||||
|
||||
|
@ -1156,9 +1158,9 @@ static void frame_handle_commit(libdecor_frame * /*frame*/, void *data)
|
|||
|
||||
/* NOTE: cannot be `const` because of the LIBDECOR API. */
|
||||
static libdecor_frame_interface libdecor_frame_iface = {
|
||||
frame_handle_configure,
|
||||
frame_handle_close,
|
||||
frame_handle_commit,
|
||||
libdecor_frame_handle_configure,
|
||||
libdecor_frame_handle_close,
|
||||
libdecor_frame_handle_commit,
|
||||
};
|
||||
|
||||
# undef LOG
|
||||
|
|
|
@ -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():
|
||||
|
|
|
@ -97,26 +97,6 @@ class Prefs(bpy.types.KeyConfigPreferences):
|
|||
default=False,
|
||||
update=update_fn,
|
||||
)
|
||||
# Experimental: only show with developer extras, see: #96544.
|
||||
use_tweak_select_passthrough: BoolProperty(
|
||||
name="Tweak Select: Mouse Select & Move",
|
||||
description=(
|
||||
"The tweak tool is activated immediately instead of placing the cursor. "
|
||||
"This is an experimental preference and may be removed"
|
||||
),
|
||||
default=False,
|
||||
update=update_fn,
|
||||
)
|
||||
# Experimental: only show with developer extras, see: #96544.
|
||||
use_tweak_tool_lmb_interaction: BoolProperty(
|
||||
name="Tweak Tool: Left Mouse Select & Move",
|
||||
description=(
|
||||
"The tweak tool is activated immediately instead of placing the cursor. "
|
||||
"This is an experimental preference and may be removed"
|
||||
),
|
||||
default=False,
|
||||
update=update_fn,
|
||||
)
|
||||
|
||||
use_alt_click_leader: BoolProperty(
|
||||
name="Alt Click Tool Prompt",
|
||||
|
@ -313,12 +293,6 @@ class Prefs(bpy.types.KeyConfigPreferences):
|
|||
row = sub.row()
|
||||
row.prop(self, "use_select_all_toggle")
|
||||
|
||||
if show_developer_ui:
|
||||
row = sub.row()
|
||||
row.prop(self, "use_tweak_select_passthrough")
|
||||
if show_developer_ui and (not is_select_left):
|
||||
row = sub.row()
|
||||
row.prop(self, "use_tweak_tool_lmb_interaction")
|
||||
if show_developer_ui:
|
||||
row = sub.row()
|
||||
row.prop(self, "use_region_toggle_pie")
|
||||
|
@ -385,11 +359,6 @@ def load():
|
|||
# Otherwise LMB activates the fallback tool and RMB always tweak-selects.
|
||||
(kc_prefs.rmb_action != 'FALLBACK_TOOL')
|
||||
),
|
||||
use_tweak_select_passthrough=(show_developer_ui and kc_prefs.use_tweak_select_passthrough),
|
||||
use_tweak_tool_lmb_interaction=(
|
||||
False if is_select_left else
|
||||
(show_developer_ui and kc_prefs.use_tweak_tool_lmb_interaction)
|
||||
),
|
||||
use_alt_tool_or_cursor=(
|
||||
(not use_mouse_emulate_3_button) and
|
||||
(kc_prefs.use_alt_tool if is_select_left else kc_prefs.use_alt_cursor)
|
||||
|
@ -397,8 +366,9 @@ def load():
|
|||
use_alt_click_leader=kc_prefs.use_alt_click_leader,
|
||||
use_pie_click_drag=kc_prefs.use_pie_click_drag,
|
||||
use_file_single_click=kc_prefs.use_file_single_click,
|
||||
experimental=prefs.experimental,
|
||||
use_alt_navigation=kc_prefs.use_alt_navigation,
|
||||
# Experimental features.
|
||||
use_experimental_grease_pencil_version3=prefs.experimental.use_grease_pencil_version3,
|
||||
),
|
||||
)
|
||||
|
||||
|
|
|
@ -41,7 +41,6 @@ class Params:
|
|||
# - Click selects only the item at the cursor position.
|
||||
# See: #97032.
|
||||
"use_tweak_select_passthrough",
|
||||
"use_tweak_tool_lmb_interaction",
|
||||
"use_mouse_emulate_3_button",
|
||||
|
||||
# User preferences:
|
||||
|
@ -78,6 +77,14 @@ class Params:
|
|||
# File selector actions on single click.
|
||||
"use_file_single_click",
|
||||
|
||||
# Experimental variables:
|
||||
# Options for experimental features.
|
||||
#
|
||||
# NOTE: don't pass the experimental struct directly as this makes it less
|
||||
# clear which experimental options impact shortcuts. Further, any experimental option
|
||||
# that adjust shortcuts need to reload the key-configuration (see: `rna_userdef.cc`).
|
||||
"use_experimental_grease_pencil_version3",
|
||||
|
||||
# Convenience variables:
|
||||
# (derived from other settings).
|
||||
#
|
||||
|
@ -99,8 +106,6 @@ class Params:
|
|||
# Since this means with RMB select enabled in edit-mode for e.g.
|
||||
# `Ctrl-LMB` would be caught by box-select instead of add/extrude.
|
||||
"tool_maybe_tweak_event",
|
||||
# Access to bpy.context.preferences.experimental
|
||||
"experimental",
|
||||
# Changes some transformers modal key-map items to avoid conflicts with navigation operations
|
||||
"use_alt_navigation",
|
||||
)
|
||||
|
@ -120,8 +125,6 @@ class Params:
|
|||
use_gizmo_drag=True,
|
||||
use_fallback_tool=False,
|
||||
use_fallback_tool_select_handled=True,
|
||||
use_tweak_select_passthrough=False,
|
||||
use_tweak_tool_lmb_interaction=False,
|
||||
use_v3d_tab_menu=False,
|
||||
use_v3d_shade_ex_pie=False,
|
||||
use_v3d_mmb_pan=False,
|
||||
|
@ -131,8 +134,8 @@ class Params:
|
|||
use_file_single_click=False,
|
||||
v3d_tilde_action='VIEW',
|
||||
v3d_alt_mmb_drag_action='RELATIVE',
|
||||
experimental=None,
|
||||
use_alt_navigation=True,
|
||||
use_experimental_grease_pencil_version3=False,
|
||||
):
|
||||
from sys import platform
|
||||
self.apple = platform == 'darwin'
|
||||
|
@ -152,8 +155,6 @@ class Params:
|
|||
else:
|
||||
self.tool_maybe_tweak_value = 'CLICK_DRAG'
|
||||
|
||||
self.use_tweak_tool_lmb_interaction = use_tweak_tool_lmb_interaction
|
||||
|
||||
self.context_menu_event = {"type": 'W', "value": 'PRESS'}
|
||||
|
||||
# Use the "cursor" functionality for RMB select.
|
||||
|
@ -174,7 +175,6 @@ class Params:
|
|||
self.action_mouse = 'RIGHTMOUSE'
|
||||
self.tool_mouse = 'LEFTMOUSE'
|
||||
self.tool_maybe_tweak_value = 'CLICK_DRAG'
|
||||
self.use_tweak_tool_lmb_interaction = False
|
||||
|
||||
if self.legacy:
|
||||
self.context_menu_event = {"type": 'W', "value": 'PRESS'}
|
||||
|
@ -211,10 +211,13 @@ class Params:
|
|||
|
||||
self.use_file_single_click = use_file_single_click
|
||||
|
||||
self.use_tweak_select_passthrough = use_tweak_select_passthrough
|
||||
self.use_tweak_select_passthrough = not legacy
|
||||
|
||||
self.use_fallback_tool = use_fallback_tool
|
||||
|
||||
# Experimental variables:
|
||||
self.use_experimental_grease_pencil_version3 = use_experimental_grease_pencil_version3
|
||||
|
||||
# Convenience variables:
|
||||
self.use_fallback_tool_select_handled = (
|
||||
True if (select_mouse == 'LEFT') else
|
||||
|
@ -234,8 +237,6 @@ class Params:
|
|||
self.tool_maybe_tweak_event = {"type": self.tool_mouse, "value": self.tool_maybe_tweak_value}
|
||||
self.use_alt_navigation = use_alt_navigation
|
||||
|
||||
self.experimental = experimental
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Constants
|
||||
|
@ -579,7 +580,7 @@ def _template_items_tool_select(
|
|||
select_passthrough = params.use_tweak_select_passthrough
|
||||
else:
|
||||
if not cursor_prioritize:
|
||||
select_passthrough = params.use_tweak_tool_lmb_interaction
|
||||
select_passthrough = True
|
||||
|
||||
if select_passthrough:
|
||||
return [
|
||||
|
@ -3884,7 +3885,7 @@ def km_grease_pencil_stroke_paint_draw_brush(params):
|
|||
)
|
||||
|
||||
# Draw
|
||||
if params.experimental and params.experimental.use_grease_pencil_version3:
|
||||
if params.use_experimental_grease_pencil_version3:
|
||||
items.extend([
|
||||
("grease_pencil.brush_stroke", {"type": 'LEFTMOUSE', "value": 'PRESS'}, None),
|
||||
("grease_pencil.brush_stroke", {"type": 'LEFTMOUSE', "value": 'PRESS', "ctrl": True},
|
||||
|
|
|
@ -5,41 +5,80 @@
|
|||
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 +89,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 +117,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 +147,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 +192,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 +324,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 +344,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,
|
||||
)
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -962,7 +962,11 @@ class SEQUENCER_MT_strip(Menu):
|
|||
|
||||
if strip_type != 'SOUND':
|
||||
layout.separator()
|
||||
layout.operator_menu_enum("sequencer.strip_modifier_add", "type", text="Add Modifier")
|
||||
layout.operator_menu_enum("sequencer.strip_video_modifier_add", "type", text="Add Modifier")
|
||||
layout.operator("sequencer.strip_modifier_copy", text="Copy Modifiers to Selection")
|
||||
else:
|
||||
layout.separator()
|
||||
layout.operator_menu_enum("sequencer.strip_sound_modifier_add", "type", text="Add Modifier")
|
||||
layout.operator("sequencer.strip_modifier_copy", text="Copy Modifiers to Selection")
|
||||
|
||||
if strip_type in {
|
||||
|
@ -1103,17 +1107,19 @@ class SEQUENCER_MT_context_menu(Menu):
|
|||
|
||||
if strip_type != 'SOUND':
|
||||
layout.separator()
|
||||
layout.operator_menu_enum("sequencer.strip_modifier_add", "type", text="Add Modifier")
|
||||
layout.operator_menu_enum("sequencer.strip_video_modifier_add", "type", text="Add Modifier")
|
||||
layout.operator("sequencer.strip_modifier_copy", text="Copy Modifiers to Selection")
|
||||
|
||||
if selected_sequences_count >= 2:
|
||||
layout.separator()
|
||||
col = layout.column()
|
||||
col.menu("SEQUENCER_MT_add_transitions", text="Add Transition")
|
||||
|
||||
elif selected_sequences_count >= 2:
|
||||
else:
|
||||
layout.separator()
|
||||
layout.operator("sequencer.crossfade_sounds", text="Crossfade Sounds")
|
||||
layout.operator_menu_enum("sequencer.strip_sound_modifier_add", "type", text="Add Modifier")
|
||||
layout.operator("sequencer.strip_modifier_copy", text="Copy Modifiers to Selection")
|
||||
if selected_sequences_count >= 2:
|
||||
layout.separator()
|
||||
layout.operator("sequencer.crossfade_sounds", text="Crossfade Sounds")
|
||||
|
||||
if selected_sequences_count >= 1:
|
||||
col = layout.column()
|
||||
|
@ -2503,8 +2509,13 @@ class SEQUENCER_PT_modifiers(SequencerButtonsPanel, Panel):
|
|||
|
||||
strip = context.active_sequence_strip
|
||||
ed = context.scene.sequence_editor
|
||||
if strip.type == 'SOUND':
|
||||
sound = strip.sound
|
||||
else:
|
||||
sound = None
|
||||
|
||||
layout.prop(strip, "use_linear_modifiers")
|
||||
if sound is None:
|
||||
layout.prop(strip, "use_linear_modifiers")
|
||||
|
||||
layout.operator_menu_enum("sequencer.strip_modifier_add", "type")
|
||||
layout.operator("sequencer.strip_modifier_copy")
|
||||
|
@ -2531,45 +2542,78 @@ class SEQUENCER_PT_modifiers(SequencerButtonsPanel, Panel):
|
|||
row.operator("sequencer.strip_modifier_remove", text="", icon='X', emboss=False).name = mod.name
|
||||
|
||||
if mod.show_expanded:
|
||||
row = box.row()
|
||||
row.prop(mod, "input_mask_type", expand=True)
|
||||
|
||||
if mod.input_mask_type == 'STRIP':
|
||||
sequences_object = ed
|
||||
if ed.meta_stack:
|
||||
sequences_object = ed.meta_stack[-1]
|
||||
box.prop_search(mod, "input_mask_strip", sequences_object, "sequences", text="Mask")
|
||||
else:
|
||||
box.prop(mod, "input_mask_id")
|
||||
if sound is None:
|
||||
row = box.row()
|
||||
row.prop(mod, "mask_time", expand=True)
|
||||
row.prop(mod, "input_mask_type", expand=True)
|
||||
|
||||
if mod.type == 'COLOR_BALANCE':
|
||||
box.prop(mod, "color_multiply")
|
||||
draw_color_balance(box, mod.color_balance)
|
||||
elif mod.type == 'CURVES':
|
||||
box.template_curve_mapping(mod, "curve_mapping", type='COLOR', show_tone=True)
|
||||
elif mod.type == 'HUE_CORRECT':
|
||||
box.template_curve_mapping(mod, "curve_mapping", type='HUE')
|
||||
elif mod.type == 'BRIGHT_CONTRAST':
|
||||
col = box.column()
|
||||
col.prop(mod, "bright")
|
||||
col.prop(mod, "contrast")
|
||||
elif mod.type == 'WHITE_BALANCE':
|
||||
col = box.column()
|
||||
col.prop(mod, "white_value")
|
||||
elif mod.type == 'TONEMAP':
|
||||
col = box.column()
|
||||
col.prop(mod, "tonemap_type")
|
||||
if mod.tonemap_type == 'RD_PHOTORECEPTOR':
|
||||
col.prop(mod, "intensity")
|
||||
if mod.input_mask_type == 'STRIP':
|
||||
sequences_object = ed
|
||||
if ed.meta_stack:
|
||||
sequences_object = ed.meta_stack[-1]
|
||||
box.prop_search(mod, "input_mask_strip", sequences_object, "sequences", text="Mask")
|
||||
else:
|
||||
box.prop(mod, "input_mask_id")
|
||||
row = box.row()
|
||||
row.prop(mod, "mask_time", expand=True)
|
||||
|
||||
if mod.type == 'COLOR_BALANCE':
|
||||
box.prop(mod, "color_multiply")
|
||||
draw_color_balance(box, mod.color_balance)
|
||||
elif mod.type == 'CURVES':
|
||||
box.template_curve_mapping(mod, "curve_mapping", type='COLOR', show_tone=True)
|
||||
elif mod.type == 'HUE_CORRECT':
|
||||
box.template_curve_mapping(mod, "curve_mapping", type='HUE')
|
||||
elif mod.type == 'BRIGHT_CONTRAST':
|
||||
col = box.column()
|
||||
col.prop(mod, "bright")
|
||||
col.prop(mod, "contrast")
|
||||
col.prop(mod, "adaptation")
|
||||
col.prop(mod, "correction")
|
||||
elif mod.tonemap_type == 'RH_SIMPLE':
|
||||
col.prop(mod, "key")
|
||||
col.prop(mod, "offset")
|
||||
col.prop(mod, "gamma")
|
||||
elif mod.type == 'WHITE_BALANCE':
|
||||
col = box.column()
|
||||
col.prop(mod, "white_value")
|
||||
elif mod.type == 'TONEMAP':
|
||||
col = box.column()
|
||||
col.prop(mod, "tonemap_type")
|
||||
if mod.tonemap_type == 'RD_PHOTORECEPTOR':
|
||||
col.prop(mod, "intensity")
|
||||
col.prop(mod, "contrast")
|
||||
col.prop(mod, "adaptation")
|
||||
col.prop(mod, "correction")
|
||||
elif mod.tonemap_type == 'RH_SIMPLE':
|
||||
col.prop(mod, "key")
|
||||
col.prop(mod, "offset")
|
||||
col.prop(mod, "gamma")
|
||||
else:
|
||||
if mod.type == 'SOUND_EQUALIZER':
|
||||
eq_row = box.row()
|
||||
# eq_graphs = eq_row.operator_menu_enum("sequencer.strip_modifier_equalizer_redefine", "graphs")
|
||||
# eq_graphs.name = mod.name
|
||||
flow = box.grid_flow(
|
||||
row_major=True,
|
||||
columns=0,
|
||||
even_columns=True,
|
||||
even_rows=False,
|
||||
align=False,
|
||||
)
|
||||
for sound_eq in mod.graphics:
|
||||
col = flow.column()
|
||||
box = col.box()
|
||||
split = box.split(factor=0.4)
|
||||
split.label(text="%.2f" % sound_eq.curve_mapping.clip_min_x)
|
||||
split.label(text="Hz")
|
||||
split.alignment = "RIGHT"
|
||||
split.label(text="%.2f" % sound_eq.curve_mapping.clip_max_x)
|
||||
box.template_curve_mapping(
|
||||
sound_eq,
|
||||
"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.alignment = 'CENTER'
|
||||
|
||||
|
||||
class SEQUENCER_PT_annotation(AnnotationDataPanel, SequencerButtonsPanel_Output, Panel):
|
||||
|
|
|
@ -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")
|
||||
|
||||
|
||||
###################################
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "BLI_linklist.h"
|
||||
#include "BLI_math_color.h"
|
||||
#include "BLI_string.h"
|
||||
#include "BLI_string_utf8.h"
|
||||
#include "BLI_string_utils.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
|
@ -46,10 +47,9 @@ BoneCollection *ANIM_bonecoll_new(const char *name)
|
|||
|
||||
/* Note: the collection name may change after the collection is added to an
|
||||
* armature, to ensure it is unique within the armature. */
|
||||
std::string alloc_name = std::string(__func__) + "('" + name + "')";
|
||||
BoneCollection *bcoll = MEM_cnew<BoneCollection>(alloc_name.c_str());
|
||||
BoneCollection *bcoll = MEM_cnew<BoneCollection>(__func__);
|
||||
|
||||
BLI_strncpy(bcoll->name, name, sizeof(bcoll->name));
|
||||
STRNCPY_UTF8(bcoll->name, name);
|
||||
bcoll->flags = default_flags;
|
||||
|
||||
bcoll->prop = nullptr;
|
||||
|
@ -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));
|
||||
|
@ -151,7 +151,7 @@ void ANIM_armature_bonecoll_active_index_set(bArmature *armature, const int bone
|
|||
|
||||
bool ANIM_armature_bonecoll_move(bArmature *armature, BoneCollection *bcoll, const int step)
|
||||
{
|
||||
if (bcoll == NULL) {
|
||||
if (bcoll == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -169,9 +169,9 @@ void ANIM_armature_bonecoll_name_set(bArmature *armature, BoneCollection *bcoll,
|
|||
{
|
||||
char old_name[sizeof(bcoll->name)];
|
||||
|
||||
BLI_strncpy(old_name, bcoll->name, sizeof(bcoll->name));
|
||||
STRNCPY(old_name, bcoll->name);
|
||||
|
||||
BLI_strncpy(bcoll->name, name, sizeof(bcoll->name));
|
||||
STRNCPY_UTF8(bcoll->name, name);
|
||||
bonecoll_ensure_name_unique(armature, bcoll);
|
||||
|
||||
BKE_animdata_fix_paths_rename_all(&armature->id, "collections", old_name, bcoll->name);
|
||||
|
@ -309,7 +309,7 @@ bool ANIM_armature_bonecoll_unassign_editbone(BoneCollection *bcoll, EditBone *e
|
|||
return was_found;
|
||||
}
|
||||
|
||||
void ANIM_armature_bonecoll_reconstruct(struct bArmature *armature)
|
||||
void ANIM_armature_bonecoll_reconstruct(bArmature *armature)
|
||||
{
|
||||
/* Remove all the old collection memberships. */
|
||||
LISTBASE_FOREACH (BoneCollection *, bcoll, &armature->collections) {
|
||||
|
@ -343,12 +343,11 @@ static bool any_bone_collection_visible(const ListBase /*BoneCollectionRef*/ *co
|
|||
/* TODO: these two functions were originally implemented for armature layers, hence the armature
|
||||
* parameters. These should be removed at some point. */
|
||||
|
||||
bool ANIM_bonecoll_is_visible(const struct bArmature * /*armature*/, const struct Bone *bone)
|
||||
bool ANIM_bonecoll_is_visible(const bArmature * /*armature*/, const Bone *bone)
|
||||
{
|
||||
return any_bone_collection_visible(&bone->runtime.collections);
|
||||
}
|
||||
bool ANIM_bonecoll_is_visible_editbone(const struct bArmature * /*armature*/,
|
||||
const struct EditBone *ebone)
|
||||
bool ANIM_bonecoll_is_visible_editbone(const bArmature * /*armature*/, const EditBone *ebone)
|
||||
{
|
||||
return any_bone_collection_visible(&ebone->bone_collections);
|
||||
}
|
||||
|
|
|
@ -19,6 +19,22 @@ class BakeItem {
|
|||
virtual ~BakeItem() = default;
|
||||
};
|
||||
|
||||
struct BakeState {
|
||||
/**
|
||||
* The ids are usually correspond to socket ids, so that the mapping stays intact even if socket
|
||||
* order changes.
|
||||
*/
|
||||
Map<int, std::unique_ptr<BakeItem>> items_by_id;
|
||||
};
|
||||
|
||||
/** Same as above, but does not own the bake items. */
|
||||
struct BakeStateRef {
|
||||
Map<int, const BakeItem *> items_by_id;
|
||||
|
||||
BakeStateRef() = default;
|
||||
BakeStateRef(const BakeState &bake_state);
|
||||
};
|
||||
|
||||
class GeometryBakeItem : public BakeItem {
|
||||
public:
|
||||
GeometrySet geometry;
|
||||
|
|
|
@ -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
|
|
@ -136,18 +136,13 @@ class DiskBDataWriter : public BDataWriter {
|
|||
BDataSlice write(const void *data, int64_t size) override;
|
||||
};
|
||||
|
||||
/**
|
||||
* Writes the bake item into `r_io_item`.
|
||||
*/
|
||||
void serialize_bake_item(const BakeItem &item,
|
||||
BDataWriter &bdata_writer,
|
||||
BDataSharing &bdata_sharing,
|
||||
io::serialize::DictionaryValue &r_io_item);
|
||||
/**
|
||||
* Creates a bake item from `io_item`.
|
||||
*/
|
||||
std::unique_ptr<BakeItem> deserialize_bake_item(const io::serialize::DictionaryValue &io_item,
|
||||
const BDataReader &bdata_reader,
|
||||
const BDataSharing &bdata_sharing);
|
||||
void serialize_bake(const BakeState &bake_state,
|
||||
BDataWriter &bdata_writer,
|
||||
BDataSharing &bdata_sharing,
|
||||
std::ostream &r_stream);
|
||||
|
||||
std::optional<BakeState> deserialize_bake(std::istream &stream,
|
||||
const BDataReader &bdata_reader,
|
||||
const BDataSharing &bdata_sharing);
|
||||
|
||||
} // namespace blender::bke
|
||||
|
|
|
@ -24,8 +24,13 @@ struct ImBuf;
|
|||
struct Scopes;
|
||||
struct rctf;
|
||||
|
||||
void BKE_curvemapping_set_defaults(
|
||||
struct CurveMapping *cumap, int tot, float minx, float miny, float maxx, float maxy);
|
||||
void BKE_curvemapping_set_defaults(struct CurveMapping *cumap,
|
||||
int tot,
|
||||
float minx,
|
||||
float miny,
|
||||
float maxx,
|
||||
float maxy,
|
||||
short default_handle_type);
|
||||
struct CurveMapping *BKE_curvemapping_add(int tot, float minx, float miny, float maxx, float maxy);
|
||||
void BKE_curvemapping_free_data(struct CurveMapping *cumap);
|
||||
void BKE_curvemapping_free(struct CurveMapping *cumap);
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -216,7 +216,8 @@ void BKE_previewimg_ensure(struct PreviewImage *prv, int size);
|
|||
|
||||
const char *BKE_previewimg_deferred_filepath_get(const struct PreviewImage *prv);
|
||||
#ifdef __cplusplus
|
||||
std::optional<int> BKE_previewimg_deferred_thumb_source_get(const struct PreviewImage *prv);
|
||||
extern "C++" std::optional<int> BKE_previewimg_deferred_thumb_source_get(
|
||||
const struct PreviewImage *prv);
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
||||
/**
|
||||
|
|
|
@ -146,7 +146,6 @@ short2 lnor_space_custom_normal_to_data(const CornerNormalSpace &lnor_space,
|
|||
* Useful to materialize sharp edges (or non-smooth faces) without actually modifying the geometry
|
||||
* (splitting edges).
|
||||
*
|
||||
* \param loop_to_face_map: Optional pre-created map from corners to their face.
|
||||
* \param sharp_edges: Optional array of sharp edge tags, used to split the evaluated normals on
|
||||
* each side of the edge.
|
||||
* \param r_lnors_spacearr: Optional return data filled with information about the custom
|
||||
|
@ -202,6 +201,7 @@ void edges_sharp_from_angle_set(OffsetIndices<int> faces,
|
|||
Span<int> corner_verts,
|
||||
Span<int> corner_edges,
|
||||
Span<float3> face_normals,
|
||||
Span<int> loop_to_face,
|
||||
const bool *sharp_faces,
|
||||
const float split_angle,
|
||||
MutableSpan<bool> sharp_edges);
|
||||
|
|
|
@ -280,12 +280,17 @@ GroupedSpan<int> build_vert_to_edge_map(Span<int2> edges,
|
|||
Array<int> &r_offsets,
|
||||
Array<int> &r_indices);
|
||||
|
||||
void build_vert_to_face_indices(OffsetIndices<int> faces,
|
||||
Span<int> corner_verts,
|
||||
OffsetIndices<int> offsets,
|
||||
MutableSpan<int> face_indices);
|
||||
GroupedSpan<int> build_vert_to_face_map(OffsetIndices<int> faces,
|
||||
Span<int> corner_verts,
|
||||
int verts_num,
|
||||
Array<int> &r_offsets,
|
||||
Array<int> &r_indices);
|
||||
|
||||
Array<int> build_vert_to_corner_indices(Span<int> corner_verts, OffsetIndices<int> offsets);
|
||||
GroupedSpan<int> build_vert_to_loop_map(Span<int> corner_verts,
|
||||
int verts_num,
|
||||
Array<int> &r_offsets,
|
||||
|
|
|
@ -141,6 +141,17 @@ struct MeshRuntime {
|
|||
SharedCache<Vector<float3>> face_normals_cache;
|
||||
SharedCache<Vector<float3>> corner_normals_cache;
|
||||
|
||||
/**
|
||||
* Cache of offsets for vert to face/corner maps. The same offsets array is used to group
|
||||
* indices for both the vertex to face and vertex to corner maps.
|
||||
*/
|
||||
SharedCache<Array<int>> vert_to_face_offset_cache;
|
||||
/** Cache of indices for vert to face map. */
|
||||
SharedCache<Array<int>> vert_to_face_map_cache;
|
||||
/** Cache of indices for vert to corner map. */
|
||||
SharedCache<Array<int>> vert_to_corner_map_cache;
|
||||
/** Cache of face indices for each face corner. */
|
||||
SharedCache<Array<int>> corner_to_face_map_cache;
|
||||
/** Cache of data about edges not used by faces. See #Mesh::loose_edges(). */
|
||||
SharedCache<LooseEdgeCache> loose_edges_cache;
|
||||
/** Cache of data about vertices not used by edges. See #Mesh::loose_verts(). */
|
||||
|
|
|
@ -288,9 +288,7 @@ class bNodeRuntime : NonCopyable, NonMovable {
|
|||
/** Update flags. */
|
||||
int update = 0;
|
||||
|
||||
/** Initial locx for insert offset animation. */
|
||||
float anim_init_locx;
|
||||
/** 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. */
|
||||
|
|
|
@ -267,12 +267,7 @@ void BKE_paint_blend_read_data(BlendDataReader *reader, const Scene *scene, Pain
|
|||
|
||||
/** Used for both vertex color and weight paint. */
|
||||
struct SculptVertexPaintGeomMap {
|
||||
blender::Array<int> vert_to_loop_offsets;
|
||||
blender::Array<int> vert_to_loop_indices;
|
||||
blender::GroupedSpan<int> vert_to_loop;
|
||||
|
||||
blender::Array<int> vert_to_face_offsets;
|
||||
blender::Array<int> vert_to_face_indices;
|
||||
blender::GroupedSpan<int> vert_to_face;
|
||||
};
|
||||
|
||||
|
@ -591,9 +586,7 @@ struct SculptSession {
|
|||
float *vmask;
|
||||
|
||||
/* Mesh connectivity maps. */
|
||||
/* Vertices to adjacent faces. */
|
||||
blender::Array<int> vert_to_face_offsets;
|
||||
blender::Array<int> vert_to_face_indices;
|
||||
/* Vertices to adjacent polys. */
|
||||
blender::GroupedSpan<int> pmap;
|
||||
|
||||
/* Edges to adjacent faces. */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -414,6 +414,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;
|
||||
|
|
|
@ -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,12 @@
|
|||
#include "BLI_sub_frame.hh"
|
||||
|
||||
struct bNodeTree;
|
||||
struct ModifierData;
|
||||
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 +30,34 @@ enum class CacheState {
|
|||
Baked,
|
||||
};
|
||||
|
||||
struct StatesAroundFrame {
|
||||
const ModifierSimulationStateAtFrame *prev = nullptr;
|
||||
const ModifierSimulationStateAtFrame *current = nullptr;
|
||||
const ModifierSimulationStateAtFrame *next = nullptr;
|
||||
struct SimulationZoneFrameCache {
|
||||
SubFrame frame;
|
||||
BakeState state;
|
||||
/** 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 {
|
||||
BakeState state;
|
||||
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 +66,19 @@ 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);
|
||||
|
||||
/**
|
||||
* Get the directory that contains all baked simulation data for the given modifier.
|
||||
*/
|
||||
std::string get_default_modifier_bake_directory(const Main &bmain,
|
||||
const Object &object,
|
||||
const ModifierData &md);
|
||||
|
||||
} // namespace blender::bke::sim
|
||||
|
|
|
@ -1,50 +0,0 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BKE_bake_items_serialize.hh"
|
||||
#include "BKE_simulation_state.hh"
|
||||
|
||||
#include "BLI_serialize.hh"
|
||||
|
||||
struct Main;
|
||||
struct ModifierData;
|
||||
struct Object;
|
||||
|
||||
namespace blender {
|
||||
class fstream;
|
||||
}
|
||||
|
||||
namespace blender::bke::sim {
|
||||
|
||||
using DictionaryValue = io::serialize::DictionaryValue;
|
||||
using DictionaryValuePtr = std::shared_ptr<DictionaryValue>;
|
||||
|
||||
/**
|
||||
* Get the directory that contains all baked simulation data for the given modifier.
|
||||
*/
|
||||
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);
|
||||
|
||||
} // namespace blender::bke::sim
|
|
@ -127,6 +127,7 @@ void BKE_sound_update_scene_listener(struct Scene *scene);
|
|||
|
||||
void *BKE_sound_scene_add_scene_sound(
|
||||
struct Scene *scene, struct Sequence *sequence, int startframe, int endframe, int frameskip);
|
||||
|
||||
void *BKE_sound_scene_add_scene_sound_defaults(struct Scene *scene, struct Sequence *sequence);
|
||||
|
||||
void *BKE_sound_add_scene_sound(
|
||||
|
@ -145,8 +146,14 @@ void BKE_sound_move_scene_sound(const struct Scene *scene,
|
|||
double audio_offset);
|
||||
void BKE_sound_move_scene_sound_defaults(struct Scene *scene, struct Sequence *sequence);
|
||||
|
||||
/* Join the Sequence with the structure in Audaspace, the second parameter is a bSound */
|
||||
void BKE_sound_update_scene_sound(void *handle, struct bSound *sound);
|
||||
|
||||
/* Join the Sequence with the structure in Audaspace, the second parameter is the AUD_Sound created
|
||||
* in Audaspace previously
|
||||
*/
|
||||
void BKE_sound_update_sequence_handle(void *handle, void *sound_handle);
|
||||
|
||||
void BKE_sound_set_cfra(int cfra);
|
||||
|
||||
void BKE_sound_set_scene_volume(struct Scene *scene, float volume);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
@ -270,7 +271,6 @@ set(SRC
|
|||
intern/shader_fx.cc
|
||||
intern/shrinkwrap.cc
|
||||
intern/simulation_state.cc
|
||||
intern/simulation_state_serialize.cc
|
||||
intern/softbody.c
|
||||
intern/sound.cc
|
||||
intern/speaker.cc
|
||||
|
@ -333,6 +333,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
|
||||
|
@ -480,7 +481,6 @@ set(SRC
|
|||
BKE_shader_fx.h
|
||||
BKE_shrinkwrap.h
|
||||
BKE_simulation_state.hh
|
||||
BKE_simulation_state_serialize.hh
|
||||
BKE_softbody.h
|
||||
BKE_sound.h
|
||||
BKE_speaker.h
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "BLI_listbase.h"
|
||||
#include "BLI_string.h"
|
||||
#include "BLI_string_ref.hh"
|
||||
#include "BLI_string_utf8.h"
|
||||
#include "BLI_string_utils.h"
|
||||
#include "BLI_uuid.h"
|
||||
|
||||
|
@ -86,7 +87,7 @@ AssetMetaData::~AssetMetaData()
|
|||
static AssetTag *asset_metadata_tag_add(AssetMetaData *asset_data, const char *const name)
|
||||
{
|
||||
AssetTag *tag = (AssetTag *)MEM_callocN(sizeof(*tag), __func__);
|
||||
STRNCPY(tag->name, name);
|
||||
STRNCPY_UTF8(tag->name, name);
|
||||
|
||||
BLI_addtail(&asset_data->tags, tag);
|
||||
asset_data->tot_tags++;
|
||||
|
|
|
@ -73,4 +73,12 @@ PrimitiveBakeItem::~PrimitiveBakeItem()
|
|||
|
||||
StringBakeItem::StringBakeItem(std::string value) : value_(std::move(value)) {}
|
||||
|
||||
BakeStateRef::BakeStateRef(const BakeState &bake_state)
|
||||
{
|
||||
this->items_by_id.reserve(bake_state.items_by_id.size());
|
||||
for (auto item : bake_state.items_by_id.items()) {
|
||||
this->items_by_id.add_new(item.key, item.value.get());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace blender::bke
|
||||
|
|
|
@ -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
|
|
@ -960,10 +960,10 @@ template<typename T>
|
|||
return false;
|
||||
}
|
||||
|
||||
void serialize_bake_item(const BakeItem &item,
|
||||
BDataWriter &bdata_writer,
|
||||
BDataSharing &bdata_sharing,
|
||||
DictionaryValue &r_io_item)
|
||||
static void serialize_bake_item(const BakeItem &item,
|
||||
BDataWriter &bdata_writer,
|
||||
BDataSharing &bdata_sharing,
|
||||
DictionaryValue &r_io_item)
|
||||
{
|
||||
if (const auto *geometry_state_item = dynamic_cast<const GeometryBakeItem *>(&item)) {
|
||||
r_io_item.append_str("type", "GEOMETRY");
|
||||
|
@ -996,9 +996,9 @@ void serialize_bake_item(const BakeItem &item,
|
|||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<BakeItem> deserialize_bake_item(const DictionaryValue &io_item,
|
||||
const BDataReader &bdata_reader,
|
||||
const BDataSharing &bdata_sharing)
|
||||
static std::unique_ptr<BakeItem> deserialize_bake_item(const DictionaryValue &io_item,
|
||||
const BDataReader &bdata_reader,
|
||||
const BDataSharing &bdata_sharing)
|
||||
{
|
||||
|
||||
const std::optional<StringRefNull> state_item_type = io_item.lookup_str("type");
|
||||
|
@ -1064,4 +1064,70 @@ std::unique_ptr<BakeItem> deserialize_bake_item(const DictionaryValue &io_item,
|
|||
return {};
|
||||
}
|
||||
|
||||
static constexpr int bake_file_version = 3;
|
||||
|
||||
void serialize_bake(const BakeState &bake_state,
|
||||
BDataWriter &bdata_writer,
|
||||
BDataSharing &bdata_sharing,
|
||||
std::ostream &r_stream)
|
||||
{
|
||||
io::serialize::DictionaryValue io_root;
|
||||
io_root.append_int("version", bake_file_version);
|
||||
io::serialize::DictionaryValue &io_items = *io_root.append_dict("items");
|
||||
for (auto item : bake_state.items_by_id.items()) {
|
||||
io::serialize::DictionaryValue &io_item = *io_items.append_dict(std::to_string(item.key));
|
||||
bke::serialize_bake_item(*item.value, bdata_writer, bdata_sharing, io_item);
|
||||
}
|
||||
|
||||
io::serialize::JsonFormatter formatter;
|
||||
formatter.serialize(r_stream, io_root);
|
||||
}
|
||||
|
||||
std::optional<BakeState> deserialize_bake(std::istream &stream,
|
||||
const BDataReader &bdata_reader,
|
||||
const BDataSharing &bdata_sharing)
|
||||
{
|
||||
JsonFormatter formatter;
|
||||
std::unique_ptr<io::serialize::Value> io_root_value = formatter.deserialize(stream);
|
||||
if (!io_root_value) {
|
||||
return std::nullopt;
|
||||
}
|
||||
const io::serialize::DictionaryValue *io_root = io_root_value->as_dictionary_value();
|
||||
if (!io_root) {
|
||||
return std::nullopt;
|
||||
}
|
||||
const std::optional<int> version = io_root->lookup_int("version");
|
||||
if (!version.has_value() || *version != bake_file_version) {
|
||||
return std::nullopt;
|
||||
}
|
||||
const io::serialize::DictionaryValue *io_items = io_root->lookup_dict("items");
|
||||
if (!io_items) {
|
||||
return std::nullopt;
|
||||
}
|
||||
BakeState bake_state;
|
||||
for (const auto &io_item_value : io_items->elements()) {
|
||||
const io::serialize::DictionaryValue *io_item = io_item_value.second->as_dictionary_value();
|
||||
if (!io_item) {
|
||||
return std::nullopt;
|
||||
}
|
||||
int id;
|
||||
try {
|
||||
id = std::stoi(io_item_value.first);
|
||||
}
|
||||
catch (...) {
|
||||
return std::nullopt;
|
||||
}
|
||||
if (bake_state.items_by_id.contains(id)) {
|
||||
return std::nullopt;
|
||||
}
|
||||
std::unique_ptr<BakeItem> bake_item = deserialize_bake_item(
|
||||
*io_item, bdata_reader, bdata_sharing);
|
||||
if (!bake_item) {
|
||||
return std::nullopt;
|
||||
}
|
||||
bake_state.items_by_id.add_new(id, std::move(bake_item));
|
||||
}
|
||||
return bake_state;
|
||||
}
|
||||
|
||||
} // namespace blender::bke
|
||||
|
|
|
@ -776,7 +776,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type)
|
|||
|
||||
/* Curve. */
|
||||
custom_curve = brush->gpencil_settings->curve_sensitivity;
|
||||
BKE_curvemapping_set_defaults(custom_curve, 0, 0.0f, 0.0f, 1.0f, 1.0f);
|
||||
BKE_curvemapping_set_defaults(custom_curve, 0, 0.0f, 0.0f, 1.0f, 1.0f, HD_AUTO);
|
||||
BKE_curvemapping_init(custom_curve);
|
||||
brush_gpencil_curvemap_reset(custom_curve->cm, 3, GPCURVE_PRESET_INK);
|
||||
|
||||
|
@ -813,7 +813,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type)
|
|||
|
||||
/* Curve. */
|
||||
custom_curve = brush->gpencil_settings->curve_sensitivity;
|
||||
BKE_curvemapping_set_defaults(custom_curve, 0, 0.0f, 0.0f, 1.0f, 1.0f);
|
||||
BKE_curvemapping_set_defaults(custom_curve, 0, 0.0f, 0.0f, 1.0f, 1.0f, HD_AUTO);
|
||||
BKE_curvemapping_init(custom_curve);
|
||||
brush_gpencil_curvemap_reset(custom_curve->cm, 3, GPCURVE_PRESET_INKNOISE);
|
||||
|
||||
|
@ -850,7 +850,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type)
|
|||
|
||||
/* Curve. */
|
||||
custom_curve = brush->gpencil_settings->curve_sensitivity;
|
||||
BKE_curvemapping_set_defaults(custom_curve, 0, 0.0f, 0.0f, 1.0f, 1.0f);
|
||||
BKE_curvemapping_set_defaults(custom_curve, 0, 0.0f, 0.0f, 1.0f, 1.0f, HD_AUTO);
|
||||
BKE_curvemapping_init(custom_curve);
|
||||
brush_gpencil_curvemap_reset(custom_curve->cm, 4, GPCURVE_PRESET_MARKER);
|
||||
|
||||
|
@ -886,12 +886,12 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type)
|
|||
|
||||
/* Curve. */
|
||||
custom_curve = brush->gpencil_settings->curve_sensitivity;
|
||||
BKE_curvemapping_set_defaults(custom_curve, 0, 0.0f, 0.0f, 1.0f, 1.0f);
|
||||
BKE_curvemapping_set_defaults(custom_curve, 0, 0.0f, 0.0f, 1.0f, 1.0f, HD_AUTO);
|
||||
BKE_curvemapping_init(custom_curve);
|
||||
brush_gpencil_curvemap_reset(custom_curve->cm, 3, GPCURVE_PRESET_CHISEL_SENSIVITY);
|
||||
|
||||
custom_curve = brush->gpencil_settings->curve_strength;
|
||||
BKE_curvemapping_set_defaults(custom_curve, 0, 0.0f, 0.0f, 1.0f, 1.0f);
|
||||
BKE_curvemapping_set_defaults(custom_curve, 0, 0.0f, 0.0f, 1.0f, 1.0f, HD_AUTO);
|
||||
BKE_curvemapping_init(custom_curve);
|
||||
brush_gpencil_curvemap_reset(custom_curve->cm, 4, GPCURVE_PRESET_CHISEL_STRENGTH);
|
||||
|
||||
|
|
|
@ -34,8 +34,13 @@
|
|||
|
||||
/* ***************** operations on full struct ************* */
|
||||
|
||||
void BKE_curvemapping_set_defaults(
|
||||
CurveMapping *cumap, int tot, float minx, float miny, float maxx, float maxy)
|
||||
void BKE_curvemapping_set_defaults(CurveMapping *cumap,
|
||||
int tot,
|
||||
float minx,
|
||||
float miny,
|
||||
float maxx,
|
||||
float maxy,
|
||||
short default_handle_type)
|
||||
{
|
||||
int a;
|
||||
float clipminx, clipminy, clipmaxx, clipmaxy;
|
||||
|
@ -57,14 +62,23 @@ void BKE_curvemapping_set_defaults(
|
|||
cumap->bwmul[0] = cumap->bwmul[1] = cumap->bwmul[2] = 1.0f;
|
||||
|
||||
for (a = 0; a < tot; a++) {
|
||||
if (default_handle_type == HD_VECT) {
|
||||
cumap->cm[a].default_handle_type = CUMA_HANDLE_VECTOR;
|
||||
}
|
||||
else if (default_handle_type == HD_AUTO_ANIM) {
|
||||
cumap->cm[a].default_handle_type = CUMA_HANDLE_AUTO_ANIM;
|
||||
}
|
||||
|
||||
cumap->cm[a].totpoint = 2;
|
||||
cumap->cm[a].curve = static_cast<CurveMapPoint *>(
|
||||
MEM_callocN(2 * sizeof(CurveMapPoint), "curve points"));
|
||||
|
||||
cumap->cm[a].curve[0].x = minx;
|
||||
cumap->cm[a].curve[0].y = miny;
|
||||
cumap->cm[a].curve[0].flag |= default_handle_type;
|
||||
cumap->cm[a].curve[1].x = maxx;
|
||||
cumap->cm[a].curve[1].y = maxy;
|
||||
cumap->cm[a].curve[1].flag |= default_handle_type;
|
||||
}
|
||||
|
||||
cumap->changed_timestamp = 0;
|
||||
|
@ -76,7 +90,7 @@ CurveMapping *BKE_curvemapping_add(int tot, float minx, float miny, float maxx,
|
|||
|
||||
cumap = static_cast<CurveMapping *>(MEM_callocN(sizeof(CurveMapping), "new curvemap"));
|
||||
|
||||
BKE_curvemapping_set_defaults(cumap, tot, minx, miny, maxx, maxy);
|
||||
BKE_curvemapping_set_defaults(cumap, tot, minx, miny, maxx, maxy, HD_AUTO);
|
||||
|
||||
return cumap;
|
||||
}
|
||||
|
@ -238,6 +252,7 @@ CurveMapPoint *BKE_curvemap_insert(CurveMap *cuma, float x, float y)
|
|||
cmp[a].x = x;
|
||||
cmp[a].y = y;
|
||||
cmp[a].flag = CUMA_SELECT;
|
||||
cmp[a].flag |= cuma->default_handle_type;
|
||||
foundloc = true;
|
||||
newcmp = &cmp[a];
|
||||
}
|
||||
|
@ -266,6 +281,7 @@ void BKE_curvemap_reset(CurveMap *cuma, const rctf *clipr, int preset, int slope
|
|||
|
||||
switch (preset) {
|
||||
case CURVE_PRESET_LINE:
|
||||
case CURVE_PRESET_CONSTANT_MEDIAN:
|
||||
cuma->totpoint = 2;
|
||||
break;
|
||||
case CURVE_PRESET_SHARP:
|
||||
|
@ -297,6 +313,10 @@ void BKE_curvemap_reset(CurveMap *cuma, const rctf *clipr, int preset, int slope
|
|||
cuma->curve = static_cast<CurveMapPoint *>(
|
||||
MEM_callocN(cuma->totpoint * sizeof(CurveMapPoint), "curve points"));
|
||||
|
||||
for (int i = 0; i < cuma->totpoint; i++) {
|
||||
cuma->curve[i].flag = cuma->default_handle_type;
|
||||
}
|
||||
|
||||
switch (preset) {
|
||||
case CURVE_PRESET_LINE:
|
||||
cuma->curve[0].x = clipr->xmin;
|
||||
|
@ -304,10 +324,18 @@ void BKE_curvemap_reset(CurveMap *cuma, const rctf *clipr, int preset, int slope
|
|||
cuma->curve[1].x = clipr->xmax;
|
||||
cuma->curve[1].y = clipr->ymin;
|
||||
if (slope == CURVEMAP_SLOPE_POS_NEG) {
|
||||
cuma->curve[0].flag &= ~CUMA_HANDLE_AUTO_ANIM;
|
||||
cuma->curve[1].flag &= ~CUMA_HANDLE_AUTO_ANIM;
|
||||
cuma->curve[0].flag |= CUMA_HANDLE_VECTOR;
|
||||
cuma->curve[1].flag |= CUMA_HANDLE_VECTOR;
|
||||
}
|
||||
break;
|
||||
case CURVE_PRESET_CONSTANT_MEDIAN:
|
||||
cuma->curve[0].x = clipr->xmin;
|
||||
cuma->curve[0].y = (clipr->ymin + clipr->ymax) / 2.0f;
|
||||
cuma->curve[1].x = clipr->xmax;
|
||||
cuma->curve[1].y = (clipr->ymin + clipr->ymax) / 2.0f;
|
||||
break;
|
||||
case CURVE_PRESET_SHARP:
|
||||
cuma->curve[0].x = 0;
|
||||
cuma->curve[0].y = 1;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -291,7 +291,7 @@ void BKE_previewimg_freefunc(void *link)
|
|||
if (!prv) {
|
||||
return;
|
||||
}
|
||||
BKE_previewimg_freefunc(&prv);
|
||||
BKE_previewimg_free(&prv);
|
||||
}
|
||||
|
||||
void BKE_previewimg_free(PreviewImage **prv)
|
||||
|
@ -310,9 +310,7 @@ void BKE_previewimg_free(PreviewImage **prv)
|
|||
PreviewImageDeferred &this_deferred = PreviewImageDeferred::from_base(**prv);
|
||||
std::destroy_at(&this_deferred.filepath);
|
||||
}
|
||||
else {
|
||||
MEM_delete(*prv);
|
||||
}
|
||||
MEM_delete(*prv);
|
||||
*prv = nullptr;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2278,7 +2278,7 @@ void BKE_keyblock_mesh_calc_normals(const KeyBlock *kb,
|
|||
faces,
|
||||
corner_verts,
|
||||
corner_edges,
|
||||
{},
|
||||
mesh->corner_to_face_map(),
|
||||
{reinterpret_cast<blender::float3 *>(vert_normals), mesh->totvert},
|
||||
{reinterpret_cast<blender::float3 *>(face_normals), faces.size()},
|
||||
sharp_edges,
|
||||
|
|
|
@ -139,6 +139,10 @@ static void mesh_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int
|
|||
mesh_dst->runtime->loose_edges_cache = mesh_src->runtime->loose_edges_cache;
|
||||
mesh_dst->runtime->looptris_cache = mesh_src->runtime->looptris_cache;
|
||||
mesh_dst->runtime->looptri_faces_cache = mesh_src->runtime->looptri_faces_cache;
|
||||
mesh_dst->runtime->vert_to_face_offset_cache = mesh_src->runtime->vert_to_face_offset_cache;
|
||||
mesh_dst->runtime->vert_to_face_map_cache = mesh_src->runtime->vert_to_face_map_cache;
|
||||
mesh_dst->runtime->vert_to_corner_map_cache = mesh_src->runtime->vert_to_corner_map_cache;
|
||||
mesh_dst->runtime->corner_to_face_map_cache = mesh_src->runtime->corner_to_face_map_cache;
|
||||
|
||||
/* Only do tessface if we have no faces. */
|
||||
const bool do_tessface = ((mesh_src->totface_legacy != 0) && (mesh_src->faces_num == 0));
|
||||
|
@ -1053,9 +1057,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;
|
||||
}
|
||||
|
||||
|
|
|
@ -204,8 +204,7 @@ class MeshFairingContext : public FairingContext {
|
|||
faces = mesh->faces();
|
||||
corner_verts_ = mesh->corner_verts();
|
||||
corner_edges_ = mesh->corner_edges();
|
||||
vlmap_ = blender::bke::mesh::build_vert_to_loop_map(
|
||||
corner_verts_, positions.size(), vert_to_face_offsets_, vert_to_face_indices_);
|
||||
vlmap_ = mesh->vert_to_corner_map();
|
||||
|
||||
/* Deformation coords. */
|
||||
co_.reserve(mesh->totvert);
|
||||
|
@ -220,7 +219,7 @@ class MeshFairingContext : public FairingContext {
|
|||
}
|
||||
}
|
||||
|
||||
loop_to_face_map_ = blender::bke::mesh::build_loop_to_face_map(faces);
|
||||
loop_to_face_map_ = mesh->corner_to_face_map();
|
||||
}
|
||||
|
||||
void adjacents_coords_from_loop(const int loop,
|
||||
|
@ -247,9 +246,7 @@ class MeshFairingContext : public FairingContext {
|
|||
Span<int> corner_edges_;
|
||||
blender::OffsetIndices<int> faces;
|
||||
Span<blender::int2> edges_;
|
||||
Array<int> loop_to_face_map_;
|
||||
Array<int> vert_to_face_offsets_;
|
||||
Array<int> vert_to_face_indices_;
|
||||
Span<int> loop_to_face_map_;
|
||||
};
|
||||
|
||||
class BMeshFairingContext : public FairingContext {
|
||||
|
|
|
@ -379,6 +379,20 @@ GroupedSpan<int> build_vert_to_edge_map(const Span<int2> edges,
|
|||
return {OffsetIndices<int>(r_offsets), r_indices};
|
||||
}
|
||||
|
||||
void build_vert_to_face_indices(const OffsetIndices<int> faces,
|
||||
const Span<int> corner_verts,
|
||||
const OffsetIndices<int> offsets,
|
||||
MutableSpan<int> r_indices)
|
||||
{
|
||||
Array<int> counts(offsets.size(), 0);
|
||||
for (const int64_t face_i : faces.index_range()) {
|
||||
for (const int vert : corner_verts.slice(faces[face_i])) {
|
||||
r_indices[offsets[vert].start() + counts[vert]] = int(face_i);
|
||||
counts[vert]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GroupedSpan<int> build_vert_to_face_map(const OffsetIndices<int> faces,
|
||||
const Span<int> corner_verts,
|
||||
const int verts_num,
|
||||
|
@ -387,17 +401,16 @@ GroupedSpan<int> build_vert_to_face_map(const OffsetIndices<int> faces,
|
|||
{
|
||||
r_offsets = create_reverse_offsets(corner_verts, verts_num);
|
||||
r_indices.reinitialize(r_offsets.last());
|
||||
Array<int> counts(verts_num, 0);
|
||||
|
||||
for (const int64_t face_i : faces.index_range()) {
|
||||
for (const int vert : corner_verts.slice(faces[face_i])) {
|
||||
r_indices[r_offsets[vert] + counts[vert]] = int(face_i);
|
||||
counts[vert]++;
|
||||
}
|
||||
}
|
||||
build_vert_to_face_indices(faces, corner_verts, OffsetIndices<int>(r_offsets), r_indices);
|
||||
return {OffsetIndices<int>(r_offsets), r_indices};
|
||||
}
|
||||
|
||||
Array<int> build_vert_to_corner_indices(const Span<int> corner_verts,
|
||||
const OffsetIndices<int> offsets)
|
||||
{
|
||||
return reverse_indices_in_groups(corner_verts, offsets);
|
||||
}
|
||||
|
||||
GroupedSpan<int> build_vert_to_loop_map(const Span<int> corner_verts,
|
||||
const int verts_num,
|
||||
Array<int> &r_offsets,
|
||||
|
|
|
@ -114,10 +114,7 @@ void BKE_mesh_merge_customdata_for_apply_modifier(Mesh *me)
|
|||
return;
|
||||
}
|
||||
|
||||
Array<int> vert_to_loop_offsets;
|
||||
Array<int> vert_to_loop_indices;
|
||||
const GroupedSpan<int> vert_to_loop = bke::mesh::build_vert_to_loop_map(
|
||||
me->corner_verts(), me->totvert, vert_to_loop_offsets, vert_to_loop_indices);
|
||||
const GroupedSpan<int> vert_to_loop = me->vert_to_corner_map();
|
||||
|
||||
Vector<float2 *> mloopuv_layers;
|
||||
mloopuv_layers.reserve(mloopuv_layers_num);
|
||||
|
|
|
@ -415,7 +415,7 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd,
|
|||
result_faces,
|
||||
result_corner_verts,
|
||||
result_corner_edges,
|
||||
{},
|
||||
result->corner_to_face_map(),
|
||||
result->vert_normals(),
|
||||
result->face_normals(),
|
||||
sharp_edges,
|
||||
|
|
|
@ -902,6 +902,7 @@ void edges_sharp_from_angle_set(const OffsetIndices<int> faces,
|
|||
const Span<int> corner_verts,
|
||||
const Span<int> corner_edges,
|
||||
const Span<float3> face_normals,
|
||||
const Span<int> loop_to_face,
|
||||
const bool *sharp_faces,
|
||||
const float split_angle,
|
||||
MutableSpan<bool> sharp_edges)
|
||||
|
@ -914,9 +915,6 @@ void edges_sharp_from_angle_set(const OffsetIndices<int> faces,
|
|||
/* Mapping edge -> loops. See #bke::mesh::normals_calc_loop for details. */
|
||||
Array<int2> edge_to_loops(sharp_edges.size(), int2(0));
|
||||
|
||||
/* Simple mapping from a loop to its face index. */
|
||||
const Array<int> loop_to_face = build_loop_to_face_map(faces);
|
||||
|
||||
mesh_edges_sharp_tag(faces,
|
||||
corner_verts,
|
||||
corner_edges,
|
||||
|
@ -1341,17 +1339,6 @@ void normals_calc_loop(const Span<float3> vert_positions,
|
|||
* Note also that loose edges always have both values set to 0! */
|
||||
Array<int2> edge_to_loops(edges.size(), int2(0));
|
||||
|
||||
/* Simple mapping from a loop to its face index. */
|
||||
Span<int> loop_to_face;
|
||||
Array<int> local_loop_to_face_map;
|
||||
if (loop_to_face_map.is_empty()) {
|
||||
local_loop_to_face_map = build_loop_to_face_map(faces);
|
||||
loop_to_face = local_loop_to_face_map;
|
||||
}
|
||||
else {
|
||||
loop_to_face = loop_to_face_map;
|
||||
}
|
||||
|
||||
CornerNormalSpaceArray _lnors_spacearr;
|
||||
|
||||
#ifdef DEBUG_TIME
|
||||
|
@ -1374,7 +1361,7 @@ void normals_calc_loop(const Span<float3> vert_positions,
|
|||
common_data.corner_verts = corner_verts;
|
||||
common_data.corner_edges = corner_edges;
|
||||
common_data.edge_to_loops = edge_to_loops;
|
||||
common_data.loop_to_face = loop_to_face;
|
||||
common_data.loop_to_face = loop_to_face_map;
|
||||
common_data.face_normals = face_normals;
|
||||
common_data.vert_normals = vert_normals;
|
||||
|
||||
|
|
|
@ -1267,12 +1267,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
|
|||
|
||||
blender::Array<blender::float3> face_cents_src;
|
||||
|
||||
Array<int> vert_to_loop_src_offsets;
|
||||
Array<int> vert_to_loop_src_indices;
|
||||
GroupedSpan<int> vert_to_loop_map_src;
|
||||
|
||||
Array<int> vert_to_face_src_offsets;
|
||||
Array<int> vert_to_face_src_indices;
|
||||
GroupedSpan<int> vert_to_face_map_src;
|
||||
|
||||
Array<int> edge_to_face_src_offsets;
|
||||
|
@ -1283,7 +1278,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
|
|||
int *face_to_looptri_map_src_buff = nullptr;
|
||||
|
||||
/* Unlike above, those are one-to-one mappings, simpler! */
|
||||
blender::Array<int> loop_to_face_map_src;
|
||||
blender::Span<int> loop_to_face_map_src;
|
||||
|
||||
const blender::Span<blender::float3> positions_src = me_src->vert_positions();
|
||||
const int num_verts_src = me_src->totvert;
|
||||
|
@ -1335,15 +1330,9 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
|
|||
}
|
||||
|
||||
if (use_from_vert) {
|
||||
vert_to_loop_map_src = bke::mesh::build_vert_to_loop_map(
|
||||
corner_verts_src, num_verts_src, vert_to_loop_src_offsets, vert_to_loop_src_indices);
|
||||
|
||||
vert_to_loop_map_src = me_src->vert_to_corner_map();
|
||||
if (mode & MREMAP_USE_POLY) {
|
||||
vert_to_face_map_src = bke::mesh::build_vert_to_face_map(faces_src,
|
||||
corner_verts_src,
|
||||
num_verts_src,
|
||||
vert_to_face_src_offsets,
|
||||
vert_to_face_src_indices);
|
||||
vert_to_face_map_src = me_src->vert_to_face_map();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1355,7 +1344,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
|
|||
edge_to_face_src_indices);
|
||||
|
||||
if (use_from_vert) {
|
||||
loop_to_face_map_src = blender::bke::mesh::build_loop_to_face_map(faces_src);
|
||||
loop_to_face_map_src = me_src->corner_to_face_map();
|
||||
face_cents_src.reinitialize(faces_src.size());
|
||||
for (const int64_t i : faces_src.index_range()) {
|
||||
face_cents_src[i] = blender::bke::mesh::face_center_calc(
|
||||
|
|
|
@ -386,27 +386,13 @@ void BKE_remesh_reproject_vertex_paint(Mesh *target, const Mesh *source)
|
|||
return;
|
||||
}
|
||||
|
||||
Array<int> source_vert_to_loop_offsets;
|
||||
Array<int> source_vert_to_loop_indices;
|
||||
GroupedSpan<int> source_lmap;
|
||||
Array<int> target_vert_to_loop_offsets;
|
||||
Array<int> target_vert_to_loop_indices;
|
||||
GroupedSpan<int> target_lmap;
|
||||
BVHTreeFromMesh bvhtree = {nullptr};
|
||||
threading::parallel_invoke(
|
||||
[&]() { BKE_bvhtree_from_mesh_get(&bvhtree, source, BVHTREE_FROM_VERTS, 2); },
|
||||
[&]() {
|
||||
source_lmap = mesh::build_vert_to_loop_map(source->corner_verts(),
|
||||
source->totvert,
|
||||
source_vert_to_loop_offsets,
|
||||
source_vert_to_loop_indices);
|
||||
},
|
||||
[&]() {
|
||||
target_lmap = mesh::build_vert_to_loop_map(target->corner_verts(),
|
||||
target->totvert,
|
||||
target_vert_to_loop_offsets,
|
||||
target_vert_to_loop_indices);
|
||||
});
|
||||
[&]() { source_lmap = source->vert_to_corner_map(); },
|
||||
[&]() { target_lmap = target->vert_to_corner_map(); });
|
||||
|
||||
const Span<float3> target_positions = target->vert_positions();
|
||||
Array<int> nearest_src_verts(target_positions.size());
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "DNA_meshdata_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
|
||||
#include "BLI_array_utils.hh"
|
||||
#include "BLI_math_geom.h"
|
||||
#include "BLI_task.hh"
|
||||
#include "BLI_timeit.hh"
|
||||
|
@ -22,6 +23,7 @@
|
|||
#include "BKE_editmesh_cache.hh"
|
||||
#include "BKE_lib_id.h"
|
||||
#include "BKE_mesh.hh"
|
||||
#include "BKE_mesh_mapping.hh"
|
||||
#include "BKE_mesh_runtime.hh"
|
||||
#include "BKE_shrinkwrap.h"
|
||||
#include "BKE_subdiv_ccg.hh"
|
||||
|
@ -125,6 +127,58 @@ static void try_tag_verts_no_face_none(const Mesh &mesh)
|
|||
|
||||
} // namespace blender::bke
|
||||
|
||||
blender::Span<int> Mesh::corner_to_face_map() const
|
||||
{
|
||||
using namespace blender;
|
||||
this->runtime->corner_to_face_map_cache.ensure([&](Array<int> &r_data) {
|
||||
const OffsetIndices faces = this->faces();
|
||||
r_data = bke::mesh::build_loop_to_face_map(faces);
|
||||
});
|
||||
return this->runtime->corner_to_face_map_cache.data();
|
||||
}
|
||||
|
||||
blender::OffsetIndices<int> Mesh::vert_to_face_map_offsets() const
|
||||
{
|
||||
using namespace blender;
|
||||
this->runtime->vert_to_face_offset_cache.ensure([&](Array<int> &r_data) {
|
||||
r_data = Array<int>(this->totvert + 1, 0);
|
||||
offset_indices::build_reverse_offsets(this->corner_verts(), r_data);
|
||||
});
|
||||
return OffsetIndices<int>(this->runtime->vert_to_face_offset_cache.data());
|
||||
}
|
||||
|
||||
blender::GroupedSpan<int> Mesh::vert_to_face_map() const
|
||||
{
|
||||
using namespace blender;
|
||||
const OffsetIndices offsets = this->vert_to_face_map_offsets();
|
||||
this->runtime->vert_to_face_map_cache.ensure([&](Array<int> &r_data) {
|
||||
r_data.reinitialize(this->totloop);
|
||||
if (this->runtime->vert_to_corner_map_cache.is_cached() &&
|
||||
this->runtime->corner_to_face_map_cache.is_cached())
|
||||
{
|
||||
/* The vertex to face cache can be built from the vertex to face corner
|
||||
* and face corner to face maps if they are both already cached. */
|
||||
array_utils::gather(this->runtime->vert_to_corner_map_cache.data().as_span(),
|
||||
this->runtime->corner_to_face_map_cache.data().as_span(),
|
||||
r_data.as_mutable_span());
|
||||
}
|
||||
else {
|
||||
bke::mesh::build_vert_to_face_indices(this->faces(), this->corner_verts(), offsets, r_data);
|
||||
}
|
||||
});
|
||||
return {offsets, this->runtime->vert_to_face_map_cache.data()};
|
||||
}
|
||||
|
||||
blender::GroupedSpan<int> Mesh::vert_to_corner_map() const
|
||||
{
|
||||
using namespace blender;
|
||||
const OffsetIndices offsets = this->vert_to_face_map_offsets();
|
||||
this->runtime->vert_to_corner_map_cache.ensure([&](Array<int> &r_data) {
|
||||
r_data = bke::mesh::build_vert_to_corner_indices(this->corner_verts(), offsets);
|
||||
});
|
||||
return {offsets, this->runtime->vert_to_corner_map_cache.data()};
|
||||
}
|
||||
|
||||
const blender::bke::LooseVertCache &Mesh::loose_verts() const
|
||||
{
|
||||
using namespace blender::bke;
|
||||
|
@ -250,6 +304,10 @@ void BKE_mesh_runtime_clear_geometry(Mesh *mesh)
|
|||
free_bvh_cache(*mesh->runtime);
|
||||
free_subdiv_ccg(*mesh->runtime);
|
||||
mesh->runtime->bounds_cache.tag_dirty();
|
||||
mesh->runtime->vert_to_face_offset_cache.tag_dirty();
|
||||
mesh->runtime->vert_to_face_map_cache.tag_dirty();
|
||||
mesh->runtime->vert_to_corner_map_cache.tag_dirty();
|
||||
mesh->runtime->corner_to_face_map_cache.tag_dirty();
|
||||
mesh->runtime->vert_normals_cache.tag_dirty();
|
||||
mesh->runtime->face_normals_cache.tag_dirty();
|
||||
mesh->runtime->loose_edges_cache.tag_dirty();
|
||||
|
@ -271,6 +329,9 @@ void BKE_mesh_tag_edges_split(Mesh *mesh)
|
|||
free_bvh_cache(*mesh->runtime);
|
||||
mesh->runtime->vert_normals_cache.tag_dirty();
|
||||
free_subdiv_ccg(*mesh->runtime);
|
||||
mesh->runtime->vert_to_face_offset_cache.tag_dirty();
|
||||
mesh->runtime->vert_to_face_map_cache.tag_dirty();
|
||||
mesh->runtime->vert_to_corner_map_cache.tag_dirty();
|
||||
if (mesh->runtime->loose_edges_cache.is_cached() &&
|
||||
mesh->runtime->loose_edges_cache.data().count != 0)
|
||||
{
|
||||
|
@ -299,6 +360,7 @@ void BKE_mesh_tag_face_winding_changed(Mesh *mesh)
|
|||
mesh->runtime->vert_normals_cache.tag_dirty();
|
||||
mesh->runtime->face_normals_cache.tag_dirty();
|
||||
mesh->runtime->corner_normals_cache.tag_dirty();
|
||||
mesh->runtime->vert_to_corner_map_cache.tag_dirty();
|
||||
}
|
||||
|
||||
void BKE_mesh_tag_positions_changed(Mesh *mesh)
|
||||
|
|
|
@ -469,10 +469,6 @@ void multires_force_sculpt_rebuild(Object *object)
|
|||
BKE_pbvh_free(ss->pbvh);
|
||||
object->sculpt->pbvh = nullptr;
|
||||
}
|
||||
|
||||
ss->vert_to_face_indices = {};
|
||||
ss->vert_to_face_offsets = {};
|
||||
ss->pmap = {};
|
||||
}
|
||||
|
||||
void multires_force_external_reload(Object *object)
|
||||
|
|
|
@ -72,14 +72,7 @@ void multires_reshape_apply_base_refit_base_mesh(MultiresReshapeContext *reshape
|
|||
blender::MutableSpan<blender::float3> base_positions = base_mesh->vert_positions_for_write();
|
||||
/* Update the context in case the vertices were duplicated. */
|
||||
reshape_context->base_positions = base_positions;
|
||||
blender::Array<int> vert_to_face_offsets;
|
||||
blender::Array<int> vert_to_face_indices;
|
||||
const blender::GroupedSpan<int> pmap = blender::bke::mesh::build_vert_to_face_map(
|
||||
reshape_context->base_faces,
|
||||
reshape_context->base_corner_verts,
|
||||
base_mesh->totvert,
|
||||
vert_to_face_offsets,
|
||||
vert_to_face_indices);
|
||||
const blender::GroupedSpan<int> pmap = base_mesh->vert_to_face_map();
|
||||
|
||||
float(*origco)[3] = static_cast<float(*)[3]>(
|
||||
MEM_calloc_arrayN(base_mesh->totvert, sizeof(float[3]), __func__));
|
||||
|
|
|
@ -925,7 +925,6 @@ static void multires_unsubdivide_prepare_original_bmesh_for_extract(
|
|||
MultiresUnsubdivideContext *context)
|
||||
{
|
||||
Mesh *original_mesh = context->original_mesh;
|
||||
const blender::OffsetIndices original_faces = original_mesh->faces();
|
||||
|
||||
Mesh *base_mesh = context->base_mesh;
|
||||
|
||||
|
@ -953,7 +952,7 @@ static void multires_unsubdivide_prepare_original_bmesh_for_extract(
|
|||
BM_elem_flag_set(v, BM_ELEM_TAG, true);
|
||||
}
|
||||
|
||||
context->loop_to_face_map = blender::bke::mesh::build_loop_to_face_map(original_faces);
|
||||
context->loop_to_face_map = original_mesh->corner_to_face_map();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -52,7 +52,7 @@ struct MultiresUnsubdivideContext {
|
|||
|
||||
/* Private data. */
|
||||
BMesh *bm_original_mesh;
|
||||
blender::Array<int> loop_to_face_map;
|
||||
blender::Span<int> loop_to_face_map;
|
||||
const int *base_to_orig_vmap;
|
||||
};
|
||||
|
||||
|
|
|
@ -490,8 +490,8 @@ static bNodeSocket *make_socket(bNodeTree *ntree,
|
|||
|
||||
sock->limit = (in_out == SOCK_IN ? 1 : 0xFFF);
|
||||
|
||||
BLI_strncpy(sock->identifier, identifier.data(), sizeof(sock->identifier));
|
||||
BLI_strncpy(sock->name, name.data(), sizeof(sock->name));
|
||||
STRNCPY(sock->identifier, identifier.data());
|
||||
STRNCPY(sock->name, name.data());
|
||||
sock->storage = nullptr;
|
||||
sock->flag |= SOCK_COLLAPSED;
|
||||
|
||||
|
@ -519,7 +519,7 @@ static void construct_interface_as_legacy_sockets(bNodeTree *ntree)
|
|||
}
|
||||
|
||||
if (socket.description) {
|
||||
BLI_strncpy(iosock->description, socket.description, sizeof(iosock->description));
|
||||
STRNCPY(iosock->description, socket.description);
|
||||
}
|
||||
node_socket_copy_default_value_data(
|
||||
eNodeSocketDatatype(iosock->typeinfo->type), iosock->default_value, socket.socket_data);
|
||||
|
@ -812,6 +812,8 @@ void ntreeBlendWrite(BlendWriter *writer, bNodeTree *ntree)
|
|||
blender::bke::forward_compat::write_legacy_sockets(writer, ntree);
|
||||
}
|
||||
|
||||
BLO_write_struct(writer, GeometryNodeAssetTraits, ntree->geometry_node_asset_traits);
|
||||
|
||||
BLO_write_struct_array(
|
||||
writer, bNestedNodeRef, ntree->nested_node_refs_num, ntree->nested_node_refs);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
@ -1205,7 +1205,7 @@ bNodeTreeInterfaceItem *bNodeTreeInterface::insert_item_copy(const bNodeTreeInte
|
|||
|
||||
bool bNodeTreeInterface::remove_item(bNodeTreeInterfaceItem &item, bool move_content_to_parent)
|
||||
{
|
||||
bNodeTreeInterfacePanel *parent = this->find_item_parent(item);
|
||||
bNodeTreeInterfacePanel *parent = this->find_item_parent(item, true);
|
||||
if (parent == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -1391,13 +1391,7 @@ void BKE_sculptsession_free_deformMats(SculptSession *ss)
|
|||
|
||||
void BKE_sculptsession_free_vwpaint_data(SculptSession *ss)
|
||||
{
|
||||
SculptVertexPaintGeomMap *gmap = nullptr;
|
||||
if (ss->mode_type == OB_MODE_VERTEX_PAINT) {
|
||||
gmap = &ss->mode.vpaint.gmap;
|
||||
}
|
||||
else if (ss->mode_type == OB_MODE_WEIGHT_PAINT) {
|
||||
gmap = &ss->mode.wpaint.gmap;
|
||||
|
||||
if (ss->mode_type == OB_MODE_WEIGHT_PAINT) {
|
||||
MEM_SAFE_FREE(ss->mode.wpaint.alpha_weight);
|
||||
if (ss->mode.wpaint.dvert_prev) {
|
||||
BKE_defvert_array_free_elems(ss->mode.wpaint.dvert_prev, ss->totvert);
|
||||
|
@ -1405,15 +1399,6 @@ void BKE_sculptsession_free_vwpaint_data(SculptSession *ss)
|
|||
ss->mode.wpaint.dvert_prev = nullptr;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
gmap->vert_to_loop_offsets = {};
|
||||
gmap->vert_to_loop_indices = {};
|
||||
gmap->vert_to_loop = {};
|
||||
gmap->vert_to_face_offsets = {};
|
||||
gmap->vert_to_face_indices = {};
|
||||
gmap->vert_to_face = {};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1459,8 +1444,6 @@ static void sculptsession_free_pbvh(Object *object)
|
|||
ss->pbvh = nullptr;
|
||||
}
|
||||
|
||||
ss->vert_to_face_offsets = {};
|
||||
ss->vert_to_face_indices = {};
|
||||
ss->pmap = {};
|
||||
ss->edge_to_face_offsets = {};
|
||||
ss->edge_to_face_indices = {};
|
||||
|
@ -1776,12 +1759,8 @@ static void sculpt_update_object(
|
|||
sculpt_attribute_update_refs(ob);
|
||||
sculpt_update_persistent_base(ob);
|
||||
|
||||
if (ob->type == OB_MESH && ss->pmap.is_empty()) {
|
||||
ss->pmap = blender::bke::mesh::build_vert_to_face_map(me->faces(),
|
||||
me->corner_verts(),
|
||||
me->totvert,
|
||||
ss->vert_to_face_offsets,
|
||||
ss->vert_to_face_indices);
|
||||
if (ob->type == OB_MESH) {
|
||||
ss->pmap = me->vert_to_face_map();
|
||||
}
|
||||
|
||||
if (ss->pbvh) {
|
||||
|
@ -2236,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,
|
||||
|
@ -2325,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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -158,7 +158,7 @@ static void scene_init_data(ID *id)
|
|||
STRNCPY(scene->r.bake.filepath, U.renderdir);
|
||||
|
||||
mblur_shutter_curve = &scene->r.mblur_shutter_curve;
|
||||
BKE_curvemapping_set_defaults(mblur_shutter_curve, 1, 0.0f, 0.0f, 1.0f, 1.0f);
|
||||
BKE_curvemapping_set_defaults(mblur_shutter_curve, 1, 0.0f, 0.0f, 1.0f, 1.0f, HD_AUTO);
|
||||
BKE_curvemapping_init(mblur_shutter_curve);
|
||||
BKE_curvemap_reset(mblur_shutter_curve->cm,
|
||||
&mblur_shutter_curve->clipr,
|
||||
|
|
|
@ -1270,7 +1270,7 @@ bool BKE_screen_area_map_blend_read_data(BlendDataReader *reader, ScrAreaMap *ar
|
|||
static void regions_remove_invalid(SpaceType *space_type, ListBase *regionbase)
|
||||
{
|
||||
LISTBASE_FOREACH_MUTABLE (ARegion *, region, regionbase) {
|
||||
if (BKE_regiontype_from_id(space_type, region->regiontype) != NULL) {
|
||||
if (BKE_regiontype_from_id(space_type, region->regiontype) != nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,10 +2,12 @@
|
|||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include "BKE_collection.h"
|
||||
#include "BKE_curves.hh"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_simulation_state.hh"
|
||||
#include "BKE_simulation_state_serialize.hh"
|
||||
|
||||
#include "DNA_modifier_types.h"
|
||||
#include "DNA_node_types.h"
|
||||
|
@ -21,213 +23,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 +41,106 @@ 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn the name into something that can be used as file name. It does not necessarily have to be
|
||||
* human readable, but it can help if it is at least partially readable.
|
||||
*/
|
||||
static std::string escape_name(const StringRef name)
|
||||
{
|
||||
std::stringstream ss;
|
||||
for (const char c : name) {
|
||||
/* Only some letters allowed. Digits are not because they could lead to name collisions. */
|
||||
if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')) {
|
||||
ss << c;
|
||||
}
|
||||
else {
|
||||
ss << int(c);
|
||||
}
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
static std::string get_blend_file_name(const Main &bmain)
|
||||
{
|
||||
const StringRefNull blend_file_path = BKE_main_blendfile_path(&bmain);
|
||||
char blend_name[FILE_MAX];
|
||||
|
||||
BLI_path_split_file_part(blend_file_path.c_str(), blend_name, sizeof(blend_name));
|
||||
const int64_t type_start_index = StringRef(blend_name).rfind(".");
|
||||
if (type_start_index == StringRef::not_found) {
|
||||
return "";
|
||||
}
|
||||
blend_name[type_start_index] = '\0';
|
||||
return "blendcache_" + StringRef(blend_name);
|
||||
}
|
||||
|
||||
static std::string get_modifier_sim_name(const Object &object, const ModifierData &md)
|
||||
{
|
||||
const std::string object_name_escaped = escape_name(object.id.name + 2);
|
||||
const std::string modifier_name_escaped = escape_name(md.name);
|
||||
return "sim_" + object_name_escaped + "_" + modifier_name_escaped;
|
||||
}
|
||||
|
||||
std::string get_default_modifier_bake_directory(const Main &bmain,
|
||||
const Object &object,
|
||||
const ModifierData &md)
|
||||
{
|
||||
char dir[FILE_MAX];
|
||||
/* Make path that's relative to the .blend file. */
|
||||
BLI_path_join(dir,
|
||||
sizeof(dir),
|
||||
"//",
|
||||
get_blend_file_name(bmain).c_str(),
|
||||
get_modifier_sim_name(object, md).c_str());
|
||||
return dir;
|
||||
}
|
||||
|
||||
} // namespace blender::bke::sim
|
||||
|
|
|
@ -1,193 +0,0 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "BKE_curves.hh"
|
||||
#include "BKE_instances.hh"
|
||||
#include "BKE_lib_id.h"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_mesh.hh"
|
||||
#include "BKE_node_runtime.hh"
|
||||
#include "BKE_pointcloud.h"
|
||||
#include "BKE_simulation_state_serialize.hh"
|
||||
|
||||
#include "DNA_material_types.h"
|
||||
#include "DNA_modifier_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
|
||||
#include "BLI_endian_defines.h"
|
||||
#include "BLI_endian_switch.h"
|
||||
#include "BLI_fileops.hh"
|
||||
#include "BLI_math_matrix_types.hh"
|
||||
#include "BLI_math_quaternion_types.hh"
|
||||
#include "BLI_path_util.h"
|
||||
|
||||
#include "RNA_access.hh"
|
||||
#include "RNA_enum_types.hh"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
namespace blender::bke::sim {
|
||||
|
||||
/**
|
||||
* Turn the name into something that can be used as file name. It does not necessarily have to be
|
||||
* human readable, but it can help if it is at least partially readable.
|
||||
*/
|
||||
static std::string escape_name(const StringRef name)
|
||||
{
|
||||
std::stringstream ss;
|
||||
for (const char c : name) {
|
||||
/* Only some letters allowed. Digits are not because they could lead to name collisions. */
|
||||
if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')) {
|
||||
ss << c;
|
||||
}
|
||||
else {
|
||||
ss << int(c);
|
||||
}
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
static std::string get_blend_file_name(const Main &bmain)
|
||||
{
|
||||
const StringRefNull blend_file_path = BKE_main_blendfile_path(&bmain);
|
||||
char blend_name[FILE_MAX];
|
||||
|
||||
BLI_path_split_file_part(blend_file_path.c_str(), blend_name, sizeof(blend_name));
|
||||
const int64_t type_start_index = StringRef(blend_name).rfind(".");
|
||||
if (type_start_index == StringRef::not_found) {
|
||||
return "";
|
||||
}
|
||||
blend_name[type_start_index] = '\0';
|
||||
return "blendcache_" + StringRef(blend_name);
|
||||
}
|
||||
|
||||
static std::string get_modifier_sim_name(const Object &object, const ModifierData &md)
|
||||
{
|
||||
const std::string object_name_escaped = escape_name(object.id.name + 2);
|
||||
const std::string modifier_name_escaped = escape_name(md.name);
|
||||
return "sim_" + object_name_escaped + "_" + modifier_name_escaped;
|
||||
}
|
||||
|
||||
std::string get_default_modifier_bake_directory(const Main &bmain,
|
||||
const Object &object,
|
||||
const ModifierData &md)
|
||||
{
|
||||
char dir[FILE_MAX];
|
||||
/* Make path that's relative to the .blend file. */
|
||||
BLI_path_join(dir,
|
||||
sizeof(dir),
|
||||
"//",
|
||||
get_blend_file_name(bmain).c_str(),
|
||||
get_modifier_sim_name(object, md).c_str());
|
||||
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
|
|
@ -789,6 +789,19 @@ void BKE_sound_update_scene_sound(void *handle, bSound *sound)
|
|||
AUD_SequenceEntry_setSound(handle, sound->playback_handle);
|
||||
}
|
||||
|
||||
#endif /* WITH_AUDASPACE */
|
||||
|
||||
void BKE_sound_update_sequence_handle(void *handle, void *sound_handle)
|
||||
{
|
||||
#ifdef WITH_AUDASPACE
|
||||
AUD_SequenceEntry_setSound(handle, sound_handle);
|
||||
#else
|
||||
UNUSED_VARS(handle, sound_handle);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef WITH_AUDASPACE
|
||||
|
||||
void BKE_sound_set_cfra(int cfra)
|
||||
{
|
||||
sound_cfra = cfra;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -2309,6 +2309,8 @@ float voronoi_n_sphere_radius(const VoronoiParams ¶ms, 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 ¶ms,
|
||||
const T coord,
|
||||
|
@ -2319,8 +2321,7 @@ VoronoiOutput fractal_voronoi_x_fx(const VoronoiParams ¶ms,
|
|||
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 ¶ms,
|
|||
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 ¶ms, const T coord)
|
||||
{
|
||||
|
@ -2375,8 +2378,7 @@ float fractal_voronoi_distance_to_edge(const VoronoiParams ¶ms, 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);
|
||||
|
|
|
@ -999,7 +999,7 @@ void blo_do_versions_270(FileData *fd, Library * /*lib*/, Main *bmain)
|
|||
if (!DNA_struct_elem_find(fd->filesdna, "RenderData", "CurveMapping", "mblur_shutter_curve")) {
|
||||
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
|
||||
CurveMapping *curve_mapping = &scene->r.mblur_shutter_curve;
|
||||
BKE_curvemapping_set_defaults(curve_mapping, 1, 0.0f, 0.0f, 1.0f, 1.0f);
|
||||
BKE_curvemapping_set_defaults(curve_mapping, 1, 0.0f, 0.0f, 1.0f, 1.0f, HD_AUTO);
|
||||
BKE_curvemapping_init(curve_mapping);
|
||||
BKE_curvemap_reset(
|
||||
curve_mapping->cm, &curve_mapping->clipr, CURVE_PRESET_MAX, CURVEMAP_SLOPE_POS_NEG);
|
||||
|
|
|
@ -71,7 +71,7 @@
|
|||
#include "BKE_modifier.h"
|
||||
#include "BKE_node.hh"
|
||||
#include "BKE_screen.h"
|
||||
#include "BKE_simulation_state_serialize.hh"
|
||||
#include "BKE_simulation_state.hh"
|
||||
#include "BKE_workspace.h"
|
||||
|
||||
#include "RNA_access.hh"
|
||||
|
|
|
@ -144,17 +144,16 @@ static void version_bonelayers_to_bonecollections(Main *bmain)
|
|||
if (arm_idprops) {
|
||||
/* See if we can use the layer name from the Bone Manager add-on. This is a popular add-on
|
||||
* for managing bone layers and giving them names. */
|
||||
BLI_snprintf(custom_prop_name, sizeof(custom_prop_name), "layer_name_%u", layer);
|
||||
SNPRINTF(custom_prop_name, "layer_name_%u", layer);
|
||||
IDProperty *prop = IDP_GetPropertyFromGroup(arm_idprops, custom_prop_name);
|
||||
if (prop != nullptr && prop->type == IDP_STRING && IDP_String(prop)[0] != '\0') {
|
||||
BLI_snprintf(
|
||||
bcoll_name, sizeof(bcoll_name), "Layer %u - %s", layer + 1, IDP_String(prop));
|
||||
SNPRINTF(bcoll_name, "Layer %u - %s", layer + 1, IDP_String(prop));
|
||||
}
|
||||
}
|
||||
if (bcoll_name[0] == '\0') {
|
||||
/* Either there was no name defined in the custom property, or
|
||||
* it was the empty string. */
|
||||
BLI_snprintf(bcoll_name, sizeof(bcoll_name), "Layer %u", layer + 1);
|
||||
SNPRINTF(bcoll_name, "Layer %u", layer + 1);
|
||||
}
|
||||
|
||||
/* Create a new bone collection for this layer. */
|
||||
|
@ -984,7 +983,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.
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -24,7 +24,7 @@ float ior_from_f0(float f0)
|
|||
}
|
||||
|
||||
/* Simplified form of F_eta(eta, 1.0). */
|
||||
float f0_from_ior(float eta)
|
||||
float F0_from_ior(float eta)
|
||||
{
|
||||
float A = (eta - 1.0) / (eta + 1.0);
|
||||
return A * A;
|
||||
|
@ -69,7 +69,7 @@ float F_eta(float eta, float cos_theta)
|
|||
/* Fresnel color blend base on fresnel factor */
|
||||
vec3 F_color_blend(float eta, float fresnel, vec3 f0_color)
|
||||
{
|
||||
float f0 = f0_from_ior(eta);
|
||||
float f0 = F0_from_ior(eta);
|
||||
float fac = saturate((fresnel - f0) / (1.0 - f0));
|
||||
return mix(f0_color, vec3(1.0), fac);
|
||||
}
|
||||
|
|
|
@ -95,11 +95,12 @@ float ambient_occlusion_eval(vec3 normal,
|
|||
vec3 safe_normalize(vec3 N);
|
||||
float fast_sqrt(float a);
|
||||
vec3 cameraVec(vec3 P);
|
||||
vec2 btdf_lut(float a, float b, float c);
|
||||
vec2 btdf_lut(float a, float b, float c, float d);
|
||||
vec2 brdf_lut(float a, float b);
|
||||
vec3 F_brdf_multi_scatter(vec3 a, vec3 b, vec2 c);
|
||||
vec3 F_brdf_single_scatter(vec3 a, vec3 b, vec2 c);
|
||||
float F_eta(float a, float b);
|
||||
float F0_from_ior(float a);
|
||||
#endif
|
||||
|
||||
#ifdef VOLUMETRICS
|
||||
|
|
|
@ -74,7 +74,7 @@ vec3 lut_coords_btdf(float cos_theta, float roughness, float ior)
|
|||
}
|
||||
|
||||
/* Returns GGX BTDF in first component and fresnel in second. */
|
||||
vec2 btdf_lut(float cos_theta, float roughness, float ior)
|
||||
vec2 btdf_lut(float cos_theta, float roughness, float ior, float do_multiscatter)
|
||||
{
|
||||
if (ior <= 1e-5) {
|
||||
return vec2(0.0);
|
||||
|
@ -82,17 +82,17 @@ vec2 btdf_lut(float cos_theta, float roughness, float ior)
|
|||
|
||||
if (ior >= 1.0) {
|
||||
vec2 split_sum = brdf_lut(cos_theta, roughness);
|
||||
float f0 = f0_from_ior(ior);
|
||||
/* Baked IOR for GGX BRDF. */
|
||||
const float specular = 1.0;
|
||||
const float eta_brdf = (2.0 / (1.0 - sqrt(0.08 * specular))) - 1.0;
|
||||
/* Avoid harsh transition coming from ior == 1. */
|
||||
float f90 = fast_sqrt(saturate(f0 / (f0_from_ior(eta_brdf) * 0.25)));
|
||||
float fresnel = F_brdf_single_scatter(vec3(f0), vec3(f90), split_sum).r;
|
||||
/* Setting the BTDF to one is not really important since it is only used for multi-scatter
|
||||
* and it's already quite close to ground truth. */
|
||||
float btdf = 1.0;
|
||||
return vec2(btdf, fresnel);
|
||||
float f0 = F0_from_ior(ior);
|
||||
/* Gradually increase `f90` from 0 to 1 when IOR is in the range of [1.0, 1.33], to avoid harsh
|
||||
* transition at `IOR == 1`. */
|
||||
float f90 = fast_sqrt(saturate(f0 / 0.02));
|
||||
|
||||
float brdf = F_brdf_multi_scatter(vec3(f0), vec3(f90), split_sum).r;
|
||||
/* Energy conservation. */
|
||||
float btdf = 1.0 - brdf;
|
||||
/* Assuming the energy loss caused by single-scattering is distributed proportionally in the
|
||||
* reflection and refraction lobes. */
|
||||
return vec2(btdf, brdf) * ((do_multiscatter == 0.0) ? sum(split_sum) : 1.0);
|
||||
}
|
||||
|
||||
vec3 coords = lut_coords_btdf(cos_theta, roughness, ior);
|
||||
|
@ -101,15 +101,21 @@ vec2 btdf_lut(float cos_theta, float roughness, float ior)
|
|||
float layer_floored = floor(layer);
|
||||
|
||||
coords.z = lut_btdf_layer_first + layer_floored;
|
||||
vec2 btdf_low = textureLod(utilTex, coords, 0.0).rg;
|
||||
vec2 btdf_brdf_low = textureLod(utilTex, coords, 0.0).rg;
|
||||
|
||||
coords.z += 1.0;
|
||||
vec2 btdf_high = textureLod(utilTex, coords, 0.0).rg;
|
||||
vec2 btdf_brdf_high = textureLod(utilTex, coords, 0.0).rg;
|
||||
|
||||
/* Manual trilinear interpolation. */
|
||||
vec2 btdf = mix(btdf_low, btdf_high, layer - layer_floored);
|
||||
vec2 btdf_brdf = mix(btdf_brdf_low, btdf_brdf_high, layer - layer_floored);
|
||||
|
||||
return btdf;
|
||||
if (do_multiscatter != 0.0) {
|
||||
/* For energy-conserving BSDF the reflection and refraction lobes should sum to one. Assuming
|
||||
* the energy loss of single-scattering is distributed proportionally in the two lobes. */
|
||||
btdf_brdf /= (btdf_brdf.x + btdf_brdf.y);
|
||||
}
|
||||
|
||||
return btdf_brdf;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -63,7 +63,7 @@ vec4 screen_space_refraction(vec3 vP, vec3 N, vec3 V, float ior, float roughness
|
|||
|
||||
/* Empirical fit for refraction. */
|
||||
/* TODO: find a better fit or precompute inside the LUT. */
|
||||
cone_tan *= 0.5 * fast_sqrt(f0_from_ior((ior < 1.0) ? 1.0 / ior : ior));
|
||||
cone_tan *= 0.5 * fast_sqrt(F0_from_ior((ior < 1.0) ? 1.0 / ior : ior));
|
||||
|
||||
float cone_footprint = hit_dist * cone_tan;
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ void main()
|
|||
}
|
||||
|
||||
/* Stubs */
|
||||
vec2 btdf_lut(float a, float b, float c)
|
||||
vec2 btdf_lut(float a, float b, float c, float d)
|
||||
{
|
||||
return vec2(0.0);
|
||||
}
|
||||
|
|
|
@ -316,7 +316,7 @@ vec2 brdf_lut(float cos_theta, float roughness)
|
|||
#endif
|
||||
}
|
||||
|
||||
vec2 btdf_lut(float cos_theta, float roughness, float ior)
|
||||
vec2 btdf_lut(float cos_theta, float roughness, float ior, float do_multiscatter)
|
||||
{
|
||||
if (ior <= 1e-5) {
|
||||
return vec2(0.0);
|
||||
|
@ -325,16 +325,16 @@ vec2 btdf_lut(float cos_theta, float roughness, float ior)
|
|||
if (ior >= 1.0) {
|
||||
vec2 split_sum = brdf_lut(cos_theta, roughness);
|
||||
float f0 = F0_from_ior(ior);
|
||||
/* Baked IOR for GGX BRDF. */
|
||||
const float specular = 1.0;
|
||||
const float eta_brdf = (2.0 / (1.0 - sqrt(0.08 * specular))) - 1.0;
|
||||
/* Avoid harsh transition coming from ior == 1. */
|
||||
float f90 = fast_sqrt(saturate(f0 / (F0_from_ior(eta_brdf) * 0.25)));
|
||||
float fresnel = F_brdf_single_scatter(vec3(f0), vec3(f90), split_sum).r;
|
||||
/* Setting the BTDF to one is not really important since it is only used for multi-scatter
|
||||
* and it's already quite close to ground truth. */
|
||||
float btdf = 1.0;
|
||||
return vec2(btdf, fresnel);
|
||||
/* Gradually increase `f90` from 0 to 1 when IOR is in the range of [1.0, 1.33], to avoid harsh
|
||||
* transition at `IOR == 1`. */
|
||||
float f90 = fast_sqrt(saturate(f0 / 0.02));
|
||||
|
||||
float brdf = F_brdf_multi_scatter(vec3(f0), vec3(f90), split_sum).r;
|
||||
/* Energy conservation. */
|
||||
float btdf = 1.0 - brdf;
|
||||
/* Assuming the energy loss caused by single-scattering is distributed proportionally in the
|
||||
* reflection and refraction lobes. */
|
||||
return vec2(btdf, brdf) * ((do_multiscatter == 0.0) ? sum(split_sum) : 1.0);
|
||||
}
|
||||
|
||||
/* IOR is sin of critical angle. */
|
||||
|
@ -355,11 +355,18 @@ vec2 btdf_lut(float cos_theta, float roughness, float ior)
|
|||
|
||||
#ifdef EEVEE_UTILITY_TX
|
||||
coords.z = UTIL_BTDF_LAYER + layer_floored;
|
||||
vec2 btdf_low = utility_tx_sample_lut(utility_tx, coords.xy, coords.z).rg;
|
||||
vec2 btdf_high = utility_tx_sample_lut(utility_tx, coords.xy, coords.z + 1.0).rg;
|
||||
vec2 btdf_brdf_low = utility_tx_sample_lut(utility_tx, coords.xy, coords.z).rg;
|
||||
vec2 btdf_brdf_high = utility_tx_sample_lut(utility_tx, coords.xy, coords.z + 1.0).rg;
|
||||
/* Manual trilinear interpolation. */
|
||||
vec2 btdf = mix(btdf_low, btdf_high, layer - layer_floored);
|
||||
return btdf;
|
||||
vec2 btdf_brdf = mix(btdf_brdf_low, btdf_brdf_high, layer - layer_floored);
|
||||
|
||||
if (do_multiscatter != 0.0) {
|
||||
/* For energy-conserving BSDF the reflection and refraction lobes should sum to one. Assuming
|
||||
* the energy loss of single-scattering is distributed proportionally in the two lobes. */
|
||||
btdf_brdf /= (btdf_brdf.x + btdf_brdf.y);
|
||||
}
|
||||
|
||||
return btdf_brdf;
|
||||
#else
|
||||
return vec2(0.0);
|
||||
#endif
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
@ -166,7 +167,7 @@ void ARMATURE_OT_collection_move(wmOperatorType *ot)
|
|||
static const EnumPropertyItem bcoll_slot_move[] = {
|
||||
{-1, "UP", 0, "Up", ""},
|
||||
{1, "DOWN", 0, "Down", ""},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
{0, nullptr, 0, nullptr, nullptr},
|
||||
};
|
||||
|
||||
/* identifiers */
|
||||
|
@ -371,7 +372,7 @@ void ARMATURE_OT_collection_assign(wmOperatorType *ot)
|
|||
/* properties */
|
||||
RNA_def_string(ot->srna,
|
||||
"name",
|
||||
NULL,
|
||||
nullptr,
|
||||
MAX_NAME,
|
||||
"Bone Collection",
|
||||
"Name of the bone collection to assign this bone to; empty to assign to the "
|
||||
|
@ -432,7 +433,7 @@ void ARMATURE_OT_collection_unassign(wmOperatorType *ot)
|
|||
|
||||
RNA_def_string(ot->srna,
|
||||
"name",
|
||||
NULL,
|
||||
nullptr,
|
||||
MAX_NAME,
|
||||
"Bone Collection",
|
||||
"Name of the bone collection to unassign this bone from; empty to unassign from "
|
||||
|
@ -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);
|
||||
|
@ -537,7 +537,7 @@ void ARMATURE_OT_collection_select(wmOperatorType *ot)
|
|||
PropertyRNA *prop = RNA_def_string(
|
||||
ot->srna,
|
||||
"name",
|
||||
NULL,
|
||||
nullptr,
|
||||
MAX_NAME,
|
||||
"Bone Collection",
|
||||
"Name of the bone collection to select bones from; empty use the active bone collection");
|
||||
|
@ -577,7 +577,7 @@ void ARMATURE_OT_collection_deselect(wmOperatorType *ot)
|
|||
PropertyRNA *prop = RNA_def_string(
|
||||
ot->srna,
|
||||
"name",
|
||||
NULL,
|
||||
nullptr,
|
||||
MAX_NAME,
|
||||
"Bone Collection",
|
||||
"Name of the bone collection to deselect bones from; empty use the active bone collection");
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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(
|
||||
|
@ -11053,10 +11051,10 @@ static int ui_pie_handler(bContext *C, const wmEvent *event, uiPopupBlockHandle
|
|||
if (menu->scrolltimer == nullptr) {
|
||||
menu->scrolltimer = WM_event_timer_add(
|
||||
CTX_wm_manager(C), CTX_wm_window(C), TIMER, PIE_MENU_INTERVAL);
|
||||
menu->scrolltimer->duration = 0.0;
|
||||
menu->scrolltimer->time_duration = 0.0;
|
||||
}
|
||||
|
||||
const double duration = menu->scrolltimer->duration;
|
||||
const double duration = menu->scrolltimer->time_duration;
|
||||
|
||||
float event_xy[2] = {float(event->xy[0]), float(event->xy[1])};
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue