Merge branch 'master' into xr-dev
This commit is contained in:
commit
ff347bf950
|
@ -256,7 +256,7 @@ endif()
|
|||
|
||||
if(UNIX AND NOT APPLE)
|
||||
option(WITH_SYSTEM_GLEW "Use GLEW OpenGL wrapper library provided by the operating system" OFF)
|
||||
option(WITH_SYSTEM_GLEW "Use GLEW OpenGL wrapper library provided by the operating system" OFF)
|
||||
option(WITH_SYSTEM_GLES "Use OpenGL ES library provided by the operating system" ON)
|
||||
option(WITH_SYSTEM_FREETYPE "Use the freetype library provided by the operating system" OFF)
|
||||
else()
|
||||
# not an option for other OS's
|
||||
|
|
|
@ -32,7 +32,7 @@ Other Convenience Targets
|
|||
* config: Run cmake configuration tool to set build options.
|
||||
* deps: Build library dependencies (intended only for platform maintainers).
|
||||
|
||||
The existance of locally build dependencies overrides the pre-built dependencies from subversion.
|
||||
The existence of locally build dependencies overrides the pre-built dependencies from subversion.
|
||||
These must be manually removed from '../lib/' to go back to using the pre-compiled libraries.
|
||||
|
||||
Project Files
|
||||
|
|
|
@ -423,6 +423,7 @@ TEST(atomic, atomic_fetch_and_and_uint32)
|
|||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name 32 bit signed int atomics
|
||||
* \{ */
|
||||
|
||||
|
@ -559,6 +560,7 @@ TEST(atomic, atomic_fetch_and_and_int32)
|
|||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name 16 bit signed int atomics
|
||||
* \{ */
|
||||
|
||||
|
@ -592,6 +594,9 @@ TEST(atomic, atomic_fetch_and_and_int16)
|
|||
}
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name 8 bit unsigned int atomics
|
||||
* \{ */
|
||||
|
||||
|
@ -638,6 +643,7 @@ TEST(atomic, atomic_fetch_and_and_int8)
|
|||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name char aliases
|
||||
* \{ */
|
||||
|
||||
|
@ -661,6 +667,7 @@ TEST(atomic, atomic_fetch_and_and_char)
|
|||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name size_t aliases
|
||||
* \{ */
|
||||
|
||||
|
@ -772,6 +779,7 @@ TEST(atomic, atomic_fetch_and_update_max_z)
|
|||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name unsigned int aliases
|
||||
* \{ */
|
||||
|
||||
|
@ -867,6 +875,7 @@ TEST(atomic, atomic_cas_u)
|
|||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name pointer aliases
|
||||
* \{ */
|
||||
|
||||
|
@ -885,6 +894,7 @@ TEST(atomic, atomic_cas_ptr)
|
|||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name floating point atomics
|
||||
* \{ */
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ from bl_ui.utils import PresetPanel
|
|||
from bpy.types import Panel
|
||||
|
||||
from bl_ui.properties_grease_pencil_common import GreasePencilSimplifyPanel
|
||||
from bl_ui.properties_render import draw_hair_settings
|
||||
from bl_ui.properties_view_layer import ViewLayerCryptomattePanel, ViewLayerAOVPanel
|
||||
|
||||
class CyclesPresetPanel(PresetPanel, Panel):
|
||||
|
@ -355,6 +356,13 @@ class CYCLES_RENDER_PT_hair(CyclesButtonsPanel, Panel):
|
|||
if ccscene.shape == 'RIBBONS':
|
||||
col.prop(ccscene, "subdivisions", text="Curve Subdivisions")
|
||||
|
||||
class CYCLES_RENDER_PT_hair_viewport_display(CyclesButtonsPanel, Panel):
|
||||
bl_label = "Viewport Display"
|
||||
bl_parent_id = "CYCLES_RENDER_PT_hair"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
def draw(self, context):
|
||||
draw_hair_settings(self, context)
|
||||
|
||||
class CYCLES_RENDER_PT_volumes(CyclesButtonsPanel, Panel):
|
||||
bl_label = "Volumes"
|
||||
|
@ -2153,6 +2161,7 @@ classes = (
|
|||
CYCLES_RENDER_PT_volumes,
|
||||
CYCLES_RENDER_PT_subdivision,
|
||||
CYCLES_RENDER_PT_hair,
|
||||
CYCLES_RENDER_PT_hair_viewport_display,
|
||||
CYCLES_RENDER_PT_simplify,
|
||||
CYCLES_RENDER_PT_simplify_viewport,
|
||||
CYCLES_RENDER_PT_simplify_render,
|
||||
|
|
|
@ -33,6 +33,191 @@
|
|||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
// A minimal copy of functionality `optix_denoiser_tiling.h` which allows to fix integer overflow
|
||||
// issues without bumping SDK or driver requirement.
|
||||
//
|
||||
// The original code is Copyright NVIDIA Corporation, BSD-3-Clause.
|
||||
namespace {
|
||||
|
||||
static OptixResult optixUtilDenoiserSplitImage(const OptixImage2D &input,
|
||||
const OptixImage2D &output,
|
||||
unsigned int overlapWindowSizeInPixels,
|
||||
unsigned int tileWidth,
|
||||
unsigned int tileHeight,
|
||||
std::vector<OptixUtilDenoiserImageTile> &tiles)
|
||||
{
|
||||
if (tileWidth == 0 || tileHeight == 0)
|
||||
return OPTIX_ERROR_INVALID_VALUE;
|
||||
|
||||
unsigned int inPixelStride = optixUtilGetPixelStride(input);
|
||||
unsigned int outPixelStride = optixUtilGetPixelStride(output);
|
||||
|
||||
int inp_w = std::min(tileWidth + 2 * overlapWindowSizeInPixels, input.width);
|
||||
int inp_h = std::min(tileHeight + 2 * overlapWindowSizeInPixels, input.height);
|
||||
int inp_y = 0, copied_y = 0;
|
||||
|
||||
do {
|
||||
int inputOffsetY = inp_y == 0 ? 0 :
|
||||
std::max((int)overlapWindowSizeInPixels,
|
||||
inp_h - ((int)input.height - inp_y));
|
||||
int copy_y = inp_y == 0 ? std::min(input.height, tileHeight + overlapWindowSizeInPixels) :
|
||||
std::min(tileHeight, input.height - copied_y);
|
||||
|
||||
int inp_x = 0, copied_x = 0;
|
||||
do {
|
||||
int inputOffsetX = inp_x == 0 ? 0 :
|
||||
std::max((int)overlapWindowSizeInPixels,
|
||||
inp_w - ((int)input.width - inp_x));
|
||||
int copy_x = inp_x == 0 ? std::min(input.width, tileWidth + overlapWindowSizeInPixels) :
|
||||
std::min(tileWidth, input.width - copied_x);
|
||||
|
||||
OptixUtilDenoiserImageTile tile;
|
||||
tile.input.data = input.data + (size_t)(inp_y - inputOffsetY) * input.rowStrideInBytes +
|
||||
+(size_t)(inp_x - inputOffsetX) * inPixelStride;
|
||||
tile.input.width = inp_w;
|
||||
tile.input.height = inp_h;
|
||||
tile.input.rowStrideInBytes = input.rowStrideInBytes;
|
||||
tile.input.pixelStrideInBytes = input.pixelStrideInBytes;
|
||||
tile.input.format = input.format;
|
||||
|
||||
tile.output.data = output.data + (size_t)inp_y * output.rowStrideInBytes +
|
||||
(size_t)inp_x * outPixelStride;
|
||||
tile.output.width = copy_x;
|
||||
tile.output.height = copy_y;
|
||||
tile.output.rowStrideInBytes = output.rowStrideInBytes;
|
||||
tile.output.pixelStrideInBytes = output.pixelStrideInBytes;
|
||||
tile.output.format = output.format;
|
||||
|
||||
tile.inputOffsetX = inputOffsetX;
|
||||
tile.inputOffsetY = inputOffsetY;
|
||||
tiles.push_back(tile);
|
||||
|
||||
inp_x += inp_x == 0 ? tileWidth + overlapWindowSizeInPixels : tileWidth;
|
||||
copied_x += copy_x;
|
||||
} while (inp_x < static_cast<int>(input.width));
|
||||
|
||||
inp_y += inp_y == 0 ? tileHeight + overlapWindowSizeInPixels : tileHeight;
|
||||
copied_y += copy_y;
|
||||
} while (inp_y < static_cast<int>(input.height));
|
||||
|
||||
return OPTIX_SUCCESS;
|
||||
}
|
||||
|
||||
static OptixResult optixUtilDenoiserInvokeTiled(OptixDenoiser denoiser,
|
||||
CUstream stream,
|
||||
const OptixDenoiserParams *params,
|
||||
CUdeviceptr denoiserState,
|
||||
size_t denoiserStateSizeInBytes,
|
||||
const OptixDenoiserGuideLayer *guideLayer,
|
||||
const OptixDenoiserLayer *layers,
|
||||
unsigned int numLayers,
|
||||
CUdeviceptr scratch,
|
||||
size_t scratchSizeInBytes,
|
||||
unsigned int overlapWindowSizeInPixels,
|
||||
unsigned int tileWidth,
|
||||
unsigned int tileHeight)
|
||||
{
|
||||
if (!guideLayer || !layers)
|
||||
return OPTIX_ERROR_INVALID_VALUE;
|
||||
|
||||
std::vector<std::vector<OptixUtilDenoiserImageTile>> tiles(numLayers);
|
||||
std::vector<std::vector<OptixUtilDenoiserImageTile>> prevTiles(numLayers);
|
||||
for (unsigned int l = 0; l < numLayers; l++) {
|
||||
if (const OptixResult res = ccl::optixUtilDenoiserSplitImage(layers[l].input,
|
||||
layers[l].output,
|
||||
overlapWindowSizeInPixels,
|
||||
tileWidth,
|
||||
tileHeight,
|
||||
tiles[l]))
|
||||
return res;
|
||||
|
||||
if (layers[l].previousOutput.data) {
|
||||
OptixImage2D dummyOutput = layers[l].previousOutput;
|
||||
if (const OptixResult res = ccl::optixUtilDenoiserSplitImage(layers[l].previousOutput,
|
||||
dummyOutput,
|
||||
overlapWindowSizeInPixels,
|
||||
tileWidth,
|
||||
tileHeight,
|
||||
prevTiles[l]))
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<OptixUtilDenoiserImageTile> albedoTiles;
|
||||
if (guideLayer->albedo.data) {
|
||||
OptixImage2D dummyOutput = guideLayer->albedo;
|
||||
if (const OptixResult res = ccl::optixUtilDenoiserSplitImage(guideLayer->albedo,
|
||||
dummyOutput,
|
||||
overlapWindowSizeInPixels,
|
||||
tileWidth,
|
||||
tileHeight,
|
||||
albedoTiles))
|
||||
return res;
|
||||
}
|
||||
|
||||
std::vector<OptixUtilDenoiserImageTile> normalTiles;
|
||||
if (guideLayer->normal.data) {
|
||||
OptixImage2D dummyOutput = guideLayer->normal;
|
||||
if (const OptixResult res = ccl::optixUtilDenoiserSplitImage(guideLayer->normal,
|
||||
dummyOutput,
|
||||
overlapWindowSizeInPixels,
|
||||
tileWidth,
|
||||
tileHeight,
|
||||
normalTiles))
|
||||
return res;
|
||||
}
|
||||
std::vector<OptixUtilDenoiserImageTile> flowTiles;
|
||||
if (guideLayer->flow.data) {
|
||||
OptixImage2D dummyOutput = guideLayer->flow;
|
||||
if (const OptixResult res = ccl::optixUtilDenoiserSplitImage(guideLayer->flow,
|
||||
dummyOutput,
|
||||
overlapWindowSizeInPixels,
|
||||
tileWidth,
|
||||
tileHeight,
|
||||
flowTiles))
|
||||
return res;
|
||||
}
|
||||
|
||||
for (size_t t = 0; t < tiles[0].size(); t++) {
|
||||
std::vector<OptixDenoiserLayer> tlayers;
|
||||
for (unsigned int l = 0; l < numLayers; l++) {
|
||||
OptixDenoiserLayer layer = {};
|
||||
layer.input = (tiles[l])[t].input;
|
||||
layer.output = (tiles[l])[t].output;
|
||||
if (layers[l].previousOutput.data)
|
||||
layer.previousOutput = (prevTiles[l])[t].input;
|
||||
tlayers.push_back(layer);
|
||||
}
|
||||
|
||||
OptixDenoiserGuideLayer gl = {};
|
||||
if (guideLayer->albedo.data)
|
||||
gl.albedo = albedoTiles[t].input;
|
||||
|
||||
if (guideLayer->normal.data)
|
||||
gl.normal = normalTiles[t].input;
|
||||
|
||||
if (guideLayer->flow.data)
|
||||
gl.flow = flowTiles[t].input;
|
||||
|
||||
if (const OptixResult res = optixDenoiserInvoke(denoiser,
|
||||
stream,
|
||||
params,
|
||||
denoiserState,
|
||||
denoiserStateSizeInBytes,
|
||||
&gl,
|
||||
&tlayers[0],
|
||||
numLayers,
|
||||
(tiles[0])[t].inputOffsetX,
|
||||
(tiles[0])[t].inputOffsetY,
|
||||
scratch,
|
||||
scratchSizeInBytes))
|
||||
return res;
|
||||
}
|
||||
return OPTIX_SUCCESS;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
OptiXDevice::Denoiser::Denoiser(OptiXDevice *device)
|
||||
: device(device), queue(device), state(device, "__denoiser_state", true)
|
||||
{
|
||||
|
@ -1075,20 +1260,20 @@ bool OptiXDevice::denoise_run(DenoiseContext &context, const DenoisePass &pass)
|
|||
/* Finally run denoising. */
|
||||
OptixDenoiserParams params = {}; /* All parameters are disabled/zero. */
|
||||
|
||||
optix_assert(optixUtilDenoiserInvokeTiled(denoiser_.optix_denoiser,
|
||||
denoiser_.queue.stream(),
|
||||
¶ms,
|
||||
denoiser_.state.device_pointer,
|
||||
denoiser_.sizes.stateSizeInBytes,
|
||||
&guide_layers,
|
||||
&image_layers,
|
||||
1,
|
||||
denoiser_.state.device_pointer +
|
||||
denoiser_.sizes.stateSizeInBytes,
|
||||
denoiser_.sizes.withOverlapScratchSizeInBytes,
|
||||
denoiser_.sizes.overlapWindowSizeInPixels,
|
||||
denoiser_.configured_size.x,
|
||||
denoiser_.configured_size.y));
|
||||
optix_assert(ccl::optixUtilDenoiserInvokeTiled(denoiser_.optix_denoiser,
|
||||
denoiser_.queue.stream(),
|
||||
¶ms,
|
||||
denoiser_.state.device_pointer,
|
||||
denoiser_.sizes.stateSizeInBytes,
|
||||
&guide_layers,
|
||||
&image_layers,
|
||||
1,
|
||||
denoiser_.state.device_pointer +
|
||||
denoiser_.sizes.stateSizeInBytes,
|
||||
denoiser_.sizes.withOverlapScratchSizeInBytes,
|
||||
denoiser_.sizes.overlapWindowSizeInPixels,
|
||||
denoiser_.configured_size.x,
|
||||
denoiser_.configured_size.y));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -80,7 +80,8 @@ static bool is_single_supported_device(Device *device, DenoiserType type)
|
|||
|
||||
if (!device->info.multi_devices.empty()) {
|
||||
/* Some configurations will use multi_devices, but keep the type of an individual device.
|
||||
* This does simplify checks for homogenous setups, but here we really need a single device. */
|
||||
* This does simplify checks for homogeneous setups, but here we really need a single device.
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -186,7 +186,7 @@ ccl_device float4 kernel_tex_image_interp(KernelGlobals kg, int id, float x, flo
|
|||
const int texture_type = info.data_type;
|
||||
if (texture_type == IMAGE_DATA_TYPE_FLOAT4 || texture_type == IMAGE_DATA_TYPE_BYTE4 ||
|
||||
texture_type == IMAGE_DATA_TYPE_HALF4 || texture_type == IMAGE_DATA_TYPE_USHORT4) {
|
||||
if (info.interpolation == INTERPOLATION_CUBIC) {
|
||||
if (info.interpolation == INTERPOLATION_CUBIC || info.interpolation == INTERPOLATION_SMART) {
|
||||
return kernel_tex_image_interp_bicubic<float4>(info, x, y);
|
||||
}
|
||||
else {
|
||||
|
@ -198,7 +198,7 @@ ccl_device float4 kernel_tex_image_interp(KernelGlobals kg, int id, float x, flo
|
|||
else {
|
||||
float f;
|
||||
|
||||
if (info.interpolation == INTERPOLATION_CUBIC) {
|
||||
if (info.interpolation == INTERPOLATION_CUBIC || info.interpolation == INTERPOLATION_SMART) {
|
||||
f = kernel_tex_image_interp_bicubic<float>(info, x, y);
|
||||
}
|
||||
else {
|
||||
|
@ -241,7 +241,7 @@ ccl_device float4 kernel_tex_image_interp_3d(KernelGlobals kg,
|
|||
#endif
|
||||
if (texture_type == IMAGE_DATA_TYPE_FLOAT4 || texture_type == IMAGE_DATA_TYPE_BYTE4 ||
|
||||
texture_type == IMAGE_DATA_TYPE_HALF4 || texture_type == IMAGE_DATA_TYPE_USHORT4) {
|
||||
if (interpolation == INTERPOLATION_CUBIC) {
|
||||
if (interpolation == INTERPOLATION_CUBIC || interpolation == INTERPOLATION_SMART) {
|
||||
return kernel_tex_image_interp_tricubic<float4>(info, x, y, z);
|
||||
}
|
||||
else {
|
||||
|
@ -252,7 +252,7 @@ ccl_device float4 kernel_tex_image_interp_3d(KernelGlobals kg,
|
|||
else {
|
||||
float f;
|
||||
|
||||
if (interpolation == INTERPOLATION_CUBIC) {
|
||||
if (interpolation == INTERPOLATION_CUBIC || interpolation == INTERPOLATION_SMART) {
|
||||
f = kernel_tex_image_interp_tricubic<float>(info, x, y, z);
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -543,7 +543,7 @@ static void read_subd_geometry(CachedData &cached_data, const SubDSchemaData &da
|
|||
|
||||
add_positions(data.positions.getValue(iss), time, cached_data);
|
||||
|
||||
if (data.topology_variance != kHomogenousTopology || cached_data.shader.size() == 0) {
|
||||
if (data.topology_variance != kHomogeneousTopology || cached_data.shader.size() == 0) {
|
||||
add_subd_polygons(cached_data, data, time);
|
||||
add_subd_edge_creases(cached_data, data, time);
|
||||
add_subd_vertex_creases(cached_data, data, time);
|
||||
|
@ -582,7 +582,7 @@ static void read_curves_data(CachedData &cached_data, const CurvesSchemaData &da
|
|||
array<int> curve_first_key;
|
||||
array<int> curve_shader;
|
||||
|
||||
const bool is_homogenous = data.topology_variance == kHomogenousTopology;
|
||||
const bool is_homogeneous = data.topology_variance == kHomogeneousTopology;
|
||||
|
||||
curve_keys.reserve(position->size());
|
||||
curve_radius.reserve(position->size());
|
||||
|
@ -605,7 +605,7 @@ static void read_curves_data(CachedData &cached_data, const CurvesSchemaData &da
|
|||
curve_radius.push_back_slow(radius * data.radius_scale);
|
||||
}
|
||||
|
||||
if (!is_homogenous || cached_data.curve_first_key.size() == 0) {
|
||||
if (!is_homogeneous || cached_data.curve_first_key.size() == 0) {
|
||||
curve_first_key.push_back_reserved(offset);
|
||||
curve_shader.push_back_reserved(0);
|
||||
}
|
||||
|
@ -616,7 +616,7 @@ static void read_curves_data(CachedData &cached_data, const CurvesSchemaData &da
|
|||
cached_data.curve_keys.add_data(curve_keys, time);
|
||||
cached_data.curve_radius.add_data(curve_radius, time);
|
||||
|
||||
if (!is_homogenous || cached_data.curve_first_key.size() == 0) {
|
||||
if (!is_homogeneous || cached_data.curve_first_key.size() == 0) {
|
||||
cached_data.curve_first_key.add_data(curve_first_key, time);
|
||||
cached_data.curve_shader.add_data(curve_shader, time);
|
||||
}
|
||||
|
|
|
@ -326,7 +326,7 @@ void GHOST_Wintab::getInput(std::vector<GHOST_WintabInfoWin32> &outWintabInfo)
|
|||
ORIENTATION ort = pkt.pkOrientation;
|
||||
|
||||
/* Convert raw fixed point data to radians. */
|
||||
float altRad = (float)((fabs((float)ort.orAltitude) / (float)m_maxAltitude) * M_PI / 2.0);
|
||||
float altRad = (float)((fabs((float)ort.orAltitude) / (float)m_maxAltitude) * M_PI_2);
|
||||
float azmRad = (float)(((float)ort.orAzimuth / (float)m_maxAzimuth) * M_PI * 2.0);
|
||||
|
||||
/* Find length of the stylus' projected vector on the XY plane. */
|
||||
|
@ -334,7 +334,7 @@ void GHOST_Wintab::getInput(std::vector<GHOST_WintabInfoWin32> &outWintabInfo)
|
|||
|
||||
/* From there calculate X and Y components based on azimuth. */
|
||||
out.tabletData.Xtilt = sin(azmRad) * vecLen;
|
||||
out.tabletData.Ytilt = (float)(sin(M_PI / 2.0 - azmRad) * vecLen);
|
||||
out.tabletData.Ytilt = (float)(sin(M_PI_2 - azmRad) * vecLen);
|
||||
}
|
||||
|
||||
out.time = pkt.pkTime;
|
||||
|
|
|
@ -193,7 +193,7 @@ void IK_QJacobian::InvertSDLS()
|
|||
// DLS. The SDLS damps individual singular values, instead of using a single
|
||||
// damping term.
|
||||
|
||||
double max_angle_change = M_PI / 4.0;
|
||||
double max_angle_change = M_PI_4;
|
||||
double epsilon = 1e-10;
|
||||
int i, j;
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ namespace iTaSC {
|
|||
#define CACHE_CHANNEL_EXTEND_SIZE 10
|
||||
#define CACHE_MAX_ITEM_SIZE 0x3FFF0
|
||||
|
||||
/* macro to get the alignement gap after an item header */
|
||||
/* macro to get the alignment gap after an item header */
|
||||
#define CACHE_ITEM_GAPB(item) (unsigned int)(((size_t)item+sizeof(CacheItem))&(sizeof(void*)-1))
|
||||
/* macro to get item data position, item=CacheItem pointer */
|
||||
#define CACHE_ITEM_DATA_POINTER(item) (void*)((unsigned char*)item+sizeof(CacheItem)+CACHE_ITEM_GAPB(item))
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
|
||||
# Update Blender version this key-map was written in:
|
||||
#
|
||||
# When the version is ``(0, 0, 0)``, the key-map being loaded didn't contain any versioning information.
|
||||
# This will older than ``(2, 92, 0)``.
|
||||
# When the version is `(0, 0, 0)`, the key-map being loaded didn't contain any versioning information.
|
||||
# This will older than `(2, 92, 0)`.
|
||||
|
||||
def keyconfig_update(keyconfig_data, keyconfig_version):
|
||||
from bpy.app import version_file as blender_version
|
||||
|
@ -14,11 +14,11 @@ def keyconfig_update(keyconfig_data, keyconfig_version):
|
|||
|
||||
# Version the key-map.
|
||||
import copy
|
||||
# Only copy once.
|
||||
has_copy = False
|
||||
|
||||
# Default repeat to false.
|
||||
if keyconfig_version <= (2, 92, 0):
|
||||
# Only copy once.
|
||||
if not has_copy:
|
||||
keyconfig_data = copy.deepcopy(keyconfig_data)
|
||||
has_copy = True
|
||||
|
@ -31,7 +31,6 @@ def keyconfig_update(keyconfig_data, keyconfig_version):
|
|||
item_event["repeat"] = True
|
||||
|
||||
if keyconfig_version <= (3, 2, 5):
|
||||
# Only copy once.
|
||||
if not has_copy:
|
||||
keyconfig_data = copy.deepcopy(keyconfig_data)
|
||||
has_copy = True
|
||||
|
@ -48,4 +47,19 @@ def keyconfig_update(keyconfig_data, keyconfig_version):
|
|||
item_event["direction"] = value
|
||||
item_event["value"] = 'CLICK_DRAG'
|
||||
|
||||
if keyconfig_version <= (3, 2, 6):
|
||||
if not has_copy:
|
||||
keyconfig_data = copy.deepcopy(keyconfig_data)
|
||||
has_copy = True
|
||||
|
||||
for _km_name, _km_parms, km_items_data in keyconfig_data:
|
||||
for (_item_op, item_event, _item_prop) in km_items_data["items"]:
|
||||
if ty_new := {
|
||||
'NDOF_BUTTON_ESC': 'ESC',
|
||||
'NDOF_BUTTON_ALT': 'LEFT_ALT',
|
||||
'NDOF_BUTTON_SHIFT': 'LEFT_SHIFT',
|
||||
'NDOF_BUTTON_CTRL': 'LEFT_CTRL',
|
||||
}.get(item_event.get("type")):
|
||||
item_event["type"] = ty_new
|
||||
|
||||
return keyconfig_data
|
||||
|
|
|
@ -580,15 +580,6 @@ class MeshPolygon(StructRNA):
|
|||
class Text(bpy_types.ID):
|
||||
__slots__ = ()
|
||||
|
||||
def as_string(self):
|
||||
"""Return the text as a string."""
|
||||
return "\n".join(line.body for line in self.lines)
|
||||
|
||||
def from_string(self, string):
|
||||
"""Replace text with this string."""
|
||||
self.clear()
|
||||
self.write(string)
|
||||
|
||||
def as_module(self):
|
||||
import bpy
|
||||
from os.path import splitext, join
|
||||
|
|
|
@ -326,6 +326,22 @@ def _template_items_hide_reveal_actions(op_hide, op_reveal):
|
|||
]
|
||||
|
||||
|
||||
def _template_object_hide_collection_from_number_keys():
|
||||
return [
|
||||
("object.hide_collection", {
|
||||
"type": NUMBERS_1[i], "value": 'PRESS',
|
||||
**({"shift": True} if extend else {}),
|
||||
**({"alt": True} if add_10 else {}),
|
||||
}, {"properties": [
|
||||
("collection_index", i + (11 if add_10 else 1)),
|
||||
("extend", extend),
|
||||
]})
|
||||
for extend in (False, True)
|
||||
for add_10 in (False, True)
|
||||
for i in range(10)
|
||||
]
|
||||
|
||||
|
||||
def _template_items_object_subdivision_set():
|
||||
return [
|
||||
("object.subdivision_set",
|
||||
|
@ -1224,7 +1240,7 @@ def km_uv_editor(params):
|
|||
("transform.shear", {"type": 'S', "value": 'PRESS', "shift": True, "ctrl": True, "alt": True}, None),
|
||||
("transform.mirror", {"type": 'M', "value": 'PRESS', "ctrl": True}, None),
|
||||
("wm.context_toggle", {"type": 'TAB', "value": 'PRESS', "shift": True},
|
||||
{"properties": [("data_path", 'tool_settings.use_snap')]}),
|
||||
{"properties": [("data_path", 'tool_settings.use_snap_uv')]}),
|
||||
("wm.context_menu_enum", {"type": 'TAB', "value": 'PRESS', "shift": True, "ctrl": True},
|
||||
{"properties": [("data_path", 'tool_settings.snap_uv_element')]}),
|
||||
*_template_items_context_menu("IMAGE_MT_uvs_context_menu", params.context_menu_event),
|
||||
|
@ -2089,7 +2105,7 @@ def km_node_editor(params):
|
|||
{"type": params.select_mouse, "value": 'CLICK_DRAG', "alt": True},
|
||||
{"properties": [("TRANSFORM_OT_translate", [("view2d_edge_pan", True)])]}),
|
||||
("wm.context_toggle", {"type": 'TAB', "value": 'PRESS', "shift": True},
|
||||
{"properties": [("data_path", 'tool_settings.use_snap')]}),
|
||||
{"properties": [("data_path", 'tool_settings.use_snap_node')]}),
|
||||
("wm.context_menu_enum", {"type": 'TAB', "value": 'PRESS', "shift": True, "ctrl": True},
|
||||
{"properties": [("data_path", 'tool_settings.snap_node_element')]}),
|
||||
("wm.context_toggle", {"type": 'Z', "value": 'PRESS', "alt": True, "shift": True},
|
||||
|
@ -4410,13 +4426,7 @@ def km_pose(params):
|
|||
("pose.breakdown", {"type": 'E', "value": 'PRESS', "shift": True}, None),
|
||||
("pose.blend_to_neighbor", {"type": 'E', "value": 'PRESS', "shift": True, "alt": True}, None),
|
||||
op_menu("VIEW3D_MT_pose_propagate", {"type": 'P', "value": 'PRESS', "alt": True}),
|
||||
*(
|
||||
(("object.hide_collection",
|
||||
{"type": NUMBERS_1[i], "value": 'PRESS', "any": True},
|
||||
{"properties": [("collection_index", i + 1)]})
|
||||
for i in range(10)
|
||||
)
|
||||
),
|
||||
*_template_object_hide_collection_from_number_keys(),
|
||||
*_template_items_context_menu("VIEW3D_MT_pose_context_menu", params.context_menu_event),
|
||||
])
|
||||
|
||||
|
@ -4486,13 +4496,7 @@ def km_object_mode(params):
|
|||
("object.link_to_collection", {"type": 'M', "value": 'PRESS', "shift": True}, None),
|
||||
*_template_items_hide_reveal_actions("object.hide_view_set", "object.hide_view_clear"),
|
||||
("object.hide_collection", {"type": 'H', "value": 'PRESS', "ctrl": True}, None),
|
||||
*(
|
||||
(("object.hide_collection",
|
||||
{"type": NUMBERS_1[i], "value": 'PRESS', "any": True},
|
||||
{"properties": [("collection_index", i + 1)]})
|
||||
for i in range(10)
|
||||
)
|
||||
),
|
||||
*_template_object_hide_collection_from_number_keys(),
|
||||
*_template_items_context_menu("VIEW3D_MT_object_context_menu", params.context_menu_event),
|
||||
])
|
||||
|
||||
|
|
|
@ -1152,7 +1152,7 @@ def km_node_editor(params):
|
|||
("node.move_detach_links_release", {"type": params.action_mouse, "value": 'CLICK_DRAG', "alt": True}, None),
|
||||
("node.move_detach_links", {"type": 'LEFTMOUSE', "value": 'CLICK_DRAG', "alt": True}, None),
|
||||
("wm.context_toggle", {"type": 'X', "value": 'PRESS'},
|
||||
{"properties": [("data_path", 'tool_settings.use_snap')]}),
|
||||
{"properties": [("data_path", 'tool_settings.use_snap_node')]}),
|
||||
])
|
||||
|
||||
return keymap
|
||||
|
|
|
@ -24,55 +24,55 @@ class MotionPathButtonsPanel:
|
|||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
# Display Range
|
||||
col = layout.column(align=True)
|
||||
col.prop(mps, "type")
|
||||
col = layout.column(align=True)
|
||||
row = layout.row(align=True)
|
||||
row.prop(mps, "type")
|
||||
if mps.type == 'RANGE':
|
||||
if bones:
|
||||
row.operator("pose.paths_range_update", text="", icon='TIME')
|
||||
else:
|
||||
row.operator("object.paths_range_update", text="", icon='TIME')
|
||||
|
||||
if mps.type == 'CURRENT_FRAME':
|
||||
col = layout.column(align=True)
|
||||
col.prop(mps, "frame_before", text="Frame Range Before")
|
||||
col.prop(mps, "frame_after", text="After")
|
||||
col.prop(mps, "frame_step", text="Step")
|
||||
|
||||
# Calculation Range
|
||||
col = layout.column(align=True)
|
||||
row = col.row(align=True)
|
||||
row.prop(mps, "range", text="Calculation Range")
|
||||
col.prop(mps, "frame_step", text="Step")
|
||||
elif mps.type == 'RANGE':
|
||||
col = layout.column(align=True)
|
||||
col.prop(mps, "frame_start", text="Frame Range Start")
|
||||
col.prop(mps, "frame_end", text="End")
|
||||
col.prop(mps, "frame_step", text="Step")
|
||||
|
||||
if mpath:
|
||||
col = layout.column(align=True)
|
||||
row = col.row(align=True)
|
||||
row.enabled = False
|
||||
row.prop(mpath, "frame_start", text="Cached Range")
|
||||
row.prop(mpath, "frame_end", text="")
|
||||
col.enabled = False
|
||||
if bones:
|
||||
col.prop(mpath, "frame_start", text="Bone Cache From")
|
||||
else:
|
||||
col.prop(mpath, "frame_start", text="Cache From")
|
||||
col.prop(mpath, "frame_end", text="To")
|
||||
|
||||
col = layout.column(align=True)
|
||||
row = col.row(align=True)
|
||||
|
||||
if bones:
|
||||
row.operator("pose.paths_update", text="Update Paths", icon='BONE_DATA')
|
||||
row.operator("pose.paths_clear", text="", icon='X').only_selected = True
|
||||
row = col.row(align=True)
|
||||
row.operator("object.paths_update_visible", text="Update All Paths", icon='WORLD')
|
||||
row.operator("pose.paths_clear", text="", icon='X').only_selected = False
|
||||
col.operator("pose.paths_update", text="Update Paths", icon='BONE_DATA')
|
||||
else:
|
||||
row.operator("object.paths_update", text="Update Paths", icon='OBJECT_DATA')
|
||||
row.operator("object.paths_clear", text="", icon='X').only_selected = True
|
||||
row = col.row(align=True)
|
||||
row.operator("object.paths_update_visible", text="Update All Paths", icon='WORLD')
|
||||
row.operator("object.paths_clear", text="", icon='X').only_selected = False
|
||||
col.operator("object.paths_update", text="Update Paths", icon='OBJECT_DATA')
|
||||
else:
|
||||
col = layout.column(align=True)
|
||||
col.label(text="No Motion Path generated yet", icon='ERROR')
|
||||
col.label(text="Nothing to show yet...", icon='ERROR')
|
||||
|
||||
# Don't invoke settings popup because settings are right above
|
||||
col.operator_context = 'EXEC_REGION_WIN'
|
||||
if bones:
|
||||
col.operator(
|
||||
"pose.paths_calculate", text="Generate for selected bones", icon='BONE_DATA')
|
||||
col.operator("pose.paths_calculate", text="Calculate...", icon='BONE_DATA')
|
||||
else:
|
||||
col.operator("object.paths_calculate", text="Generate", icon='OBJECT_DATA')
|
||||
row = col.row(align=True)
|
||||
row.operator("object.paths_update_visible", text="Update All Paths", icon='WORLD')
|
||||
row.operator("object.paths_clear", text="", icon='X').only_selected = False
|
||||
col.operator("object.paths_calculate", text="Calculate...", icon='OBJECT_DATA')
|
||||
|
||||
row = col.row(align=True)
|
||||
row.operator("object.paths_update_visible", text="Update All Paths", icon='WORLD')
|
||||
if bones:
|
||||
row.operator("pose.paths_clear", text="", icon='X')
|
||||
else:
|
||||
row.operator("object.paths_clear", text="", icon='X')
|
||||
|
||||
|
||||
class MotionPathButtonsPanel_display:
|
||||
|
|
|
@ -289,7 +289,6 @@ class DATA_PT_active_spline(CurveButtonsPanelActive, Panel):
|
|||
|
||||
if is_surf:
|
||||
subsub = sub.column()
|
||||
subsub.active = (not act_spline.use_cyclic_v)
|
||||
subsub.prop(act_spline, "use_bezier_v", text="V")
|
||||
|
||||
sub = col.column(heading="Endpoint", align=True)
|
||||
|
@ -297,7 +296,6 @@ class DATA_PT_active_spline(CurveButtonsPanelActive, Panel):
|
|||
|
||||
if is_surf:
|
||||
subsub = sub.column()
|
||||
subsub.active = (not act_spline.use_cyclic_v)
|
||||
subsub.prop(act_spline, "use_endpoint_v", text="V")
|
||||
|
||||
sub = col.column(align=True)
|
||||
|
@ -322,6 +320,17 @@ class DATA_PT_active_spline(CurveButtonsPanelActive, Panel):
|
|||
col.prop(act_spline, "radius_interpolation", text="Radius")
|
||||
|
||||
layout.prop(act_spline, "use_smooth")
|
||||
if act_spline.type == 'NURBS':
|
||||
col = None
|
||||
for direction in range(2):
|
||||
message = act_spline.valid_message(direction)
|
||||
if not message:
|
||||
continue
|
||||
if col is None:
|
||||
layout.separator()
|
||||
col = layout.column(align=True)
|
||||
col.label(text=message, icon='INFO')
|
||||
del col
|
||||
|
||||
|
||||
class DATA_PT_font(CurveButtonsPanelText, Panel):
|
||||
|
|
|
@ -43,6 +43,8 @@ class DATA_PT_curves_surface(DataButtonsPanel, Panel):
|
|||
layout = self.layout
|
||||
ob = context.object
|
||||
|
||||
layout.use_property_split = True
|
||||
|
||||
layout.prop(ob.data, "surface")
|
||||
|
||||
|
||||
|
|
|
@ -484,6 +484,18 @@ class RENDER_PT_eevee_film(RenderButtonsPanel, Panel):
|
|||
sub.prop(props, "overscan_size", text="")
|
||||
|
||||
|
||||
def draw_hair_settings(self, context):
|
||||
layout = self.layout
|
||||
scene = context.scene
|
||||
rd = scene.render
|
||||
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False # No animation.
|
||||
|
||||
layout.prop(rd, "hair_type", text="Shape", expand=True)
|
||||
layout.prop(rd, "hair_subdiv")
|
||||
|
||||
|
||||
class RENDER_PT_eevee_hair(RenderButtonsPanel, Panel):
|
||||
bl_label = "Hair"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
@ -494,14 +506,7 @@ class RENDER_PT_eevee_hair(RenderButtonsPanel, Panel):
|
|||
return (context.engine in cls.COMPAT_ENGINES)
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
scene = context.scene
|
||||
rd = scene.render
|
||||
|
||||
layout.use_property_split = True
|
||||
|
||||
layout.prop(rd, "hair_type", expand=True)
|
||||
layout.prop(rd, "hair_subdiv")
|
||||
draw_hair_settings(self, context)
|
||||
|
||||
|
||||
class RENDER_PT_eevee_performance(RenderButtonsPanel, Panel):
|
||||
|
@ -519,6 +524,7 @@ class RENDER_PT_eevee_performance(RenderButtonsPanel, Panel):
|
|||
rd = scene.render
|
||||
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False # No animation.
|
||||
|
||||
layout.prop(rd, "use_high_quality_normals")
|
||||
|
||||
|
|
|
@ -663,10 +663,6 @@ class DOPESHEET_MT_context_menu(Menu):
|
|||
layout.operator_menu_enum("action.mirror", "type", text="Mirror")
|
||||
layout.operator_menu_enum("action.snap", "type", text="Snap")
|
||||
|
||||
if st.mode == 'DOPESHEET':
|
||||
layout.separator()
|
||||
layout.menu("VIEW3D_MT_motion_path")
|
||||
|
||||
|
||||
class DOPESHEET_MT_channel_context_menu(Menu):
|
||||
bl_label = "Dope Sheet Channel Context Menu"
|
||||
|
|
|
@ -390,9 +390,6 @@ class GRAPH_MT_context_menu(Menu):
|
|||
layout.operator_menu_enum("graph.mirror", "type", text="Mirror")
|
||||
layout.operator_menu_enum("graph.snap", "type", text="Snap")
|
||||
|
||||
layout.separator()
|
||||
layout.menu("VIEW3D_MT_motion_path")
|
||||
|
||||
|
||||
class GRAPH_MT_pivot_pie(Menu):
|
||||
bl_label = "Pivot Point"
|
||||
|
|
|
@ -724,7 +724,7 @@ class IMAGE_HT_header(Header):
|
|||
act_snap_uv_element = tool_settings.bl_rna.properties['snap_uv_element'].enum_items[snap_uv_element]
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.prop(tool_settings, "use_snap", text="")
|
||||
row.prop(tool_settings, "use_snap_uv", text="")
|
||||
|
||||
sub = row.row(align=True)
|
||||
sub.popover(
|
||||
|
|
|
@ -185,7 +185,7 @@ class NODE_HT_header(Header):
|
|||
|
||||
# Snap
|
||||
row = layout.row(align=True)
|
||||
row.prop(tool_settings, "use_snap", text="")
|
||||
row.prop(tool_settings, "use_snap_node", text="")
|
||||
row.prop(tool_settings, "snap_node_element", icon_only=True)
|
||||
if tool_settings.snap_node_element != 'GRID':
|
||||
row.prop(tool_settings, "snap_target", text="")
|
||||
|
|
|
@ -55,7 +55,7 @@ ToolDef = namedtuple(
|
|||
# Description (for tool-tip), when not set, use the description of 'operator',
|
||||
# may be a string or a 'function(context, item, key-map) -> string'.
|
||||
"description",
|
||||
# The name of the icon to use (found in ``release/datafiles/icons``) or None for no icon.
|
||||
# The name of the icon to use (found in `release/datafiles/icons`) or None for no icon.
|
||||
"icon",
|
||||
# An optional cursor to use when this tool is active.
|
||||
"cursor",
|
||||
|
@ -65,12 +65,12 @@ ToolDef = namedtuple(
|
|||
"widget",
|
||||
# Optional key-map for tool, possible values are:
|
||||
#
|
||||
# - ``None`` when the tool doesn't have a key-map.
|
||||
# - `None` when the tool doesn't have a key-map.
|
||||
# Also the default value when no key-map value is defined.
|
||||
#
|
||||
# - A string literal for the key-map name, the key-map items are located in the default key-map.
|
||||
#
|
||||
# - ``()`` an empty tuple for a default name.
|
||||
# - `()` an empty tuple for a default name.
|
||||
# This is convenience functionality for generating a key-map name.
|
||||
# So if a tool name is "Bone Size", in "Edit Armature" mode for the "3D View",
|
||||
# All of these values are combined into an id, e.g:
|
||||
|
@ -82,7 +82,7 @@ ToolDef = namedtuple(
|
|||
# - A function that populates a key-maps passed in as an argument.
|
||||
#
|
||||
# - A tuple filled with triple's of:
|
||||
# ``(operator_id, operator_properties, keymap_item_args)``.
|
||||
# `(operator_id, operator_properties, keymap_item_args)`.
|
||||
#
|
||||
# Use this to define the key-map in-line.
|
||||
#
|
||||
|
|
|
@ -2262,6 +2262,7 @@ class USERPREF_PT_experimental_new_features(ExperimentalPanel, Panel):
|
|||
({"property": "use_sculpt_tools_tilt"}, "T82877"),
|
||||
({"property": "use_extended_asset_browser"}, ("project/view/130/", "Project Page")),
|
||||
({"property": "use_override_templates"}, ("T73318", "Milestone 4")),
|
||||
({"property": "use_named_attribute_nodes"}, ("T91742")),
|
||||
),
|
||||
)
|
||||
|
||||
|
|
|
@ -1248,6 +1248,7 @@ class VIEW3D_MT_view_navigation(Menu):
|
|||
layout.operator("view3d.zoom", text="Zoom In").delta = 1
|
||||
layout.operator("view3d.zoom", text="Zoom Out").delta = -1
|
||||
layout.operator("view3d.zoom_border", text="Zoom Region...")
|
||||
layout.operator("view3d.dolly", text="Dolly View...")
|
||||
layout.operator("view3d.zoom_camera_1_to_1", text="Zoom Camera 1:1")
|
||||
|
||||
layout.separator()
|
||||
|
@ -2390,25 +2391,6 @@ class VIEW3D_MT_object_clear(Menu):
|
|||
layout.operator("object.origin_clear", text="Origin")
|
||||
|
||||
|
||||
class VIEW3D_MT_motion_path(Menu):
|
||||
bl_label = "Motion Paths"
|
||||
|
||||
def draw(self, _context):
|
||||
layout = self.layout
|
||||
ob = _context.object
|
||||
if ob.mode == 'OBJECT':
|
||||
layout.operator("object.paths_calculate")
|
||||
layout.operator("object.paths_update")
|
||||
layout.operator("object.paths_update_visible")
|
||||
layout.operator("object.paths_clear", text="Clear all").only_selected = False
|
||||
layout.operator("object.paths_clear", text="Clear selected").only_selected = True
|
||||
elif ob.mode == 'POSE':
|
||||
layout.operator("pose.paths_calculate")
|
||||
layout.operator("pose.paths_update")
|
||||
layout.operator("pose.paths_clear", text="Clear all").only_selected = False
|
||||
layout.operator("pose.paths_clear", text="Clear selected").only_selected = True
|
||||
|
||||
|
||||
class VIEW3D_MT_object_context_menu(Menu):
|
||||
bl_label = "Object Context Menu"
|
||||
|
||||
|
@ -2610,7 +2592,6 @@ class VIEW3D_MT_object_context_menu(Menu):
|
|||
layout.menu("VIEW3D_MT_mirror")
|
||||
layout.menu("VIEW3D_MT_snap")
|
||||
layout.menu("VIEW3D_MT_object_parent")
|
||||
layout.menu("VIEW3D_MT_motion_path")
|
||||
layout.operator_context = 'INVOKE_REGION_WIN'
|
||||
|
||||
if view and view.local_view:
|
||||
|
@ -3658,10 +3639,10 @@ class VIEW3D_MT_pose_context_menu(Menu):
|
|||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("pose.paths_calculate")
|
||||
layout.operator("pose.paths_update")
|
||||
layout.operator("pose.paths_clear", text="Clear all").only_selected = False
|
||||
layout.operator("pose.paths_clear", text="Clear selected").only_selected = True
|
||||
layout.operator("pose.paths_calculate", text="Calculate Motion Paths")
|
||||
layout.operator("pose.paths_clear", text="Clear Motion Paths")
|
||||
layout.operator("pose.paths_update", text="Update Armature Motion Paths")
|
||||
layout.operator("object.paths_update_visible", text="Update All Motion Paths")
|
||||
|
||||
layout.separator()
|
||||
|
||||
|
@ -7513,13 +7494,20 @@ class VIEW3D_PT_sculpt_context_menu(Panel):
|
|||
UnifiedPaintPanel.prop_unified_color_picker(split, context, brush, "color", value_slider=True)
|
||||
layout.prop(brush, "blend", text="")
|
||||
|
||||
ups = context.tool_settings.unified_paint_settings
|
||||
size = "size"
|
||||
size_owner = ups if ups.use_unified_size else brush
|
||||
if size_owner.use_locked_size == 'SCENE':
|
||||
size = "unprojected_radius"
|
||||
|
||||
UnifiedPaintPanel.prop_unified(
|
||||
layout,
|
||||
context,
|
||||
brush,
|
||||
"size",
|
||||
size,
|
||||
unified_name="use_unified_size",
|
||||
pressure_name="use_pressure_size",
|
||||
text="Radius",
|
||||
slider=True,
|
||||
)
|
||||
UnifiedPaintPanel.prop_unified(
|
||||
|
@ -7650,7 +7638,6 @@ classes = (
|
|||
VIEW3D_MT_object_quick_effects,
|
||||
VIEW3D_MT_object_showhide,
|
||||
VIEW3D_MT_object_cleanup,
|
||||
VIEW3D_MT_motion_path,
|
||||
VIEW3D_MT_make_single_user,
|
||||
VIEW3D_MT_make_links,
|
||||
VIEW3D_MT_brush_paint_modes,
|
||||
|
|
|
@ -201,6 +201,8 @@ def geometry_input_node_items(context):
|
|||
yield NodeItem("ShaderNodeValue")
|
||||
yield NodeItem("FunctionNodeInputVector")
|
||||
yield NodeItemCustom(draw=lambda self, layout, context: layout.separator())
|
||||
if named_attribute_poll(context):
|
||||
yield NodeItem("GeometryNodeInputNamedAttribute")
|
||||
yield NodeItem("GeometryNodeInputID")
|
||||
yield NodeItem("GeometryNodeInputIndex")
|
||||
yield NodeItem("GeometryNodeInputNormal")
|
||||
|
@ -358,6 +360,10 @@ def geometry_nodes_legacy_poll(context):
|
|||
return context.preferences.experimental.use_geometry_nodes_legacy
|
||||
|
||||
|
||||
def named_attribute_poll(context):
|
||||
return context.preferences.experimental.use_named_attribute_nodes
|
||||
|
||||
|
||||
# All standard node categories currently used in nodes.
|
||||
|
||||
shader_node_categories = [
|
||||
|
@ -683,6 +689,8 @@ geometry_node_categories = [
|
|||
NodeItem("GeometryNodeAttributeDomainSize"),
|
||||
NodeItem("GeometryNodeAttributeStatistic"),
|
||||
NodeItem("GeometryNodeAttributeTransfer"),
|
||||
NodeItem("GeometryNodeStoreNamedAttribute", poll=named_attribute_poll),
|
||||
NodeItem("GeometryNodeRemoveAttribute", poll=named_attribute_poll),
|
||||
]),
|
||||
GeometryNodeCategory("GEO_COLOR", "Color", items=[
|
||||
NodeItem("ShaderNodeMixRGB"),
|
||||
|
|
|
@ -25,7 +25,7 @@ extern "C" {
|
|||
|
||||
/* Blender file format version. */
|
||||
#define BLENDER_FILE_VERSION BLENDER_VERSION
|
||||
#define BLENDER_FILE_SUBVERSION 5
|
||||
#define BLENDER_FILE_SUBVERSION 6
|
||||
|
||||
/* Minimum Blender version that supports reading file written with the current
|
||||
* version. Older Blender versions will test this and show a warning if the file
|
||||
|
|
|
@ -269,6 +269,14 @@ void BKE_nurb_knot_calc_v(struct Nurb *nu);
|
|||
bool BKE_nurb_check_valid_u(const struct Nurb *nu);
|
||||
bool BKE_nurb_check_valid_v(const struct Nurb *nu);
|
||||
bool BKE_nurb_check_valid_uv(const struct Nurb *nu);
|
||||
bool BKE_nurb_valid_message(int pnts,
|
||||
short order,
|
||||
short flag,
|
||||
short type,
|
||||
bool is_surf,
|
||||
const char *dir,
|
||||
char *message_dst,
|
||||
size_t maxncpy);
|
||||
|
||||
bool BKE_nurb_order_clamp_u(struct Nurb *nu);
|
||||
bool BKE_nurb_order_clamp_v(struct Nurb *nu);
|
||||
|
|
|
@ -62,7 +62,9 @@ class CurvesGeometry : public ::CurvesGeometry {
|
|||
*/
|
||||
CurvesGeometry(int point_size, int curve_size);
|
||||
CurvesGeometry(const CurvesGeometry &other);
|
||||
CurvesGeometry(CurvesGeometry &&other);
|
||||
CurvesGeometry &operator=(const CurvesGeometry &other);
|
||||
CurvesGeometry &operator=(CurvesGeometry &&other);
|
||||
~CurvesGeometry();
|
||||
|
||||
static CurvesGeometry &wrap(::CurvesGeometry &dna_struct)
|
||||
|
@ -95,6 +97,7 @@ class CurvesGeometry : public ::CurvesGeometry {
|
|||
* Access a range of indices of point data for a specific curve.
|
||||
*/
|
||||
IndexRange range_for_curve(int index) const;
|
||||
IndexRange range_for_curves(IndexRange curves) const;
|
||||
|
||||
/** The type (#CurveType) of each curve, or potentially a single if all are the same type. */
|
||||
VArray<int8_t> curve_types() const;
|
||||
|
@ -147,6 +150,8 @@ class CurvesGeometry : public ::CurvesGeometry {
|
|||
|
||||
void update_customdata_pointers();
|
||||
|
||||
void remove_curves(IndexMask curves_to_delete);
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* Attributes.
|
||||
*/
|
||||
|
|
|
@ -1392,7 +1392,7 @@ struct TexResult;
|
|||
#define GEO_NODE_LEGACY_ATTRIBUTE_COMBINE_XYZ 1027
|
||||
#define GEO_NODE_LEGACY_ATTRIBUTE_SEPARATE_XYZ 1028
|
||||
#define GEO_NODE_SUBDIVIDE_MESH 1029
|
||||
#define GEO_NODE_ATTRIBUTE_REMOVE 1030
|
||||
#define GEO_NODE_LEGACY_ATTRIBUTE_REMOVE 1030
|
||||
#define GEO_NODE_LEGACY_ATTRIBUTE_CONVERT 1031
|
||||
#define GEO_NODE_MESH_PRIMITIVE_CUBE 1032
|
||||
#define GEO_NODE_MESH_PRIMITIVE_CIRCLE 1033
|
||||
|
@ -1517,6 +1517,9 @@ struct TexResult;
|
|||
#define GEO_NODE_MERGE_BY_DISTANCE 1153
|
||||
#define GEO_NODE_DUPLICATE_ELEMENTS 1154
|
||||
#define GEO_NODE_INPUT_MESH_FACE_IS_PLANAR 1155
|
||||
#define GEO_NODE_STORE_NAMED_ATTRIBUTE 1156
|
||||
#define GEO_NODE_INPUT_NAMED_ATTRIBUTE 1157
|
||||
#define GEO_NODE_REMOVE_ATTRIBUTE 1158
|
||||
|
||||
/** \} */
|
||||
|
||||
|
|
|
@ -244,7 +244,7 @@ class Spline {
|
|||
};
|
||||
|
||||
/**
|
||||
* A Bézier spline is made up of a many curve segments, possibly achieving continuity of curvature
|
||||
* A Bezier spline is made up of a many curve segments, possibly achieving continuity of curvature
|
||||
* by constraining the alignment of curve handles. Evaluation stores the positions and a map of
|
||||
* factors and indices in a list of floats, which is then used to interpolate any other data.
|
||||
*/
|
||||
|
@ -449,22 +449,19 @@ class BezierSpline final : public Spline {
|
|||
*/
|
||||
class NURBSpline final : public Spline {
|
||||
public:
|
||||
enum class KnotsMode {
|
||||
Normal,
|
||||
EndPoint,
|
||||
Bezier,
|
||||
};
|
||||
|
||||
/** Method used to recalculate the knots vector when points are added or removed. */
|
||||
KnotsMode knots_mode;
|
||||
|
||||
struct BasisCache {
|
||||
/** The influence at each control point `i + #start_index`. */
|
||||
/**
|
||||
* For each evaluated point, the weight for all control points that influences it.
|
||||
* The vector's size is the evaluated point count multiplied by the spline's order.
|
||||
*/
|
||||
blender::Vector<float> weights;
|
||||
/**
|
||||
* An offset for the start of #weights: the first control point index with a non-zero weight.
|
||||
*/
|
||||
int start_index;
|
||||
blender::Vector<int> start_indices;
|
||||
};
|
||||
|
||||
private:
|
||||
|
@ -490,7 +487,7 @@ class NURBSpline final : public Spline {
|
|||
mutable bool knots_dirty_ = true;
|
||||
|
||||
/** Cache of control point influences on each evaluated point. */
|
||||
mutable blender::Vector<BasisCache> basis_cache_;
|
||||
mutable BasisCache basis_cache_;
|
||||
mutable std::mutex basis_cache_mutex_;
|
||||
mutable bool basis_cache_dirty_ = true;
|
||||
|
||||
|
@ -553,11 +550,11 @@ class NURBSpline final : public Spline {
|
|||
void reverse_impl() override;
|
||||
|
||||
void calculate_knots() const;
|
||||
blender::Span<BasisCache> calculate_basis_cache() const;
|
||||
const BasisCache &calculate_basis_cache() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* A Poly spline is like a Bézier spline with a resolution of one. The main reason to distinguish
|
||||
* A Poly spline is like a Bezier spline with a resolution of one. The main reason to distinguish
|
||||
* the two is for reduced complexity and increased performance, since interpolating data to control
|
||||
* points does not change it.
|
||||
*
|
||||
|
|
|
@ -14,6 +14,8 @@ struct Main;
|
|||
struct Text;
|
||||
struct TextLine;
|
||||
|
||||
#include "BLI_compiler_attrs.h"
|
||||
|
||||
/**
|
||||
* \note caller must handle `compiled` member.
|
||||
*/
|
||||
|
@ -55,7 +57,8 @@ void BKE_text_write(struct Text *text, const char *str);
|
|||
int BKE_text_file_modified_check(struct Text *text);
|
||||
void BKE_text_file_modified_ignore(struct Text *text);
|
||||
|
||||
char *txt_to_buf(struct Text *text, int *r_buf_strlen);
|
||||
char *txt_to_buf(struct Text *text, size_t *r_buf_strlen)
|
||||
ATTR_NONNULL(1, 2) ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL;
|
||||
void txt_clean_text(struct Text *text);
|
||||
void txt_order_cursors(struct Text *text, bool reverse);
|
||||
int txt_find_string(struct Text *text, const char *findstr, int wrap, int match_case);
|
||||
|
@ -89,7 +92,7 @@ void txt_sel_all(struct Text *text);
|
|||
void txt_sel_clear(struct Text *text);
|
||||
void txt_sel_line(struct Text *text);
|
||||
void txt_sel_set(struct Text *text, int startl, int startc, int endl, int endc);
|
||||
char *txt_sel_to_buf(struct Text *text, int *r_buf_strlen);
|
||||
char *txt_sel_to_buf(struct Text *text, size_t *r_buf_strlen);
|
||||
void txt_insert_buf(struct Text *text, const char *in_buffer);
|
||||
void txt_split_curline(struct Text *text);
|
||||
void txt_backspace_char(struct Text *text);
|
||||
|
@ -135,11 +138,12 @@ enum {
|
|||
/**
|
||||
* Create a buffer, the only requirement is #txt_from_buf_for_undo can decode it.
|
||||
*/
|
||||
char *txt_to_buf_for_undo(struct Text *text, int *r_buf_len);
|
||||
char *txt_to_buf_for_undo(struct Text *text, size_t *r_buf_len)
|
||||
ATTR_NONNULL(1, 2) ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL;
|
||||
/**
|
||||
* Decode a buffer from #txt_to_buf_for_undo.
|
||||
*/
|
||||
void txt_from_buf_for_undo(struct Text *text, const char *buf, int buf_len);
|
||||
void txt_from_buf_for_undo(struct Text *text, const char *buf, size_t buf_len) ATTR_NONNULL(1, 2);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -39,6 +39,8 @@ set(INC
|
|||
|
||||
# dna_type_offsets.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/../makesdna/intern
|
||||
# RNA_prototypes.h
|
||||
${CMAKE_BINARY_DIR}/source/blender/makesrna
|
||||
)
|
||||
|
||||
set(INC_SYS
|
||||
|
@ -794,6 +796,8 @@ blender_add_lib(bf_blenkernel "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
|
|||
|
||||
# Needed so we can use dna_type_offsets.h for defaults initialization.
|
||||
add_dependencies(bf_blenkernel bf_dna)
|
||||
# RNA_prototypes.h
|
||||
add_dependencies(bf_blenkernel bf_rna)
|
||||
|
||||
|
||||
if(WITH_GTESTS)
|
||||
|
@ -807,6 +811,7 @@ if(WITH_GTESTS)
|
|||
intern/asset_test.cc
|
||||
intern/bpath_test.cc
|
||||
intern/cryptomatte_test.cc
|
||||
intern/curves_geometry_test.cc
|
||||
intern/fcurve_test.cc
|
||||
intern/idprop_serialize_test.cc
|
||||
intern/image_partial_update_test.cc
|
||||
|
@ -822,4 +827,7 @@ if(WITH_GTESTS)
|
|||
)
|
||||
include(GTestTesting)
|
||||
blender_add_test_lib(bf_blenkernel_tests "${TEST_SRC}" "${INC};${TEST_INC}" "${INC_SYS}" "${LIB}")
|
||||
|
||||
# RNA_prototypes.h
|
||||
add_dependencies(bf_blenkernel_tests bf_rna)
|
||||
endif()
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
#include "BIK_api.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
#include "RNA_prototypes.h"
|
||||
|
||||
#include "BLO_read_write.h"
|
||||
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
#include "DEG_depsgraph_query.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
#include "RNA_prototypes.h"
|
||||
|
||||
#include "BLO_read_write.h"
|
||||
|
||||
|
|
|
@ -153,11 +153,6 @@ bMotionPath *animviz_verify_motionpaths(ReportList *reports,
|
|||
if ((mpath->start_frame != mpath->end_frame) && (mpath->length > 0)) {
|
||||
/* outer check ensures that we have some curve data for this path */
|
||||
if (mpath->length == expected_length) {
|
||||
/* The length might be the same, but the start and end could be different */
|
||||
if (mpath->start_frame != avs->path_sf) {
|
||||
mpath->start_frame = avs->path_sf;
|
||||
mpath->end_frame = avs->path_ef;
|
||||
}
|
||||
/* return/use this as it is already valid length */
|
||||
return mpath;
|
||||
}
|
||||
|
|
|
@ -285,7 +285,7 @@ TEST(vec_roll_to_mat3_normalized, Roll1)
|
|||
const float expected_roll_mat[3][3] = {{0.211324856f, 0.577350259f, -0.788675129f},
|
||||
{0.577350259f, 0.577350259f, 0.577350259f},
|
||||
{0.788675129f, -0.577350259f, -0.211324856f}};
|
||||
test_vec_roll_to_mat3_normalized(input, float(M_PI * 0.5), expected_roll_mat);
|
||||
test_vec_roll_to_mat3_normalized(input, float(M_PI_2), expected_roll_mat);
|
||||
}
|
||||
|
||||
/** Test that the matrix is orthogonal for an input close to -Y. */
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
#include "RNA_prototypes.h"
|
||||
#include "RNA_types.h"
|
||||
|
||||
static ListBase callback_slots[BKE_CB_EVT_TOT] = {{NULL}};
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include "RE_engine.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
#include "RNA_prototypes.h"
|
||||
|
||||
#include "CLG_log.h"
|
||||
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
#include "BLI_index_range.hh"
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_math_vec_types.hh"
|
||||
#include "BLI_string.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "BLT_translation.h"
|
||||
|
||||
/* Allow using deprecated functionality for .blend file I/O. */
|
||||
|
@ -1156,12 +1156,13 @@ void BKE_nurb_bpoint_calc_plane(struct Nurb *nu, BPoint *bp, float r_plane[3])
|
|||
static void calcknots(float *knots, const int pnts, const short order, const short flag)
|
||||
{
|
||||
const bool is_cyclic = flag & CU_NURB_CYCLIC;
|
||||
const bool is_bezier = flag & CU_NURB_BEZIER && !(flag & CU_NURB_ENDPOINT);
|
||||
const bool is_end_point = flag & CU_NURB_ENDPOINT && !(flag & CU_NURB_BEZIER);
|
||||
const bool is_bezier = flag & CU_NURB_BEZIER;
|
||||
const bool is_end_point = flag & CU_NURB_ENDPOINT;
|
||||
/* Inner knots are always repeated once except on Bezier case. */
|
||||
const int repeat_inner = is_bezier ? order - 1 : 1;
|
||||
/* How many times to repeat 0.0 at the beginning of knot. */
|
||||
const int head = is_end_point && !is_cyclic ? order : (is_bezier ? order / 2 : 1);
|
||||
const int head = is_end_point ? (order - (is_cyclic ? 1 : 0)) :
|
||||
(is_bezier ? min_ii(2, repeat_inner) : 1);
|
||||
/* Number of knots replicating widths of the starting knots.
|
||||
* Covers both Cyclic and EndPoint cases. */
|
||||
const int tail = is_cyclic ? 2 * order - 1 : (is_end_point ? order : 0);
|
||||
|
@ -1171,11 +1172,17 @@ static void calcknots(float *knots, const int pnts, const short order, const sho
|
|||
int r = head;
|
||||
float current = 0.0f;
|
||||
|
||||
for (const int i : IndexRange(knot_count - tail)) {
|
||||
const int offset = is_end_point && is_cyclic ? 1 : 0;
|
||||
if (offset) {
|
||||
knots[0] = current;
|
||||
current += 1.0f;
|
||||
}
|
||||
|
||||
for (const int i : IndexRange(offset, knot_count - offset - tail)) {
|
||||
knots[i] = current;
|
||||
r--;
|
||||
if (r == 0) {
|
||||
current += 1.0;
|
||||
current += 1.0f;
|
||||
r = repeat_inner;
|
||||
}
|
||||
}
|
||||
|
@ -4693,59 +4700,56 @@ void BKE_curve_nurbs_key_vert_tilts_apply(ListBase *lb, const float *key)
|
|||
}
|
||||
}
|
||||
|
||||
bool BKE_nurb_valid_message(const int pnts,
|
||||
const short order,
|
||||
const short flag,
|
||||
const short type,
|
||||
const bool is_surf,
|
||||
const char *dir,
|
||||
char *message_dst,
|
||||
const size_t maxncpy)
|
||||
{
|
||||
const char *msg_template = "";
|
||||
uint16_t points_needed = 0;
|
||||
|
||||
if (pnts <= 1) {
|
||||
msg_template = TIP_("At least two points required.");
|
||||
}
|
||||
else if (type == CU_NURBS) {
|
||||
if (pnts < order) {
|
||||
msg_template = TIP_("Must have more control points than Order");
|
||||
}
|
||||
else if (flag & CU_NURB_BEZIER) {
|
||||
if (flag & CU_NURB_CYCLIC) {
|
||||
const uint16_t remainder = pnts % (order - 1);
|
||||
points_needed = remainder > 0 ? order - 1 - remainder : 0;
|
||||
}
|
||||
else if (((flag & CU_NURB_ENDPOINT) == 0) && pnts <= order) {
|
||||
points_needed = order + 1 - pnts;
|
||||
}
|
||||
if (points_needed) {
|
||||
msg_template = is_surf ? TIP_("%d more %s row(s) needed for Bezier") :
|
||||
TIP_("%d more point(s) needed for Bezier");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (message_dst) {
|
||||
BLI_snprintf(message_dst, maxncpy, msg_template, points_needed, dir);
|
||||
}
|
||||
return msg_template[0];
|
||||
}
|
||||
|
||||
bool BKE_nurb_check_valid_u(const Nurb *nu)
|
||||
{
|
||||
if (nu->pntsu <= 1) {
|
||||
return false;
|
||||
}
|
||||
if (nu->type != CU_NURBS) {
|
||||
return true; /* not a nurb, lets assume its valid */
|
||||
}
|
||||
|
||||
if (nu->pntsu < nu->orderu) {
|
||||
return false;
|
||||
}
|
||||
if (((nu->flagu & CU_NURB_CYCLIC) == 0) && (nu->flagu & CU_NURB_BEZIER)) {
|
||||
/* Bezier U Endpoints */
|
||||
if (nu->orderu == 4) {
|
||||
if (nu->pntsu < 5) {
|
||||
return false; /* bezier with 4 orderu needs 5 points */
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (nu->orderu != 3) {
|
||||
return false; /* order must be 3 or 4 */
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return !BKE_nurb_valid_message(
|
||||
nu->pntsu, nu->orderu, nu->flagu, nu->type, nu->pntsv > 1, "U", nullptr, 0);
|
||||
}
|
||||
|
||||
bool BKE_nurb_check_valid_v(const Nurb *nu)
|
||||
{
|
||||
if (nu->pntsv <= 1) {
|
||||
return false;
|
||||
}
|
||||
if (nu->type != CU_NURBS) {
|
||||
return true; /* not a nurb, lets assume its valid */
|
||||
}
|
||||
|
||||
if (nu->pntsv < nu->orderv) {
|
||||
return false;
|
||||
}
|
||||
if (((nu->flagv & CU_NURB_CYCLIC) == 0) && (nu->flagv & CU_NURB_BEZIER)) {
|
||||
/* Bezier V Endpoints */
|
||||
if (nu->orderv == 4) {
|
||||
if (nu->pntsv < 5) {
|
||||
return false; /* bezier with 4 orderu needs 5 points */
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (nu->orderv != 3) {
|
||||
return false; /* order must be 3 or 4 */
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return !BKE_nurb_valid_message(
|
||||
nu->pntsv, nu->orderv, nu->flagv, nu->type, nu->pntsv > 1, "V", nullptr, 0);
|
||||
}
|
||||
|
||||
bool BKE_nurb_check_valid_uv(const Nurb *nu)
|
||||
|
@ -4767,10 +4771,6 @@ bool BKE_nurb_order_clamp_u(struct Nurb *nu)
|
|||
nu->orderu = max_ii(2, nu->pntsu);
|
||||
changed = true;
|
||||
}
|
||||
if (((nu->flagu & CU_NURB_CYCLIC) == 0) && (nu->flagu & CU_NURB_BEZIER)) {
|
||||
CLAMP(nu->orderu, 3, 4);
|
||||
changed = true;
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
|
@ -4781,10 +4781,6 @@ bool BKE_nurb_order_clamp_v(struct Nurb *nu)
|
|||
nu->orderv = max_ii(2, nu->pntsv);
|
||||
changed = true;
|
||||
}
|
||||
if (((nu->flagv & CU_NURB_CYCLIC) == 0) && (nu->flagv & CU_NURB_BEZIER)) {
|
||||
CLAMP(nu->orderv, 3, 4);
|
||||
changed = true;
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
|
|
|
@ -203,19 +203,21 @@ static Spline::NormalCalculationMode normal_mode_from_dna_curve(const int twist_
|
|||
return Spline::NormalCalculationMode::Minimum;
|
||||
}
|
||||
|
||||
static NURBSpline::KnotsMode knots_mode_from_dna_nurb(const short flag)
|
||||
static KnotsMode knots_mode_from_dna_nurb(const short flag)
|
||||
{
|
||||
switch (flag & (CU_NURB_ENDPOINT | CU_NURB_BEZIER)) {
|
||||
case CU_NURB_ENDPOINT:
|
||||
return NURBSpline::KnotsMode::EndPoint;
|
||||
return NURBS_KNOT_MODE_ENDPOINT;
|
||||
case CU_NURB_BEZIER:
|
||||
return NURBSpline::KnotsMode::Bezier;
|
||||
return NURBS_KNOT_MODE_BEZIER;
|
||||
case CU_NURB_ENDPOINT | CU_NURB_BEZIER:
|
||||
return NURBS_KNOT_MODE_ENDPOINT_BEZIER;
|
||||
default:
|
||||
return NURBSpline::KnotsMode::Normal;
|
||||
return NURBS_KNOT_MODE_NORMAL;
|
||||
}
|
||||
|
||||
BLI_assert_unreachable();
|
||||
return NURBSpline::KnotsMode::Normal;
|
||||
return NURBS_KNOT_MODE_NORMAL;
|
||||
}
|
||||
|
||||
static SplinePtr spline_from_dna_bezier(const Nurb &nurb)
|
||||
|
@ -419,8 +421,7 @@ std::unique_ptr<CurveEval> curves_to_curve_eval(const Curves &curves)
|
|||
nurb_spline->resize(point_range.size());
|
||||
nurb_spline->weights().copy_from(nurbs_weights.slice(point_range));
|
||||
nurb_spline->set_order(nurbs_orders[curve_index]);
|
||||
nurb_spline->knots_mode = static_cast<NURBSpline::KnotsMode>(
|
||||
nurbs_knots_modes[curve_index]);
|
||||
nurb_spline->knots_mode = static_cast<KnotsMode>(nurbs_knots_modes[curve_index]);
|
||||
|
||||
spline = std::move(nurb_spline);
|
||||
break;
|
||||
|
|
|
@ -84,6 +84,42 @@ CurvesGeometry &CurvesGeometry::operator=(const CurvesGeometry &other)
|
|||
return *this;
|
||||
}
|
||||
|
||||
/* The source should be empty, but in a valid state so that using it further will work. */
|
||||
static void move_curves_geometry(CurvesGeometry &dst, CurvesGeometry &src)
|
||||
{
|
||||
dst.point_size = src.point_size;
|
||||
std::swap(dst.point_data, src.point_data);
|
||||
CustomData_free(&src.point_data, src.point_size);
|
||||
src.point_size = 0;
|
||||
|
||||
dst.curve_size = src.curve_size;
|
||||
std::swap(dst.curve_data, dst.curve_data);
|
||||
CustomData_free(&src.curve_data, src.curve_size);
|
||||
src.curve_size = 0;
|
||||
|
||||
std::swap(dst.curve_offsets, src.curve_offsets);
|
||||
MEM_SAFE_FREE(src.curve_offsets);
|
||||
|
||||
std::swap(dst.runtime, src.runtime);
|
||||
|
||||
src.update_customdata_pointers();
|
||||
dst.update_customdata_pointers();
|
||||
}
|
||||
|
||||
CurvesGeometry::CurvesGeometry(CurvesGeometry &&other)
|
||||
: CurvesGeometry(other.point_size, other.curve_size)
|
||||
{
|
||||
move_curves_geometry(*this, other);
|
||||
}
|
||||
|
||||
CurvesGeometry &CurvesGeometry::operator=(CurvesGeometry &&other)
|
||||
{
|
||||
if (this != &other) {
|
||||
move_curves_geometry(*this, other);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
CurvesGeometry::~CurvesGeometry()
|
||||
{
|
||||
CustomData_free(&this->point_data, this->point_size);
|
||||
|
@ -124,11 +160,22 @@ int CurvesGeometry::evaluated_points_size() const
|
|||
|
||||
IndexRange CurvesGeometry::range_for_curve(const int index) const
|
||||
{
|
||||
BLI_assert(this->curve_size > 0);
|
||||
BLI_assert(this->curve_offsets != nullptr);
|
||||
const int offset = this->curve_offsets[index];
|
||||
const int offset_next = this->curve_offsets[index + 1];
|
||||
return {offset, offset_next - offset};
|
||||
}
|
||||
|
||||
IndexRange CurvesGeometry::range_for_curves(const IndexRange curves) const
|
||||
{
|
||||
BLI_assert(this->curve_size > 0);
|
||||
BLI_assert(this->curve_offsets != nullptr);
|
||||
const int offset = this->curve_offsets[curves.start()];
|
||||
const int offset_next = this->curve_offsets[curves.one_after_last()];
|
||||
return {offset, offset_next - offset};
|
||||
}
|
||||
|
||||
static int domain_size(const CurvesGeometry &curves, const AttributeDomain domain)
|
||||
{
|
||||
return domain == ATTR_DOMAIN_POINT ? curves.points_size() : curves.curves_size();
|
||||
|
@ -305,6 +352,134 @@ void CurvesGeometry::update_customdata_pointers()
|
|||
&this->point_data, CD_PROP_INT8, ATTR_CURVE_TYPE.c_str());
|
||||
}
|
||||
|
||||
static void *ensure_customdata_layer(CustomData &custom_data,
|
||||
const StringRefNull name,
|
||||
const CustomDataType data_type,
|
||||
const int tot_elements)
|
||||
{
|
||||
for (const int other_layer_i : IndexRange(custom_data.totlayer)) {
|
||||
CustomDataLayer &new_layer = custom_data.layers[other_layer_i];
|
||||
if (name == StringRef(new_layer.name)) {
|
||||
return new_layer.data;
|
||||
}
|
||||
}
|
||||
return CustomData_add_layer_named(
|
||||
&custom_data, data_type, CD_DEFAULT, nullptr, tot_elements, name.c_str());
|
||||
}
|
||||
|
||||
static CurvesGeometry copy_with_removed_curves(const CurvesGeometry &curves,
|
||||
const IndexMask curves_to_delete)
|
||||
{
|
||||
const Span<int> old_offsets = curves.offsets();
|
||||
const Vector<IndexRange> old_curve_ranges = curves_to_delete.extract_ranges_invert(
|
||||
curves.curves_range(), nullptr);
|
||||
Vector<IndexRange> new_curve_ranges;
|
||||
Vector<IndexRange> old_point_ranges;
|
||||
Vector<IndexRange> new_point_ranges;
|
||||
int new_tot_points = 0;
|
||||
int new_tot_curves = 0;
|
||||
for (const IndexRange &curve_range : old_curve_ranges) {
|
||||
new_curve_ranges.append(IndexRange(new_tot_curves, curve_range.size()));
|
||||
new_tot_curves += curve_range.size();
|
||||
|
||||
const IndexRange old_point_range = curves.range_for_curves(curve_range);
|
||||
old_point_ranges.append(old_point_range);
|
||||
new_point_ranges.append(IndexRange(new_tot_points, old_point_range.size()));
|
||||
new_tot_points += old_point_range.size();
|
||||
}
|
||||
|
||||
CurvesGeometry new_curves{new_tot_points, new_tot_curves};
|
||||
|
||||
threading::parallel_invoke(
|
||||
/* Initialize curve offsets. */
|
||||
[&]() {
|
||||
MutableSpan<int> new_offsets = new_curves.offsets();
|
||||
new_offsets.last() = new_tot_points;
|
||||
threading::parallel_for(
|
||||
old_curve_ranges.index_range(), 128, [&](const IndexRange ranges_range) {
|
||||
for (const int range_i : ranges_range) {
|
||||
const IndexRange old_curve_range = old_curve_ranges[range_i];
|
||||
const IndexRange new_curve_range = new_curve_ranges[range_i];
|
||||
const IndexRange old_point_range = old_point_ranges[range_i];
|
||||
const IndexRange new_point_range = new_point_ranges[range_i];
|
||||
const int offset_shift = new_point_range.start() - old_point_range.start();
|
||||
const int curves_in_range = old_curve_range.size();
|
||||
threading::parallel_for(
|
||||
IndexRange(curves_in_range), 512, [&](const IndexRange range) {
|
||||
for (const int i : range) {
|
||||
const int old_curve_i = old_curve_range[i];
|
||||
const int new_curve_i = new_curve_range[i];
|
||||
const int old_offset = old_offsets[old_curve_i];
|
||||
const int new_offset = old_offset + offset_shift;
|
||||
new_offsets[new_curve_i] = new_offset;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
/* Copy over point attributes. */
|
||||
[&]() {
|
||||
const CustomData &old_point_data = curves.point_data;
|
||||
CustomData &new_point_data = new_curves.point_data;
|
||||
for (const int layer_i : IndexRange(old_point_data.totlayer)) {
|
||||
const CustomDataLayer &old_layer = old_point_data.layers[layer_i];
|
||||
const CustomDataType data_type = static_cast<CustomDataType>(old_layer.type);
|
||||
const CPPType &type = *bke::custom_data_type_to_cpp_type(data_type);
|
||||
|
||||
const void *src_buffer = old_layer.data;
|
||||
void *dst_buffer = ensure_customdata_layer(
|
||||
new_point_data, old_layer.name, data_type, new_tot_points);
|
||||
|
||||
threading::parallel_for(
|
||||
old_curve_ranges.index_range(), 128, [&](const IndexRange ranges_range) {
|
||||
for (const int range_i : ranges_range) {
|
||||
const IndexRange old_point_range = old_point_ranges[range_i];
|
||||
const IndexRange new_point_range = new_point_ranges[range_i];
|
||||
|
||||
type.copy_construct_n(
|
||||
POINTER_OFFSET(src_buffer, type.size() * old_point_range.start()),
|
||||
POINTER_OFFSET(dst_buffer, type.size() * new_point_range.start()),
|
||||
old_point_range.size());
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
/* Copy over curve attributes. */
|
||||
[&]() {
|
||||
const CustomData &old_curve_data = curves.curve_data;
|
||||
CustomData &new_curve_data = new_curves.curve_data;
|
||||
for (const int layer_i : IndexRange(old_curve_data.totlayer)) {
|
||||
const CustomDataLayer &old_layer = old_curve_data.layers[layer_i];
|
||||
const CustomDataType data_type = static_cast<CustomDataType>(old_layer.type);
|
||||
const CPPType &type = *bke::custom_data_type_to_cpp_type(data_type);
|
||||
|
||||
const void *src_buffer = old_layer.data;
|
||||
void *dst_buffer = ensure_customdata_layer(
|
||||
new_curve_data, old_layer.name, data_type, new_tot_points);
|
||||
|
||||
threading::parallel_for(
|
||||
old_curve_ranges.index_range(), 128, [&](const IndexRange ranges_range) {
|
||||
for (const int range_i : ranges_range) {
|
||||
const IndexRange old_curve_range = old_curve_ranges[range_i];
|
||||
const IndexRange new_curve_range = new_curve_ranges[range_i];
|
||||
|
||||
type.copy_construct_n(
|
||||
POINTER_OFFSET(src_buffer, type.size() * old_curve_range.start()),
|
||||
POINTER_OFFSET(dst_buffer, type.size() * new_curve_range.start()),
|
||||
old_curve_range.size());
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return new_curves;
|
||||
}
|
||||
|
||||
void CurvesGeometry::remove_curves(const IndexMask curves_to_delete)
|
||||
{
|
||||
*this = copy_with_removed_curves(*this, curves_to_delete);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup bke
|
||||
*/
|
||||
|
||||
#include "BKE_curves.hh"
|
||||
|
||||
#include "testing/testing.h"
|
||||
|
||||
namespace blender::bke::tests {
|
||||
|
||||
static CurvesGeometry create_basic_curves(const int points_size, const int curves_size)
|
||||
{
|
||||
CurvesGeometry curves(points_size, curves_size);
|
||||
|
||||
const int curve_length = points_size / curves_size;
|
||||
for (const int i : curves.curves_range()) {
|
||||
curves.offsets()[i] = points_size * curve_length;
|
||||
}
|
||||
curves.offsets().last() = points_size;
|
||||
|
||||
for (const int i : curves.points_range()) {
|
||||
curves.positions()[i] = {float(i), float(i % curve_length), 0.0f};
|
||||
}
|
||||
|
||||
return curves;
|
||||
}
|
||||
|
||||
TEST(curves_geometry, Empty)
|
||||
{
|
||||
CurvesGeometry empty(0, 0);
|
||||
empty.cyclic();
|
||||
float3 min;
|
||||
float3 max;
|
||||
EXPECT_FALSE(empty.bounds_min_max(min, max));
|
||||
}
|
||||
|
||||
TEST(curves_geometry, Move)
|
||||
{
|
||||
CurvesGeometry curves = create_basic_curves(100, 10);
|
||||
|
||||
const int *offsets_data = curves.offsets().data();
|
||||
const float3 *positions_data = curves.positions().data();
|
||||
|
||||
CurvesGeometry other = std::move(curves);
|
||||
|
||||
/* The old curves should be empty, and the offsets are expected to be null. */
|
||||
EXPECT_EQ(curves.points_size(), 0); /* NOLINT: bugprone-use-after-move */
|
||||
EXPECT_EQ(curves.curve_offsets, nullptr); /* NOLINT: bugprone-use-after-move */
|
||||
|
||||
/* Just a basic check that the new curves work okay. */
|
||||
float3 min;
|
||||
float3 max;
|
||||
EXPECT_TRUE(other.bounds_min_max(min, max));
|
||||
|
||||
curves = std::move(other);
|
||||
|
||||
CurvesGeometry second_other(std::move(curves));
|
||||
|
||||
/* The data should not have been reallocated ever. */
|
||||
EXPECT_EQ(second_other.positions().data(), positions_data);
|
||||
EXPECT_EQ(second_other.offsets().data(), offsets_data);
|
||||
}
|
||||
|
||||
} // namespace blender::bke::tests
|
|
@ -1049,6 +1049,11 @@ class VertexGroupsAttributeProvider final : public DynamicAttributesProvider {
|
|||
if (mesh->dvert == nullptr) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Copy the data layer if it is shared with some other mesh. */
|
||||
mesh->dvert = (MDeformVert *)CustomData_duplicate_referenced_layer(
|
||||
&mesh->vdata, CD_MDEFORMVERT, mesh->totvert);
|
||||
|
||||
for (MDeformVert &dvert : MutableSpan(mesh->dvert, mesh->totvert)) {
|
||||
MDeformWeight *weight = BKE_defvert_find_index(&dvert, index);
|
||||
BKE_defvert_remove_group(&dvert, weight);
|
||||
|
|
|
@ -2032,7 +2032,7 @@ void BKE_gpencil_stroke_simplify_adaptive(bGPdata *gpd, bGPDstroke *gps, float e
|
|||
|
||||
void BKE_gpencil_stroke_simplify_fixed(bGPdata *gpd, bGPDstroke *gps)
|
||||
{
|
||||
if (gps->totpoints < 5) {
|
||||
if (gps->totpoints < 4) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2047,7 +2047,7 @@ void BKE_gpencil_stroke_simplify_fixed(bGPdata *gpd, bGPDstroke *gps)
|
|||
|
||||
/* resize gps */
|
||||
int newtot = (gps->totpoints - 2) / 2;
|
||||
if (((gps->totpoints - 2) % 2) > 0) {
|
||||
if ((gps->totpoints % 2) != 0) {
|
||||
newtot++;
|
||||
}
|
||||
newtot += 2;
|
||||
|
|
|
@ -109,7 +109,11 @@ static void image_init(Image *ima, short source, short type);
|
|||
static void image_free_packedfiles(Image *ima);
|
||||
static void copy_image_packedfiles(ListBase *lb_dst, const ListBase *lb_src);
|
||||
|
||||
/* Reset runtime image fields when data-block is being initialized. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Image #IDTypeInfo API
|
||||
* \{ */
|
||||
|
||||
/** Reset runtime image fields when data-block is being initialized. */
|
||||
static void image_runtime_reset(struct Image *image)
|
||||
{
|
||||
memset(&image->runtime, 0, sizeof(image->runtime));
|
||||
|
@ -117,7 +121,7 @@ static void image_runtime_reset(struct Image *image)
|
|||
BLI_mutex_init(static_cast<ThreadMutex *>(image->runtime.cache_mutex));
|
||||
}
|
||||
|
||||
/* Reset runtime image fields when data-block is being copied. */
|
||||
/** Reset runtime image fields when data-block is being copied. */
|
||||
static void image_runtime_reset_on_copy(struct Image *image)
|
||||
{
|
||||
image->runtime.cache_mutex = MEM_mallocN(sizeof(ThreadMutex), "image runtime cache_mutex");
|
||||
|
@ -479,7 +483,11 @@ static void image_add_view(Image *ima, const char *viewname, const char *filepat
|
|||
# define IMA_INDEX_PASS(index) (index & ~1023)
|
||||
#endif
|
||||
|
||||
/* ******** IMAGE CACHE ************* */
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Image Cache
|
||||
* \{ */
|
||||
|
||||
typedef struct ImageCacheKey {
|
||||
int index;
|
||||
|
@ -548,7 +556,11 @@ static struct ImBuf *imagecache_get(Image *image, int index, bool *r_is_cached_e
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
/* ***************** ALLOC & FREE, DATA MANAGING *************** */
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Allocate & Free, Data Managing
|
||||
* \{ */
|
||||
|
||||
static void image_free_cached_frames(Image *image)
|
||||
{
|
||||
|
@ -666,12 +678,12 @@ static Image *image_alloc(Main *bmain, const char *name, short source, short typ
|
|||
return ima;
|
||||
}
|
||||
|
||||
/* Get the ibuf from an image cache by its index and entry.
|
||||
/**
|
||||
* Get the ibuf from an image cache by its index and entry.
|
||||
* Local use here only.
|
||||
*
|
||||
* Returns referenced image buffer if it exists, callee is to
|
||||
* call IMB_freeImBuf to de-reference the image buffer after
|
||||
* it's done handling it.
|
||||
* \returns referenced image buffer if it exists, callee is to call #IMB_freeImBuf
|
||||
* to de-reference the image buffer after it's done handling it.
|
||||
*/
|
||||
static ImBuf *image_get_cached_ibuf_for_index_entry(Image *ima,
|
||||
int index,
|
||||
|
@ -1112,7 +1124,7 @@ Image *BKE_image_add_generated(Main *bmain,
|
|||
const bool is_data,
|
||||
const bool tiled)
|
||||
{
|
||||
/* on save, type is changed to FILE in editsima.c */
|
||||
/* Saving the image changes it's #Image.source to #IMA_SRC_FILE (leave as generated here). */
|
||||
Image *ima;
|
||||
if (tiled) {
|
||||
ima = image_alloc(bmain, name, IMA_SRC_TILED, IMA_TYPE_IMAGE);
|
||||
|
@ -1127,7 +1139,8 @@ Image *BKE_image_add_generated(Main *bmain,
|
|||
int view_id;
|
||||
const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME};
|
||||
|
||||
// STRNCPY(ima->filepath, name); /* don't do this, this writes in ain invalid filepath! */
|
||||
/* NOTE: leave `ima->filepath` unset,
|
||||
* setting it to a dummy value may write to an invalid file-path. */
|
||||
ima->gen_x = width;
|
||||
ima->gen_y = height;
|
||||
ima->gen_type = gen_type;
|
||||
|
@ -1148,7 +1161,7 @@ Image *BKE_image_add_generated(Main *bmain,
|
|||
int entry = tiled ? 1001 : 0;
|
||||
image_assign_ibuf(ima, ibuf, stereo3d ? view_id : index, entry);
|
||||
|
||||
/* image_assign_ibuf puts buffer to the cache, which increments user counter. */
|
||||
/* #image_assign_ibuf puts buffer to the cache, which increments user counter. */
|
||||
IMB_freeImBuf(ibuf);
|
||||
if (!stereo3d) {
|
||||
break;
|
||||
|
@ -1162,7 +1175,6 @@ Image *BKE_image_add_generated(Main *bmain,
|
|||
|
||||
Image *BKE_image_add_from_imbuf(Main *bmain, ImBuf *ibuf, const char *name)
|
||||
{
|
||||
/* on save, type is changed to FILE in editsima.c */
|
||||
Image *ima;
|
||||
|
||||
if (name == nullptr) {
|
||||
|
@ -1179,7 +1191,7 @@ Image *BKE_image_add_from_imbuf(Main *bmain, ImBuf *ibuf, const char *name)
|
|||
return ima;
|
||||
}
|
||||
|
||||
/* Pack image buffer to memory as PNG or EXR. */
|
||||
/** Pack image buffer to memory as PNG or EXR. */
|
||||
static bool image_memorypack_imbuf(Image *ima, ImBuf *ibuf, const char *filepath)
|
||||
{
|
||||
ibuf->ftype = (ibuf->rect_float) ? IMB_FTYPE_OPENEXR : IMB_FTYPE_PNG;
|
||||
|
@ -1472,7 +1484,11 @@ void BKE_image_all_free_anim_ibufs(Main *bmain, int cfra)
|
|||
}
|
||||
}
|
||||
|
||||
/* *********** READ AND WRITE ************** */
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Read and Write
|
||||
* \{ */
|
||||
|
||||
int BKE_image_imtype_to_ftype(const char imtype, ImbFormatOptions *r_options)
|
||||
{
|
||||
|
@ -1607,7 +1623,7 @@ bool BKE_imtype_supports_zbuf(const char imtype)
|
|||
{
|
||||
switch (imtype) {
|
||||
case R_IMF_IMTYPE_IRIZ:
|
||||
case R_IMF_IMTYPE_OPENEXR: /* but not R_IMF_IMTYPE_MULTILAYER */
|
||||
case R_IMF_IMTYPE_OPENEXR: /* But not #R_IMF_IMTYPE_MULTILAYER. */
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -1698,7 +1714,7 @@ char BKE_imtype_valid_depths(const char imtype)
|
|||
return R_IMF_CHAN_DEPTH_16 | R_IMF_CHAN_DEPTH_32;
|
||||
case R_IMF_IMTYPE_MULTILAYER:
|
||||
return R_IMF_CHAN_DEPTH_16 | R_IMF_CHAN_DEPTH_32;
|
||||
/* eeh, cineon does some strange 10bits per channel */
|
||||
/* NOTE: CINEON uses an unusual 10bits-LOG per channel. */
|
||||
case R_IMF_IMTYPE_DPX:
|
||||
return R_IMF_CHAN_DEPTH_8 | R_IMF_CHAN_DEPTH_10 | R_IMF_CHAN_DEPTH_12 | R_IMF_CHAN_DEPTH_16;
|
||||
case R_IMF_IMTYPE_CINEON:
|
||||
|
@ -1707,7 +1723,7 @@ char BKE_imtype_valid_depths(const char imtype)
|
|||
return R_IMF_CHAN_DEPTH_8 | R_IMF_CHAN_DEPTH_12 | R_IMF_CHAN_DEPTH_16;
|
||||
case R_IMF_IMTYPE_PNG:
|
||||
return R_IMF_CHAN_DEPTH_8 | R_IMF_CHAN_DEPTH_16;
|
||||
/* most formats are 8bit only */
|
||||
/* Most formats are 8bit only. */
|
||||
default:
|
||||
return R_IMF_CHAN_DEPTH_8;
|
||||
}
|
||||
|
@ -2704,7 +2720,7 @@ void BKE_image_stamp_buf(Scene *scene,
|
|||
|
||||
if (TEXT_SIZE_CHECK(stamp_data.scene, w, h)) {
|
||||
|
||||
/* Bottom right corner, with an extra space because blenfont is too strict! */
|
||||
/* Bottom right corner, with an extra space because the BLF API is too strict! */
|
||||
x = width - w - 2;
|
||||
|
||||
/* extra space for background. */
|
||||
|
@ -2726,7 +2742,7 @@ void BKE_image_stamp_buf(Scene *scene,
|
|||
|
||||
if (TEXT_SIZE_CHECK(stamp_data.strip, w, h)) {
|
||||
|
||||
/* Top right corner, with an extra space because blenfont is too strict! */
|
||||
/* Top right corner, with an extra space because the BLF API is too strict! */
|
||||
x = width - w - pad;
|
||||
y = height - h;
|
||||
|
||||
|
@ -3131,7 +3147,7 @@ void BKE_imbuf_write_prepare(ImBuf *ibuf, const ImageFormatData *imf)
|
|||
}
|
||||
#endif
|
||||
else {
|
||||
/* R_IMF_IMTYPE_JPEG90, etc. default we save jpegs */
|
||||
/* #R_IMF_IMTYPE_JPEG90, etc. fallback to JPEG image. */
|
||||
if (quality < 10) {
|
||||
quality = 90;
|
||||
}
|
||||
|
@ -3278,7 +3294,11 @@ struct anim *openanim(const char *name, int flags, int streamindex, char colorsp
|
|||
return anim;
|
||||
}
|
||||
|
||||
/* ************************* New Image API *************** */
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name New Image API
|
||||
* \{ */
|
||||
|
||||
/* Notes about Image storage
|
||||
* - packedfile
|
||||
|
@ -3290,8 +3310,8 @@ struct anim *openanim(const char *name, int flags, int streamindex, char colorsp
|
|||
* - renderresult
|
||||
* -> comes from packedfile or filename
|
||||
* - listbase
|
||||
* -> ibufs from exrhandle
|
||||
* - flipbook array
|
||||
* -> ibufs from EXR-handle.
|
||||
* - flip-book array
|
||||
* -> ibufs come from movie, temporary renderresult or sequence
|
||||
* - ibuf
|
||||
* -> comes from packedfile or filename or generated
|
||||
|
@ -3834,8 +3854,10 @@ void BKE_image_signal(Main *bmain, Image *ima, ImageUser *iuser, int signal)
|
|||
BKE_ntree_update_main(bmain, nullptr);
|
||||
}
|
||||
|
||||
/* return renderpass for a given pass index and active view */
|
||||
/* fallback to available if there are missing passes for active view */
|
||||
/**
|
||||
* \return render-pass for a given pass index and active view.
|
||||
* fallback to available if there are missing passes for active view.
|
||||
*/
|
||||
static RenderPass *image_render_pass_get(RenderLayer *rl,
|
||||
const int pass,
|
||||
const int view,
|
||||
|
@ -4477,7 +4499,11 @@ void BKE_image_backup_render(Scene *scene, Image *ima, bool free_current_slot)
|
|||
ima->last_render_slot = ima->render_slot;
|
||||
}
|
||||
|
||||
/**************************** multiview load openexr *********************************/
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Multiview Load OpenEXR
|
||||
* \{ */
|
||||
|
||||
static void image_add_view(Image *ima, const char *viewname, const char *filepath)
|
||||
{
|
||||
|
@ -4510,8 +4536,8 @@ static void image_add_view(Image *ima, const char *viewname, const char *filepat
|
|||
}
|
||||
}
|
||||
|
||||
/* after imbuf load, openexr type can return with a exrhandle open */
|
||||
/* in that case we have to build a render-result */
|
||||
/* After imbuf load, OpenEXR type can return with a EXR-handle open
|
||||
* in that case we have to build a render-result. */
|
||||
#ifdef WITH_OPENEXR
|
||||
static void image_create_multilayer(Image *ima, ImBuf *ibuf, int framenr)
|
||||
{
|
||||
|
@ -4536,7 +4562,7 @@ static void image_create_multilayer(Image *ima, ImBuf *ibuf, int framenr)
|
|||
}
|
||||
#endif /* WITH_OPENEXR */
|
||||
|
||||
/* common stuff to do with images after loading */
|
||||
/** Common stuff to do with images after loading. */
|
||||
static void image_init_after_load(Image *ima, ImageUser *iuser, ImBuf *UNUSED(ibuf))
|
||||
{
|
||||
/* Preview is null when it has never been used as an icon before.
|
||||
|
@ -4571,7 +4597,9 @@ static int imbuf_alpha_flags_for_image(Image *ima)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* the number of files will vary according to the stereo format */
|
||||
/**
|
||||
* \return the number of files will vary according to the stereo format.
|
||||
*/
|
||||
static int image_num_files(Image *ima)
|
||||
{
|
||||
const bool is_multiview = BKE_image_is_multiview(ima);
|
||||
|
@ -5402,30 +5430,30 @@ static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock)
|
|||
}
|
||||
|
||||
if (ibuf == nullptr) {
|
||||
/* we are sure we have to load the ibuf, using source and type */
|
||||
/* We are sure we have to load the ibuf, using source and type. */
|
||||
if (ima->source == IMA_SRC_MOVIE) {
|
||||
/* source is from single file, use flipbook to store ibuf */
|
||||
/* Source is from single file, use flip-book to store ibuf. */
|
||||
ibuf = image_load_movie_file(ima, iuser, entry);
|
||||
}
|
||||
else if (ima->source == IMA_SRC_SEQUENCE) {
|
||||
if (ima->type == IMA_TYPE_IMAGE) {
|
||||
/* regular files, ibufs in flipbook, allows saving */
|
||||
/* Regular files, ibufs in flip-book, allows saving. */
|
||||
ibuf = image_load_sequence_file(ima, iuser, entry, entry);
|
||||
}
|
||||
/* no else; on load the ima type can change */
|
||||
if (ima->type == IMA_TYPE_MULTILAYER) {
|
||||
/* only 1 layer/pass stored in imbufs, no exrhandle anim storage, no saving */
|
||||
/* Only 1 layer/pass stored in imbufs, no EXR-handle anim storage, no saving. */
|
||||
ibuf = image_load_sequence_multilayer(ima, iuser, entry, entry);
|
||||
}
|
||||
}
|
||||
else if (ima->source == IMA_SRC_TILED) {
|
||||
if (ima->type == IMA_TYPE_IMAGE) {
|
||||
/* regular files, ibufs in flipbook, allows saving */
|
||||
/* Regular files, ibufs in flip-book, allows saving */
|
||||
ibuf = image_load_sequence_file(ima, iuser, entry, 0);
|
||||
}
|
||||
/* no else; on load the ima type can change */
|
||||
if (ima->type == IMA_TYPE_MULTILAYER) {
|
||||
/* only 1 layer/pass stored in imbufs, no exrhandle anim storage, no saving */
|
||||
/* Only 1 layer/pass stored in imbufs, no EXR-handle anim storage, no saving. */
|
||||
ibuf = image_load_sequence_multilayer(ima, iuser, entry, 0);
|
||||
}
|
||||
}
|
||||
|
@ -5441,8 +5469,8 @@ static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock)
|
|||
}
|
||||
}
|
||||
else if (ima->source == IMA_SRC_GENERATED) {
|
||||
/* generated is: ibuf is allocated dynamically */
|
||||
/* UV testgrid or black or solid etc */
|
||||
/* Generated is: `ibuf` is allocated dynamically. */
|
||||
/* UV test-grid or black or solid etc. */
|
||||
if (ima->gen_x == 0) {
|
||||
ima->gen_x = 1024;
|
||||
}
|
||||
|
@ -5564,7 +5592,11 @@ bool BKE_image_has_ibuf(Image *ima, ImageUser *iuser)
|
|||
return ibuf != nullptr;
|
||||
}
|
||||
|
||||
/* ******** Pool for image buffers ******** */
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Pool for Image Buffers
|
||||
* \{ */
|
||||
|
||||
struct ImagePoolItem {
|
||||
struct ImagePoolItem *next, *prev;
|
||||
|
@ -6274,7 +6306,11 @@ static void image_update_views_format(Image *ima, ImageUser *iuser)
|
|||
}
|
||||
}
|
||||
|
||||
/**************************** Render Slots ***************************/
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Render Slots
|
||||
* \{ */
|
||||
|
||||
RenderSlot *BKE_image_add_renderslot(Image *ima, const char *name)
|
||||
{
|
||||
|
@ -6392,3 +6428,5 @@ RenderSlot *BKE_image_get_renderslot(Image *ima, int index)
|
|||
/* Can be null for images without render slots. */
|
||||
return static_cast<RenderSlot *>(BLI_findlink(&ima->renderslots, index));
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
#include "BKE_scene.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
#include "RNA_prototypes.h"
|
||||
|
||||
#include "BLO_read_write.h"
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "CLG_log.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
#include "RNA_prototypes.h"
|
||||
|
||||
#include "GHOST_Path-api.h"
|
||||
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#include "PIL_time.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
#include "RNA_prototypes.h"
|
||||
#include "RNA_types.h"
|
||||
|
||||
#include "atomic_ops.h"
|
||||
|
|
|
@ -609,7 +609,7 @@ float BKE_mask_spline_project_co(MaskSpline *spline,
|
|||
|
||||
if (len_squared_v2(v1) > proj_eps_sq) {
|
||||
ang1 = angle_v2v2(v1, n1);
|
||||
if (ang1 > (float)M_PI / 2.0f) {
|
||||
if (ang1 > (float)M_PI_2) {
|
||||
ang1 = (float)M_PI - ang1;
|
||||
}
|
||||
|
||||
|
@ -635,7 +635,7 @@ float BKE_mask_spline_project_co(MaskSpline *spline,
|
|||
|
||||
if (len_squared_v2(v2) > proj_eps_sq) {
|
||||
ang2 = angle_v2v2(v2, n2);
|
||||
if (ang2 > (float)M_PI / 2.0f) {
|
||||
if (ang2 > (float)M_PI_2) {
|
||||
ang2 = (float)M_PI - ang2;
|
||||
}
|
||||
|
||||
|
|
|
@ -1609,8 +1609,10 @@ void BKE_movieclip_get_cache_segments(MovieClip *clip,
|
|||
if (clip->cache) {
|
||||
int proxy = rendersize_to_proxy(user, clip->flag);
|
||||
|
||||
BLI_thread_lock(LOCK_MOVIECLIP);
|
||||
IMB_moviecache_get_cache_segments(
|
||||
clip->cache->moviecache, proxy, user->render_flag, r_totseg, r_points);
|
||||
BLI_thread_unlock(LOCK_MOVIECLIP);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -41,6 +41,8 @@
|
|||
#include "BLO_read_write.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
#include "RNA_prototypes.h"
|
||||
|
||||
#include "nla_private.h"
|
||||
|
||||
static CLG_LogRef LOG = {"bke.nla"};
|
||||
|
|
|
@ -63,6 +63,7 @@
|
|||
|
||||
#include "RNA_access.h"
|
||||
#include "RNA_define.h"
|
||||
#include "RNA_prototypes.h"
|
||||
|
||||
#include "NOD_common.h"
|
||||
#include "NOD_composite.h"
|
||||
|
@ -4693,6 +4694,7 @@ static void registerGeometryNodes()
|
|||
|
||||
register_node_type_geo_legacy_attribute_proximity();
|
||||
register_node_type_geo_legacy_attribute_randomize();
|
||||
register_node_type_geo_legacy_attribute_remove();
|
||||
register_node_type_geo_legacy_attribute_transfer();
|
||||
register_node_type_geo_legacy_curve_endpoints();
|
||||
register_node_type_geo_legacy_curve_reverse();
|
||||
|
@ -4725,7 +4727,6 @@ static void registerGeometryNodes()
|
|||
register_node_type_geo_attribute_map_range();
|
||||
register_node_type_geo_attribute_math();
|
||||
register_node_type_geo_attribute_mix();
|
||||
register_node_type_geo_attribute_remove();
|
||||
register_node_type_geo_attribute_separate_xyz();
|
||||
register_node_type_geo_attribute_statistic();
|
||||
register_node_type_geo_attribute_vector_math();
|
||||
|
@ -4767,6 +4768,7 @@ static void registerGeometryNodes()
|
|||
register_node_type_geo_flip_faces();
|
||||
register_node_type_geo_geometry_to_instance();
|
||||
register_node_type_geo_image_texture();
|
||||
register_node_type_geo_input_named_attribute();
|
||||
register_node_type_geo_input_curve_handles();
|
||||
register_node_type_geo_input_curve_tilt();
|
||||
register_node_type_geo_input_id();
|
||||
|
@ -4820,6 +4822,7 @@ static void registerGeometryNodes()
|
|||
register_node_type_geo_proximity();
|
||||
register_node_type_geo_raycast();
|
||||
register_node_type_geo_realize_instances();
|
||||
register_node_type_geo_remove_attribute();
|
||||
register_node_type_geo_rotate_instances();
|
||||
register_node_type_geo_sample_texture();
|
||||
register_node_type_geo_scale_elements();
|
||||
|
@ -4837,6 +4840,7 @@ static void registerGeometryNodes()
|
|||
register_node_type_geo_set_shade_smooth();
|
||||
register_node_type_geo_set_spline_cyclic();
|
||||
register_node_type_geo_set_spline_resolution();
|
||||
register_node_type_geo_store_named_attribute();
|
||||
register_node_type_geo_string_join();
|
||||
register_node_type_geo_string_to_curves();
|
||||
register_node_type_geo_subdivision_surface();
|
||||
|
|
|
@ -1339,8 +1339,7 @@ class NodeTreeMainUpdater {
|
|||
{
|
||||
Vector<const SocketRef *> sockets;
|
||||
for (const NodeRef *node : tree.nodes()) {
|
||||
const bNode *bnode = node->bnode();
|
||||
if (bnode->typeinfo->nclass != NODE_CLASS_OUTPUT && bnode->type != NODE_GROUP_OUTPUT) {
|
||||
if (!this->is_output_node(*node)) {
|
||||
continue;
|
||||
}
|
||||
for (const InputSocketRef *socket : node->inputs()) {
|
||||
|
@ -1352,6 +1351,24 @@ class NodeTreeMainUpdater {
|
|||
return sockets;
|
||||
}
|
||||
|
||||
bool is_output_node(const NodeRef &node) const
|
||||
{
|
||||
const bNode &bnode = *node.bnode();
|
||||
if (bnode.typeinfo->nclass == NODE_CLASS_OUTPUT) {
|
||||
return true;
|
||||
}
|
||||
if (bnode.type == NODE_GROUP_OUTPUT) {
|
||||
return true;
|
||||
}
|
||||
/* Assume node groups without output sockets are outputs. */
|
||||
/* TODO: Store whether a node group contains a top-level output node (e.g. Material Output) in
|
||||
* run-time information on the node group itself. */
|
||||
if (bnode.type == NODE_GROUP && node.outputs().is_empty()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes a hash that changes when the node tree topology connected to an output node changes.
|
||||
* Adding reroutes does not have an effect on the hash.
|
||||
|
|
|
@ -85,7 +85,7 @@ static void do_kink_spiral_deform(ParticleKey *state,
|
|||
* and goes up to the Golden Spiral for 1.0
|
||||
* https://en.wikipedia.org/wiki/Golden_spiral
|
||||
*/
|
||||
const float b = shape * (1.0f + sqrtf(5.0f)) / (float)M_PI * 0.25f;
|
||||
const float b = shape * (1.0f + sqrtf(5.0f)) / (float)M_PI_4;
|
||||
/* angle of the spiral against the curve (rotated opposite to make a smooth transition) */
|
||||
const float start_angle = ((b != 0.0f) ? atanf(1.0f / b) : (float)-M_PI_2) +
|
||||
(b > 0.0f ? -(float)M_PI_2 : (float)M_PI_2);
|
||||
|
|
|
@ -142,15 +142,11 @@ bool NURBSpline::check_valid_size_and_order() const
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!is_cyclic_ && this->knots_mode == KnotsMode::Bezier) {
|
||||
if (order_ == 4) {
|
||||
if (this->size() < 5) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (order_ != 3) {
|
||||
if (ELEM(this->knots_mode, NURBS_KNOT_MODE_BEZIER, NURBS_KNOT_MODE_ENDPOINT_BEZIER)) {
|
||||
if (this->knots_mode == NURBS_KNOT_MODE_BEZIER && this->size() <= order_) {
|
||||
return false;
|
||||
}
|
||||
return (!is_cyclic_ || this->size() % (order_ - 1) == 0);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -166,12 +162,13 @@ void NURBSpline::calculate_knots() const
|
|||
{
|
||||
const KnotsMode mode = this->knots_mode;
|
||||
const int order = order_;
|
||||
const bool is_bezier = mode == NURBSpline::KnotsMode::Bezier;
|
||||
const bool is_end_point = mode == NURBSpline::KnotsMode::EndPoint;
|
||||
const bool is_bezier = ELEM(mode, NURBS_KNOT_MODE_BEZIER, NURBS_KNOT_MODE_ENDPOINT_BEZIER);
|
||||
const bool is_end_point = ELEM(mode, NURBS_KNOT_MODE_ENDPOINT, NURBS_KNOT_MODE_ENDPOINT_BEZIER);
|
||||
/* Inner knots are always repeated once except on Bezier case. */
|
||||
const int repeat_inner = is_bezier ? order - 1 : 1;
|
||||
/* How many times to repeat 0.0 at the beginning of knot. */
|
||||
const int head = is_end_point && !is_cyclic_ ? order : (is_bezier ? order / 2 : 1);
|
||||
const int head = is_end_point ? (order - (is_cyclic_ ? 1 : 0)) :
|
||||
(is_bezier ? min_ii(2, repeat_inner) : 1);
|
||||
/* Number of knots replicating widths of the starting knots.
|
||||
* Covers both Cyclic and EndPoint cases. */
|
||||
const int tail = is_cyclic_ ? 2 * order - 1 : (is_end_point ? order : 0);
|
||||
|
@ -182,7 +179,13 @@ void NURBSpline::calculate_knots() const
|
|||
int r = head;
|
||||
float current = 0.0f;
|
||||
|
||||
for (const int i : IndexRange(knots.size() - tail)) {
|
||||
const int offset = is_end_point && is_cyclic_ ? 1 : 0;
|
||||
if (offset) {
|
||||
knots[0] = current;
|
||||
current += 1.0f;
|
||||
}
|
||||
|
||||
for (const int i : IndexRange(offset, knots.size() - offset - tail)) {
|
||||
knots[i] = current;
|
||||
r--;
|
||||
if (r == 0) {
|
||||
|
@ -219,64 +222,58 @@ Span<float> NURBSpline::knots() const
|
|||
|
||||
static void calculate_basis_for_point(const float parameter,
|
||||
const int size,
|
||||
const int order,
|
||||
Span<float> knots,
|
||||
MutableSpan<float> basis_buffer,
|
||||
NURBSpline::BasisCache &basis_cache)
|
||||
const int degree,
|
||||
const Span<float> knots,
|
||||
MutableSpan<float> r_weights,
|
||||
int &r_start_index)
|
||||
{
|
||||
/* Clamp parameter due to floating point inaccuracy. */
|
||||
const float t = std::clamp(parameter, knots[0], knots[size + order - 1]);
|
||||
const int order = degree + 1;
|
||||
|
||||
int start = 0;
|
||||
int end = 0;
|
||||
for (const int i : IndexRange(size + order - 1)) {
|
||||
for (const int i : IndexRange(size + degree)) {
|
||||
const bool knots_equal = knots[i] == knots[i + 1];
|
||||
if (knots_equal || t < knots[i] || t > knots[i + 1]) {
|
||||
basis_buffer[i] = 0.0f;
|
||||
if (knots_equal || parameter < knots[i] || parameter > knots[i + 1]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
basis_buffer[i] = 1.0f;
|
||||
start = std::max(i - order - 1, 0);
|
||||
start = std::max(i - degree, 0);
|
||||
end = i;
|
||||
basis_buffer.slice(i + 1, size + order - 1 - i).fill(0.0f);
|
||||
break;
|
||||
}
|
||||
basis_buffer[size + order - 1] = 0.0f;
|
||||
|
||||
for (const int i_order : IndexRange(2, order - 1)) {
|
||||
if (end + i_order >= size + order) {
|
||||
end = size + order - 1 - i_order;
|
||||
Array<float, 12> buffer(order * 2, 0.0f);
|
||||
|
||||
buffer[end - start] = 1.0f;
|
||||
|
||||
for (const int i_order : IndexRange(2, degree)) {
|
||||
if (end + i_order >= knots.size()) {
|
||||
end = size + degree - i_order;
|
||||
}
|
||||
for (const int i : IndexRange(start, end - start + 1)) {
|
||||
for (const int i : IndexRange(end - start + 1)) {
|
||||
const int knot_index = start + i;
|
||||
|
||||
float new_basis = 0.0f;
|
||||
if (basis_buffer[i] != 0.0f) {
|
||||
new_basis += ((t - knots[i]) * basis_buffer[i]) / (knots[i + i_order - 1] - knots[i]);
|
||||
if (buffer[i] != 0.0f) {
|
||||
new_basis += ((parameter - knots[knot_index]) * buffer[i]) /
|
||||
(knots[knot_index + i_order - 1] - knots[knot_index]);
|
||||
}
|
||||
|
||||
if (basis_buffer[i + 1] != 0.0f) {
|
||||
new_basis += ((knots[i + i_order] - t) * basis_buffer[i + 1]) /
|
||||
(knots[i + i_order] - knots[i + 1]);
|
||||
if (buffer[i + 1] != 0.0f) {
|
||||
new_basis += ((knots[knot_index + i_order] - parameter) * buffer[i + 1]) /
|
||||
(knots[knot_index + i_order] - knots[knot_index + 1]);
|
||||
}
|
||||
|
||||
basis_buffer[i] = new_basis;
|
||||
buffer[i] = new_basis;
|
||||
}
|
||||
}
|
||||
|
||||
/* Shrink the range of calculated values to avoid storing unnecessary zeros. */
|
||||
while (basis_buffer[start] == 0.0f && start < end) {
|
||||
start++;
|
||||
}
|
||||
while (basis_buffer[end] == 0.0f && end > start) {
|
||||
end--;
|
||||
}
|
||||
|
||||
basis_cache.weights.clear();
|
||||
basis_cache.weights.extend(basis_buffer.slice(start, end - start + 1));
|
||||
basis_cache.start_index = start;
|
||||
buffer.as_mutable_span().drop_front(end - start + 1).fill(0.0f);
|
||||
r_weights.copy_from(buffer.as_span().take_front(order));
|
||||
r_start_index = start;
|
||||
}
|
||||
|
||||
Span<NURBSpline::BasisCache> NURBSpline::calculate_basis_cache() const
|
||||
const NURBSpline::BasisCache &NURBSpline::calculate_basis_cache() const
|
||||
{
|
||||
if (!basis_cache_dirty_) {
|
||||
return basis_cache_;
|
||||
|
@ -289,38 +286,41 @@ Span<NURBSpline::BasisCache> NURBSpline::calculate_basis_cache() const
|
|||
|
||||
const int size = this->size();
|
||||
const int eval_size = this->evaluated_points_size();
|
||||
if (eval_size == 0) {
|
||||
return {};
|
||||
}
|
||||
|
||||
basis_cache_.resize(eval_size);
|
||||
|
||||
const int order = this->order();
|
||||
Span<float> control_weights = this->weights();
|
||||
Span<float> knots = this->knots();
|
||||
const int degree = order - 1;
|
||||
|
||||
MutableSpan<BasisCache> basis_cache(basis_cache_);
|
||||
basis_cache_.weights.resize(eval_size * order);
|
||||
basis_cache_.start_indices.resize(eval_size);
|
||||
|
||||
/* This buffer is reused by each basis calculation to store temporary values.
|
||||
* Theoretically it could be optimized away in the future. */
|
||||
Array<float> basis_buffer(this->knots_size());
|
||||
if (eval_size == 0) {
|
||||
return basis_cache_;
|
||||
}
|
||||
|
||||
const float start = knots[order - 1];
|
||||
const float end = is_cyclic_ ? knots[size + order - 1] : knots[size];
|
||||
MutableSpan<float> basis_weights(basis_cache_.weights);
|
||||
MutableSpan<int> basis_start_indices(basis_cache_.start_indices);
|
||||
|
||||
const Span<float> control_weights = this->weights();
|
||||
const Span<float> knots = this->knots();
|
||||
|
||||
const int last_control_point_index = is_cyclic_ ? size + degree : size;
|
||||
|
||||
const float start = knots[degree];
|
||||
const float end = knots[last_control_point_index];
|
||||
const float step = (end - start) / this->evaluated_edges_size();
|
||||
float parameter = start;
|
||||
for (const int i : IndexRange(eval_size)) {
|
||||
BasisCache &basis = basis_cache[i];
|
||||
/* Clamp parameter due to floating point inaccuracy. */
|
||||
const float parameter = std::clamp(start + step * i, knots[0], knots[size + degree]);
|
||||
|
||||
MutableSpan<float> point_weights = basis_weights.slice(i * order, order);
|
||||
|
||||
calculate_basis_for_point(
|
||||
parameter, size + (is_cyclic_ ? order - 1 : 0), order, knots, basis_buffer, basis);
|
||||
BLI_assert(basis.weights.size() <= order);
|
||||
parameter, last_control_point_index, degree, knots, point_weights, basis_start_indices[i]);
|
||||
|
||||
for (const int j : basis.weights.index_range()) {
|
||||
const int point_index = (basis.start_index + j) % size;
|
||||
basis.weights[j] *= control_weights[point_index];
|
||||
for (const int j : point_weights.index_range()) {
|
||||
const int point_index = (basis_start_indices[i] + j) % size;
|
||||
point_weights[j] *= control_weights[point_index];
|
||||
}
|
||||
|
||||
parameter += step;
|
||||
}
|
||||
|
||||
basis_cache_dirty_ = false;
|
||||
|
@ -328,17 +328,18 @@ Span<NURBSpline::BasisCache> NURBSpline::calculate_basis_cache() const
|
|||
}
|
||||
|
||||
template<typename T>
|
||||
void interpolate_to_evaluated_impl(Span<NURBSpline::BasisCache> weights,
|
||||
void interpolate_to_evaluated_impl(const NURBSpline::BasisCache &basis_cache,
|
||||
const int order,
|
||||
const blender::VArray<T> &src,
|
||||
MutableSpan<T> dst)
|
||||
{
|
||||
const int size = src.size();
|
||||
BLI_assert(dst.size() == weights.size());
|
||||
blender::attribute_math::DefaultMixer<T> mixer(dst);
|
||||
|
||||
for (const int i : dst.index_range()) {
|
||||
Span<float> point_weights = weights[i].weights;
|
||||
const int start_index = weights[i].start_index;
|
||||
Span<float> point_weights = basis_cache.weights.as_span().slice(i * order, order);
|
||||
const int start_index = basis_cache.start_indices[i];
|
||||
|
||||
for (const int j : point_weights.index_range()) {
|
||||
const int point_index = (start_index + j) % size;
|
||||
mixer.mix_in(i, src[point_index], point_weights[j]);
|
||||
|
@ -356,14 +357,14 @@ GVArray NURBSpline::interpolate_to_evaluated(const GVArray &src) const
|
|||
return src;
|
||||
}
|
||||
|
||||
Span<BasisCache> basis_cache = this->calculate_basis_cache();
|
||||
const BasisCache &basis_cache = this->calculate_basis_cache();
|
||||
|
||||
GVArray new_varray;
|
||||
blender::attribute_math::convert_to_static_type(src.type(), [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
if constexpr (!std::is_void_v<blender::attribute_math::DefaultMixer<T>>) {
|
||||
Array<T> values(this->evaluated_points_size());
|
||||
interpolate_to_evaluated_impl<T>(basis_cache, src.typed<T>(), values);
|
||||
interpolate_to_evaluated_impl<T>(basis_cache, this->order(), src.typed<T>(), values);
|
||||
new_varray = VArray<T>::ForContainer(std::move(values));
|
||||
}
|
||||
});
|
||||
|
|
|
@ -415,8 +415,6 @@ static void subdiv_mesh_tls_free(void *tls_v)
|
|||
|
||||
/** \} */
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Accumulation helpers
|
||||
* \{ */
|
||||
|
|
|
@ -1349,7 +1349,7 @@ void txt_sel_set(Text *text, int startl, int startc, int endl, int endc)
|
|||
* - Are not null terminated.
|
||||
* \{ */
|
||||
|
||||
char *txt_to_buf_for_undo(Text *text, int *r_buf_len)
|
||||
char *txt_to_buf_for_undo(Text *text, size_t *r_buf_len)
|
||||
{
|
||||
int buf_len = 0;
|
||||
LISTBASE_FOREACH (const TextLine *, l, &text->lines) {
|
||||
|
@ -1366,7 +1366,7 @@ char *txt_to_buf_for_undo(Text *text, int *r_buf_len)
|
|||
return buf;
|
||||
}
|
||||
|
||||
void txt_from_buf_for_undo(Text *text, const char *buf, int buf_len)
|
||||
void txt_from_buf_for_undo(Text *text, const char *buf, size_t buf_len)
|
||||
{
|
||||
const char *buf_end = buf + buf_len;
|
||||
const char *buf_step = buf;
|
||||
|
@ -1434,87 +1434,29 @@ void txt_from_buf_for_undo(Text *text, const char *buf, int buf_len)
|
|||
/** \name Cut and Paste Functions
|
||||
* \{ */
|
||||
|
||||
char *txt_to_buf(Text *text, int *r_buf_strlen)
|
||||
char *txt_to_buf(Text *text, size_t *r_buf_strlen)
|
||||
{
|
||||
int length;
|
||||
TextLine *tmp, *linef, *linel;
|
||||
int charf, charl;
|
||||
char *buf;
|
||||
|
||||
if (r_buf_strlen) {
|
||||
*r_buf_strlen = 0;
|
||||
/* Identical to #txt_to_buf_for_undo except that the string is nil terminated. */
|
||||
size_t buf_len = 0;
|
||||
LISTBASE_FOREACH (const TextLine *, l, &text->lines) {
|
||||
buf_len += l->len + 1;
|
||||
}
|
||||
|
||||
if (!text->curl) {
|
||||
return NULL;
|
||||
char *buf = MEM_mallocN(buf_len + 1, __func__);
|
||||
char *buf_step = buf;
|
||||
LISTBASE_FOREACH (const TextLine *, l, &text->lines) {
|
||||
memcpy(buf_step, l->line, l->len);
|
||||
buf_step += l->len;
|
||||
*buf_step++ = '\n';
|
||||
}
|
||||
if (!text->sell) {
|
||||
return NULL;
|
||||
}
|
||||
if (!text->lines.first) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
linef = text->lines.first;
|
||||
charf = 0;
|
||||
|
||||
linel = text->lines.last;
|
||||
charl = linel->len;
|
||||
|
||||
if (linef == text->lines.last) {
|
||||
length = charl - charf;
|
||||
|
||||
buf = MEM_mallocN(length + 2, "text buffer");
|
||||
|
||||
BLI_strncpy(buf, linef->line + charf, length + 1);
|
||||
buf[length] = 0;
|
||||
}
|
||||
else {
|
||||
length = linef->len - charf;
|
||||
length += charl;
|
||||
length += 2; /* For the 2 '\n' */
|
||||
|
||||
tmp = linef->next;
|
||||
while (tmp && tmp != linel) {
|
||||
length += tmp->len + 1;
|
||||
tmp = tmp->next;
|
||||
}
|
||||
|
||||
buf = MEM_mallocN(length + 1, "cut buffer");
|
||||
|
||||
strncpy(buf, linef->line + charf, linef->len - charf);
|
||||
length = linef->len - charf;
|
||||
|
||||
buf[length++] = '\n';
|
||||
|
||||
tmp = linef->next;
|
||||
while (tmp && tmp != linel) {
|
||||
strncpy(buf + length, tmp->line, tmp->len);
|
||||
length += tmp->len;
|
||||
|
||||
buf[length++] = '\n';
|
||||
|
||||
tmp = tmp->next;
|
||||
}
|
||||
strncpy(buf + length, linel->line, charl);
|
||||
length += charl;
|
||||
|
||||
/* python compiler wants an empty end line */
|
||||
buf[length++] = '\n';
|
||||
buf[length] = 0;
|
||||
}
|
||||
|
||||
if (r_buf_strlen) {
|
||||
*r_buf_strlen = length;
|
||||
}
|
||||
|
||||
*buf_step = '\0';
|
||||
*r_buf_strlen = buf_len;
|
||||
return buf;
|
||||
}
|
||||
|
||||
char *txt_sel_to_buf(Text *text, int *r_buf_strlen)
|
||||
char *txt_sel_to_buf(Text *text, size_t *r_buf_strlen)
|
||||
{
|
||||
char *buf;
|
||||
int length = 0;
|
||||
size_t length = 0;
|
||||
TextLine *tmp, *linef, *linel;
|
||||
int charf, charl;
|
||||
|
||||
|
@ -1558,42 +1500,32 @@ char *txt_sel_to_buf(Text *text, int *r_buf_strlen)
|
|||
|
||||
if (linef == linel) {
|
||||
length = charl - charf;
|
||||
|
||||
buf = MEM_mallocN(length + 1, "sel buffer");
|
||||
|
||||
BLI_strncpy(buf, linef->line + charf, length + 1);
|
||||
memcpy(buf, linef->line + charf, length + 1);
|
||||
}
|
||||
else {
|
||||
length += linef->len - charf;
|
||||
length += charl;
|
||||
length++; /* For the '\n' */
|
||||
/* Add 1 for the '\n' */
|
||||
length = (linef->len - charf) + charl + 1;
|
||||
|
||||
tmp = linef->next;
|
||||
while (tmp && tmp != linel) {
|
||||
for (tmp = linef->next; tmp && tmp != linel; tmp = tmp->next) {
|
||||
length += tmp->len + 1;
|
||||
tmp = tmp->next;
|
||||
}
|
||||
|
||||
buf = MEM_mallocN(length + 1, "sel buffer");
|
||||
|
||||
strncpy(buf, linef->line + charf, linef->len - charf);
|
||||
memcpy(buf, linef->line + charf, linef->len - charf);
|
||||
length = linef->len - charf;
|
||||
|
||||
buf[length++] = '\n';
|
||||
|
||||
tmp = linef->next;
|
||||
while (tmp && tmp != linel) {
|
||||
strncpy(buf + length, tmp->line, tmp->len);
|
||||
for (tmp = linef->next; tmp && tmp != linel; tmp = tmp->next) {
|
||||
memcpy(buf + length, tmp->line, tmp->len);
|
||||
length += tmp->len;
|
||||
|
||||
buf[length++] = '\n';
|
||||
|
||||
tmp = tmp->next;
|
||||
}
|
||||
strncpy(buf + length, linel->line, charl);
|
||||
length += charl;
|
||||
|
||||
buf[length] = 0;
|
||||
memcpy(buf + length, linel->line, charl);
|
||||
length += charl;
|
||||
buf[length] = '\0';
|
||||
}
|
||||
|
||||
if (r_buf_strlen) {
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include "IMB_imbuf_types.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
#include "RNA_prototypes.h"
|
||||
|
||||
#include "libmv-capi.h"
|
||||
#include "tracking_private.h"
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "BKE_tracking.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
#include "RNA_prototypes.h"
|
||||
|
||||
#include "libmv-capi.h"
|
||||
#include "tracking_private.h"
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "DNA_movieclip_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
#include "RNA_access.h"
|
||||
#include "RNA_prototypes.h"
|
||||
|
||||
#include "BLI_ghash.h"
|
||||
#include "BLI_listbase.h"
|
||||
|
|
|
@ -34,11 +34,12 @@ BLI_memiter *BLI_memiter_create(unsigned int chunk_size_min)
|
|||
ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL;
|
||||
void *BLI_memiter_alloc(BLI_memiter *mi, unsigned int size)
|
||||
/* WARNING: `ATTR_MALLOC` attribute on #BLI_memiter_alloc causes crash, see: D2756. */
|
||||
ATTR_RETURNS_NONNULL ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL ATTR_NONNULL(1);
|
||||
ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL ATTR_NONNULL(1);
|
||||
void BLI_memiter_alloc_from(BLI_memiter *mi, uint elem_size, const void *data_from)
|
||||
ATTR_NONNULL(1, 3);
|
||||
void *BLI_memiter_calloc(BLI_memiter *mi, unsigned int size)
|
||||
ATTR_RETURNS_NONNULL ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL ATTR_NONNULL(1);
|
||||
void *BLI_memiter_calloc(BLI_memiter *mi,
|
||||
unsigned int size) ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL
|
||||
ATTR_NONNULL(1);
|
||||
void BLI_memiter_destroy(BLI_memiter *mi) ATTR_NONNULL(1);
|
||||
void BLI_memiter_clear(BLI_memiter *mi) ATTR_NONNULL(1);
|
||||
unsigned int BLI_memiter_count(const BLI_memiter *mi) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
|
||||
|
|
|
@ -95,10 +95,10 @@ MINLINE float saacos(float fac)
|
|||
MINLINE float saasin(float fac)
|
||||
{
|
||||
if (UNLIKELY(fac <= -1.0f)) {
|
||||
return (float)-M_PI / 2.0f;
|
||||
return (float)-M_PI_2;
|
||||
}
|
||||
else if (UNLIKELY(fac >= 1.0f)) {
|
||||
return (float)M_PI / 2.0f;
|
||||
return (float)M_PI_2;
|
||||
}
|
||||
else {
|
||||
return asinf(fac);
|
||||
|
@ -131,10 +131,10 @@ MINLINE float saacosf(float fac)
|
|||
MINLINE float saasinf(float fac)
|
||||
{
|
||||
if (UNLIKELY(fac <= -1.0f)) {
|
||||
return (float)-M_PI / 2.0f;
|
||||
return (float)-M_PI_2;
|
||||
}
|
||||
else if (UNLIKELY(fac >= 1.0f)) {
|
||||
return (float)M_PI / 2.0f;
|
||||
return (float)M_PI_2;
|
||||
}
|
||||
else {
|
||||
return asinf(fac);
|
||||
|
|
|
@ -289,7 +289,7 @@ void mid_v3_v3v3_angle_weighted(float r[3], const float a[3], const float b[3])
|
|||
BLI_ASSERT_UNIT_V3(b);
|
||||
|
||||
add_v3_v3v3(r, a, b);
|
||||
angle = ((float)(1.0 / (M_PI / 2.0)) *
|
||||
angle = ((float)M_2_PI *
|
||||
/* normally we would only multiply by 2,
|
||||
* but instead of an angle make this 0-1 factor */
|
||||
2.0f) *
|
||||
|
@ -305,7 +305,7 @@ void mid_v3_angle_weighted(float r[3])
|
|||
/* double check they are normalized */
|
||||
BLI_assert(len_squared_v3(r) <= 1.0f + FLT_EPSILON);
|
||||
|
||||
angle = ((float)(1.0 / (M_PI / 2.0)) *
|
||||
angle = ((float)M_2_PI *
|
||||
/* normally we would only multiply by 2,
|
||||
* but instead of an angle make this 0-1 factor */
|
||||
2.0f) *
|
||||
|
|
|
@ -91,7 +91,7 @@ TEST(task, MempoolIter)
|
|||
|
||||
int i;
|
||||
|
||||
/* 'Randomly' add and remove some items from mempool, to create a non-homogenous one. */
|
||||
/* 'Randomly' add and remove some items from mempool, to create a non-homogeneous one. */
|
||||
int num_items = 0;
|
||||
for (i = 0; i < NUM_ITEMS; i++) {
|
||||
data[i] = (int *)BLI_mempool_alloc(mempool);
|
||||
|
|
|
@ -22,7 +22,8 @@ set(INC
|
|||
|
||||
# for writefile.c: dna_type_offsets.h
|
||||
${CMAKE_BINARY_DIR}/source/blender/makesdna/intern
|
||||
|
||||
# RNA_prototypes.h
|
||||
${CMAKE_BINARY_DIR}/source/blender/makesrna
|
||||
)
|
||||
|
||||
set(INC_SYS
|
||||
|
@ -84,6 +85,8 @@ blender_add_lib(bf_blenloader "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
|
|||
|
||||
# needed so writefile.c can use dna_type_offsets.h
|
||||
add_dependencies(bf_blenloader bf_dna)
|
||||
# RNA_prototypes.h
|
||||
add_dependencies(bf_blenloader bf_rna)
|
||||
|
||||
if(WITH_GTESTS)
|
||||
set(TEST_SRC
|
||||
|
|
|
@ -1838,7 +1838,7 @@ void blo_do_versions_260(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
|||
Image *image = blo_do_versions_newlibadr(fd, tex->id.lib, tex->ima);
|
||||
|
||||
if (image && (image->flag & IMA_DO_PREMUL) == 0) {
|
||||
const int IMA_IGNORE_ALPHA = (1 << 12);
|
||||
enum { IMA_IGNORE_ALPHA = (1 << 12) };
|
||||
image->flag |= IMA_IGNORE_ALPHA;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1550,7 +1550,7 @@ void do_versions_after_linking_280(Main *bmain, ReportList *UNUSED(reports))
|
|||
|
||||
if (!MAIN_VERSION_ATLEAST(bmain, 280, 69)) {
|
||||
/* Unify DOF settings (EEVEE part only) */
|
||||
const int SCE_EEVEE_DOF_ENABLED = (1 << 7);
|
||||
enum { SCE_EEVEE_DOF_ENABLED = (1 << 7) };
|
||||
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
|
||||
if (STREQ(scene->r.engine, RE_engine_id_BLENDER_EEVEE)) {
|
||||
if (scene->eevee.flag & SCE_EEVEE_DOF_ENABLED) {
|
||||
|
@ -2312,7 +2312,7 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
|||
} \
|
||||
} \
|
||||
((void)0)
|
||||
const int SCE_EEVEE_DOF_ENABLED = (1 << 7);
|
||||
enum { SCE_EEVEE_DOF_ENABLED = (1 << 7) };
|
||||
IDProperty *props = IDP_GetPropertyFromGroup(scene->layer_properties,
|
||||
RE_engine_id_BLENDER_EEVEE);
|
||||
// EEVEE_GET_BOOL(props, volumetric_enable, SCE_EEVEE_VOLUMETRIC_ENABLED);
|
||||
|
@ -4032,7 +4032,7 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
|||
if (!MAIN_VERSION_ATLEAST(bmain, 280, 70)) {
|
||||
/* New image alpha modes. */
|
||||
LISTBASE_FOREACH (Image *, image, &bmain->images) {
|
||||
const int IMA_IGNORE_ALPHA = (1 << 12);
|
||||
enum { IMA_IGNORE_ALPHA = (1 << 12) };
|
||||
if (image->flag & IMA_IGNORE_ALPHA) {
|
||||
image->alpha_mode = IMA_ALPHA_IGNORE;
|
||||
image->flag &= ~IMA_IGNORE_ALPHA;
|
||||
|
@ -4497,7 +4497,7 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
|||
clmd->sim_parms->max_internal_tension = 15.0f;
|
||||
clmd->sim_parms->internal_compression = 15.0f;
|
||||
clmd->sim_parms->max_internal_compression = 15.0f;
|
||||
clmd->sim_parms->internal_spring_max_diversion = M_PI / 4.0f;
|
||||
clmd->sim_parms->internal_spring_max_diversion = M_PI_4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -701,8 +701,10 @@ static void panels_remove_x_closed_flag_recursive(Panel *panel)
|
|||
static void do_versions_point_attributes(CustomData *pdata)
|
||||
{
|
||||
/* Change to generic named float/float3 attributes. */
|
||||
const int CD_LOCATION = 43;
|
||||
const int CD_RADIUS = 44;
|
||||
enum {
|
||||
CD_LOCATION = 43,
|
||||
CD_RADIUS = 44,
|
||||
};
|
||||
|
||||
for (int i = 0; i < pdata->totlayer; i++) {
|
||||
CustomDataLayer *layer = &pdata->layers[i];
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "BKE_armature.h"
|
||||
#include "BKE_asset.h"
|
||||
#include "BKE_collection.h"
|
||||
#include "BKE_curve.h"
|
||||
#include "BKE_deform.h"
|
||||
#include "BKE_fcurve.h"
|
||||
#include "BKE_fcurve_driver.h"
|
||||
|
@ -55,6 +56,7 @@
|
|||
|
||||
#include "RNA_access.h"
|
||||
#include "RNA_enum_types.h"
|
||||
#include "RNA_prototypes.h"
|
||||
|
||||
#include "BLO_readfile.h"
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
@ -525,7 +527,7 @@ static void version_geometry_nodes_add_realize_instance_nodes(bNodeTree *ntree)
|
|||
GEO_NODE_TRIM_CURVE,
|
||||
GEO_NODE_REPLACE_MATERIAL,
|
||||
GEO_NODE_SUBDIVIDE_MESH,
|
||||
GEO_NODE_ATTRIBUTE_REMOVE,
|
||||
GEO_NODE_LEGACY_ATTRIBUTE_REMOVE,
|
||||
GEO_NODE_TRIANGULATE)) {
|
||||
bNodeSocket *geometry_socket = node->inputs.first;
|
||||
add_realize_instances_before_socket(ntree, node, geometry_socket);
|
||||
|
@ -997,7 +999,7 @@ static bool geometry_node_is_293_legacy(const short node_type)
|
|||
/* Maybe legacy: Might need special attribute handling, depending on design. */
|
||||
case GEO_NODE_SWITCH:
|
||||
case GEO_NODE_JOIN_GEOMETRY:
|
||||
case GEO_NODE_ATTRIBUTE_REMOVE:
|
||||
case GEO_NODE_LEGACY_ATTRIBUTE_REMOVE:
|
||||
case GEO_NODE_OBJECT_INFO:
|
||||
case GEO_NODE_COLLECTION_INFO:
|
||||
return false;
|
||||
|
@ -1481,6 +1483,10 @@ static void version_liboverride_rnacollections_insertion_animdata(ID *id)
|
|||
/* NOLINTNEXTLINE: readability-function-size */
|
||||
void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
||||
{
|
||||
/* The #SCE_SNAP_SEQ flag has been removed in favor of the #SCE_SNAP which can be used for each
|
||||
* snap_flag member individually. */
|
||||
enum { SCE_SNAP_SEQ = (1 << 7) };
|
||||
|
||||
if (!MAIN_VERSION_ATLEAST(bmain, 300, 1)) {
|
||||
/* Set default value for the new bisect_threshold parameter in the mirror modifier. */
|
||||
if (!DNA_struct_elem_find(fd->filesdna, "MirrorModifierData", "float", "bisect_threshold")) {
|
||||
|
@ -2567,6 +2573,59 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
|||
}
|
||||
}
|
||||
|
||||
if (!MAIN_VERSION_ATLEAST(bmain, 302, 6)) {
|
||||
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
|
||||
ToolSettings *ts = scene->toolsettings;
|
||||
if (ts->uv_relax_method == 0) {
|
||||
ts->uv_relax_method = UV_SCULPT_TOOL_RELAX_LAPLACIAN;
|
||||
}
|
||||
}
|
||||
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
|
||||
ToolSettings *tool_settings = scene->toolsettings;
|
||||
tool_settings->snap_flag_seq = tool_settings->snap_flag & ~(SCE_SNAP | SCE_SNAP_SEQ);
|
||||
if (tool_settings->snap_flag & SCE_SNAP_SEQ) {
|
||||
tool_settings->snap_flag_seq |= SCE_SNAP;
|
||||
tool_settings->snap_flag &= ~SCE_SNAP_SEQ;
|
||||
}
|
||||
|
||||
tool_settings->snap_flag_node = tool_settings->snap_flag;
|
||||
tool_settings->snap_uv_flag |= tool_settings->snap_flag & SCE_SNAP;
|
||||
}
|
||||
|
||||
/* Alter NURBS knot mode flags to fit new modes. */
|
||||
LISTBASE_FOREACH (Curve *, curve, &bmain->curves) {
|
||||
LISTBASE_FOREACH (Nurb *, nurb, &curve->nurb) {
|
||||
/* Previously other flags were ignored if CU_NURB_CYCLIC is set. */
|
||||
if (nurb->flagu & CU_NURB_CYCLIC) {
|
||||
nurb->flagu = CU_NURB_CYCLIC;
|
||||
}
|
||||
/* CU_NURB_BEZIER and CU_NURB_ENDPOINT were ignored if combined. */
|
||||
else if (nurb->flagu & CU_NURB_BEZIER && nurb->flagu & CU_NURB_ENDPOINT) {
|
||||
nurb->flagu &= ~(CU_NURB_BEZIER | CU_NURB_ENDPOINT);
|
||||
BKE_nurb_knot_calc_u(nurb);
|
||||
}
|
||||
/* Bezier NURBS of order 3 were clamped to first control point. */
|
||||
else if (nurb->orderu == 3 && (nurb->flagu & CU_NURB_BEZIER)) {
|
||||
nurb->flagu |= CU_NURB_ENDPOINT;
|
||||
}
|
||||
|
||||
/* Previously other flags were ignored if CU_NURB_CYCLIC is set. */
|
||||
if (nurb->flagv & CU_NURB_CYCLIC) {
|
||||
nurb->flagv = CU_NURB_CYCLIC;
|
||||
}
|
||||
/* CU_NURB_BEZIER and CU_NURB_ENDPOINT were ignored if used together. */
|
||||
else if (nurb->flagv & CU_NURB_BEZIER && nurb->flagv & CU_NURB_ENDPOINT) {
|
||||
nurb->flagv &= ~(CU_NURB_BEZIER | CU_NURB_ENDPOINT);
|
||||
BKE_nurb_knot_calc_v(nurb);
|
||||
}
|
||||
/* Bezier NURBS of order 3 were clamped to first control point. */
|
||||
else if (nurb->orderv == 3 && (nurb->flagv & CU_NURB_BEZIER)) {
|
||||
nurb->flagv |= CU_NURB_ENDPOINT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Versioning code until next subversion bump goes here.
|
||||
*
|
||||
|
@ -2579,10 +2638,12 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
|||
{
|
||||
/* Keep this block, even when empty. */
|
||||
|
||||
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
|
||||
ToolSettings *ts = scene->toolsettings;
|
||||
if (ts->uv_relax_method == 0) {
|
||||
ts->uv_relax_method = UV_SCULPT_TOOL_RELAX_LAPLACIAN;
|
||||
/* Deprecate the attribute remove node. It was hidden and is replaced by a version without a
|
||||
* multi-input socket. */
|
||||
LISTBASE_FOREACH (bNodeTree *, ntree, &bmain->nodetrees) {
|
||||
if (ntree->type == NTREE_GEOMETRY) {
|
||||
version_node_id(
|
||||
ntree, GEO_NODE_LEGACY_ATTRIBUTE_REMOVE, "GeometryNodeLegacyAttributeRemove");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -330,7 +330,7 @@ static void image_node_colorspace(bNode *node)
|
|||
return;
|
||||
}
|
||||
|
||||
const int SHD_COLORSPACE_NONE = 0;
|
||||
enum { SHD_COLORSPACE_NONE = 0 };
|
||||
Image *image = (Image *)node->id;
|
||||
if (color_space == SHD_COLORSPACE_NONE) {
|
||||
STRNCPY(image->colorspace_settings.name,
|
||||
|
@ -1362,10 +1362,12 @@ void blo_do_versions_cycles(FileData *UNUSED(fd), Library *UNUSED(lib), Main *bm
|
|||
|
||||
void do_versions_after_linking_cycles(Main *bmain)
|
||||
{
|
||||
const int DENOISER_AUTO = 0;
|
||||
const int DENOISER_NLM = 1;
|
||||
const int DENOISER_OPTIX = 2;
|
||||
const int DENOISER_OPENIMAGEDENOISE = 4;
|
||||
enum {
|
||||
DENOISER_AUTO = 0,
|
||||
DENOISER_NLM = 1,
|
||||
DENOISER_OPTIX = 2,
|
||||
DENOISER_OPENIMAGEDENOISE = 4,
|
||||
};
|
||||
|
||||
if (!MAIN_VERSION_ATLEAST(bmain, 280, 66)) {
|
||||
/* Shader node tree changes. After lib linking so we have all the typeinfo
|
||||
|
|
|
@ -7106,7 +7106,7 @@ static void find_even_superellipse_chords(int n, float r, double *xvals, double
|
|||
return;
|
||||
}
|
||||
if (r == PRO_CIRCLE_R) {
|
||||
double temp = (M_PI / 2) / n;
|
||||
double temp = M_PI_2 / n;
|
||||
/* Angle spacing. */
|
||||
for (int i = 0; i <= n; i++) {
|
||||
xvals[i] = sin(i * temp);
|
||||
|
|
|
@ -26,6 +26,8 @@ set(INC
|
|||
|
||||
# dna_type_offsets.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/../makesdna/intern
|
||||
# RNA_prototypes.h
|
||||
${CMAKE_BINARY_DIR}/source/blender/makesrna
|
||||
)
|
||||
|
||||
set(INC_SYS
|
||||
|
@ -666,3 +668,5 @@ endif()
|
|||
|
||||
# Needed so we can use dna_type_offsets.h for defaults initialization.
|
||||
add_dependencies(bf_compositor bf_dna)
|
||||
# RNA_prototypes.h
|
||||
add_dependencies(bf_compositor bf_rna)
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "BKE_node.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
#include "RNA_prototypes.h"
|
||||
|
||||
#include "COM_Node.h" /* own include */
|
||||
|
||||
|
|
|
@ -15,6 +15,8 @@ set(INC
|
|||
../windowmanager
|
||||
../../../intern/atomic
|
||||
../../../intern/guardedalloc
|
||||
# RNA_prototypes.h
|
||||
${CMAKE_BINARY_DIR}/source/blender/makesrna
|
||||
)
|
||||
|
||||
set(INC_SYS
|
||||
|
@ -155,6 +157,9 @@ endif()
|
|||
|
||||
blender_add_lib(bf_depsgraph "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
|
||||
|
||||
# RNA_prototypes.h
|
||||
add_dependencies(bf_depsgraph bf_rna)
|
||||
|
||||
if(WITH_GTESTS)
|
||||
set(TEST_SRC
|
||||
intern/builder/deg_builder_rna_test.cc
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
|
||||
#include "BKE_action.h"
|
||||
|
||||
#include "RNA_prototypes.h"
|
||||
|
||||
#include "intern/builder/deg_builder_cache.h"
|
||||
#include "intern/builder/deg_builder_remove_noop.h"
|
||||
#include "intern/depsgraph.h"
|
||||
|
|
|
@ -91,6 +91,7 @@
|
|||
#include "BKE_world.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
#include "RNA_prototypes.h"
|
||||
#include "RNA_types.h"
|
||||
|
||||
#include "DEG_depsgraph.h"
|
||||
|
|
|
@ -82,6 +82,7 @@
|
|||
#include "BKE_world.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
#include "RNA_prototypes.h"
|
||||
#include "RNA_types.h"
|
||||
|
||||
#include "SEQ_iterator.h"
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
#include "BKE_armature.h"
|
||||
#include "BKE_constraint.h"
|
||||
|
||||
#include "RNA_prototypes.h"
|
||||
|
||||
#include "DEG_depsgraph.h"
|
||||
#include "DEG_depsgraph_build.h"
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "BKE_constraint.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
#include "RNA_prototypes.h"
|
||||
|
||||
#include "intern/builder/deg_builder.h"
|
||||
#include "intern/depsgraph.h"
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "DNA_scene_types.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
#include "RNA_prototypes.h"
|
||||
|
||||
#include "DEG_depsgraph.h"
|
||||
#include "DEG_depsgraph_query.h"
|
||||
|
|
|
@ -62,7 +62,7 @@ static float circle_to_polygon_radius(float sides_count, float theta)
|
|||
cosf(theta - side_angle * floorf((sides_count * theta + M_PI) / (2.0f * M_PI)));
|
||||
}
|
||||
|
||||
/* Remap input angle to have homogenous spacing of points along a polygon edge.
|
||||
/* Remap input angle to have homogeneous spacing of points along a polygon edge.
|
||||
* Expect theta to be in [0..2pi] range. */
|
||||
static float circle_to_polygon_angle(float sides_count, float theta)
|
||||
{
|
||||
|
|
|
@ -613,7 +613,7 @@ void EEVEE_lightprobes_planar_data_from_object(Object *ob,
|
|||
eplanar->clip_edge_y_neg = dot_v3v3(eplanar->clip_vec_y, vec);
|
||||
|
||||
/* Facing factors */
|
||||
float max_angle = max_ff(1e-2f, 1.0f - probe->falloff) * M_PI * 0.5f;
|
||||
float max_angle = max_ff(1e-2f, 1.0f - probe->falloff) * M_PI_2;
|
||||
float min_angle = 0.0f;
|
||||
eplanar->facing_scale = 1.0f / max_ff(1e-8f, cosf(min_angle) - cosf(max_angle));
|
||||
eplanar->facing_bias = -min_ff(1.0f - 1e-8f, cosf(max_angle)) * eplanar->facing_scale;
|
||||
|
|
|
@ -217,7 +217,7 @@ void EEVEE_lookdev_cache_init(EEVEE_Data *vedata,
|
|||
float x_rot_matrix[3][3];
|
||||
DRW_view_viewmat_get(NULL, view_matrix, false);
|
||||
copy_m3_m4(view_rot_matrix, view_matrix);
|
||||
axis_angle_to_mat3_single(x_rot_matrix, 'X', M_PI / 2.0f);
|
||||
axis_angle_to_mat3_single(x_rot_matrix, 'X', M_PI_2);
|
||||
mul_m3_m3m3(view_rot_matrix, x_rot_matrix, view_rot_matrix);
|
||||
mul_m3_m3m3(view_rot_matrix, g_data->studiolight_matrix, view_rot_matrix);
|
||||
copy_m3_m3(studiolight_matrix, view_rot_matrix);
|
||||
|
|
|
@ -35,7 +35,7 @@ float circle_to_polygon_radius(float sides_count, float theta)
|
|||
cos(theta - side_angle * floor((sides_count * theta + M_PI) / M_2PI));
|
||||
}
|
||||
|
||||
/* Remap input angle to have homogenous spacing of points along a polygon edge.
|
||||
/* Remap input angle to have homogeneous spacing of points along a polygon edge.
|
||||
* Expect theta to be in [0..2pi] range. */
|
||||
float circle_to_polygon_angle(float sides_count, float theta)
|
||||
{
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#pragma BLENDER_REQUIRE(common_utiltex_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(effect_dof_lib.glsl)
|
||||
|
||||
/* Mipmapped input buffers, halfres but with padding to ensure mipmap alignement. */
|
||||
/* Mipmapped input buffers, halfres but with padding to ensure mipmap alignment. */
|
||||
uniform sampler2D colorBuffer;
|
||||
uniform sampler2D cocBuffer;
|
||||
|
||||
|
|
|
@ -103,7 +103,7 @@ void main()
|
|||
color4 = colors[3] * weights[3];
|
||||
|
||||
/* Extend to cover at least the unit circle */
|
||||
const float extend = (cos(M_PI / 4.0) + 1.0) * 2.0;
|
||||
const float extend = (cos(M_PI_4) + 1.0) * 2.0;
|
||||
/* Crappy diagram
|
||||
* ex 1
|
||||
* | \
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* Adapted from http://rastergrid.com/blog/2010/10/hierarchical-z-map-based-occlusion-culling/
|
||||
*
|
||||
* Major simplification has been made since we pad the buffer to always be bigger than input to
|
||||
* avoid mipmapping misalignement.
|
||||
* avoid mipmapping misalignment.
|
||||
*/
|
||||
|
||||
#ifdef LAYERED
|
||||
|
|
|
@ -40,7 +40,7 @@ float light_translucent_power_with_falloff(LightData ld, vec3 N, vec4 l_vector)
|
|||
if (ld.l_type >= AREA_RECT) {
|
||||
power = (ld.l_sizex * ld.l_sizey * 4.0 * M_PI) * (1.0 / 80.0);
|
||||
if (ld.l_type == AREA_ELLIPSE) {
|
||||
power *= M_PI * 0.25;
|
||||
power *= M_PI_4;
|
||||
}
|
||||
power *= 0.3 * 20.0 *
|
||||
max(0.0, dot(-ld.l_forward, l_vector.xyz / l_vector.w)); /* XXX ad hoc, empirical */
|
||||
|
|
|
@ -16,9 +16,9 @@ out vec4 FragColor;
|
|||
vec3 background_transform_to_world(vec3 viewvec)
|
||||
{
|
||||
vec4 v = (ProjectionMatrix[3][3] == 0.0) ? vec4(viewvec, 1.0) : vec4(0.0, 0.0, 1.0, 1.0);
|
||||
vec4 co_homogenous = (ProjectionMatrixInverse * v);
|
||||
vec4 co_homogeneous = (ProjectionMatrixInverse * v);
|
||||
|
||||
vec4 co = vec4(co_homogenous.xyz / co_homogenous.w, 0.0);
|
||||
vec4 co = vec4(co_homogeneous.xyz / co_homogeneous.w, 0.0);
|
||||
return (ViewMatrixInverse * co).xyz;
|
||||
}
|
||||
|
||||
|
|
|
@ -387,7 +387,7 @@ void gpencil_light_pool_populate(GPENCIL_LightPool *lightpool, Object *ob)
|
|||
normalize_m4_m4(mat, ob->obmat);
|
||||
invert_m4(mat);
|
||||
gp_light->type = GP_LIGHT_TYPE_SPOT;
|
||||
gp_light->spotsize = cosf(M_PI * 0.5f);
|
||||
gp_light->spotsize = cosf(M_PI_2);
|
||||
gp_light->spotblend = (1.0f - gp_light->spotsize) * 1.0f;
|
||||
}
|
||||
else if (la->type == LA_SUN) {
|
||||
|
|
|
@ -442,7 +442,7 @@ void stroke_vertex()
|
|||
if (is_dot) {
|
||||
# ifdef GP_MATERIAL_BUFFER_LEN
|
||||
int alignement = GP_FLAG(m) & GP_STROKE_ALIGNMENT;
|
||||
/* For one point strokes use object aligment. */
|
||||
/* For one point strokes use object alignment. */
|
||||
if (ma.x == -1 && ma2.x == -1 && alignement == GP_STROKE_ALIGNMENT_STROKE) {
|
||||
alignement = GP_STROKE_ALIGNMENT_OBJECT;
|
||||
}
|
||||
|
|
|
@ -2123,7 +2123,7 @@ static bool pchan_culling_test_bbone(const DRWView *view,
|
|||
BoundSphere bsphere;
|
||||
float size[3];
|
||||
mat4_to_size(size, bbones_mat->mat);
|
||||
copy_v3_v3(bsphere.center, bbones_mat->mat[3]);
|
||||
mul_v3_m4v3(bsphere.center, ob->obmat, bbones_mat->mat[3]);
|
||||
bsphere.radius = len_v3(size) * ob_scale;
|
||||
if (DRW_culling_sphere_test(view, &bsphere)) {
|
||||
return true;
|
||||
|
|
|
@ -90,8 +90,8 @@ static void motion_path_get_frame_range_to_draw(bAnimVizSettings *avs,
|
|||
end = current_frame + avs->path_ac + 1;
|
||||
}
|
||||
else {
|
||||
start = mpath->start_frame;
|
||||
end = mpath->end_frame;
|
||||
start = avs->path_sf;
|
||||
end = avs->path_ef;
|
||||
}
|
||||
|
||||
if (start > end) {
|
||||
|
|
|
@ -275,7 +275,7 @@ void workbench_update_world_ubo(WORKBENCH_PrivateData *wpd)
|
|||
copy_v2_v2(wd.viewport_size_inv, DRW_viewport_invert_size_get());
|
||||
copy_v3_v3(wd.object_outline_color, wpd->shading.object_outline_color);
|
||||
wd.object_outline_color[3] = 1.0f;
|
||||
wd.ui_scale = G_draw.block.sizePixel;
|
||||
wd.ui_scale = DRW_state_is_image_render() ? 1.0f : G_draw.block.sizePixel;
|
||||
wd.matcap_orientation = (wpd->shading.flag & V3D_SHADING_MATCAP_FLIP_X) != 0;
|
||||
|
||||
workbench_studiolight_data_update(wpd, &wd);
|
||||
|
|
|
@ -31,22 +31,22 @@ static void square_to_circle(float x, float y, float *r, float *T)
|
|||
if (x > -y) {
|
||||
if (x > y) {
|
||||
*r = x;
|
||||
*T = (M_PI / 4.0f) * (y / x);
|
||||
*T = M_PI_4 * (y / x);
|
||||
}
|
||||
else {
|
||||
*r = y;
|
||||
*T = (M_PI / 4.0f) * (2 - (x / y));
|
||||
*T = M_PI_4 * (2 - (x / y));
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (x < y) {
|
||||
*r = -x;
|
||||
*T = (M_PI / 4.0f) * (4 + (y / x));
|
||||
*T = M_PI_4 * (4 + (y / x));
|
||||
}
|
||||
else {
|
||||
*r = -y;
|
||||
if (y != 0) {
|
||||
*T = (M_PI / 4.0f) * (6 - (x / y));
|
||||
*T = M_PI_4 * (6 - (x / y));
|
||||
}
|
||||
else {
|
||||
*T = 0.0f;
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#define M_PI 3.14159265358979323846 /* pi */
|
||||
#define M_2PI 6.28318530717958647692 /* 2*pi */
|
||||
#define M_PI_2 1.57079632679489661923 /* pi/2 */
|
||||
#define M_PI_4 0.78539816339744830962 /* pi/4 */
|
||||
#define M_1_PI 0.318309886183790671538 /* 1/pi */
|
||||
#define M_1_2PI 0.159154943091895335768 /* 1/(2*pi) */
|
||||
#define M_1_PI2 0.101321183642337771443 /* 1/(pi^2) */
|
||||
|
@ -93,7 +94,7 @@ vec2 sqr(vec2 a) { return a * a; }
|
|||
vec3 sqr(vec3 a) { return a * a; }
|
||||
vec4 sqr(vec4 a) { return a * a; }
|
||||
|
||||
/* Use manual powers for fixed powers. pow() can have unpredicatble results on some implementations.
|
||||
/* Use manual powers for fixed powers. pow() can have unpredictable results on some implementations.
|
||||
* (see T87369, T87541) */
|
||||
float pow6(float x) { return sqr(sqr(x) * x); }
|
||||
float pow8(float x) { return sqr(sqr(sqr(x))); }
|
||||
|
|
|
@ -14,6 +14,8 @@ set(INC
|
|||
../../../../intern/clog
|
||||
../../../../intern/glew-mx
|
||||
../../../../intern/guardedalloc
|
||||
# RNA_prototypes.h
|
||||
${CMAKE_BINARY_DIR}/source/blender/makesrna
|
||||
)
|
||||
|
||||
|
||||
|
@ -52,6 +54,9 @@ endif()
|
|||
|
||||
blender_add_lib(bf_editor_animation "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
|
||||
|
||||
# RNA_prototypes.h
|
||||
add_dependencies(bf_editor_animation bf_rna)
|
||||
|
||||
if(WITH_GTESTS)
|
||||
set(TEST_SRC
|
||||
keyframes_keylist_test.cc
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include "DNA_world_types.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
#include "RNA_prototypes.h"
|
||||
|
||||
#include "BKE_anim_data.h"
|
||||
#include "BKE_animsys.h"
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue