WIP: Brush assets project #106303
|
@ -870,19 +870,29 @@ else()
|
|||
endif()
|
||||
|
||||
# Vulkan
|
||||
if(NOT APPLE)
|
||||
option(WITH_VULKAN_BACKEND "Enable Vulkan as graphics backend (experimental)" ON)
|
||||
option(WITH_VULKAN_GUARDEDALLOC "\
|
||||
Use guardedalloc for host allocations done inside Vulkan (development option)"
|
||||
OFF
|
||||
)
|
||||
option(WITH_VULKAN_BACKEND "Enable Vulkan as graphics backend (experimental)" ON)
|
||||
option(WITH_VULKAN_GUARDEDALLOC "Use guardedalloc for host allocations done inside Vulkan (development option)"
|
||||
OFF
|
||||
)
|
||||
mark_as_advanced(
|
||||
WITH_VULKAN_BACKEND
|
||||
WITH_VULKAN_GUARDEDALLOC
|
||||
)
|
||||
if(APPLE)
|
||||
option(WITH_VULKAN_MOLTENVK "Enable Vulkan over MoltenVK (development option)" OFF)
|
||||
mark_as_advanced(
|
||||
WITH_VULKAN_BACKEND
|
||||
WITH_VULKAN_GUARDEDALLOC
|
||||
WITH_VULKAN_MOLTENVK
|
||||
)
|
||||
if(NOT WITH_EXPERIMENTAL_FEATURES)
|
||||
set(WITH_VULKAN_BACKEND OFF)
|
||||
endif()
|
||||
|
||||
if(APPLE AND NOT WITH_VULKAN_MOLTENVK)
|
||||
set(WITH_VULKAN_BACKEND OFF)
|
||||
endif()
|
||||
if(NOT WITH_EXPERIMENTAL_FEATURES)
|
||||
if (APPLE)
|
||||
set(WITH_VULKAN_MOLTENVK OFF)
|
||||
endif()
|
||||
set(WITH_VULKAN_BACKEND OFF)
|
||||
endif()
|
||||
|
||||
# Metal
|
||||
|
|
|
@ -43,11 +43,11 @@ find_path(MOLTENVK_INCLUDE_DIR
|
|||
|
||||
find_library(MOLTENVK_LIBRARY
|
||||
NAMES
|
||||
MoltenVK
|
||||
libMoltenVK.dylib
|
||||
HINTS
|
||||
${_moltenvk_SEARCH_DIRS}
|
||||
PATH_SUFFIXES
|
||||
dylib/macOS
|
||||
dynamic/dylib/macOS
|
||||
)
|
||||
|
||||
# handle the QUIETLY and REQUIRED arguments and set MOLTENVK_FOUND to TRUE if
|
||||
|
|
|
@ -108,6 +108,12 @@ if(WITH_OPENSUBDIV)
|
|||
endif()
|
||||
add_bundled_libraries(opensubdiv/lib)
|
||||
|
||||
if(WITH_VULKAN_BACKEND)
|
||||
find_package(MoltenVK REQUIRED)
|
||||
find_package(ShaderC REQUIRED)
|
||||
find_package(Vulkan REQUIRED)
|
||||
endif()
|
||||
|
||||
if(WITH_CODEC_SNDFILE)
|
||||
find_package(SndFile)
|
||||
find_library(_sndfile_FLAC_LIBRARY NAMES flac HINTS ${LIBDIR}/sndfile/lib)
|
||||
|
|
|
@ -945,7 +945,9 @@ ccl_device_forceinline bool integrate_volume_phase_scatter(
|
|||
INTEGRATOR_STATE_WRITE(state, ray, D) = normalize(phase_wo);
|
||||
INTEGRATOR_STATE_WRITE(state, ray, tmin) = 0.0f;
|
||||
# ifdef __LIGHT_TREE__
|
||||
INTEGRATOR_STATE_WRITE(state, ray, previous_dt) = ray->tmax - ray->tmin;
|
||||
if (kernel_data.integrator.use_light_tree) {
|
||||
INTEGRATOR_STATE_WRITE(state, ray, previous_dt) = ray->tmax - ray->tmin;
|
||||
}
|
||||
# endif
|
||||
INTEGRATOR_STATE_WRITE(state, ray, tmax) = FLT_MAX;
|
||||
# ifdef __RAY_DIFFERENTIALS__
|
||||
|
|
|
@ -75,9 +75,7 @@ KERNEL_STRUCT_MEMBER(ray, float, tmax, KERNEL_FEATURE_PATH_TRACING)
|
|||
KERNEL_STRUCT_MEMBER(ray, float, time, KERNEL_FEATURE_PATH_TRACING)
|
||||
KERNEL_STRUCT_MEMBER(ray, float, dP, KERNEL_FEATURE_PATH_TRACING)
|
||||
KERNEL_STRUCT_MEMBER(ray, float, dD, KERNEL_FEATURE_PATH_TRACING)
|
||||
#ifdef __LIGHT_TREE__
|
||||
KERNEL_STRUCT_MEMBER(ray, float, previous_dt, KERNEL_FEATURE_PATH_TRACING)
|
||||
#endif
|
||||
KERNEL_STRUCT_MEMBER(ray, float, previous_dt, KERNEL_FEATURE_LIGHT_TREE)
|
||||
KERNEL_STRUCT_END(ray)
|
||||
|
||||
/*************************** Intersection result ******************************/
|
||||
|
|
|
@ -1748,6 +1748,9 @@ enum KernelFeatureFlag : uint32_t {
|
|||
|
||||
/* Use denoising kernels and output denoising passes. */
|
||||
KERNEL_FEATURE_DENOISING = (1U << 29U),
|
||||
|
||||
/* Light tree. */
|
||||
KERNEL_FEATURE_LIGHT_TREE = (1U << 30U),
|
||||
};
|
||||
|
||||
/* Shader node feature mask, to specialize shader evaluation for kernels. */
|
||||
|
|
|
@ -345,6 +345,10 @@ uint Integrator::get_kernel_features() const
|
|||
kernel_features |= KERNEL_FEATURE_AO_ADDITIVE;
|
||||
}
|
||||
|
||||
if (get_use_light_tree()) {
|
||||
kernel_features |= KERNEL_FEATURE_LIGHT_TREE;
|
||||
}
|
||||
|
||||
return kernel_features;
|
||||
}
|
||||
|
||||
|
|
|
@ -32,10 +32,6 @@
|
|||
|
||||
#include <sys/stat.h>
|
||||
|
||||
/* Set to 0 to allow devices that do not have the required features.
|
||||
* This allows development on OSX until we really needs these features. */
|
||||
#define STRICT_REQUIREMENTS true
|
||||
|
||||
/*
|
||||
* Should we only select surfaces that are known to be compatible. Or should we in case no
|
||||
* compatible surfaces have been found select the first one.
|
||||
|
@ -226,14 +222,15 @@ class GHOST_DeviceVK {
|
|||
queue_create_infos.push_back(graphic_queue_create_info);
|
||||
|
||||
VkPhysicalDeviceFeatures device_features = {};
|
||||
#if STRICT_REQUIREMENTS
|
||||
#ifndef __APPLE__
|
||||
device_features.geometryShader = VK_TRUE;
|
||||
device_features.dualSrcBlend = VK_TRUE;
|
||||
/* MoltenVK supports logicOp, needs to be build with MVK_USE_METAL_PRIVATE_API. */
|
||||
device_features.logicOp = VK_TRUE;
|
||||
#endif
|
||||
device_features.dualSrcBlend = VK_TRUE;
|
||||
device_features.imageCubeArray = VK_TRUE;
|
||||
device_features.multiViewport = VK_TRUE;
|
||||
device_features.shaderClipDistance = VK_TRUE;
|
||||
#endif
|
||||
device_features.drawIndirectFirstInstance = VK_TRUE;
|
||||
device_features.fragmentStoresAndAtomics = VK_TRUE;
|
||||
device_features.samplerAnisotropy = features.features.samplerAnisotropy;
|
||||
|
@ -355,7 +352,11 @@ static GHOST_TSuccess ensure_vulkan_device(VkInstance vk_instance,
|
|||
}
|
||||
}
|
||||
|
||||
#if STRICT_REQUIREMENTS
|
||||
#ifdef __APPLE__
|
||||
if (!device_vk.features.features.dualSrcBlend || !device_vk.features.features.imageCubeArray) {
|
||||
continue;
|
||||
}
|
||||
#else
|
||||
if (!device_vk.features.features.geometryShader || !device_vk.features.features.dualSrcBlend ||
|
||||
!device_vk.features.features.logicOp || !device_vk.features.features.imageCubeArray)
|
||||
{
|
||||
|
@ -1000,8 +1001,7 @@ GHOST_TSuccess GHOST_ContextVK::initializeDrawingContext()
|
|||
|
||||
if (use_window_surface) {
|
||||
const char *native_surface_extension_name = getPlatformSpecificSurfaceExtension();
|
||||
|
||||
requireExtension(extensions_available, extensions_enabled, "VK_KHR_surface");
|
||||
requireExtension(extensions_available, extensions_enabled, VK_KHR_SURFACE_EXTENSION_NAME);
|
||||
requireExtension(extensions_available, extensions_enabled, native_surface_extension_name);
|
||||
|
||||
extensions_device.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
|
||||
|
@ -1010,10 +1010,13 @@ GHOST_TSuccess GHOST_ContextVK::initializeDrawingContext()
|
|||
extensions_device.push_back(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME);
|
||||
|
||||
/* Enable MoltenVK required instance extensions. */
|
||||
#ifdef VK_MVK_MOLTENVK_EXTENSION_NAME
|
||||
#ifdef __APPLE__
|
||||
requireExtension(
|
||||
extensions_available, extensions_enabled, "VK_KHR_get_physical_device_properties2");
|
||||
extensions_available, extensions_enabled, VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME);
|
||||
#endif
|
||||
requireExtension(extensions_available,
|
||||
extensions_enabled,
|
||||
VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
|
||||
|
||||
VkInstance instance = VK_NULL_HANDLE;
|
||||
if (!vulkan_device.has_value()) {
|
||||
|
@ -1046,6 +1049,10 @@ GHOST_TSuccess GHOST_ContextVK::initializeDrawingContext()
|
|||
create_info.pNext = &validationFeatures;
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
create_info.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
|
||||
#endif
|
||||
|
||||
VK_CHECK(vkCreateInstance(&create_info, nullptr, &instance));
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -56,12 +56,11 @@ size_t malloc_usable_size(void *ptr);
|
|||
#endif
|
||||
|
||||
#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__OpenBSD__)
|
||||
// Needed for memalign on Linux and _aligned_alloc on Windows.
|
||||
/* Needed for `memalign` on Linux and _aligned_alloc on Windows. */
|
||||
|
||||
# include <malloc.h>
|
||||
#else
|
||||
// Apple's malloc is 16-byte aligned, and does not have malloc.h, so include
|
||||
// stdilb instead.
|
||||
/* Apple's malloc is 16-byte aligned, and does not have malloc.h, so include stdilb instead. */
|
||||
# include <stdlib.h>
|
||||
#endif
|
||||
|
||||
|
|
|
@ -76,7 +76,7 @@ the model.
|
|||
* \ingroup intern_sky_modal
|
||||
*/
|
||||
|
||||
// Uses Sep 9 pattern / Aug 23 mean dataset
|
||||
/* Uses Sep 9 pattern / Aug 23 mean dataset. */
|
||||
|
||||
static const double datasetXYZ1[] = {
|
||||
// albedo 0, turbidity 1
|
||||
|
|
|
@ -773,7 +773,7 @@ const bTheme U_theme_default = {
|
|||
.sub_back = RGBA(0x0000001f),
|
||||
},
|
||||
.shade2 = RGBA(0x4d4d4de6),
|
||||
.hilite = RGBA(0x65a2ffff),
|
||||
.hilite = RGBA(0x71a8ffff),
|
||||
.grid = RGBA(0x1d1d1dff),
|
||||
.vertex_size = 3,
|
||||
.outline_width = 1,
|
||||
|
@ -941,7 +941,7 @@ const bTheme U_theme_default = {
|
|||
.console_input = RGBA(0xf2f2f2ff),
|
||||
.console_info = RGBA(0x95d600ff),
|
||||
.console_error = RGBA(0xff4d84ff),
|
||||
.console_cursor = RGBA(0xff0000ff),
|
||||
.console_cursor = RGBA(0x71a8ffff),
|
||||
.console_select = RGBA(0xffffff30),
|
||||
.vertex_size = 3,
|
||||
.outline_width = 1,
|
||||
|
|
|
@ -78,7 +78,7 @@ Comment[wa]=Modelaedje 3D, animåcion, rindou eyet après-produccion
|
|||
Comment[zh_HK]=3D 模型、動畫、算圖和後製
|
||||
Comment[zh_CN]=3D 建模、动画、渲染和后期制作
|
||||
Comment[zh_TW]=3D 模型、動畫、算圖和後製
|
||||
Keywords=3d;cg;modeling;animation;painting;sculpting;texturing;video editing;video tracking;rendering;render engine;cycles;game engine;python;
|
||||
Keywords=3d;cg;modeling;animation;painting;sculpting;texturing;video editing;video tracking;rendering;render engine;cycles;python;
|
||||
Exec=blender %f
|
||||
Icon=blender
|
||||
Terminal=false
|
||||
|
|
|
@ -369,7 +369,6 @@
|
|||
speaker="#000000"
|
||||
vertex="#000000"
|
||||
vertex_select="#ff7a00"
|
||||
vertex_active="#000000"
|
||||
vertex_size="3"
|
||||
vertex_bevel="#00a5ff"
|
||||
vertex_unreferenced="#000000"
|
||||
|
@ -735,7 +734,6 @@
|
|||
grid="#353535ff"
|
||||
vertex="#000000"
|
||||
vertex_select="#ff8500"
|
||||
vertex_active="#000000"
|
||||
vertex_size="3"
|
||||
vertex_bevel="#000000"
|
||||
vertex_unreferenced="#000000"
|
||||
|
@ -1168,7 +1166,7 @@
|
|||
line_input="#f2f2f2"
|
||||
line_info="#95d600"
|
||||
line_error="#ff4d84"
|
||||
cursor="#ff0000"
|
||||
cursor="#71a8ff"
|
||||
select="#ffffff30"
|
||||
>
|
||||
<space>
|
||||
|
|
|
@ -3656,7 +3656,7 @@ def km_animation_channels(params):
|
|||
# ------------------------------------------------------------------------------
|
||||
# Object Grease Pencil Modes
|
||||
|
||||
def km_grease_pencil(params):
|
||||
def km_gpencil_legacy(params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil",
|
||||
|
@ -3694,7 +3694,7 @@ def km_grease_pencil(params):
|
|||
return keymap
|
||||
|
||||
|
||||
def _grease_pencil_selection(params, *, alt_select=False):
|
||||
def _gpencil_legacy_selection(params, *, alt_select=False):
|
||||
return [
|
||||
# Select all
|
||||
*_template_items_select_actions(params, "gpencil.select_all"),
|
||||
|
@ -3727,7 +3727,7 @@ def _grease_pencil_selection(params, *, alt_select=False):
|
|||
]
|
||||
|
||||
|
||||
def _grease_pencil_display():
|
||||
def _gpencil_legacy_display():
|
||||
return [
|
||||
("wm.context_toggle", {"type": 'Q', "value": 'PRESS', "shift": True},
|
||||
{"properties": [("data_path", 'space_data.overlay.use_gpencil_edit_lines')]}),
|
||||
|
@ -3736,7 +3736,7 @@ def _grease_pencil_display():
|
|||
]
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_edit_mode(params):
|
||||
def km_gpencil_legacy_stroke_edit_mode(params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Edit Mode",
|
||||
|
@ -3751,7 +3751,7 @@ def km_grease_pencil_stroke_edit_mode(params):
|
|||
(op_tool_cycle, "builtin.interpolate"), params),
|
||||
("gpencil.interpolate_sequence", {"type": 'E', "value": 'PRESS', "shift": True, "ctrl": True}, None),
|
||||
# Selection
|
||||
*_grease_pencil_selection(params),
|
||||
*_gpencil_legacy_selection(params),
|
||||
("gpencil.select_lasso", {"type": params.action_mouse, "value": 'CLICK_DRAG', "ctrl": True},
|
||||
{"properties": [("mode", 'ADD')]}),
|
||||
("gpencil.select_lasso", {"type": params.action_mouse, "value": 'CLICK_DRAG', "shift": True, "ctrl": True},
|
||||
|
@ -3795,7 +3795,7 @@ def km_grease_pencil_stroke_edit_mode(params):
|
|||
*_template_items_hide_reveal_actions("gpencil.hide", "gpencil.reveal"),
|
||||
("gpencil.selection_opacity_toggle", {"type": 'H', "value": 'PRESS', "ctrl": True}, None),
|
||||
# Display
|
||||
*_grease_pencil_display(),
|
||||
*_gpencil_legacy_display(),
|
||||
# Isolate layer
|
||||
("gpencil.layer_isolate", {"type": 'NUMPAD_ASTERIX', "value": 'PRESS'}, None),
|
||||
# Move to layer
|
||||
|
@ -3843,7 +3843,7 @@ def km_grease_pencil_stroke_edit_mode(params):
|
|||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_curve_edit_mode(_params):
|
||||
def km_gpencil_legacy_stroke_curve_edit_mode(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Curve Edit Mode",
|
||||
|
@ -3859,7 +3859,7 @@ def km_grease_pencil_stroke_curve_edit_mode(_params):
|
|||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_paint_mode(params):
|
||||
def km_gpencil_legacy_stroke_paint_mode(params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Paint Mode",
|
||||
|
@ -3911,7 +3911,7 @@ def km_grease_pencil_stroke_paint_mode(params):
|
|||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_paint_draw_brush(params):
|
||||
def km_gpencil_legacy_stroke_paint_draw_brush(params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Paint (Draw brush)",
|
||||
|
@ -3944,7 +3944,7 @@ def km_grease_pencil_stroke_paint_draw_brush(params):
|
|||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_paint_erase(_params):
|
||||
def km_gpencil_legacy_stroke_paint_erase(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Paint (Erase)",
|
||||
|
@ -3963,7 +3963,7 @@ def km_grease_pencil_stroke_paint_erase(_params):
|
|||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_paint_fill(_params):
|
||||
def km_gpencil_legacy_stroke_paint_fill(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Paint (Fill)",
|
||||
|
@ -3999,7 +3999,7 @@ def km_grease_pencil_stroke_paint_fill(_params):
|
|||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_paint_tint(_params):
|
||||
def km_gpencil_legacy_stroke_paint_tint(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Paint (Tint)",
|
||||
|
@ -4018,7 +4018,7 @@ def km_grease_pencil_stroke_paint_tint(_params):
|
|||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_sculpt_mode(params):
|
||||
def km_gpencil_legacy_stroke_sculpt_mode(params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Sculpt Mode",
|
||||
|
@ -4028,7 +4028,7 @@ def km_grease_pencil_stroke_sculpt_mode(params):
|
|||
|
||||
items.extend([
|
||||
# Selection
|
||||
*_grease_pencil_selection(params, alt_select=True),
|
||||
*_gpencil_legacy_selection(params, alt_select=True),
|
||||
*_template_items_select_lasso(params, "gpencil.select_lasso"),
|
||||
# Selection mode
|
||||
("wm.context_toggle", {"type": 'ONE', "value": 'PRESS'},
|
||||
|
@ -4051,7 +4051,7 @@ def km_grease_pencil_stroke_sculpt_mode(params):
|
|||
# Copy
|
||||
("gpencil.copy", {"type": 'C', "value": 'PRESS', "ctrl": True}, None),
|
||||
# Display
|
||||
*_grease_pencil_display(),
|
||||
*_gpencil_legacy_display(),
|
||||
# Active layer
|
||||
op_menu("GPENCIL_MT_layer_active", {"type": 'Y', "value": 'PRESS'}),
|
||||
# Active material
|
||||
|
@ -4077,7 +4077,7 @@ def km_grease_pencil_stroke_sculpt_mode(params):
|
|||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_sculpt_smooth(_params):
|
||||
def km_gpencil_legacy_stroke_sculpt_smooth(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Sculpt (Smooth)",
|
||||
|
@ -4097,7 +4097,7 @@ def km_grease_pencil_stroke_sculpt_smooth(_params):
|
|||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_sculpt_thickness(_params):
|
||||
def km_gpencil_legacy_stroke_sculpt_thickness(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Sculpt (Thickness)",
|
||||
|
@ -4117,7 +4117,7 @@ def km_grease_pencil_stroke_sculpt_thickness(_params):
|
|||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_sculpt_strength(_params):
|
||||
def km_gpencil_legacy_stroke_sculpt_strength(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Sculpt (Strength)",
|
||||
|
@ -4137,7 +4137,7 @@ def km_grease_pencil_stroke_sculpt_strength(_params):
|
|||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_sculpt_grab(_params):
|
||||
def km_gpencil_legacy_stroke_sculpt_grab(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Sculpt (Grab)",
|
||||
|
@ -4157,7 +4157,7 @@ def km_grease_pencil_stroke_sculpt_grab(_params):
|
|||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_sculpt_push(_params):
|
||||
def km_gpencil_legacy_stroke_sculpt_push(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Sculpt (Push)",
|
||||
|
@ -4177,7 +4177,7 @@ def km_grease_pencil_stroke_sculpt_push(_params):
|
|||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_sculpt_twist(_params):
|
||||
def km_gpencil_legacy_stroke_sculpt_twist(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Sculpt (Twist)",
|
||||
|
@ -4197,7 +4197,7 @@ def km_grease_pencil_stroke_sculpt_twist(_params):
|
|||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_sculpt_pinch(_params):
|
||||
def km_gpencil_legacy_stroke_sculpt_pinch(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Sculpt (Pinch)",
|
||||
|
@ -4217,7 +4217,7 @@ def km_grease_pencil_stroke_sculpt_pinch(_params):
|
|||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_sculpt_randomize(_params):
|
||||
def km_gpencil_legacy_stroke_sculpt_randomize(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Sculpt (Randomize)",
|
||||
|
@ -4237,7 +4237,7 @@ def km_grease_pencil_stroke_sculpt_randomize(_params):
|
|||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_sculpt_clone(_params):
|
||||
def km_gpencil_legacy_stroke_sculpt_clone(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Sculpt (Clone)",
|
||||
|
@ -4257,7 +4257,7 @@ def km_grease_pencil_stroke_sculpt_clone(_params):
|
|||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_weight_mode(params):
|
||||
def km_gpencil_legacy_stroke_weight_mode(params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Weight Mode",
|
||||
|
@ -4281,7 +4281,7 @@ def km_grease_pencil_stroke_weight_mode(params):
|
|||
("brush.scale_size", {"type": 'RIGHT_BRACKET', "value": 'PRESS', "repeat": True},
|
||||
{"properties": [("scalar", 1.0 / 0.9)]}),
|
||||
# Display
|
||||
*_grease_pencil_display(),
|
||||
*_gpencil_legacy_display(),
|
||||
# Active layer
|
||||
op_menu("GPENCIL_MT_layer_active", {"type": 'Y', "value": 'PRESS'}),
|
||||
# Merge Layer
|
||||
|
@ -4310,7 +4310,7 @@ def km_grease_pencil_stroke_weight_mode(params):
|
|||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_weight_draw(_params):
|
||||
def km_gpencil_legacy_stroke_weight_draw(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Weight (Draw)",
|
||||
|
@ -4327,7 +4327,7 @@ def km_grease_pencil_stroke_weight_draw(_params):
|
|||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_weight_blur(_params):
|
||||
def km_gpencil_legacy_stroke_weight_blur(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Weight (Blur)",
|
||||
|
@ -4344,7 +4344,7 @@ def km_grease_pencil_stroke_weight_blur(_params):
|
|||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_weight_average(_params):
|
||||
def km_gpencil_legacy_stroke_weight_average(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Weight (Average)",
|
||||
|
@ -4361,7 +4361,7 @@ def km_grease_pencil_stroke_weight_average(_params):
|
|||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_weight_smear(_params):
|
||||
def km_gpencil_legacy_stroke_weight_smear(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Weight (Smear)",
|
||||
|
@ -4378,7 +4378,7 @@ def km_grease_pencil_stroke_weight_smear(_params):
|
|||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_vertex_mode(params):
|
||||
def km_gpencil_legacy_stroke_vertex_mode(params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Vertex Mode",
|
||||
|
@ -4388,7 +4388,7 @@ def km_grease_pencil_stroke_vertex_mode(params):
|
|||
|
||||
items.extend([
|
||||
# Selection
|
||||
*_grease_pencil_selection(params, alt_select=True),
|
||||
*_gpencil_legacy_selection(params, alt_select=True),
|
||||
*_template_items_select_lasso(params, "gpencil.select_lasso"),
|
||||
# Selection mode
|
||||
("wm.context_toggle", {"type": 'ONE', "value": 'PRESS'},
|
||||
|
@ -4413,7 +4413,7 @@ def km_grease_pencil_stroke_vertex_mode(params):
|
|||
# Color Flip
|
||||
("gpencil.tint_flip", {"type": 'X', "value": 'PRESS'}, None),
|
||||
# Display
|
||||
*_grease_pencil_display(),
|
||||
*_gpencil_legacy_display(),
|
||||
# Active layer
|
||||
op_menu("GPENCIL_MT_layer_active", {"type": 'Y', "value": 'PRESS'}),
|
||||
# Merge Layer
|
||||
|
@ -4433,7 +4433,7 @@ def km_grease_pencil_stroke_vertex_mode(params):
|
|||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_vertex_draw(_params):
|
||||
def km_gpencil_legacy_stroke_vertex_draw(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Vertex (Draw)",
|
||||
|
@ -4460,7 +4460,7 @@ def km_grease_pencil_stroke_vertex_draw(_params):
|
|||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_vertex_blur(_params):
|
||||
def km_gpencil_legacy_stroke_vertex_blur(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Vertex (Blur)",
|
||||
|
@ -4485,7 +4485,7 @@ def km_grease_pencil_stroke_vertex_blur(_params):
|
|||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_vertex_average(_params):
|
||||
def km_gpencil_legacy_stroke_vertex_average(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Vertex (Average)",
|
||||
|
@ -4512,7 +4512,7 @@ def km_grease_pencil_stroke_vertex_average(_params):
|
|||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_vertex_smear(_params):
|
||||
def km_gpencil_legacy_stroke_vertex_smear(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Vertex (Smear)",
|
||||
|
@ -4537,7 +4537,7 @@ def km_grease_pencil_stroke_vertex_smear(_params):
|
|||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_vertex_replace(_params):
|
||||
def km_gpencil_legacy_stroke_vertex_replace(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Vertex (Replace)",
|
||||
|
@ -4680,6 +4680,25 @@ def km_grease_pencil_edit_mode(params):
|
|||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_sculpt_mode(params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Sculpt Mode",
|
||||
{"space_type": 'EMPTY', "region_type": 'WINDOW'},
|
||||
{"items": items}
|
||||
)
|
||||
|
||||
items.extend([
|
||||
("brush.scale_size", {"type": 'LEFT_BRACKET', "value": 'PRESS', "repeat": True},
|
||||
{"properties": [("scalar", 0.9)]}),
|
||||
("brush.scale_size", {"type": 'RIGHT_BRACKET', "value": 'PRESS', "repeat": True},
|
||||
{"properties": [("scalar", 1.0 / 0.9)]}),
|
||||
*_template_paint_radial_control("gpencil_sculpt_paint"),
|
||||
])
|
||||
|
||||
return keymap
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Object/Pose Modes
|
||||
|
||||
|
@ -8609,38 +8628,40 @@ def generate_keymaps(params=None):
|
|||
km_animation_channels(params),
|
||||
|
||||
# Modes.
|
||||
km_grease_pencil(params), # TODO: Rename to km_annotate
|
||||
km_grease_pencil_stroke_curve_edit_mode(params),
|
||||
km_grease_pencil_stroke_edit_mode(params),
|
||||
km_grease_pencil_stroke_paint_mode(params),
|
||||
km_grease_pencil_stroke_paint_draw_brush(params),
|
||||
km_grease_pencil_stroke_paint_erase(params),
|
||||
km_grease_pencil_stroke_paint_fill(params),
|
||||
km_grease_pencil_stroke_paint_tint(params),
|
||||
km_grease_pencil_stroke_sculpt_mode(params),
|
||||
km_grease_pencil_stroke_sculpt_smooth(params),
|
||||
km_grease_pencil_stroke_sculpt_thickness(params),
|
||||
km_grease_pencil_stroke_sculpt_strength(params),
|
||||
km_grease_pencil_stroke_sculpt_grab(params),
|
||||
km_grease_pencil_stroke_sculpt_push(params),
|
||||
km_grease_pencil_stroke_sculpt_twist(params),
|
||||
km_grease_pencil_stroke_sculpt_pinch(params),
|
||||
km_grease_pencil_stroke_sculpt_randomize(params),
|
||||
km_grease_pencil_stroke_sculpt_clone(params),
|
||||
km_grease_pencil_stroke_weight_mode(params),
|
||||
km_grease_pencil_stroke_weight_draw(params),
|
||||
km_grease_pencil_stroke_weight_blur(params),
|
||||
km_grease_pencil_stroke_weight_average(params),
|
||||
km_grease_pencil_stroke_weight_smear(params),
|
||||
km_grease_pencil_stroke_vertex_mode(params),
|
||||
km_grease_pencil_stroke_vertex_draw(params),
|
||||
km_grease_pencil_stroke_vertex_blur(params),
|
||||
km_grease_pencil_stroke_vertex_average(params),
|
||||
km_grease_pencil_stroke_vertex_smear(params),
|
||||
km_grease_pencil_stroke_vertex_replace(params),
|
||||
# Grease Pencil v2
|
||||
km_gpencil_legacy(params), # TODO: Rename to km_annotate
|
||||
km_gpencil_legacy_stroke_curve_edit_mode(params),
|
||||
km_gpencil_legacy_stroke_edit_mode(params),
|
||||
km_gpencil_legacy_stroke_paint_mode(params),
|
||||
km_gpencil_legacy_stroke_paint_draw_brush(params),
|
||||
km_gpencil_legacy_stroke_paint_erase(params),
|
||||
km_gpencil_legacy_stroke_paint_fill(params),
|
||||
km_gpencil_legacy_stroke_paint_tint(params),
|
||||
km_gpencil_legacy_stroke_sculpt_mode(params),
|
||||
km_gpencil_legacy_stroke_sculpt_smooth(params),
|
||||
km_gpencil_legacy_stroke_sculpt_thickness(params),
|
||||
km_gpencil_legacy_stroke_sculpt_strength(params),
|
||||
km_gpencil_legacy_stroke_sculpt_grab(params),
|
||||
km_gpencil_legacy_stroke_sculpt_push(params),
|
||||
km_gpencil_legacy_stroke_sculpt_twist(params),
|
||||
km_gpencil_legacy_stroke_sculpt_pinch(params),
|
||||
km_gpencil_legacy_stroke_sculpt_randomize(params),
|
||||
km_gpencil_legacy_stroke_sculpt_clone(params),
|
||||
km_gpencil_legacy_stroke_weight_mode(params),
|
||||
km_gpencil_legacy_stroke_weight_draw(params),
|
||||
km_gpencil_legacy_stroke_weight_blur(params),
|
||||
km_gpencil_legacy_stroke_weight_average(params),
|
||||
km_gpencil_legacy_stroke_weight_smear(params),
|
||||
km_gpencil_legacy_stroke_vertex_mode(params),
|
||||
km_gpencil_legacy_stroke_vertex_draw(params),
|
||||
km_gpencil_legacy_stroke_vertex_blur(params),
|
||||
km_gpencil_legacy_stroke_vertex_average(params),
|
||||
km_gpencil_legacy_stroke_vertex_smear(params),
|
||||
km_gpencil_legacy_stroke_vertex_replace(params),
|
||||
# Grease Pencil v3
|
||||
km_grease_pencil_paint_mode(params),
|
||||
km_grease_pencil_edit_mode(params),
|
||||
km_grease_pencil_sculpt_mode(params),
|
||||
# Object mode.
|
||||
km_object_mode(params),
|
||||
km_object_non_modal(params),
|
||||
|
|
|
@ -2341,7 +2341,7 @@ def km_animation_channels(params):
|
|||
# Modes
|
||||
|
||||
|
||||
def km_grease_pencil(_params):
|
||||
def km_gpencil_legacy(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil",
|
||||
|
@ -2352,7 +2352,7 @@ def km_grease_pencil(_params):
|
|||
return keymap
|
||||
|
||||
|
||||
def _grease_pencil_selection(params):
|
||||
def _gpencil_legacy_selection(params):
|
||||
return [
|
||||
# Select all
|
||||
("gpencil.select_all", {"type": 'A', "value": 'PRESS', "ctrl": True}, {"properties": [("action", 'SELECT')]}),
|
||||
|
@ -2369,7 +2369,7 @@ def _grease_pencil_selection(params):
|
|||
]
|
||||
|
||||
|
||||
def _grease_pencil_display():
|
||||
def _gpencil_legacy_display():
|
||||
return [
|
||||
("wm.context_toggle", {"type": 'Q', "value": 'PRESS', "shift": True},
|
||||
{"properties": [("data_path", 'space_data.overlay.use_gpencil_edit_lines')]}),
|
||||
|
@ -2378,7 +2378,7 @@ def _grease_pencil_display():
|
|||
]
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_edit_mode(params):
|
||||
def km_gpencil_legacy_stroke_edit_mode(params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Edit Mode",
|
||||
|
@ -2393,7 +2393,7 @@ def km_grease_pencil_stroke_edit_mode(params):
|
|||
("gpencil.select", {"type": 'LEFTMOUSE', "value": 'CLICK', "shift": True},
|
||||
{"properties": [("extend", True), ("toggle", True)]}),
|
||||
# Selection
|
||||
*_grease_pencil_selection(params),
|
||||
*_gpencil_legacy_selection(params),
|
||||
("gpencil.select_all", {"type": 'A', "value": 'PRESS', "ctrl": True}, {"properties": [("action", 'SELECT')]}),
|
||||
# Duplicate and move selected points
|
||||
("gpencil.duplicate_move", {"type": 'D', "value": 'PRESS', "ctrl": True}, None),
|
||||
|
@ -2453,7 +2453,7 @@ def km_grease_pencil_stroke_edit_mode(params):
|
|||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_paint_mode(params):
|
||||
def km_gpencil_legacy_stroke_paint_mode(params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Paint Mode",
|
||||
|
@ -2509,7 +2509,7 @@ def km_grease_pencil_stroke_paint_mode(params):
|
|||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_paint_draw_brush(params):
|
||||
def km_gpencil_legacy_stroke_paint_draw_brush(params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Paint (Draw brush)",
|
||||
|
@ -2540,7 +2540,7 @@ def km_grease_pencil_stroke_paint_draw_brush(params):
|
|||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_paint_erase(params):
|
||||
def km_gpencil_legacy_stroke_paint_erase(params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Paint (Erase)",
|
||||
|
@ -2559,7 +2559,7 @@ def km_grease_pencil_stroke_paint_erase(params):
|
|||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_paint_fill(params):
|
||||
def km_gpencil_legacy_stroke_paint_fill(params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Paint (Fill)",
|
||||
|
@ -2584,7 +2584,7 @@ def km_grease_pencil_stroke_paint_fill(params):
|
|||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_paint_tint(params):
|
||||
def km_gpencil_legacy_stroke_paint_tint(params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Paint (Tint)",
|
||||
|
@ -2603,7 +2603,7 @@ def km_grease_pencil_stroke_paint_tint(params):
|
|||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_sculpt_mode(params):
|
||||
def km_gpencil_legacy_stroke_sculpt_mode(params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Sculpt Mode",
|
||||
|
@ -2625,7 +2625,7 @@ def km_grease_pencil_stroke_sculpt_mode(params):
|
|||
("gpencil.select", {"type": 'LEFTMOUSE', "value": 'CLICK', "shift": True, "alt": True, "ctrl": True},
|
||||
{"properties": [("use_shift_extend", True), ("toggle", True)]}),
|
||||
# Selection
|
||||
*_grease_pencil_selection(params),
|
||||
*_gpencil_legacy_selection(params),
|
||||
# Brush properties
|
||||
("wm.radial_control", {"type": 'U', "value": 'PRESS'},
|
||||
{"properties": [("data_path_primary", 'tool_settings.gpencil_sculpt_paint.brush.strength')]}),
|
||||
|
@ -2638,7 +2638,7 @@ def km_grease_pencil_stroke_sculpt_mode(params):
|
|||
# Copy
|
||||
("gpencil.copy", {"type": 'C', "value": 'PRESS', "ctrl": True}, None),
|
||||
# Display
|
||||
*_grease_pencil_display(),
|
||||
*_gpencil_legacy_display(),
|
||||
# Delete
|
||||
op_menu("VIEW3D_MT_edit_gpencil_delete", {"type": 'BACK_SPACE', "value": 'PRESS'}),
|
||||
op_menu("VIEW3D_MT_edit_gpencil_delete", {"type": 'DEL', "value": 'PRESS'}),
|
||||
|
@ -2663,7 +2663,7 @@ def km_grease_pencil_stroke_sculpt_mode(params):
|
|||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_sculpt_smooth(_params):
|
||||
def km_gpencil_legacy_stroke_sculpt_smooth(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Sculpt (Smooth)",
|
||||
|
@ -2683,7 +2683,7 @@ def km_grease_pencil_stroke_sculpt_smooth(_params):
|
|||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_sculpt_thickness(_params):
|
||||
def km_gpencil_legacy_stroke_sculpt_thickness(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Sculpt (Thickness)",
|
||||
|
@ -2703,7 +2703,7 @@ def km_grease_pencil_stroke_sculpt_thickness(_params):
|
|||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_sculpt_strength(_params):
|
||||
def km_gpencil_legacy_stroke_sculpt_strength(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Sculpt (Strength)",
|
||||
|
@ -2723,7 +2723,7 @@ def km_grease_pencil_stroke_sculpt_strength(_params):
|
|||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_sculpt_grab(_params):
|
||||
def km_gpencil_legacy_stroke_sculpt_grab(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Sculpt (Grab)",
|
||||
|
@ -2743,7 +2743,7 @@ def km_grease_pencil_stroke_sculpt_grab(_params):
|
|||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_sculpt_push(_params):
|
||||
def km_gpencil_legacy_stroke_sculpt_push(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Sculpt (Push)",
|
||||
|
@ -2763,7 +2763,7 @@ def km_grease_pencil_stroke_sculpt_push(_params):
|
|||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_sculpt_twist(_params):
|
||||
def km_gpencil_legacy_stroke_sculpt_twist(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Sculpt (Twist)",
|
||||
|
@ -2783,7 +2783,7 @@ def km_grease_pencil_stroke_sculpt_twist(_params):
|
|||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_sculpt_pinch(_params):
|
||||
def km_gpencil_legacy_stroke_sculpt_pinch(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Sculpt (Pinch)",
|
||||
|
@ -2803,7 +2803,7 @@ def km_grease_pencil_stroke_sculpt_pinch(_params):
|
|||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_sculpt_randomize(_params):
|
||||
def km_gpencil_legacy_stroke_sculpt_randomize(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Sculpt (Randomize)",
|
||||
|
@ -2823,7 +2823,7 @@ def km_grease_pencil_stroke_sculpt_randomize(_params):
|
|||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_sculpt_clone(_params):
|
||||
def km_gpencil_legacy_stroke_sculpt_clone(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Sculpt (Clone)",
|
||||
|
@ -2843,7 +2843,7 @@ def km_grease_pencil_stroke_sculpt_clone(_params):
|
|||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_weight_mode(params):
|
||||
def km_gpencil_legacy_stroke_weight_mode(params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Weight Mode",
|
||||
|
@ -2888,7 +2888,7 @@ def km_grease_pencil_stroke_weight_mode(params):
|
|||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_weight_draw(_params):
|
||||
def km_gpencil_legacy_stroke_weight_draw(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Weight (Draw)",
|
||||
|
@ -2906,7 +2906,7 @@ def km_grease_pencil_stroke_weight_draw(_params):
|
|||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_weight_blur(_params):
|
||||
def km_gpencil_legacy_stroke_weight_blur(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Weight (Blur)",
|
||||
|
@ -2922,7 +2922,7 @@ def km_grease_pencil_stroke_weight_blur(_params):
|
|||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_weight_average(_params):
|
||||
def km_gpencil_legacy_stroke_weight_average(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Weight (Average)",
|
||||
|
@ -2938,7 +2938,7 @@ def km_grease_pencil_stroke_weight_average(_params):
|
|||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_weight_smear(_params):
|
||||
def km_gpencil_legacy_stroke_weight_smear(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Weight (Smear)",
|
||||
|
@ -2954,7 +2954,7 @@ def km_grease_pencil_stroke_weight_smear(_params):
|
|||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_vertex_mode(params):
|
||||
def km_gpencil_legacy_stroke_vertex_mode(params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Vertex Mode",
|
||||
|
@ -2976,7 +2976,7 @@ def km_grease_pencil_stroke_vertex_mode(params):
|
|||
("gpencil.select", {"type": 'LEFTMOUSE', "value": 'CLICK', "shift": True, "alt": True, "ctrl": True},
|
||||
{"properties": [("use_shift_extend", True), ("toggle", True)]}),
|
||||
# Selection
|
||||
*_grease_pencil_selection(params),
|
||||
*_gpencil_legacy_selection(params),
|
||||
# Brush strength
|
||||
("wm.radial_control", {"type": 'U', "value": 'PRESS'},
|
||||
{"properties": [("data_path_primary", 'tool_settings.gpencil_vertex_paint.brush.gpencil_settings.pen_strength')]}),
|
||||
|
@ -2990,7 +2990,7 @@ def km_grease_pencil_stroke_vertex_mode(params):
|
|||
# Color operators
|
||||
("gpencil.tint_flip", {"type": 'X', "value": 'PRESS'}, None),
|
||||
# Display
|
||||
*_grease_pencil_display(),
|
||||
*_gpencil_legacy_display(),
|
||||
# Delete
|
||||
op_menu("VIEW3D_MT_edit_gpencil_delete", {"type": 'BACK_SPACE', "value": 'PRESS'}),
|
||||
op_menu("VIEW3D_MT_edit_gpencil_delete", {"type": 'DEL', "value": 'PRESS'}),
|
||||
|
@ -3013,7 +3013,7 @@ def km_grease_pencil_stroke_vertex_mode(params):
|
|||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_vertex_draw(params):
|
||||
def km_gpencil_legacy_stroke_vertex_draw(params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Vertex (Draw)",
|
||||
|
@ -3038,7 +3038,7 @@ def km_grease_pencil_stroke_vertex_draw(params):
|
|||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_vertex_blur(params):
|
||||
def km_gpencil_legacy_stroke_vertex_blur(params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Vertex (Blur)",
|
||||
|
@ -3061,7 +3061,7 @@ def km_grease_pencil_stroke_vertex_blur(params):
|
|||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_vertex_average(params):
|
||||
def km_gpencil_legacy_stroke_vertex_average(params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Vertex (Average)",
|
||||
|
@ -3086,7 +3086,7 @@ def km_grease_pencil_stroke_vertex_average(params):
|
|||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_vertex_smear(params):
|
||||
def km_gpencil_legacy_stroke_vertex_smear(params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Vertex (Smear)",
|
||||
|
@ -3109,7 +3109,7 @@ def km_grease_pencil_stroke_vertex_smear(params):
|
|||
return keymap
|
||||
|
||||
|
||||
def km_grease_pencil_stroke_vertex_replace(params):
|
||||
def km_gpencil_legacy_stroke_vertex_replace(params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Grease Pencil Stroke Vertex (Replace)",
|
||||
|
@ -4520,34 +4520,34 @@ def generate_keymaps_impl(params=None):
|
|||
km_animation_channels(params),
|
||||
|
||||
# Modes.
|
||||
# km_grease_pencil(params), # Empty.
|
||||
km_grease_pencil_stroke_edit_mode(params),
|
||||
km_grease_pencil_stroke_paint_mode(params),
|
||||
km_grease_pencil_stroke_paint_draw_brush(params),
|
||||
km_grease_pencil_stroke_paint_erase(params),
|
||||
km_grease_pencil_stroke_paint_fill(params),
|
||||
km_grease_pencil_stroke_paint_tint(params),
|
||||
km_grease_pencil_stroke_sculpt_mode(params),
|
||||
km_grease_pencil_stroke_sculpt_smooth(params),
|
||||
km_grease_pencil_stroke_sculpt_thickness(params),
|
||||
km_grease_pencil_stroke_sculpt_strength(params),
|
||||
km_grease_pencil_stroke_sculpt_grab(params),
|
||||
km_grease_pencil_stroke_sculpt_push(params),
|
||||
km_grease_pencil_stroke_sculpt_twist(params),
|
||||
km_grease_pencil_stroke_sculpt_pinch(params),
|
||||
km_grease_pencil_stroke_sculpt_randomize(params),
|
||||
km_grease_pencil_stroke_sculpt_clone(params),
|
||||
km_grease_pencil_stroke_weight_mode(params),
|
||||
km_grease_pencil_stroke_weight_draw(params),
|
||||
km_grease_pencil_stroke_weight_blur(params),
|
||||
km_grease_pencil_stroke_weight_average(params),
|
||||
km_grease_pencil_stroke_weight_smear(params),
|
||||
km_grease_pencil_stroke_vertex_mode(params),
|
||||
km_grease_pencil_stroke_vertex_draw(params),
|
||||
km_grease_pencil_stroke_vertex_blur(params),
|
||||
km_grease_pencil_stroke_vertex_average(params),
|
||||
km_grease_pencil_stroke_vertex_smear(params),
|
||||
km_grease_pencil_stroke_vertex_replace(params),
|
||||
# km_gpencil_legacy(params), # Empty.
|
||||
km_gpencil_legacy_stroke_edit_mode(params),
|
||||
km_gpencil_legacy_stroke_paint_mode(params),
|
||||
km_gpencil_legacy_stroke_paint_draw_brush(params),
|
||||
km_gpencil_legacy_stroke_paint_erase(params),
|
||||
km_gpencil_legacy_stroke_paint_fill(params),
|
||||
km_gpencil_legacy_stroke_paint_tint(params),
|
||||
km_gpencil_legacy_stroke_sculpt_mode(params),
|
||||
km_gpencil_legacy_stroke_sculpt_smooth(params),
|
||||
km_gpencil_legacy_stroke_sculpt_thickness(params),
|
||||
km_gpencil_legacy_stroke_sculpt_strength(params),
|
||||
km_gpencil_legacy_stroke_sculpt_grab(params),
|
||||
km_gpencil_legacy_stroke_sculpt_push(params),
|
||||
km_gpencil_legacy_stroke_sculpt_twist(params),
|
||||
km_gpencil_legacy_stroke_sculpt_pinch(params),
|
||||
km_gpencil_legacy_stroke_sculpt_randomize(params),
|
||||
km_gpencil_legacy_stroke_sculpt_clone(params),
|
||||
km_gpencil_legacy_stroke_weight_mode(params),
|
||||
km_gpencil_legacy_stroke_weight_draw(params),
|
||||
km_gpencil_legacy_stroke_weight_blur(params),
|
||||
km_gpencil_legacy_stroke_weight_average(params),
|
||||
km_gpencil_legacy_stroke_weight_smear(params),
|
||||
km_gpencil_legacy_stroke_vertex_mode(params),
|
||||
km_gpencil_legacy_stroke_vertex_draw(params),
|
||||
km_gpencil_legacy_stroke_vertex_blur(params),
|
||||
km_gpencil_legacy_stroke_vertex_average(params),
|
||||
km_gpencil_legacy_stroke_vertex_smear(params),
|
||||
km_gpencil_legacy_stroke_vertex_replace(params),
|
||||
km_face_mask(params),
|
||||
km_weight_paint_vertex_selection(params),
|
||||
km_pose(params),
|
||||
|
|
|
@ -71,7 +71,6 @@ class ANIM_OT_keying_set_export(Operator):
|
|||
|
||||
f.write("ks.use_insertkey_needed = %s\n" % ks.use_insertkey_needed)
|
||||
f.write("ks.use_insertkey_visual = %s\n" % ks.use_insertkey_visual)
|
||||
f.write("ks.use_insertkey_xyz_to_rgb = %s\n" % ks.use_insertkey_xyz_to_rgb)
|
||||
f.write("\n")
|
||||
|
||||
# --------------------------------------------------------
|
||||
|
|
|
@ -589,6 +589,11 @@ class RemovePresetInterfaceTheme(AddPresetBase, Operator):
|
|||
def invoke(self, context, event):
|
||||
return context.window_manager.invoke_confirm(self, event, title="Remove Custom Theme", confirm_text="Delete")
|
||||
|
||||
def post_cb(self, context):
|
||||
# Without this, the name & colors are kept after removing the theme.
|
||||
# Even though the theme is removed from the list, it's seems like a bug to keep it displayed after removal.
|
||||
bpy.ops.preferences.reset_default_theme()
|
||||
|
||||
|
||||
class SavePresetInterfaceTheme(AddPresetBase, Operator):
|
||||
"""Save a custom theme in the preset list"""
|
||||
|
|
|
@ -70,7 +70,7 @@ class GreasePencilDisplayPanel:
|
|||
def poll(cls, context):
|
||||
ob = context.active_object
|
||||
brush = context.tool_settings.gpencil_paint.brush
|
||||
if ob and ob.type == 'GPENCIL' and brush:
|
||||
if ob and ob.type in {'GPENCIL', 'GREASE_PENCIL'} and brush:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
|
|
@ -84,6 +84,8 @@ class UnifiedPaintPanel:
|
|||
return tool_settings.curves_sculpt
|
||||
elif mode == 'PAINT_GREASE_PENCIL':
|
||||
return tool_settings.gpencil_paint
|
||||
elif mode == 'SCULPT_GREASE_PENCIL':
|
||||
return tool_settings.gpencil_sculpt_paint
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
|
@ -914,6 +916,11 @@ def brush_shared_settings(layout, context, brush, popover=False):
|
|||
size = True
|
||||
strength = True
|
||||
|
||||
# Grease Pencil #
|
||||
if mode == 'SCULPT_GREASE_PENCIL':
|
||||
size = True
|
||||
strength = True
|
||||
|
||||
### Draw settings. ###
|
||||
ups = context.scene.tool_settings.unified_paint_settings
|
||||
|
||||
|
@ -1064,6 +1071,17 @@ def brush_settings_advanced(layout, context, brush, popover=False):
|
|||
col.prop(brush, "use_original_plane", text="Plane")
|
||||
layout.separator()
|
||||
|
||||
elif mode == 'SCULPT_GREASE_PENCIL':
|
||||
tool = brush.gpencil_sculpt_tool
|
||||
gp_settings = brush.gpencil_settings
|
||||
|
||||
if tool in {'SMOOTH', 'RANDOMIZE'}:
|
||||
col = layout.column(heading="Affect", align=True)
|
||||
col.prop(gp_settings, "use_edit_position", text="Position")
|
||||
col.prop(gp_settings, "use_edit_strength", text="Strength")
|
||||
col.prop(gp_settings, "use_edit_thickness", text="Thickness")
|
||||
col.prop(gp_settings, "use_edit_uv", text="UV")
|
||||
|
||||
# 3D and 2D Texture Paint.
|
||||
elif mode in {'PAINT_TEXTURE', 'PAINT_2D'}:
|
||||
layout.prop(brush, "image_tool")
|
||||
|
|
|
@ -2506,6 +2506,37 @@ class _defs_gpencil_sculpt:
|
|||
)
|
||||
|
||||
|
||||
class _defs_grease_pencil_sculpt:
|
||||
@staticmethod
|
||||
def poll_select_mask(context):
|
||||
if context is None:
|
||||
return True
|
||||
ob = context.active_object
|
||||
tool_settings = context.scene.tool_settings
|
||||
return (
|
||||
ob is not None and
|
||||
ob.type in {'GPENCIL', 'GREASE_PENCIL'} and (
|
||||
tool_settings.use_gpencil_select_mask_point or
|
||||
tool_settings.use_gpencil_select_mask_stroke or
|
||||
tool_settings.use_gpencil_select_mask_segment
|
||||
)
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def generate_from_brushes(context):
|
||||
return generate_from_enum_ex(
|
||||
context,
|
||||
idname_prefix="builtin_brush.",
|
||||
icon_prefix="ops.gpencil.sculpt_",
|
||||
type=bpy.types.Brush,
|
||||
# Uses GPv2 tool settings
|
||||
attr="gpencil_sculpt_tool",
|
||||
tooldef_keywords=dict(
|
||||
operator="grease_pencil.sculpt_paint",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
class _defs_gpencil_weight:
|
||||
|
||||
@staticmethod
|
||||
|
@ -3213,6 +3244,16 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel):
|
|||
None,
|
||||
*_tools_annotate,
|
||||
],
|
||||
'SCULPT_GREASE_PENCIL': [
|
||||
_defs_grease_pencil_sculpt.generate_from_brushes,
|
||||
None,
|
||||
*_tools_annotate,
|
||||
lambda context: (
|
||||
VIEW3D_PT_tools_active._tools_gpencil_select
|
||||
if _defs_grease_pencil_sculpt.poll_select_mask(context)
|
||||
else ()
|
||||
),
|
||||
],
|
||||
'PAINT_TEXTURE': [
|
||||
_defs_texture_paint.generate_from_brushes,
|
||||
None,
|
||||
|
|
|
@ -120,6 +120,14 @@ class VIEW3D_HT_tool_header(Header):
|
|||
if tool in {'SMOOTH', 'RANDOMIZE'}:
|
||||
layout.popover("VIEW3D_PT_tools_grease_pencil_sculpt_brush_popover")
|
||||
layout.popover("VIEW3D_PT_tools_grease_pencil_sculpt_appearance")
|
||||
elif tool_mode == 'SCULPT_GREASE_PENCIL':
|
||||
if is_valid_context:
|
||||
brush = context.tool_settings.gpencil_sculpt_paint.brush
|
||||
if brush:
|
||||
tool = brush.gpencil_sculpt_tool
|
||||
if tool in {'SMOOTH', 'RANDOMIZE'}:
|
||||
layout.popover("VIEW3D_PT_tools_grease_pencil_sculpt_brush_popover")
|
||||
layout.popover("VIEW3D_PT_tools_grease_pencil_sculpt_appearance")
|
||||
elif tool_mode == 'WEIGHT_GPENCIL':
|
||||
if is_valid_context:
|
||||
layout.popover("VIEW3D_PT_tools_grease_pencil_weight_appearance")
|
||||
|
@ -417,6 +425,59 @@ class _draw_tool_settings_context_mode:
|
|||
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def SCULPT_GREASE_PENCIL(context, layout, tool):
|
||||
if (tool is None) or (not tool.has_datablock):
|
||||
return False
|
||||
|
||||
paint = context.tool_settings.gpencil_sculpt_paint
|
||||
layout.template_ID_preview(paint, "brush", rows=3, cols=8, hide_buttons=True)
|
||||
|
||||
brush = paint.brush
|
||||
if brush is None:
|
||||
return False
|
||||
|
||||
tool_settings = context.tool_settings
|
||||
capabilities = brush.sculpt_capabilities
|
||||
|
||||
ups = tool_settings.unified_paint_settings
|
||||
|
||||
size = "size"
|
||||
size_owner = ups if ups.use_unified_size else brush
|
||||
if size_owner.use_locked_size == 'SCENE':
|
||||
size = "unprojected_radius"
|
||||
|
||||
UnifiedPaintPanel.prop_unified(
|
||||
layout,
|
||||
context,
|
||||
brush,
|
||||
size,
|
||||
pressure_name="use_pressure_size",
|
||||
unified_name="use_unified_size",
|
||||
text="Radius",
|
||||
slider=True,
|
||||
header=True,
|
||||
)
|
||||
|
||||
# strength, use_strength_pressure
|
||||
pressure_name = "use_pressure_strength" if capabilities.has_strength_pressure else None
|
||||
UnifiedPaintPanel.prop_unified(
|
||||
layout,
|
||||
context,
|
||||
brush,
|
||||
"strength",
|
||||
pressure_name=pressure_name,
|
||||
unified_name="use_unified_strength",
|
||||
text="Strength",
|
||||
header=True,
|
||||
)
|
||||
|
||||
# direction
|
||||
if not capabilities.has_direction:
|
||||
layout.row().prop(brush, "direction", expand=True, text="")
|
||||
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def WEIGHT_GPENCIL(context, layout, tool):
|
||||
if (tool is None) or (not tool.has_datablock):
|
||||
|
@ -1132,7 +1193,7 @@ class VIEW3D_MT_editor_menus(Menu):
|
|||
layout.menu("VIEW3D_MT_select_paint_mask")
|
||||
elif mesh.use_paint_mask_vertex and mode_string in {'PAINT_WEIGHT', 'PAINT_VERTEX'}:
|
||||
layout.menu("VIEW3D_MT_select_paint_mask_vertex")
|
||||
elif mode_string not in {'SCULPT', 'SCULPT_CURVES', 'PAINT_GREASE_PENCIL'}:
|
||||
elif mode_string not in {'SCULPT', 'SCULPT_CURVES', 'PAINT_GREASE_PENCIL', 'SCULPT_GREASE_PENCIL'}:
|
||||
layout.menu("VIEW3D_MT_select_%s" % mode_string.lower())
|
||||
|
||||
if gp_edit:
|
||||
|
@ -1183,7 +1244,7 @@ class VIEW3D_MT_editor_menus(Menu):
|
|||
layout.menu("VIEW3D_MT_edit_greasepencil_point")
|
||||
|
||||
elif obj:
|
||||
if mode_string not in {'PAINT_TEXTURE', 'SCULPT_CURVES'}:
|
||||
if mode_string not in {'PAINT_TEXTURE', 'SCULPT_CURVES', 'SCULPT_GREASE_PENCIL'}:
|
||||
layout.menu("VIEW3D_MT_%s" % mode_string.lower())
|
||||
if mode_string == 'SCULPT':
|
||||
layout.menu("VIEW3D_MT_mask")
|
||||
|
|
|
@ -619,8 +619,11 @@ class VIEW3D_PT_slots_paint_canvas(SelectPaintSlotHelper, View3DPanel, Panel):
|
|||
if mat and mat.texture_paint_images and mat.texture_paint_slots:
|
||||
label = mat.texture_paint_slots[mat.paint_active_slot].name
|
||||
elif paint.canvas_source == 'COLOR_ATTRIBUTE':
|
||||
label = (me.color_attributes.active_color.name if me.color_attributes.active_color
|
||||
else iface_("Color Attribute"))
|
||||
active_color = me.color_attributes.active_color
|
||||
label = (
|
||||
active_color.name if active_color else
|
||||
iface_("Color Attribute")
|
||||
)
|
||||
elif paint.canvas_image:
|
||||
label = paint.canvas_image.name
|
||||
|
||||
|
@ -637,7 +640,7 @@ class VIEW3D_PT_slots_color_attributes(Panel):
|
|||
me = context.object.data
|
||||
active_color = me.color_attributes.active_color
|
||||
self.bl_label = (
|
||||
iface_(active_color.name) if active_color else
|
||||
active_color.name if active_color else
|
||||
iface_("Color Attributes")
|
||||
)
|
||||
|
||||
|
@ -678,7 +681,7 @@ class VIEW3D_PT_slots_vertex_groups(Panel):
|
|||
ob = context.object
|
||||
groups = ob.vertex_groups
|
||||
self.bl_label = (
|
||||
iface_(groups.active.name) if groups and groups.active else
|
||||
groups.active.name if groups and groups.active else
|
||||
iface_("Vertex Groups")
|
||||
)
|
||||
|
||||
|
|
|
@ -1207,12 +1207,11 @@ bool armature_bonecoll_is_child_of(const bArmature *armature,
|
|||
const int potential_child_index)
|
||||
{
|
||||
/* Check for roots, before we try and access collection_array[-1]. */
|
||||
const bool is_root = armature_bonecoll_is_root(armature, potential_child_index);
|
||||
if (is_root) {
|
||||
if (armature_bonecoll_is_root(armature, potential_child_index)) {
|
||||
return potential_parent_index == -1;
|
||||
}
|
||||
if (potential_parent_index < 0) {
|
||||
return is_root;
|
||||
return false;
|
||||
}
|
||||
|
||||
const BoneCollection *potential_parent = armature->collection_array[potential_parent_index];
|
||||
|
|
|
@ -916,7 +916,7 @@ TEST_F(ArmatureBoneCollections, bcoll_move_to_parent__root_unroot)
|
|||
ASSERT_EQ(6, arm.collection_array_num);
|
||||
EXPECT_STREQ(bcoll_root_0->name, arm.collection_array[0]->name);
|
||||
EXPECT_STREQ(bcoll_root_1->name, arm.collection_array[1]->name);
|
||||
EXPECT_STREQ(bcoll_r0_child1->name, arm.collection_array[2]->name); // Became a root.
|
||||
EXPECT_STREQ(bcoll_r0_child1->name, arm.collection_array[2]->name); /* Became a root. */
|
||||
EXPECT_STREQ(bcoll_r0_child0->name, arm.collection_array[3]->name);
|
||||
EXPECT_STREQ(bcoll_r0_child2->name, arm.collection_array[4]->name);
|
||||
EXPECT_STREQ(bcoll_r1_child0->name, arm.collection_array[5]->name);
|
||||
|
@ -941,10 +941,10 @@ TEST_F(ArmatureBoneCollections, bcoll_move_to_parent__root_unroot)
|
|||
ASSERT_EQ(2, arm.collection_root_count);
|
||||
ASSERT_EQ(6, arm.collection_array_num);
|
||||
EXPECT_STREQ(bcoll_root_0->name, arm.collection_array[0]->name);
|
||||
EXPECT_STREQ(bcoll_r0_child1->name, arm.collection_array[1]->name); // Actually a root.
|
||||
EXPECT_STREQ(bcoll_r0_child1->name, arm.collection_array[1]->name); /* Actually a root. */
|
||||
EXPECT_STREQ(bcoll_r0_child0->name, arm.collection_array[2]->name);
|
||||
EXPECT_STREQ(bcoll_r0_child2->name, arm.collection_array[3]->name);
|
||||
EXPECT_STREQ(bcoll_root_1->name, arm.collection_array[4]->name); // Became a child.
|
||||
EXPECT_STREQ(bcoll_root_1->name, arm.collection_array[4]->name); /* Became a child. */
|
||||
EXPECT_STREQ(bcoll_r1_child0->name, arm.collection_array[5]->name);
|
||||
|
||||
EXPECT_EQ(2, arm.collection_array[0]->child_index);
|
||||
|
|
|
@ -29,7 +29,7 @@ extern "C" {
|
|||
|
||||
/* Blender file format version. */
|
||||
#define BLENDER_FILE_VERSION BLENDER_VERSION
|
||||
#define BLENDER_FILE_SUBVERSION 13
|
||||
#define BLENDER_FILE_SUBVERSION 15
|
||||
|
||||
/* Minimum Blender version that supports reading file written with the current
|
||||
* version. Older Blender versions will test this and cancel loading the file, showing a warning to
|
||||
|
|
|
@ -141,8 +141,9 @@ enum eContextObjectMode {
|
|||
CTX_MODE_VERTEX_GPENCIL_LEGACY,
|
||||
CTX_MODE_SCULPT_CURVES,
|
||||
CTX_MODE_PAINT_GREASE_PENCIL,
|
||||
CTX_MODE_SCULPT_GREASE_PENCIL,
|
||||
};
|
||||
#define CTX_MODE_NUM (CTX_MODE_PAINT_GREASE_PENCIL + 1)
|
||||
#define CTX_MODE_NUM (CTX_MODE_SCULPT_GREASE_PENCIL + 1)
|
||||
|
||||
/* Context */
|
||||
|
||||
|
|
|
@ -87,6 +87,7 @@ extern const uchar PAINT_CURSOR_VERTEX_PAINT[3];
|
|||
extern const uchar PAINT_CURSOR_WEIGHT_PAINT[3];
|
||||
extern const uchar PAINT_CURSOR_TEXTURE_PAINT[3];
|
||||
extern const uchar PAINT_CURSOR_SCULPT_CURVES[3];
|
||||
extern const uchar PAINT_CURSOR_SCULPT_GREASE_PENCIL[3];
|
||||
|
||||
enum class PaintMode : int8_t {
|
||||
Sculpt = 0,
|
||||
|
@ -105,9 +106,11 @@ enum class PaintMode : int8_t {
|
|||
WeightGPencil = 9,
|
||||
/** Curves. */
|
||||
SculptCurves = 10,
|
||||
/** Grease Pencil. */
|
||||
SculptGreasePencil = 11,
|
||||
|
||||
/** Keep last. */
|
||||
Invalid = 11,
|
||||
Invalid = 12,
|
||||
};
|
||||
|
||||
#define PAINT_MODE_HAS_BRUSH(mode) !ELEM(mode, PaintMode::SculptUV)
|
||||
|
|
|
@ -1191,7 +1191,12 @@ enum eContextObjectMode CTX_data_mode_enum_ex(const Object *obedit,
|
|||
return CTX_MODE_EDIT_GPENCIL_LEGACY;
|
||||
}
|
||||
if (object_mode & OB_MODE_SCULPT_GPENCIL_LEGACY) {
|
||||
return CTX_MODE_SCULPT_GPENCIL_LEGACY;
|
||||
if (ob->type == OB_GPENCIL_LEGACY) {
|
||||
return CTX_MODE_SCULPT_GPENCIL_LEGACY;
|
||||
}
|
||||
if (ob->type == OB_GREASE_PENCIL) {
|
||||
return CTX_MODE_SCULPT_GREASE_PENCIL;
|
||||
}
|
||||
}
|
||||
if (object_mode & OB_MODE_WEIGHT_GPENCIL_LEGACY) {
|
||||
return CTX_MODE_WEIGHT_GPENCIL_LEGACY;
|
||||
|
@ -1248,6 +1253,7 @@ static const char *data_mode_strings[] = {
|
|||
"greasepencil_vertex",
|
||||
"curves_sculpt",
|
||||
"grease_pencil_paint",
|
||||
"grease_pencil_sculpt",
|
||||
nullptr,
|
||||
};
|
||||
BLI_STATIC_ASSERT(ARRAY_SIZE(data_mode_strings) == CTX_MODE_NUM + 1,
|
||||
|
|
|
@ -1966,8 +1966,12 @@ void BKE_fcurve_merge_duplicate_keys(FCurve *fcu, const int sel_flag, const bool
|
|||
|
||||
void BKE_fcurve_deduplicate_keys(FCurve *fcu)
|
||||
{
|
||||
if (fcu->totvert < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
BLI_assert_msg(fcu->bezt, "this function only works with regular (non-sampled) FCurves");
|
||||
if (fcu->totvert < 2 || fcu->bezt == nullptr) {
|
||||
if (fcu->bezt == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -643,13 +643,13 @@ static float (*mask_spline_feather_differentiated_points_with_resolution__double
|
|||
/* before we transform verts */
|
||||
len_base = len_v2v2(bezt_prev->vec[1], bezt_curr->vec[1]);
|
||||
|
||||
// add_v2_v2(bezt_prev->vec[0], point_prev_n); // not needed
|
||||
// add_v2_v2(bezt_prev->vec[0], point_prev_n); /* Not needed. */
|
||||
add_v2_v2(bezt_prev->vec[1], point_prev_n);
|
||||
add_v2_v2(bezt_prev->vec[2], point_prev_n);
|
||||
|
||||
add_v2_v2(bezt_curr->vec[0], point_curr_n);
|
||||
add_v2_v2(bezt_curr->vec[1], point_curr_n);
|
||||
// add_v2_v2(bezt_curr->vec[2], point_curr_n); // not needed
|
||||
// add_v2_v2(bezt_curr->vec[2], point_curr_n); /* Not needed. */
|
||||
|
||||
len_feather = len_v2v2(bezt_prev->vec[1], bezt_curr->vec[1]);
|
||||
|
||||
|
|
|
@ -6,10 +6,11 @@
|
|||
* \ingroup bke
|
||||
*/
|
||||
|
||||
#include "BLI_map.hh"
|
||||
#include "BLI_array_utils.hh"
|
||||
#include "BLI_ordered_edge.hh"
|
||||
#include "BLI_task.hh"
|
||||
#include "BLI_threads.h"
|
||||
#include "BLI_vector_set.hh"
|
||||
|
||||
#include "BKE_attribute.hh"
|
||||
#include "BKE_customdata.hh"
|
||||
|
@ -28,12 +29,12 @@ static uint64_t edge_hash_2(const OrderedEdge &edge)
|
|||
return edge.v_low;
|
||||
}
|
||||
|
||||
/* The map first contains an edge pointer and later an index. */
|
||||
union OrigEdgeOrIndex {
|
||||
const int2 *original_edge;
|
||||
int index;
|
||||
};
|
||||
using EdgeMap = Map<OrderedEdge, OrigEdgeOrIndex>;
|
||||
using EdgeMap = VectorSet<OrderedEdge,
|
||||
DefaultProbingStrategy,
|
||||
DefaultHash<OrderedEdge>,
|
||||
DefaultEquality<OrderedEdge>,
|
||||
SimpleVectorSetSlot<OrderedEdge, int>,
|
||||
GuardedAllocator>;
|
||||
|
||||
static void reserve_hash_maps(const Mesh &mesh,
|
||||
const bool keep_existing_edges,
|
||||
|
@ -52,11 +53,11 @@ static void add_existing_edges_to_hash_maps(const Mesh &mesh,
|
|||
const Span<int2> edges = mesh.edges();
|
||||
threading::parallel_for_each(edge_maps, [&](EdgeMap &edge_map) {
|
||||
const int task_index = &edge_map - edge_maps.data();
|
||||
for (const int2 &edge : edges) {
|
||||
const OrderedEdge ordered_edge(edge[0], edge[1]);
|
||||
for (const int2 edge : edges) {
|
||||
const OrderedEdge ordered_edge(edge);
|
||||
/* Only add the edge when it belongs into this map. */
|
||||
if (task_index == (parallel_mask & edge_hash_2(ordered_edge))) {
|
||||
edge_map.add_new(ordered_edge, {&edge});
|
||||
edge_map.add(ordered_edge);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -76,11 +77,11 @@ static void add_face_edges_to_hash_maps(const Mesh &mesh,
|
|||
const int vert = corner_verts[corner];
|
||||
const int vert_prev = corner_verts[bke::mesh::face_corner_prev(face, corner)];
|
||||
/* Can only be the same when the mesh data is invalid. */
|
||||
if (vert_prev != vert) {
|
||||
if (LIKELY(vert_prev != vert)) {
|
||||
const OrderedEdge ordered_edge(vert_prev, vert);
|
||||
/* Only add the edge when it belongs into this map. */
|
||||
if (task_index == (parallel_mask & edge_hash_2(ordered_edge))) {
|
||||
edge_map.lookup_or_add(ordered_edge, {nullptr});
|
||||
edge_map.add(ordered_edge);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -89,38 +90,17 @@ static void add_face_edges_to_hash_maps(const Mesh &mesh,
|
|||
}
|
||||
|
||||
static void serialize_and_initialize_deduplicated_edges(MutableSpan<EdgeMap> edge_maps,
|
||||
const OffsetIndices<int> edge_offsets,
|
||||
MutableSpan<int2> new_edges)
|
||||
{
|
||||
/* All edges are distributed in the hash tables now. They have to be serialized into a single
|
||||
* array below. To be able to parallelize this, we have to compute edge index offsets for each
|
||||
* map. */
|
||||
Array<int> edge_sizes(edge_maps.size() + 1);
|
||||
for (const int i : edge_maps.index_range()) {
|
||||
edge_sizes[i] = edge_maps[i].size();
|
||||
}
|
||||
const OffsetIndices<int> edge_offsets = offset_indices::accumulate_counts_to_offsets(edge_sizes);
|
||||
|
||||
threading::parallel_for_each(edge_maps, [&](EdgeMap &edge_map) {
|
||||
const int task_index = &edge_map - edge_maps.data();
|
||||
if (edge_offsets[task_index].is_empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
int new_edge_index = edge_offsets[task_index].first();
|
||||
for (EdgeMap::MutableItem item : edge_map.items()) {
|
||||
int2 &new_edge = new_edges[new_edge_index];
|
||||
const int2 *orig_edge = item.value.original_edge;
|
||||
if (orig_edge != nullptr) {
|
||||
/* Copy values from original edge. */
|
||||
new_edge = *orig_edge;
|
||||
}
|
||||
else {
|
||||
/* Initialize new edge. */
|
||||
new_edge = int2(item.key.v_low, item.key.v_high);
|
||||
}
|
||||
item.value.index = new_edge_index;
|
||||
new_edge_index++;
|
||||
}
|
||||
MutableSpan<int2> result_edges = new_edges.slice(edge_offsets[task_index]);
|
||||
result_edges.copy_from(edge_map.as_span().cast<int2>());
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -128,6 +108,7 @@ static void update_edge_indices_in_face_loops(const OffsetIndices<int> faces,
|
|||
const Span<int> corner_verts,
|
||||
const Span<EdgeMap> edge_maps,
|
||||
const uint32_t parallel_mask,
|
||||
const OffsetIndices<int> edge_offsets,
|
||||
MutableSpan<int> corner_edges)
|
||||
{
|
||||
threading::parallel_for(faces.index_range(), 100, [&](IndexRange range) {
|
||||
|
@ -136,20 +117,19 @@ static void update_edge_indices_in_face_loops(const OffsetIndices<int> faces,
|
|||
for (const int corner : face) {
|
||||
const int vert = corner_verts[corner];
|
||||
const int vert_prev = corner_verts[bke::mesh::face_corner_next(face, corner)];
|
||||
|
||||
int edge_index;
|
||||
if (vert_prev != vert) {
|
||||
const OrderedEdge ordered_edge(vert_prev, vert);
|
||||
/* Double lookup: First find the map that contains the edge, then lookup the edge. */
|
||||
const EdgeMap &edge_map = edge_maps[parallel_mask & edge_hash_2(ordered_edge)];
|
||||
edge_index = edge_map.lookup(ordered_edge).index;
|
||||
}
|
||||
else {
|
||||
if (UNLIKELY(vert == vert_prev)) {
|
||||
/* This is an invalid edge; normally this does not happen in Blender,
|
||||
* but it can be part of an imported mesh with invalid geometry. See
|
||||
* #76514. */
|
||||
edge_index = 0;
|
||||
corner_edges[corner] = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
const OrderedEdge ordered_edge(vert_prev, vert);
|
||||
const int task_index = parallel_mask & edge_hash_2(ordered_edge);
|
||||
const EdgeMap &edge_map = edge_maps[task_index];
|
||||
const int edge_i = edge_map.index_of(ordered_edge);
|
||||
const int edge_index = edge_offsets[task_index][edge_i];
|
||||
corner_edges[corner] = edge_index;
|
||||
}
|
||||
}
|
||||
|
@ -173,6 +153,24 @@ static void clear_hash_tables(MutableSpan<EdgeMap> edge_maps)
|
|||
threading::parallel_for_each(edge_maps, [](EdgeMap &edge_map) { edge_map.clear_and_shrink(); });
|
||||
}
|
||||
|
||||
static void deselect_known_edges(const OffsetIndices<int> edge_offsets,
|
||||
const Span<EdgeMap> edge_maps,
|
||||
const uint32_t parallel_mask,
|
||||
const Span<int2> known_edges,
|
||||
MutableSpan<bool> selection)
|
||||
{
|
||||
threading::parallel_for(known_edges.index_range(), 2048, [&](const IndexRange range) {
|
||||
for (const int2 original_edge : known_edges.slice(range)) {
|
||||
const OrderedEdge ordered_edge(original_edge);
|
||||
const int task_index = parallel_mask & edge_hash_2(ordered_edge);
|
||||
const EdgeMap &edge_map = edge_maps[task_index];
|
||||
const int edge_i = edge_map.index_of(ordered_edge);
|
||||
const int edge_index = edge_offsets[task_index][edge_i];
|
||||
selection[edge_index] = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace calc_edges
|
||||
|
||||
void mesh_calc_edges(Mesh &mesh, bool keep_existing_edges, const bool select_new_edges)
|
||||
|
@ -191,24 +189,35 @@ void mesh_calc_edges(Mesh &mesh, bool keep_existing_edges, const bool select_new
|
|||
}
|
||||
calc_edges::add_face_edges_to_hash_maps(mesh, parallel_mask, edge_maps);
|
||||
|
||||
/* Compute total number of edges. */
|
||||
int new_totedge = 0;
|
||||
for (const calc_edges::EdgeMap &edge_map : edge_maps) {
|
||||
new_totedge += edge_map.size();
|
||||
Array<int> edge_sizes(edge_maps.size() + 1);
|
||||
for (const int i : edge_maps.index_range()) {
|
||||
edge_sizes[i] = edge_maps[i].size();
|
||||
}
|
||||
const OffsetIndices<int> edge_offsets = offset_indices::accumulate_counts_to_offsets(edge_sizes);
|
||||
|
||||
/* Create new edges. */
|
||||
MutableAttributeAccessor attributes = mesh.attributes_for_write();
|
||||
attributes.add<int>(".corner_edge", AttrDomain::Corner, AttributeInitConstruct());
|
||||
MutableSpan<int2> new_edges(MEM_cnew_array<int2>(new_totedge, __func__), new_totedge);
|
||||
calc_edges::serialize_and_initialize_deduplicated_edges(edge_maps, new_edges);
|
||||
calc_edges::update_edge_indices_in_face_loops(
|
||||
mesh.faces(), mesh.corner_verts(), edge_maps, parallel_mask, mesh.corner_edges_for_write());
|
||||
MutableSpan<int2> new_edges(MEM_cnew_array<int2>(edge_offsets.total_size(), __func__),
|
||||
edge_offsets.total_size());
|
||||
calc_edges::serialize_and_initialize_deduplicated_edges(edge_maps, edge_offsets, new_edges);
|
||||
calc_edges::update_edge_indices_in_face_loops(mesh.faces(),
|
||||
mesh.corner_verts(),
|
||||
edge_maps,
|
||||
parallel_mask,
|
||||
edge_offsets,
|
||||
mesh.corner_edges_for_write());
|
||||
|
||||
Array<int2> original_edges;
|
||||
if (keep_existing_edges && select_new_edges) {
|
||||
original_edges.reinitialize(mesh.edges_num);
|
||||
array_utils::copy(mesh.edges(), original_edges.as_mutable_span());
|
||||
}
|
||||
|
||||
/* Free old CustomData and assign new one. */
|
||||
CustomData_free(&mesh.edge_data, mesh.edges_num);
|
||||
CustomData_reset(&mesh.edge_data);
|
||||
mesh.edges_num = new_totedge;
|
||||
mesh.edges_num = edge_offsets.total_size();
|
||||
attributes.add<int2>(".edge_verts", AttrDomain::Edge, AttributeInitMoveArray(new_edges.data()));
|
||||
|
||||
if (select_new_edges) {
|
||||
|
@ -216,14 +225,10 @@ void mesh_calc_edges(Mesh &mesh, bool keep_existing_edges, const bool select_new
|
|||
SpanAttributeWriter<bool> select_edge = attributes.lookup_or_add_for_write_span<bool>(
|
||||
".select_edge", AttrDomain::Edge);
|
||||
if (select_edge) {
|
||||
int new_edge_index = 0;
|
||||
for (const calc_edges::EdgeMap &edge_map : edge_maps) {
|
||||
for (const calc_edges::EdgeMap::Item item : edge_map.items()) {
|
||||
if (item.value.original_edge == nullptr) {
|
||||
select_edge.span[new_edge_index] = true;
|
||||
}
|
||||
new_edge_index++;
|
||||
}
|
||||
select_edge.span.fill(true);
|
||||
if (!original_edges.is_empty()) {
|
||||
calc_edges::deselect_known_edges(
|
||||
edge_offsets, edge_maps, parallel_mask, original_edges, select_edge.span);
|
||||
}
|
||||
select_edge.finish();
|
||||
}
|
||||
|
@ -235,7 +240,7 @@ void mesh_calc_edges(Mesh &mesh, bool keep_existing_edges, const bool select_new
|
|||
}
|
||||
|
||||
/* Explicitly clear edge maps, because that way it can be parallelized. */
|
||||
clear_hash_tables(edge_maps);
|
||||
calc_edges::clear_hash_tables(edge_maps);
|
||||
}
|
||||
|
||||
} // namespace blender::bke
|
||||
|
|
|
@ -1348,12 +1348,11 @@ OceanCache *BKE_ocean_init_cache(const char *bakepath,
|
|||
void BKE_ocean_simulate_cache(OceanCache *och, int frame)
|
||||
{
|
||||
char filepath[FILE_MAX];
|
||||
int f = frame;
|
||||
|
||||
/* ibufs array is zero based, but filenames are based on frame numbers */
|
||||
/* still need to clamp frame numbers to valid range of images on disk though */
|
||||
CLAMP(frame, och->start, och->end);
|
||||
f = frame - och->start; /* shift to 0 based */
|
||||
const int f = frame - och->start; /* shift to 0 based */
|
||||
|
||||
/* if image is already loaded in mem, return */
|
||||
if (och->ibufs_disp[f] != nullptr) {
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <cstring>
|
||||
#include <optional>
|
||||
|
||||
#include "DNA_object_enums.h"
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "DNA_asset_types.h"
|
||||
|
@ -254,6 +255,7 @@ const uchar PAINT_CURSOR_VERTEX_PAINT[3] = {255, 255, 255};
|
|||
const uchar PAINT_CURSOR_WEIGHT_PAINT[3] = {200, 200, 255};
|
||||
const uchar PAINT_CURSOR_TEXTURE_PAINT[3] = {255, 255, 255};
|
||||
const uchar PAINT_CURSOR_SCULPT_CURVES[3] = {255, 100, 100};
|
||||
const uchar PAINT_CURSOR_SCULPT_GREASE_PENCIL[3] = {255, 100, 100};
|
||||
|
||||
static ePaintOverlayControlFlags overlay_flags = (ePaintOverlayControlFlags)0;
|
||||
|
||||
|
@ -365,6 +367,9 @@ bool BKE_paint_ensure_from_paintmode(Main *bmain, Scene *sce, PaintMode mode)
|
|||
case PaintMode::SculptCurves:
|
||||
paint_ptr = (Paint **)&ts->curves_sculpt;
|
||||
break;
|
||||
case PaintMode::SculptGreasePencil:
|
||||
paint_ptr = (Paint **)&ts->gp_sculptpaint;
|
||||
break;
|
||||
case PaintMode::Invalid:
|
||||
break;
|
||||
}
|
||||
|
@ -402,6 +407,8 @@ Paint *BKE_paint_get_active_from_paintmode(Scene *sce, PaintMode mode)
|
|||
return &ts->gp_weightpaint->paint;
|
||||
case PaintMode::SculptCurves:
|
||||
return &ts->curves_sculpt->paint;
|
||||
case PaintMode::SculptGreasePencil:
|
||||
return &ts->gp_sculptpaint->paint;
|
||||
case PaintMode::Invalid:
|
||||
return nullptr;
|
||||
default:
|
||||
|
@ -436,6 +443,8 @@ const EnumPropertyItem *BKE_paint_get_tool_enum_from_paintmode(const PaintMode m
|
|||
return rna_enum_brush_gpencil_weight_types_items;
|
||||
case PaintMode::SculptCurves:
|
||||
return rna_enum_brush_curves_sculpt_tool_items;
|
||||
case PaintMode::SculptGreasePencil:
|
||||
return rna_enum_brush_gpencil_sculpt_types_items;
|
||||
case PaintMode::Invalid:
|
||||
break;
|
||||
}
|
||||
|
@ -545,7 +554,13 @@ PaintMode BKE_paintmode_get_active_from_context(const bContext *C)
|
|||
case OB_MODE_SCULPT:
|
||||
return PaintMode::Sculpt;
|
||||
case OB_MODE_SCULPT_GPENCIL_LEGACY:
|
||||
return PaintMode::SculptGPencil;
|
||||
if (obact->type == OB_GPENCIL_LEGACY) {
|
||||
return PaintMode::SculptGPencil;
|
||||
}
|
||||
if (obact->type == OB_GREASE_PENCIL) {
|
||||
return PaintMode::SculptGreasePencil;
|
||||
}
|
||||
return PaintMode::Invalid;
|
||||
case OB_MODE_WEIGHT_GPENCIL_LEGACY:
|
||||
return PaintMode::WeightGPencil;
|
||||
case OB_MODE_VERTEX_PAINT:
|
||||
|
@ -597,6 +612,8 @@ PaintMode BKE_paintmode_get_from_tool(const bToolRef *tref)
|
|||
return PaintMode::SculptCurves;
|
||||
case CTX_MODE_PAINT_GREASE_PENCIL:
|
||||
return PaintMode::GPencil;
|
||||
case CTX_MODE_SCULPT_GREASE_PENCIL:
|
||||
return PaintMode::SculptGreasePencil;
|
||||
}
|
||||
}
|
||||
else if (tref->space_type == SPACE_IMAGE) {
|
||||
|
@ -872,6 +889,8 @@ uint BKE_paint_get_brush_tool_offset_from_paintmode(const PaintMode mode)
|
|||
return offsetof(Brush, gpencil_weight_tool);
|
||||
case PaintMode::SculptCurves:
|
||||
return offsetof(Brush, curves_sculpt_tool);
|
||||
case PaintMode::SculptGreasePencil:
|
||||
return offsetof(Brush, gpencil_sculpt_tool);
|
||||
case PaintMode::Invalid:
|
||||
break; /* We don't use these yet. */
|
||||
}
|
||||
|
@ -1206,6 +1225,8 @@ eObjectMode BKE_paint_object_mode_from_paintmode(const PaintMode mode)
|
|||
return OB_MODE_SCULPT_CURVES;
|
||||
case PaintMode::GPencil:
|
||||
return OB_MODE_PAINT_GREASE_PENCIL;
|
||||
case PaintMode::SculptGreasePencil:
|
||||
return OB_MODE_SCULPT_GPENCIL_LEGACY;
|
||||
case PaintMode::Invalid:
|
||||
default:
|
||||
return OB_MODE_OBJECT;
|
||||
|
|
|
@ -1669,7 +1669,7 @@ template<typename T>
|
|||
MatBase<T, 4, 4> result = mat;
|
||||
const bool is_perspective = mat[2][3] == -1.0f;
|
||||
const bool is_perspective_infinite = mat[2][2] == -1.0f;
|
||||
if (is_perspective | is_perspective_infinite) {
|
||||
if (is_perspective || is_perspective_infinite) {
|
||||
result[2][0] -= mat[0][0] * offset.x / math::length(float3(mat[0][0], mat[1][0], mat[2][0]));
|
||||
result[2][1] -= mat[1][1] * offset.y / math::length(float3(mat[0][1], mat[1][1], mat[2][1]));
|
||||
}
|
||||
|
|
|
@ -179,7 +179,7 @@ std::string BLI_uniquename_cb(blender::FunctionRef<bool(blender::StringRef)> uni
|
|||
* \param name_offset: Offset of name within block structure
|
||||
* \param name_maxncpy: Maximum length of name area
|
||||
*/
|
||||
void BLI_uniquename(struct ListBase *list,
|
||||
void BLI_uniquename(const struct ListBase *list,
|
||||
void *vlink,
|
||||
const char *defname,
|
||||
char delim,
|
||||
|
|
|
@ -32,7 +32,9 @@ namespace blender {
|
|||
* The simplest possible vector set slot. It stores the index and state in a signed integer. If the
|
||||
* value is negative, it represents empty or occupied state. Otherwise it represents the index.
|
||||
*/
|
||||
template<typename Key> class SimpleVectorSetSlot {
|
||||
template<typename Key, typename IndexT = int64_t> class SimpleVectorSetSlot {
|
||||
static_assert(std::is_integral_v<IndexT> && std::is_signed_v<IndexT>);
|
||||
|
||||
private:
|
||||
#define s_is_empty -1
|
||||
#define s_is_removed -2
|
||||
|
@ -40,7 +42,7 @@ template<typename Key> class SimpleVectorSetSlot {
|
|||
/**
|
||||
* After the default constructor has run, the slot has to be in the empty state.
|
||||
*/
|
||||
int64_t state_ = s_is_empty;
|
||||
IndexT state_ = s_is_empty;
|
||||
|
||||
public:
|
||||
/**
|
||||
|
@ -62,7 +64,7 @@ template<typename Key> class SimpleVectorSetSlot {
|
|||
/**
|
||||
* Return the stored index. It is assumed that the slot is occupied.
|
||||
*/
|
||||
int64_t index() const
|
||||
IndexT index() const
|
||||
{
|
||||
BLI_assert(this->is_occupied());
|
||||
return state_;
|
||||
|
@ -88,7 +90,7 @@ template<typename Key> class SimpleVectorSetSlot {
|
|||
* Change the state of this slot from empty/removed to occupied. The hash can be used by other
|
||||
* slot implementations.
|
||||
*/
|
||||
void occupy(int64_t index, uint64_t /*hash*/)
|
||||
void occupy(IndexT index, uint64_t /*hash*/)
|
||||
{
|
||||
BLI_assert(!this->is_occupied());
|
||||
state_ = index;
|
||||
|
@ -98,7 +100,7 @@ template<typename Key> class SimpleVectorSetSlot {
|
|||
* The key has changed its position in the vector, so the index has to be updated. This method
|
||||
* can assume that the slot is currently occupied.
|
||||
*/
|
||||
void update_index(int64_t index)
|
||||
void update_index(IndexT index)
|
||||
{
|
||||
BLI_assert(this->is_occupied());
|
||||
state_ = index;
|
||||
|
@ -116,7 +118,7 @@ template<typename Key> class SimpleVectorSetSlot {
|
|||
/**
|
||||
* Return true if this slot is currently occupied and its corresponding key has the given index.
|
||||
*/
|
||||
bool has_index(int64_t index) const
|
||||
bool has_index(IndexT index) const
|
||||
{
|
||||
return state_ == index;
|
||||
}
|
||||
|
|
|
@ -1204,8 +1204,8 @@ static int delete_soft(const char *file, const char **error_message)
|
|||
const char *args[5];
|
||||
const char *process_failed;
|
||||
|
||||
char *xdg_current_desktop = getenv("XDG_CURRENT_DESKTOP");
|
||||
char *xdg_session_desktop = getenv("XDG_SESSION_DESKTOP");
|
||||
const char *xdg_current_desktop = getenv("XDG_CURRENT_DESKTOP");
|
||||
const char *xdg_session_desktop = getenv("XDG_SESSION_DESKTOP");
|
||||
|
||||
if ((xdg_current_desktop != nullptr && STREQ(xdg_current_desktop, "KDE")) ||
|
||||
(xdg_session_desktop != nullptr && STREQ(xdg_session_desktop, "KDE")))
|
||||
|
|
|
@ -53,11 +53,10 @@ bool BLI_tridiagonal_solve(
|
|||
|
||||
size_t bytes = sizeof(double) * (uint)count;
|
||||
double *c1 = (double *)MEM_mallocN(bytes * 2, "tridiagonal_c1d1");
|
||||
double *d1 = c1 + count;
|
||||
|
||||
if (!c1) {
|
||||
return false;
|
||||
}
|
||||
double *d1 = c1 + count;
|
||||
|
||||
int i;
|
||||
double c_prev, d_prev, x_prev;
|
||||
|
@ -120,11 +119,10 @@ bool BLI_tridiagonal_solve_cyclic(
|
|||
|
||||
size_t bytes = sizeof(float) * (uint)count;
|
||||
float *tmp = (float *)MEM_mallocN(bytes * 2, "tridiagonal_ex");
|
||||
float *b2 = tmp + count;
|
||||
|
||||
if (!tmp) {
|
||||
return false;
|
||||
}
|
||||
float *b2 = tmp + count;
|
||||
|
||||
/* Prepare the non-cyclic system; relies on tridiagonal_solve ignoring values. */
|
||||
memcpy(b2, b, bytes);
|
||||
|
|
|
@ -1397,7 +1397,7 @@ static bool is_pwn(const IMesh &tm, const TriMeshTopology &tmtopo)
|
|||
* the dummy triangle lies, then finding which cell is between
|
||||
* the two triangles on either side of the dummy.
|
||||
*/
|
||||
static int find_cell_for_point_near_edge(mpq3 p,
|
||||
static int find_cell_for_point_near_edge(const mpq3 &p,
|
||||
const Edge &e,
|
||||
const IMesh &tm,
|
||||
const TriMeshTopology &tmtopo,
|
||||
|
@ -3254,7 +3254,7 @@ static void do_dissolve(FaceMergeState *fms)
|
|||
* \note it is possible that some of the triangles in \a tris have reversed orientation
|
||||
* to the rest, so we have to handle the two cases separately.
|
||||
*/
|
||||
static Vector<Face *> merge_tris_for_face(Vector<int> tris,
|
||||
static Vector<Face *> merge_tris_for_face(const Vector<int> &tris,
|
||||
const IMesh &tm,
|
||||
const IMesh &imesh_in,
|
||||
IMeshArena *arena)
|
||||
|
|
|
@ -468,7 +468,10 @@ std::string BLI_uniquename_cb(blender::FunctionRef<bool(blender::StringRef)> uni
|
|||
* \param name_offset: should be calculated using `offsetof(structname, membername)`
|
||||
* macro from `stddef.h`
|
||||
*/
|
||||
static bool uniquename_find_dupe(ListBase *list, void *vlink, const char *name, int name_offset)
|
||||
static bool uniquename_find_dupe(const ListBase *list,
|
||||
void *vlink,
|
||||
const char *name,
|
||||
int name_offset)
|
||||
{
|
||||
for (Link *link = static_cast<Link *>(list->first); link; link = link->next) {
|
||||
if (link != vlink) {
|
||||
|
@ -483,7 +486,7 @@ static bool uniquename_find_dupe(ListBase *list, void *vlink, const char *name,
|
|||
}
|
||||
|
||||
struct UniqueNameCheckData {
|
||||
ListBase *lb;
|
||||
const ListBase *lb;
|
||||
void *vlink;
|
||||
int name_offset;
|
||||
};
|
||||
|
@ -495,7 +498,7 @@ static bool uniquename_unique_check(void *arg, const char *name)
|
|||
return uniquename_find_dupe(data->lb, data->vlink, name, data->name_offset);
|
||||
}
|
||||
|
||||
void BLI_uniquename(ListBase *list,
|
||||
void BLI_uniquename(const ListBase *list,
|
||||
void *vlink,
|
||||
const char *defname,
|
||||
char delim,
|
||||
|
|
|
@ -140,7 +140,7 @@ char *BLI_cpu_brand_string(void)
|
|||
return brand;
|
||||
}
|
||||
#else
|
||||
// No CPUID on ARM64, so we pull from the registry (on Windows) instead
|
||||
/* No CPUID on ARM64, so we pull from the registry (on Windows) instead. */
|
||||
DWORD vendorIdentifierLength = 255;
|
||||
char vendorIdentifier[255];
|
||||
if (RegGetValueA(HKEY_LOCAL_MACHINE,
|
||||
|
|
|
@ -3145,7 +3145,7 @@ void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain)
|
|||
}
|
||||
}
|
||||
|
||||
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 13)) {
|
||||
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 14)) {
|
||||
update_paint_modes_for_brush_assets(*bmain);
|
||||
}
|
||||
|
||||
|
|
|
@ -140,6 +140,16 @@ static void do_versions_theme(const UserDef *userdef, bTheme *btheme)
|
|||
FROM_DEFAULT_V4_UCHAR(space_view3d.face_mode_select);
|
||||
}
|
||||
|
||||
if (!USER_VERSION_ATLEAST(402, 13)) {
|
||||
FROM_DEFAULT_V4_UCHAR(space_text.hilite);
|
||||
FROM_DEFAULT_V4_UCHAR(space_console.console_cursor);
|
||||
}
|
||||
|
||||
if (!USER_VERSION_ATLEAST(402, 14)) {
|
||||
BLI_uniquename(
|
||||
&userdef->themes, btheme, "Theme", '.', offsetof(bTheme, name), sizeof(btheme->name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Always bump subversion in BKE_blender_version.h when adding versioning
|
||||
* code here, and wrap it inside a USER_VERSION_ATLEAST check.
|
||||
|
|
|
@ -691,13 +691,13 @@ static void SMAABlendingWeightCalculationVS(float2 texcoord,
|
|||
{
|
||||
pixcoord = texcoord * float2(size);
|
||||
|
||||
// We will use these offsets for the searches later on (see @PSEUDO_GATHER4):
|
||||
/* We will use these offsets for the searches later on (see @PSEUDO_GATHER4): */
|
||||
offset[0] = float4(texcoord.xy(), texcoord.xy()) +
|
||||
float4(-0.25f, -0.125f, 1.25f, -0.125f) / float4(size, size);
|
||||
offset[1] = float4(texcoord.xy(), texcoord.xy()) +
|
||||
float4(-0.125f, -0.25f, -0.125f, 1.25f) / float4(size, size);
|
||||
|
||||
// And these for the searches, they indicate the ends of the loops:
|
||||
/* And these for the searches, they indicate the ends of the loops: */
|
||||
offset[2] = float4(offset[0].x, offset[0].z, offset[1].y, offset[1].w) +
|
||||
(float4(-2.0f, 2.0f, -2.0f, 2.0f) * float(SMAA_MAX_SEARCH_STEPS)) /
|
||||
float4(float2(size.x), float2(size.y));
|
||||
|
@ -710,7 +710,7 @@ static void SMAANeighborhoodBlendingVS(float2 texcoord, int2 size, float4 &offse
|
|||
{
|
||||
offset = float4(texcoord, texcoord) + float4(1.0f, 0.0f, 0.0f, 1.0f) / float4(size, size);
|
||||
}
|
||||
#endif // SMAA_INCLUDE_VS
|
||||
#endif /* SMAA_INCLUDE_VS */
|
||||
|
||||
/**
|
||||
* Luma Edge Detection
|
||||
|
@ -732,11 +732,11 @@ static float2 SMAALumaEdgeDetectionPS(float2 texcoord,
|
|||
float2 threshold = SMAACalculatePredicatedThreshold(
|
||||
texcoord, offset, SMAATexturePass2D(predicationTex));
|
||||
#else
|
||||
// Calculate the threshold:
|
||||
/* Calculate the threshold: */
|
||||
float2 threshold = float2(edge_threshold, edge_threshold);
|
||||
#endif
|
||||
|
||||
// Calculate lumas:
|
||||
/* Calculate lumas: */
|
||||
// float4 weights = float4(0.2126, 0.7152, 0.0722, 0.0);
|
||||
float4 weights = float4(luminance_coefficients, 0.0f);
|
||||
float L = math::dot(SMAASamplePoint(colorTex, texcoord), weights);
|
||||
|
@ -744,40 +744,40 @@ static float2 SMAALumaEdgeDetectionPS(float2 texcoord,
|
|||
float Lleft = math::dot(SMAASamplePoint(colorTex, offset[0].xy()), weights);
|
||||
float Ltop = math::dot(SMAASamplePoint(colorTex, offset[0].zw()), weights);
|
||||
|
||||
// We do the usual threshold:
|
||||
/* We do the usual threshold: */
|
||||
float4 delta;
|
||||
float2 delta_left_top = math::abs(L - float2(Lleft, Ltop));
|
||||
delta.x = delta_left_top.x;
|
||||
delta.y = delta_left_top.y;
|
||||
float2 edges = math::step(threshold, delta.xy());
|
||||
|
||||
// Then return early if there is no edge:
|
||||
/* Then return early if there is no edge: */
|
||||
if (math::dot(edges, float2(1.0f, 1.0f)) == 0.0f) {
|
||||
return float2(0.0f);
|
||||
}
|
||||
|
||||
// Calculate right and bottom deltas:
|
||||
/* Calculate right and bottom deltas: */
|
||||
float Lright = math::dot(SMAASamplePoint(colorTex, offset[1].xy()), weights);
|
||||
float Lbottom = math::dot(SMAASamplePoint(colorTex, offset[1].zw()), weights);
|
||||
float2 delta_right_bottom = math::abs(L - float2(Lright, Lbottom));
|
||||
delta.z = delta_right_bottom.x;
|
||||
delta.w = delta_right_bottom.y;
|
||||
|
||||
// Calculate the maximum delta in the direct neighborhood:
|
||||
/* Calculate the maximum delta in the direct neighborhood: */
|
||||
float2 maxDelta = math::max(delta.xy(), delta.zw());
|
||||
|
||||
// Calculate left-left and top-top deltas:
|
||||
/* Calculate left-left and top-top deltas: */
|
||||
float Lleftleft = math::dot(SMAASamplePoint(colorTex, offset[2].xy()), weights);
|
||||
float Ltoptop = math::dot(SMAASamplePoint(colorTex, offset[2].zw()), weights);
|
||||
float2 delta_left_left_top_top = math::abs(float2(Lleft, Ltop) - float2(Lleftleft, Ltoptop));
|
||||
delta.z = delta_left_left_top_top.x;
|
||||
delta.w = delta_left_left_top_top.y;
|
||||
|
||||
// Calculate the final maximum delta:
|
||||
/* Calculate the final maximum delta: */
|
||||
maxDelta = math::max(maxDelta.xy(), delta.zw());
|
||||
float finalDelta = math::max(maxDelta.x, maxDelta.y);
|
||||
|
||||
// Local contrast adaptation:
|
||||
/* Local contrast adaptation: */
|
||||
edges *= math::step(finalDelta, local_contrast_adaptation_factor * delta.xy());
|
||||
|
||||
return edges;
|
||||
|
@ -793,19 +793,20 @@ static float2 SMAALumaEdgeDetectionPS(float2 texcoord,
|
|||
*/
|
||||
static float2 SMAADecodeDiagBilinearAccess(float2 e)
|
||||
{
|
||||
// Bilinear access for fetching 'e' have a 0.25 offset, and we are
|
||||
// interested in the R and G edges:
|
||||
//
|
||||
// +---G---+-------+
|
||||
// | x o R x |
|
||||
// +-------+-------+
|
||||
//
|
||||
// Then, if one of these edge is enabled:
|
||||
// Red: (0.75 * X + 0.25 * 1) => 0.25 or 1.0
|
||||
// Green: (0.75 * 1 + 0.25 * X) => 0.75 or 1.0
|
||||
//
|
||||
// This function will unpack the values (mad + mul + round):
|
||||
// wolframalpha.com: round(x * abs(5 * x - 5 * 0.75)) plot 0 to 1
|
||||
/* Bilinear access for fetching 'e' have a 0.25 offset, and we are
|
||||
* interested in the R and G edges:
|
||||
*
|
||||
* +---G---+-------+
|
||||
* | x o R x |
|
||||
* +-------+-------+
|
||||
*
|
||||
* Then, if one of these edge is enabled:
|
||||
* Red: `(0.75 * X + 0.25 * 1) => 0.25 or 1.0`
|
||||
* Green: `(0.75 * 1 + 0.25 * X) => 0.75 or 1.0`
|
||||
*
|
||||
* This function will unpack the values `(mad + mul + round)`:
|
||||
* wolframalpha.com: `round(x * abs(5 * x - 5 * 0.75))` plot 0 to 1
|
||||
*/
|
||||
e.x = e.x * math::abs(5.0f * e.x - 5.0f * 0.75f);
|
||||
return math::round(e);
|
||||
}
|
||||
|
@ -840,7 +841,7 @@ static float2 SMAASearchDiag2(
|
|||
SMAATexture2D(edgesTex), float2 texcoord, float2 dir, int2 size, float2 &e)
|
||||
{
|
||||
float4 coord = float4(texcoord, -1.0f, 1.0f);
|
||||
coord.x += 0.25f / size.x; // See @SearchDiag2Optimization
|
||||
coord.x += 0.25f / size.x; /* See @SearchDiag2Optimization */
|
||||
float3 t = float3(1.0f / float2(size), 1.0f);
|
||||
while (coord.z < float(SMAA_MAX_SEARCH_STEPS_DIAG - 1) && coord.w > 0.9f) {
|
||||
float3 increment = mad(t, float3(dir, 1.0f), coord.xyz());
|
||||
|
@ -848,12 +849,12 @@ static float2 SMAASearchDiag2(
|
|||
coord.y = increment.y;
|
||||
coord.z = increment.z;
|
||||
|
||||
// @SearchDiag2Optimization
|
||||
// Fetch both edges at once using bilinear filtering:
|
||||
/* @SearchDiag2Optimization */
|
||||
/* Fetch both edges at once using bilinear filtering: */
|
||||
e = SMAASampleLevelZero(edgesTex, coord.xy()).xy();
|
||||
e = SMAADecodeDiagBilinearAccess(e);
|
||||
|
||||
// Non-optimized version:
|
||||
/* Non-optimized version: */
|
||||
// e.g = SMAASampleLevelZero(edgesTex, coord.xy).g;
|
||||
// e.r = SMAASampleLevelZeroOffset(edgesTex, coord.xy, int2(1, 0), size).r;
|
||||
|
||||
|
@ -871,16 +872,16 @@ static float2 SMAAAreaDiag(SMAATexture2D(areaTex), float2 dist, float2 e, float
|
|||
float2 texcoord = mad(
|
||||
float2(SMAA_AREATEX_MAX_DISTANCE_DIAG, SMAA_AREATEX_MAX_DISTANCE_DIAG), e, dist);
|
||||
|
||||
// We do a scale and bias for mapping to texel space:
|
||||
/* We do a scale and bias for mapping to texel space: */
|
||||
texcoord = mad(SMAA_AREATEX_PIXEL_SIZE, texcoord, 0.5f * SMAA_AREATEX_PIXEL_SIZE);
|
||||
|
||||
// Diagonal areas are on the second half of the texture:
|
||||
/* Diagonal areas are on the second half of the texture: */
|
||||
texcoord.x += 0.5f;
|
||||
|
||||
// Move to proper place, according to the subpixel offset:
|
||||
/* Move to proper place, according to the subpixel offset: */
|
||||
texcoord.y += SMAA_AREATEX_SUBTEX_SIZE * offset;
|
||||
|
||||
// Do it!
|
||||
/* Do it! */
|
||||
return SMAA_AREATEX_SELECT(SMAASampleLevelZero(areaTex, texcoord));
|
||||
}
|
||||
|
||||
|
@ -896,7 +897,7 @@ static float2 SMAACalculateDiagWeights(SMAATexture2D(edgesTex),
|
|||
{
|
||||
float2 weights = float2(0.0f, 0.0f);
|
||||
|
||||
// Search for the line ends:
|
||||
/* Search for the line ends: */
|
||||
float4 d;
|
||||
float2 end;
|
||||
if (e.x > 0.0f) {
|
||||
|
@ -916,8 +917,8 @@ static float2 SMAACalculateDiagWeights(SMAATexture2D(edgesTex),
|
|||
d.w = positive_diagonal.y;
|
||||
|
||||
SMAA_BRANCH
|
||||
if (d.x + d.y > 2.0f) { // d.x + d.y + 1 > 3
|
||||
// Fetch the crossing edges:
|
||||
if (d.x + d.y > 2.0f) { /* `d.x + d.y + 1 > 3`. */
|
||||
/* Fetch the crossing edges: */
|
||||
float4 coords = float4(texcoord, texcoord) +
|
||||
float4(-d.x + 0.25f, d.x, d.y, -d.y - 0.25f) / float4(size, size);
|
||||
float4 c;
|
||||
|
@ -933,7 +934,7 @@ static float2 SMAACalculateDiagWeights(SMAATexture2D(edgesTex),
|
|||
c.w = decoded_access.z;
|
||||
c.z = decoded_access.w;
|
||||
|
||||
// Non-optimized version:
|
||||
/* Non-optimized version: */
|
||||
// float4 coords = mad(float4(-d.x, d.x, d.y, -d.y), SMAA_RT_METRICS.xyxy, texcoord.xyxy);
|
||||
// float4 c;
|
||||
// c.x = SMAASampleLevelZeroOffset(edgesTex, coords.xy, int2(-1, 0), size).g;
|
||||
|
@ -941,17 +942,17 @@ static float2 SMAACalculateDiagWeights(SMAATexture2D(edgesTex),
|
|||
// c.z = SMAASampleLevelZeroOffset(edgesTex, coords.zw, int2( 1, 0), size).g;
|
||||
// c.w = SMAASampleLevelZeroOffset(edgesTex, coords.zw, int2( 1, -1), size).r;
|
||||
|
||||
// Merge crossing edges at each side into a single value:
|
||||
/* Merge crossing edges at each side into a single value: */
|
||||
float2 cc = mad(float2(2.0f, 2.0f), float2(c.x, c.z), float2(c.y, c.w));
|
||||
|
||||
// Remove the crossing edge if we didn't found the end of the line:
|
||||
/* Remove the crossing edge if we didn't found the end of the line: */
|
||||
SMAAMovc(math::step(0.9f, d.zw()), cc, float2(0.0f, 0.0f));
|
||||
|
||||
// Fetch the areas for this line:
|
||||
/* Fetch the areas for this line: */
|
||||
weights += SMAAAreaDiag(SMAATexturePass2D(areaTex), d.xy(), cc, subsampleIndices.z);
|
||||
}
|
||||
|
||||
// Search for the line ends:
|
||||
/* Search for the line ends: */
|
||||
float2 negative_diagonal = SMAASearchDiag2(
|
||||
SMAATexturePass2D(edgesTex), texcoord, float2(-1.0f, -1.0f), size, end);
|
||||
d.x = negative_diagonal.x;
|
||||
|
@ -969,8 +970,8 @@ static float2 SMAACalculateDiagWeights(SMAATexture2D(edgesTex),
|
|||
}
|
||||
|
||||
SMAA_BRANCH
|
||||
if (d.x + d.y > 2.0f) { // d.x + d.y + 1 > 3
|
||||
// Fetch the crossing edges:
|
||||
if (d.x + d.y > 2.0f) { /* `d.x + d.y + 1 > 3` */
|
||||
/* Fetch the crossing edges: */
|
||||
float4 coords = float4(texcoord, texcoord) + float4(-d.x, -d.x, d.y, d.y) / float4(size, size);
|
||||
float4 c;
|
||||
c.x = SMAASampleLevelZeroOffset(edgesTex, coords.xy(), int2(-1, 0), size).y;
|
||||
|
@ -980,10 +981,10 @@ static float2 SMAACalculateDiagWeights(SMAATexture2D(edgesTex),
|
|||
c.w = left_edge.x;
|
||||
float2 cc = mad(float2(2.0f, 2.0f), float2(c.x, c.z), float2(c.y, c.w));
|
||||
|
||||
// Remove the crossing edge if we didn't found the end of the line:
|
||||
/* Remove the crossing edge if we didn't found the end of the line: */
|
||||
SMAAMovc(math::step(0.9f, d.zw()), cc, float2(0.0f, 0.0f));
|
||||
|
||||
// Fetch the areas for this line:
|
||||
/* Fetch the areas for this line: */
|
||||
float2 area = SMAAAreaDiag(SMAATexturePass2D(areaTex), d.xy(), cc, subsampleIndices.w).xy();
|
||||
weights.x += area.y;
|
||||
weights.y += area.x;
|
||||
|
@ -1004,21 +1005,21 @@ static float2 SMAACalculateDiagWeights(SMAATexture2D(edgesTex),
|
|||
*/
|
||||
static float SMAASearchLength(SMAATexture2D(searchTex), float2 e, float offset)
|
||||
{
|
||||
// The texture is flipped vertically, with left and right cases taking half
|
||||
// of the space horizontally:
|
||||
/* The texture is flipped vertically, with left and right cases taking half
|
||||
* of the space horizontally: */
|
||||
float2 scale = SMAA_SEARCHTEX_SIZE * float2(0.5f, -1.0f);
|
||||
float2 bias = SMAA_SEARCHTEX_SIZE * float2(offset, 1.0f);
|
||||
|
||||
// Scale and bias to access texel centers:
|
||||
/* Scale and bias to access texel centers: */
|
||||
scale += float2(-1.0f, 1.0f);
|
||||
bias += float2(0.5f, -0.5f);
|
||||
|
||||
// Convert from pixel coordinates to texcoords:
|
||||
// (We use SMAA_SEARCHTEX_PACKED_SIZE because the texture is cropped)
|
||||
/* Convert from pixel coordinates to texcoords:
|
||||
* (We use SMAA_SEARCHTEX_PACKED_SIZE because the texture is cropped). */
|
||||
scale *= 1.0f / SMAA_SEARCHTEX_PACKED_SIZE;
|
||||
bias *= 1.0f / SMAA_SEARCHTEX_PACKED_SIZE;
|
||||
|
||||
// Lookup the search texture:
|
||||
/* Lookup the search texture: */
|
||||
return SMAA_SEARCHTEX_SELECT(SMAASampleLevelZero(searchTex, mad(scale, e, bias)));
|
||||
}
|
||||
|
||||
|
@ -1036,8 +1037,8 @@ static float SMAASearchXLeft(
|
|||
* which edges are active from the four fetched ones.
|
||||
*/
|
||||
float2 e = float2(0.0f, 1.0f);
|
||||
while (texcoord.x > end && e.y > 0.8281f && // Is there some edge not activated?
|
||||
e.x == 0.0f) // Or is there a crossing edge that breaks the line?
|
||||
while (texcoord.x > end && e.y > 0.8281f && /* Is there some edge not activated? */
|
||||
e.x == 0.0f) /* Or is there a crossing edge that breaks the line? */
|
||||
{
|
||||
e = SMAASampleLevelZero(edgesTex, texcoord).xy();
|
||||
texcoord = texcoord - float2(2.0f, 0.0f) / float2(size);
|
||||
|
@ -1047,26 +1048,26 @@ static float SMAASearchXLeft(
|
|||
-(255.0f / 127.0f), SMAASearchLength(SMAATexturePass2D(searchTex), e, 0.0f), 3.25f);
|
||||
return texcoord.x + offset / size.x;
|
||||
|
||||
// Non-optimized version:
|
||||
// We correct the previous (-0.25, -0.125) offset we applied:
|
||||
/* Non-optimized version:
|
||||
* We correct the previous (-0.25, -0.125) offset we applied: */
|
||||
// texcoord.x += 0.25 * SMAA_RT_METRICS.x;
|
||||
|
||||
// The searches are bias by 1, so adjust the coords accordingly:
|
||||
/* The searches are bias by 1, so adjust the coords accordingly: */
|
||||
// texcoord.x += SMAA_RT_METRICS.x;
|
||||
|
||||
// Disambiguate the length added by the last step:
|
||||
// texcoord.x += 2.0 * SMAA_RT_METRICS.x; // Undo last step
|
||||
/* Disambiguate the length added by the last step: */
|
||||
// texcoord.x += 2.0 * SMAA_RT_METRICS.x; /* Undo last step. */
|
||||
// texcoord.x -= SMAA_RT_METRICS.x * (255.0 / 127.0) *
|
||||
// SMAASearchLength(SMAATexturePass2D(searchTex), e, 0.0); return mad(SMAA_RT_METRICS.x, offset,
|
||||
// texcoord.x);
|
||||
// SMAASearchLength(SMAATexturePass2D(searchTex), e, 0.0);
|
||||
// return mad(SMAA_RT_METRICS.x, offset, texcoord.x);
|
||||
}
|
||||
|
||||
static float SMAASearchXRight(
|
||||
SMAATexture2D(edgesTex), SMAATexture2D(searchTex), float2 texcoord, float end, int2 size)
|
||||
{
|
||||
float2 e = float2(0.0f, 1.0f);
|
||||
while (texcoord.x < end && e.y > 0.8281f && // Is there some edge not activated?
|
||||
e.x == 0.0f) // Or is there a crossing edge that breaks the line?
|
||||
while (texcoord.x < end && e.y > 0.8281f && /* Is there some edge not activated? */
|
||||
e.x == 0.0f) /* Or is there a crossing edge that breaks the line? */
|
||||
{
|
||||
e = SMAASampleLevelZero(edgesTex, texcoord).xy();
|
||||
texcoord = texcoord + float2(2.0f, 0.0f) / float2(size);
|
||||
|
@ -1080,8 +1081,8 @@ static float SMAASearchYUp(
|
|||
SMAATexture2D(edgesTex), SMAATexture2D(searchTex), float2 texcoord, float end, int2 size)
|
||||
{
|
||||
float2 e = float2(1.0f, 0.0f);
|
||||
while (texcoord.y > end && e.x > 0.8281f && // Is there some edge not activated?
|
||||
e.y == 0.0f) // Or is there a crossing edge that breaks the line?
|
||||
while (texcoord.y > end && e.x > 0.8281f && /* Is there some edge not activated? */
|
||||
e.y == 0.0f) /* Or is there a crossing edge that breaks the line? */
|
||||
{
|
||||
e = SMAASampleLevelZero(edgesTex, texcoord).xy();
|
||||
texcoord = texcoord - float2(0.0f, 2.0f) / float2(size);
|
||||
|
@ -1097,8 +1098,8 @@ static float SMAASearchYDown(
|
|||
SMAATexture2D(edgesTex), SMAATexture2D(searchTex), float2 texcoord, float end, int2 size)
|
||||
{
|
||||
float2 e = float2(1.0f, 0.0f);
|
||||
while (texcoord.y < end && e.x > 0.8281f && // Is there some edge not activated?
|
||||
e.y == 0.0f) // Or is there a crossing edge that breaks the line?
|
||||
while (texcoord.y < end && e.x > 0.8281f && /* Is there some edge not activated? */
|
||||
e.y == 0.0f) /* Or is there a crossing edge that breaks the line? */
|
||||
{
|
||||
e = SMAASampleLevelZero(edgesTex, texcoord).xy();
|
||||
texcoord = texcoord + float2(0.0f, 2.0f) / float2(size);
|
||||
|
@ -1116,18 +1117,18 @@ static float SMAASearchYDown(
|
|||
*/
|
||||
static float2 SMAAArea(SMAATexture2D(areaTex), float2 dist, float e1, float e2, float offset)
|
||||
{
|
||||
// Rounding prevents precision errors of bilinear filtering:
|
||||
/* Rounding prevents precision errors of bilinear filtering: */
|
||||
float2 texcoord = mad(float2(SMAA_AREATEX_MAX_DISTANCE, SMAA_AREATEX_MAX_DISTANCE),
|
||||
math::round(4.0f * float2(e1, e2)),
|
||||
dist);
|
||||
|
||||
// We do a scale and bias for mapping to texel space:
|
||||
/* We do a scale and bias for mapping to texel space: */
|
||||
texcoord = mad(SMAA_AREATEX_PIXEL_SIZE, texcoord, 0.5f * SMAA_AREATEX_PIXEL_SIZE);
|
||||
|
||||
// Move to proper place, according to the subpixel offset:
|
||||
/* Move to proper place, according to the subpixel offset: */
|
||||
texcoord.y = mad(SMAA_AREATEX_SUBTEX_SIZE, offset, texcoord.y);
|
||||
|
||||
// Do it!
|
||||
/* Do it! */
|
||||
return SMAA_AREATEX_SELECT(SMAASampleLevelZero(areaTex, texcoord));
|
||||
}
|
||||
|
||||
|
@ -1145,7 +1146,7 @@ static void SMAADetectHorizontalCornerPattern(SMAATexture2D(edgesTex),
|
|||
float2 leftRight = math::step(d, float2(d.y, d.x));
|
||||
float2 rounding = (1.0f - corner_rounding / 100.0f) * leftRight;
|
||||
|
||||
rounding /= leftRight.x + leftRight.y; // Reduce blending for pixels in the center of a line.
|
||||
rounding /= leftRight.x + leftRight.y; /* Reduce blending for pixels in the center of a line. */
|
||||
|
||||
float2 factor = float2(1.0f, 1.0f);
|
||||
factor.x -= rounding.x * SMAASampleLevelZeroOffset(edgesTex, texcoord.xy(), int2(0, 1), size).x;
|
||||
|
@ -1192,16 +1193,17 @@ static float4 SMAABlendingWeightCalculationPS(float2 texcoord,
|
|||
float4 subsampleIndices,
|
||||
int2 size,
|
||||
int corner_rounding)
|
||||
{ // Just pass zero for SMAA 1x, see @SUBSAMPLE_INDICES.
|
||||
{
|
||||
/* Just pass zero for SMAA 1x, see @SUBSAMPLE_INDICES. */
|
||||
float4 weights = float4(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
|
||||
float2 e = SMAASamplePoint(edgesTex, texcoord).xy();
|
||||
|
||||
SMAA_BRANCH
|
||||
if (e.y > 0.0f) { // Edge at north
|
||||
if (e.y > 0.0f) { /* Edge at north. */
|
||||
#if !defined(SMAA_DISABLE_DIAG_DETECTION)
|
||||
// Diagonals have both north and west edges, so searching for them in
|
||||
// one of the boundaries is enough.
|
||||
/* Diagonals have both north and west edges, so searching for them in
|
||||
* one of the boundaries is enough. */
|
||||
float2 diagonal_weights = SMAACalculateDiagWeights(SMAATexturePass2D(edgesTex),
|
||||
SMAATexturePass2D(areaTex),
|
||||
texcoord,
|
||||
|
@ -1212,15 +1214,15 @@ static float4 SMAABlendingWeightCalculationPS(float2 texcoord,
|
|||
weights.x = diagonal_weights.x;
|
||||
weights.y = diagonal_weights.y;
|
||||
|
||||
// We give priority to diagonals, so if we find a diagonal we skip
|
||||
// horizontal/vertical processing.
|
||||
/* We give priority to diagonals, so if we find a diagonal we skip
|
||||
* horizontal/vertical processing. */
|
||||
SMAA_BRANCH
|
||||
if (weights.x == -weights.y) { // weights.x + weights.y == 0.0
|
||||
if (weights.x == -weights.y) { /* `weights.x + weights.y == 0.0` */
|
||||
#endif
|
||||
|
||||
float2 d;
|
||||
|
||||
// Find the distance to the left:
|
||||
/* Find the distance to the left: */
|
||||
float3 coords;
|
||||
coords.x = SMAASearchXLeft(SMAATexturePass2D(edgesTex),
|
||||
SMAATexturePass2D(searchTex),
|
||||
|
@ -1231,12 +1233,12 @@ static float4 SMAABlendingWeightCalculationPS(float2 texcoord,
|
|||
offset[1].y; // offset[1].y = texcoord.y - 0.25 * SMAA_RT_METRICS.y (@CROSSING_OFFSET)
|
||||
d.x = coords.x;
|
||||
|
||||
// Now fetch the left crossing edges, two at a time using bilinear
|
||||
// filtering. Sampling at -0.25 (see @CROSSING_OFFSET) enables to
|
||||
// discern what value each edge has:
|
||||
/* Now fetch the left crossing edges, two at a time using bilinear
|
||||
* filtering. Sampling at -0.25 (see @CROSSING_OFFSET) enables to
|
||||
* discern what value each edge has: */
|
||||
float e1 = SMAASampleLevelZero(edgesTex, coords.xy()).x;
|
||||
|
||||
// Find the distance to the right:
|
||||
/* Find the distance to the right: */
|
||||
coords.z = SMAASearchXRight(SMAATexturePass2D(edgesTex),
|
||||
SMAATexturePass2D(searchTex),
|
||||
offset[0].zw(),
|
||||
|
@ -1244,25 +1246,23 @@ static float4 SMAABlendingWeightCalculationPS(float2 texcoord,
|
|||
size);
|
||||
d.y = coords.z;
|
||||
|
||||
// We want the distances to be in pixel units (doing this here allows
|
||||
// better interleaving of arithmetic and memory accesses):
|
||||
/* We want the distances to be in pixel units (doing this here allows
|
||||
* better interleaving of arithmetic and memory accesses): */
|
||||
d = math::abs(math::round(mad(float2(size.x), d, -float2(pixcoord.x))));
|
||||
|
||||
// SMAAArea below needs a sqrt, as the areas texture is compressed
|
||||
// quadratically:
|
||||
/* SMAAArea below needs a sqrt, as the areas texture is compressed quadratically: */
|
||||
float2 sqrt_d = math::sqrt(d);
|
||||
|
||||
// Fetch the right crossing edges:
|
||||
/* Fetch the right crossing edges: */
|
||||
float e2 =
|
||||
SMAASampleLevelZeroOffset(edgesTex, float2(coords.z, coords.y), int2(1, 0), size).x;
|
||||
|
||||
// Ok, we know how this pattern looks like, now it is time for getting
|
||||
// the actual area:
|
||||
/* Ok, we know how this pattern looks like, now it is time for getting the actual area: */
|
||||
float2 area = SMAAArea(SMAATexturePass2D(areaTex), sqrt_d, e1, e2, subsampleIndices.y);
|
||||
weights.x = area.x;
|
||||
weights.y = area.y;
|
||||
|
||||
// Fix corners:
|
||||
/* Fix corners: */
|
||||
coords.y = texcoord.y;
|
||||
|
||||
float2 corner_weight = weights.xy();
|
||||
|
@ -1278,15 +1278,15 @@ static float4 SMAABlendingWeightCalculationPS(float2 texcoord,
|
|||
#if !defined(SMAA_DISABLE_DIAG_DETECTION)
|
||||
}
|
||||
else
|
||||
e.x = 0.0f; // Skip vertical processing.
|
||||
e.x = 0.0f; /* Skip vertical processing. */
|
||||
#endif
|
||||
}
|
||||
|
||||
SMAA_BRANCH
|
||||
if (e.x > 0.0f) { // Edge at west
|
||||
if (e.x > 0.0f) { /* Edge at west. */
|
||||
float2 d;
|
||||
|
||||
// Find the distance to the top:
|
||||
/* Find the distance to the top: */
|
||||
float3 coords;
|
||||
coords.y = SMAASearchYUp(SMAATexturePass2D(edgesTex),
|
||||
SMAATexturePass2D(searchTex),
|
||||
|
@ -1296,10 +1296,10 @@ static float4 SMAABlendingWeightCalculationPS(float2 texcoord,
|
|||
coords.x = offset[0].x; // offset[1].x = texcoord.x - 0.25 * SMAA_RT_METRICS.x;
|
||||
d.x = coords.y;
|
||||
|
||||
// Fetch the top crossing edges:
|
||||
/* Fetch the top crossing edges: */
|
||||
float e1 = SMAASampleLevelZero(edgesTex, coords.xy()).y;
|
||||
|
||||
// Find the distance to the bottom:
|
||||
/* Find the distance to the bottom: */
|
||||
coords.z = SMAASearchYDown(SMAATexturePass2D(edgesTex),
|
||||
SMAATexturePass2D(searchTex),
|
||||
offset[1].zw(),
|
||||
|
@ -1307,22 +1307,21 @@ static float4 SMAABlendingWeightCalculationPS(float2 texcoord,
|
|||
size);
|
||||
d.y = coords.z;
|
||||
|
||||
// We want the distances to be in pixel units:
|
||||
/* We want the distances to be in pixel units: */
|
||||
d = math::abs(math::round(mad(float2(size.y), d, -float2(pixcoord.y))));
|
||||
|
||||
// SMAAArea below needs a sqrt, as the areas texture is compressed
|
||||
// quadratically:
|
||||
/* SMAAArea below needs a sqrt, as the areas texture is compressed quadratically: */
|
||||
float2 sqrt_d = math::sqrt(d);
|
||||
|
||||
// Fetch the bottom crossing edges:
|
||||
/* Fetch the bottom crossing edges: */
|
||||
float e2 = SMAASampleLevelZeroOffset(edgesTex, float2(coords.x, coords.z), int2(0, 1), size).y;
|
||||
|
||||
// Get the area for this direction:
|
||||
/* Get the area for this direction: */
|
||||
float2 area = SMAAArea(SMAATexturePass2D(areaTex), sqrt_d, e1, e2, subsampleIndices.x);
|
||||
weights.z = area.x;
|
||||
weights.w = area.y;
|
||||
|
||||
// Fix corners:
|
||||
/* Fix corners: */
|
||||
coords.x = texcoord.x;
|
||||
|
||||
float2 corner_weight = weights.zw();
|
||||
|
@ -1351,14 +1350,14 @@ static float4 SMAANeighborhoodBlendingPS(float2 texcoord,
|
|||
#endif
|
||||
int2 size)
|
||||
{
|
||||
// Fetch the blending weights for current pixel:
|
||||
/* Fetch the blending weights for current pixel: */
|
||||
float4 a;
|
||||
a.x = SMAASample(blendTex, offset.xy()).w; // Right
|
||||
a.y = SMAASample(blendTex, offset.zw()).y; // Top
|
||||
a.z = SMAASample(blendTex, texcoord).z; // Left
|
||||
a.w = SMAASample(blendTex, texcoord).x; // Bottom
|
||||
|
||||
// Is there any blending weight with a value greater than 0.0?
|
||||
/* Is there any blending weight with a value greater than 0.0? */
|
||||
SMAA_BRANCH
|
||||
if (math::dot(a, float4(1.0f, 1.0f, 1.0f, 1.0f)) < 1e-5f) {
|
||||
float4 color = SMAASampleLevelZero(colorTex, texcoord);
|
||||
|
@ -1366,38 +1365,37 @@ static float4 SMAANeighborhoodBlendingPS(float2 texcoord,
|
|||
#if SMAA_REPROJECTION
|
||||
float2 velocity = SMAA_DECODE_VELOCITY(SMAASampleLevelZero(velocityTex, texcoord));
|
||||
|
||||
// Pack velocity into the alpha channel:
|
||||
/* Pack velocity into the alpha channel: */
|
||||
color.a = math::sqrt(5.0f * math::length(velocity));
|
||||
#endif
|
||||
|
||||
return color;
|
||||
}
|
||||
else {
|
||||
bool h = math::max(a.x, a.z) > math::max(a.y, a.w); // max(horizontal) > max(vertical)
|
||||
bool h = math::max(a.x, a.z) > math::max(a.y, a.w); /* `max(horizontal) > max(vertical)`. */
|
||||
|
||||
// Calculate the blending offsets:
|
||||
/* Calculate the blending offsets: */
|
||||
float4 blendingOffset = float4(0.0f, a.y, 0.0f, a.w);
|
||||
float2 blendingWeight = float2(a.y, a.w);
|
||||
SMAAMovc(float4(h), blendingOffset, float4(a.x, 0.0f, a.z, 0.0f));
|
||||
SMAAMovc(float2(h), blendingWeight, float2(a.x, a.z));
|
||||
blendingWeight /= math::dot(blendingWeight, float2(1.0f, 1.0f));
|
||||
|
||||
// Calculate the texture coordinates:
|
||||
/* Calculate the texture coordinates: */
|
||||
float4 blendingCoord = float4(texcoord, texcoord) + blendingOffset / float4(size, -size);
|
||||
|
||||
// We exploit bilinear filtering to mix current pixel with the chosen
|
||||
// neighbor:
|
||||
/* We exploit bilinear filtering to mix current pixel with the chosen neighbor: */
|
||||
float4 color = blendingWeight.x * SMAASampleLevelZero(colorTex, blendingCoord.xy());
|
||||
color += blendingWeight.y * SMAASampleLevelZero(colorTex, blendingCoord.zw());
|
||||
|
||||
#if SMAA_REPROJECTION
|
||||
// Antialias velocity for proper reprojection in a later stage:
|
||||
/* Antialias velocity for proper reprojection in a later stage: */
|
||||
float2 velocity = blendingWeight.x *
|
||||
SMAA_DECODE_VELOCITY(SMAASampleLevelZero(velocityTex, blendingCoord.xy()));
|
||||
velocity += blendingWeight.y *
|
||||
SMAA_DECODE_VELOCITY(SMAASampleLevelZero(velocityTex, blendingCoord.zw()));
|
||||
|
||||
// Pack velocity into the alpha channel:
|
||||
/* Pack velocity into the alpha channel: */
|
||||
color.a = math::sqrt(5.0f * math::length(velocity));
|
||||
#endif
|
||||
|
||||
|
|
|
@ -458,6 +458,9 @@ void Film::sync()
|
|||
accumulate_ps_.specialize_constant(sh, "samples_len", &data_.samples_len);
|
||||
accumulate_ps_.specialize_constant(sh, "use_reprojection", &use_reprojection_);
|
||||
accumulate_ps_.specialize_constant(sh, "scaling_factor", data_.scaling_factor);
|
||||
accumulate_ps_.specialize_constant(sh, "combined_id", &data_.combined_id);
|
||||
accumulate_ps_.specialize_constant(sh, "display_id", &data_.display_id);
|
||||
accumulate_ps_.specialize_constant(sh, "normal_id", &data_.normal_id);
|
||||
accumulate_ps_.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS);
|
||||
accumulate_ps_.shader_set(sh);
|
||||
accumulate_ps_.bind_resources(inst_.uniform_data);
|
||||
|
|
|
@ -278,8 +278,8 @@ class DeferredLayer : DeferredLayerBase {
|
|||
void render(View &main_view,
|
||||
View &render_view,
|
||||
Framebuffer &prepass_fb,
|
||||
Framebuffer &gbuffer_fb,
|
||||
Framebuffer &combined_fb,
|
||||
Framebuffer &gbuffer_fb,
|
||||
int2 extent,
|
||||
RayTraceBuffer &rt_buffer,
|
||||
bool is_first_pass);
|
||||
|
|
|
@ -53,6 +53,7 @@ void VolumeModule::init()
|
|||
data_.shadow_steps = (shadow_enabled) ? scene_eval->eevee.volumetric_shadow_samples : 0;
|
||||
|
||||
data_.light_clamp = scene_eval->eevee.volumetric_light_clamp;
|
||||
data_.light_clamp = (data_.light_clamp > 0.0) ? data_.light_clamp : 1e20;
|
||||
|
||||
use_reprojection_ = (scene_eval->eevee.flag & SCE_EEVEE_TAA_REPROJECTION) != 0;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#pragma BLENDER_REQUIRE(gpu_shader_utildefines_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(gpu_shader_math_vector_lib.glsl)
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name YCoCg
|
||||
* \{ */
|
||||
|
@ -55,15 +58,11 @@ vec3 colorspace_safe_color(vec3 c)
|
|||
/**
|
||||
* Clamp all components to the specified maximum and avoid color shifting.
|
||||
*/
|
||||
vec3 colorspace_brightness_clamp_max(vec3 color, float max_value)
|
||||
vec3 colorspace_brightness_clamp_max(vec3 color, float limit)
|
||||
{
|
||||
float luma = max(1e-8, max(max(color.r, color.g), color.b));
|
||||
if (luma < 1e-8) {
|
||||
return color;
|
||||
}
|
||||
return color * (1.0 - max(0.0, luma - max_value) / luma);
|
||||
return color * saturate(limit / max(1e-8, reduce_max(abs(color))));
|
||||
}
|
||||
vec4 colorspace_brightness_clamp_max(vec4 color, float max_value)
|
||||
vec4 colorspace_brightness_clamp_max(vec4 color, float limit)
|
||||
{
|
||||
return vec4(colorspace_brightness_clamp_max(color.rgb, max_value), color.a);
|
||||
return vec4(colorspace_brightness_clamp_max(color.rgb, limit), color.a);
|
||||
}
|
||||
|
|
|
@ -12,20 +12,19 @@ void main()
|
|||
if (uniform_buf.film.display_only) {
|
||||
out_depth = imageLoad(depth_img, texel_film).r;
|
||||
|
||||
if (uniform_buf.film.display_id == -1) {
|
||||
if (display_id == -1) {
|
||||
out_color = texelFetch(in_combined_tx, texel_film, 0);
|
||||
}
|
||||
else if (uniform_buf.film.display_storage_type == PASS_STORAGE_VALUE) {
|
||||
out_color.rgb =
|
||||
imageLoad(value_accum_img, ivec3(texel_film, uniform_buf.film.display_id)).rrr;
|
||||
out_color.rgb = imageLoad(value_accum_img, ivec3(texel_film, display_id)).rrr;
|
||||
out_color.a = 1.0;
|
||||
}
|
||||
else if (uniform_buf.film.display_storage_type == PASS_STORAGE_COLOR) {
|
||||
out_color = imageLoad(color_accum_img, ivec3(texel_film, uniform_buf.film.display_id));
|
||||
out_color = imageLoad(color_accum_img, ivec3(texel_film, display_id));
|
||||
}
|
||||
else /* PASS_STORAGE_CRYPTOMATTE */ {
|
||||
out_color = cryptomatte_false_color(
|
||||
imageLoad(cryptomatte_img, ivec3(texel_film, uniform_buf.film.display_id)).r);
|
||||
imageLoad(cryptomatte_img, ivec3(texel_film, display_id)).r);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -87,7 +87,7 @@ float film_weight_accumulation(ivec2 texel_film)
|
|||
/* TODO(fclem): Reference implementation, also needed for panoramic cameras. */
|
||||
if (scaling_factor > 1) {
|
||||
float weight = 0.0;
|
||||
for (int i = 0; i < uniform_buf.film.samples_len; i++) {
|
||||
for (int i = 0; i < samples_len; i++) {
|
||||
weight += film_sample_get(i, texel_film).weight;
|
||||
}
|
||||
return weight;
|
||||
|
@ -132,7 +132,7 @@ void film_sample_accum_mist(FilmSample samp, inout float accum)
|
|||
|
||||
void film_sample_accum_combined(FilmSample samp, inout vec4 accum, inout float weight_accum)
|
||||
{
|
||||
if (uniform_buf.film.combined_id == -1) {
|
||||
if (combined_id == -1) {
|
||||
return;
|
||||
}
|
||||
vec4 color = film_texelfetch_as_YCoCg_opacity(combined_tx, samp.texel);
|
||||
|
@ -436,7 +436,7 @@ float film_history_blend_factor(float velocity,
|
|||
void film_store_combined(
|
||||
FilmSample dst, ivec2 src_texel, vec4 color, float color_weight, inout vec4 display)
|
||||
{
|
||||
if (uniform_buf.film.combined_id == -1) {
|
||||
if (combined_id == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -499,7 +499,7 @@ void film_store_combined(
|
|||
color = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
}
|
||||
|
||||
if (uniform_buf.film.display_id == -1) {
|
||||
if (display_id == -1) {
|
||||
display = color;
|
||||
}
|
||||
imageStore(out_combined_img, dst.texel, color);
|
||||
|
@ -520,7 +520,7 @@ void film_store_color(FilmSample dst, int pass_id, vec4 color, inout vec4 displa
|
|||
color = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
}
|
||||
|
||||
if (uniform_buf.film.display_id == pass_id) {
|
||||
if (display_id == pass_id) {
|
||||
display = color;
|
||||
}
|
||||
imageStore(color_accum_img, ivec3(dst.texel, pass_id), color);
|
||||
|
@ -541,7 +541,7 @@ void film_store_value(FilmSample dst, int pass_id, float value, inout vec4 displ
|
|||
value = 0.0;
|
||||
}
|
||||
|
||||
if (uniform_buf.film.display_id == pass_id) {
|
||||
if (display_id == pass_id) {
|
||||
display = vec4(value, value, value, 1.0);
|
||||
}
|
||||
imageStore(value_accum_img, ivec3(dst.texel, pass_id), vec4(value));
|
||||
|
@ -554,7 +554,7 @@ void film_store_data(ivec2 texel_film, int pass_id, vec4 data_sample, inout vec4
|
|||
return;
|
||||
}
|
||||
|
||||
if (uniform_buf.film.display_id == pass_id) {
|
||||
if (display_id == pass_id) {
|
||||
display = data_sample;
|
||||
}
|
||||
imageStore(color_accum_img, ivec3(texel_film, pass_id), data_sample);
|
||||
|
@ -616,7 +616,7 @@ void film_process_data(ivec2 texel_film, out vec4 out_color, out float out_depth
|
|||
/* NOTE: We split the accumulations into separate loops to avoid using too much registers and
|
||||
* maximize occupancy. */
|
||||
|
||||
if (uniform_buf.film.combined_id != -1) {
|
||||
if (combined_id != -1) {
|
||||
/* NOTE: Do weight accumulation again since we use custom weights. */
|
||||
float weight_accum = 0.0;
|
||||
vec4 combined_accum = vec4(0.0);
|
||||
|
@ -643,10 +643,10 @@ void film_process_data(ivec2 texel_film, out vec4 out_color, out float out_depth
|
|||
vector *= vec4(vec2(uniform_buf.film.render_extent), vec2(uniform_buf.film.render_extent));
|
||||
|
||||
film_store_depth(texel_film, depth, out_depth);
|
||||
if (uniform_buf.film.normal_id != -1) {
|
||||
if (normal_id != -1) {
|
||||
vec4 normal = texelFetch(
|
||||
rp_color_tx, ivec3(film_sample.texel, uniform_buf.render_pass.normal_id), 0);
|
||||
film_store_data(texel_film, uniform_buf.film.normal_id, normal, out_color);
|
||||
film_store_data(texel_film, normal_id, normal, out_color);
|
||||
}
|
||||
if (uniform_buf.film.position_id != -1) {
|
||||
vec4 position = texelFetch(
|
||||
|
@ -658,10 +658,8 @@ void film_process_data(ivec2 texel_film, out vec4 out_color, out float out_depth
|
|||
}
|
||||
else {
|
||||
out_depth = imageLoad(depth_img, texel_film).r;
|
||||
if (uniform_buf.film.display_id != -1 &&
|
||||
uniform_buf.film.display_id == uniform_buf.film.normal_id)
|
||||
{
|
||||
out_color = imageLoad(color_accum_img, ivec3(texel_film, uniform_buf.film.display_id));
|
||||
if (display_id != -1 && display_id == normal_id) {
|
||||
out_color = imageLoad(color_accum_img, ivec3(texel_film, display_id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -185,20 +185,6 @@ vec3 volume_light(LightData light, const bool is_directional, LightVector lv)
|
|||
float power = 1.0;
|
||||
if (!is_directional) {
|
||||
float volume_radius_squared = light_local_data_get(light).radius_squared;
|
||||
float light_clamp = uniform_buf.volumes.light_clamp;
|
||||
if (light_clamp != 0.0) {
|
||||
/* 0.0 light clamp means it's disabled. */
|
||||
float max_power = reduce_max(light.color) * light.power[LIGHT_VOLUME];
|
||||
if (max_power > 0.0) {
|
||||
/* The limit of the power attenuation function when the distance to the light goes to 0 is
|
||||
* `2 / r^2` where r is the light radius. We need to find the right radius that emits at
|
||||
* most the volume light upper bound. Inverting the function we get: */
|
||||
float min_radius_squared = 1.0 / (0.5 * light_clamp / max_power);
|
||||
/* Square it here to avoid a multiplication inside the shader. */
|
||||
volume_radius_squared = max(volume_radius_squared, min_radius_squared);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Using "Point Light Attenuation Without Singularity" from Cem Yuksel
|
||||
* http://www.cemyuksel.com/research/pointlightattenuation/pointlightattenuation.pdf
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#pragma BLENDER_REQUIRE(eevee_lightprobe_eval_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(eevee_volume_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(eevee_sampling_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(eevee_colorspace_lib.glsl)
|
||||
|
||||
#pragma BLENDER_REQUIRE(eevee_volume_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(eevee_sampling_lib.glsl)
|
||||
|
@ -25,6 +26,7 @@ vec3 volume_scatter_light_eval(
|
|||
{
|
||||
LightData light = light_buf[l_idx];
|
||||
|
||||
/* TODO(fclem): Own light list for volume without lights that have 0 volume influence. */
|
||||
if (light.power[LIGHT_VOLUME] == 0.0) {
|
||||
return vec3(0);
|
||||
}
|
||||
|
@ -41,14 +43,15 @@ vec3 volume_scatter_light_eval(
|
|||
visibility *= shadow_sample(is_directional, shadow_atlas_tx, shadow_tilemaps_tx, light, P)
|
||||
.light_visibilty;
|
||||
}
|
||||
|
||||
visibility *= volume_phase_function(-V, lv.L, s_anisotropy);
|
||||
if (visibility < LIGHT_ATTENUATION_THRESHOLD) {
|
||||
return vec3(0);
|
||||
}
|
||||
|
||||
vec3 Li = volume_light(light, is_directional, lv) *
|
||||
vec3 Li = volume_light(light, is_directional, lv) * visibility *
|
||||
volume_shadow(light, is_directional, P, lv, extinction_tx);
|
||||
return Li * visibility * volume_phase_function(-V, lv.L, s_anisotropy);
|
||||
|
||||
return colorspace_brightness_clamp_max(Li, uniform_buf.volumes.light_clamp);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -27,6 +27,9 @@ GPU_SHADER_CREATE_INFO(eevee_film)
|
|||
.specialization_constant(Type::INT, "samples_len", 0)
|
||||
.specialization_constant(Type::BOOL, "use_reprojection", false)
|
||||
.specialization_constant(Type::INT, "scaling_factor", 1)
|
||||
.specialization_constant(Type::INT, "combined_id", 0)
|
||||
.specialization_constant(Type::INT, "display_id", -1)
|
||||
.specialization_constant(Type::INT, "normal_id", -1)
|
||||
.additional_info("eevee_shared")
|
||||
.additional_info("eevee_global_ubo")
|
||||
.additional_info("eevee_velocity_camera")
|
||||
|
|
|
@ -182,6 +182,7 @@ static void OVERLAY_cache_init(void *vedata)
|
|||
OVERLAY_edit_lattice_cache_init(data);
|
||||
break;
|
||||
case CTX_MODE_PAINT_GREASE_PENCIL:
|
||||
case CTX_MODE_SCULPT_GREASE_PENCIL:
|
||||
case CTX_MODE_EDIT_GREASE_PENCIL:
|
||||
OVERLAY_edit_grease_pencil_cache_init(data);
|
||||
break;
|
||||
|
|
|
@ -225,8 +225,9 @@ struct SortedFaceData {
|
|||
Array<int> tris_num_by_material;
|
||||
/**
|
||||
* The first triangle index for each face, sorted into slices by material.
|
||||
* May be empty if the mesh only has a single material.
|
||||
*/
|
||||
Array<int> face_tri_offsets;
|
||||
std::optional<Array<int>> face_tri_offsets;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -611,7 +611,6 @@ void mesh_buffer_cache_create_requested(TaskGraph *task_graph,
|
|||
*/
|
||||
const bool do_hq_normals = (scene->r.perf_flag & SCE_PERF_HQ_NORMALS) != 0 ||
|
||||
GPU_use_hq_normals_workaround();
|
||||
const bool override_single_mat = mesh_render_mat_len_get(object, mesh) <= 1;
|
||||
|
||||
/* Create an array containing all the extractors that needs to be executed. */
|
||||
ExtractorRunDatas extractors;
|
||||
|
@ -621,8 +620,7 @@ void mesh_buffer_cache_create_requested(TaskGraph *task_graph,
|
|||
#define EXTRACT_ADD_REQUESTED(type, name) \
|
||||
do { \
|
||||
if (DRW_##type##_requested(mbuflist->type.name)) { \
|
||||
const MeshExtract *extractor = mesh_extract_override_get( \
|
||||
&extract_##name, do_hq_normals, override_single_mat); \
|
||||
const MeshExtract *extractor = mesh_extract_override_get(&extract_##name, do_hq_normals); \
|
||||
extractors.append(extractor); \
|
||||
} \
|
||||
} while (0)
|
||||
|
|
|
@ -189,9 +189,10 @@ static void accumululate_material_counts_mesh(
|
|||
const MeshRenderData &mr, threading::EnumerableThreadSpecific<Array<int>> &all_tri_counts)
|
||||
{
|
||||
const OffsetIndices faces = mr.faces;
|
||||
if (mr.material_indices.is_empty()) {
|
||||
if (mr.use_hide && !mr.hide_poly.is_empty()) {
|
||||
const Span hide_poly = mr.hide_poly;
|
||||
const Span<bool> hide_poly = mr.hide_poly;
|
||||
const Span material_indices = mr.material_indices;
|
||||
if (material_indices.is_empty()) {
|
||||
if (!hide_poly.is_empty()) {
|
||||
all_tri_counts.local().first() = threading::parallel_reduce(
|
||||
faces.index_range(),
|
||||
4096,
|
||||
|
@ -212,13 +213,12 @@ static void accumululate_material_counts_mesh(
|
|||
return;
|
||||
}
|
||||
|
||||
const Span material_indices = mr.material_indices;
|
||||
threading::parallel_for(material_indices.index_range(), 1024, [&](const IndexRange range) {
|
||||
Array<int> &tri_counts = all_tri_counts.local();
|
||||
const int last_index = tri_counts.size() - 1;
|
||||
if (mr.use_hide && !mr.hide_poly.is_empty()) {
|
||||
if (!hide_poly.is_empty()) {
|
||||
for (const int i : range) {
|
||||
if (!mr.hide_poly[i]) {
|
||||
if (!hide_poly[i]) {
|
||||
const int mat = std::clamp(material_indices[i], 0, last_index);
|
||||
tri_counts[mat] += bke::mesh::face_triangles_num(faces[i].size());
|
||||
}
|
||||
|
@ -257,64 +257,109 @@ static Array<int> mesh_render_data_mat_tri_len_build(const MeshRenderData &mr)
|
|||
return std::move(tris_num_by_material);
|
||||
}
|
||||
|
||||
static void mesh_render_data_faces_sorted_build(MeshRenderData &mr, MeshBufferCache &cache)
|
||||
static Array<int> calc_face_tri_starts_bmesh(const MeshRenderData &mr,
|
||||
MutableSpan<int> material_tri_starts)
|
||||
{
|
||||
cache.face_sorted.tris_num_by_material = mesh_render_data_mat_tri_len_build(mr);
|
||||
const Span<int> tris_num_by_material = cache.face_sorted.tris_num_by_material;
|
||||
BMesh &bm = *mr.bm;
|
||||
Array<int> face_tri_offsets(bm.totface);
|
||||
#ifndef NDEBUG
|
||||
face_tri_offsets.fill(-1);
|
||||
#endif
|
||||
|
||||
/* Apply offset. */
|
||||
int visible_tris_num = 0;
|
||||
Array<int, 32> mat_tri_offs(mr.materials_num);
|
||||
{
|
||||
for (int i = 0; i < mr.materials_num; i++) {
|
||||
mat_tri_offs[i] = visible_tris_num;
|
||||
visible_tris_num += tris_num_by_material[i];
|
||||
const int mat_last = mr.materials_num - 1;
|
||||
BMIter iter;
|
||||
BMFace *face;
|
||||
int i;
|
||||
BM_ITER_MESH_INDEX (face, &iter, &bm, BM_FACES_OF_MESH, i) {
|
||||
if (BM_elem_flag_test(face, BM_ELEM_HIDDEN)) {
|
||||
continue;
|
||||
}
|
||||
const int mat = std::clamp(int(face->mat_nr), 0, mat_last);
|
||||
face_tri_offsets[i] = material_tri_starts[mat];
|
||||
material_tri_starts[mat] += face->len - 2;
|
||||
}
|
||||
cache.face_sorted.visible_tris_num = visible_tris_num;
|
||||
|
||||
cache.face_sorted.face_tri_offsets.reinitialize(mr.faces_num);
|
||||
MutableSpan<int> face_tri_offsets = cache.face_sorted.face_tri_offsets;
|
||||
return face_tri_offsets;
|
||||
}
|
||||
|
||||
static bool mesh_is_single_material(const OffsetIndices<int> material_tri_starts)
|
||||
{
|
||||
const int used_materials = std::count_if(
|
||||
material_tri_starts.index_range().begin(),
|
||||
material_tri_starts.index_range().end(),
|
||||
[&](const int i) { return material_tri_starts[i].size() > 0; });
|
||||
return used_materials == 1;
|
||||
}
|
||||
|
||||
static std::optional<Array<int>> calc_face_tri_starts_mesh(const MeshRenderData &mr,
|
||||
MutableSpan<int> material_tri_starts)
|
||||
{
|
||||
const bool single_material = mesh_is_single_material(material_tri_starts.as_span());
|
||||
if (single_material && mr.hide_poly.is_empty()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
const OffsetIndices faces = mr.faces;
|
||||
const Span<bool> hide_poly = mr.hide_poly;
|
||||
|
||||
Array<int> face_tri_offsets(faces.size());
|
||||
#ifndef NDEBUG
|
||||
face_tri_offsets.fill(-1);
|
||||
#endif
|
||||
|
||||
if (single_material) {
|
||||
int offset = 0;
|
||||
for (const int face : faces.index_range()) {
|
||||
if (hide_poly[face]) {
|
||||
continue;
|
||||
}
|
||||
face_tri_offsets[face] = offset;
|
||||
offset += bke::mesh::face_triangles_num(faces[face].size());
|
||||
}
|
||||
return face_tri_offsets;
|
||||
}
|
||||
|
||||
const Span<int> material_indices = mr.material_indices;
|
||||
const int mat_last = mr.materials_num - 1;
|
||||
for (const int face : faces.index_range()) {
|
||||
if (!hide_poly.is_empty() && hide_poly[face]) {
|
||||
continue;
|
||||
}
|
||||
const int mat = std::clamp(material_indices[face], 0, mat_last);
|
||||
face_tri_offsets[face] = material_tri_starts[mat];
|
||||
material_tri_starts[mat] += bke::mesh::face_triangles_num(faces[face].size());
|
||||
}
|
||||
|
||||
return face_tri_offsets;
|
||||
}
|
||||
|
||||
static SortedFaceData mesh_render_data_faces_sorted_build(const MeshRenderData &mr)
|
||||
{
|
||||
SortedFaceData cache;
|
||||
cache.tris_num_by_material = mesh_render_data_mat_tri_len_build(mr);
|
||||
const Span<int> tris_num_by_material = cache.tris_num_by_material;
|
||||
|
||||
Array<int, 32> material_tri_starts(mr.materials_num + 1);
|
||||
material_tri_starts.as_mutable_span().drop_back(1).copy_from(tris_num_by_material);
|
||||
offset_indices::accumulate_counts_to_offsets(material_tri_starts);
|
||||
cache.visible_tris_num = material_tri_starts.last();
|
||||
|
||||
/* Sort per material. */
|
||||
int mat_last = mr.materials_num - 1;
|
||||
if (mr.extract_type == MR_EXTRACT_BMESH) {
|
||||
BMIter iter;
|
||||
BMFace *f;
|
||||
int i;
|
||||
BM_ITER_MESH_INDEX (f, &iter, mr.bm, BM_FACES_OF_MESH, i) {
|
||||
if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
|
||||
const int mat = clamp_i(f->mat_nr, 0, mat_last);
|
||||
face_tri_offsets[i] = mat_tri_offs[mat];
|
||||
mat_tri_offs[mat] += f->len - 2;
|
||||
}
|
||||
else {
|
||||
face_tri_offsets[i] = -1;
|
||||
}
|
||||
}
|
||||
cache.face_tri_offsets = calc_face_tri_starts_bmesh(mr, material_tri_starts);
|
||||
}
|
||||
else {
|
||||
for (int i = 0; i < mr.faces_num; i++) {
|
||||
if (!(mr.use_hide && !mr.hide_poly.is_empty() && mr.hide_poly[i])) {
|
||||
const int mat = mr.material_indices.is_empty() ?
|
||||
0 :
|
||||
clamp_i(mr.material_indices[i], 0, mat_last);
|
||||
face_tri_offsets[i] = mat_tri_offs[mat];
|
||||
mat_tri_offs[mat] += mr.faces[i].size() - 2;
|
||||
}
|
||||
else {
|
||||
face_tri_offsets[i] = -1;
|
||||
}
|
||||
}
|
||||
cache.face_tri_offsets = calc_face_tri_starts_mesh(mr, material_tri_starts);
|
||||
}
|
||||
return cache;
|
||||
}
|
||||
|
||||
static void mesh_render_data_faces_sorted_ensure(MeshRenderData &mr, MeshBufferCache &cache)
|
||||
{
|
||||
if (!cache.face_sorted.face_tri_offsets.is_empty()) {
|
||||
if (cache.face_sorted.visible_tris_num > 0) {
|
||||
return;
|
||||
}
|
||||
mesh_render_data_faces_sorted_build(mr, cache);
|
||||
cache.face_sorted = mesh_render_data_faces_sorted_build(mr);
|
||||
}
|
||||
|
||||
void mesh_render_data_update_faces_sorted(MeshRenderData &mr,
|
||||
|
|
|
@ -64,26 +64,13 @@ static const MeshExtract *mesh_extract_override_hq_normals(const MeshExtract *ex
|
|||
return extractor;
|
||||
}
|
||||
|
||||
static const MeshExtract *mesh_extract_override_single_material(const MeshExtract *extractor)
|
||||
{
|
||||
if (extractor == &extract_tris) {
|
||||
return &extract_tris_single_mat;
|
||||
}
|
||||
return extractor;
|
||||
}
|
||||
|
||||
const MeshExtract *mesh_extract_override_get(const MeshExtract *extractor,
|
||||
const bool do_hq_normals,
|
||||
const bool do_single_mat)
|
||||
const bool do_hq_normals)
|
||||
{
|
||||
if (do_hq_normals) {
|
||||
extractor = mesh_extract_override_hq_normals(extractor);
|
||||
}
|
||||
|
||||
if (do_single_mat) {
|
||||
extractor = mesh_extract_override_single_material(extractor);
|
||||
}
|
||||
|
||||
return extractor;
|
||||
}
|
||||
|
||||
|
|
|
@ -320,9 +320,7 @@ struct EditLoopData {
|
|||
|
||||
void *mesh_extract_buffer_get(const MeshExtract *extractor, MeshBufferList *mbuflist);
|
||||
eMRIterType mesh_extract_iter_type(const MeshExtract *ext);
|
||||
const MeshExtract *mesh_extract_override_get(const MeshExtract *extractor,
|
||||
bool do_hq_normals,
|
||||
bool do_single_mat);
|
||||
const MeshExtract *mesh_extract_override_get(const MeshExtract *extractor, bool do_hq_normals);
|
||||
void mesh_render_data_face_flag(const MeshRenderData &mr,
|
||||
const BMFace *efa,
|
||||
BMUVOffsets offsets,
|
||||
|
@ -340,7 +338,6 @@ template<typename GPUType>
|
|||
void extract_vert_normals(const MeshRenderData &mr, MutableSpan<GPUType> normals);
|
||||
|
||||
extern const MeshExtract extract_tris;
|
||||
extern const MeshExtract extract_tris_single_mat;
|
||||
extern const MeshExtract extract_lines;
|
||||
extern const MeshExtract extract_lines_with_lines_loose;
|
||||
extern const MeshExtract extract_lines_loose_only;
|
||||
|
|
|
@ -16,83 +16,84 @@
|
|||
|
||||
namespace blender::draw {
|
||||
|
||||
static void extract_tris_mat_task_reduce(void *_userdata_to, void *_userdata_from)
|
||||
{
|
||||
GPUIndexBufBuilder *elb_to = static_cast<GPUIndexBufBuilder *>(_userdata_to);
|
||||
GPUIndexBufBuilder *elb_from = static_cast<GPUIndexBufBuilder *>(_userdata_from);
|
||||
GPU_indexbuf_join(elb_to, elb_from);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/** \name Extract Triangles Indices (multi material)
|
||||
* \{ */
|
||||
|
||||
static void extract_tris_init(const MeshRenderData &mr,
|
||||
MeshBatchCache & /*cache*/,
|
||||
void * /*ibo*/,
|
||||
void *tls_data)
|
||||
static void extract_tris_mesh(const MeshRenderData &mr, gpu::IndexBuf &ibo)
|
||||
{
|
||||
GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(tls_data);
|
||||
GPU_indexbuf_init(elb, GPU_PRIM_TRIS, mr.face_sorted->visible_tris_num, mr.corners_num);
|
||||
}
|
||||
|
||||
static void extract_tris_iter_face_bm(const MeshRenderData &mr,
|
||||
const BMFace *f,
|
||||
const int f_index,
|
||||
void *_data)
|
||||
{
|
||||
int tri_offset = mr.face_sorted->face_tri_offsets[f_index];
|
||||
if (tri_offset == -1) {
|
||||
const Span<int3> corner_tris = mr.corner_tris;
|
||||
if (!mr.face_sorted->face_tri_offsets) {
|
||||
/* There are no hidden faces and no reordering is necessary to group triangles with the same
|
||||
* material. The corner indices from #Mesh::corner_tris() can be copied directly to the GPU. */
|
||||
BLI_assert(mr.face_sorted->visible_tris_num == corner_tris.size());
|
||||
GPU_indexbuf_build_in_place_from_memory(&ibo,
|
||||
GPU_PRIM_TRIS,
|
||||
corner_tris.cast<uint32_t>().data(),
|
||||
corner_tris.size(),
|
||||
0,
|
||||
mr.corners_num,
|
||||
false);
|
||||
return;
|
||||
}
|
||||
|
||||
GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(_data);
|
||||
int tri_first_index_real = poly_to_tri_count(f_index, BM_elem_index_get(f->l_first));
|
||||
const OffsetIndices faces = mr.faces;
|
||||
const Span<bool> hide_poly = mr.hide_poly;
|
||||
|
||||
Span<std::array<BMLoop *, 3>> looptris = mr.edit_bmesh->looptris;
|
||||
int tri_len = f->len - 2;
|
||||
for (int offs = 0; offs < tri_len; offs++) {
|
||||
const std::array<BMLoop *, 3> &elt = looptris[tri_first_index_real + offs];
|
||||
int tri_index = tri_offset + offs;
|
||||
GPU_indexbuf_set_tri_verts(elb,
|
||||
tri_index,
|
||||
BM_elem_index_get(elt[0]),
|
||||
BM_elem_index_get(elt[1]),
|
||||
BM_elem_index_get(elt[2]));
|
||||
}
|
||||
GPUIndexBufBuilder builder;
|
||||
GPU_indexbuf_init(&builder, GPU_PRIM_TRIS, mr.face_sorted->visible_tris_num, mr.corners_num);
|
||||
MutableSpan<uint3> data = GPU_indexbuf_get_data(&builder).cast<uint3>();
|
||||
|
||||
const Span<int> face_tri_offsets = mr.face_sorted->face_tri_offsets->as_span();
|
||||
threading::parallel_for(faces.index_range(), 2048, [&](const IndexRange range) {
|
||||
for (const int face : range) {
|
||||
if (!hide_poly.is_empty() && hide_poly[face]) {
|
||||
continue;
|
||||
}
|
||||
const IndexRange mesh_range = bke::mesh::face_triangles_range(faces, face);
|
||||
const Span<uint3> mesh_tris = corner_tris.slice(mesh_range).cast<uint3>();
|
||||
MutableSpan<uint3> ibo_tris = data.slice(face_tri_offsets[face], mesh_tris.size());
|
||||
ibo_tris.copy_from(mesh_tris);
|
||||
}
|
||||
});
|
||||
|
||||
GPU_indexbuf_build_in_place_ex(&builder, 0, mr.face_sorted->visible_tris_num, false, &ibo);
|
||||
}
|
||||
|
||||
static void extract_tris_iter_face_mesh(const MeshRenderData &mr,
|
||||
const int face_index,
|
||||
void *_data)
|
||||
static void extract_tris_bmesh(const MeshRenderData &mr, gpu::IndexBuf &ibo)
|
||||
{
|
||||
int tri_offset = mr.face_sorted->face_tri_offsets[face_index];
|
||||
if (tri_offset == -1) {
|
||||
return;
|
||||
}
|
||||
GPUIndexBufBuilder builder;
|
||||
GPU_indexbuf_init(&builder, GPU_PRIM_TRIS, mr.face_sorted->visible_tris_num, mr.corners_num);
|
||||
MutableSpan<uint3> data = GPU_indexbuf_get_data(&builder).cast<uint3>();
|
||||
|
||||
const IndexRange face = mr.faces[face_index];
|
||||
BMesh &bm = *mr.bm;
|
||||
const Span<std::array<BMLoop *, 3>> looptris = mr.edit_bmesh->looptris;
|
||||
const Span<int> face_tri_offsets = *mr.face_sorted->face_tri_offsets;
|
||||
threading::parallel_for(IndexRange(bm.totface), 1024, [&](const IndexRange range) {
|
||||
for (const int face_index : range) {
|
||||
const BMFace &face = *BM_face_at_index(&bm, face_index);
|
||||
if (BM_elem_flag_test(&face, BM_ELEM_HIDDEN)) {
|
||||
continue;
|
||||
}
|
||||
const int loop_index = BM_elem_index_get(BM_FACE_FIRST_LOOP(&face));
|
||||
const IndexRange bm_tris(poly_to_tri_count(face_index, loop_index),
|
||||
bke::mesh::face_triangles_num(face.len));
|
||||
const IndexRange ibo_tris(face_tri_offsets[face_index], bm_tris.size());
|
||||
for (const int i : bm_tris.index_range()) {
|
||||
data[ibo_tris[i]] = uint3(BM_elem_index_get(looptris[bm_tris[i]][0]),
|
||||
BM_elem_index_get(looptris[bm_tris[i]][1]),
|
||||
BM_elem_index_get(looptris[bm_tris[i]][2]));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(_data);
|
||||
int tri_first_index_real = poly_to_tri_count(face_index, face.start());
|
||||
|
||||
int tri_len = face.size() - 2;
|
||||
for (int offs = 0; offs < tri_len; offs++) {
|
||||
const int3 &tri = mr.corner_tris[tri_first_index_real + offs];
|
||||
int tri_index = tri_offset + offs;
|
||||
GPU_indexbuf_set_tri_verts(elb, tri_index, tri[0], tri[1], tri[2]);
|
||||
}
|
||||
GPU_indexbuf_build_in_place_ex(&builder, 0, mr.face_sorted->visible_tris_num, false, &ibo);
|
||||
}
|
||||
|
||||
static void extract_tris_finish(const MeshRenderData &mr,
|
||||
MeshBatchCache &cache,
|
||||
void *buf,
|
||||
void *_data)
|
||||
gpu::IndexBuf &ibo)
|
||||
{
|
||||
gpu::IndexBuf *ibo = static_cast<gpu::IndexBuf *>(buf);
|
||||
GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(_data);
|
||||
GPU_indexbuf_build_in_place(elb, ibo);
|
||||
|
||||
/* Create ibo sub-ranges. Always do this to avoid error when the standard surface batch
|
||||
* is created before the surfaces-per-material. */
|
||||
if (mr.use_final_mesh && cache.tris_per_mat) {
|
||||
|
@ -107,12 +108,29 @@ static void extract_tris_finish(const MeshRenderData &mr,
|
|||
/* Multiply by 3 because these are triangle indices. */
|
||||
const int start = mat_start * 3;
|
||||
const int len = mat_tri_len * 3;
|
||||
GPU_indexbuf_create_subrange_in_place(cache.tris_per_mat[i], ibo, start, len);
|
||||
GPU_indexbuf_create_subrange_in_place(cache.tris_per_mat[i], &ibo, start, len);
|
||||
mat_start += mat_tri_len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void extract_tris_init(const MeshRenderData &mr,
|
||||
MeshBatchCache &cache,
|
||||
void *ibo_v,
|
||||
void * /*tls_data*/)
|
||||
{
|
||||
gpu::IndexBuf &ibo = *static_cast<gpu::IndexBuf *>(ibo_v);
|
||||
|
||||
if (mr.extract_type == MR_EXTRACT_MESH) {
|
||||
extract_tris_mesh(mr, ibo);
|
||||
}
|
||||
else {
|
||||
extract_tris_bmesh(mr, ibo);
|
||||
}
|
||||
|
||||
extract_tris_finish(mr, cache, ibo);
|
||||
}
|
||||
|
||||
static void extract_tris_init_subdiv(const DRWSubdivCache &subdiv_cache,
|
||||
const MeshRenderData & /*mr*/,
|
||||
MeshBatchCache &cache,
|
||||
|
@ -144,101 +162,7 @@ constexpr MeshExtract create_extractor_tris()
|
|||
MeshExtract extractor = {nullptr};
|
||||
extractor.init = extract_tris_init;
|
||||
extractor.init_subdiv = extract_tris_init_subdiv;
|
||||
extractor.iter_face_bm = extract_tris_iter_face_bm;
|
||||
extractor.iter_face_mesh = extract_tris_iter_face_mesh;
|
||||
extractor.task_reduce = extract_tris_mat_task_reduce;
|
||||
extractor.finish = extract_tris_finish;
|
||||
extractor.data_type = MR_DATA_CORNER_TRI | MR_DATA_POLYS_SORTED;
|
||||
extractor.data_size = sizeof(GPUIndexBufBuilder);
|
||||
extractor.use_threading = true;
|
||||
extractor.mesh_buffer_offset = offsetof(MeshBufferList, ibo.tris);
|
||||
return extractor;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/** \name Extract Triangles Indices (single material)
|
||||
* \{ */
|
||||
|
||||
static void extract_tris_single_mat_init(const MeshRenderData &mr,
|
||||
MeshBatchCache & /*cache*/,
|
||||
void * /*ibo*/,
|
||||
void *tls_data)
|
||||
{
|
||||
GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(tls_data);
|
||||
GPU_indexbuf_init(elb, GPU_PRIM_TRIS, mr.corner_tris_num, mr.corners_num);
|
||||
}
|
||||
|
||||
static void extract_tris_single_mat_iter_looptri_bm(const MeshRenderData & /*mr*/,
|
||||
BMLoop **elt,
|
||||
const int elt_index,
|
||||
void *_data)
|
||||
{
|
||||
GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(_data);
|
||||
if (!BM_elem_flag_test(elt[0]->f, BM_ELEM_HIDDEN)) {
|
||||
GPU_indexbuf_set_tri_verts(elb,
|
||||
elt_index,
|
||||
BM_elem_index_get(elt[0]),
|
||||
BM_elem_index_get(elt[1]),
|
||||
BM_elem_index_get(elt[2]));
|
||||
}
|
||||
else {
|
||||
GPU_indexbuf_set_tri_restart(elb, elt_index);
|
||||
}
|
||||
}
|
||||
|
||||
static void extract_tris_single_mat_iter_corner_tri_mesh(const MeshRenderData &mr,
|
||||
const int3 &tri,
|
||||
const int tri_index,
|
||||
void *_data)
|
||||
{
|
||||
GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(_data);
|
||||
const int face_i = mr.corner_tri_faces[tri_index];
|
||||
const bool hidden = mr.use_hide && !mr.hide_poly.is_empty() && mr.hide_poly[face_i];
|
||||
if (hidden) {
|
||||
GPU_indexbuf_set_tri_restart(elb, tri_index);
|
||||
}
|
||||
else {
|
||||
GPU_indexbuf_set_tri_verts(elb, tri_index, tri[0], tri[1], tri[2]);
|
||||
}
|
||||
}
|
||||
|
||||
static void extract_tris_single_mat_finish(const MeshRenderData &mr,
|
||||
MeshBatchCache &cache,
|
||||
void *buf,
|
||||
void *_data)
|
||||
{
|
||||
gpu::IndexBuf *ibo = static_cast<gpu::IndexBuf *>(buf);
|
||||
GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(_data);
|
||||
GPU_indexbuf_build_in_place(elb, ibo);
|
||||
|
||||
/* Create ibo sub-ranges. Always do this to avoid error when the standard surface batch
|
||||
* is created before the surfaces-per-material. */
|
||||
if (mr.use_final_mesh && cache.tris_per_mat) {
|
||||
for (int i = 0; i < mr.materials_num; i++) {
|
||||
/* These IBOs have not been queried yet but we create them just in case they are needed
|
||||
* later since they are not tracked by mesh_buffer_cache_create_requested(). */
|
||||
if (cache.tris_per_mat[i] == nullptr) {
|
||||
cache.tris_per_mat[i] = GPU_indexbuf_calloc();
|
||||
}
|
||||
/* Multiply by 3 because these are triangle indices. */
|
||||
const int len = mr.corner_tris_num * 3;
|
||||
GPU_indexbuf_create_subrange_in_place(cache.tris_per_mat[i], ibo, 0, len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
constexpr MeshExtract create_extractor_tris_single_mat()
|
||||
{
|
||||
MeshExtract extractor = {nullptr};
|
||||
extractor.init = extract_tris_single_mat_init;
|
||||
extractor.init_subdiv = extract_tris_init_subdiv;
|
||||
extractor.iter_looptri_bm = extract_tris_single_mat_iter_looptri_bm;
|
||||
extractor.iter_corner_tri_mesh = extract_tris_single_mat_iter_corner_tri_mesh;
|
||||
extractor.task_reduce = extract_tris_mat_task_reduce;
|
||||
extractor.finish = extract_tris_single_mat_finish;
|
||||
extractor.data_type = MR_DATA_NONE;
|
||||
extractor.data_size = sizeof(GPUIndexBufBuilder);
|
||||
extractor.use_threading = true;
|
||||
extractor.mesh_buffer_offset = offsetof(MeshBufferList, ibo.tris);
|
||||
return extractor;
|
||||
|
@ -247,6 +171,5 @@ constexpr MeshExtract create_extractor_tris_single_mat()
|
|||
/** \} */
|
||||
|
||||
const MeshExtract extract_tris = create_extractor_tris();
|
||||
const MeshExtract extract_tris_single_mat = create_extractor_tris_single_mat();
|
||||
|
||||
} // namespace blender::draw
|
||||
|
|
|
@ -353,10 +353,10 @@ void storage_tag_main_data_dirty()
|
|||
}
|
||||
}
|
||||
|
||||
void storage_id_remap(ID *id_new, ID *id_old)
|
||||
void storage_id_remap(ID *id_old, ID *id_new)
|
||||
{
|
||||
for (AssetList &list : global_storage().values()) {
|
||||
list.remap_id(id_new, id_old);
|
||||
list.remap_id(id_old, id_new);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1365,6 +1365,8 @@ static int exec(bContext *C, wmOperator * /*op*/)
|
|||
attributes.remove("cyclic");
|
||||
}
|
||||
|
||||
curves.calculate_bezier_auto_handles();
|
||||
|
||||
DEG_id_tag_update(&curves_id->id, ID_RECALC_GEOMETRY);
|
||||
WM_event_add_notifier(C, NC_GEOM | ND_DATA, curves_id);
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#include "DNA_object_enums.h"
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BLI_ghash.h"
|
||||
|
@ -25,6 +26,7 @@
|
|||
#include "BLT_translation.hh"
|
||||
|
||||
#include "DNA_gpencil_legacy_types.h"
|
||||
#include "DNA_grease_pencil_types.h"
|
||||
#include "DNA_material_types.h"
|
||||
#include "DNA_meshdata_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
|
@ -61,6 +63,7 @@
|
|||
#include "UI_view2d.hh"
|
||||
|
||||
#include "ED_gpencil_legacy.hh"
|
||||
#include "ED_image.hh"
|
||||
#include "ED_object.hh"
|
||||
#include "ED_outliner.hh"
|
||||
#include "ED_screen.hh"
|
||||
|
@ -453,10 +456,25 @@ static bool gpencil_sculptmode_toggle_poll(bContext *C)
|
|||
{
|
||||
/* if using gpencil object, use this gpd */
|
||||
Object *ob = CTX_data_active_object(C);
|
||||
if ((ob) && (ob->type == OB_GPENCIL_LEGACY)) {
|
||||
if (ob == nullptr) {
|
||||
return false;
|
||||
}
|
||||
if (ELEM(ob->type, OB_GPENCIL_LEGACY, OB_GREASE_PENCIL)) {
|
||||
return ob->data != nullptr;
|
||||
}
|
||||
return ED_gpencil_data_get_active(C) != nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool gpencil_sculpt_poll_view3d(bContext *C)
|
||||
{
|
||||
const Object *ob = CTX_data_active_object(C);
|
||||
if (ob == nullptr || (ob->mode & OB_MODE_SCULPT_GPENCIL_LEGACY) == 0) {
|
||||
return false;
|
||||
}
|
||||
if (CTX_wm_region_view3d(C) == nullptr) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static int gpencil_sculptmode_toggle_exec(bContext *C, wmOperator *op)
|
||||
|
@ -467,35 +485,49 @@ static int gpencil_sculptmode_toggle_exec(bContext *C, wmOperator *op)
|
|||
const bool back = RNA_boolean_get(op->ptr, "back");
|
||||
|
||||
wmMsgBus *mbus = CTX_wm_message_bus(C);
|
||||
bGPdata *gpd = ED_gpencil_data_get_active(C);
|
||||
bool is_object = false;
|
||||
short mode;
|
||||
/* if using a gpencil object, use this datablock */
|
||||
Object *ob = CTX_data_active_object(C);
|
||||
if ((ob) && (ob->type == OB_GPENCIL_LEGACY)) {
|
||||
gpd = static_cast<bGPdata *>(ob->data);
|
||||
bGPdata *gpd = ED_gpencil_data_get_active(C);
|
||||
if (gpd == nullptr) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
/* Just toggle sculptmode flag... */
|
||||
gpd->flag ^= GP_DATA_STROKE_SCULPTMODE;
|
||||
/* set mode */
|
||||
if (gpd->flag & GP_DATA_STROKE_SCULPTMODE) {
|
||||
mode = OB_MODE_SCULPT_GPENCIL_LEGACY;
|
||||
}
|
||||
else {
|
||||
/* try to back previous mode */
|
||||
if ((ob->restore_mode) && (back == 1)) {
|
||||
mode = ob->restore_mode;
|
||||
}
|
||||
else {
|
||||
mode = OB_MODE_OBJECT;
|
||||
}
|
||||
}
|
||||
is_object = true;
|
||||
}
|
||||
if ((ob) && (ob->type == OB_GREASE_PENCIL)) {
|
||||
const bool is_mode_set = (ob->mode & OB_MODE_SCULPT_GPENCIL_LEGACY) != 0;
|
||||
if (is_mode_set) {
|
||||
mode = OB_MODE_OBJECT;
|
||||
}
|
||||
else {
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
BKE_paint_init(
|
||||
bmain, scene, PaintMode::SculptGreasePencil, PAINT_CURSOR_SCULPT_GREASE_PENCIL);
|
||||
Paint *paint = BKE_paint_get_active_from_paintmode(scene, PaintMode::SculptGreasePencil);
|
||||
ED_paint_cursor_start(paint, gpencil_sculpt_poll_view3d);
|
||||
mode = OB_MODE_SCULPT_GPENCIL_LEGACY;
|
||||
}
|
||||
is_object = true;
|
||||
}
|
||||
|
||||
if (gpd == nullptr) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
/* Just toggle sculptmode flag... */
|
||||
gpd->flag ^= GP_DATA_STROKE_SCULPTMODE;
|
||||
/* set mode */
|
||||
if (gpd->flag & GP_DATA_STROKE_SCULPTMODE) {
|
||||
mode = OB_MODE_SCULPT_GPENCIL_LEGACY;
|
||||
}
|
||||
else {
|
||||
mode = OB_MODE_OBJECT;
|
||||
}
|
||||
|
||||
if (is_object) {
|
||||
/* try to back previous mode */
|
||||
if ((ob->restore_mode) && ((gpd->flag & GP_DATA_STROKE_SCULPTMODE) == 0) && (back == 1)) {
|
||||
mode = ob->restore_mode;
|
||||
}
|
||||
ob->restore_mode = ob->mode;
|
||||
ob->mode = mode;
|
||||
}
|
||||
|
@ -511,9 +543,16 @@ static int gpencil_sculptmode_toggle_exec(bContext *C, wmOperator *op)
|
|||
}
|
||||
|
||||
/* setup other modes */
|
||||
ED_gpencil_setup_modes(C, gpd, mode);
|
||||
/* set cache as dirty */
|
||||
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
|
||||
if (ob->type == OB_GPENCIL_LEGACY) {
|
||||
bGPdata *gpd = ED_gpencil_data_get_active(C);
|
||||
ED_gpencil_setup_modes(C, gpd, mode);
|
||||
/* set cache as dirty */
|
||||
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
|
||||
}
|
||||
if (ob->type == OB_GREASE_PENCIL) {
|
||||
GreasePencil *grease_pencil = static_cast<GreasePencil *>(ob->data);
|
||||
DEG_id_tag_update(&grease_pencil->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
|
||||
}
|
||||
|
||||
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | ND_GPENCIL_EDITMODE, nullptr);
|
||||
WM_event_add_notifier(C, NC_SCENE | ND_MODE, nullptr);
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include "BKE_context.hh"
|
||||
|
||||
#include "DNA_object_enums.h"
|
||||
#include "DNA_scene_types.h"
|
||||
|
||||
#include "ED_grease_pencil.hh"
|
||||
|
@ -81,6 +82,22 @@ bool grease_pencil_painting_poll(bContext *C)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool grease_pencil_sculpting_poll(bContext *C)
|
||||
{
|
||||
if (!active_grease_pencil_poll(C)) {
|
||||
return false;
|
||||
}
|
||||
Object *object = CTX_data_active_object(C);
|
||||
if ((object->mode & OB_MODE_SCULPT_GPENCIL_LEGACY) == 0) {
|
||||
return false;
|
||||
}
|
||||
ToolSettings *ts = CTX_data_tool_settings(C);
|
||||
if (!ts || !ts->gp_sculptpaint) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void keymap_grease_pencil_edit_mode(wmKeyConfig *keyconf)
|
||||
{
|
||||
wmKeyMap *keymap = WM_keymap_ensure(
|
||||
|
|
|
@ -175,6 +175,7 @@ bool editable_grease_pencil_poll(bContext *C);
|
|||
bool active_grease_pencil_layer_poll(bContext *C);
|
||||
bool editable_grease_pencil_point_selection_poll(bContext *C);
|
||||
bool grease_pencil_painting_poll(bContext *C);
|
||||
bool grease_pencil_sculpting_poll(bContext *C);
|
||||
|
||||
struct DrawingInfo {
|
||||
const bke::greasepencil::Drawing &drawing;
|
||||
|
|
|
@ -1066,18 +1066,21 @@ const uchar *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colorid)
|
|||
|
||||
void UI_theme_init_default()
|
||||
{
|
||||
/* we search for the theme with name Default */
|
||||
/* We search for the theme with the default name. */
|
||||
bTheme *btheme = static_cast<bTheme *>(
|
||||
BLI_findstring(&U.themes, "Default", offsetof(bTheme, name)));
|
||||
BLI_findstring(&U.themes, U_theme_default.name, offsetof(bTheme, name)));
|
||||
if (btheme == nullptr) {
|
||||
btheme = MEM_cnew<bTheme>(__func__);
|
||||
BLI_addtail(&U.themes, btheme);
|
||||
BLI_addhead(&U.themes, btheme);
|
||||
}
|
||||
|
||||
/* Must be first, see `U.themes` doc-string. */
|
||||
BLI_listbase_rotate_first(&U.themes, btheme);
|
||||
|
||||
UI_SetTheme(0, 0); /* make sure the global used in this file is set */
|
||||
|
||||
const int active_theme_area = btheme->active_theme_area;
|
||||
memcpy(btheme, &U_theme_default, sizeof(*btheme));
|
||||
MEMCPY_STRUCT_AFTER(btheme, &U_theme_default, name);
|
||||
btheme->active_theme_area = active_theme_area;
|
||||
}
|
||||
|
||||
|
|
|
@ -115,7 +115,7 @@ static int wm_obj_export_exec(bContext *C, wmOperator *op)
|
|||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static void ui_obj_export_settings(uiLayout *layout, PointerRNA *imfptr)
|
||||
static void ui_obj_export_settings(const bContext *C, uiLayout *layout, PointerRNA *imfptr)
|
||||
{
|
||||
const bool export_animation = RNA_boolean_get(imfptr, "export_animation");
|
||||
const bool export_smooth_groups = RNA_boolean_get(imfptr, "export_smooth_groups");
|
||||
|
@ -129,9 +129,16 @@ static void ui_obj_export_settings(uiLayout *layout, PointerRNA *imfptr)
|
|||
/* Object Transform options. */
|
||||
box = uiLayoutBox(layout);
|
||||
col = uiLayoutColumn(box, false);
|
||||
sub = uiLayoutColumnWithHeading(col, false, IFACE_("Limit to"));
|
||||
uiItemR(
|
||||
sub, imfptr, "export_selected_objects", UI_ITEM_NONE, IFACE_("Selected Only"), ICON_NONE);
|
||||
|
||||
if (CTX_wm_space_file(C)) {
|
||||
sub = uiLayoutColumnWithHeading(col, false, IFACE_("Limit to"));
|
||||
uiItemR(
|
||||
sub, imfptr, "export_selected_objects", UI_ITEM_NONE, IFACE_("Selected Only"), ICON_NONE);
|
||||
}
|
||||
else {
|
||||
sub = uiLayoutColumn(col, false);
|
||||
}
|
||||
|
||||
uiItemR(sub, imfptr, "global_scale", UI_ITEM_NONE, nullptr, ICON_NONE);
|
||||
uiItemR(sub, imfptr, "forward_axis", UI_ITEM_NONE, IFACE_("Forward Axis"), ICON_NONE);
|
||||
uiItemR(sub, imfptr, "up_axis", UI_ITEM_NONE, IFACE_("Up Axis"), ICON_NONE);
|
||||
|
@ -197,9 +204,9 @@ static void ui_obj_export_settings(uiLayout *layout, PointerRNA *imfptr)
|
|||
uiItemR(sub, imfptr, "end_frame", UI_ITEM_NONE, IFACE_("End"), ICON_NONE);
|
||||
}
|
||||
|
||||
static void wm_obj_export_draw(bContext * /*C*/, wmOperator *op)
|
||||
static void wm_obj_export_draw(bContext *C, wmOperator *op)
|
||||
{
|
||||
ui_obj_export_settings(op->layout, op->ptr);
|
||||
ui_obj_export_settings(C, op->layout, op->ptr);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -222,7 +222,7 @@ static int wm_usd_export_exec(bContext *C, wmOperator *op)
|
|||
return as_background_job || ok ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
static void wm_usd_export_draw(bContext * /*C*/, wmOperator *op)
|
||||
static void wm_usd_export_draw(bContext *C, wmOperator *op)
|
||||
{
|
||||
uiLayout *layout = op->layout;
|
||||
uiLayout *col;
|
||||
|
@ -232,9 +232,11 @@ static void wm_usd_export_draw(bContext * /*C*/, wmOperator *op)
|
|||
|
||||
uiLayout *box = uiLayoutBox(layout);
|
||||
|
||||
col = uiLayoutColumn(box, true);
|
||||
uiItemR(col, ptr, "selected_objects_only", UI_ITEM_NONE, nullptr, ICON_NONE);
|
||||
uiItemR(col, ptr, "visible_objects_only", UI_ITEM_NONE, nullptr, ICON_NONE);
|
||||
if (CTX_wm_space_file(C)) {
|
||||
col = uiLayoutColumn(box, true);
|
||||
uiItemR(col, ptr, "selected_objects_only", UI_ITEM_NONE, nullptr, ICON_NONE);
|
||||
uiItemR(col, ptr, "visible_objects_only", UI_ITEM_NONE, nullptr, ICON_NONE);
|
||||
}
|
||||
|
||||
col = uiLayoutColumn(box, true);
|
||||
uiItemR(col, ptr, "export_animation", UI_ITEM_NONE, nullptr, ICON_NONE);
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
* actual mode switching logic is per-object type.
|
||||
*/
|
||||
|
||||
#include "DNA_object_enums.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
|
||||
|
@ -147,7 +148,9 @@ bool mode_compat_test(const Object *ob, eObjectMode mode)
|
|||
}
|
||||
break;
|
||||
case OB_GREASE_PENCIL:
|
||||
if (mode & (OB_MODE_EDIT | OB_MODE_PAINT_GREASE_PENCIL | OB_MODE_WEIGHT_PAINT)) {
|
||||
if (mode & (OB_MODE_EDIT | OB_MODE_PAINT_GREASE_PENCIL | OB_MODE_WEIGHT_PAINT |
|
||||
OB_MODE_SCULPT_GPENCIL_LEGACY))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "DNA_brush_types.h"
|
||||
#include "DNA_grease_pencil_types.h"
|
||||
|
||||
#include "DNA_scene_types.h"
|
||||
#include "ED_grease_pencil.hh"
|
||||
#include "ED_image.hh"
|
||||
#include "ED_object.hh"
|
||||
|
@ -30,41 +31,9 @@
|
|||
namespace blender::ed::sculpt_paint {
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Brush Stroke Operator
|
||||
/** \name Common Paint Operator Functions
|
||||
* \{ */
|
||||
|
||||
static bool start_brush_operation(bContext &C,
|
||||
wmOperator & /*op*/,
|
||||
PaintStroke *paint_stroke,
|
||||
const InputSample &start_sample)
|
||||
{
|
||||
// const BrushStrokeMode mode = static_cast<BrushStrokeMode>(RNA_enum_get(op.ptr, "mode"));
|
||||
|
||||
const Scene &scene = *CTX_data_scene(&C);
|
||||
const GpPaint &gp_paint = *scene.toolsettings->gp_paint;
|
||||
const Brush &brush = *BKE_paint_brush_for_read(&gp_paint.paint);
|
||||
GreasePencilStrokeOperation *operation = nullptr;
|
||||
switch (brush.gpencil_tool) {
|
||||
case GPAINT_TOOL_DRAW:
|
||||
/* FIXME: Somehow store the unique_ptr in the PaintStroke. */
|
||||
operation = greasepencil::new_paint_operation().release();
|
||||
break;
|
||||
case GPAINT_TOOL_ERASE:
|
||||
operation = greasepencil::new_erase_operation().release();
|
||||
break;
|
||||
case GPAINT_TOOL_TINT:
|
||||
operation = greasepencil::new_tint_operation().release();
|
||||
break;
|
||||
}
|
||||
|
||||
if (operation) {
|
||||
paint_stroke_set_mode_data(paint_stroke, operation);
|
||||
operation->on_stroke_begin(C, start_sample);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool stroke_get_location(bContext * /*C*/,
|
||||
float out[3],
|
||||
const float mouse[2],
|
||||
|
@ -76,19 +45,19 @@ static bool stroke_get_location(bContext * /*C*/,
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool stroke_test_start(bContext *C, wmOperator *op, const float mouse[2])
|
||||
static void stroke_start(bContext &C,
|
||||
wmOperator &op,
|
||||
const float2 &mouse,
|
||||
GreasePencilStrokeOperation &operation)
|
||||
{
|
||||
PaintStroke *paint_stroke = static_cast<PaintStroke *>(op->customdata);
|
||||
PaintStroke *paint_stroke = static_cast<PaintStroke *>(op.customdata);
|
||||
|
||||
InputSample start_sample;
|
||||
start_sample.mouse_position = float2(mouse);
|
||||
start_sample.pressure = 0.0f;
|
||||
|
||||
if (!start_brush_operation(*C, *op, paint_stroke, start_sample)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
paint_stroke_set_mode_data(paint_stroke, &operation);
|
||||
operation.on_stroke_begin(C, start_sample);
|
||||
}
|
||||
|
||||
static void stroke_update_step(bContext *C,
|
||||
|
@ -121,6 +90,12 @@ static void stroke_done(const bContext *C, PaintStroke *stroke)
|
|||
operation->~GreasePencilStrokeOperation();
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Brush Stroke Operator
|
||||
* \{ */
|
||||
|
||||
static bool grease_pencil_brush_stroke_poll(bContext *C)
|
||||
{
|
||||
if (!ed::greasepencil::grease_pencil_painting_poll(C)) {
|
||||
|
@ -132,6 +107,37 @@ static bool grease_pencil_brush_stroke_poll(bContext *C)
|
|||
return true;
|
||||
}
|
||||
|
||||
static GreasePencilStrokeOperation *grease_pencil_brush_stroke_operation(bContext &C)
|
||||
{
|
||||
const Scene &scene = *CTX_data_scene(&C);
|
||||
const GpPaint &gp_paint = *scene.toolsettings->gp_paint;
|
||||
const Brush &brush = *BKE_paint_brush_for_read(&gp_paint.paint);
|
||||
switch (eBrushGPaintTool(brush.gpencil_tool)) {
|
||||
case GPAINT_TOOL_DRAW:
|
||||
/* FIXME: Somehow store the unique_ptr in the PaintStroke. */
|
||||
return greasepencil::new_paint_operation().release();
|
||||
case GPAINT_TOOL_ERASE:
|
||||
return greasepencil::new_erase_operation().release();
|
||||
case GPAINT_TOOL_FILL:
|
||||
return nullptr;
|
||||
case GPAINT_TOOL_TINT:
|
||||
return greasepencil::new_tint_operation().release();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static bool grease_pencil_brush_stroke_test_start(bContext *C,
|
||||
wmOperator *op,
|
||||
const float mouse[2])
|
||||
{
|
||||
GreasePencilStrokeOperation *operation = grease_pencil_brush_stroke_operation(*C);
|
||||
if (operation) {
|
||||
stroke_start(*C, *op, float2(mouse), *operation);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static int grease_pencil_brush_stroke_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
{
|
||||
const Scene *scene = CTX_data_scene(C);
|
||||
|
@ -168,7 +174,7 @@ static int grease_pencil_brush_stroke_invoke(bContext *C, wmOperator *op, const
|
|||
op->customdata = paint_stroke_new(C,
|
||||
op,
|
||||
stroke_get_location,
|
||||
stroke_test_start,
|
||||
grease_pencil_brush_stroke_test_start,
|
||||
stroke_update_step,
|
||||
stroke_redraw,
|
||||
stroke_done,
|
||||
|
@ -211,6 +217,140 @@ static void GREASE_PENCIL_OT_brush_stroke(wmOperatorType *ot)
|
|||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Sculpt Operator
|
||||
* \{ */
|
||||
|
||||
static bool grease_pencil_sculpt_paint_poll(bContext *C)
|
||||
{
|
||||
if (!ed::greasepencil::grease_pencil_sculpting_poll(C)) {
|
||||
return false;
|
||||
}
|
||||
if (!WM_toolsystem_active_tool_is_brush(C)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static GreasePencilStrokeOperation *grease_pencil_sculpt_paint_operation(bContext &C)
|
||||
{
|
||||
const Scene &scene = *CTX_data_scene(&C);
|
||||
const GpSculptPaint &gp_sculptpaint = *scene.toolsettings->gp_sculptpaint;
|
||||
const Brush &brush = *BKE_paint_brush_for_read(&gp_sculptpaint.paint);
|
||||
switch (eBrushGPSculptTool(brush.gpencil_sculpt_tool)) {
|
||||
case GPSCULPT_TOOL_SMOOTH:
|
||||
return nullptr;
|
||||
case GPSCULPT_TOOL_THICKNESS:
|
||||
return nullptr;
|
||||
case GPSCULPT_TOOL_STRENGTH:
|
||||
return nullptr;
|
||||
case GPSCULPT_TOOL_GRAB:
|
||||
return nullptr;
|
||||
case GPSCULPT_TOOL_PUSH:
|
||||
return nullptr;
|
||||
case GPSCULPT_TOOL_TWIST:
|
||||
return nullptr;
|
||||
case GPSCULPT_TOOL_PINCH:
|
||||
return nullptr;
|
||||
case GPSCULPT_TOOL_RANDOMIZE:
|
||||
return nullptr;
|
||||
case GPSCULPT_TOOL_CLONE:
|
||||
return nullptr;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static bool grease_pencil_sculpt_paint_test_start(bContext *C,
|
||||
wmOperator *op,
|
||||
const float mouse[2])
|
||||
{
|
||||
GreasePencilStrokeOperation *operation = grease_pencil_sculpt_paint_operation(*C);
|
||||
if (operation) {
|
||||
stroke_start(*C, *op, float2(mouse), *operation);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static int grease_pencil_sculpt_paint_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
{
|
||||
const Scene *scene = CTX_data_scene(C);
|
||||
const Object *object = CTX_data_active_object(C);
|
||||
if (!object || object->type != OB_GREASE_PENCIL) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
GreasePencil &grease_pencil = *static_cast<GreasePencil *>(object->data);
|
||||
if (!grease_pencil.has_active_layer()) {
|
||||
BKE_report(op->reports, RPT_ERROR, "No active Grease Pencil layer");
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
const Paint *paint = BKE_paint_get_active_from_context(C);
|
||||
const Brush *brush = BKE_paint_brush_for_read(paint);
|
||||
if (brush == nullptr) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
bke::greasepencil::Layer &active_layer = *grease_pencil.get_active_layer();
|
||||
|
||||
if (!active_layer.is_editable()) {
|
||||
BKE_report(op->reports, RPT_ERROR, "Active layer is locked or hidden");
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
/* Ensure a drawing at the current keyframe. */
|
||||
if (!ed::greasepencil::ensure_active_keyframe(*scene, grease_pencil)) {
|
||||
BKE_report(op->reports, RPT_ERROR, "No Grease Pencil frame to draw on");
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
op->customdata = paint_stroke_new(C,
|
||||
op,
|
||||
stroke_get_location,
|
||||
grease_pencil_sculpt_paint_test_start,
|
||||
stroke_update_step,
|
||||
stroke_redraw,
|
||||
stroke_done,
|
||||
event->type);
|
||||
|
||||
const int return_value = op->type->modal(C, op, event);
|
||||
if (return_value == OPERATOR_FINISHED) {
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
WM_event_add_modal_handler(C, op);
|
||||
return OPERATOR_RUNNING_MODAL;
|
||||
}
|
||||
|
||||
static int grease_pencil_sculpt_paint_modal(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
{
|
||||
return paint_stroke_modal(C, op, event, reinterpret_cast<PaintStroke **>(&op->customdata));
|
||||
}
|
||||
|
||||
static void grease_pencil_sculpt_paint_cancel(bContext *C, wmOperator *op)
|
||||
{
|
||||
paint_stroke_cancel(C, op, static_cast<PaintStroke *>(op->customdata));
|
||||
}
|
||||
|
||||
static void GREASE_PENCIL_OT_sculpt_paint(wmOperatorType *ot)
|
||||
{
|
||||
ot->name = "Grease Pencil Draw";
|
||||
ot->idname = "GREASE_PENCIL_OT_sculpt_paint";
|
||||
ot->description = "Draw a new stroke in the active Grease Pencil object";
|
||||
|
||||
ot->poll = grease_pencil_sculpt_paint_poll;
|
||||
ot->invoke = grease_pencil_sculpt_paint_invoke;
|
||||
ot->modal = grease_pencil_sculpt_paint_modal;
|
||||
ot->cancel = grease_pencil_sculpt_paint_cancel;
|
||||
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
|
||||
paint_stroke_operator_properties(ot);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Toggle Draw Mode
|
||||
* \{ */
|
||||
|
@ -306,6 +446,7 @@ void ED_operatortypes_grease_pencil_draw()
|
|||
{
|
||||
using namespace blender::ed::sculpt_paint;
|
||||
WM_operatortype_append(GREASE_PENCIL_OT_brush_stroke);
|
||||
WM_operatortype_append(GREASE_PENCIL_OT_sculpt_paint);
|
||||
WM_operatortype_append(GREASE_PENCIL_OT_draw_mode_toggle);
|
||||
}
|
||||
|
||||
|
|
|
@ -793,7 +793,7 @@ struct EraseOperationExecutor {
|
|||
erased = hard_eraser(src, screen_space_positions, dst, self.keep_caps);
|
||||
break;
|
||||
case GP_BRUSH_ERASER_SOFT:
|
||||
// To be implemented
|
||||
/* To be implemented. */
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -1220,6 +1220,7 @@ static bool paint_use_2d_cursor(PaintMode mode)
|
|||
case PaintMode::SculptGPencil:
|
||||
case PaintMode::WeightGPencil:
|
||||
case PaintMode::SculptCurves:
|
||||
case PaintMode::SculptGreasePencil:
|
||||
case PaintMode::GPencil:
|
||||
return true;
|
||||
case PaintMode::Invalid:
|
||||
|
|
|
@ -689,6 +689,9 @@ static int paintcurve_draw_exec(bContext *C, wmOperator * /*op*/)
|
|||
case PaintMode::GPencil:
|
||||
name = "GREASE_PENCIL_OT_brush_stroke";
|
||||
break;
|
||||
case PaintMode::SculptGreasePencil:
|
||||
name = "GREASE_PENCIL_OT_sculpt_paint";
|
||||
break;
|
||||
default:
|
||||
return OPERATOR_PASS_THROUGH;
|
||||
}
|
||||
|
|
|
@ -1041,7 +1041,7 @@ bool paint_space_stroke_enabled(Brush *br, PaintMode mode)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (mode == PaintMode::GPencil) {
|
||||
if (ELEM(mode, PaintMode::GPencil, PaintMode::SculptGreasePencil)) {
|
||||
/* No spacing needed for now. */
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -636,7 +636,7 @@ static void nla_draw_strip_text(AnimData *adt,
|
|||
else {
|
||||
col[0] = col[1] = col[2] = 255;
|
||||
}
|
||||
// Default strip to 100% opacity.
|
||||
/* Default strip to 100% opacity. */
|
||||
col[3] = 255;
|
||||
|
||||
/* Reduce text opacity if a track is soloed,
|
||||
|
|
|
@ -1403,6 +1403,10 @@ static void outliner_set_properties_tab(bContext *C, TreeElement *te, TreeStoreE
|
|||
ptr = RNA_pointer_create(tselem->id, &RNA_BoneCollection, te->directdata);
|
||||
context = BCONTEXT_DATA;
|
||||
break;
|
||||
case TSE_LAYER_COLLECTION:
|
||||
ptr = RNA_pointer_create(tselem->id, &RNA_Collection, te->directdata);
|
||||
context = BCONTEXT_COLLECTION;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -409,6 +409,10 @@ static void view3d_main_region_init(wmWindowManager *wm, ARegion *region)
|
|||
wm->defaultconf, "Grease Pencil Paint Mode", SPACE_EMPTY, RGN_TYPE_WINDOW);
|
||||
WM_event_add_keymap_handler(®ion->handlers, keymap);
|
||||
|
||||
keymap = WM_keymap_ensure(
|
||||
wm->defaultconf, "Grease Pencil Sculpt Mode", SPACE_EMPTY, RGN_TYPE_WINDOW);
|
||||
WM_event_add_keymap_handler(®ion->handlers, keymap);
|
||||
|
||||
/* Edit-font key-map swallows almost all (because of text input). */
|
||||
keymap = WM_keymap_ensure(wm->defaultconf, "Font", SPACE_EMPTY, RGN_TYPE_WINDOW);
|
||||
WM_event_add_keymap_handler(®ion->handlers, keymap);
|
||||
|
@ -1707,6 +1711,9 @@ void ED_view3d_buttons_region_layout_ex(const bContext *C,
|
|||
case CTX_MODE_PAINT_GREASE_PENCIL:
|
||||
ARRAY_SET_ITEMS(contexts, ".grease_pencil_paint");
|
||||
break;
|
||||
case CTX_MODE_SCULPT_GREASE_PENCIL:
|
||||
ARRAY_SET_ITEMS(contexts, ".paint_common", ".grease_pencil_sculpt");
|
||||
break;
|
||||
case CTX_MODE_EDIT_POINT_CLOUD:
|
||||
ARRAY_SET_ITEMS(contexts, ".point_cloud_edit");
|
||||
break;
|
||||
|
|
|
@ -291,6 +291,7 @@ static bool view3d_ruler_pick(wmGizmoGroup *gzgroup,
|
|||
}
|
||||
}
|
||||
}
|
||||
UNUSED_VARS(dist_best);
|
||||
|
||||
*r_co_index = co_index_best;
|
||||
return found;
|
||||
|
|
|
@ -733,53 +733,50 @@ struct BeztMap {
|
|||
};
|
||||
|
||||
/**
|
||||
* This function converts an FCurve's BezTriple array to a BeztMap array
|
||||
* NOTE: this allocates memory that will need to get freed later.
|
||||
* Converts an FCurve's BezTriple array to a BeztMap vector.
|
||||
*/
|
||||
static BeztMap *bezt_to_beztmaps(BezTriple *bezts, int totvert)
|
||||
static blender::Vector<BeztMap> bezt_to_beztmaps(BezTriple *bezts, const int totvert)
|
||||
{
|
||||
BezTriple *bezt = bezts;
|
||||
BezTriple *prevbezt = nullptr;
|
||||
BeztMap *bezm, *bezms;
|
||||
int i;
|
||||
|
||||
/* Allocate memory for this array. */
|
||||
if (totvert == 0 || bezts == nullptr) {
|
||||
return nullptr;
|
||||
return {};
|
||||
}
|
||||
bezm = bezms = static_cast<BeztMap *>(MEM_callocN(sizeof(BeztMap) * totvert, "BeztMaps"));
|
||||
|
||||
/* Assign beztriples to beztmaps. */
|
||||
for (i = 0; i < totvert; i++, bezm++, prevbezt = bezt, bezt++) {
|
||||
bezm->bezt = bezt;
|
||||
blender::Vector<BeztMap> bezms = blender::Vector<BeztMap>(totvert);
|
||||
|
||||
bezm->oldIndex = i;
|
||||
BezTriple *prevbezt = nullptr;
|
||||
for (const int i : bezms.index_range()) {
|
||||
BezTriple *bezt = &bezts[i];
|
||||
BeztMap &bezm = bezms[i];
|
||||
bezm.bezt = bezt;
|
||||
|
||||
bezm->prev_ipo = (prevbezt) ? prevbezt->ipo : bezt->ipo;
|
||||
bezm->current_ipo = bezt->ipo;
|
||||
bezm.oldIndex = i;
|
||||
|
||||
bezm.prev_ipo = (prevbezt) ? prevbezt->ipo : bezt->ipo;
|
||||
bezm.current_ipo = bezt->ipo;
|
||||
|
||||
prevbezt = bezt;
|
||||
}
|
||||
|
||||
return bezms;
|
||||
}
|
||||
|
||||
/* This function copies the code of sort_time_ipocurve, but acts on BeztMap structs instead. */
|
||||
static void sort_time_beztmaps(BeztMap *bezms, int totvert)
|
||||
static void sort_time_beztmaps(const blender::MutableSpan<BeztMap> bezms)
|
||||
{
|
||||
BeztMap *bezm;
|
||||
int i, ok = 1;
|
||||
bool ok = true;
|
||||
|
||||
/* Keep repeating the process until nothing is out of place anymore. */
|
||||
while (ok) {
|
||||
ok = 0;
|
||||
ok = false;
|
||||
|
||||
bezm = bezms;
|
||||
i = totvert;
|
||||
while (i--) {
|
||||
for (const int i : bezms.index_range()) {
|
||||
bezm = &bezms[i];
|
||||
/* Is current bezm out of order (i.e. occurs later than next)? */
|
||||
if (i > 0) {
|
||||
if (i < bezms.size() - 1) {
|
||||
if (bezm->bezt->vec[1][0] > (bezm + 1)->bezt->vec[1][0]) {
|
||||
std::swap(*bezm, *(bezm + 1));
|
||||
ok = 1;
|
||||
ok = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -797,34 +794,33 @@ static void sort_time_beztmaps(BeztMap *bezms, int totvert)
|
|||
bezm->swap_handles = -1;
|
||||
}
|
||||
}
|
||||
|
||||
bezm++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* This function firstly adjusts the pointers that the transdata has to each BezTriple. */
|
||||
static void beztmap_to_data(TransInfo *t, FCurve *fcu, BeztMap *bezms, int totvert)
|
||||
static void beztmap_to_data(TransInfo *t, FCurve *fcu, const blender::Span<BeztMap> bezms)
|
||||
{
|
||||
TransData2D *td2d;
|
||||
TransData *td;
|
||||
|
||||
TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
|
||||
|
||||
/* Dynamically allocate an array of chars to mark whether an TransData's
|
||||
* pointers have been fixed already, so that we don't override ones that are already done. */
|
||||
char *adjusted = static_cast<char *>(MEM_callocN(tc->data_len, "beztmap_adjusted_map"));
|
||||
/* Used to mark whether an TransData's pointers have been fixed already, so that we don't
|
||||
* override ones that are already done. */
|
||||
blender::Vector<bool> adjusted(tc->data_len, false);
|
||||
|
||||
/* For each beztmap item, find if it is used anywhere. */
|
||||
BeztMap *bezm = bezms;
|
||||
for (int i = 0; i < totvert; i++, bezm++) {
|
||||
const BeztMap *bezm;
|
||||
for (const int i : bezms.index_range()) {
|
||||
bezm = &bezms[i];
|
||||
/* Loop through transdata, testing if we have a hit
|
||||
* for the handles (vec[0]/vec[2]), we must also check if they need to be swapped. */
|
||||
td2d = tc->data_2d;
|
||||
td = tc->data;
|
||||
for (int j = 0; j < tc->data_len; j++, td2d++, td++) {
|
||||
/* Skip item if already marked. */
|
||||
if (adjusted[j] != 0) {
|
||||
if (adjusted[j]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -837,7 +833,7 @@ static void beztmap_to_data(TransInfo *t, FCurve *fcu, BeztMap *bezms, int totve
|
|||
else {
|
||||
td2d->loc2d = fcu->bezt[i].vec[0];
|
||||
}
|
||||
adjusted[j] = 1;
|
||||
adjusted[j] = true;
|
||||
}
|
||||
else if (td2d->loc2d == bezm->bezt->vec[2]) {
|
||||
if (bezm->swap_handles == 1) {
|
||||
|
@ -846,7 +842,7 @@ static void beztmap_to_data(TransInfo *t, FCurve *fcu, BeztMap *bezms, int totve
|
|||
else {
|
||||
td2d->loc2d = fcu->bezt[i].vec[2];
|
||||
}
|
||||
adjusted[j] = 1;
|
||||
adjusted[j] = true;
|
||||
}
|
||||
else if (td2d->loc2d == bezm->bezt->vec[1]) {
|
||||
td2d->loc2d = fcu->bezt[i].vec[1];
|
||||
|
@ -859,7 +855,7 @@ static void beztmap_to_data(TransInfo *t, FCurve *fcu, BeztMap *bezms, int totve
|
|||
td2d->h2 = fcu->bezt[i].vec[2];
|
||||
}
|
||||
|
||||
adjusted[j] = 1;
|
||||
adjusted[j] = true;
|
||||
}
|
||||
|
||||
/* The handle type pointer has to be updated too. */
|
||||
|
@ -875,9 +871,6 @@ static void beztmap_to_data(TransInfo *t, FCurve *fcu, BeztMap *bezms, int totve
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Free temp memory used for 'adjusted' array. */
|
||||
MEM_freeN(adjusted);
|
||||
}
|
||||
|
||||
/* This function is called by recalc_data during the Transform loop to recalculate
|
||||
|
@ -900,16 +893,11 @@ static void remake_graph_transdata(TransInfo *t, const blender::Span<FCurve *> f
|
|||
continue;
|
||||
}
|
||||
|
||||
BeztMap *bezm;
|
||||
|
||||
/* Adjust transform-data pointers. */
|
||||
/* NOTE: none of these functions use 'use_handle', it could be removed. */
|
||||
bezm = bezt_to_beztmaps(fcu->bezt, fcu->totvert);
|
||||
sort_time_beztmaps(bezm, fcu->totvert);
|
||||
beztmap_to_data(t, fcu, bezm, fcu->totvert);
|
||||
|
||||
/* Free mapping stuff. */
|
||||
MEM_freeN(bezm);
|
||||
blender::Vector<BeztMap> bezms = bezt_to_beztmaps(fcu->bezt, fcu->totvert);
|
||||
sort_time_beztmaps(bezms);
|
||||
beztmap_to_data(t, fcu, bezms);
|
||||
|
||||
/* Re-sort actual beztriples
|
||||
* (perhaps this could be done using the beztmaps to save time?). */
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "BLI_span.hh"
|
||||
|
||||
#include "GPU_primitive.hh"
|
||||
|
||||
#define GPU_TRACK_INDEX_RANGE 1
|
||||
|
@ -154,6 +156,8 @@ blender::gpu::IndexBuf *GPU_indexbuf_build_on_device(uint index_len);
|
|||
|
||||
void GPU_indexbuf_init_build_on_device(blender::gpu::IndexBuf *elem, uint index_len);
|
||||
|
||||
blender::MutableSpan<uint32_t> GPU_indexbuf_get_data(GPUIndexBufBuilder *);
|
||||
|
||||
/*
|
||||
* Thread safe.
|
||||
*
|
||||
|
@ -180,6 +184,26 @@ void GPU_indexbuf_set_tri_restart(GPUIndexBufBuilder *builder, uint elem);
|
|||
|
||||
blender::gpu::IndexBuf *GPU_indexbuf_build(GPUIndexBufBuilder *);
|
||||
void GPU_indexbuf_build_in_place(GPUIndexBufBuilder *, blender::gpu::IndexBuf *);
|
||||
void GPU_indexbuf_build_in_place_ex(GPUIndexBufBuilder *builder,
|
||||
uint index_min,
|
||||
uint index_max,
|
||||
bool uses_restart_indices,
|
||||
blender::gpu::IndexBuf *elem);
|
||||
|
||||
/**
|
||||
* Fill an IBO by uploading the referenced data directly to the GPU, bypassing the separate storage
|
||||
* in the IBO. This should be used whenever the equivalent indices already exist in a contiguous
|
||||
* array on the CPU.
|
||||
*
|
||||
* \todo The optimization to avoid the local copy currently isn't implemented.
|
||||
*/
|
||||
void GPU_indexbuf_build_in_place_from_memory(blender::gpu::IndexBuf *ibo,
|
||||
GPUPrimType prim_type,
|
||||
const uint32_t *data,
|
||||
int32_t data_len,
|
||||
int32_t index_min,
|
||||
int32_t index_max,
|
||||
bool uses_restart_indices);
|
||||
|
||||
void GPU_indexbuf_bind_as_ssbo(blender::gpu::IndexBuf *elem, int binding);
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BLI_array_utils.hh"
|
||||
#include "BLI_math_base.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
|
@ -96,6 +97,11 @@ void GPU_indexbuf_init_build_on_device(IndexBuf *elem, uint index_len)
|
|||
elem_->init_build_on_device(index_len);
|
||||
}
|
||||
|
||||
blender::MutableSpan<uint32_t> GPU_indexbuf_get_data(GPUIndexBufBuilder *builder)
|
||||
{
|
||||
return {builder->data, builder->max_index_len};
|
||||
}
|
||||
|
||||
void GPU_indexbuf_join(GPUIndexBufBuilder *builder_to, const GPUIndexBufBuilder *builder_from)
|
||||
{
|
||||
BLI_assert(builder_to->data == builder_from->data);
|
||||
|
@ -492,6 +498,43 @@ void GPU_indexbuf_build_in_place(GPUIndexBufBuilder *builder, IndexBuf *elem)
|
|||
builder->data = nullptr;
|
||||
}
|
||||
|
||||
void GPU_indexbuf_build_in_place_ex(GPUIndexBufBuilder *builder,
|
||||
const uint index_min,
|
||||
const uint index_max,
|
||||
const bool uses_restart_indices,
|
||||
IndexBuf *elem)
|
||||
{
|
||||
BLI_assert(builder->data != nullptr);
|
||||
/* Transfer data ownership to IndexBuf.
|
||||
* It will be uploaded upon first use. */
|
||||
elem->init(builder->max_index_len,
|
||||
builder->data,
|
||||
index_min,
|
||||
index_max,
|
||||
builder->prim_type,
|
||||
uses_restart_indices);
|
||||
builder->data = nullptr;
|
||||
}
|
||||
|
||||
void GPU_indexbuf_build_in_place_from_memory(IndexBuf *ibo,
|
||||
const GPUPrimType prim_type,
|
||||
const uint32_t *data,
|
||||
const int32_t data_len,
|
||||
const int32_t index_min,
|
||||
const int32_t index_max,
|
||||
const bool uses_restart_indices)
|
||||
{
|
||||
const uint32_t indices_num = data_len * indices_per_primitive(prim_type);
|
||||
/* TODO: The need for this copy is meant to be temporary. The data should be uploaded directly to
|
||||
* the GPU here rather than copied to an array owned by the IBO first. */
|
||||
uint32_t *copy = static_cast<uint32_t *>(
|
||||
MEM_malloc_arrayN(indices_num, sizeof(uint32_t), __func__));
|
||||
threading::memory_bandwidth_bound_task(sizeof(uint32_t) * indices_num * 2, [&]() {
|
||||
array_utils::copy(Span(data, indices_num), MutableSpan(copy, indices_num));
|
||||
});
|
||||
ibo->init(indices_num, copy, index_min, index_max, prim_type, uses_restart_indices);
|
||||
}
|
||||
|
||||
void GPU_indexbuf_create_subrange_in_place(IndexBuf *elem,
|
||||
IndexBuf *elem_src,
|
||||
uint start,
|
||||
|
|
|
@ -2215,8 +2215,14 @@ void gpu::MTLTexture::prepare_internal()
|
|||
* bandwidth implications for lossless compression and is considered best-practice.
|
||||
*
|
||||
* Attachment usage also required for depth-stencil attachment targets, for depth-update support.
|
||||
* NOTE: Emulated atomic textures cannot support render-target usage. For clearing, the backing
|
||||
* buffer is cleared instead.
|
||||
*/
|
||||
gpu_image_usage_flags_ |= GPU_TEXTURE_USAGE_ATTACHMENT;
|
||||
if (!((gpu_image_usage_flags_ & GPU_TEXTURE_USAGE_ATOMIC) &&
|
||||
!MTLBackend::get_capabilities().supports_texture_atomics))
|
||||
{
|
||||
gpu_image_usage_flags_ |= GPU_TEXTURE_USAGE_ATTACHMENT;
|
||||
}
|
||||
|
||||
/* Derive maximum number of mip levels by default.
|
||||
* TODO(Metal): This can be removed if max mip counts are specified upfront. */
|
||||
|
|
|
@ -103,7 +103,9 @@ void VKBackend::detect_workarounds(VKDevice &device)
|
|||
!device.physical_device_vulkan_12_features_get().shaderOutputViewportIndex;
|
||||
|
||||
/* AMD GPUs don't support texture formats that use are aligned to 24 or 48 bits. */
|
||||
if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_ANY)) {
|
||||
if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_ANY) ||
|
||||
GPU_type_matches(GPU_DEVICE_APPLE, GPU_OS_MAC, GPU_DRIVER_ANY))
|
||||
{
|
||||
workarounds.not_aligned_pixel_formats = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ class VKVertexAttributeObject {
|
|||
|
||||
void bind(VKContext &context);
|
||||
|
||||
// Copy assignment operator.
|
||||
/** Copy assignment operator. */
|
||||
VKVertexAttributeObject &operator=(const VKVertexAttributeObject &other);
|
||||
|
||||
void update_bindings(const VKContext &context, VKBatch &batch);
|
||||
|
|
|
@ -48,13 +48,13 @@ void ArmatureExporter::add_bone_collections(Object *ob_arm, COLLADASW::Node &nod
|
|||
|
||||
std::string collection_names = collection_stream.str();
|
||||
if (collection_names.length() > 1) {
|
||||
collection_names.pop_back(); // Pop off the last \n.
|
||||
collection_names.pop_back(); /* Pop off the last `\n`. */
|
||||
node.addExtraTechniqueParameter("blender", "collections", collection_names);
|
||||
}
|
||||
|
||||
std::string visible_names = visible_stream.str();
|
||||
if (visible_names.length() > 1) {
|
||||
visible_names.pop_back(); // Pop off the last \n.
|
||||
visible_names.pop_back(); /* Pop off the last `\n`. */
|
||||
node.addExtraTechniqueParameter("blender", "visible_collections", visible_names);
|
||||
}
|
||||
|
||||
|
@ -195,7 +195,7 @@ void ArmatureExporter::add_bone_node(Bone *bone,
|
|||
collection_names += std::string(bcoll_ref->bcoll->name) + "\n";
|
||||
}
|
||||
if (collection_names.length() > 1) {
|
||||
collection_names.pop_back(); // Pop off the last \n.
|
||||
collection_names.pop_back(); /* Pop off the last `\n`. */
|
||||
node.addExtraTechniqueParameter("blender", "", collection_names, "", "collections");
|
||||
}
|
||||
|
||||
|
|
|
@ -77,10 +77,14 @@ void export_frame(Depsgraph *depsgraph,
|
|||
std::replace(object_name.begin(), object_name.end(), ' ', '_');
|
||||
|
||||
/* Include object name in the exported file name. */
|
||||
std::string suffix = object_name + ".stl";
|
||||
char filepath[FILE_MAX];
|
||||
STRNCPY(filepath, export_params.filepath);
|
||||
BLI_path_extension_replace(filepath, FILE_MAX, suffix.c_str());
|
||||
BLI_path_suffix(filepath, FILE_MAX, object_name.c_str(), "");
|
||||
/* Make sure we have .stl extension (case insensitive). */
|
||||
if (!BLI_path_extension_check(filepath, ".stl")) {
|
||||
BLI_path_extension_ensure(filepath, FILE_MAX, ".stl");
|
||||
}
|
||||
|
||||
try {
|
||||
writer = std::make_unique<FileWriter>(filepath, export_params.ascii_format);
|
||||
}
|
||||
|
|
|
@ -70,7 +70,7 @@ std::string add_unique_name(blender::Set<std::string> &names, const std::string
|
|||
return unique_name;
|
||||
}
|
||||
|
||||
} // End anonymous namespace.
|
||||
} // namespace
|
||||
|
||||
namespace blender::io::usd {
|
||||
|
||||
|
|
|
@ -491,7 +491,7 @@ bool USD_export(bContext *C,
|
|||
if (!collection) {
|
||||
BKE_reportf(job->params.worker_status->reports,
|
||||
RPT_ERROR,
|
||||
"USD Export: Unable to find collection %s",
|
||||
"USD Export: Unable to find collection '%s'",
|
||||
job->params.collection);
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -765,4 +765,4 @@ UsdPathSet USDStageReader::collect_point_instancer_proto_paths() const
|
|||
return result;
|
||||
}
|
||||
|
||||
} // Namespace blender::io::usd
|
||||
} // namespace blender::io::usd
|
||||
|
|
|
@ -372,7 +372,7 @@ void add_skinned_mesh_bindings(const pxr::UsdSkelSkeleton &skel,
|
|||
}
|
||||
}
|
||||
|
||||
} // End anonymous namespace.
|
||||
} // namespace
|
||||
|
||||
namespace blender::io::usd {
|
||||
|
||||
|
|
|
@ -339,7 +339,7 @@ void exporter_main(bContext *C, const OBJExportParams &export_params)
|
|||
if (!collection) {
|
||||
BKE_reportf(export_params.reports,
|
||||
RPT_ERROR,
|
||||
"OBJ Export: Unable to find collection %s",
|
||||
"OBJ Export: Unable to find collection '%s'",
|
||||
export_params.collection);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -853,21 +853,6 @@ enum {
|
|||
/** \name Render Conversion/Simplification Settings
|
||||
* \{ */
|
||||
|
||||
/** Control render convert and shading engine. */
|
||||
typedef struct RenderProfile {
|
||||
struct RenderProfile *next, *prev;
|
||||
char name[32];
|
||||
|
||||
short particle_perc;
|
||||
short subsurf_max;
|
||||
short shadbufsample_max;
|
||||
char _pad1[2];
|
||||
|
||||
float ao_error;
|
||||
char _pad2[4];
|
||||
|
||||
} RenderProfile;
|
||||
|
||||
/* UV Paint. */
|
||||
/** #ToolSettings::uv_sculpt_settings */
|
||||
enum {
|
||||
|
|
|
@ -483,12 +483,15 @@ typedef struct ThemeStripColor {
|
|||
/**
|
||||
* A theme.
|
||||
*
|
||||
* \note Currently only a single theme is ever used at once.
|
||||
* \note Currently only the first theme is used at once.
|
||||
* Different theme presets are stored as external files now.
|
||||
*/
|
||||
typedef struct bTheme {
|
||||
struct bTheme *next, *prev;
|
||||
char name[32];
|
||||
/** #MAX_NAME. */
|
||||
char name[64];
|
||||
|
||||
/* NOTE: Values after `name` are copied when resetting the default theme. */
|
||||
|
||||
ThemeUI tui;
|
||||
|
||||
|
@ -854,6 +857,10 @@ typedef struct UserDef {
|
|||
/** Startup application template. */
|
||||
char app_template[64];
|
||||
|
||||
/**
|
||||
* A list of themes (#bTheme), the first is only used currently.
|
||||
* But there may be multiple themes in the list.
|
||||
*/
|
||||
struct ListBase themes;
|
||||
struct ListBase uifonts;
|
||||
struct ListBase uistyles;
|
||||
|
|
|
@ -765,7 +765,7 @@ StructRNA *ID_code_to_RNA_type(short idcode);
|
|||
#if defined __GNUC__
|
||||
# define RNA_warning(format, args...) _RNA_warning("%s: " format "\n", __func__, ##args)
|
||||
#elif defined(_MSVC_TRADITIONAL) && \
|
||||
!_MSVC_TRADITIONAL // The "new preprocessor" is enabled via /Zc:preprocessor
|
||||
!_MSVC_TRADITIONAL /* The "new preprocessor" is enabled via `/Zc:preprocessor`. */
|
||||
# define RNA_warning(format, ...) _RNA_warning("%s: " format "\n", __FUNCTION__, ##__VA_ARGS__)
|
||||
#else
|
||||
# define RNA_warning(format, ...) _RNA_warning("%s: " format "\n", __FUNCTION__, __VA_ARGS__)
|
||||
|
|
|
@ -498,7 +498,7 @@ static bool rna_property_override_operation_store(Main *bmain,
|
|||
}
|
||||
}
|
||||
|
||||
if (ptr_storage != nullptr && prop_storage->magic == RNA_MAGIC &&
|
||||
if ((prop_storage->magic == RNA_MAGIC) &&
|
||||
!ELEM(prop_storage->override_store, nullptr, override_store))
|
||||
{
|
||||
override_store = nullptr;
|
||||
|
|
|
@ -46,6 +46,7 @@ const EnumPropertyItem rna_enum_context_mode_items[] = {
|
|||
{CTX_MODE_VERTEX_GPENCIL_LEGACY, "VERTEX_GPENCIL", 0, "Grease Pencil Vertex Paint", ""},
|
||||
{CTX_MODE_SCULPT_CURVES, "SCULPT_CURVES", 0, "Curves Sculpt", ""},
|
||||
{CTX_MODE_PAINT_GREASE_PENCIL, "PAINT_GREASE_PENCIL", 0, "Grease Pencil Paint", ""},
|
||||
{CTX_MODE_SCULPT_GREASE_PENCIL, "SCULPT_GREASE_PENCIL", 0, "Grease Pencil Sculpt", ""},
|
||||
{0, nullptr, 0, nullptr, nullptr},
|
||||
};
|
||||
|
||||
|
|
|
@ -1021,6 +1021,13 @@ static int rna_lang_enum_properties_get_no_international(PointerRNA * /*ptr*/)
|
|||
}
|
||||
# endif
|
||||
|
||||
static void rna_Theme_name_set(PointerRNA *ptr, const char *value)
|
||||
{
|
||||
bTheme *btheme = static_cast<bTheme *>(ptr->data);
|
||||
STRNCPY_UTF8(btheme->name, value);
|
||||
BLI_uniquename(&U.themes, btheme, "Theme", '.', offsetof(bTheme, name), sizeof(btheme->name));
|
||||
}
|
||||
|
||||
static void rna_Addon_module_set(PointerRNA *ptr, const char *value)
|
||||
{
|
||||
bAddon *addon = (bAddon *)ptr->data;
|
||||
|
@ -2168,7 +2175,7 @@ static void rna_def_userdef_theme_spaces_asset_shelf_main(StructRNA *srna)
|
|||
RNA_def_property_ui_text(prop, "Asset Shelf", "Settings for asset shelf");
|
||||
}
|
||||
|
||||
static void rna_def_userdef_theme_spaces_vertex(StructRNA *srna)
|
||||
static void rna_def_userdef_theme_spaces_vertex(StructRNA *srna, const bool has_vertex_active)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
|
||||
|
@ -2182,10 +2189,12 @@ static void rna_def_userdef_theme_spaces_vertex(StructRNA *srna)
|
|||
RNA_def_property_ui_text(prop, "Vertex Select", "");
|
||||
RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
|
||||
|
||||
prop = RNA_def_property(srna, "vertex_active", PROP_FLOAT, PROP_COLOR_GAMMA);
|
||||
RNA_def_property_array(prop, 3);
|
||||
RNA_def_property_ui_text(prop, "Active Vertex", "");
|
||||
RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
|
||||
if (has_vertex_active) {
|
||||
prop = RNA_def_property(srna, "vertex_active", PROP_FLOAT, PROP_COLOR_GAMMA);
|
||||
RNA_def_property_array(prop, 3);
|
||||
RNA_def_property_ui_text(prop, "Active Vertex", "");
|
||||
RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
|
||||
}
|
||||
|
||||
prop = RNA_def_property(srna, "vertex_size", PROP_INT, PROP_PIXEL);
|
||||
RNA_def_property_range(prop, 1, 32);
|
||||
|
@ -2561,7 +2570,7 @@ static void rna_def_userdef_theme_space_view3d(BlenderRNA *brna)
|
|||
|
||||
/* Mesh Object specific */
|
||||
|
||||
rna_def_userdef_theme_spaces_vertex(srna);
|
||||
rna_def_userdef_theme_spaces_vertex(srna, false);
|
||||
rna_def_userdef_theme_spaces_edge(srna);
|
||||
rna_def_userdef_theme_spaces_face(srna);
|
||||
|
||||
|
@ -2773,7 +2782,7 @@ static void rna_def_userdef_theme_space_graph(BlenderRNA *brna)
|
|||
RNA_def_property_ui_text(prop, "Preview Range", "Color of preview range overlay");
|
||||
RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
|
||||
|
||||
rna_def_userdef_theme_spaces_vertex(srna);
|
||||
rna_def_userdef_theme_spaces_vertex(srna, true);
|
||||
rna_def_userdef_theme_spaces_curves(srna, false, true, true, true);
|
||||
}
|
||||
|
||||
|
@ -3339,7 +3348,7 @@ static void rna_def_userdef_theme_space_image(BlenderRNA *brna)
|
|||
RNA_def_property_ui_text(prop, "Grid", "");
|
||||
RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
|
||||
|
||||
rna_def_userdef_theme_spaces_vertex(srna);
|
||||
rna_def_userdef_theme_spaces_vertex(srna, false);
|
||||
rna_def_userdef_theme_spaces_face(srna);
|
||||
|
||||
prop = RNA_def_property(srna, "editmesh_active", PROP_FLOAT, PROP_COLOR_GAMMA);
|
||||
|
@ -4287,6 +4296,7 @@ static void rna_def_userdef_themes(BlenderRNA *brna)
|
|||
|
||||
prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_ui_text(prop, "Name", "Name of the theme");
|
||||
RNA_def_property_string_funcs(prop, nullptr, nullptr, "rna_Theme_name_set");
|
||||
RNA_def_struct_name_property(srna, prop);
|
||||
/* XXX: for now putting this in presets is silly - its just Default */
|
||||
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
||||
|
|
|
@ -62,18 +62,17 @@ static PyObject *pygpu_compute_dispatch(PyObject * /*self*/, PyObject *args, PyO
|
|||
if (_PyArg_ParseTupleAndKeywordsFast(
|
||||
args, kwds, &_parser, &py_shader, &groups_x_len, &groups_y_len, &groups_z_len))
|
||||
{
|
||||
|
||||
if (!BPyGPUShader_Check(py_shader)) {
|
||||
PyErr_Format(PyExc_TypeError, "Expected a GPUShader, got %s", Py_TYPE(py_shader)->tp_name);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Check that groups do not exceed GPU_max_work_group_count()
|
||||
/* Check that groups do not exceed #GPU_max_work_group_count(). */
|
||||
const int max_work_group_count_x = GPU_max_work_group_count(0);
|
||||
const int max_work_group_count_y = GPU_max_work_group_count(1);
|
||||
const int max_work_group_count_z = GPU_max_work_group_count(2);
|
||||
|
||||
// Report back to the user both the requested and the maximum supported value
|
||||
/* Report back to the user both the requested and the maximum supported value. */
|
||||
if (groups_x_len > GPU_max_work_group_count(0)) {
|
||||
PyErr_Format(PyExc_ValueError,
|
||||
"groups_x_len (%d) exceeds maximum supported value (max work group count: %d)",
|
||||
|
|
|
@ -45,7 +45,7 @@ void SEQ_for_each_callback(ListBase *seqbase, SeqForEachFunc callback, void *use
|
|||
seq_for_each_recursive(seqbase, callback, user_data);
|
||||
}
|
||||
|
||||
VectorSet<Sequence *> SEQ_query_by_reference(Sequence *reference_strip,
|
||||
VectorSet<Sequence *> SEQ_query_by_reference(Sequence *seq_reference,
|
||||
const Scene *scene,
|
||||
ListBase *seqbase,
|
||||
void seq_query_func(const Scene *scene,
|
||||
|
@ -54,7 +54,7 @@ VectorSet<Sequence *> SEQ_query_by_reference(Sequence *reference_strip,
|
|||
VectorSet<Sequence *> &strips))
|
||||
{
|
||||
VectorSet<Sequence *> strips;
|
||||
seq_query_func(scene, reference_strip, seqbase, strips);
|
||||
seq_query_func(scene, seq_reference, seqbase, strips);
|
||||
return strips;
|
||||
}
|
||||
|
||||
|
|
|
@ -272,7 +272,7 @@ void *SEQ_sound_equalizermodifier_recreator(Sequence *seq, SequenceModifierData
|
|||
|
||||
SoundEqualizerModifierData *semd = (SoundEqualizerModifierData *)smd;
|
||||
|
||||
// No Equalizer definition
|
||||
/* No equalizer definition. */
|
||||
if (BLI_listbase_is_empty(&semd->graphics)) {
|
||||
return sound;
|
||||
}
|
||||
|
@ -286,7 +286,7 @@ void *SEQ_sound_equalizermodifier_recreator(Sequence *seq, SequenceModifierData
|
|||
float maxX;
|
||||
float interval = SOUND_EQUALIZER_DEFAULT_MAX_FREQ / float(SOUND_EQUALIZER_SIZE_DEFINITION);
|
||||
|
||||
// Visit all equalizer definitions
|
||||
/* Visit all equalizer definitions. */
|
||||
LISTBASE_FOREACH (EQCurveMappingData *, mapping, &semd->graphics) {
|
||||
eq_mapping = &mapping->curve_mapping;
|
||||
BKE_curvemapping_init(eq_mapping);
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue