UI: Asset Shelf (Experimental Feature) #104831

Closed
Julian Eisel wants to merge 399 commits from asset-shelf into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
208 changed files with 2192 additions and 204768 deletions
Showing only changes of commit 4093e3c6db - Show all commits

View File

@ -693,7 +693,7 @@ if(UNIX)
if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang")
option(WITH_LINKER_LLD "Use ld.lld linker which is usually faster than ld.gold" OFF)
mark_as_advanced(WITH_LINKER_LLD)
option(WITH_LINKER_MOLD "Use ld.mold linker which is usually faster than ld.gold & ld.lld. Needs \"sold\" subscription on macOS." OFF)
option(WITH_LINKER_MOLD "Use ld.mold linker which is usually faster than ld.gold & ld.lld" OFF)
mark_as_advanced(WITH_LINKER_MOLD)
endif()
endif()

View File

@ -269,6 +269,20 @@ DEPS_CRITICAL_SUBPACKAGES = (
DISTRO_ID_ARCH: "dbus",
},
),
Package(name="OpenGL Library",
distro_package_names={DISTRO_ID_DEBIAN: "libgl-dev",
DISTRO_ID_FEDORA: "mesa-libGL-devel",
DISTRO_ID_SUSE: "Mesa-libGL-devel",
DISTRO_ID_ARCH: "libglvnd",
},
),
Package(name="EGL Library",
distro_package_names={DISTRO_ID_DEBIAN: "libegl-dev",
DISTRO_ID_FEDORA: "mesa-libEGL-devel",
DISTRO_ID_SUSE: "Mesa-libEGL-devel",
DISTRO_ID_ARCH: None, # Included in `libglvnd`.
},
),
)

View File

@ -186,8 +186,6 @@ endif()
# C++ standards conformace (/permissive-) is available on msvc 15.5 (1912) and up
if(NOT MSVC_CLANG)
string(APPEND CMAKE_CXX_FLAGS " /permissive-")
# Two-phase name lookup does not place nicely with OpenMP yet, so disable for now
string(APPEND CMAKE_CXX_FLAGS " /Zc:twoPhase-")
endif()
if(WITH_WINDOWS_SCCACHE AND CMAKE_VS_MSBUILD_COMMAND)

View File

@ -39,6 +39,7 @@ shader node_normal_map(float Strength = 1.0,
/* apply strength */
mcolor[0] *= Strength;
mcolor[1] *= Strength;
mcolor[2] = mix(1.0, mcolor[2], clamp(Strength, 0.0, 1.0));
Normal = normalize(mcolor[0] * tangent + mcolor[1] * B + mcolor[2] * ninterp);

View File

@ -316,6 +316,7 @@ ccl_device_noinline void svm_node_normal_map(KernelGlobals kg,
/* Apply strength in the tangent case. */
color.x *= strength;
color.y *= strength;
color.z = mix(1.0f, color.z, saturatef(strength));
/* apply normal map */
float3 B = sign * cross(normal, tangent);

View File

@ -154,7 +154,7 @@ extern void GHOST_GetAllDisplayDimensions(GHOST_SystemHandle systemhandle,
* The new window is added to the list of windows managed.
* Never explicitly delete the window, use disposeWindow() instead.
* \param systemhandle: The handle to the system.
* \param parent_windowhandle: Handle of parent (or owner) window, or NULL
* \param parent_windowhandle: Handle of parent (or owner) window, or nullptr
* \param title: The name of the window.
* (displayed in the title bar of the window if the OS supports it).
* \param left: The coordinate of the left edge of the window.
@ -164,7 +164,7 @@ extern void GHOST_GetAllDisplayDimensions(GHOST_SystemHandle systemhandle,
* \param state: The state of the window when opened.
* \param is_dialog: Stay on top of parent window, no icon in taskbar, can't be minimized.
* \param gpuSettings: Misc GPU options.
* \return A handle to the new window ( == NULL if creation failed).
* \return A handle to the new window ( == nullptr if creation failed).
*/
extern GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle,
GHOST_WindowHandle parent_windowhandle,
@ -182,7 +182,7 @@ extern GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle,
* Never explicitly delete the context, use #disposeContext() instead.
* \param systemhandle: The handle to the system.
* \param gpuSettings: Misc GPU options.
* \return A handle to the new context ( == NULL if creation failed).
* \return A handle to the new context ( == nullptr if creation failed).
*/
extern GHOST_ContextHandle GHOST_CreateGPUContext(GHOST_SystemHandle systemhandle,
GHOST_GPUSettings gpuSettings);
@ -495,7 +495,7 @@ extern uint64_t GHOST_GetEventTime(GHOST_EventHandle eventhandle);
/**
* Returns the window this event was generated on,
* or NULL if it is a 'system' event.
* or nullptr if it is a 'system' event.
* \param eventhandle: The handle to the event.
* \return The generating window.
*/
@ -951,7 +951,7 @@ extern bool GHOST_UseNativePixels(void);
extern GHOST_TCapabilityFlag GHOST_GetCapabilities(void);
/**
* Assign the callback which generates a back-trace (may be NULL).
* Assign the callback which generates a back-trace (may be nullptr).
*/
extern void GHOST_SetBacktraceHandler(GHOST_TBacktraceFn backtrace_fn);
@ -1081,7 +1081,7 @@ int GHOST_XrSessionNeedsUpsideDownDrawing(const GHOST_XrContextHandle xr_context
/* events */
/**
* Invoke handling of all OpenXR events for \a xr_context. Should be called on every main-loop
* iteration and will early-exit if \a xr_context is NULL (so caller doesn't have to check).
* iteration and will early-exit if \a xr_context is nullptr (so caller doesn't have to check).
*
* \returns GHOST_kSuccess if any event was handled, otherwise GHOST_kFailure.
*/
@ -1139,7 +1139,7 @@ int GHOST_XrAttachActionSets(GHOST_XrContextHandle xr_context);
/**
* Update button/tracking states for OpenXR actions.
*
* \param action_set_name: The name of the action set to sync. If NULL, all action sets
* \param action_set_name: The name of the action set to sync. If nullptr, all action sets
* attached to the session will be synced.
*/
int GHOST_XrSyncActions(GHOST_XrContextHandle xr_context, const char *action_set_name);

View File

@ -45,7 +45,7 @@ class GHOST_IEvent {
/**
* Returns the window this event was generated on,
* or NULL if it is a 'system' event.
* or nullptr if it is a 'system' event.
* \return The generating window.
*/
virtual GHOST_IWindow *getWindow() = 0;

View File

@ -61,7 +61,7 @@ class GHOST_IEventConsumer;
* - Windows.
* - X11.
* - SDL2 (experimental).
* - NULL (headless mode).
* - null (headless mode).
*
* \section Building GHOST
*
@ -189,7 +189,7 @@ class GHOST_ISystem {
virtual GHOST_ITimerTask *installTimer(uint64_t delay,
uint64_t interval,
GHOST_TimerProcPtr timerProc,
GHOST_TUserDataPtr userData = NULL) = 0;
GHOST_TUserDataPtr userData = nullptr) = 0;
/**
* Removes a timer.
@ -246,7 +246,7 @@ class GHOST_ISystem {
GHOST_GPUSettings gpuSettings,
const bool exclusive = false,
const bool is_dialog = false,
const GHOST_IWindow *parentWindow = NULL) = 0;
const GHOST_IWindow *parentWindow = nullptr) = 0;
/**
* Dispose a window.

View File

@ -647,7 +647,7 @@ typedef struct {
/** The key code. */
GHOST_TKey key;
/** The unicode character. if the length is 6, not NULL terminated if all 6 are set. */
/** The unicode character. if the length is 6, not nullptr terminated if all 6 are set. */
char utf8_buf[6];
/**

View File

@ -12,7 +12,7 @@
#include "GHOST_IContext.hh"
#include "GHOST_Types.h"
#include <cstdlib> // for NULL
#include <cstdlib> // for nullptr
class GHOST_Context : public GHOST_IContext {
public:
@ -232,7 +232,7 @@ class GHOST_Context : public GHOST_IContext {
};
#ifdef _WIN32
bool win32_chk(bool result, const char *file = NULL, int line = 0, const char *text = NULL);
bool win32_chk(bool result, const char *file = nullptr, int line = 0, const char *text = nullptr);
bool win32_silent_chk(bool result);
# ifndef NDEBUG

View File

@ -17,8 +17,8 @@
#include "GHOST_ContextD3D.hh"
#include "GHOST_ContextWGL.hh" /* For shared drawing */
HMODULE GHOST_ContextD3D::s_d3d_lib = NULL;
PFN_D3D11_CREATE_DEVICE GHOST_ContextD3D::s_D3D11CreateDeviceFn = NULL;
HMODULE GHOST_ContextD3D::s_d3d_lib = nullptr;
PFN_D3D11_CREATE_DEVICE GHOST_ContextD3D::s_D3D11CreateDeviceFn = nullptr;
GHOST_ContextD3D::GHOST_ContextD3D(bool stereoVisual, HWND hWnd)
: GHOST_Context(stereoVisual), m_hWnd(hWnd)
@ -49,24 +49,24 @@ GHOST_TSuccess GHOST_ContextD3D::releaseDrawingContext()
GHOST_TSuccess GHOST_ContextD3D::setupD3DLib()
{
if (s_d3d_lib == NULL) {
if (s_d3d_lib == nullptr) {
s_d3d_lib = LoadLibraryA("d3d11.dll");
WIN32_CHK(s_d3d_lib != NULL);
WIN32_CHK(s_d3d_lib != nullptr);
if (s_d3d_lib == NULL) {
if (s_d3d_lib == nullptr) {
fprintf(stderr, "LoadLibrary(\"d3d11.dll\") failed!\n");
return GHOST_kFailure;
}
}
if (s_D3D11CreateDeviceFn == NULL) {
if (s_D3D11CreateDeviceFn == nullptr) {
s_D3D11CreateDeviceFn = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(s_d3d_lib,
"D3D11CreateDevice");
WIN32_CHK(s_D3D11CreateDeviceFn != NULL);
WIN32_CHK(s_D3D11CreateDeviceFn != nullptr);
if (s_D3D11CreateDeviceFn == NULL) {
if (s_D3D11CreateDeviceFn == nullptr) {
fprintf(stderr, "GetProcAddress(s_d3d_lib, \"D3D11CreateDevice\") failed!\n");
return GHOST_kFailure;
}
@ -82,19 +82,19 @@ GHOST_TSuccess GHOST_ContextD3D::initializeDrawingContext()
}
HRESULT hres = s_D3D11CreateDeviceFn(
NULL,
nullptr,
D3D_DRIVER_TYPE_HARDWARE,
NULL,
nullptr,
/* For debugging you may want to pass D3D11_CREATE_DEVICE_DEBUG here, but that requires
* additional setup, see
* https://docs.microsoft.com/en-us/windows/win32/direct3d11/overviews-direct3d-11-devices-layers#debug-layer.
*/
0,
NULL,
nullptr,
0,
D3D11_SDK_VERSION,
&m_device,
NULL,
nullptr,
&m_device_ctx);
WIN32_CHK(hres == S_OK);
@ -138,10 +138,10 @@ class GHOST_SharedOpenGLResource {
texDesc.MipLevels = 1;
texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
device->CreateTexture2D(&texDesc, NULL, &tex);
device->CreateTexture2D(&texDesc, nullptr, &tex);
if (!tex) {
/* If texture creation fails, we just return and leave the render target unset. So it needs
* to be NULL-checked before use. */
* to be nullptr-checked before use. */
fprintf(stderr, "Error creating texture for shared DirectX-OpenGL resource\n");
return;
}
@ -251,7 +251,7 @@ class GHOST_SharedOpenGLResource {
GHOST_TSuccess initialize()
{
m_shared.device = wglDXOpenDeviceNV(m_device);
if (m_shared.device == NULL) {
if (m_shared.device == nullptr) {
fprintf(stderr, "Error opening shared device using wglDXOpenDeviceNV()\n");
return GHOST_kFailure;
}

View File

@ -161,7 +161,7 @@ class GHOST_DeviceVK {
~GHOST_DeviceVK()
{
if (device != VK_NULL_HANDLE) {
vkDestroyDevice(device, NULL);
vkDestroyDevice(device, nullptr);
}
}
@ -175,10 +175,11 @@ class GHOST_DeviceVK {
bool extensions_support(const vector<const char *> &required_extensions)
{
uint32_t ext_count;
vkEnumerateDeviceExtensionProperties(physical_device, NULL, &ext_count, NULL);
vkEnumerateDeviceExtensionProperties(physical_device, nullptr, &ext_count, nullptr);
vector<VkExtensionProperties> available_exts(ext_count);
vkEnumerateDeviceExtensionProperties(physical_device, NULL, &ext_count, available_exts.data());
vkEnumerateDeviceExtensionProperties(
physical_device, nullptr, &ext_count, available_exts.data());
for (const auto &extension_needed : required_extensions) {
bool found = false;
@ -232,13 +233,13 @@ class GHOST_DeviceVK {
device_create_info.ppEnabledExtensionNames = extensions_device.data();
device_create_info.pEnabledFeatures = &device_features;
vkCreateDevice(physical_device, &device_create_info, NULL, &device);
vkCreateDevice(physical_device, &device_create_info, nullptr, &device);
}
void init_generic_queue_family()
{
uint32_t queue_family_count = 0;
vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &queue_family_count, NULL);
vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &queue_family_count, nullptr);
vector<VkQueueFamilyProperties> queue_families(queue_family_count);
vkGetPhysicalDeviceQueueFamilyProperties(
@ -282,7 +283,7 @@ static GHOST_TSuccess ensure_vulkan_device(VkInstance vk_instance,
VkPhysicalDevice best_physical_device = VK_NULL_HANDLE;
uint32_t device_count = 0;
vkEnumeratePhysicalDevices(vk_instance, &device_count, NULL);
vkEnumeratePhysicalDevices(vk_instance, &device_count, nullptr);
vector<VkPhysicalDevice> physical_devices(device_count);
vkEnumeratePhysicalDevices(vk_instance, &device_count, physical_devices.data());
@ -298,11 +299,11 @@ static GHOST_TSuccess ensure_vulkan_device(VkInstance vk_instance,
if (vk_surface != VK_NULL_HANDLE) {
uint32_t format_count;
vkGetPhysicalDeviceSurfaceFormatsKHR(
device_vk.physical_device, vk_surface, &format_count, NULL);
device_vk.physical_device, vk_surface, &format_count, nullptr);
uint32_t present_count;
vkGetPhysicalDeviceSurfacePresentModesKHR(
device_vk.physical_device, vk_surface, &present_count, NULL);
device_vk.physical_device, vk_surface, &present_count, nullptr);
/* For now anything will do. */
if (format_count == 0 || present_count == 0) {
@ -403,10 +404,10 @@ GHOST_ContextVK::~GHOST_ContextVK()
destroySwapchain();
if (m_command_pool != VK_NULL_HANDLE) {
vkDestroyCommandPool(device_vk.device, m_command_pool, NULL);
vkDestroyCommandPool(device_vk.device, m_command_pool, nullptr);
}
if (m_surface != VK_NULL_HANDLE) {
vkDestroySurfaceKHR(device_vk.instance, m_surface, NULL);
vkDestroySurfaceKHR(device_vk.instance, m_surface, nullptr);
}
device_vk.users--;
@ -422,28 +423,28 @@ GHOST_TSuccess GHOST_ContextVK::destroySwapchain()
VkDevice device = vulkan_device->device;
for (auto semaphore : m_image_available_semaphores) {
vkDestroySemaphore(device, semaphore, NULL);
vkDestroySemaphore(device, semaphore, nullptr);
}
for (auto semaphore : m_render_finished_semaphores) {
vkDestroySemaphore(device, semaphore, NULL);
vkDestroySemaphore(device, semaphore, nullptr);
}
for (auto fence : m_in_flight_fences) {
vkDestroyFence(device, fence, NULL);
vkDestroyFence(device, fence, nullptr);
}
for (auto framebuffer : m_swapchain_framebuffers) {
vkDestroyFramebuffer(device, framebuffer, NULL);
vkDestroyFramebuffer(device, framebuffer, nullptr);
}
if (m_render_pass != VK_NULL_HANDLE) {
vkDestroyRenderPass(device, m_render_pass, NULL);
vkDestroyRenderPass(device, m_render_pass, nullptr);
}
for (auto command_buffer : m_command_buffers) {
vkFreeCommandBuffers(device, m_command_pool, 1, &command_buffer);
}
for (auto imageView : m_swapchain_image_views) {
vkDestroyImageView(device, imageView, NULL);
vkDestroyImageView(device, imageView, nullptr);
}
if (m_swapchain != VK_NULL_HANDLE) {
vkDestroySwapchainKHR(device, m_swapchain, NULL);
vkDestroySwapchainKHR(device, m_swapchain, nullptr);
}
return GHOST_kSuccess;
}
@ -509,7 +510,7 @@ GHOST_TSuccess GHOST_ContextVK::swapBuffers()
present_info.swapchainCount = 1;
present_info.pSwapchains = &m_swapchain;
present_info.pImageIndices = &m_currentImage;
present_info.pResults = NULL;
present_info.pResults = nullptr;
result = vkQueuePresentKHR(m_present_queue, &present_info);
@ -612,10 +613,10 @@ GHOST_TSuccess GHOST_ContextVK::releaseDrawingContext()
static vector<VkExtensionProperties> getExtensionsAvailable()
{
uint32_t extension_count = 0;
vkEnumerateInstanceExtensionProperties(NULL, &extension_count, NULL);
vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, nullptr);
vector<VkExtensionProperties> extensions(extension_count);
vkEnumerateInstanceExtensionProperties(NULL, &extension_count, extensions.data());
vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, extensions.data());
return extensions;
}
@ -646,7 +647,7 @@ static void requireExtension(vector<VkExtensionProperties> &extensions_available
static vector<VkLayerProperties> getLayersAvailable()
{
uint32_t layer_count = 0;
vkEnumerateInstanceLayerProperties(&layer_count, NULL);
vkEnumerateInstanceLayerProperties(&layer_count, nullptr);
vector<VkLayerProperties> layers(layer_count);
vkEnumerateInstanceLayerProperties(&layer_count, layers.data());
@ -731,7 +732,7 @@ static GHOST_TSuccess create_render_pass(VkDevice device,
renderPassInfo.subpassCount = 1;
renderPassInfo.pSubpasses = &subpass;
VK_CHECK(vkCreateRenderPass(device, &renderPassInfo, NULL, r_renderPass));
VK_CHECK(vkCreateRenderPass(device, &renderPassInfo, nullptr, r_renderPass));
return GHOST_kSuccess;
}
@ -742,7 +743,7 @@ static GHOST_TSuccess selectPresentMode(VkPhysicalDevice device,
{
// TODO cleanup: we are not going to use MAILBOX as it isn't supported by renderdoc.
uint32_t present_count;
vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &present_count, NULL);
vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &present_count, nullptr);
vector<VkPresentModeKHR> presents(present_count);
vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &present_count, presents.data());
/* MAILBOX is the lowest latency V-Sync enabled mode so use it if available */
@ -773,7 +774,7 @@ GHOST_TSuccess GHOST_ContextVK::createCommandPools()
poolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
poolInfo.queueFamilyIndex = vulkan_device->generic_queue_family;
VK_CHECK(vkCreateCommandPool(vulkan_device->device, &poolInfo, NULL, &m_command_pool));
VK_CHECK(vkCreateCommandPool(vulkan_device->device, &poolInfo, nullptr, &m_command_pool));
return GHOST_kSuccess;
}
@ -834,7 +835,7 @@ static bool selectSurfaceFormat(const VkPhysicalDevice physical_device,
VkSurfaceFormatKHR &r_surfaceFormat)
{
uint32_t format_count;
vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device, surface, &format_count, NULL);
vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device, surface, &format_count, nullptr);
vector<VkSurfaceFormatKHR> formats(format_count);
vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device, surface, &format_count, formats.data());
@ -913,15 +914,15 @@ GHOST_TSuccess GHOST_ContextVK::createSwapchain()
create_info.oldSwapchain = VK_NULL_HANDLE; /* TODO Window resize */
create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
create_info.queueFamilyIndexCount = 0;
create_info.pQueueFamilyIndices = NULL;
create_info.pQueueFamilyIndices = nullptr;
VkDevice device = vulkan_device->device;
VK_CHECK(vkCreateSwapchainKHR(device, &create_info, NULL, &m_swapchain));
VK_CHECK(vkCreateSwapchainKHR(device, &create_info, nullptr, &m_swapchain));
create_render_pass(device, format.format, &m_render_pass);
/* image_count may not be what we requested! Getter for final value. */
vkGetSwapchainImagesKHR(device, m_swapchain, &image_count, NULL);
vkGetSwapchainImagesKHR(device, m_swapchain, &image_count, nullptr);
m_swapchain_images.resize(image_count);
vkGetSwapchainImagesKHR(device, m_swapchain, &image_count, m_swapchain_images.data());
@ -945,7 +946,7 @@ GHOST_TSuccess GHOST_ContextVK::createSwapchain()
view_create_info.subresourceRange.baseArrayLayer = 0;
view_create_info.subresourceRange.layerCount = 1;
VK_CHECK(vkCreateImageView(device, &view_create_info, NULL, &m_swapchain_image_views[i]));
VK_CHECK(vkCreateImageView(device, &view_create_info, nullptr, &m_swapchain_image_views[i]));
VkImageView attachments[] = {m_swapchain_image_views[i]};
@ -958,7 +959,7 @@ GHOST_TSuccess GHOST_ContextVK::createSwapchain()
fb_create_info.height = m_render_extent.height;
fb_create_info.layers = 1;
VK_CHECK(vkCreateFramebuffer(device, &fb_create_info, NULL, &m_swapchain_framebuffers[i]));
VK_CHECK(vkCreateFramebuffer(device, &fb_create_info, nullptr, &m_swapchain_framebuffers[i]));
}
m_image_available_semaphores.resize(MAX_FRAMES_IN_FLIGHT);
@ -973,10 +974,12 @@ GHOST_TSuccess GHOST_ContextVK::createSwapchain()
for (int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
VK_CHECK(vkCreateSemaphore(device, &semaphore_info, NULL, &m_image_available_semaphores[i]));
VK_CHECK(vkCreateSemaphore(device, &semaphore_info, NULL, &m_render_finished_semaphores[i]));
VK_CHECK(
vkCreateSemaphore(device, &semaphore_info, nullptr, &m_image_available_semaphores[i]));
VK_CHECK(
vkCreateSemaphore(device, &semaphore_info, nullptr, &m_render_finished_semaphores[i]));
VK_CHECK(vkCreateFence(device, &fence_info, NULL, &m_in_flight_fences[i]));
VK_CHECK(vkCreateFence(device, &fence_info, nullptr, &m_in_flight_fences[i]));
}
createGraphicsCommandBuffers();
@ -1002,24 +1005,24 @@ const char *GHOST_ContextVK::getPlatformSpecificSurfaceExtension() const
# endif
}
#endif
return NULL;
return nullptr;
}
GHOST_TSuccess GHOST_ContextVK::initializeDrawingContext()
{
#ifdef _WIN32
const bool use_window_surface = (m_hwnd != NULL);
const bool use_window_surface = (m_hwnd != nullptr);
#elif defined(__APPLE__)
const bool use_window_surface = (m_metal_layer != NULL);
const bool use_window_surface = (m_metal_layer != nullptr);
#else /* UNIX/Linux */
bool use_window_surface = false;
switch (m_platform) {
case GHOST_kVulkanPlatformX11:
use_window_surface = (m_display != NULL) && (m_window != (Window)NULL);
use_window_surface = (m_display != nullptr) && (m_window != (Window) nullptr);
break;
# ifdef WITH_GHOST_WAYLAND
case GHOST_kVulkanPlatformWayland:
use_window_surface = (m_wayland_display != NULL) && (m_wayland_surface != NULL);
use_window_surface = (m_wayland_display != nullptr) && (m_wayland_surface != nullptr);
break;
# endif
}
@ -1070,7 +1073,7 @@ GHOST_TSuccess GHOST_ContextVK::initializeDrawingContext()
create_info.ppEnabledLayerNames = layers_enabled.data();
create_info.enabledExtensionCount = static_cast<uint32_t>(extensions_enabled.size());
create_info.ppEnabledExtensionNames = extensions_enabled.data();
VK_CHECK(vkCreateInstance(&create_info, NULL, &instance));
VK_CHECK(vkCreateInstance(&create_info, nullptr, &instance));
}
else {
instance = vulkan_device->instance;
@ -1080,13 +1083,13 @@ GHOST_TSuccess GHOST_ContextVK::initializeDrawingContext()
#ifdef _WIN32
VkWin32SurfaceCreateInfoKHR surface_create_info = {};
surface_create_info.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
surface_create_info.hinstance = GetModuleHandle(NULL);
surface_create_info.hinstance = GetModuleHandle(nullptr);
surface_create_info.hwnd = m_hwnd;
VK_CHECK(vkCreateWin32SurfaceKHR(instance, &surface_create_info, NULL, &m_surface));
VK_CHECK(vkCreateWin32SurfaceKHR(instance, &surface_create_info, nullptr, &m_surface));
#elif defined(__APPLE__)
VkMetalSurfaceCreateInfoEXT info = {};
info.sType = VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT;
info.pNext = NULL;
info.pNext = nullptr;
info.flags = 0;
info.pLayer = m_metal_layer;
VK_CHECK(vkCreateMetalSurfaceEXT(instance, &info, nullptr, &m_surface));
@ -1097,7 +1100,7 @@ GHOST_TSuccess GHOST_ContextVK::initializeDrawingContext()
surface_create_info.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR;
surface_create_info.dpy = m_display;
surface_create_info.window = m_window;
VK_CHECK(vkCreateXlibSurfaceKHR(instance, &surface_create_info, NULL, &m_surface));
VK_CHECK(vkCreateXlibSurfaceKHR(instance, &surface_create_info, nullptr, &m_surface));
break;
}
# ifdef WITH_GHOST_WAYLAND
@ -1106,7 +1109,7 @@ GHOST_TSuccess GHOST_ContextVK::initializeDrawingContext()
surface_create_info.sType = VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR;
surface_create_info.display = m_wayland_display;
surface_create_info.surface = m_wayland_surface;
VK_CHECK(vkCreateWaylandSurfaceKHR(instance, &surface_create_info, NULL, &m_surface));
VK_CHECK(vkCreateWaylandSurfaceKHR(instance, &surface_create_info, nullptr, &m_surface));
break;
}
# endif

View File

@ -16,13 +16,13 @@
#include <cstdio>
#include <vector>
HGLRC GHOST_ContextWGL::s_sharedHGLRC = NULL;
HGLRC GHOST_ContextWGL::s_sharedHGLRC = nullptr;
int GHOST_ContextWGL::s_sharedCount = 0;
/* Some third-generation Intel video-cards are constantly bring problems */
static bool is_crappy_intel_card()
{
return strstr((const char *)glGetString(GL_VENDOR), "Intel") != NULL;
return strstr((const char *)glGetString(GL_VENDOR), "Intel") != nullptr;
}
GHOST_ContextWGL::GHOST_ContextWGL(bool stereoVisual,
@ -43,22 +43,22 @@ GHOST_ContextWGL::GHOST_ContextWGL(bool stereoVisual,
m_contextFlags(contextFlags),
m_alphaBackground(alphaBackground),
m_contextResetNotificationStrategy(contextResetNotificationStrategy),
m_hGLRC(NULL)
m_hGLRC(nullptr)
#ifndef NDEBUG
,
m_dummyVendor(NULL),
m_dummyRenderer(NULL),
m_dummyVersion(NULL)
m_dummyVendor(nullptr),
m_dummyRenderer(nullptr),
m_dummyVersion(nullptr)
#endif
{
assert(m_hDC != NULL);
assert(m_hDC != nullptr);
}
GHOST_ContextWGL::~GHOST_ContextWGL()
{
if (m_hGLRC != NULL) {
if (m_hGLRC != nullptr) {
if (m_hGLRC == ::wglGetCurrentContext())
WIN32_CHK(::wglMakeCurrent(NULL, NULL));
WIN32_CHK(::wglMakeCurrent(nullptr, nullptr));
if (m_hGLRC != s_sharedHGLRC || s_sharedCount == 1) {
assert(s_sharedCount > 0);
@ -66,7 +66,7 @@ GHOST_ContextWGL::~GHOST_ContextWGL()
s_sharedCount--;
if (s_sharedCount == 0)
s_sharedHGLRC = NULL;
s_sharedHGLRC = nullptr;
WIN32_CHK(::wglDeleteContext(m_hGLRC));
}
@ -117,7 +117,7 @@ GHOST_TSuccess GHOST_ContextWGL::activateDrawingContext()
GHOST_TSuccess GHOST_ContextWGL::releaseDrawingContext()
{
if (WIN32_CHK(::wglMakeCurrent(NULL, NULL))) {
if (WIN32_CHK(::wglMakeCurrent(nullptr, nullptr))) {
return GHOST_kSuccess;
}
else {
@ -176,7 +176,7 @@ static int choose_pixel_format_legacy(HDC hDC, PIXELFORMATDESCRIPTOR &preferredP
WIN32_CHK(iLastResortPixelFormat != 0);
int lastPFD = ::DescribePixelFormat(hDC, 1, sizeof(PIXELFORMATDESCRIPTOR), NULL);
int lastPFD = ::DescribePixelFormat(hDC, 1, sizeof(PIXELFORMATDESCRIPTOR), nullptr);
WIN32_CHK(lastPFD != 0);
@ -262,7 +262,7 @@ static HWND clone_window(HWND hWnd, LPVOID lpParam)
hInstance,
lpParam);
WIN32_CHK(hwndCloned != NULL);
WIN32_CHK(hwndCloned != nullptr);
return hwndCloned;
}
@ -306,13 +306,13 @@ static void makeAttribList(std::vector<int> &out, bool stereoVisual, bool needAl
/* Temporary context used to create the actual context. We need ARB pixel format
* and context extensions, which are only available within a context. */
struct DummyContextWGL {
HWND dummyHWND = NULL;
HWND dummyHWND = nullptr;
HDC dummyHDC = NULL;
HGLRC dummyHGLRC = NULL;
HDC dummyHDC = nullptr;
HGLRC dummyHGLRC = nullptr;
HDC prevHDC = NULL;
HGLRC prevHGLRC = NULL;
HDC prevHDC = nullptr;
HGLRC prevHGLRC = nullptr;
int dummyPixelFormat = 0;
@ -381,15 +381,15 @@ struct DummyContextWGL {
return;
if (hWnd) {
dummyHWND = clone_window(hWnd, NULL);
dummyHWND = clone_window(hWnd, nullptr);
if (dummyHWND == NULL)
if (dummyHWND == nullptr)
return;
dummyHDC = GetDC(dummyHWND);
}
if (!WIN32_CHK(dummyHDC != NULL))
if (!WIN32_CHK(dummyHDC != nullptr))
return;
if (!WIN32_CHK(::SetPixelFormat(dummyHDC, dummyPixelFormat, &chosenPFD)))
@ -397,7 +397,7 @@ struct DummyContextWGL {
dummyHGLRC = ::wglCreateContext(dummyHDC);
if (!WIN32_CHK(dummyHGLRC != NULL))
if (!WIN32_CHK(dummyHGLRC != nullptr))
return;
if (!WIN32_CHK(::wglMakeCurrent(dummyHDC, dummyHGLRC)))
@ -415,11 +415,11 @@ struct DummyContextWGL {
{
WIN32_CHK(::wglMakeCurrent(prevHDC, prevHGLRC));
if (dummyHGLRC != NULL)
if (dummyHGLRC != nullptr)
WIN32_CHK(::wglDeleteContext(dummyHGLRC));
if (dummyHWND != NULL) {
if (dummyHDC != NULL)
if (dummyHWND != nullptr) {
if (dummyHDC != nullptr)
WIN32_CHK(::ReleaseDC(dummyHWND, dummyHDC));
WIN32_CHK(::DestroyWindow(dummyHWND));
@ -440,7 +440,7 @@ int GHOST_ContextWGL::_choose_pixel_format_arb_1(bool stereoVisual, bool needAlp
uint nNumFormats;
WIN32_CHK(wglChoosePixelFormatARB(
m_hDC, &(iAttributes[0]), NULL, _MAX_PIXEL_FORMATS, iPixelFormats, &nNumFormats));
m_hDC, &(iAttributes[0]), nullptr, _MAX_PIXEL_FORMATS, iPixelFormats, &nNumFormats));
if (nNumFormats > 0) {
iPixelFormat = iPixelFormats[0];
@ -604,7 +604,7 @@ GHOST_TSuccess GHOST_ContextWGL::initializeDrawingContext()
iAttributes.push_back(0);
m_hGLRC = ::wglCreateContextAttribsARB(m_hDC, NULL, &(iAttributes[0]));
m_hGLRC = ::wglCreateContextAttribsARB(m_hDC, nullptr, &(iAttributes[0]));
}
}
@ -612,14 +612,14 @@ GHOST_TSuccess GHOST_ContextWGL::initializeDrawingContext()
* a context with version higher than 3.3 Core. */
{
const bool silent = m_contextMajorVersion > 3;
if (!WIN32_CHK_SILENT(m_hGLRC != NULL, silent)) {
if (!WIN32_CHK_SILENT(m_hGLRC != nullptr, silent)) {
goto error;
}
}
s_sharedCount++;
if (s_sharedHGLRC == NULL) {
if (s_sharedHGLRC == nullptr) {
s_sharedHGLRC = m_hGLRC;
}
else if (!WIN32_CHK(::wglShareLists(s_sharedHGLRC, m_hGLRC))) {
@ -667,8 +667,8 @@ GHOST_TSuccess GHOST_ContextWGL::releaseNativeHandles()
GHOST_TSuccess success = m_hGLRC != s_sharedHGLRC || s_sharedCount == 1 ? GHOST_kSuccess :
GHOST_kFailure;
m_hWnd = NULL;
m_hDC = NULL;
m_hWnd = nullptr;
m_hDC = nullptr;
return success;
}

View File

@ -133,7 +133,7 @@ GHOST_TSuccess GHOST_DisplayManagerCocoa::setCurrentDisplaySetting(
(size_t)setting.xPixels,
(size_t)setting.yPixels,
(CGRefreshRate)setting.frequency,
NULL);
nullptr);
#endif
#ifdef GHOST_DEBUG

View File

@ -28,7 +28,7 @@ GHOST_TSuccess GHOST_DisplayManagerWin32::getNumDisplays(uint8_t &numDisplays) c
static BOOL get_dd(DWORD d, DISPLAY_DEVICE *dd)
{
dd->cb = sizeof(DISPLAY_DEVICE);
return ::EnumDisplayDevices(NULL, d, dd, 0);
return ::EnumDisplayDevices(nullptr, d, dd, 0);
}
GHOST_TSuccess GHOST_DisplayManagerWin32::getNumDisplaySettings(uint8_t display,

View File

@ -9,7 +9,7 @@
* \ingroup GHOST
*/
#include <stdio.h>
#include <cstdio>
#ifdef WITH_X11_XF86VMODE
# include <X11/Xlib.h>

View File

@ -37,14 +37,14 @@ HRESULT __stdcall GHOST_DropTargetWin32::QueryInterface(REFIID riid, void **ppv_
if (!ppv_obj) {
return E_INVALIDARG;
}
*ppv_obj = NULL;
*ppv_obj = nullptr;
if (riid == IID_IUnknown || riid == IID_IDropTarget) {
AddRef();
*ppv_obj = (void *)this;
return S_OK;
}
*ppv_obj = NULL;
*ppv_obj = nullptr;
return E_NOINTERFACE;
}
@ -87,7 +87,7 @@ HRESULT __stdcall GHOST_DropTargetWin32::DragEnter(IDataObject *p_data_object,
m_draggedObjectType = getGhostType(p_data_object);
m_system->pushDragDropEvent(
GHOST_kEventDraggingEntered, m_draggedObjectType, m_window, pt.x, pt.y, NULL);
GHOST_kEventDraggingEntered, m_draggedObjectType, m_window, pt.x, pt.y, nullptr);
return S_OK;
}
@ -107,7 +107,7 @@ HRESULT __stdcall GHOST_DropTargetWin32::DragOver(DWORD /*grf_key_state*/,
// *pdw_effect = DROPEFFECT_COPY;
}
m_system->pushDragDropEvent(
GHOST_kEventDraggingUpdated, m_draggedObjectType, m_window, pt.x, pt.y, NULL);
GHOST_kEventDraggingUpdated, m_draggedObjectType, m_window, pt.x, pt.y, nullptr);
return S_OK;
}
@ -117,7 +117,7 @@ HRESULT __stdcall GHOST_DropTargetWin32::DragOver(DWORD /*grf_key_state*/,
HRESULT __stdcall GHOST_DropTargetWin32::DragLeave(void)
{
m_system->pushDragDropEvent(
GHOST_kEventDraggingExited, m_draggedObjectType, m_window, 0, 0, NULL);
GHOST_kEventDraggingExited, m_draggedObjectType, m_window, 0, 0, nullptr);
m_draggedObjectType = GHOST_kDragnDropTypeUnknown;
return S_OK;
}
@ -194,14 +194,14 @@ void *GHOST_DropTargetWin32::getGhostData(IDataObject *p_data_object)
#ifdef WITH_GHOST_DEBUG
::printf("\nGHOST_kDragnDropTypeUnknown");
#endif /* WITH_GHOST_DEBUG */
return NULL;
return nullptr;
}
return NULL;
return nullptr;
}
void *GHOST_DropTargetWin32::getDropDataAsFilenames(IDataObject *p_data_object)
{
GHOST_TStringArray *str_array = NULL;
GHOST_TStringArray *str_array = nullptr;
FORMATETC fmtetc = {CF_HDROP, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
/* Check if data-object supplies the format we want.
@ -211,7 +211,7 @@ void *GHOST_DropTargetWin32::getDropDataAsFilenames(IDataObject *p_data_object)
if (p_data_object->GetData(&fmtetc, &stgmed) == S_OK) {
const HDROP hdrop = (HDROP)::GlobalLock(stgmed.hGlobal);
const uint totfiles = ::DragQueryFileW(hdrop, -1, NULL, 0);
const uint totfiles = ::DragQueryFileW(hdrop, -1, nullptr, 0);
if (totfiles) {
str_array = (GHOST_TStringArray *)::malloc(sizeof(GHOST_TStringArray));
str_array->count = 0;
@ -284,23 +284,23 @@ void *GHOST_DropTargetWin32::getDropDataAsString(IDataObject *p_data_object)
}
}
return NULL;
return nullptr;
}
int GHOST_DropTargetWin32::WideCharToANSI(LPCWSTR in, char *&out)
{
int size;
out = NULL; /* caller should free if != NULL */
out = nullptr; /* caller should free if != nullptr */
/* Get the required size. */
size = ::WideCharToMultiByte(CP_ACP, /* System Default Codepage */
0x00000400, /* WC_NO_BEST_FIT_CHARS */
in,
-1, /* -1 null terminated, makes output null terminated too. */
NULL,
nullptr,
0,
NULL,
NULL);
nullptr,
nullptr);
if (!size) {
#ifdef WITH_GHOST_DEBUG
@ -315,14 +315,14 @@ int GHOST_DropTargetWin32::WideCharToANSI(LPCWSTR in, char *&out)
return 0;
}
size = ::WideCharToMultiByte(CP_ACP, 0x00000400, in, -1, (LPSTR)out, size, NULL, NULL);
size = ::WideCharToMultiByte(CP_ACP, 0x00000400, in, -1, (LPSTR)out, size, nullptr, nullptr);
if (!size) {
#ifdef WITH_GHOST_DEBUG
::printLastError();
#endif /* WITH_GHOST_DEBUG */
::free(out);
out = NULL;
out = nullptr;
}
return size;
}
@ -335,12 +335,12 @@ void printLastError(void)
err = GetLastError();
if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
nullptr,
err,
0,
(LPTSTR)&s,
0,
NULL))
nullptr))
{
printf("\nLastError: (%d) %s\n", int(err), s);
LocalFree(s);

View File

@ -116,7 +116,7 @@ class GHOST_DropTargetWin32 : public IDropTarget {
* The ANSI codepage is the system default codepage,
* and can change from system to system.
* \param in: LPCWSTR.
* \param out: char *. Is set to NULL on failure.
* \param out: char *. Is set to nullptr on failure.
* \return 0 on failure. Else the size of the string including '\0'.
*/
int WideCharToANSI(LPCWSTR in, char *&out);

View File

@ -20,7 +20,7 @@ class GHOST_Event : public GHOST_IEvent {
* Constructor.
* \param msec: The time this event was generated.
* \param type: The type of this event.
* \param window: The generating window (or NULL if system event).
* \param window: The generating window (or nullptr if system event).
*/
GHOST_Event(uint64_t msec, GHOST_TEventType type, GHOST_IWindow *window)
: m_type(type), m_time(msec), m_window(window), m_data(nullptr)
@ -47,7 +47,7 @@ class GHOST_Event : public GHOST_IEvent {
/**
* Returns the window this event was generated on,
* or NULL if it is a 'system' event.
* or nullptr if it is a 'system' event.
* \return The generating window.
*/
GHOST_IWindow *getWindow()

View File

@ -74,7 +74,7 @@ class GHOST_EventDragnDrop : public GHOST_Event {
~GHOST_EventDragnDrop()
{
/* Free the dropped object data. */
if (m_dragnDropEventData.data == NULL)
if (m_dragnDropEventData.data == nullptr)
return;
switch (m_dragnDropEventData.dataType) {

View File

@ -99,7 +99,7 @@ class GHOST_EventManager {
* \param type: The type of events to be removed.
* \param window: The window to remove the events for.
*/
void removeTypeEvents(GHOST_TEventType type, GHOST_IWindow *window = NULL);
void removeTypeEvents(GHOST_TEventType type, GHOST_IWindow *window = nullptr);
protected:
/**

View File

@ -20,7 +20,7 @@ class GHOST_EventString : public GHOST_Event {
* Constructor.
* \param msec: The time this event was generated.
* \param type: The type of this event.
* \param window: The generating window (or NULL if system event).
* \param window: The generating window (or nullptr if system event).
* \param data_ptr: Pointer to the (un-formatted) data associated with the event.
*/
GHOST_EventString(uint64_t msec,

View File

@ -44,7 +44,7 @@ void GHOST_ImeWin32::UpdateInputLanguage()
GetLocaleInfoEx(locale, LOCALE_SISO639LANGNAME, language_u16, W32_ISO639_LEN);
/* Store this as a UTF-8 string. */
WideCharToMultiByte(
CP_UTF8, 0, language_u16, W32_ISO639_LEN, language_, W32_ISO639_LEN, NULL, NULL);
CP_UTF8, 0, language_u16, W32_ISO639_LEN, language_, W32_ISO639_LEN, nullptr, nullptr);
}
BOOL GHOST_ImeWin32::IsLanguage(const char name[W32_ISO639_LEN])
@ -115,7 +115,7 @@ void GHOST_ImeWin32::CreateImeWindow(HWND window_handle)
* their window position, we also create a caret for Japanese IMEs.
*/
if (!system_caret_ && (IsLanguage(IMELANG_CHINESE) || IsLanguage(IMELANG_JAPANESE))) {
system_caret_ = ::CreateCaret(window_handle, NULL, 1, 1);
system_caret_ = ::CreateCaret(window_handle, nullptr, 1, 1);
}
/* Restore the positions of the IME windows. */
UpdateImeWindow(window_handle);
@ -267,7 +267,7 @@ void GHOST_ImeWin32::GetCaret(HIMC imm_context, LPARAM lparam, ImeComposition *c
}
}
else if (IsLanguage(IMELANG_CHINESE)) {
int clause_size = ImmGetCompositionStringW(imm_context, GCS_COMPCLAUSE, NULL, 0);
int clause_size = ImmGetCompositionStringW(imm_context, GCS_COMPCLAUSE, nullptr, 0);
if (clause_size) {
static std::vector<ulong> clauses;
clause_size = clause_size / sizeof(clauses[0]);
@ -303,7 +303,7 @@ void GHOST_ImeWin32::GetCaret(HIMC imm_context, LPARAM lparam, ImeComposition *c
* a clause being converted.
*/
if (lparam & GCS_COMPATTR) {
int attribute_size = ::ImmGetCompositionStringW(imm_context, GCS_COMPATTR, NULL, 0);
int attribute_size = ::ImmGetCompositionStringW(imm_context, GCS_COMPATTR, nullptr, 0);
if (attribute_size > 0) {
char *attribute_data = new char[attribute_size];
if (attribute_data) {
@ -346,7 +346,7 @@ bool GHOST_ImeWin32::GetString(HIMC imm_context,
{
bool result = false;
if (lparam & type) {
int string_size = ::ImmGetCompositionStringW(imm_context, type, NULL, 0);
int string_size = ::ImmGetCompositionStringW(imm_context, type, nullptr, 0);
if (string_size > 0) {
int string_length = string_size / sizeof(wchar_t);
wchar_t *string_data = new wchar_t[string_length + 1];
@ -392,7 +392,7 @@ bool GHOST_ImeWin32::GetComposition(HWND window_handle, LPARAM lparam, ImeCompos
result = GetString(imm_context, lparam, GCS_COMPSTR, composition);
/* Retrieve the cursor position in the IME composition. */
int cursor_position = ::ImmGetCompositionStringW(imm_context, GCS_CURSORPOS, NULL, 0);
int cursor_position = ::ImmGetCompositionStringW(imm_context, GCS_CURSORPOS, nullptr, 0);
composition->cursor_position = cursor_position;
composition->target_start = -1;
composition->target_end = -1;
@ -421,7 +421,7 @@ void GHOST_ImeWin32::EndIME(HWND window_handle)
return;
is_enable = false;
CleanupComposition(window_handle);
::ImmAssociateContextEx(window_handle, NULL, 0);
::ImmAssociateContextEx(window_handle, nullptr, 0);
eventImeData.composite_len = 0;
}
@ -436,7 +436,7 @@ void GHOST_ImeWin32::BeginIME(HWND window_handle, const GHOST_Rect &caret_rect,
* IMM ignores this call if the IME context is loaded. Therefore, we do
* not have to check whether or not the IME context is loaded.
*/
::ImmAssociateContextEx(window_handle, NULL, IACE_DEFAULT);
::ImmAssociateContextEx(window_handle, nullptr, IACE_DEFAULT);
/* Complete the ongoing composition and move the IME windows. */
HIMC imm_context = ::ImmGetContext(window_handle);
if (imm_context) {

View File

@ -15,8 +15,8 @@
#endif
// static callback functions need to talk to these objects:
static GHOST_SystemCocoa *ghost_system = NULL;
static GHOST_NDOFManager *ndof_manager = NULL;
static GHOST_SystemCocoa *ghost_system = nullptr;
static GHOST_NDOFManager *ndof_manager = nullptr;
static uint16_t clientID = 0;
@ -73,7 +73,7 @@ typedef int16_t (*ConnexionClientControl_ptr)(uint16_t clientID,
int32_t param,
int32_t *result);
#define DECLARE_FUNC(name) name##_ptr name = NULL
#define DECLARE_FUNC(name) name##_ptr name = nullptr
DECLARE_FUNC(SetConnexionHandlers);
DECLARE_FUNC(InstallConnexionHandlers);
@ -115,14 +115,14 @@ static bool load_driver_functions()
if (module) {
LOAD_FUNC(SetConnexionHandlers);
if (SetConnexionHandlers != NULL) {
if (SetConnexionHandlers != nullptr) {
driver_loaded = true;
has_new_driver = true;
}
else {
LOAD_FUNC(InstallConnexionHandlers);
driver_loaded = (InstallConnexionHandlers != NULL);
driver_loaded = (InstallConnexionHandlers != nullptr);
}
if (driver_loaded) {
@ -132,7 +132,7 @@ static bool load_driver_functions()
LOAD_FUNC(UnregisterConnexionClient);
LOAD_FUNC(ConnexionClientControl);
has_old_driver = (SetConnexionClientButtonMask == NULL);
has_old_driver = (SetConnexionClientButtonMask == nullptr);
}
}
#if DEBUG_NDOF_DRIVER
@ -259,8 +259,8 @@ GHOST_NDOFManagerCocoa::~GHOST_NDOFManagerCocoa()
CleanupConnexionHandlers();
unload_driver();
ghost_system = NULL;
ndof_manager = NULL;
ghost_system = nullptr;
ndof_manager = nullptr;
}
}

View File

@ -8,8 +8,8 @@
/* Logging, use `ghost.ndof.unix.*` prefix. */
#include "CLG_log.h"
#include <cstdio>
#include <spnav.h>
#include <stdio.h>
#include <unistd.h>
static const char *spnav_sock_path = "/var/run/spnav.sock";

View File

@ -92,7 +92,7 @@ class GHOST_SystemCocoa : public GHOST_System {
GHOST_GPUSettings gpuSettings,
const bool exclusive = false,
const bool is_dialog = false,
const GHOST_IWindow *parentWindow = NULL);
const GHOST_IWindow *parentWindow = nullptr);
/**
* Create a new off-screen context.

View File

@ -502,7 +502,7 @@ GHOST_SystemCocoa::GHOST_SystemCocoa()
int mib[2];
struct timeval boottime;
size_t len;
char *rstring = NULL;
char *rstring = nullptr;
m_modifierMask = 0;
m_outsideLoopEventProcessed = false;
@ -516,18 +516,18 @@ GHOST_SystemCocoa::GHOST_SystemCocoa()
mib[1] = KERN_BOOTTIME;
len = sizeof(struct timeval);
sysctl(mib, 2, &boottime, &len, NULL, 0);
sysctl(mib, 2, &boottime, &len, nullptr, 0);
m_start_time = ((boottime.tv_sec * 1000) + (boottime.tv_usec / 1000));
/* Detect multi-touch track-pad. */
mib[0] = CTL_HW;
mib[1] = HW_MODEL;
sysctl(mib, 2, NULL, &len, NULL, 0);
sysctl(mib, 2, nullptr, &len, nullptr, 0);
rstring = (char *)malloc(len);
sysctl(mib, 2, rstring, &len, NULL, 0);
sysctl(mib, 2, rstring, &len, nullptr, 0);
free(rstring);
rstring = NULL;
rstring = nullptr;
m_ignoreWindowSizedMessages = false;
m_ignoreMomentumScroll = false;
@ -657,7 +657,7 @@ uint64_t GHOST_SystemCocoa::getMilliSeconds() const
// Cocoa equivalent exists in 10.6 ([[NSProcessInfo processInfo] systemUptime])
struct timeval currentTime;
gettimeofday(&currentTime, NULL);
gettimeofday(&currentTime, nullptr);
// Return timestamp of system uptime
@ -707,7 +707,7 @@ GHOST_IWindow *GHOST_SystemCocoa::createWindow(const char *title,
const bool is_dialog,
const GHOST_IWindow *parentWindow)
{
GHOST_IWindow *window = NULL;
GHOST_IWindow *window = nullptr;
@autoreleasepool {
// Get the available rect for including window contents
@ -750,7 +750,7 @@ GHOST_IWindow *GHOST_SystemCocoa::createWindow(const char *title,
else {
GHOST_PRINT("GHOST_SystemCocoa::createWindow(): window invalid\n");
delete window;
window = NULL;
window = nullptr;
}
}
return window;
@ -768,7 +768,7 @@ GHOST_IContext *GHOST_SystemCocoa::createOffscreenContext(GHOST_GPUSettings gpuS
switch (gpuSettings.context_type) {
#ifdef WITH_VULKAN_BACKEND
case GHOST_kDrawingContextTypeVulkan: {
GHOST_Context *context = new GHOST_ContextVK(false, NULL, 1, 2, debug_context);
GHOST_Context *context = new GHOST_ContextVK(false, nullptr, 1, 2, debug_context);
if (context->initializeDrawingContext()) {
return context;
}
@ -780,7 +780,7 @@ GHOST_IContext *GHOST_SystemCocoa::createOffscreenContext(GHOST_GPUSettings gpuS
#ifdef WITH_METAL_BACKEND
case GHOST_kDrawingContextTypeMetal: {
/* TODO(fclem): Remove OpenGL support and rename context to ContextMTL */
GHOST_Context *context = new GHOST_ContextCGL(false, NULL, NULL, debug_context);
GHOST_Context *context = new GHOST_ContextCGL(false, nullptr, nullptr, debug_context);
if (context->initializeDrawingContext()) {
return context;
}
@ -953,7 +953,7 @@ bool GHOST_SystemCocoa::processEvents(bool /*waitForEvent*/)
timeOut = 0.0;
}
::ReceiveNextEvent(0, NULL, timeOut, false, &event);
::ReceiveNextEvent(0, nullptr, timeOut, false, &event);
}
if (timerMgr->fireTimers(getMilliSeconds())) {
@ -1172,7 +1172,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType
case GHOST_kEventDraggingExited:
window->clientToScreenIntern(mouseX, mouseY, mouseX, mouseY);
pushEvent(new GHOST_EventDragnDrop(
getMilliSeconds(), eventType, draggedObjectType, window, mouseX, mouseY, NULL));
getMilliSeconds(), eventType, draggedObjectType, window, mouseX, mouseY, nullptr));
break;
case GHOST_kEventDraggingDropDone: {
@ -1231,7 +1231,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType
temp_buff = (uint8_t *)malloc(pastedTextSize + 1);
if (temp_buff == NULL) {
if (temp_buff == nullptr) {
return GHOST_kFailure;
}
@ -1247,10 +1247,10 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType
case GHOST_kDragnDropTypeBitmap: {
NSImage *droppedImg = (NSImage *)data;
NSSize imgSize = [droppedImg size];
ImBuf *ibuf = NULL;
uint8_t *rasterRGB = NULL;
uint8_t *rasterRGBA = NULL;
uint8_t *toIBuf = NULL;
ImBuf *ibuf = nullptr;
uint8_t *rasterRGB = nullptr;
uint8_t *rasterRGBA = nullptr;
uint8_t *toIBuf = nullptr;
int x, y, to_i, from_i;
NSBitmapImageRep *blBitmapFormatImageRGB, *blBitmapFormatImageRGBA, *bitmapImage = nil;
NSEnumerator *enumerator;
@ -1296,7 +1296,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType
/* First get RGB values w/o Alpha to avoid pre-multiplication,
* 32bit but last byte is unused */
blBitmapFormatImageRGB = [[NSBitmapImageRep alloc]
initWithBitmapDataPlanes:NULL
initWithBitmapDataPlanes:nullptr
pixelsWide:imgSize.width
pixelsHigh:imgSize.height
bitsPerSample:8
@ -1316,7 +1316,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType
[NSGraphicsContext restoreGraphicsState];
rasterRGB = (uint8_t *)[blBitmapFormatImageRGB bitmapData];
if (rasterRGB == NULL) {
if (rasterRGB == nullptr) {
[bitmapImage release];
[blBitmapFormatImageRGB release];
[droppedImg release];
@ -1325,7 +1325,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType
/* Then get Alpha values by getting the RGBA image (that is pre-multiplied BTW) */
blBitmapFormatImageRGBA = [[NSBitmapImageRep alloc]
initWithBitmapDataPlanes:NULL
initWithBitmapDataPlanes:nullptr
pixelsWide:imgSize.width
pixelsHigh:imgSize.height
bitsPerSample:8
@ -1345,7 +1345,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType
[NSGraphicsContext restoreGraphicsState];
rasterRGBA = (uint8_t *)[blBitmapFormatImageRGBA bitmapData];
if (rasterRGBA == NULL) {
if (rasterRGBA == nullptr) {
[bitmapImage release];
[blBitmapFormatImageRGB release];
[blBitmapFormatImageRGBA release];
@ -1422,7 +1422,7 @@ bool GHOST_SystemCocoa::handleOpenDocumentRequest(void *filepathStr)
}
GHOST_Window *window = m_windowManager->getWindows().empty() ?
NULL :
nullptr :
(GHOST_Window *)m_windowManager->getWindows().front();
if (!window) {
@ -1438,7 +1438,7 @@ bool GHOST_SystemCocoa::handleOpenDocumentRequest(void *filepathStr)
filenameTextSize = [filepath lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
temp_buff = (char *)malloc(filenameTextSize + 1);
if (temp_buff == NULL) {
if (temp_buff == nullptr) {
return GHOST_kFailure;
}
@ -1898,7 +1898,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleKeyEvent(void *eventPtr)
}
else {
pushEvent(new GHOST_EventKey(
[event timestamp] * 1000, GHOST_kEventKeyUp, window, keyCode, false, NULL));
[event timestamp] * 1000, GHOST_kEventKeyUp, window, keyCode, false, nullptr));
#if 0
printf("Key up rawCode=0x%x charsIgnoringModifiers=%c keyCode=%u utf8=%s\n",
[event keyCode],
@ -1976,15 +1976,15 @@ char *GHOST_SystemCocoa::getClipboard(bool /*selection*/) const
NSString *textPasted = [pasteBoard stringForType:NSPasteboardTypeString];
if (textPasted == nil) {
return NULL;
return nullptr;
}
pastedTextSize = [textPasted lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
temp_buff = (char *)malloc(pastedTextSize + 1);
if (temp_buff == NULL) {
return NULL;
if (temp_buff == nullptr) {
return nullptr;
}
strncpy(temp_buff, [textPasted cStringUsingEncoding:NSUTF8StringEncoding], pastedTextSize);
@ -1995,7 +1995,7 @@ char *GHOST_SystemCocoa::getClipboard(bool /*selection*/) const
return temp_buff;
}
else {
return NULL;
return nullptr;
}
}
}

View File

@ -26,7 +26,7 @@ static const char *GetApplicationSupportDir(const char *versionstr,
NSApplicationSupportDirectory, mask, YES);
if ([paths count] == 0) {
return NULL;
return nullptr;
}
const NSString *const basePath = [paths objectAtIndex:0];
@ -83,13 +83,13 @@ const char *GHOST_SystemPathsCocoa::getUserSpecialDir(GHOST_TUserSpecialDirTypes
GHOST_ASSERT(
false,
"GHOST_SystemPathsCocoa::getUserSpecialDir(): Invalid enum value for type parameter");
return NULL;
return nullptr;
}
const NSArray *const paths = NSSearchPathForDirectoriesInDomains(
ns_directory, NSUserDomainMask, YES);
if ([paths count] == 0) {
return NULL;
return nullptr;
}
const NSString *const basePath = [paths objectAtIndex:0];
@ -106,7 +106,7 @@ const char *GHOST_SystemPathsCocoa::getBinaryDir() const
const NSString *const basePath = [[NSBundle mainBundle] bundlePath];
if (basePath == nil) {
return NULL;
return nullptr;
}
strcpy(tempPath, [basePath cStringUsingEncoding:NSASCIIStringEncoding]);

View File

@ -23,10 +23,10 @@ const char *GHOST_SystemPathsWin32::getSystemDir(int, const char *versionstr) co
{
/* 1 utf-16 might translate into 3 utf-8. 2 utf-16 translates into 4 utf-8. */
static char knownpath[MAX_PATH * 3 + 128] = {0};
PWSTR knownpath_16 = NULL;
PWSTR knownpath_16 = nullptr;
HRESULT hResult = SHGetKnownFolderPath(
FOLDERID_ProgramData, KF_FLAG_DEFAULT, NULL, &knownpath_16);
FOLDERID_ProgramData, KF_FLAG_DEFAULT, nullptr, &knownpath_16);
if (hResult == S_OK) {
conv_utf_16_to_8(knownpath_16, knownpath, MAX_PATH * 3);
@ -36,16 +36,16 @@ const char *GHOST_SystemPathsWin32::getSystemDir(int, const char *versionstr) co
return knownpath;
}
return NULL;
return nullptr;
}
const char *GHOST_SystemPathsWin32::getUserDir(int, const char *versionstr) const
{
static char knownpath[MAX_PATH * 3 + 128] = {0};
PWSTR knownpath_16 = NULL;
PWSTR knownpath_16 = nullptr;
HRESULT hResult = SHGetKnownFolderPath(
FOLDERID_RoamingAppData, KF_FLAG_DEFAULT, NULL, &knownpath_16);
FOLDERID_RoamingAppData, KF_FLAG_DEFAULT, nullptr, &knownpath_16);
if (hResult == S_OK) {
conv_utf_16_to_8(knownpath_16, knownpath, MAX_PATH * 3);
@ -55,7 +55,7 @@ const char *GHOST_SystemPathsWin32::getUserDir(int, const char *versionstr) cons
return knownpath;
}
return NULL;
return nullptr;
}
const char *GHOST_SystemPathsWin32::getUserSpecialDir(GHOST_TUserSpecialDirTypes type) const
@ -88,12 +88,12 @@ const char *GHOST_SystemPathsWin32::getUserSpecialDir(GHOST_TUserSpecialDirTypes
GHOST_ASSERT(
false,
"GHOST_SystemPathsWin32::getUserSpecialDir(): Invalid enum value for type parameter");
return NULL;
return nullptr;
}
static char knownpath[MAX_PATH * 3] = {0};
PWSTR knownpath_16 = NULL;
HRESULT hResult = SHGetKnownFolderPath(folderid, KF_FLAG_DEFAULT, NULL, &knownpath_16);
PWSTR knownpath_16 = nullptr;
HRESULT hResult = SHGetKnownFolderPath(folderid, KF_FLAG_DEFAULT, nullptr, &knownpath_16);
if (hResult == S_OK) {
conv_utf_16_to_8(knownpath_16, knownpath, MAX_PATH * 3);
@ -102,7 +102,7 @@ const char *GHOST_SystemPathsWin32::getUserSpecialDir(GHOST_TUserSpecialDirTypes
}
CoTaskMemFree(knownpath_16);
return NULL;
return nullptr;
}
const char *GHOST_SystemPathsWin32::getBinaryDir() const
@ -115,7 +115,7 @@ const char *GHOST_SystemPathsWin32::getBinaryDir() const
return fullname;
}
return NULL;
return nullptr;
}
void GHOST_SystemPathsWin32::addToSystemRecentFiles(const char *filepath) const
@ -125,11 +125,11 @@ void GHOST_SystemPathsWin32::addToSystemRecentFiles(const char *filepath) const
SHARDAPPIDINFO info;
IShellItem *shell_item;
HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
HRESULT hr = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
if (!SUCCEEDED(hr))
return;
hr = SHCreateItemFromParsingName(filepath_16, NULL, IID_PPV_ARGS(&shell_item));
hr = SHCreateItemFromParsingName(filepath_16, nullptr, IID_PPV_ARGS(&shell_item));
if (SUCCEEDED(hr)) {
info.psi = shell_item;
info.pszAppID = BLENDER_WIN_APPID_16;

View File

@ -736,12 +736,12 @@ struct GWL_Seat {
/**
* Keep a state with shift enabled, use to access predictable number access for AZERTY keymaps.
* If shift is not supported by the key-map, this is set to NULL.
* If shift is not supported by the key-map, this is set to nullptr.
*/
struct xkb_state *xkb_state_empty_with_shift = nullptr;
/**
* Keep a state with number-lock enabled, use to access predictable key-pad symbols.
* If number-lock is not supported by the key-map, this is set to NULL.
* If number-lock is not supported by the key-map, this is set to nullptr.
*/
struct xkb_state *xkb_state_empty_with_numlock = nullptr;
@ -1789,7 +1789,7 @@ static size_t ghost_wl_shm_format_as_size(enum wl_shm_format format)
}
/**
* Return a #wl_buffer, ready to have it's data filled in or NULL in case of failure.
* Return a #wl_buffer, ready to have it's data filled in or nullptr in case of failure.
* The caller is responsible for calling `unmap(buffer_data, buffer_size)`.
*
* \param r_buffer_data: The buffer to be filled.
@ -4993,7 +4993,7 @@ static void gwl_registry_wl_seat_remove(GWL_Display *display, void *user_data, c
gwl_seat_capability_keyboard_disable(seat);
gwl_seat_capability_touch_disable(seat);
/* Un-referencing checks for NULL case. */
/* Un-referencing checks for nullptr case. */
xkb_state_unref(seat->xkb_state);
xkb_state_unref(seat->xkb_state_empty);
xkb_state_unref(seat->xkb_state_empty_with_shift);
@ -6270,7 +6270,7 @@ GHOST_IContext *GHOST_SystemWayland::createOffscreenContext(GHOST_GPUSettings gp
GHOST_Context *context = new GHOST_ContextVK(false,
GHOST_kVulkanPlatformWayland,
0,
NULL,
nullptr,
wl_surface,
display_->wl_display,
1,
@ -6997,7 +6997,7 @@ GHOST_TimerManager *GHOST_SystemWayland::ghost_timer_manager()
GWL_Output *ghost_wl_output_user_data(wl_output *wl_output)
{
GHOST_ASSERT(wl_output, "output must not be NULL");
GHOST_ASSERT(wl_output, "output must not be nullptr");
GHOST_ASSERT(ghost_wl_output_own(wl_output), "output is not owned by GHOST");
GWL_Output *output = static_cast<GWL_Output *>(wl_output_get_user_data(wl_output));
return output;
@ -7005,7 +7005,7 @@ GWL_Output *ghost_wl_output_user_data(wl_output *wl_output)
GHOST_WindowWayland *ghost_wl_surface_user_data(wl_surface *wl_surface)
{
GHOST_ASSERT(wl_surface, "wl_surface must not be NULL");
GHOST_ASSERT(wl_surface, "wl_surface must not be nullptr");
GHOST_ASSERT(ghost_wl_surface_own(wl_surface), "wl_surface is not owned by GHOST");
GHOST_WindowWayland *win = static_cast<GHOST_WindowWayland *>(
wl_surface_get_user_data(wl_surface));

View File

@ -256,7 +256,7 @@ class GHOST_SystemWayland : public GHOST_System {
void output_scale_update(GWL_Output *output);
/**
* Clear all references to this surface to prevent accessing NULL pointers.
* Clear all references to this surface to prevent accessing nullptr pointers.
*
* \return true when any references were removed.
*/

View File

@ -255,7 +255,7 @@ GHOST_IWindow *GHOST_SystemWin32::createWindow(const char *title,
else {
GHOST_PRINT("GHOST_SystemWin32::createWindow(): window invalid\n");
delete window;
window = NULL;
window = nullptr;
}
return window;
@ -293,10 +293,10 @@ GHOST_IContext *GHOST_SystemWin32::createOffscreenContext(GHOST_GPUSettings gpuS
0,
64,
64,
NULL,
NULL,
GetModuleHandle(NULL),
NULL);
nullptr,
nullptr,
GetModuleHandle(nullptr),
nullptr);
HDC mHDC = GetDC(wnd);
HDC prev_hdc = wglGetCurrentDC();
@ -356,10 +356,10 @@ GHOST_ContextD3D *GHOST_SystemWin32::createOffscreenContextD3D()
0,
64,
64,
NULL,
NULL,
GetModuleHandle(NULL),
NULL);
nullptr,
nullptr,
GetModuleHandle(nullptr),
nullptr);
GHOST_ContextD3D *context = new GHOST_ContextD3D(false, wnd);
if (context->initializeDrawingContext()) {
@ -384,7 +384,7 @@ bool GHOST_SystemWin32::processEvents(bool waitForEvent)
do {
GHOST_TimerManager *timerMgr = getTimerManager();
if (waitForEvent && !::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) {
if (waitForEvent && !::PeekMessage(&msg, nullptr, 0, 0, PM_NOREMOVE)) {
#if 1
::Sleep(1);
#else
@ -395,9 +395,9 @@ bool GHOST_SystemWin32::processEvents(bool waitForEvent)
::WaitMessage();
}
else if (maxSleep >= 0.0) {
::SetTimer(NULL, 0, maxSleep, NULL);
::SetTimer(nullptr, 0, maxSleep, nullptr);
::WaitMessage();
::KillTimer(NULL, 0);
::KillTimer(nullptr, 0);
}
#endif
}
@ -409,7 +409,7 @@ bool GHOST_SystemWin32::processEvents(bool waitForEvent)
driveTrackpad();
/* Process all the events waiting for us. */
while (::PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE) != 0) {
while (::PeekMessageW(&msg, nullptr, 0, 0, PM_REMOVE) != 0) {
/* #TranslateMessage doesn't alter the message, and doesn't change our raw keyboard data.
* Needed for #MapVirtualKey or if we ever need to get chars from wm_ime_char or similar. */
::TranslateMessage(&msg);
@ -532,7 +532,7 @@ GHOST_TSuccess GHOST_SystemWin32::init()
wc.hIcon = ::LoadIcon(wc.hInstance, "APPICON");
if (!wc.hIcon) {
::LoadIcon(NULL, IDI_APPLICATION);
::LoadIcon(nullptr, IDI_APPLICATION);
}
wc.hCursor = ::LoadCursor(0, IDC_ARROW);
wc.hbrBackground =
@ -1062,7 +1062,7 @@ GHOST_EventCursor *GHOST_SystemWin32::processCursorEvent(GHOST_WindowWin32 *wind
if (window->getTabletData().Active != GHOST_kTabletModeNone) {
/* While pen devices are in range, cursor movement is handled by tablet input processing. */
return NULL;
return nullptr;
}
int32_t x_screen = screen_co[0], y_screen = screen_co[1];
@ -1138,7 +1138,7 @@ GHOST_EventCursor *GHOST_SystemWin32::processCursorEvent(GHOST_WindowWin32 *wind
/* When wrapping we don't need to add an event because the setCursorPosition call will cause
* a new event after. */
return NULL;
return nullptr;
}
is_warping_x = false;
@ -1247,7 +1247,7 @@ GHOST_EventKey *GHOST_SystemWin32::processKeyEvent(GHOST_WindowWin32 *window, RA
if (key_down && ((utf8_char[0] & 0x80) == 0)) {
const char ascii = utf8_char[0];
if (window->getImeInput()->IsImeKeyEvent(ascii, key)) {
return NULL;
return nullptr;
}
}
#endif /* WITH_INPUT_IME */
@ -1264,7 +1264,7 @@ GHOST_EventKey *GHOST_SystemWin32::processKeyEvent(GHOST_WindowWin32 *window, RA
#endif
}
else {
event = NULL;
event = nullptr;
}
return event;
@ -1280,7 +1280,7 @@ GHOST_Event *GHOST_SystemWin32::processWindowSizeEvent(GHOST_WindowWin32 *window
if (window->m_inLiveResize) {
system->pushEvent(sizeEvent);
system->dispatchEvents();
return NULL;
return nullptr;
}
return sizeEvent;
}
@ -1468,7 +1468,7 @@ void GHOST_SystemWin32::processTrackpad()
LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, uint msg, WPARAM wParam, LPARAM lParam)
{
GHOST_Event *event = NULL;
GHOST_Event *event = nullptr;
bool eventHandled = false;
LRESULT lResult = 0;
@ -2011,7 +2011,7 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, uint msg, WPARAM wParam,
*/
if (!window->m_inLiveResize) {
event = processWindowEvent(GHOST_kEventWindowUpdate, window);
::ValidateRect(hwnd, NULL);
::ValidateRect(hwnd, nullptr);
}
else {
eventHandled = true;
@ -2084,7 +2084,7 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, uint msg, WPARAM wParam,
/* Then move and resize window. */
SetWindowPos(hwnd,
NULL,
nullptr,
suggestedWindowRect->left,
suggestedWindowRect->top,
suggestedWindowRect->right - suggestedWindowRect->left,
@ -2111,8 +2111,10 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, uint msg, WPARAM wParam,
break;
}
case WM_SETTINGCHANGE: {
/* Microsoft: "Note that some applications send this message with lParam set to NULL" */
if ((lParam != NULL) && (wcscmp(LPCWSTR(lParam), L"ImmersiveColorSet") == 0)) {
/* Microsoft: "Note that some applications send this message with lParam set to nullptr"
*/
if (((void *)lParam != nullptr) && (wcscmp(LPCWSTR(lParam), L"ImmersiveColorSet") == 0))
{
window->ThemeRefresh();
}
break;
@ -2228,17 +2230,17 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, uint msg, WPARAM wParam,
char *GHOST_SystemWin32::getClipboard(bool /*selection*/) const
{
if (IsClipboardFormatAvailable(CF_UNICODETEXT) && OpenClipboard(NULL)) {
if (IsClipboardFormatAvailable(CF_UNICODETEXT) && OpenClipboard(nullptr)) {
wchar_t *buffer;
HANDLE hData = GetClipboardData(CF_UNICODETEXT);
if (hData == NULL) {
if (hData == nullptr) {
CloseClipboard();
return NULL;
return nullptr;
}
buffer = (wchar_t *)GlobalLock(hData);
if (!buffer) {
CloseClipboard();
return NULL;
return nullptr;
}
char *temp_buff = alloc_utf_8_from_16(buffer, 0);
@ -2250,18 +2252,18 @@ char *GHOST_SystemWin32::getClipboard(bool /*selection*/) const
return temp_buff;
}
if (IsClipboardFormatAvailable(CF_TEXT) && OpenClipboard(NULL)) {
if (IsClipboardFormatAvailable(CF_TEXT) && OpenClipboard(nullptr)) {
char *buffer;
size_t len = 0;
HANDLE hData = GetClipboardData(CF_TEXT);
if (hData == NULL) {
if (hData == nullptr) {
CloseClipboard();
return NULL;
return nullptr;
}
buffer = (char *)GlobalLock(hData);
if (!buffer) {
CloseClipboard();
return NULL;
return nullptr;
}
len = strlen(buffer);
@ -2285,7 +2287,7 @@ void GHOST_SystemWin32::putClipboard(const char *buffer, bool selection) const
return;
} /* For copying the selection, used on X11. */
if (OpenClipboard(NULL)) {
if (OpenClipboard(nullptr)) {
EmptyClipboard();
/* Get length of buffer including the terminating null. */
@ -2589,10 +2591,10 @@ GHOST_TSuccess GHOST_SystemWin32::showMessageBox(const char *title,
config.pButtons = (link) ? buttons : buttons + 1;
config.cButtons = (link) ? 2 : 1;
TaskDialogIndirect(&config, &nButtonPressed, NULL, NULL);
TaskDialogIndirect(&config, &nButtonPressed, nullptr, nullptr);
switch (nButtonPressed) {
case IDOK:
ShellExecute(NULL, "open", link, NULL, NULL, SW_SHOWNORMAL);
ShellExecute(nullptr, "open", link, nullptr, nullptr, SW_SHOWNORMAL);
break;
case IDCONTINUE:
break;
@ -2659,8 +2661,8 @@ static bool isStartedFromCommandPrompt()
GetWindowThreadProcessId(hwnd, &pid);
if (getProcessName(ppid, parent_name, sizeof(parent_name))) {
char *filename = strrchr(parent_name, '\\');
if (filename != NULL) {
start_from_launcher = strstr(filename, "blender.exe") != NULL;
if (filename != nullptr) {
start_from_launcher = strstr(filename, "blender.exe") != nullptr;
}
}

View File

@ -359,7 +359,7 @@ GHOST_IContext *GHOST_SystemX11::createOffscreenContext(GHOST_GPUSettings gpuSet
#ifdef WITH_VULKAN_BACKEND
case GHOST_kDrawingContextTypeVulkan: {
GHOST_Context *context = new GHOST_ContextVK(
false, GHOST_kVulkanPlatformX11, 0, m_display, NULL, NULL, 1, 2, debug_context);
false, GHOST_kVulkanPlatformX11, 0, m_display, nullptr, nullptr, 1, 2, debug_context);
if (context->initializeDrawingContext()) {
return context;
}

View File

@ -21,8 +21,8 @@ GHOST_DirectManipulationHelper::GHOST_DirectManipulationHelper(
DWORD directManipulationViewportHandlerCookie,
bool isScrollDirectionInverted)
: m_hWnd(hWnd),
m_scrollDirectionRegKey(NULL),
m_scrollDirectionChangeEvent(NULL),
m_scrollDirectionRegKey(nullptr),
m_scrollDirectionChangeEvent(nullptr),
m_directManipulationManager(directManipulationManager),
m_directManipulationUpdateManager(directManipulationUpdateManager),
m_directManipulationViewport(directManipulationViewport),
@ -123,7 +123,7 @@ bool GHOST_DirectManipulationHelper::getScrollDirectionFromReg()
L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\PrecisionTouchPad\\",
L"ScrollDirection",
RRF_RT_REG_DWORD,
NULL,
nullptr,
&scrollDirectionRegValue,
&pcbData));
if (!SUCCEEDED(hr)) {
@ -151,7 +151,7 @@ void GHOST_DirectManipulationHelper::registerScrollDirectionChangeListener()
}
if (!m_scrollDirectionChangeEvent) {
m_scrollDirectionChangeEvent = CreateEventW(NULL, true, false, NULL);
m_scrollDirectionChangeEvent = CreateEventW(nullptr, true, false, nullptr);
}
else {
ResetEvent(m_scrollDirectionChangeEvent);
@ -219,11 +219,11 @@ GHOST_DirectManipulationHelper::~GHOST_DirectManipulationHelper()
if (m_scrollDirectionChangeEvent) {
CloseHandle(m_scrollDirectionChangeEvent);
m_scrollDirectionChangeEvent = NULL;
m_scrollDirectionChangeEvent = nullptr;
}
if (m_scrollDirectionRegKey) {
RegCloseKey(m_scrollDirectionRegKey);
m_scrollDirectionRegKey = NULL;
m_scrollDirectionRegKey = nullptr;
}
}

View File

@ -458,7 +458,7 @@ GHOST_WindowCocoa::~GHOST_WindowCocoa()
bool GHOST_WindowCocoa::getValid() const
{
NSView *view = (m_openGLView) ? m_openGLView : m_metalView;
return GHOST_Window::getValid() && m_window != NULL && view != NULL;
return GHOST_Window::getValid() && m_window != nullptr && view != nullptr;
}
void *GHOST_WindowCocoa::getOSWindow() const
@ -940,7 +940,7 @@ static NSCursor *getImageCursor(GHOST_TStandardCursor shape, NSString *name, NSP
@autoreleasepool {
/* clang-format on */
NSImage *image = [NSImage imageNamed:name];
if (image != NULL) {
if (image != nullptr) {
cursors[index] = [[NSCursor alloc] initWithImage:image hotSpot:hotspot];
}
}
@ -959,7 +959,7 @@ NSCursor *GHOST_WindowCocoa::getStandardCursor(GHOST_TStandardCursor shape) cons
return m_customCursor;
}
else {
return NULL;
return nullptr;
}
case GHOST_kStandardCursorDestroy:
return [NSCursor disappearingItemCursor];
@ -1024,7 +1024,7 @@ NSCursor *GHOST_WindowCocoa::getStandardCursor(GHOST_TStandardCursor shape) cons
case GHOST_kStandardCursorCrosshairC:
return getImageCursor(shape, @"crossc.pdf", NSMakePoint(16, 16));
default:
return NULL;
return nullptr;
}
}
@ -1043,7 +1043,7 @@ void GHOST_WindowCocoa::loadCursor(bool visible, GHOST_TStandardCursor shape) co
}
NSCursor *cursor = getStandardCursor(shape);
if (cursor == NULL) {
if (cursor == nullptr) {
cursor = getStandardCursor(GHOST_kStandardCursorDefault);
}

View File

@ -59,7 +59,7 @@ class GHOST_WindowManager {
/**
* Returns pointer to the full-screen window.
* \return The full-screen window (NULL if not in full-screen).
* \return The full-screen window (nullptr if not in full-screen).
*/
GHOST_IWindow *getFullScreenWindow() const;
@ -86,7 +86,7 @@ class GHOST_WindowManager {
/**
* Returns the active window (the window receiving events).
* There can be only one window active which should be in the current window list.
* \return window The active window (or NULL if there is none).
* \return window The active window (or nullptr if there is none).
*/
GHOST_IWindow *getActiveWindow() const;

View File

@ -1762,7 +1762,7 @@ GHOST_Context *GHOST_WindowWayland::newDrawingContext(GHOST_TDrawingContextType
GHOST_Context *context = new GHOST_ContextVK(m_wantStereoVisual,
GHOST_kVulkanPlatformWayland,
0,
NULL,
nullptr,
window_->wl_surface,
system_->wl_display(),
1,

View File

@ -62,7 +62,7 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
m_mousePresent(false),
m_inLiveResize(false),
m_system(system),
m_dropTarget(NULL),
m_dropTarget(nullptr),
m_hWnd(0),
m_hDC(0),
m_isDialog(dialog),
@ -71,13 +71,13 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
m_nPressedButtons(0),
m_customCursor(0),
m_wantAlphaBackground(alphaBackground),
m_Bar(NULL),
m_wintab(NULL),
m_Bar(nullptr),
m_wintab(nullptr),
m_lastPointerTabletData(GHOST_TABLET_DATA_NONE),
m_normal_state(GHOST_kWindowStateNormal),
m_user32(::LoadLibrary("user32.dll")),
m_parentWindowHwnd(parentwindow ? parentwindow->m_hWnd : HWND_DESKTOP),
m_directManipulationHelper(NULL),
m_directManipulationHelper(nullptr),
m_debug_context(is_debug)
{
DWORD style = parentwindow ?
@ -116,7 +116,7 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
0); /* pointer to window-creation data */
free(title_16);
if (m_hWnd == NULL) {
if (m_hWnd == nullptr) {
return;
}
@ -140,7 +140,7 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
MessageBox(m_hWnd, text, title, MB_OK | MB_ICONERROR);
::ReleaseDC(m_hWnd, m_hDC);
::DestroyWindow(m_hWnd);
m_hWnd = NULL;
m_hWnd = nullptr;
if (!parentwindow) {
exit(0);
}
@ -215,7 +215,7 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
/* Allow the showing of a progress bar on the taskbar. */
CoCreateInstance(
CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, IID_ITaskbarList3, (LPVOID *)&m_Bar);
CLSID_TaskbarList, nullptr, CLSCTX_INPROC_SERVER, IID_ITaskbarList3, (LPVOID *)&m_Bar);
/* Initialize Direct Manipulation. */
m_directManipulationHelper = GHOST_DirectManipulationHelper::create(m_hWnd, getDPIHint());
@ -263,24 +263,24 @@ GHOST_WindowWin32::~GHOST_WindowWin32()
if (m_Bar) {
m_Bar->SetProgressState(m_hWnd, TBPF_NOPROGRESS);
m_Bar->Release();
m_Bar = NULL;
m_Bar = nullptr;
}
closeWintab();
if (m_user32) {
FreeLibrary(m_user32);
m_user32 = NULL;
m_user32 = nullptr;
}
if (m_customCursor) {
DestroyCursor(m_customCursor);
m_customCursor = NULL;
m_customCursor = nullptr;
}
if (m_hWnd != NULL && m_hDC != NULL && releaseNativeHandles()) {
if (m_hWnd != nullptr && m_hDC != nullptr && releaseNativeHandles()) {
::ReleaseDC(m_hWnd, m_hDC);
m_hDC = NULL;
m_hDC = nullptr;
}
if (m_hWnd) {
@ -289,7 +289,7 @@ GHOST_WindowWin32::~GHOST_WindowWin32()
for (GHOST_IWindow *iter_win : m_system->getWindowManager()->getWindows()) {
GHOST_WindowWin32 *iter_winwin = (GHOST_WindowWin32 *)iter_win;
if (iter_winwin->m_parentWindowHwnd == m_hWnd) {
::SetWindowLongPtr(iter_winwin->m_hWnd, GWLP_HWNDPARENT, NULL);
::SetWindowLongPtr(iter_winwin->m_hWnd, GWLP_HWNDPARENT, 0);
iter_winwin->m_parentWindowHwnd = 0;
}
}
@ -299,15 +299,15 @@ GHOST_WindowWin32::~GHOST_WindowWin32()
RevokeDragDrop(m_hWnd);
/* Release our reference of the DropTarget and it will delete itself eventually. */
m_dropTarget->Release();
m_dropTarget = NULL;
m_dropTarget = nullptr;
}
::SetWindowLongPtr(m_hWnd, GWLP_USERDATA, NULL);
::SetWindowLongPtr(m_hWnd, GWLP_USERDATA, 0);
::DestroyWindow(m_hWnd);
m_hWnd = 0;
}
delete m_directManipulationHelper;
m_directManipulationHelper = NULL;
m_directManipulationHelper = nullptr;
}
void GHOST_WindowWin32::adjustWindowRectForClosestMonitor(LPRECT win_rect,
@ -565,7 +565,7 @@ GHOST_TSuccess GHOST_WindowWin32::setOrder(GHOST_TWindowOrder order)
setState(GHOST_kWindowStateNormal);
}
hWndInsertAfter = HWND_TOP;
hWndToRaise = NULL;
hWndToRaise = nullptr;
}
if (::SetWindowPos(m_hWnd, hWndInsertAfter, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE) == FALSE) {
@ -690,7 +690,7 @@ void GHOST_WindowWin32::updateMouseCapture(GHOST_MouseCaptureEventWin32 event)
HCURSOR GHOST_WindowWin32::getStandardCursor(GHOST_TStandardCursor shape) const
{
/* Convert GHOST cursor to Windows OEM cursor. */
HANDLE cursor = NULL;
HANDLE cursor = nullptr;
HMODULE module = ::GetModuleHandle(0);
uint32_t flags = LR_SHARED | LR_DEFAULTSIZE;
int cx = 0, cy = 0;
@ -701,7 +701,7 @@ HCURSOR GHOST_WindowWin32::getStandardCursor(GHOST_TStandardCursor shape) const
return m_customCursor;
}
else {
return NULL;
return nullptr;
}
case GHOST_kStandardCursorRightArrow:
cursor = ::LoadImage(module, "arrowright_cursor", IMAGE_CURSOR, cx, cy, flags);
@ -746,13 +746,13 @@ HCURSOR GHOST_WindowWin32::getStandardCursor(GHOST_TStandardCursor shape) const
cursor = ::LoadImage(module, "scrollew_cursor", IMAGE_CURSOR, cx, cy, flags);
break;
case GHOST_kStandardCursorHelp:
cursor = ::LoadImage(NULL, IDC_HELP, IMAGE_CURSOR, cx, cy, flags);
cursor = ::LoadImage(nullptr, IDC_HELP, IMAGE_CURSOR, cx, cy, flags);
break; /* Arrow and question mark */
case GHOST_kStandardCursorWait:
cursor = ::LoadImage(NULL, IDC_WAIT, IMAGE_CURSOR, cx, cy, flags);
cursor = ::LoadImage(nullptr, IDC_WAIT, IMAGE_CURSOR, cx, cy, flags);
break; /* Hourglass */
case GHOST_kStandardCursorText:
cursor = ::LoadImage(NULL, IDC_IBEAM, IMAGE_CURSOR, cx, cy, flags);
cursor = ::LoadImage(nullptr, IDC_IBEAM, IMAGE_CURSOR, cx, cy, flags);
break; /* I-beam */
case GHOST_kStandardCursorCrosshair:
cursor = ::LoadImage(module, "cross_cursor", IMAGE_CURSOR, cx, cy, flags);
@ -775,19 +775,19 @@ HCURSOR GHOST_WindowWin32::getStandardCursor(GHOST_TStandardCursor shape) const
cursor = ::LoadImage(module, "moveew_cursor", IMAGE_CURSOR, cx, cy, flags);
break; /* Double-pointed arrow pointing west and east */
case GHOST_kStandardCursorTopSide:
cursor = ::LoadImage(NULL, IDC_UPARROW, IMAGE_CURSOR, cx, cy, flags);
cursor = ::LoadImage(nullptr, IDC_UPARROW, IMAGE_CURSOR, cx, cy, flags);
break; /* Vertical arrow */
case GHOST_kStandardCursorTopLeftCorner:
cursor = ::LoadImage(NULL, IDC_SIZENWSE, IMAGE_CURSOR, cx, cy, flags);
cursor = ::LoadImage(nullptr, IDC_SIZENWSE, IMAGE_CURSOR, cx, cy, flags);
break;
case GHOST_kStandardCursorTopRightCorner:
cursor = ::LoadImage(NULL, IDC_SIZENESW, IMAGE_CURSOR, cx, cy, flags);
cursor = ::LoadImage(nullptr, IDC_SIZENESW, IMAGE_CURSOR, cx, cy, flags);
break;
case GHOST_kStandardCursorBottomRightCorner:
cursor = ::LoadImage(NULL, IDC_SIZENWSE, IMAGE_CURSOR, cx, cy, flags);
cursor = ::LoadImage(nullptr, IDC_SIZENWSE, IMAGE_CURSOR, cx, cy, flags);
break;
case GHOST_kStandardCursorBottomLeftCorner:
cursor = ::LoadImage(NULL, IDC_SIZENESW, IMAGE_CURSOR, cx, cy, flags);
cursor = ::LoadImage(nullptr, IDC_SIZENESW, IMAGE_CURSOR, cx, cy, flags);
break;
case GHOST_kStandardCursorPencil:
cursor = ::LoadImage(module, "pencil_cursor", IMAGE_CURSOR, cx, cy, flags);
@ -800,14 +800,14 @@ HCURSOR GHOST_WindowWin32::getStandardCursor(GHOST_TStandardCursor shape) const
cursor = ::LoadImage(module, "forbidden_cursor", IMAGE_CURSOR, cx, cy, flags);
break; /* Slashed circle */
case GHOST_kStandardCursorDefault:
cursor = NULL;
cursor = nullptr;
break;
default:
return NULL;
return nullptr;
}
if (cursor == NULL) {
cursor = ::LoadImage(NULL, IDC_ARROW, IMAGE_CURSOR, cx, cy, flags);
if (cursor == nullptr) {
cursor = ::LoadImage(nullptr, IDC_ARROW, IMAGE_CURSOR, cx, cy, flags);
}
return (HCURSOR)cursor;
@ -825,7 +825,7 @@ void GHOST_WindowWin32::loadCursor(bool visible, GHOST_TStandardCursor shape) co
}
HCURSOR cursor = getStandardCursor(shape);
if (cursor == NULL) {
if (cursor == nullptr) {
cursor = getStandardCursor(GHOST_kStandardCursorDefault);
}
::SetCursor(cursor);
@ -899,7 +899,7 @@ GHOST_TSuccess GHOST_WindowWin32::getPointerInfo(
GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)GHOST_System::getSystem();
uint32_t outCount = 0;
if (!(GetPointerPenInfoHistory(pointerId, &outCount, NULL))) {
if (!(GetPointerPenInfoHistory(pointerId, &outCount, nullptr))) {
return GHOST_kFailure;
}
@ -1010,7 +1010,7 @@ void GHOST_WindowWin32::closeWintab()
{
WINTAB_PRINTF("Closing Wintab for window %p\n", m_hWnd);
delete m_wintab;
m_wintab = NULL;
m_wintab = nullptr;
}
bool GHOST_WindowWin32::usingTabletAPI(GHOST_TTabletAPI api) const
@ -1049,7 +1049,7 @@ void GHOST_WindowWin32::ThemeRefresh()
L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize\\",
L"AppsUseLightTheme",
RRF_RT_REG_DWORD,
NULL,
nullptr,
&lightMode,
&pcbData) == ERROR_SUCCESS)
{
@ -1124,7 +1124,7 @@ GHOST_TSuccess GHOST_WindowWin32::setWindowCustomCursorShape(uint8_t *bitmap,
if (m_customCursor) {
DestroyCursor(m_customCursor);
m_customCursor = NULL;
m_customCursor = nullptr;
}
memset(&andData, 0xFF, sizeof(andData));

View File

@ -1182,8 +1182,8 @@ GHOST_Context *GHOST_WindowX11::newDrawingContext(GHOST_TDrawingContextType type
GHOST_kVulkanPlatformX11,
m_window,
m_display,
NULL,
NULL,
nullptr,
nullptr,
1,
2,
m_is_debug_context);

View File

@ -276,7 +276,7 @@ void GHOST_XrContext::setErrorHandler(GHOST_XrErrorHandlerFn handler_fn, void *c
* \{ */
/**
* \param layer_name: May be NULL for extensions not belonging to a specific layer.
* \param layer_name: May be nullptr for extensions not belonging to a specific layer.
*/
void GHOST_XrContext::initExtensionsEx(std::vector<XrExtensionProperties> &extensions,
const char *layer_name)
@ -462,7 +462,7 @@ std::vector<GHOST_TXrGraphicsBinding> GHOST_XrContext::determineGraphicsBindingT
const GHOST_XrContextCreateInfo *create_info)
{
std::vector<GHOST_TXrGraphicsBinding> result;
assert(create_info->gpu_binding_candidates != NULL);
assert(create_info->gpu_binding_candidates != nullptr);
assert(create_info->gpu_binding_candidates_count > 0);
for (uint32_t i = 0; i < create_info->gpu_binding_candidates_count; i++) {

View File

@ -277,7 +277,8 @@ GHOST_XrSession::LifeExpectancy GHOST_XrSession::handleStateChangeEvent(
{
m_oxr->session_state = lifecycle.state;
/* Runtime may send events for apparently destroyed session. Our handle should be NULL then. */
/* Runtime may send events for apparently destroyed session. Our handle should be nullptr then.
*/
assert(m_oxr->session == XR_NULL_HANDLE || m_oxr->session == lifecycle.session);
switch (lifecycle.state) {

View File

@ -94,7 +94,7 @@ GHOST_XrSwapchain::GHOST_XrSwapchain(GHOST_XrSwapchain &&other)
GHOST_XrSwapchain::~GHOST_XrSwapchain()
{
/* m_oxr may be NULL after move. */
/* m_oxr may be nullptr after move. */
if (m_oxr && m_oxr->swapchain != XR_NULL_HANDLE) {
CHECK_XR_ASSERT(xrDestroySwapchain(m_oxr->swapchain));
}

View File

@ -187,12 +187,12 @@ static void mainwindow_do_key(MainWindow *mw, GHOST_TKey key, int press)
break;
case GHOST_kKeyLeftBracket:
if (press) {
GHOST_SetCursorVisibility(mw->win, 0);
GHOST_SetCursorVisibility(mw->win, false);
}
break;
case GHOST_kKeyRightBracket:
if (press) {
GHOST_SetCursorVisibility(mw->win, 1);
GHOST_SetCursorVisibility(mw->win, true);
}
break;
case GHOST_kKeyE:

View File

@ -22,6 +22,7 @@
#define LIBMV_NUMERIC_POLY_H_
#include <stdio.h>
#include <algorithm>
#include <cmath>
namespace libmv {

View File

@ -54,17 +54,11 @@ displays:
- !<View> {name: Standard, colorspace: sRGB}
- !<View> {name: Filmic, colorspace: Filmic sRGB}
- !<View> {name: Filmic Log, colorspace: Filmic Log}
- !<View> {name: Raw, colorspace: Raw}
- !<View> {name: False Color, colorspace: False Color}
XYZ:
- !<View> {name: Standard, colorspace: XYZ}
- !<View> {name: DCI, colorspace: dci_xyz}
- !<View> {name: Raw, colorspace: Raw}
None:
- !<View> {name: Standard, colorspace: Raw}
- !<View> {name: Raw, colorspace: Non-Color}
active_displays: [sRGB, XYZ, None]
active_views: [Standard, Filmic, Filmic Log, Raw, False Color]
active_displays: [sRGB]
active_views: [Standard, Filmic, Filmic Log, False Color, Raw]
colorspaces:
- !<ColorSpace>
@ -76,13 +70,6 @@ colorspaces:
Rec. 709 (Full Range), Blender native linear space
isdata: false
- !<ColorSpace>
name: Raw
family: raw
equalitygroup:
bitdepth: 32f
isdata: true
- !<ColorSpace>
name: Linear ACES
family: linear
@ -109,18 +96,6 @@ colorspaces:
- !<FileTransform> {src: srgb_to_xyz.spimtx, interpolation: linear}
- !<BuiltinTransform> {style: "UTILITY - ACES-AP1_to_CIE-XYZ-D65_BFD", direction: inverse}
- !<ColorSpace>
name: nuke_rec709
family: display
equalitygroup:
bitdepth: 32f
description: |
Rec. 709 (Full Range) Display Space
isdata: false
to_reference: !<GroupTransform>
children:
- !<FileTransform> {src: rec709.spi1d, interpolation: linear}
- !<ColorSpace>
name: XYZ
family: linear
@ -131,31 +106,6 @@ colorspaces:
children:
- !<FileTransform> {src: srgb_to_xyz.spimtx, interpolation: linear}
- !<ColorSpace>
name: dci_xyz
family: display
equalitygroup:
bitdepth: 16f
description: |
OpenDCP output LUT with DCI reference white and Gamma 2.6
isdata: false
from_reference: !<GroupTransform>
children:
- !<FileTransform> {src: srgb_to_xyz.spimtx, interpolation: linear}
- !<FileTransform> {src: dci_xyz.spi1d, interpolation: linear}
- !<ColorSpace>
name: lg10
family: display
equalitygroup:
bitdepth: 10ui
description: |
conversion from film log
isdata: false
to_reference: !<GroupTransform>
children:
- !<FileTransform> {src: lg10.spi1d, interpolation: nearest}
- !<ColorSpace>
name: sRGB
family:
@ -169,9 +119,10 @@ colorspaces:
- !<ColorSpace>
name: Non-Color
aliases: [Generic Data, Non-Colour Data, Raw, Utility - Raw]
family: raw
description: |
Color space used for images which contain non-color data (e.g. normal maps)
Generic data that is not color, will not apply any color transform (e.g. normal maps)
equalitygroup:
bitdepth: 32f
isdata: true

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +0,0 @@
1.0498110175 0.0000000000 -0.0000974845 0
-0.4959030231 1.3733130458 0.0982400361 0
0.0000000000 0.0000000000 0.9912520182 0

View File

@ -1,5 +0,0 @@
import bpy
material = (bpy.context.material.active_node_material if bpy.context.material.active_node_material else bpy.context.material)
material.subsurface_scattering.radius = 11.605, 3.884, 1.754
material.subsurface_scattering.color = 0.430, 0.210, 0.168

View File

@ -1,5 +0,0 @@
import bpy
material = (bpy.context.material.active_node_material if bpy.context.material.active_node_material else bpy.context.material)
material.subsurface_scattering.radius = 9.436, 3.348, 1.790
material.subsurface_scattering.color = 0.439, 0.216, 0.141

View File

@ -1,5 +0,0 @@
import bpy
material = (bpy.context.material.active_node_material if bpy.context.material.active_node_material else bpy.context.material)
material.subsurface_scattering.radius = 15.028, 4.664, 2.541
material.subsurface_scattering.color = 0.987, 0.943, 0.827

View File

@ -1,5 +0,0 @@
import bpy
material = (bpy.context.material.active_node_material if bpy.context.material.active_node_material else bpy.context.material)
material.subsurface_scattering.radius = 4.762, 0.575, 0.394
material.subsurface_scattering.color = 0.222, 0.008, 0.002

View File

@ -1,5 +0,0 @@
import bpy
material = (bpy.context.material.active_node_material if bpy.context.material.active_node_material else bpy.context.material)
material.subsurface_scattering.radius = 8.509, 5.566, 3.951
material.subsurface_scattering.color = 0.925, 0.905, 0.884

View File

@ -1,5 +0,0 @@
import bpy
material = (bpy.context.material.active_node_material if bpy.context.material.active_node_material else bpy.context.material)
material.subsurface_scattering.radius = 14.266, 7.228, 2.036
material.subsurface_scattering.color = 0.855, 0.740, 0.292

View File

@ -1,5 +0,0 @@
import bpy
material = (bpy.context.material.active_node_material if bpy.context.material.active_node_material else bpy.context.material)
material.subsurface_scattering.radius = 18.424, 10.443, 3.502
material.subsurface_scattering.color = 0.889, 0.888, 0.796

View File

@ -1,5 +0,0 @@
import bpy
material = (bpy.context.material.active_node_material if bpy.context.material.active_node_material else bpy.context.material)
material.subsurface_scattering.radius = 3.673, 1.367, 0.683
material.subsurface_scattering.color = 0.574, 0.313, 0.174

View File

@ -1,5 +0,0 @@
import bpy
material = (bpy.context.material.active_node_material if bpy.context.material.active_node_material else bpy.context.material)
material.subsurface_scattering.radius = 4.821, 1.694, 1.090
material.subsurface_scattering.color = 0.749, 0.571, 0.467

View File

@ -1,5 +0,0 @@
import bpy
material = (bpy.context.material.active_node_material if bpy.context.material.active_node_material else bpy.context.material)
material.subsurface_scattering.radius = 10.899, 6.575, 2.508
material.subsurface_scattering.color = 0.947, 0.931, 0.852

View File

@ -153,6 +153,9 @@ class MoveModifierToNodes(Operator):
if not first_geometry_input:
first_geometry_input = group_node_input
if not first_geometry_input:
self.report({"WARNING"}, "Node group must have a geometry input")
return {'CANCELLED'}
group.links.new(group_input_node.outputs[0], first_geometry_input)
# Adjust locations of named attribute input nodes and group input node to make some space.
@ -195,6 +198,9 @@ class MoveModifierToNodes(Operator):
group.links.new(store_nodes[-1].outputs["Geometry"], group_output_node.inputs[data_("Geometry")])
else:
if not first_geometry_output:
self.report({"WARNING"}, "Node group must have a geometry output")
return {"CANCELLED"}
group.links.new(first_geometry_output, group_output_node.inputs[data_("Geometry")])
modifier.node_group = group

View File

@ -62,18 +62,13 @@ def draw_root_assets(layout):
def add_simulation_zone(layout, label):
"""Add simulation zone to a menu."""
target_bl_rna = bpy.types.Node.bl_rna_get_subclass("GeometryNodeSimulationOutput")
if target_bl_rna:
translation_context = target_bl_rna.translation_context
else:
translation_context = i18n_contexts.default
props = layout.operator("node.add_simulation_zone", text=label, text_ctxt=translation_context)
props = layout.operator("node.add_simulation_zone", text=label, text_ctxt=i18n_contexts.default)
props.use_transform = True
return props
def add_repeat_zone(layout, label):
props = layout.operator("node.add_repeat_zone", text=label)
props = layout.operator("node.add_repeat_zone", text=label, text_ctxt=i18n_contexts.default)
props.use_transform = True
return props

View File

@ -765,6 +765,12 @@ class VIEW3D_HT_header(Header):
depress=(tool_settings.gpencil_selectmode_edit == 'STROKE'),
).mode = 'STROKE'
if object_mode == 'PAINT_GREASE_PENCIL':
row = layout.row()
sub = row.row(align=True)
sub.prop(tool_settings, "use_gpencil_draw_additive", text="", icon='FREEZE')
# Grease Pencil (legacy)
if obj and obj.type == 'GPENCIL' and context.gpencil_data:
gpd = context.gpencil_data

View File

@ -118,7 +118,6 @@ set(SRC_DNA_DEFAULTS_INC
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_particle_defaults.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_pointcloud_defaults.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_scene_defaults.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_simulation_defaults.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_space_defaults.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_speaker_defaults.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_texture_defaults.h

View File

@ -166,6 +166,8 @@ class AssetLibrary {
*/
AssetIdentifier asset_identifier_from_library(StringRef relative_asset_path);
std::string resolve_asset_weak_reference_to_full_path(const AssetWeakReference &asset_reference);
eAssetLibraryType library_type() const;
StringRefNull name() const;
StringRefNull root_path() const;

View File

@ -302,6 +302,13 @@ AssetIdentifier AssetLibrary::asset_identifier_from_library(StringRef relative_a
return AssetIdentifier(root_path_, relative_asset_path);
}
std::string AssetLibrary::resolve_asset_weak_reference_to_full_path(
const AssetWeakReference &asset_reference)
{
AssetLibraryService *service = AssetLibraryService::get();
return service->resolve_asset_weak_reference_to_full_path(asset_reference);
}
void AssetLibrary::refresh_catalog_simplename(AssetMetaData *asset_data)
{
if (BLI_uuid_is_nil(asset_data->catalog_id)) {

View File

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

View File

@ -429,11 +429,6 @@ void CustomData_bmesh_interp(struct CustomData *data,
*/
void CustomData_swap_corners(struct CustomData *data, int index, const int *corner_indices);
/**
* Swap two items of given custom data, in all available layers.
*/
void CustomData_swap(struct CustomData *data, int index_a, int index_b);
/**
* Retrieve a pointer to an element of the active layer of the given \a type, chosen by the
* \a index, if it exists.

View File

@ -9,6 +9,8 @@
* \brief Low-level operations for grease pencil.
*/
#include <atomic>
#include "BLI_function_ref.hh"
#include "BLI_map.hh"
#include "BLI_math_vector_types.hh"
@ -62,6 +64,13 @@ class DrawingRuntime {
* Triangle cache for all the strokes in the drawing.
*/
mutable SharedCache<Vector<uint3>> triangles_cache;
/**
* Number of users for this drawing. The users are the frames in the Grease Pencil layers.
* Different frames can refer to the same drawing, so we need to make sure we count these users
* and remove a drawing if it has zero users.
*/
mutable std::atomic<int> user_count = 1;
};
class Drawing : public ::GreasePencilDrawing {
@ -92,6 +101,22 @@ class Drawing : public ::GreasePencilDrawing {
*/
VArray<float> opacities() const;
MutableSpan<float> opacities_for_write();
/**
* Add a user for this drawing. When a drawing has multiple users, both users are allowed to
* modifify this drawings data.
*/
void add_user() const;
/**
* Removes a user from this drawing. Note that this does not handle deleting the drawing if it
* has not users.
*/
void remove_user() const;
/**
* Returns true for when this drawing has more than one user.
*/
bool is_instanced() const;
bool has_users() const;
};
class LayerGroup;
@ -167,6 +192,10 @@ class LayerMask : public ::GreasePencilLayerMask {
~LayerMask();
};
/* The key of a GreasePencilFrame in the frames map is the starting scene frame number (int) of
* that frame. */
using FramesMapKey = int;
class LayerRuntime {
public:
/**
@ -194,11 +223,11 @@ class LayerRuntime {
* referenced drawings are discarded. If the frame is longer than the number of referenced
* drawings, then the last referenced drawing is held for the rest of the duration.
*/
Map<int, GreasePencilFrame> frames_;
Map<FramesMapKey, GreasePencilFrame> frames_;
/**
* Caches a sorted vector of the keys of `frames_`.
*/
mutable SharedCache<Vector<int>> sorted_keys_cache_;
mutable SharedCache<Vector<FramesMapKey>> sorted_keys_cache_;
/**
* A vector of LayerMask. This layer will be masked by the layers referenced in the masks.
* A layer can have zero or more layer masks.
@ -237,8 +266,8 @@ class Layer : public ::GreasePencilLayer {
/**
* \returns the frames mapping.
*/
const Map<int, GreasePencilFrame> &frames() const;
Map<int, GreasePencilFrame> &frames_for_write();
const Map<FramesMapKey, GreasePencilFrame> &frames() const;
Map<FramesMapKey, GreasePencilFrame> &frames_for_write();
bool is_visible() const;
bool is_locked() const;
@ -248,28 +277,44 @@ class Layer : public ::GreasePencilLayer {
/**
* Adds a new frame into the layer frames map.
* Fails if there already exists a frame at \a frame_number that is not a null-frame.
* Null-frame at \a frame_number and subsequent null-frames are removed.
* Fails if there already exists a frame at \a key that is not a null-frame.
* Null-frame at \a key and subsequent null-frames are removed.
*
* If \a duration is 0, the frame is marked as an implicit hold (see `GP_FRAME_IMPLICIT_HOLD`).
* Otherwise adds an additional null-frame at \a frame_number + \a duration, if necessary, to
* Otherwise adds an additional null-frame at \a key + \a duration, if necessary, to
* indicate the end of the added frame.
*
* \returns a pointer to the added frame on success, otherwise nullptr.
*/
GreasePencilFrame *add_frame(int frame_number, int drawing_index, int duration = 0);
GreasePencilFrame *add_frame(FramesMapKey key, int drawing_index, int duration = 0);
/**
* Removes a frame with \a key from the frames map.
*
* Fails if the map does not contain a frame with \a key or in the specific case where
* the previous frame has a fixed duration (is not marked as an implicit hold) and the frame to
* remove is a null frame.
*
* Will remove null frames after the frame to remove.
* \return true on success.
*/
bool remove_frame(FramesMapKey key);
/**
* Returns the sorted (start) frame numbers of the frames of this layer.
* Returns the sorted keys (start frame numbers) of the frames of this layer.
* \note This will cache the keys lazily.
*/
Span<int> sorted_keys() const;
Span<FramesMapKey> sorted_keys() const;
/**
* \returns the index of the active drawing at frame \a frame_number or -1 if there is no
* drawing. */
int drawing_index_at(const int frame_number) const;
/**
* \returns the key of the active frame at \a frame_number or -1 if there is no frame.
*/
FramesMapKey frame_key_at(int frame_number) const;
/**
* \returns a pointer to the active frame at \a frame_number or nullptr if there is no frame.
*/
@ -284,9 +329,19 @@ class Layer : public ::GreasePencilLayer {
*/
void tag_frames_map_keys_changed();
private:
using SortedKeysIterator = const int *;
private:
GreasePencilFrame *add_frame_internal(int frame_number, int drawing_index);
int frame_index_at(int frame_number) const;
/**
* Removes null frames starting from \a begin until \a end (excluded) or until a non-null frame
* is reached. \param begin, end: Iterators into the `sorted_keys` span. \returns an iterator to
* the element after the last null-frame that was removed.
*/
SortedKeysIterator remove_leading_null_frames_in_range(SortedKeysIterator begin,
SortedKeysIterator end);
};
class LayerGroupRuntime {
@ -482,6 +537,26 @@ class GreasePencilRuntime {
} // namespace blender::bke
inline void blender::bke::greasepencil::Drawing::add_user() const
{
this->runtime->user_count.fetch_add(1, std::memory_order_relaxed);
}
inline void blender::bke::greasepencil::Drawing::remove_user() const
{
this->runtime->user_count.fetch_sub(1, std::memory_order_relaxed);
}
inline bool blender::bke::greasepencil::Drawing::is_instanced() const
{
return this->runtime->user_count.load(std::memory_order_relaxed) > 1;
}
inline bool blender::bke::greasepencil::Drawing::has_users() const
{
return this->runtime->user_count.load(std::memory_order_relaxed) > 0;
}
inline blender::bke::greasepencil::Drawing &GreasePencilDrawing::wrap()
{
return *reinterpret_cast<blender::bke::greasepencil::Drawing *>(this);

View File

@ -537,40 +537,6 @@ void BKE_mesh_calc_volume(const float (*vert_positions)[3],
*/
void BKE_mesh_mdisp_flip(struct MDisps *md, bool use_loop_mdisp_flip);
/**
* Flip (invert winding of) the given \a face, i.e. reverse order of its loops
* (keeping the same vertex as 'start point').
*
* \param face: the face to flip.
* \param mloop: the full loops array.
* \param loop_data: the loops custom data.
*/
void BKE_mesh_face_flip_ex(int face_offset,
int face_size,
int *corner_verts,
int *corner_edges,
struct CustomData *loop_data,
float (*lnors)[3],
struct MDisps *mdisp,
bool use_loop_mdisp_flip);
void BKE_mesh_face_flip(int face_offset,
int face_size,
int *corner_verts,
int *corner_edges,
struct CustomData *loop_data,
int totloop);
/**
* Flip (invert winding of) all faces (used to inverse their normals).
*
* \note Invalidates tessellation, caller must handle that.
*/
void BKE_mesh_faces_flip(const int *face_offsets,
int *corner_verts,
int *corner_edges,
struct CustomData *loop_data,
int faces_num);
/**
* Account for custom-data such as UVs becoming detached because of imprecision
* in custom-data interpolation.

View File

@ -8,10 +8,12 @@
* \ingroup bke
*/
#include "BLI_index_mask.hh"
#include "BKE_mesh.h"
namespace blender::bke::mesh {
namespace blender::bke {
namespace mesh {
/* -------------------------------------------------------------------- */
/** \name Polygon Data Evaluation
* \{ */
@ -270,7 +272,11 @@ inline int edge_other_vert(const int2 &edge, const int vert)
/** \} */
} // namespace blender::bke::mesh
} // namespace mesh
void mesh_flip_faces(Mesh &mesh, const IndexMask &selection);
} // namespace blender::bke
/* -------------------------------------------------------------------- */
/** \name Inline Mesh Data Access

View File

@ -246,7 +246,6 @@ bool BKE_scene_uses_cycles_experimental_features(struct Scene *scene);
void BKE_scene_copy_data_eevee(struct Scene *sce_dst, const struct Scene *sce_src);
void BKE_scene_disable_color_management(struct Scene *scene);
bool BKE_scene_check_color_management_enabled(const struct Scene *scene);
bool BKE_scene_check_rigidbody_active(const struct Scene *scene);
int BKE_scene_num_threads(const struct Scene *scene);

View File

@ -202,6 +202,7 @@ set(SRC
intern/mesh_debug.cc
intern/mesh_evaluate.cc
intern/mesh_fair.cc
intern/mesh_flip_faces.cc
intern/mesh_iterators.cc
intern/mesh_legacy_convert.cc
intern/mesh_mapping.cc

View File

@ -284,7 +284,7 @@ static IDRemapper *reuse_bmain_data_remapper_ensure(ReuseOldBMainData *reuse_dat
IDRemapper *remapper = reuse_data->remapper;
LISTBASE_FOREACH (Library *, old_lib_iter, &old_bmain->libraries) {
/* In case newly opened `new_bmain` is a library of the `old_bmain`, remap it to NULL, since a
/* In case newly opened `new_bmain` is a library of the `old_bmain`, remap it to null, since a
* file should never ever have linked data from itself. */
if (STREQ(old_lib_iter->filepath_abs, new_bmain->filepath)) {
BKE_id_remapper_add(remapper, &old_lib_iter->id, nullptr);
@ -314,12 +314,12 @@ static bool reuse_bmain_data_remapper_is_id_remapped(IDRemapper *remapper, ID *i
IDRemapperApplyResult result = BKE_id_remapper_get_mapping_result(
remapper, id, ID_REMAP_APPLY_DEFAULT, nullptr);
if (ELEM(result, ID_REMAP_RESULT_SOURCE_REMAPPED, ID_REMAP_RESULT_SOURCE_UNASSIGNED)) {
/* ID is already remapped to its matching ID in the new main, or explicitly remapped to NULL,
/* ID is already remapped to its matching ID in the new main, or explicitly remapped to null,
* nothing else to do here. */
return true;
}
BLI_assert_msg(result != ID_REMAP_RESULT_SOURCE_NOT_MAPPABLE,
"There should never be a non-mappable (i.e. NULL) input here.");
"There should never be a non-mappable (i.e. null) input here.");
BLI_assert(result == ID_REMAP_RESULT_SOURCE_UNAVAILABLE);
return false;
}
@ -783,7 +783,7 @@ static void setup_app_data(bContext *C,
if (track_undo_scene) {
/* Keep the old (to-be-freed) scene, remapping below will ensure it's remapped to the
* matching new scene if available, or NULL otherwise, in which case
* matching new scene if available, or null otherwise, in which case
* #wm_data_consistency_ensure will define `curscene` as the active one. */
}
/* Enforce curscene to be in current screen. */

View File

@ -3505,32 +3505,6 @@ void CustomData_swap_corners(CustomData *data, const int index, const int *corne
}
}
void CustomData_swap(CustomData *data, const int index_a, const int index_b)
{
char buff_static[256];
if (index_a == index_b) {
return;
}
for (int i = 0; i < data->totlayer; i++) {
const LayerTypeInfo *typeInfo = layerType_getInfo(eCustomDataType(data->layers[i].type));
const size_t size = typeInfo->size;
const size_t offset_a = size * index_a;
const size_t offset_b = size * index_b;
void *buff = size <= sizeof(buff_static) ? buff_static : MEM_mallocN(size, __func__);
memcpy(buff, POINTER_OFFSET(data->layers[i].data, offset_a), size);
memcpy(POINTER_OFFSET(data->layers[i].data, offset_a),
POINTER_OFFSET(data->layers[i].data, offset_b),
size);
memcpy(POINTER_OFFSET(data->layers[i].data, offset_b), buff, size);
if (buff != buff_static) {
MEM_freeN(buff);
}
}
}
void *CustomData_get_for_write(CustomData *data,
const int index,

View File

@ -1498,8 +1498,6 @@ struct DynamicPaintSetInitColorData {
blender::Span<MLoopTri> looptris;
const MLoopCol *mloopcol;
ImagePool *pool;
bool scene_color_manage;
};
static void dynamic_paint_set_init_color_tex_to_vcol_cb(void *__restrict userdata,
@ -1517,8 +1515,6 @@ static void dynamic_paint_set_init_color_tex_to_vcol_cb(void *__restrict userdat
ImagePool *pool = data->pool;
Tex *tex = data->surface->init_texture;
const bool scene_color_manage = data->scene_color_manage;
float uv[3] = {0.0f};
for (int j = 3; j--;) {
@ -1529,7 +1525,7 @@ static void dynamic_paint_set_init_color_tex_to_vcol_cb(void *__restrict userdat
uv[0] = mloopuv[looptris[i].tri[j]][0] * 2.0f - 1.0f;
uv[1] = mloopuv[looptris[i].tri[j]][1] * 2.0f - 1.0f;
multitex_ext_safe(tex, uv, &texres, pool, scene_color_manage, false);
multitex_ext_safe(tex, uv, &texres, pool, true, false);
if (texres.tin > pPoint[vert].color[3]) {
copy_v3_v3(pPoint[vert].color, texres.trgba);
@ -1553,8 +1549,6 @@ static void dynamic_paint_set_init_color_tex_to_imseq_cb(void *__restrict userda
ImgSeqFormatData *f_data = (ImgSeqFormatData *)sData->format_data;
const int samples = (data->surface->flags & MOD_DPAINT_ANTIALIAS) ? 5 : 1;
const bool scene_color_manage = data->scene_color_manage;
float uv[9] = {0.0f};
float uv_final[3] = {0.0f};
@ -1571,7 +1565,7 @@ static void dynamic_paint_set_init_color_tex_to_imseq_cb(void *__restrict userda
uv_final[0] = uv_final[0] * 2.0f - 1.0f;
uv_final[1] = uv_final[1] * 2.0f - 1.0f;
multitex_ext_safe(tex, uv_final, &texres, nullptr, scene_color_manage, false);
multitex_ext_safe(tex, uv_final, &texres, nullptr, true, false);
/* apply color */
copy_v3_v3(pPoint[i].color, texres.trgba);
@ -1606,12 +1600,11 @@ static void dynamic_paint_set_init_color_vcol_to_imseq_cb(
copy_v4_v4(pPoint[i].color, final_color);
}
static void dynamicPaint_setInitialColor(const Scene *scene, DynamicPaintSurface *surface)
static void dynamicPaint_setInitialColor(const Scene * /*scene*/, DynamicPaintSurface *surface)
{
PaintSurfaceData *sData = surface->data;
PaintPoint *pPoint = (PaintPoint *)sData->type_data;
Mesh *mesh = dynamicPaint_canvas_mesh_get(surface->canvas);
const bool scene_color_manage = BKE_scene_check_color_management_enabled(scene);
if (surface->type != MOD_DPAINT_SURFACE_T_PAINT) {
return;
@ -1662,7 +1655,6 @@ static void dynamicPaint_setInitialColor(const Scene *scene, DynamicPaintSurface
data.looptris = looptris;
data.mloopuv = mloopuv;
data.pool = pool;
data.scene_color_manage = scene_color_manage;
TaskParallelSettings settings;
BLI_parallel_range_settings_defaults(&settings);
@ -1676,7 +1668,6 @@ static void dynamicPaint_setInitialColor(const Scene *scene, DynamicPaintSurface
data.surface = surface;
data.looptris = looptris;
data.mloopuv = mloopuv;
data.scene_color_manage = scene_color_manage;
TaskParallelSettings settings;
BLI_parallel_range_settings_defaults(&settings);

View File

@ -226,13 +226,12 @@ const float (*BKE_editmesh_vert_coords_when_deformed(Depsgraph *depsgraph,
const float(*coords)[3] = nullptr;
*r_is_alloc = false;
Mesh *me = static_cast<Mesh *>(ob->data);
Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(object_eval);
if (BKE_mesh_wrapper_vert_coords(me) != nullptr) {
if (Mesh *mesh_cage = BKE_object_get_editmesh_eval_cage(ob)) {
/* Deformed, and we have deformed coords already. */
coords = BKE_mesh_wrapper_vert_coords(me);
coords = BKE_mesh_wrapper_vert_coords(mesh_cage);
}
else if ((editmesh_eval_final != nullptr) &&
(editmesh_eval_final->runtime->wrapper_type == ME_WRAPPER_TYPE_BMESH))

View File

@ -872,7 +872,6 @@ static void do_texture_effector(EffectorCache *eff,
float nabla = eff->pd->tex_nabla;
int hasrgb;
short mode = eff->pd->tex_mode;
bool scene_color_manage;
if (!eff->pd->tex) {
return;
@ -894,10 +893,8 @@ static void do_texture_effector(EffectorCache *eff,
madd_v3_v3fl(tex_co, efd->nor, fac);
}
scene_color_manage = BKE_scene_check_color_management_enabled(eff->scene);
hasrgb = multitex_ext(
eff->pd->tex, tex_co, nullptr, nullptr, 0, result, 0, nullptr, scene_color_manage, false);
eff->pd->tex, tex_co, nullptr, nullptr, 0, result, 0, nullptr, true, false);
if (hasrgb && mode == PFIELD_TEX_RGB) {
force[0] = (0.5f - result->trgba[0]) * strength;
@ -908,42 +905,15 @@ static void do_texture_effector(EffectorCache *eff,
strength /= nabla;
tex_co[0] += nabla;
multitex_ext(eff->pd->tex,
tex_co,
nullptr,
nullptr,
0,
result + 1,
0,
nullptr,
scene_color_manage,
false);
multitex_ext(eff->pd->tex, tex_co, nullptr, nullptr, 0, result + 1, 0, nullptr, true, false);
tex_co[0] -= nabla;
tex_co[1] += nabla;
multitex_ext(eff->pd->tex,
tex_co,
nullptr,
nullptr,
0,
result + 2,
0,
nullptr,
scene_color_manage,
false);
multitex_ext(eff->pd->tex, tex_co, nullptr, nullptr, 0, result + 2, 0, nullptr, true, false);
tex_co[1] -= nabla;
tex_co[2] += nabla;
multitex_ext(eff->pd->tex,
tex_co,
nullptr,
nullptr,
0,
result + 3,
0,
nullptr,
scene_color_manage,
false);
multitex_ext(eff->pd->tex, tex_co, nullptr, nullptr, 0, result + 3, 0, nullptr, true, false);
if (mode == PFIELD_TEX_GRAD || !hasrgb) { /* if we don't have rgb fall back to grad */
/* generate intensity if texture only has rgb value */

View File

@ -109,7 +109,6 @@ static void grease_pencil_copy_data(Main * /*bmain*/,
break;
}
}
/* TODO: Update drawing user counts. */
}
/* Duplicate layer tree. */
@ -601,53 +600,57 @@ bool Layer::is_selected() const
return ((this->base.flag & GP_LAYER_TREE_NODE_SELECT) != 0);
}
GreasePencilFrame *Layer::add_frame_internal(const int frame_number, const int drawing_index)
Layer::SortedKeysIterator Layer::remove_leading_null_frames_in_range(
Layer::SortedKeysIterator begin, Layer::SortedKeysIterator end)
{
Layer::SortedKeysIterator next_it = begin;
while (next_it != end && this->frames().lookup(*next_it).is_null()) {
this->frames_for_write().remove_contained(*next_it);
this->tag_frames_map_keys_changed();
next_it = std::next(next_it);
}
return next_it;
}
GreasePencilFrame *Layer::add_frame_internal(const FramesMapKey key, const int drawing_index)
{
BLI_assert(drawing_index != -1);
if (!this->frames().contains(frame_number)) {
if (!this->frames().contains(key)) {
GreasePencilFrame frame{};
frame.drawing_index = drawing_index;
this->frames_for_write().add(frame_number, frame);
this->frames_for_write().add_new(key, frame);
this->tag_frames_map_keys_changed();
return this->frames_for_write().lookup_ptr(frame_number);
return this->frames_for_write().lookup_ptr(key);
}
/* Overwrite null-frames. */
if (this->frames().lookup(frame_number).is_null()) {
if (this->frames().lookup(key).is_null()) {
GreasePencilFrame frame{};
frame.drawing_index = drawing_index;
this->frames_for_write().add_overwrite(frame_number, frame);
this->frames_for_write().add_overwrite(key, frame);
this->tag_frames_map_changed();
return this->frames_for_write().lookup_ptr(frame_number);
return this->frames_for_write().lookup_ptr(key);
}
return nullptr;
}
GreasePencilFrame *Layer::add_frame(const int frame_number,
GreasePencilFrame *Layer::add_frame(const FramesMapKey key,
const int drawing_index,
const int duration)
{
BLI_assert(duration >= 0);
GreasePencilFrame *frame = this->add_frame_internal(frame_number, drawing_index);
GreasePencilFrame *frame = this->add_frame_internal(key, drawing_index);
if (frame == nullptr) {
return nullptr;
}
Span<int> sorted_keys = this->sorted_keys();
const int end_frame_number = frame_number + duration;
/* Finds the next greater frame_number that is stored in the map. */
auto next_frame_number_it = std::upper_bound(
sorted_keys.begin(), sorted_keys.end(), frame_number);
Span<FramesMapKey> sorted_keys = this->sorted_keys();
const FramesMapKey end_key = key + duration;
/* Finds the next greater key that is stored in the map. */
SortedKeysIterator next_key_it = std::upper_bound(sorted_keys.begin(), sorted_keys.end(), key);
/* If the next frame we found is at the end of the frame we're inserting, then we are done. */
if (next_frame_number_it != sorted_keys.end() && *next_frame_number_it == end_frame_number) {
if (next_key_it != sorted_keys.end() && *next_key_it == end_key) {
return frame;
}
/* While the next frame is a null frame, remove it. */
while (next_frame_number_it != sorted_keys.end() &&
this->frames().lookup(*next_frame_number_it).is_null())
{
this->frames_for_write().remove(*next_frame_number_it);
this->tag_frames_map_keys_changed();
next_frame_number_it = std::next(next_frame_number_it);
}
next_key_it = this->remove_leading_null_frames_in_range(next_key_it, sorted_keys.end());
/* If the duration is set to 0, the frame is marked as an implicit hold.*/
if (duration == 0) {
frame->flag |= GP_FRAME_IMPLICIT_HOLD;
@ -655,19 +658,57 @@ GreasePencilFrame *Layer::add_frame(const int frame_number,
}
/* If the next frame comes after the end of the frame we're inserting (or if there are no more
* frames), add a null-frame. */
if (next_frame_number_it == sorted_keys.end() || *next_frame_number_it > end_frame_number) {
this->frames_for_write().add(end_frame_number, GreasePencilFrame::null());
if (next_key_it == sorted_keys.end() || *next_key_it > end_key) {
this->frames_for_write().add_new(end_key, GreasePencilFrame::null());
this->tag_frames_map_keys_changed();
}
return frame;
}
Span<int> Layer::sorted_keys() const
bool Layer::remove_frame(const FramesMapKey key)
{
this->runtime->sorted_keys_cache_.ensure([&](Vector<int> &r_data) {
/* If the frame number is not in the frames map, do nothing. */
if (!this->frames().contains(key)) {
return false;
}
if (this->frames().size() == 1) {
this->frames_for_write().remove_contained(key);
this->tag_frames_map_keys_changed();
return true;
}
Span<FramesMapKey> sorted_keys = this->sorted_keys();
/* Find the index of the frame to remove in the `sorted_keys` array. */
SortedKeysIterator remove_key_it = std::lower_bound(sorted_keys.begin(), sorted_keys.end(), key);
/* If there is a next frame: */
if (std::next(remove_key_it) != sorted_keys.end()) {
SortedKeysIterator next_key_it = std::next(remove_key_it);
this->remove_leading_null_frames_in_range(next_key_it, sorted_keys.end());
}
/* If there is a previous frame: */
if (remove_key_it != sorted_keys.begin()) {
SortedKeysIterator prev_key_it = std::prev(remove_key_it);
const GreasePencilFrame &prev_frame = this->frames().lookup(*prev_key_it);
/* If the previous frame is not an implicit hold (e.g. it has a fixed duration) and it's not a
* null frame, we cannot just delete the frame. We need to replace it with a null frame. */
if (!prev_frame.is_implicit_hold() && !prev_frame.is_null()) {
this->frames_for_write().lookup(key) = GreasePencilFrame::null();
/* Since the original frame was replaced with a null frame, we consider the frame to be
* successfully removed here. */
return true;
}
}
/* Finally, remove the actual frame. */
this->frames_for_write().remove_contained(key);
this->tag_frames_map_keys_changed();
return true;
}
Span<FramesMapKey> Layer::sorted_keys() const
{
this->runtime->sorted_keys_cache_.ensure([&](Vector<FramesMapKey> &r_data) {
r_data.reinitialize(this->frames().size());
int i = 0;
for (int64_t key : this->frames().keys()) {
for (FramesMapKey key : this->frames().keys()) {
r_data[i++] = key;
}
std::sort(r_data.begin(), r_data.end());
@ -675,7 +716,7 @@ Span<int> Layer::sorted_keys() const
return this->runtime->sorted_keys_cache_.data();
}
int Layer::frame_index_at(const int frame_number) const
FramesMapKey Layer::frame_key_at(const int frame_number) const
{
Span<int> sorted_keys = this->sorted_keys();
/* No keyframes, return no drawing. */
@ -691,7 +732,7 @@ int Layer::frame_index_at(const int frame_number) const
return sorted_keys.last();
}
/* Search for the drawing. upper_bound will get the drawing just after. */
auto it = std::upper_bound(sorted_keys.begin(), sorted_keys.end(), frame_number);
SortedKeysIterator it = std::upper_bound(sorted_keys.begin(), sorted_keys.end(), frame_number);
if (it == sorted_keys.end() || it == sorted_keys.begin()) {
return -1;
}
@ -700,14 +741,14 @@ int Layer::frame_index_at(const int frame_number) const
const GreasePencilFrame *Layer::frame_at(const int frame_number) const
{
const int frame_index = this->frame_index_at(frame_number);
return (frame_index == -1) ? nullptr : this->frames().lookup_ptr(frame_index);
const FramesMapKey frame_key = this->frame_key_at(frame_number);
return (frame_key == -1) ? nullptr : this->frames().lookup_ptr(frame_key);
}
GreasePencilFrame *Layer::frame_at(const int frame_number)
{
const int frame_index = this->frame_index_at(frame_number);
return (frame_index == -1) ? nullptr : this->frames_for_write().lookup_ptr(frame_index);
const FramesMapKey frame_key = this->frame_key_at(frame_number);
return (frame_key == -1) ? nullptr : this->frames_for_write().lookup_ptr(frame_key);
}
int Layer::drawing_index_at(const int frame_number) const
@ -1339,8 +1380,21 @@ void GreasePencil::add_empty_drawings(const int add_num)
new_drawings[i] = reinterpret_cast<GreasePencilDrawingBase *>(
MEM_new<blender::bke::greasepencil::Drawing>(__func__));
}
}
/* TODO: Update drawing user counts. */
void GreasePencil::add_duplicate_drawings(const int duplicate_num,
const blender::bke::greasepencil::Drawing &drawing)
{
using namespace blender;
BLI_assert(duplicate_num > 0);
const int prev_num = this->drawings().size();
grow_array<GreasePencilDrawingBase *>(
&this->drawing_array, &this->drawing_array_num, duplicate_num);
MutableSpan<GreasePencilDrawingBase *> new_drawings = this->drawings().drop_front(prev_num);
for (const int i : new_drawings.index_range()) {
new_drawings[i] = reinterpret_cast<GreasePencilDrawingBase *>(
MEM_new<bke::greasepencil::Drawing>(__func__, drawing));
}
}
bool GreasePencil::insert_blank_frame(blender::bke::greasepencil::Layer &layer,
@ -1358,6 +1412,99 @@ bool GreasePencil::insert_blank_frame(blender::bke::greasepencil::Layer &layer,
return true;
}
static int get_frame_duration(const blender::bke::greasepencil::Layer &layer,
const int frame_number)
{
Span<int> sorted_keys = layer.sorted_keys();
const int *frame_number_it = std::lower_bound(
sorted_keys.begin(), sorted_keys.end(), frame_number);
if (std::next(frame_number_it) == sorted_keys.end()) {
return 0;
}
const int next_frame_number = *(std::next(frame_number_it));
return next_frame_number - frame_number;
}
bool GreasePencil::insert_duplicate_frame(blender::bke::greasepencil::Layer &layer,
const int src_frame_number,
const int dst_frame_number,
const bool do_instance)
{
using namespace blender::bke::greasepencil;
if (!layer.frames().contains(src_frame_number)) {
return false;
}
const GreasePencilFrame &src_frame = layer.frames().lookup(src_frame_number);
/* Create the new frame structure, with the same duration.
* If we want to make an instance of the source frame, the drawing index gets copied from the
* source frame. Otherwise, we set the drawing index to the size of the drawings array, since we
* are going to add a new drawing copied from the source drawing. */
const int duration = src_frame.is_implicit_hold() ? 0 :
get_frame_duration(layer, src_frame_number);
const int drawing_index = do_instance ? src_frame.drawing_index : int(this->drawings().size());
GreasePencilFrame *dst_frame = layer.add_frame(dst_frame_number, drawing_index, duration);
if (dst_frame == nullptr) {
return false;
}
dst_frame->type = src_frame.type;
const GreasePencilDrawingBase *src_drawing_base = this->drawings(src_frame.drawing_index);
switch (src_drawing_base->type) {
case GP_DRAWING: {
const Drawing &src_drawing =
reinterpret_cast<const GreasePencilDrawing *>(src_drawing_base)->wrap();
if (do_instance) {
/* Adds the duplicate frame as a new instance of the same drawing. We thus increase the
* user count of the corresponding drawing. */
src_drawing.add_user();
}
else {
/* Create a copy of the drawing, and add it at the end of the drawings array.
* Note that the frame already points to this new drawing, as the drawing index was set to
* `int(this->drawings().size())`. */
this->add_duplicate_drawings(1, src_drawing);
}
break;
}
case GP_DRAWING_REFERENCE:
/* TODO: Duplicate drawing references is not yet implemented.
* For now, just remove the frame that we inserted. */
layer.remove_frame(dst_frame_number);
return false;
}
return true;
}
void GreasePencil::remove_frame_at(blender::bke::greasepencil::Layer &layer,
const int frame_number)
{
using namespace blender::bke::greasepencil;
if (!layer.frames().contains(frame_number)) {
return;
}
const GreasePencilFrame &frame_to_remove = layer.frames().lookup(frame_number);
const int drawing_index_to_remove = frame_to_remove.drawing_index;
if (!layer.remove_frame(frame_number)) {
/* If removing the frame was not successful, return early. */
return;
}
GreasePencilDrawingBase *drawing_base = this->drawings(drawing_index_to_remove);
if (drawing_base->type != GP_DRAWING) {
/* If the drawing is referenced from another object, we don't track it's users because we
* cannot delete drawings from another object. Return early. */
return;
}
Drawing &drawing = reinterpret_cast<GreasePencilDrawing *>(drawing_base)->wrap();
drawing.remove_user();
if (!drawing.has_users()) {
this->remove_drawing(drawing_index_to_remove);
}
}
void GreasePencil::remove_drawing(const int index_to_remove)
{
using namespace blender::bke::greasepencil;
@ -1849,8 +1996,8 @@ static void read_layer(BlendDataReader *reader,
/* Re-create frames data in runtime map. */
node->wrap().runtime = MEM_new<blender::bke::greasepencil::LayerRuntime>(__func__);
for (int i = 0; i < node->frames_storage.num; i++) {
node->wrap().frames_for_write().add(node->frames_storage.keys[i],
node->frames_storage.values[i]);
node->wrap().frames_for_write().add_new(node->frames_storage.keys[i],
node->frames_storage.values[i]);
}
/* Read layer masks. */

View File

@ -173,7 +173,7 @@ struct GreasePencilLayerFramesExample {
* Scene Frame: |0|1|2|3|4|5|6|7|8|9|0|1|2|3|4|5|6|...
* Drawing: [#0 ][#1 ] [#2 ]
*/
const int sorted_keys[5] = {0, 5, 10, 12, 16};
const FramesMapKey sorted_keys[5] = {0, 5, 10, 12, 16};
GreasePencilFrame sorted_values[5] = {{0}, {1}, {-1}, {2}, {-1}};
Layer layer;
@ -230,7 +230,7 @@ TEST(greasepencil, add_frame_duration_check_duration)
{
GreasePencilLayerFramesExample ex;
EXPECT_TRUE(ex.layer.add_frame(17, 3, 10));
Span<int> sorted_keys = ex.layer.sorted_keys();
Span<FramesMapKey> sorted_keys = ex.layer.sorted_keys();
EXPECT_EQ(sorted_keys.size(), 7);
EXPECT_EQ(sorted_keys[6] - sorted_keys[5], 10);
}
@ -247,11 +247,71 @@ TEST(greasepencil, add_frame_duration_override_null_frames)
EXPECT_EQ(layer.drawing_index_at(0), 1);
EXPECT_EQ(layer.drawing_index_at(1), 3);
EXPECT_EQ(layer.drawing_index_at(11), -1);
Span<int> sorted_keys = layer.sorted_keys();
Span<FramesMapKey> sorted_keys = layer.sorted_keys();
EXPECT_EQ(sorted_keys.size(), 3);
EXPECT_EQ(sorted_keys[0], 0);
EXPECT_EQ(sorted_keys[1], 1);
EXPECT_EQ(sorted_keys[2], 11);
}
TEST(greasepencil, remove_frame_single)
{
Layer layer;
layer.add_frame(0, 1);
layer.remove_frame(0);
EXPECT_EQ(layer.frames().size(), 0);
}
TEST(greasepencil, remove_frame_first)
{
Layer layer;
layer.add_frame(0, 1);
layer.add_frame(5, 2);
layer.remove_frame(0);
EXPECT_EQ(layer.frames().size(), 1);
EXPECT_EQ(layer.frames().lookup(5).drawing_index, 2);
}
TEST(greasepencil, remove_frame_last)
{
Layer layer;
layer.add_frame(0, 1);
layer.add_frame(5, 2);
layer.remove_frame(5);
EXPECT_EQ(layer.frames().size(), 1);
EXPECT_EQ(layer.frames().lookup(0).drawing_index, 1);
}
TEST(greasepencil, remove_frame_implicit_hold)
{
Layer layer;
layer.add_frame(0, 1, 4);
layer.add_frame(5, 2);
layer.remove_frame(5);
EXPECT_EQ(layer.frames().size(), 2);
EXPECT_EQ(layer.frames().lookup(0).drawing_index, 1);
EXPECT_TRUE(layer.frames().lookup(4).is_null());
}
TEST(greasepencil, remove_frame_fixed_duration_end)
{
Layer layer;
layer.add_frame(0, 1, 5);
layer.add_frame(5, 2);
layer.remove_frame(0);
EXPECT_EQ(layer.frames().size(), 1);
EXPECT_EQ(layer.frames().lookup(5).drawing_index, 2);
}
TEST(greasepencil, remove_frame_fixed_duration_overwrite_end)
{
Layer layer;
layer.add_frame(0, 1, 5);
layer.add_frame(5, 2);
layer.remove_frame(5);
EXPECT_EQ(layer.frames().size(), 2);
EXPECT_EQ(layer.frames().lookup(0).drawing_index, 1);
EXPECT_TRUE(layer.frames().lookup(5).is_null());
}
} // namespace blender::bke::greasepencil::tests

View File

@ -17,6 +17,7 @@
#include "DNA_object_types.h"
#include "BLI_alloca.h"
#include "BLI_array_utils.hh"
#include "BLI_bitmap.h"
#include "BLI_edgehash.h"
#include "BLI_index_range.hh"
@ -31,7 +32,9 @@
#include "BKE_multires.h"
using blender::float3;
using blender::int2;
using blender::MutableSpan;
using blender::OffsetIndices;
using blender::Span;
using blender::VArray;
@ -498,93 +501,41 @@ void BKE_mesh_mdisp_flip(MDisps *md, const bool use_loop_mdisp_flip)
}
}
void BKE_mesh_face_flip_ex(const int face_offset,
const int face_size,
int *corner_verts,
int *corner_edges,
CustomData *loop_data,
float (*lnors)[3],
MDisps *mdisp,
const bool use_loop_mdisp_flip)
{
int loopstart = face_offset;
int loopend = loopstart + face_size - 1;
const bool corner_verts_in_data =
(CustomData_get_layer_named(loop_data, CD_PROP_INT32, ".corner_vert") == corner_verts);
const bool corner_edges_in_data =
(CustomData_get_layer_named(loop_data, CD_PROP_INT32, ".corner_edge") == corner_edges);
if (mdisp) {
for (int i = loopstart; i <= loopend; i++) {
BKE_mesh_mdisp_flip(&mdisp[i], use_loop_mdisp_flip);
}
}
/* Note that we keep same start vertex for flipped face. */
/* We also have to update loops edge
* (they will get their original 'other edge', that is,
* the original edge of their original previous loop)... */
int prev_edge_index = corner_edges[loopstart];
corner_edges[loopstart] = corner_edges[loopend];
for (loopstart++; loopend > loopstart; loopstart++, loopend--) {
corner_edges[loopend] = corner_edges[loopend - 1];
std::swap(corner_edges[loopstart], prev_edge_index);
if (!corner_verts_in_data) {
std::swap(corner_verts[loopstart], corner_verts[loopend]);
}
if (!corner_edges_in_data) {
std::swap(corner_edges[loopstart], corner_edges[loopend]);
}
if (lnors) {
swap_v3_v3(lnors[loopstart], lnors[loopend]);
}
CustomData_swap(loop_data, loopstart, loopend);
}
/* Even if we did not swap the other 'pivot' loop, we need to set its swapped edge. */
if (loopstart == loopend) {
corner_edges[loopstart] = prev_edge_index;
}
}
void BKE_mesh_face_flip(const int face_offset,
const int face_size,
int *corner_verts,
int *corner_edges,
CustomData *loop_data,
const int totloop)
{
MDisps *mdisp = (MDisps *)CustomData_get_layer_for_write(loop_data, CD_MDISPS, totloop);
BKE_mesh_face_flip_ex(
face_offset, face_size, corner_verts, corner_edges, loop_data, nullptr, mdisp, true);
}
void BKE_mesh_faces_flip(const int *face_offsets,
int *corner_verts,
int *corner_edges,
CustomData *loop_data,
int faces_num)
{
const blender::OffsetIndices faces(blender::Span(face_offsets, faces_num + 1));
MDisps *mdisp = (MDisps *)CustomData_get_layer_for_write(loop_data, CD_MDISPS, faces_num);
for (const int i : faces.index_range()) {
BKE_mesh_face_flip_ex(faces[i].start(),
faces[i].size(),
corner_verts,
corner_edges,
loop_data,
nullptr,
mdisp,
true);
}
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Mesh Flag Flushing
/** \name Visibility Interpolation
* \{ */
/* Hide edges when either of their vertices are hidden. */
static void edge_hide_from_vert(const Span<int2> edges,
const Span<bool> hide_vert,
MutableSpan<bool> hide_edge)
{
using namespace blender;
threading::parallel_for(edges.index_range(), 4096, [&](const IndexRange range) {
for (const int i : range) {
hide_edge[i] = hide_vert[edges[i][0]] || hide_vert[edges[i][1]];
}
});
}
/* Hide faces when any of their vertices are hidden. */
static void face_hide_from_vert(const OffsetIndices<int> faces,
const Span<int> corner_verts,
const Span<bool> hide_vert,
MutableSpan<bool> hide_poly)
{
using namespace blender;
threading::parallel_for(faces.index_range(), 4096, [&](const IndexRange range) {
for (const int i : range) {
const Span<int> face_verts = corner_verts.slice(faces[i]);
hide_poly[i] = std::any_of(
face_verts.begin(), face_verts.end(), [&](const int vert) { return hide_vert[vert]; });
}
});
}
void BKE_mesh_flush_hidden_from_verts(Mesh *me)
{
using namespace blender;
@ -599,28 +550,16 @@ void BKE_mesh_flush_hidden_from_verts(Mesh *me)
return;
}
const VArraySpan<bool> hide_vert_span{hide_vert};
const Span<int2> edges = me->edges();
const OffsetIndices faces = me->faces();
const Span<int> corner_verts = me->corner_verts();
/* Hide edges when either of their vertices are hidden. */
SpanAttributeWriter<bool> hide_edge = attributes.lookup_or_add_for_write_only_span<bool>(
".hide_edge", ATTR_DOMAIN_EDGE);
for (const int i : edges.index_range()) {
const int2 &edge = edges[i];
hide_edge.span[i] = hide_vert_span[edge[0]] || hide_vert_span[edge[1]];
}
hide_edge.finish();
/* Hide faces when any of their vertices are hidden. */
SpanAttributeWriter<bool> hide_poly = attributes.lookup_or_add_for_write_only_span<bool>(
".hide_poly", ATTR_DOMAIN_FACE);
for (const int i : faces.index_range()) {
const Span<int> face_verts = corner_verts.slice(faces[i]);
hide_poly.span[i] = std::any_of(face_verts.begin(), face_verts.end(), [&](const int vert) {
return hide_vert_span[vert];
});
}
edge_hide_from_vert(me->edges(), hide_vert_span, hide_edge.span);
face_hide_from_vert(me->faces(), me->corner_verts(), hide_vert_span, hide_poly.span);
hide_edge.finish();
hide_poly.finish();
}
@ -647,30 +586,37 @@ void BKE_mesh_flush_hidden_from_faces(Mesh *me)
".hide_edge", ATTR_DOMAIN_EDGE);
/* Hide all edges or vertices connected to hidden polygons. */
for (const int i : faces.index_range()) {
if (hide_poly_span[i]) {
for (const int corner : faces[i]) {
hide_vert.span[corner_verts[corner]] = true;
hide_edge.span[corner_edges[corner]] = true;
threading::parallel_for(faces.index_range(), 1024, [&](const IndexRange range) {
for (const int i : range) {
if (hide_poly_span[i]) {
hide_vert.span.fill_indices(corner_verts.slice(faces[i]), true);
hide_edge.span.fill_indices(corner_edges.slice(faces[i]), true);
}
}
}
});
/* Unhide vertices and edges connected to visible polygons. */
for (const int i : faces.index_range()) {
if (!hide_poly_span[i]) {
for (const int corner : faces[i]) {
hide_vert.span[corner_verts[corner]] = false;
hide_edge.span[corner_edges[corner]] = false;
threading::parallel_for(faces.index_range(), 1024, [&](const IndexRange range) {
for (const int i : range) {
if (!hide_poly_span[i]) {
hide_vert.span.fill_indices(corner_verts.slice(faces[i]), false);
hide_edge.span.fill_indices(corner_edges.slice(faces[i]), false);
}
}
}
});
hide_vert.finish();
hide_edge.finish();
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Selection Interpolation
* \{ */
void BKE_mesh_flush_select_from_faces(Mesh *me)
{
using namespace blender;
using namespace blender::bke;
MutableAttributeAccessor attributes = me->attributes_for_write();
const VArray<bool> select_poly = *attributes.lookup_or_default<bool>(
@ -687,44 +633,18 @@ void BKE_mesh_flush_select_from_faces(Mesh *me)
/* Use generic domain interpolation to read the face attribute on the other domains.
* Assume selected faces are not hidden and none of their vertices/edges are hidden. */
attributes.lookup_or_default<bool>(".select_poly", ATTR_DOMAIN_POINT, false)
.varray.materialize(select_vert.span);
attributes.lookup_or_default<bool>(".select_poly", ATTR_DOMAIN_EDGE, false)
.varray.materialize(select_edge.span);
array_utils::copy(*attributes.lookup_or_default<bool>(".select_poly", ATTR_DOMAIN_POINT, false),
select_vert.span);
array_utils::copy(*attributes.lookup_or_default<bool>(".select_poly", ATTR_DOMAIN_EDGE, false),
select_edge.span);
select_vert.finish();
select_edge.finish();
}
static void mesh_flush_select_from_verts(const Span<blender::int2> edges,
const blender::OffsetIndices<int> faces,
const Span<int> corner_verts,
const VArray<bool> &hide_edge,
const VArray<bool> &hide_poly,
const VArray<bool> &select_vert,
MutableSpan<bool> select_edge,
MutableSpan<bool> select_poly)
{
/* Select visible edges that have both of their vertices selected. */
for (const int i : edges.index_range()) {
if (!hide_edge[i]) {
const blender::int2 &edge = edges[i];
select_edge[i] = select_vert[edge[0]] && select_vert[edge[1]];
}
}
/* Select visible faces that have all of their vertices selected. */
for (const int i : faces.index_range()) {
if (!hide_poly[i]) {
const Span<int> face_verts = corner_verts.slice(faces[i]);
select_poly[i] = std::all_of(
face_verts.begin(), face_verts.end(), [&](const int vert) { return select_vert[vert]; });
}
}
}
void BKE_mesh_flush_select_from_verts(Mesh *me)
{
using namespace blender;
using namespace blender::bke;
MutableAttributeAccessor attributes = me->attributes_for_write();
const VArray<bool> select_vert = *attributes.lookup_or_default<bool>(
@ -738,15 +658,24 @@ void BKE_mesh_flush_select_from_verts(Mesh *me)
".select_edge", ATTR_DOMAIN_EDGE);
SpanAttributeWriter<bool> select_poly = attributes.lookup_or_add_for_write_only_span<bool>(
".select_poly", ATTR_DOMAIN_FACE);
mesh_flush_select_from_verts(
me->edges(),
me->faces(),
me->corner_verts(),
*attributes.lookup_or_default<bool>(".hide_edge", ATTR_DOMAIN_EDGE, false),
*attributes.lookup_or_default<bool>(".hide_poly", ATTR_DOMAIN_FACE, false),
select_vert,
select_edge.span,
select_poly.span);
{
IndexMaskMemory memory;
const VArray<bool> hide_edge = *attributes.lookup_or_default<bool>(
".hide_edge", ATTR_DOMAIN_EDGE, false);
array_utils::copy(
*attributes.lookup_or_default<bool>(".select_vert", ATTR_DOMAIN_EDGE, false),
IndexMask::from_bools(hide_edge, memory).complement(hide_edge.index_range(), memory),
select_edge.span);
}
{
IndexMaskMemory memory;
const VArray<bool> hide_poly = *attributes.lookup_or_default<bool>(
".hide_poly", ATTR_DOMAIN_FACE, false);
array_utils::copy(
*attributes.lookup_or_default<bool>(".select_vert", ATTR_DOMAIN_FACE, false),
IndexMask::from_bools(hide_poly, memory).complement(hide_poly.index_range(), memory),
select_poly.span);
}
select_edge.finish();
select_poly.finish();
}

View File

@ -0,0 +1,99 @@
/* SPDX-FileCopyrightText: 2023 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "DNA_mesh_types.h"
#include "BLI_task.hh"
#include "BKE_attribute.hh"
#include "BKE_attribute_math.hh"
#include "BKE_mesh.hh"
namespace blender::bke {
template<typename T>
static void flip_corner_data(const OffsetIndices<int> faces,
const IndexMask &face_selection,
MutableSpan<T> data)
{
face_selection.foreach_index(GrainSize(1024),
[&](const int i) { data.slice(faces[i].drop_front(1)).reverse(); });
}
template<typename T>
static void flip_custom_data_type(const OffsetIndices<int> faces,
CustomData &loop_data,
const IndexMask &face_selection,
const eCustomDataType data_type)
{
BLI_assert(sizeof(T) == CustomData_sizeof(data_type));
for (const int i : IndexRange(CustomData_number_of_layers(&loop_data, data_type))) {
T *data = static_cast<T *>(
CustomData_get_layer_n_for_write(&loop_data, data_type, i, faces.total_size()));
flip_corner_data(faces, face_selection, MutableSpan(data, faces.total_size()));
}
}
void mesh_flip_faces(Mesh &mesh, const IndexMask &selection)
{
if (mesh.faces_num == 0 || selection.is_empty()) {
return;
}
const OffsetIndices faces = mesh.faces();
MutableSpan<int> corner_verts = mesh.corner_verts_for_write();
MutableSpan<int> corner_edges = mesh.corner_edges_for_write();
selection.foreach_index(GrainSize(1024), [&](const int i) {
const IndexRange face = faces[i];
for (const int j : IndexRange(face.size() / 2)) {
const int a = face[j + 1];
const int b = face.last(j);
std::swap(corner_verts[a], corner_verts[b]);
std::swap(corner_edges[a - 1], corner_edges[b]);
}
});
flip_custom_data_type<float4x4>(faces, mesh.loop_data, selection, CD_TANGENT);
flip_custom_data_type<float4>(faces, mesh.loop_data, selection, CD_MLOOPTANGENT);
flip_custom_data_type<short2>(faces, mesh.loop_data, selection, CD_CUSTOMLOOPNORMAL);
flip_custom_data_type<float>(faces, mesh.loop_data, selection, CD_PAINT_MASK);
flip_custom_data_type<GridPaintMask>(faces, mesh.loop_data, selection, CD_GRID_PAINT_MASK);
flip_custom_data_type<OrigSpaceLoop>(faces, mesh.loop_data, selection, CD_ORIGSPACE_MLOOP);
flip_custom_data_type<MDisps>(faces, mesh.loop_data, selection, CD_MDISPS);
if (MDisps *mdisp = static_cast<MDisps *>(
CustomData_get_layer_for_write(&mesh.loop_data, CD_MDISPS, mesh.totloop)))
{
selection.foreach_index(GrainSize(512), [&](const int i) {
for (const int corner : faces[i]) {
BKE_mesh_mdisp_flip(&mdisp[corner], true);
}
});
}
bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
attributes.for_all(
[&](const bke::AttributeIDRef &attribute_id, const bke::AttributeMetaData &meta_data) {
if (meta_data.data_type == CD_PROP_STRING) {
return true;
}
if (meta_data.domain != ATTR_DOMAIN_CORNER) {
return true;
}
if (ELEM(attribute_id.name(), ".corner_vert", ".corner_edge")) {
return true;
}
bke::GSpanAttributeWriter attribute = attributes.lookup_for_write_span(attribute_id);
bke::attribute_math::convert_to_static_type(meta_data.data_type, [&](auto dummy) {
using T = decltype(dummy);
flip_corner_data(faces, selection, attribute.span.typed<T>());
});
attribute.finish();
return true;
});
BKE_mesh_tag_face_winding_changed(&mesh);
}
} // namespace blender::bke

View File

@ -1304,18 +1304,6 @@ static bool update_search_cb(PBVHNode *node, void *data_v)
return true;
}
struct PBVHUpdateData {
PBVH *pbvh;
Span<PBVHNode *> nodes;
int flag = 0;
bool show_sculpt_face_sets = false;
PBVHAttrReq *attrs = nullptr;
int attrs_num = 0;
PBVHUpdateData(PBVH *pbvh_, Span<PBVHNode *> nodes_) : pbvh(pbvh_), nodes(nodes_) {}
};
static void pbvh_faces_update_normals(PBVH *pbvh, Span<PBVHNode *> nodes)
{
using namespace blender;
@ -1377,124 +1365,81 @@ static void pbvh_faces_update_normals(PBVH *pbvh, Span<PBVHNode *> nodes)
});
}
static void pbvh_update_mask_redraw_task_cb(void *__restrict userdata,
const int n,
const TaskParallelTLS *__restrict /*tls*/)
static void node_update_mask_redraw(PBVH &pbvh, PBVHNode &node)
{
if (!(node.flag & PBVH_UpdateMask)) {
return;
}
node.flag &= ~PBVH_UpdateMask;
PBVHUpdateData *data = static_cast<PBVHUpdateData *>(userdata);
PBVH *pbvh = data->pbvh;
PBVHNode *node = data->nodes[n];
if (node->flag & PBVH_UpdateMask) {
bool has_unmasked = false;
bool has_masked = true;
if (node.flag & PBVH_Leaf) {
PBVHVertexIter vd;
bool has_unmasked = false;
bool has_masked = true;
if (node->flag & PBVH_Leaf) {
PBVHVertexIter vd;
BKE_pbvh_vertex_iter_begin (pbvh, node, vd, PBVH_ITER_ALL) {
if (vd.mask && *vd.mask < 1.0f) {
has_unmasked = true;
}
if (vd.mask && *vd.mask > 0.0f) {
has_masked = false;
}
BKE_pbvh_vertex_iter_begin (&pbvh, &node, vd, PBVH_ITER_ALL) {
if (vd.mask && *vd.mask < 1.0f) {
has_unmasked = true;
}
if (vd.mask && *vd.mask > 0.0f) {
has_masked = false;
}
BKE_pbvh_vertex_iter_end;
}
else {
has_unmasked = true;
has_masked = true;
}
BKE_pbvh_node_fully_masked_set(node, !has_unmasked);
BKE_pbvh_node_fully_unmasked_set(node, has_masked);
BKE_pbvh_vertex_iter_end;
}
else {
has_unmasked = true;
has_masked = true;
}
BKE_pbvh_node_fully_masked_set(&node, !has_unmasked);
BKE_pbvh_node_fully_unmasked_set(&node, has_masked);
}
node->flag &= ~PBVH_UpdateMask;
static void node_update_visibility_redraw(PBVH &pbvh, PBVHNode &node)
{
if (!(node.flag & PBVH_UpdateVisibility)) {
return;
}
node.flag &= ~PBVH_UpdateVisibility;
BKE_pbvh_node_fully_hidden_set(&node, true);
if (node.flag & PBVH_Leaf) {
PBVHVertexIter vd;
BKE_pbvh_vertex_iter_begin (&pbvh, &node, vd, PBVH_ITER_ALL) {
if (vd.visible) {
BKE_pbvh_node_fully_hidden_set(&node, false);
return;
}
}
BKE_pbvh_vertex_iter_end;
}
}
static void pbvh_update_mask_redraw(PBVH *pbvh, Span<PBVHNode *> nodes, int flag)
static void node_update_bounds(PBVH &pbvh, PBVHNode &node, const PBVHNodeFlags flag)
{
PBVHUpdateData data(pbvh, nodes);
data.pbvh = pbvh;
data.nodes = nodes;
data.flag = flag;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
BLI_task_parallel_range(0, nodes.size(), &data, pbvh_update_mask_redraw_task_cb, &settings);
}
static void pbvh_update_visibility_redraw_task_cb(void *__restrict userdata,
const int n,
const TaskParallelTLS *__restrict /*tls*/)
{
PBVHUpdateData *data = static_cast<PBVHUpdateData *>(userdata);
PBVH *pbvh = data->pbvh;
PBVHNode *node = data->nodes[n];
if (node->flag & PBVH_UpdateVisibility) {
node->flag &= ~PBVH_UpdateVisibility;
BKE_pbvh_node_fully_hidden_set(node, true);
if (node->flag & PBVH_Leaf) {
PBVHVertexIter vd;
BKE_pbvh_vertex_iter_begin (pbvh, node, vd, PBVH_ITER_ALL) {
if (vd.visible) {
BKE_pbvh_node_fully_hidden_set(node, false);
return;
}
}
BKE_pbvh_vertex_iter_end;
}
}
}
static void pbvh_update_visibility_redraw(PBVH *pbvh, Span<PBVHNode *> nodes, int flag)
{
PBVHUpdateData data(pbvh, nodes);
data.pbvh = pbvh;
data.nodes = nodes;
data.flag = flag;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
BLI_task_parallel_range(
0, nodes.size(), &data, pbvh_update_visibility_redraw_task_cb, &settings);
}
static void pbvh_update_BB_redraw_task_cb(void *__restrict userdata,
const int n,
const TaskParallelTLS *__restrict /*tls*/)
{
PBVHUpdateData *data = static_cast<PBVHUpdateData *>(userdata);
PBVH *pbvh = data->pbvh;
PBVHNode *node = data->nodes[n];
const int flag = data->flag;
if ((flag & PBVH_UpdateBB) && (node->flag & PBVH_UpdateBB)) {
if ((flag & PBVH_UpdateBB) && (node.flag & PBVH_UpdateBB)) {
/* don't clear flag yet, leave it for flushing later */
/* Note that bvh usage is read-only here, so no need to thread-protect it. */
update_node_vb(pbvh, node);
update_node_vb(&pbvh, &node);
}
if ((flag & PBVH_UpdateOriginalBB) && (node->flag & PBVH_UpdateOriginalBB)) {
node->orig_vb = node->vb;
if ((flag & PBVH_UpdateOriginalBB) && (node.flag & PBVH_UpdateOriginalBB)) {
node.orig_vb = node.vb;
}
if ((flag & PBVH_UpdateRedraw) && (node->flag & PBVH_UpdateRedraw)) {
node->flag &= ~PBVH_UpdateRedraw;
if ((flag & PBVH_UpdateRedraw) && (node.flag & PBVH_UpdateRedraw)) {
node.flag &= ~PBVH_UpdateRedraw;
}
}
static void pbvh_update_BB_redraw(PBVH *pbvh, Span<PBVHNode *> nodes, int flag)
{
/* update BB, redraw flag */
PBVHUpdateData data(pbvh, nodes);
data.flag = flag;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
BLI_task_parallel_range(0, nodes.size(), &data, pbvh_update_BB_redraw_task_cb, &settings);
using namespace blender;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
for (PBVHNode *node : nodes.slice(range)) {
node_update_bounds(*pbvh, *node, PBVHNodeFlags(flag));
}
});
}
bool BKE_pbvh_get_color_layer(Mesh *me, CustomDataLayer **r_layer, eAttrDomain *r_domain)
@ -1505,32 +1450,24 @@ bool BKE_pbvh_get_color_layer(Mesh *me, CustomDataLayer **r_layer, eAttrDomain *
return *r_layer != nullptr;
}
static void pbvh_update_draw_buffer_cb(void *__restrict userdata,
const int n,
const TaskParallelTLS *__restrict /*tls*/)
static void node_update_draw_buffers(PBVH &pbvh, PBVHNode &node)
{
/* Create and update draw buffers. The functions called here must not
* do any OpenGL calls. Flags are not cleared immediately, that happens
* after GPU_pbvh_buffer_flush() which does the final OpenGL calls. */
PBVHUpdateData *data = static_cast<PBVHUpdateData *>(userdata);
PBVH *pbvh = data->pbvh;
PBVHNode *node = data->nodes[n];
if (node->flag & PBVH_RebuildDrawBuffers) {
if (node.flag & PBVH_RebuildDrawBuffers) {
PBVH_GPU_Args args;
pbvh_draw_args_init(pbvh, &args, node);
node->draw_batches = DRW_pbvh_node_create(args);
pbvh_draw_args_init(&pbvh, &args, &node);
node.draw_batches = DRW_pbvh_node_create(args);
}
if (node->flag & PBVH_UpdateDrawBuffers) {
node->debug_draw_gen++;
if (node.flag & PBVH_UpdateDrawBuffers) {
node.debug_draw_gen++;
if (node->draw_batches) {
if (node.draw_batches) {
PBVH_GPU_Args args;
pbvh_draw_args_init(pbvh, &args, node);
DRW_pbvh_node_update(node->draw_batches, args);
pbvh_draw_args_init(&pbvh, &args, &node);
DRW_pbvh_node_update(node.draw_batches, args);
}
}
}
@ -1545,25 +1482,11 @@ void pbvh_free_draw_buffers(PBVH * /*pbvh*/, PBVHNode *node)
static void pbvh_update_draw_buffers(PBVH *pbvh, Span<PBVHNode *> nodes, int update_flag)
{
const CustomData *vdata;
switch (pbvh->header.type) {
case PBVH_BMESH:
if (!pbvh->header.bm) {
/* BMesh hasn't been created yet */
return;
}
vdata = &pbvh->header.bm->vdata;
break;
case PBVH_FACES:
vdata = pbvh->vert_data;
break;
case PBVH_GRIDS:
vdata = nullptr;
break;
using namespace blender;
if (pbvh->header.type == PBVH_BMESH && !pbvh->header.bm) {
/* BMesh hasn't been created yet */
return;
}
UNUSED_VARS(vdata);
if ((update_flag & PBVH_RebuildDrawBuffers) || ELEM(pbvh->header.type, PBVH_GRIDS, PBVH_BMESH)) {
/* Free buffers uses OpenGL, so not in parallel. */
@ -1581,15 +1504,16 @@ static void pbvh_update_draw_buffers(PBVH *pbvh, Span<PBVHNode *> nodes, int upd
}
/* Parallel creation and update of draw buffers. */
PBVHUpdateData data(pbvh, nodes);
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
BLI_task_parallel_range(0, nodes.size(), &data, pbvh_update_draw_buffer_cb, &settings);
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
for (PBVHNode *node : nodes.slice(range)) {
node_update_draw_buffers(*pbvh, *node);
}
});
/* Flush buffers uses OpenGL, so not in parallel. */
for (PBVHNode *node : nodes) {
if (node->flag & PBVH_UpdateDrawBuffers) {
/* Flush buffers uses OpenGL, so not in parallel. */
if (node->draw_batches) {
DRW_pbvh_node_gpu_flush(node->draw_batches);
@ -1652,6 +1576,7 @@ void BKE_pbvh_update_bounds(PBVH *pbvh, int flag)
void BKE_pbvh_update_vertex_data(PBVH *pbvh, int flag)
{
using namespace blender;
if (pbvh->nodes.is_empty()) {
return;
}
@ -1660,7 +1585,11 @@ void BKE_pbvh_update_vertex_data(PBVH *pbvh, int flag)
pbvh, update_search_cb, POINTER_FROM_INT(flag));
if (flag & (PBVH_UpdateMask)) {
pbvh_update_mask_redraw(pbvh, nodes, flag);
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
for (PBVHNode *node : nodes.as_span().slice(range)) {
node_update_mask_redraw(*pbvh, *node);
}
});
}
if (flag & (PBVH_UpdateColor)) {
@ -1670,22 +1599,22 @@ void BKE_pbvh_update_vertex_data(PBVH *pbvh, int flag)
}
if (flag & (PBVH_UpdateVisibility)) {
pbvh_update_visibility_redraw(pbvh, nodes, flag);
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
for (PBVHNode *node : nodes.as_span().slice(range)) {
node_update_visibility_redraw(*pbvh, *node);
}
});
}
}
static void pbvh_faces_node_visibility_update(PBVH *pbvh, PBVHNode *node)
{
int totvert, i;
BKE_pbvh_node_num_verts(pbvh, node, nullptr, &totvert);
const int *vert_indices = BKE_pbvh_node_get_vert_indices(node);
if (pbvh->hide_vert == nullptr) {
BKE_pbvh_node_fully_hidden_set(node, false);
return;
}
for (i = 0; i < totvert; i++) {
if (!(pbvh->hide_vert[vert_indices[i]])) {
for (const int vert : node->vert_indices) {
if (!(pbvh->hide_vert[vert])) {
BKE_pbvh_node_fully_hidden_set(node, false);
return;
}
@ -1754,42 +1683,28 @@ static void pbvh_bmesh_node_visibility_update(PBVHNode *node)
BKE_pbvh_node_fully_hidden_set(node, true);
}
static void pbvh_update_visibility_task_cb(void *__restrict userdata,
const int n,
const TaskParallelTLS *__restrict /*tls*/)
static void node_update_visibility(PBVH &pbvh, PBVHNode &node)
{
PBVHUpdateData *data = static_cast<PBVHUpdateData *>(userdata);
PBVH *pbvh = data->pbvh;
PBVHNode *node = data->nodes[n];
if (node->flag & PBVH_UpdateVisibility) {
switch (BKE_pbvh_type(pbvh)) {
case PBVH_FACES:
pbvh_faces_node_visibility_update(pbvh, node);
break;
case PBVH_GRIDS:
pbvh_grids_node_visibility_update(pbvh, node);
break;
case PBVH_BMESH:
pbvh_bmesh_node_visibility_update(node);
break;
}
node->flag &= ~PBVH_UpdateVisibility;
if (!(node.flag & PBVH_UpdateVisibility)) {
return;
}
node.flag &= ~PBVH_UpdateVisibility;
switch (BKE_pbvh_type(&pbvh)) {
case PBVH_FACES:
pbvh_faces_node_visibility_update(&pbvh, &node);
break;
case PBVH_GRIDS:
pbvh_grids_node_visibility_update(&pbvh, &node);
break;
case PBVH_BMESH:
pbvh_bmesh_node_visibility_update(&node);
break;
}
}
static void pbvh_update_visibility(PBVH *pbvh, Span<PBVHNode *> nodes)
{
PBVHUpdateData data(pbvh, nodes);
data.pbvh = pbvh;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, nodes.size());
BLI_task_parallel_range(0, nodes.size(), &data, pbvh_update_visibility_task_cb, &settings);
}
void BKE_pbvh_update_visibility(PBVH *pbvh)
{
using namespace blender;
if (pbvh->nodes.is_empty()) {
return;
}
@ -1797,7 +1712,11 @@ void BKE_pbvh_update_visibility(PBVH *pbvh)
Vector<PBVHNode *> nodes = blender::bke::pbvh::search_gather(
pbvh, update_search_cb, POINTER_FROM_INT(PBVH_UpdateVisibility));
pbvh_update_visibility(pbvh, nodes);
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
for (PBVHNode *node : nodes.as_span().slice(range)) {
node_update_visibility(*pbvh, *node);
}
});
}
void BKE_pbvh_redraw_BB(PBVH *pbvh, float bb_min[3], float bb_max[3])
@ -2590,86 +2509,87 @@ bool BKE_pbvh_node_raycast(PBVH *pbvh,
void BKE_pbvh_clip_ray_ortho(
PBVH *pbvh, bool original, float ray_start[3], float ray_end[3], float ray_normal[3])
{
if (!pbvh->nodes.is_empty()) {
float rootmin_start, rootmin_end;
float bb_min_root[3], bb_max_root[3], bb_center[3], bb_diff[3];
IsectRayAABB_Precalc ray;
float ray_normal_inv[3];
float offset = 1.0f + 1e-3f;
const float offset_vec[3] = {1e-3f, 1e-3f, 1e-3f};
if (original) {
BKE_pbvh_node_get_original_BB(&pbvh->nodes.first(), bb_min_root, bb_max_root);
}
else {
BKE_pbvh_node_get_BB(&pbvh->nodes.first(), bb_min_root, bb_max_root);
}
/* Calc rough clipping to avoid overflow later. See #109555. */
float mat[3][3];
axis_dominant_v3_to_m3(mat, ray_normal);
float a[3], b[3], min[3] = {FLT_MAX, FLT_MAX, FLT_MAX}, max[3] = {FLT_MIN, FLT_MIN, FLT_MIN};
/* Compute AABB bounds rotated along ray_normal.*/
copy_v3_v3(a, bb_min_root);
copy_v3_v3(b, bb_max_root);
mul_m3_v3(mat, a);
mul_m3_v3(mat, b);
minmax_v3v3_v3(min, max, a);
minmax_v3v3_v3(min, max, b);
float cent[3];
/* Find midpoint of aabb on ray. */
mid_v3_v3v3(cent, bb_min_root, bb_max_root);
float t = line_point_factor_v3(cent, ray_start, ray_end);
interp_v3_v3v3(cent, ray_start, ray_end, t);
/* Compute rough interval. */
float dist = max[2] - min[2];
madd_v3_v3v3fl(ray_start, cent, ray_normal, -dist);
madd_v3_v3v3fl(ray_end, cent, ray_normal, dist);
/* Slightly offset min and max in case we have a zero width node
* (due to a plane mesh for instance), or faces very close to the bounding box boundary. */
mid_v3_v3v3(bb_center, bb_max_root, bb_min_root);
/* Diff should be same for both min/max since it's calculated from center. */
sub_v3_v3v3(bb_diff, bb_max_root, bb_center);
/* Handles case of zero width bb. */
add_v3_v3(bb_diff, offset_vec);
madd_v3_v3v3fl(bb_max_root, bb_center, bb_diff, offset);
madd_v3_v3v3fl(bb_min_root, bb_center, bb_diff, -offset);
/* Final projection of start ray. */
isect_ray_aabb_v3_precalc(&ray, ray_start, ray_normal);
if (!isect_ray_aabb_v3(&ray, bb_min_root, bb_max_root, &rootmin_start)) {
return;
}
/* Final projection of end ray. */
mul_v3_v3fl(ray_normal_inv, ray_normal, -1.0);
isect_ray_aabb_v3_precalc(&ray, ray_end, ray_normal_inv);
/* Unlikely to fail exiting if entering succeeded, still keep this here. */
if (!isect_ray_aabb_v3(&ray, bb_min_root, bb_max_root, &rootmin_end)) {
return;
}
/*
* As a last-ditch effort to correct floating point overflow compute
* and add an epsilon if rootmin_start == rootmin_end.
*/
float epsilon = (std::nextafter(rootmin_start, rootmin_start + 1000.0f) - rootmin_start) *
5000.0f;
if (rootmin_start == rootmin_end) {
rootmin_start -= epsilon;
rootmin_end += epsilon;
}
madd_v3_v3v3fl(ray_start, ray_start, ray_normal, rootmin_start);
madd_v3_v3v3fl(ray_end, ray_end, ray_normal_inv, rootmin_end);
if (pbvh->nodes.is_empty()) {
return;
}
float rootmin_start, rootmin_end;
float bb_min_root[3], bb_max_root[3], bb_center[3], bb_diff[3];
IsectRayAABB_Precalc ray;
float ray_normal_inv[3];
float offset = 1.0f + 1e-3f;
const float offset_vec[3] = {1e-3f, 1e-3f, 1e-3f};
if (original) {
BKE_pbvh_node_get_original_BB(&pbvh->nodes.first(), bb_min_root, bb_max_root);
}
else {
BKE_pbvh_node_get_BB(&pbvh->nodes.first(), bb_min_root, bb_max_root);
}
/* Calc rough clipping to avoid overflow later. See #109555. */
float mat[3][3];
axis_dominant_v3_to_m3(mat, ray_normal);
float a[3], b[3], min[3] = {FLT_MAX, FLT_MAX, FLT_MAX}, max[3] = {FLT_MIN, FLT_MIN, FLT_MIN};
/* Compute AABB bounds rotated along ray_normal.*/
copy_v3_v3(a, bb_min_root);
copy_v3_v3(b, bb_max_root);
mul_m3_v3(mat, a);
mul_m3_v3(mat, b);
minmax_v3v3_v3(min, max, a);
minmax_v3v3_v3(min, max, b);
float cent[3];
/* Find midpoint of aabb on ray. */
mid_v3_v3v3(cent, bb_min_root, bb_max_root);
float t = line_point_factor_v3(cent, ray_start, ray_end);
interp_v3_v3v3(cent, ray_start, ray_end, t);
/* Compute rough interval. */
float dist = max[2] - min[2];
madd_v3_v3v3fl(ray_start, cent, ray_normal, -dist);
madd_v3_v3v3fl(ray_end, cent, ray_normal, dist);
/* Slightly offset min and max in case we have a zero width node
* (due to a plane mesh for instance), or faces very close to the bounding box boundary. */
mid_v3_v3v3(bb_center, bb_max_root, bb_min_root);
/* Diff should be same for both min/max since it's calculated from center. */
sub_v3_v3v3(bb_diff, bb_max_root, bb_center);
/* Handles case of zero width bb. */
add_v3_v3(bb_diff, offset_vec);
madd_v3_v3v3fl(bb_max_root, bb_center, bb_diff, offset);
madd_v3_v3v3fl(bb_min_root, bb_center, bb_diff, -offset);
/* Final projection of start ray. */
isect_ray_aabb_v3_precalc(&ray, ray_start, ray_normal);
if (!isect_ray_aabb_v3(&ray, bb_min_root, bb_max_root, &rootmin_start)) {
return;
}
/* Final projection of end ray. */
mul_v3_v3fl(ray_normal_inv, ray_normal, -1.0);
isect_ray_aabb_v3_precalc(&ray, ray_end, ray_normal_inv);
/* Unlikely to fail exiting if entering succeeded, still keep this here. */
if (!isect_ray_aabb_v3(&ray, bb_min_root, bb_max_root, &rootmin_end)) {
return;
}
/*
* As a last-ditch effort to correct floating point overflow compute
* and add an epsilon if rootmin_start == rootmin_end.
*/
float epsilon = (std::nextafter(rootmin_start, rootmin_start + 1000.0f) - rootmin_start) *
5000.0f;
if (rootmin_start == rootmin_end) {
rootmin_start -= epsilon;
rootmin_end += epsilon;
}
madd_v3_v3v3fl(ray_start, ray_start, ray_normal, rootmin_start);
madd_v3_v3v3fl(ray_end, ray_end, ray_normal_inv, rootmin_end);
}
/* -------------------------------------------------------------------- */
@ -3208,7 +3128,6 @@ void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int m
BKE_pbvh_node_get_grids(pbvh, node, &grid_indices, &totgrid, nullptr, &gridsize, &grids);
BKE_pbvh_node_num_verts(pbvh, node, &uniq_verts, &totvert);
const int *vert_indices = BKE_pbvh_node_get_vert_indices(node);
vi->key = pbvh->gridkey;
vi->grids = grids;
@ -3222,7 +3141,7 @@ void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int m
else {
vi->totvert = uniq_verts;
}
vi->vert_indices = vert_indices;
vi->vert_indices = node->vert_indices.data();
vi->vert_positions = pbvh->vert_positions;
vi->is_mesh = !pbvh->vert_positions.is_empty();

View File

@ -3063,18 +3063,13 @@ void BKE_scene_disable_color_management(Scene *scene)
STRNCPY(display_settings->display_device, none_display_name);
view = IMB_colormanagement_view_get_default_name(display_settings->display_device);
view = IMB_colormanagement_view_get_raw_or_default_name(display_settings->display_device);
if (view) {
STRNCPY(view_settings->view_transform, view);
}
}
bool BKE_scene_check_color_management_enabled(const Scene *scene)
{
return !STREQ(scene->display_settings.display_device, "None");
}
bool BKE_scene_check_rigidbody_active(const Scene *scene)
{
return scene && scene->rigidbody_world && scene->rigidbody_world->group &&

View File

@ -1890,7 +1890,7 @@ static void update_mapping_node_fcurve_rna_path_callback(ID * /* id */,
* in the node. To correct this, a Vector Minimum and/or a Vector Maximum
* nodes are added if needed.
*
* Finally, the TexMapping struct is freed and node->storage is set to NULL.
* Finally, the #TexMapping struct is freed and `node->storage` is set to null.
*
* Since the RNA paths of the properties changed, we also have to update the
* rna_path of the FCurves if they exist. To do that, we loop over FCurves
@ -1903,7 +1903,7 @@ static void update_mapping_node_inputs_and_properties(bNodeTree *ntree)
bool need_update = false;
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
/* If node->storage is NULL, then conversion has already taken place.
/* If `node->storage` is null, then conversion has already taken place.
* This can happen if a file with the new mapping node [saved from (2, 81, 8) or newer]
* is opened in a blender version prior to (2, 81, 8) and saved from there again. */
if (node->type == SH_NODE_MAPPING && node->storage) {

View File

@ -37,6 +37,7 @@
#include "BKE_mesh_legacy_convert.h"
#include "BKE_node.hh"
#include "BKE_node_runtime.hh"
#include "BKE_scene.h"
#include "BKE_tracking.h"
#include "BLO_readfile.h"
@ -507,6 +508,21 @@ void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain)
}
}
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 13)) {
/* For the scenes configured to use the "None" display disable the color management
* again. This will handle situation when the "None" display is removed and is replaced with
* a "Raw" view instead.
*
* Note that this versioning will do nothing if the "None" display exists in the OCIO
* configuration. */
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
const ColorManagedDisplaySettings &display_settings = scene->display_settings;
if (STREQ(display_settings.display_device, "None")) {
BKE_scene_disable_color_management(scene);
}
}
}
/**
* Versioning code until next subversion bump goes here.
*

View File

@ -38,7 +38,7 @@ struct Global {
Global G;
#endif
/* We cannot use NULL char until ultimate step, would give nightmare to our C string
/* We cannot use null char until ultimate step, would give nightmare to our C string
* processing... Using one of the UTF-8 invalid bytes (as per our BLI string_utf8.c) */
#define NULLSEP_STR "\xff"
#define NULLSEP_CHR '\xff'

View File

@ -56,9 +56,6 @@ class Context {
* composite output will be used as a fallback viewer if no other viewer exists */
virtual bool use_composite_output() const = 0;
/* True if color management should be used for texture evaluation. */
virtual bool use_texture_color_management() const = 0;
/* Get the render settings for compositing. */
virtual const RenderData &get_render_data() const = 0;

View File

@ -4,7 +4,7 @@
ivec3 compute_saturation_indices(vec3 v)
{
int index_of_max = ((v.x > v.y) ? ((v.x > v.z) ? 0 : 2) : ((v.y > v.z) ? 1 : 2));
ivec2 other_indices = ivec2(mod(ivec2(index_of_max) + ivec2(1, 2), ivec2(3)));
ivec2 other_indices = (ivec2(index_of_max) + ivec2(1, 2)) % 3;
int min_index = min(other_indices.x, other_indices.y);
int max_index = max(other_indices.x, other_indices.y);
return ivec3(index_of_max, max_index, min_index);

View File

@ -5,7 +5,7 @@
ivec3 compute_saturation_indices(vec3 v)
{
int index_of_max = ((v.x > v.y) ? ((v.x > v.z) ? 0 : 2) : ((v.y > v.z) ? 1 : 2));
ivec2 other_indices = ivec2(mod(ivec2(index_of_max) + ivec2(1, 2), ivec2(3)));
ivec2 other_indices = (ivec2(index_of_max) + ivec2(1, 2)) % 3;
int min_index = min(other_indices.x, other_indices.y);
int max_index = max(other_indices.x, other_indices.y);
return ivec3(index_of_max, max_index, min_index);

View File

@ -81,11 +81,6 @@ class Context : public realtime_compositor::Context {
return false;
}
bool use_texture_color_management() const override
{
return BKE_scene_check_color_management_enabled(DRW_context_state_get()->scene);
}
const RenderData &get_render_data() const override
{
return DRW_context_state_get()->scene->r;

View File

@ -1404,7 +1404,7 @@ static void particle_batch_cache_ensure_pos(Object *object,
for (curr_point = 0, i = 0, pa = psys->particles; i < psys->totpart; i++, pa++) {
state.time = DEG_get_ctime(draw_ctx->depsgraph);
if (!psys_get_particle_state(&sim, i, &state, 0)) {
if (!psys_get_particle_state(&sim, i, &state, false)) {
continue;
}

View File

@ -8,7 +8,7 @@
* GPU fluid drawing functions.
*/
#include <string.h>
#include <cstring>
#include "BLI_listbase.h"
#include "BLI_math.h"
@ -179,7 +179,7 @@ static GPUTexture *create_volume_texture(const int dim[3],
return nullptr;
}
while (1) {
while (true) {
tex = GPU_texture_create_3d("volume",
UNPACK3(final_dim),
1,

View File

@ -6,7 +6,7 @@
* \ingroup draw
*/
#include <stdio.h>
#include <cstdio>
#include "BLI_alloca.h"
#include "BLI_listbase.h"

View File

@ -3499,7 +3499,9 @@ static bool acf_gpl_setting_valid(bAnimContext * /*ac*/,
}
/* Get the appropriate flag(s) for the setting when it is valid. */
static int acf_gpl_setting_flag(bAnimContext * /*ac*/, eAnimChannel_Settings setting, bool *r_neg)
static int acf_gpl_setting_flag_legacy(bAnimContext * /*ac*/,
eAnimChannel_Settings setting,
bool *r_neg)
{
/* Clear extra return data first. */
*r_neg = false;
@ -3549,7 +3551,7 @@ static bAnimChannelType ACF_GPL_LEGACY = {
/*icon*/ nullptr,
/*has_setting*/ acf_gpl_setting_valid,
/*setting_flag*/ acf_gpl_setting_flag,
/*setting_flag*/ acf_gpl_setting_flag_legacy,
/*setting_ptr*/ acf_gpl_setting_ptr_legacy,
};
@ -3578,6 +3580,17 @@ static bool acf_gpl_name_prop(bAnimListElem *ale, PointerRNA *r_ptr, PropertyRNA
return (*r_prop != nullptr);
}
static int acf_gpl_setting_flag(bAnimContext * /*ac*/, eAnimChannel_Settings setting, bool *r_neg)
{
*r_neg = false;
switch (setting) {
case ACHANNEL_SETTING_SELECT: /* selected */
return GP_LAYER_TREE_NODE_SELECT;
default: /* unsupported */
return 0;
}
}
/* Get pointer to the setting */
static void *acf_gpl_setting_ptr(bAnimListElem *ale,
eAnimChannel_Settings /*setting*/,

View File

@ -297,7 +297,6 @@ void ANIM_set_active_channel(bAnimContext *ac,
gpl->flag |= GP_LAYER_ACTIVE;
break;
}
/* unhandled currently, but may be interesting */
case ANIMTYPE_MASKLAYER:
case ANIMTYPE_SHAPEKEY:
@ -3650,6 +3649,26 @@ static int click_select_channel_gplayer(bContext *C,
return (ND_ANIMCHAN | NA_EDITED); /* Animation Editors updates */
}
static int click_select_channel_grease_pencil_layer(bContext *C,
bAnimContext *ac,
bAnimListElem *ale,
const short /*selectmode*/,
const int /*filter*/)
{
/* TODO: Implement other selection modes. */
GreasePencilLayer *layer = static_cast<GreasePencilLayer *>(ale->data);
GreasePencil *grease_pencil = reinterpret_cast<GreasePencil *>(ale->id);
/* Clear previous channel selection and set active flag on current selection */
ANIM_anim_channels_select_set(ac, ACHANNEL_SETFLAG_CLEAR);
layer->base.flag |= GP_LAYER_TREE_NODE_SELECT;
grease_pencil->active_layer = layer;
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_SELECTED, nullptr);
return (ND_ANIMCHAN | NA_EDITED);
}
static int click_select_channel_maskdatablock(bAnimListElem *ale)
{
Mask *mask = (Mask *)ale->data;
@ -3784,6 +3803,13 @@ static int mouse_anim_channels(bContext *C,
case ANIMTYPE_GPLAYER:
notifierFlags |= click_select_channel_gplayer(C, ac, ale, selectmode, filter);
break;
case ANIMTYPE_GREASE_PENCIL_DATABLOCK:
/*todo*/
break;
case ANIMTYPE_GREASE_PENCIL_LAYER:
notifierFlags |= click_select_channel_grease_pencil_layer(
C, ac, ale, SELECT_REPLACE, filter);
break;
case ANIMTYPE_MASKDATABLOCK:
notifierFlags |= click_select_channel_maskdatablock(ale);
break;

View File

@ -13,6 +13,7 @@
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
#include "DNA_gpencil_legacy_types.h"
#include "DNA_grease_pencil_types.h"
#include "DNA_mask_types.h"
#include "DNA_node_types.h"
#include "DNA_object_types.h"
@ -290,6 +291,16 @@ void ANIM_sync_animchannels_to_data(const bContext *C)
case ANIMTYPE_GPLAYER:
animchan_sync_gplayer(ale);
break;
case ANIMTYPE_GREASE_PENCIL_LAYER:
GreasePencil *grease_pencil = reinterpret_cast<GreasePencil *>(ale->id);
GreasePencilLayer *layer = static_cast<GreasePencilLayer *>(ale->data);
if (grease_pencil->active_layer == layer) {
layer->base.flag |= GP_LAYER_TREE_NODE_SELECT;
}
else {
layer->base.flag &= ~GP_LAYER_TREE_NODE_SELECT;
}
break;
}
}

View File

@ -39,6 +39,7 @@
#include "DEG_depsgraph_query.h"
#include "RNA_access.h"
#include "RNA_define.h"
#include "RNA_enum_types.h"
#include "UI_interface.h"
@ -69,9 +70,92 @@ namespace blender::ed::geometry {
/** \name Operator
* \{ */
static const bNodeTree *get_node_group(const bContext &C)
/**
* #AssetLibrary::resolve_asset_weak_reference_to_full_path() currently does not support local
* assets.
*/
static const asset_system::AssetRepresentation *get_local_asset_from_relative_identifier(
const bContext &C, const StringRefNull relative_identifier, ReportList *reports)
{
const asset_system::AssetRepresentation *asset = CTX_wm_asset(&C);
AssetLibraryReference library_ref{};
library_ref.type = ASSET_LIBRARY_LOCAL;
ED_assetlist_storage_fetch(&library_ref, &C);
ED_assetlist_ensure_previews_job(&library_ref, &C);
const asset_system::AssetRepresentation *matching_asset = nullptr;
ED_assetlist_iterate(library_ref, [&](asset_system::AssetRepresentation &asset) {
if (asset.get_identifier().library_relative_identifier() == relative_identifier) {
matching_asset = &asset;
return false;
}
return true;
});
if (reports && !matching_asset) {
if (ED_assetlist_is_loaded(&library_ref)) {
BKE_reportf(
reports, RPT_ERROR, "No asset found at path \"%s\"", relative_identifier.c_str());
}
else {
BKE_report(reports, RPT_WARNING, "Asset loading is unfinished");
}
}
return matching_asset;
}
static const asset_system::AssetRepresentation *find_asset_from_weak_ref(
const bContext &C, const AssetWeakReference &weak_ref, ReportList *reports)
{
if (weak_ref.asset_library_type == ASSET_LIBRARY_LOCAL) {
return get_local_asset_from_relative_identifier(
C, weak_ref.relative_asset_identifier, reports);
}
const AssetLibraryReference library_ref = asset_system::all_library_reference();
ED_assetlist_storage_fetch(&library_ref, &C);
ED_assetlist_ensure_previews_job(&library_ref, &C);
asset_system::AssetLibrary *all_library = ED_assetlist_library_get_once_available(
asset_system::all_library_reference());
if (!all_library) {
BKE_report(reports, RPT_WARNING, "Asset loading is unfinished");
}
const std::string full_path = all_library->resolve_asset_weak_reference_to_full_path(weak_ref);
const asset_system::AssetRepresentation *matching_asset = nullptr;
ED_assetlist_iterate(library_ref, [&](asset_system::AssetRepresentation &asset) {
if (asset.get_identifier().full_path() == full_path) {
matching_asset = &asset;
return false;
}
return true;
});
if (reports && !matching_asset) {
if (ED_assetlist_is_loaded(&library_ref)) {
BKE_reportf(reports, RPT_ERROR, "No asset found at path \"%s\"", full_path.c_str());
}
}
return matching_asset;
}
/** \note Does not check asset type or meta data. */
static const asset_system::AssetRepresentation *get_asset(const bContext &C,
PointerRNA &ptr,
ReportList *reports)
{
AssetWeakReference weak_ref{};
weak_ref.asset_library_type = RNA_enum_get(&ptr, "asset_library_type");
weak_ref.asset_library_identifier = RNA_string_get_alloc(
&ptr, "asset_library_identifier", nullptr, 0, nullptr);
weak_ref.relative_asset_identifier = RNA_string_get_alloc(
&ptr, "relative_asset_identifier", nullptr, 0, nullptr);
return find_asset_from_weak_ref(C, weak_ref, reports);
}
static const bNodeTree *get_node_group(const bContext &C, PointerRNA &ptr, ReportList *reports)
{
const asset_system::AssetRepresentation *asset = get_asset(C, ptr, reports);
if (!asset) {
return nullptr;
}
@ -82,6 +166,9 @@ static const bNodeTree *get_node_group(const bContext &C)
return nullptr;
}
if (node_group->type != NTREE_GEOMETRY) {
if (reports) {
BKE_report(reports, RPT_ERROR, "Asset is not a geometry node group");
}
return nullptr;
}
return node_group;
@ -217,7 +304,7 @@ static int run_node_group_exec(bContext *C, wmOperator *op)
}
const eObjectMode mode = eObjectMode(active_object->mode);
const bNodeTree *node_tree = get_node_group(*C);
const bNodeTree *node_tree = get_node_group(*C, *op->ptr, op->reports);
if (!node_tree) {
return OPERATOR_CANCELLED;
}
@ -268,7 +355,7 @@ static int run_node_group_exec(bContext *C, wmOperator *op)
static int run_node_group_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/)
{
const bNodeTree *node_tree = get_node_group(*C);
const bNodeTree *node_tree = get_node_group(*C, *op->ptr, op->reports);
if (!node_tree) {
return OPERATOR_CANCELLED;
}
@ -279,11 +366,9 @@ static int run_node_group_invoke(bContext *C, wmOperator *op, const wmEvent * /*
return run_node_group_exec(C, op);
}
static char *run_node_group_get_description(bContext *C,
wmOperatorType * /*ot*/,
PointerRNA * /*ptr*/)
static char *run_node_group_get_description(bContext *C, wmOperatorType * /*ot*/, PointerRNA *ptr)
{
const asset_system::AssetRepresentation *asset = CTX_wm_asset(C);
const asset_system::AssetRepresentation *asset = get_asset(*C, *ptr, nullptr);
if (!asset) {
return nullptr;
}
@ -294,34 +379,33 @@ static char *run_node_group_get_description(bContext *C,
return BLI_strdup(description);
}
static bool run_node_group_poll(bContext *C)
{
const asset_system::AssetRepresentation *asset = CTX_wm_asset(C);
if (!asset) {
return false;
}
const Object *object = CTX_data_active_object(C);
if (object->type != OB_CURVES) {
return false;
}
if (object->mode != OB_MODE_SCULPT_CURVES) {
return false;
}
return true;
}
void GEOMETRY_OT_execute_node_group(wmOperatorType *ot)
{
ot->name = "Run Node Group";
ot->idname = __func__;
ot->description = "Execute a node group on geometry";
ot->poll = run_node_group_poll;
/* A proper poll is not possible, since it doesn't have access to the operator's properties. */
ot->invoke = run_node_group_invoke;
ot->exec = run_node_group_exec;
ot->get_description = run_node_group_get_description;
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
PropertyRNA *prop;
prop = RNA_def_enum(ot->srna,
"asset_library_type",
rna_enum_aset_library_type_items,
ASSET_LIBRARY_LOCAL,
"Asset Library Type",
"");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_string(
ot->srna, "asset_library_identifier", nullptr, 0, "Asset Library Identifier", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_string(
ot->srna, "relative_asset_identifier", nullptr, 0, "Relative Asset Identifier", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
/** \} */
@ -430,9 +514,20 @@ static void node_add_catalog_assets_draw(const bContext *C, Menu *menu)
for (const asset_system::AssetRepresentation *asset : assets) {
uiLayout *col = uiLayoutColumn(layout, false);
PointerRNA asset_ptr = asset::create_asset_rna_ptr(asset);
uiLayoutSetContextPointer(col, "asset", &asset_ptr);
uiItemO(col, IFACE_(asset->get_name().c_str()), ICON_NONE, "GEOMETRY_OT_execute_node_group");
wmOperatorType *ot = WM_operatortype_find("GEOMETRY_OT_execute_node_group", true);
const std::unique_ptr<AssetWeakReference> weak_ref = asset->make_weak_reference();
PointerRNA props_ptr;
uiItemFullO_ptr(col,
ot,
IFACE_(asset->get_name().c_str()),
ICON_NONE,
nullptr,
WM_OP_INVOKE_DEFAULT,
eUI_Item_Flag(0),
&props_ptr);
RNA_enum_set(&props_ptr, "asset_library_type", weak_ref->asset_library_type);
RNA_string_set(&props_ptr, "asset_library_identifier", weak_ref->asset_library_identifier);
RNA_string_set(&props_ptr, "relative_asset_identifier", weak_ref->relative_asset_identifier);
}
asset_system::AssetLibrary *all_library = ED_assetlist_library_get_once_available(

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