WIP: Experiment: Geometry Nodes: support baking individual simulations #112179

Closed
Jacques Lucke wants to merge 51 commits from JacquesLucke/blender:simulation-bake-individual into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
170 changed files with 1868 additions and 1381 deletions
Showing only changes of commit 5523451243 - Show all commits

View File

@ -1681,9 +1681,13 @@ class CyclesPreferences(bpy.types.AddonPreferences):
import _cycles
has_peer_memory = 0
has_rt_api_support = False
for device in _cycles.available_devices(compute_device_type):
if device[3] and self.find_existing_device_entry(device).use:
has_peer_memory += 1
if device[4] and self.find_existing_device_entry(device).use:
has_rt_api_support = True
if has_peer_memory > 1:
row = layout.row()
row.use_property_split = True
@ -1700,13 +1704,14 @@ class CyclesPreferences(bpy.types.AddonPreferences):
# MetalRT only works on Apple Silicon and Navi2.
is_arm64 = platform.machine() == 'arm64'
if is_arm64 or is_navi_2:
if is_arm64 or (is_navi_2 and has_rt_api_support):
col = layout.column()
col.use_property_split = True
# Kernel specialization is only supported on Apple Silicon
if is_arm64:
col.prop(self, "kernel_optimization_level")
col.prop(self, "use_metalrt")
if has_rt_api_support:
col.prop(self, "use_metalrt")
if compute_device_type == 'HIP':
has_cuda, has_optix, has_hip, has_metal, has_oneapi, has_hiprt = _cycles.get_device_types()

View File

@ -410,11 +410,12 @@ static PyObject *available_devices_func(PyObject * /*self*/, PyObject *args)
for (size_t i = 0; i < devices.size(); i++) {
DeviceInfo &device = devices[i];
string type_name = Device::string_from_type(device.type);
PyObject *device_tuple = PyTuple_New(4);
PyObject *device_tuple = PyTuple_New(5);
PyTuple_SET_ITEM(device_tuple, 0, pyunicode_from_string(device.description.c_str()));
PyTuple_SET_ITEM(device_tuple, 1, pyunicode_from_string(type_name.c_str()));
PyTuple_SET_ITEM(device_tuple, 2, pyunicode_from_string(device.id.c_str()));
PyTuple_SET_ITEM(device_tuple, 3, PyBool_FromLong(device.has_peer_memory));
PyTuple_SET_ITEM(device_tuple, 4, PyBool_FromLong(device.use_hardware_raytracing));
PyTuple_SET_ITEM(ret, i, device_tuple);
}

View File

@ -22,7 +22,9 @@ class BVHMetal : public BVH {
API_AVAILABLE(macos(11.0))
vector<id<MTLAccelerationStructure>> blas_array;
vector<uint32_t> blas_lookup;
API_AVAILABLE(macos(11.0))
vector<id<MTLAccelerationStructure>> unique_blas_array;
bool motion_blur = false;

View File

@ -132,6 +132,7 @@ bool BVHMetal::build_BLAS_mesh(Progress &progress,
geomDescMotion.indexType = MTLIndexTypeUInt32;
geomDescMotion.triangleCount = num_indices / 3;
geomDescMotion.intersectionFunctionTableOffset = 0;
geomDescMotion.opaque = true;
geomDesc = geomDescMotion;
}
@ -146,6 +147,7 @@ bool BVHMetal::build_BLAS_mesh(Progress &progress,
geomDescNoMotion.indexType = MTLIndexTypeUInt32;
geomDescNoMotion.triangleCount = num_indices / 3;
geomDescNoMotion.intersectionFunctionTableOffset = 0;
geomDescNoMotion.opaque = true;
geomDesc = geomDescNoMotion;
}
@ -165,6 +167,7 @@ bool BVHMetal::build_BLAS_mesh(Progress &progress,
accelDesc.motionEndBorderMode = MTLMotionBorderModeClamp;
accelDesc.motionKeyframeCount = num_motion_steps;
}
accelDesc.usage |= MTLAccelerationStructureUsageExtendedLimits;
if (!use_fast_trace_bvh) {
accelDesc.usage |= (MTLAccelerationStructureUsageRefit |
@ -255,7 +258,8 @@ bool BVHMetal::build_BLAS_hair(Progress &progress,
Geometry *const geom,
bool refit)
{
if (@available(macos 12.0, *)) {
# if defined(MAC_OS_VERSION_14_0)
if (@available(macos 14.0, *)) {
/* Build BLAS for hair curves */
Hair *hair = static_cast<Hair *>(geom);
if (hair->num_curves() == 0) {
@ -268,7 +272,6 @@ bool BVHMetal::build_BLAS_hair(Progress &progress,
/*------------------------------------------------*/
const bool use_fast_trace_bvh = (params.bvh_type == BVH_TYPE_STATIC);
const size_t num_segments = hair->num_segments();
size_t num_motion_steps = 1;
Attribute *motion_keys = hair->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
@ -276,8 +279,6 @@ bool BVHMetal::build_BLAS_hair(Progress &progress,
num_motion_steps = hair->get_motion_steps();
}
const size_t num_aabbs = num_segments * num_motion_steps;
MTLResourceOptions storage_mode;
if (device.hasUnifiedMemory) {
storage_mode = MTLResourceStorageModeShared;
@ -286,91 +287,197 @@ bool BVHMetal::build_BLAS_hair(Progress &progress,
storage_mode = MTLResourceStorageModeManaged;
}
/* Allocate a GPU buffer for the AABB data and populate it */
id<MTLBuffer> aabbBuf = [device
newBufferWithLength:num_aabbs * sizeof(MTLAxisAlignedBoundingBox)
options:storage_mode];
MTLAxisAlignedBoundingBox *aabb_data = (MTLAxisAlignedBoundingBox *)[aabbBuf contents];
/* Get AABBs for each motion step */
size_t center_step = (num_motion_steps - 1) / 2;
for (size_t step = 0; step < num_motion_steps; ++step) {
/* The center step for motion vertices is not stored in the attribute */
const float3 *keys = hair->get_curve_keys().data();
if (step != center_step) {
size_t attr_offset = (step > center_step) ? step - 1 : step;
/* Technically this is a float4 array, but sizeof(float3) == sizeof(float4) */
keys = motion_keys->data_float3() + attr_offset * hair->get_curve_keys().size();
}
for (size_t j = 0, i = 0; j < hair->num_curves(); ++j) {
const Hair::Curve curve = hair->get_curve(j);
for (int segment = 0; segment < curve.num_segments(); ++segment, ++i) {
{
BoundBox bounds = BoundBox::empty;
curve.bounds_grow(segment, keys, hair->get_curve_radius().data(), bounds);
const size_t index = step * num_segments + i;
aabb_data[index].min = (MTLPackedFloat3 &)bounds.min;
aabb_data[index].max = (MTLPackedFloat3 &)bounds.max;
}
}
}
}
if (storage_mode == MTLResourceStorageModeManaged) {
[aabbBuf didModifyRange:NSMakeRange(0, aabbBuf.length)];
}
# if 0
for (size_t i=0; i<num_aabbs && i < 400; i++) {
MTLAxisAlignedBoundingBox& bb = aabb_data[i];
printf(" %d: %.1f,%.1f,%.1f -- %.1f,%.1f,%.1f\n", int(i), bb.min.x, bb.min.y, bb.min.z, bb.max.x, bb.max.y, bb.max.z);
}
# endif
id<MTLBuffer> cpBuffer = nil;
id<MTLBuffer> radiusBuffer = nil;
id<MTLBuffer> idxBuffer = nil;
MTLAccelerationStructureGeometryDescriptor *geomDesc;
if (motion_blur) {
std::vector<MTLMotionKeyframeData *> aabb_ptrs;
aabb_ptrs.reserve(num_motion_steps);
MTLAccelerationStructureMotionCurveGeometryDescriptor *geomDescCrv =
[MTLAccelerationStructureMotionCurveGeometryDescriptor descriptor];
uint64_t numKeys = hair->num_keys();
uint64_t numCurves = hair->num_curves();
const array<float> &radiuses = hair->get_curve_radius();
/* Gather the curve geometry. */
std::vector<float3> cpData;
std::vector<int> idxData;
std::vector<float> radiusData;
cpData.reserve(numKeys);
radiusData.reserve(numKeys);
std::vector<int> step_offsets;
for (size_t step = 0; step < num_motion_steps; ++step) {
MTLMotionKeyframeData *k = [MTLMotionKeyframeData data];
k.buffer = aabbBuf;
k.offset = step * num_segments * sizeof(MTLAxisAlignedBoundingBox);
aabb_ptrs.push_back(k);
/* The center step for motion vertices is not stored in the attribute. */
const float3 *keys = hair->get_curve_keys().data();
size_t center_step = (num_motion_steps - 1) / 2;
if (step != center_step) {
size_t attr_offset = (step > center_step) ? step - 1 : step;
/* Technically this is a float4 array, but sizeof(float3) == sizeof(float4). */
keys = motion_keys->data_float3() + attr_offset * numKeys;
}
step_offsets.push_back(cpData.size());
for (int c = 0; c < numCurves; ++c) {
const Hair::Curve curve = hair->get_curve(c);
int segCount = curve.num_segments();
int firstKey = curve.first_key;
uint64_t idxBase = cpData.size();
cpData.push_back(keys[firstKey]);
radiusData.push_back(radiuses[firstKey]);
for (int s = 0; s < segCount; ++s) {
if (step == 0) {
idxData.push_back(idxBase + s);
}
cpData.push_back(keys[firstKey + s]);
radiusData.push_back(radiuses[firstKey + s]);
}
cpData.push_back(keys[firstKey + curve.num_keys - 1]);
cpData.push_back(keys[firstKey + curve.num_keys - 1]);
radiusData.push_back(radiuses[firstKey + curve.num_keys - 1]);
radiusData.push_back(radiuses[firstKey + curve.num_keys - 1]);
}
}
MTLAccelerationStructureMotionBoundingBoxGeometryDescriptor *geomDescMotion =
[MTLAccelerationStructureMotionBoundingBoxGeometryDescriptor descriptor];
geomDescMotion.boundingBoxBuffers = [NSArray arrayWithObjects:aabb_ptrs.data()
count:aabb_ptrs.size()];
geomDescMotion.boundingBoxCount = num_segments;
geomDescMotion.boundingBoxStride = sizeof(aabb_data[0]);
geomDescMotion.intersectionFunctionTableOffset = 1;
/* Allocate and populate MTLBuffers for geometry. */
idxBuffer = [device newBufferWithBytes:idxData.data()
length:idxData.size() * sizeof(int)
options:storage_mode];
cpBuffer = [device newBufferWithBytes:cpData.data()
length:cpData.size() * sizeof(float3)
options:storage_mode];
radiusBuffer = [device newBufferWithBytes:radiusData.data()
length:radiusData.size() * sizeof(float)
options:storage_mode];
std::vector<MTLMotionKeyframeData *> cp_ptrs;
std::vector<MTLMotionKeyframeData *> radius_ptrs;
cp_ptrs.reserve(num_motion_steps);
radius_ptrs.reserve(num_motion_steps);
for (size_t step = 0; step < num_motion_steps; ++step) {
MTLMotionKeyframeData *k = [MTLMotionKeyframeData data];
k.buffer = cpBuffer;
k.offset = step_offsets[step] * sizeof(float3);
cp_ptrs.push_back(k);
k = [MTLMotionKeyframeData data];
k.buffer = radiusBuffer;
k.offset = step_offsets[step] * sizeof(float);
radius_ptrs.push_back(k);
}
if (storage_mode == MTLResourceStorageModeManaged) {
[cpBuffer didModifyRange:NSMakeRange(0, cpBuffer.length)];
[idxBuffer didModifyRange:NSMakeRange(0, idxBuffer.length)];
[radiusBuffer didModifyRange:NSMakeRange(0, radiusBuffer.length)];
}
geomDescCrv.controlPointBuffers = [NSArray arrayWithObjects:cp_ptrs.data()
count:cp_ptrs.size()];
geomDescCrv.radiusBuffers = [NSArray arrayWithObjects:radius_ptrs.data()
count:radius_ptrs.size()];
geomDescCrv.controlPointCount = cpData.size();
geomDescCrv.controlPointStride = sizeof(float3);
geomDescCrv.controlPointFormat = MTLAttributeFormatFloat3;
geomDescCrv.radiusStride = sizeof(float);
geomDescCrv.radiusFormat = MTLAttributeFormatFloat;
geomDescCrv.segmentCount = idxData.size();
geomDescCrv.segmentControlPointCount = 4;
geomDescCrv.curveType = (hair->curve_shape == CURVE_RIBBON) ? MTLCurveTypeFlat :
MTLCurveTypeRound;
geomDescCrv.curveBasis = MTLCurveBasisCatmullRom;
geomDescCrv.curveEndCaps = MTLCurveEndCapsDisk;
geomDescCrv.indexType = MTLIndexTypeUInt32;
geomDescCrv.indexBuffer = idxBuffer;
geomDescCrv.intersectionFunctionTableOffset = 1;
/* Force a single any-hit call, so shadow record-all behavior works correctly */
/* (Match optix behavior: unsigned int build_flags =
* OPTIX_GEOMETRY_FLAG_REQUIRE_SINGLE_ANYHIT_CALL;) */
geomDescMotion.allowDuplicateIntersectionFunctionInvocation = false;
geomDescMotion.opaque = true;
geomDesc = geomDescMotion;
geomDescCrv.allowDuplicateIntersectionFunctionInvocation = false;
geomDescCrv.opaque = true;
geomDesc = geomDescCrv;
}
else {
MTLAccelerationStructureBoundingBoxGeometryDescriptor *geomDescNoMotion =
[MTLAccelerationStructureBoundingBoxGeometryDescriptor descriptor];
geomDescNoMotion.boundingBoxBuffer = aabbBuf;
geomDescNoMotion.boundingBoxBufferOffset = 0;
geomDescNoMotion.boundingBoxCount = int(num_aabbs);
geomDescNoMotion.boundingBoxStride = sizeof(aabb_data[0]);
geomDescNoMotion.intersectionFunctionTableOffset = 1;
MTLAccelerationStructureCurveGeometryDescriptor *geomDescCrv =
[MTLAccelerationStructureCurveGeometryDescriptor descriptor];
uint64_t numKeys = hair->num_keys();
uint64_t numCurves = hair->num_curves();
const array<float> &radiuses = hair->get_curve_radius();
/* Gather the curve geometry. */
std::vector<float3> cpData;
std::vector<int> idxData;
std::vector<float> radiusData;
cpData.reserve(numKeys);
radiusData.reserve(numKeys);
auto keys = hair->get_curve_keys();
for (int c = 0; c < numCurves; ++c) {
const Hair::Curve curve = hair->get_curve(c);
int segCount = curve.num_segments();
int firstKey = curve.first_key;
radiusData.push_back(radiuses[firstKey]);
uint64_t idxBase = cpData.size();
cpData.push_back(keys[firstKey]);
for (int s = 0; s < segCount; ++s) {
idxData.push_back(idxBase + s);
cpData.push_back(keys[firstKey + s]);
radiusData.push_back(radiuses[firstKey + s]);
}
cpData.push_back(keys[firstKey + curve.num_keys - 1]);
cpData.push_back(keys[firstKey + curve.num_keys - 1]);
radiusData.push_back(radiuses[firstKey + curve.num_keys - 1]);
radiusData.push_back(radiuses[firstKey + curve.num_keys - 1]);
}
/* Allocate and populate MTLBuffers for geometry. */
idxBuffer = [device newBufferWithBytes:idxData.data()
length:idxData.size() * sizeof(int)
options:storage_mode];
cpBuffer = [device newBufferWithBytes:cpData.data()
length:cpData.size() * sizeof(float3)
options:storage_mode];
radiusBuffer = [device newBufferWithBytes:radiusData.data()
length:radiusData.size() * sizeof(float)
options:storage_mode];
if (storage_mode == MTLResourceStorageModeManaged) {
[cpBuffer didModifyRange:NSMakeRange(0, cpBuffer.length)];
[idxBuffer didModifyRange:NSMakeRange(0, idxBuffer.length)];
[radiusBuffer didModifyRange:NSMakeRange(0, radiusBuffer.length)];
}
geomDescCrv.controlPointBuffer = cpBuffer;
geomDescCrv.radiusBuffer = radiusBuffer;
geomDescCrv.controlPointCount = cpData.size();
geomDescCrv.controlPointStride = sizeof(float3);
geomDescCrv.controlPointFormat = MTLAttributeFormatFloat3;
geomDescCrv.controlPointBufferOffset = 0;
geomDescCrv.segmentCount = idxData.size();
geomDescCrv.segmentControlPointCount = 4;
geomDescCrv.curveType = (hair->curve_shape == CURVE_RIBBON) ? MTLCurveTypeFlat :
MTLCurveTypeRound;
geomDescCrv.curveBasis = MTLCurveBasisCatmullRom;
geomDescCrv.curveEndCaps = MTLCurveEndCapsDisk;
geomDescCrv.indexType = MTLIndexTypeUInt32;
geomDescCrv.indexBuffer = idxBuffer;
geomDescCrv.intersectionFunctionTableOffset = 1;
/* Force a single any-hit call, so shadow record-all behavior works correctly */
/* (Match optix behavior: unsigned int build_flags =
* OPTIX_GEOMETRY_FLAG_REQUIRE_SINGLE_ANYHIT_CALL;) */
geomDescNoMotion.allowDuplicateIntersectionFunctionInvocation = false;
geomDescNoMotion.opaque = true;
geomDesc = geomDescNoMotion;
geomDescCrv.allowDuplicateIntersectionFunctionInvocation = false;
geomDescCrv.opaque = true;
geomDesc = geomDescCrv;
}
MTLPrimitiveAccelerationStructureDescriptor *accelDesc =
@ -389,6 +496,7 @@ bool BVHMetal::build_BLAS_hair(Progress &progress,
accelDesc.usage |= (MTLAccelerationStructureUsageRefit |
MTLAccelerationStructureUsagePreferFastBuild);
}
accelDesc.usage |= MTLAccelerationStructureUsageExtendedLimits;
MTLAccelerationStructureSizes accelSizes = [device
accelerationStructureSizesWithDescriptor:accelDesc];
@ -423,10 +531,11 @@ bool BVHMetal::build_BLAS_hair(Progress &progress,
[accelCommands addCompletedHandler:^(id<MTLCommandBuffer> /*command_buffer*/) {
/* free temp resources */
[scratchBuf release];
[aabbBuf release];
[cpBuffer release];
[radiusBuffer release];
[idxBuffer release];
if (use_fast_trace_bvh) {
/* Compact the accel structure */
uint64_t compressed_size = *(uint64_t *)sizeBuf.contents;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
@ -461,8 +570,10 @@ bool BVHMetal::build_BLAS_hair(Progress &progress,
accel_struct_building = true;
[accelCommands commit];
return true;
}
# endif /* MAC_OS_VERSION_14_0 */
return false;
}
@ -605,10 +716,11 @@ bool BVHMetal::build_BLAS_pointcloud(Progress &progress,
if (motion_blur) {
accelDesc.motionStartTime = 0.0f;
accelDesc.motionEndTime = 1.0f;
accelDesc.motionStartBorderMode = MTLMotionBorderModeVanish;
accelDesc.motionEndBorderMode = MTLMotionBorderModeVanish;
// accelDesc.motionStartBorderMode = MTLMotionBorderModeVanish;
// accelDesc.motionEndBorderMode = MTLMotionBorderModeVanish;
accelDesc.motionKeyframeCount = num_motion_steps;
}
accelDesc.usage |= MTLAccelerationStructureUsageExtendedLimits;
if (!use_fast_trace_bvh) {
accelDesc.usage |= (MTLAccelerationStructureUsageRefit |
@ -756,10 +868,11 @@ bool BVHMetal::build_TLAS(Progress &progress,
uint32_t num_instances = 0;
uint32_t num_motion_transforms = 0;
for (Object *ob : objects) {
/* Skip non-traceable objects */
num_instances++;
/* Skip motion for non-traceable objects */
if (!ob->is_traceable())
continue;
num_instances++;
if (ob->use_motion()) {
num_motion_transforms += max((size_t)1, ob->get_motion().size());
@ -829,28 +942,40 @@ bool BVHMetal::build_TLAS(Progress &progress,
uint32_t instance_index = 0;
uint32_t motion_transform_index = 0;
// allocate look up buffer for wost case scenario
uint64_t count = objects.size();
blas_lookup.resize(count);
blas_array.clear();
blas_array.reserve(num_instances);
for (Object *ob : objects) {
/* Skip non-traceable objects */
if (!ob->is_traceable())
continue;
Geometry const *geom = ob->get_geometry();
BVHMetal const *blas = static_cast<BVHMetal const *>(geom->bvh);
if (!blas || !blas->accel_struct) {
/* Place a degenerate instance, to ensure [[instance_id]] equals ob->get_device_index()
* in our intersection functions */
if (motion_blur) {
MTLAccelerationStructureMotionInstanceDescriptor *instances =
(MTLAccelerationStructureMotionInstanceDescriptor *)[instanceBuf contents];
MTLAccelerationStructureMotionInstanceDescriptor &desc = instances[instance_index++];
memset(&desc, 0x00, sizeof(desc));
}
else {
MTLAccelerationStructureUserIDInstanceDescriptor *instances =
(MTLAccelerationStructureUserIDInstanceDescriptor *)[instanceBuf contents];
MTLAccelerationStructureUserIDInstanceDescriptor &desc = instances[instance_index++];
memset(&desc, 0x00, sizeof(desc));
}
blas_array.push_back(nil);
continue;
}
blas_array.push_back(blas->accel_struct);
uint32_t accel_struct_index = get_blas_index(blas);
/* Add some of the object visibility bits to the mask.
* __prim_visibility contains the combined visibility bits of all instances, so is not
* reliable if they differ between instances.
*
* METAL_WIP: OptiX visibility mask can only contain 8 bits, so have to trade-off here
* and select just a few important ones.
*/
uint32_t mask = ob->visibility_for_tracing() & 0xFF;
uint32_t mask = ob->visibility_for_tracing();
/* Have to have at least one bit in the mask, or else instance would always be culled. */
if (0 == mask) {
@ -858,11 +983,25 @@ bool BVHMetal::build_TLAS(Progress &progress,
}
/* Set user instance ID to object index */
int object_index = ob->get_device_index();
uint32_t user_id = uint32_t(object_index);
uint32_t primitive_offset = 0;
int currIndex = instance_index++;
assert(user_id < blas_lookup.size());
blas_lookup[user_id] = accel_struct_index;
if (geom->geometry_type == Geometry::HAIR) {
/* Build BLAS for curve primitives. */
Hair *const hair = static_cast<Hair *const>(const_cast<Geometry *>(geom));
primitive_offset = uint32_t(hair->curve_segment_offset);
}
else if (geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::VOLUME) {
/* Build BLAS for triangle primitives. */
Mesh *const mesh = static_cast<Mesh *const>(const_cast<Geometry *>(geom));
primitive_offset = uint32_t(mesh->prim_offset);
}
else if (geom->geometry_type == Geometry::POINTCLOUD) {
/* Build BLAS for points primitives. */
PointCloud *const pointcloud = static_cast<PointCloud *const>(
const_cast<Geometry *>(geom));
primitive_offset = uint32_t(pointcloud->prim_offset);
}
/* Bake into the appropriate descriptor */
if (motion_blur) {
@ -871,7 +1010,7 @@ bool BVHMetal::build_TLAS(Progress &progress,
MTLAccelerationStructureMotionInstanceDescriptor &desc = instances[currIndex];
desc.accelerationStructureIndex = accel_struct_index;
desc.userID = user_id;
desc.userID = primitive_offset;
desc.mask = mask;
desc.motionStartTime = 0.0f;
desc.motionEndTime = 1.0f;
@ -917,9 +1056,10 @@ bool BVHMetal::build_TLAS(Progress &progress,
MTLAccelerationStructureUserIDInstanceDescriptor &desc = instances[currIndex];
desc.accelerationStructureIndex = accel_struct_index;
desc.userID = user_id;
desc.userID = primitive_offset;
desc.mask = mask;
desc.intersectionFunctionTableOffset = 0;
desc.options = MTLAccelerationStructureInstanceOptionOpaque;
float *t = (float *)&desc.transformationMatrix;
if (ob->get_geometry()->is_instanced()) {
@ -959,6 +1099,7 @@ bool BVHMetal::build_TLAS(Progress &progress,
accelDesc.motionTransformCount = num_motion_transforms;
}
accelDesc.usage |= MTLAccelerationStructureUsageExtendedLimits;
if (!use_fast_trace_bvh) {
accelDesc.usage |= (MTLAccelerationStructureUsageRefit |
MTLAccelerationStructureUsagePreferFastBuild);
@ -1001,11 +1142,12 @@ bool BVHMetal::build_TLAS(Progress &progress,
/* Cache top and bottom-level acceleration structs */
accel_struct = accel;
blas_array.clear();
blas_array.reserve(all_blas.count);
for (id<MTLAccelerationStructure> blas in all_blas) {
blas_array.push_back(blas);
}
unique_blas_array.clear();
unique_blas_array.reserve(all_blas.count);
[all_blas enumerateObjectsUsingBlock:^(id<MTLAccelerationStructure> blas, NSUInteger, BOOL *) {
unique_blas_array.push_back(blas);
}];
return true;
}

View File

@ -62,12 +62,17 @@ void device_metal_info(vector<DeviceInfo> &devices)
info.has_light_tree = vendor != METAL_GPU_AMD;
info.has_mnee = vendor != METAL_GPU_AMD;
info.use_hardware_raytracing = vendor != METAL_GPU_INTEL;
if (info.use_hardware_raytracing) {
if (@available(macos 11.0, *)) {
info.use_hardware_raytracing = false;
/* MetalRT now uses features exposed in Xcode versions corresponding to macOS 14+, so don't
* expose it in builds from older Xcode versions. */
# if defined(MAC_OS_VERSION_14_0)
if (vendor != METAL_GPU_INTEL) {
if (@available(macos 14.0, *)) {
info.use_hardware_raytracing = device.supportsRaytracing;
}
}
# endif
devices.push_back(info);
device_index++;

View File

@ -82,7 +82,6 @@ class MetalDevice : public Device {
/* BLAS encoding & lookup */
id<MTLArgumentEncoder> mtlBlasArgEncoder = nil;
id<MTLBuffer> blas_buffer = nil;
id<MTLBuffer> blas_lookup_buffer = nil;
bool use_metalrt = false;
MetalPipelineType kernel_specialization_level = PSO_GENERIC;

View File

@ -81,7 +81,7 @@ MetalDevice::MetalDevice(const DeviceInfo &info, Stats &stats, Profiler &profile
mtlDevice = usable_devices[mtlDevId];
device_vendor = MetalInfo::get_device_vendor(mtlDevice);
assert(device_vendor != METAL_GPU_UNKNOWN);
metal_printf("Creating new Cycles device for Metal: %s\n", info.description.c_str());
metal_printf("Creating new Cycles Metal device: %s\n", info.description.c_str());
/* determine default storage mode based on whether UMA is supported */
@ -549,9 +549,14 @@ void MetalDevice::compile_and_load(int device_id, MetalPipelineType pso_type)
# endif
options.fastMathEnabled = YES;
if (@available(macOS 12.0, *)) {
if (@available(macos 12.0, *)) {
options.languageVersion = MTLLanguageVersion2_4;
}
# if defined(MAC_OS_VERSION_14_0)
if (@available(macos 14.0, *)) {
options.languageVersion = MTLLanguageVersion3_1;
}
# endif
if (getenv("CYCLES_METAL_PROFILING") || getenv("CYCLES_METAL_DEBUG")) {
path_write_text(path_cache_get(string_printf("%s.metal", kernel_type_as_string(pso_type))),
@ -1372,24 +1377,14 @@ void MetalDevice::build_bvh(BVH *bvh, Progress &progress, bool refit)
stats.mem_alloc(blas_buffer.allocatedSize);
for (uint64_t i = 0; i < count; ++i) {
[mtlBlasArgEncoder setArgumentBuffer:blas_buffer
offset:i * mtlBlasArgEncoder.encodedLength];
[mtlBlasArgEncoder setAccelerationStructure:bvhMetalRT->blas_array[i] atIndex:0];
if (bvhMetalRT->blas_array[i]) {
[mtlBlasArgEncoder setArgumentBuffer:blas_buffer
offset:i * mtlBlasArgEncoder.encodedLength];
[mtlBlasArgEncoder setAccelerationStructure:bvhMetalRT->blas_array[i] atIndex:0];
}
}
count = bvhMetalRT->blas_lookup.size();
bufferSize = sizeof(uint32_t) * count;
blas_lookup_buffer = [mtlDevice newBufferWithLength:bufferSize
options:default_storage_mode];
stats.mem_alloc(blas_lookup_buffer.allocatedSize);
memcpy([blas_lookup_buffer contents],
bvhMetalRT -> blas_lookup.data(),
blas_lookup_buffer.allocatedSize);
if (default_storage_mode == MTLResourceStorageModeManaged) {
[blas_buffer didModifyRange:NSMakeRange(0, blas_buffer.length)];
[blas_lookup_buffer didModifyRange:NSMakeRange(0, blas_lookup_buffer.length)];
}
}
}

View File

@ -22,10 +22,8 @@ enum {
METALRT_FUNC_LOCAL_BOX,
METALRT_FUNC_LOCAL_TRI_PRIM,
METALRT_FUNC_LOCAL_BOX_PRIM,
METALRT_FUNC_CURVE_RIBBON,
METALRT_FUNC_CURVE_RIBBON_SHADOW,
METALRT_FUNC_CURVE_ALL,
METALRT_FUNC_CURVE_ALL_SHADOW,
METALRT_FUNC_CURVE,
METALRT_FUNC_CURVE_SHADOW,
METALRT_FUNC_POINT,
METALRT_FUNC_POINT_SHADOW,
METALRT_FUNC_NUM

View File

@ -493,10 +493,8 @@ void MetalKernelPipeline::compile()
"__anyhit__cycles_metalrt_local_hit_box",
"__anyhit__cycles_metalrt_local_hit_tri_prim",
"__anyhit__cycles_metalrt_local_hit_box_prim",
"__intersection__curve_ribbon",
"__intersection__curve_ribbon_shadow",
"__intersection__curve_all",
"__intersection__curve_all_shadow",
"__intersection__curve",
"__intersection__curve_shadow",
"__intersection__point",
"__intersection__point_shadow",
};
@ -540,17 +538,8 @@ void MetalKernelPipeline::compile()
id<MTLFunction> point_intersect_default = nil;
id<MTLFunction> point_intersect_shadow = nil;
if (kernel_features & KERNEL_FEATURE_HAIR) {
/* Add curve intersection programs. */
if (kernel_features & KERNEL_FEATURE_HAIR_THICK) {
/* Slower programs for thick hair since that also slows down ribbons.
* Ideally this should not be needed. */
curve_intersect_default = rt_intersection_function[METALRT_FUNC_CURVE_ALL];
curve_intersect_shadow = rt_intersection_function[METALRT_FUNC_CURVE_ALL_SHADOW];
}
else {
curve_intersect_default = rt_intersection_function[METALRT_FUNC_CURVE_RIBBON];
curve_intersect_shadow = rt_intersection_function[METALRT_FUNC_CURVE_RIBBON_SHADOW];
}
curve_intersect_default = rt_intersection_function[METALRT_FUNC_CURVE];
curve_intersect_shadow = rt_intersection_function[METALRT_FUNC_CURVE_SHADOW];
}
if (kernel_features & KERNEL_FEATURE_POINTCLOUD) {
point_intersect_default = rt_intersection_function[METALRT_FUNC_POINT];
@ -585,8 +574,8 @@ void MetalKernelPipeline::compile()
rt_intersection_function[METALRT_FUNC_LOCAL_BOX_PRIM],
nil];
NSMutableSet *unique_functions = [NSMutableSet
setWithArray:table_functions[METALRT_TABLE_DEFAULT]];
NSMutableSet *unique_functions = [[NSMutableSet alloc] init];
[unique_functions addObjectsFromArray:table_functions[METALRT_TABLE_DEFAULT]];
[unique_functions addObjectsFromArray:table_functions[METALRT_TABLE_SHADOW]];
[unique_functions addObjectsFromArray:table_functions[METALRT_TABLE_LOCAL]];
[unique_functions addObjectsFromArray:table_functions[METALRT_TABLE_LOCAL_PRIM]];

View File

@ -490,9 +490,6 @@ bool MetalDeviceQueue::enqueue(DeviceKernel kernel,
[metal_device_->mtlAncillaryArgEncoder setBuffer:metal_device_->blas_buffer
offset:0
atIndex:8];
[metal_device_->mtlAncillaryArgEncoder setBuffer:metal_device_->blas_lookup_buffer
offset:0
atIndex:9];
}
for (int table = 0; table < METALRT_TABLE_NUM; table++) {
@ -546,10 +543,8 @@ bool MetalDeviceQueue::enqueue(DeviceKernel kernel,
[mtlComputeCommandEncoder useResource:bvhMetalRT->accel_struct usage:MTLResourceUsageRead];
[mtlComputeCommandEncoder useResource:metal_device_->blas_buffer
usage:MTLResourceUsageRead];
[mtlComputeCommandEncoder useResource:metal_device_->blas_lookup_buffer
usage:MTLResourceUsageRead];
[mtlComputeCommandEncoder useResources:bvhMetalRT->blas_array.data()
count:bvhMetalRT->blas_array.size()
[mtlComputeCommandEncoder useResources:bvhMetalRT->unique_blas_array.data()
count:bvhMetalRT->unique_blas_array.size()
usage:MTLResourceUsageRead];
}
}

View File

@ -16,12 +16,6 @@ CCL_NAMESPACE_BEGIN
struct MetalRTIntersectionPayload {
RaySelfPrimitives self;
uint visibility;
float u, v;
int prim;
int type;
#if defined(__METALRT_MOTION__)
float time;
#endif
};
struct MetalRTIntersectionLocalPayload {
@ -37,9 +31,6 @@ struct MetalRTIntersectionLocalPayload {
struct MetalRTIntersectionShadowPayload {
RaySelfPrimitives self;
uint visibility;
#if defined(__METALRT_MOTION__)
float time;
#endif
int state;
float throughput;
short max_hits;
@ -48,6 +39,98 @@ struct MetalRTIntersectionShadowPayload {
bool result;
};
ccl_device_forceinline bool curve_ribbon_accept(
KernelGlobals kg, float u, float t, ccl_private const Ray *ray, int object, int prim, int type)
{
KernelCurve kcurve = kernel_data_fetch(curves, prim);
int k0 = kcurve.first_key + PRIMITIVE_UNPACK_SEGMENT(type);
int k1 = k0 + 1;
int ka = max(k0 - 1, kcurve.first_key);
int kb = min(k1 + 1, kcurve.first_key + kcurve.num_keys - 1);
/* We can ignore motion blur here because we don't need the positions, and it doesn't affect the
* radius. */
float radius[4];
radius[0] = kernel_data_fetch(curve_keys, ka).w;
radius[1] = kernel_data_fetch(curve_keys, k0).w;
radius[2] = kernel_data_fetch(curve_keys, k1).w;
radius[3] = kernel_data_fetch(curve_keys, kb).w;
const float r = metal::catmull_rom(u, radius[0], radius[1], radius[2], radius[3]);
/* MPJ TODO: Can we ignore motion and/or object transforms here? Depends on scaling? */
float3 ray_P = ray->P;
float3 ray_D = ray->D;
if (!(kernel_data_fetch(object_flag, object) & SD_OBJECT_TRANSFORM_APPLIED)) {
float3 idir;
#if defined(__METALRT_MOTION__)
bvh_instance_motion_push(NULL, object, ray, &ray_P, &ray_D, &idir);
#else
bvh_instance_push(NULL, object, ray, &ray_P, &ray_D, &idir);
#endif
}
/* ignore self intersections */
const float avoidance_factor = 2.0f;
return t * len(ray_D) > avoidance_factor * r;
}
ccl_device_forceinline float curve_ribbon_v(
KernelGlobals kg, float u, float t, ccl_private const Ray *ray, int object, int prim, int type)
{
#if defined(__METALRT_MOTION__)
float time = ray->time;
#else
float time = 0.0f;
#endif
const bool is_motion = (type & PRIMITIVE_MOTION);
KernelCurve kcurve = kernel_data_fetch(curves, prim);
int k0 = kcurve.first_key + PRIMITIVE_UNPACK_SEGMENT(type);
int k1 = k0 + 1;
int ka = max(k0 - 1, kcurve.first_key);
int kb = min(k1 + 1, kcurve.first_key + kcurve.num_keys - 1);
float4 curve[4];
if (!is_motion) {
curve[0] = kernel_data_fetch(curve_keys, ka);
curve[1] = kernel_data_fetch(curve_keys, k0);
curve[2] = kernel_data_fetch(curve_keys, k1);
curve[3] = kernel_data_fetch(curve_keys, kb);
}
else {
motion_curve_keys(kg, object, prim, time, ka, k0, k1, kb, curve);
}
float3 ray_P = ray->P;
float3 ray_D = ray->D;
if (!(kernel_data_fetch(object_flag, object) & SD_OBJECT_TRANSFORM_APPLIED)) {
float3 idir;
#if defined(__METALRT_MOTION__)
bvh_instance_motion_push(NULL, object, ray, &ray_P, &ray_D, &idir);
#else
bvh_instance_push(NULL, object, ray, &ray_P, &ray_D, &idir);
#endif
}
const float4 P_curve4 = metal::catmull_rom(u, curve[0], curve[1], curve[2], curve[3]);
const float r_curve = P_curve4.w;
float3 P = ray_P + ray_D * t;
const float3 P_curve = float4_to_float3(P_curve4);
const float4 dPdu4 = metal::catmull_rom_derivative(u, curve[0], curve[1], curve[2], curve[3]);
const float3 dPdu = float4_to_float3(dPdu4);
const float3 tangent = normalize(dPdu);
const float3 bitangent = normalize(cross(tangent, -ray_D));
float v = dot(P - P_curve, bitangent) / r_curve;
return clamp(v, -1.0, 1.0f);
}
/* Scene intersection. */
ccl_device_intersect bool scene_intersect(KernelGlobals kg,
@ -79,41 +162,34 @@ ccl_device_intersect bool scene_intersect(KernelGlobals kg,
metal::raytracing::ray r(ray->P, ray->D, ray->tmin, ray->tmax);
metalrt_intersector_type metalrt_intersect;
metalrt_intersect.force_opacity(metal::raytracing::forced_opacity::non_opaque);
metalrt_intersect.assume_geometry_type(
metal::raytracing::geometry_type::triangle |
(kernel_data.bvh.have_curves ? metal::raytracing::geometry_type::curve :
metal::raytracing::geometry_type::none) |
(kernel_data.bvh.have_points ? metal::raytracing::geometry_type::bounding_box :
metal::raytracing::geometry_type::none));
bool triangle_only = !kernel_data.bvh.have_curves && !kernel_data.bvh.have_points;
if (triangle_only) {
metalrt_intersect.assume_geometry_type(metal::raytracing::geometry_type::triangle);
if (visibility & PATH_RAY_SHADOW_OPAQUE) {
metalrt_intersect.accept_any_intersection(true);
}
MetalRTIntersectionPayload payload;
payload.self = ray->self;
payload.u = 0.0f;
payload.v = 0.0f;
payload.visibility = visibility;
typename metalrt_intersector_type::result_type intersection;
uint ray_mask = visibility & 0xFF;
if (0 == ray_mask && (visibility & ~0xFF) != 0) {
ray_mask = 0xFF;
/* No further intersector setup required: Default MetalRT behavior is any-hit. */
}
else if (visibility & PATH_RAY_SHADOW_OPAQUE) {
/* No further intersector setup required: Shadow ray early termination is controlled by the
* intersection handler */
}
#if defined(__METALRT_MOTION__)
payload.time = ray->time;
intersection = metalrt_intersect.intersect(r,
metal_ancillaries->accel_struct,
ray_mask,
visibility,
ray->time,
metal_ancillaries->ift_default,
payload);
#else
intersection = metalrt_intersect.intersect(
r, metal_ancillaries->accel_struct, ray_mask, metal_ancillaries->ift_default, payload);
r, metal_ancillaries->accel_struct, visibility, metal_ancillaries->ift_default, payload);
#endif
if (intersection.type == intersection_type::none) {
@ -123,23 +199,71 @@ ccl_device_intersect bool scene_intersect(KernelGlobals kg,
return false;
}
isect->t = intersection.distance;
isect->prim = payload.prim;
isect->type = payload.type;
isect->object = intersection.user_instance_id;
isect->object = intersection.instance_id;
isect->t = intersection.distance;
if (intersection.type == intersection_type::triangle) {
isect->prim = intersection.primitive_id + intersection.user_instance_id;
isect->type = kernel_data_fetch(objects, intersection.instance_id).primitive_type;
isect->u = intersection.triangle_barycentric_coord.x;
isect->v = intersection.triangle_barycentric_coord.y;
}
else {
isect->u = payload.u;
isect->v = payload.v;
else if (kernel_data.bvh.have_curves && intersection.type == intersection_type::curve) {
int prim = intersection.primitive_id + intersection.user_instance_id;
const KernelCurveSegment segment = kernel_data_fetch(curve_segments, prim);
isect->prim = segment.prim;
isect->type = segment.type;
isect->u = intersection.curve_parameter;
if (segment.type & PRIMITIVE_CURVE_RIBBON) {
isect->v = curve_ribbon_v(kg,
intersection.curve_parameter,
intersection.distance,
ray,
intersection.instance_id,
segment.prim,
segment.type);
}
else {
isect->v = 0.0f;
}
}
else if (kernel_data.bvh.have_points && intersection.type == intersection_type::bounding_box) {
const int object = intersection.instance_id;
const uint prim = intersection.primitive_id + intersection.user_instance_id;
const int prim_type = kernel_data_fetch(objects, object).primitive_type;
if (!(kernel_data_fetch(object_flag, object) & SD_OBJECT_TRANSFORM_APPLIED)) {
float3 idir;
#if defined(__METALRT_MOTION__)
bvh_instance_motion_push(NULL, object, ray, &r.origin, &r.direction, &idir);
#else
bvh_instance_push(NULL, object, ray, &r.origin, &r.direction, &idir);
#endif
}
if (prim_type & PRIMITIVE_POINT) {
if (!point_intersect(NULL,
isect,
r.origin,
r.direction,
ray->tmin,
ray->tmax,
object,
prim,
ray->time,
prim_type))
{
/* Shouldn't get here */
kernel_assert(!"Intersection mismatch");
isect->t = ray->tmax;
isect->type = PRIMITIVE_NONE;
return false;
}
return true;
}
}
return isect->type != PRIMITIVE_NONE;
return true;
}
#ifdef __BVH_LOCAL__
@ -198,25 +322,18 @@ ccl_device_intersect bool scene_intersect_local(KernelGlobals kg,
# if defined(__METALRT_MOTION__)
metalrt_intersector_type metalrt_intersect;
typename metalrt_intersector_type::result_type intersection;
metalrt_intersect.force_opacity(metal::raytracing::forced_opacity::non_opaque);
bool triangle_only = !kernel_data.bvh.have_curves && !kernel_data.bvh.have_points;
if (triangle_only) {
metalrt_intersect.assume_geometry_type(metal::raytracing::geometry_type::triangle);
}
intersection = metalrt_intersect.intersect(
r, metal_ancillaries->accel_struct, 0xFF, ray->time, metal_ancillaries->ift_local, payload);
# else
metalrt_blas_intersector_type metalrt_intersect;
typename metalrt_blas_intersector_type::result_type intersection;
# endif
metalrt_intersect.force_opacity(metal::raytracing::forced_opacity::non_opaque);
bool triangle_only = !kernel_data.bvh.have_curves && !kernel_data.bvh.have_points;
if (triangle_only) {
metalrt_intersect.assume_geometry_type(metal::raytracing::geometry_type::triangle);
}
metalrt_intersect.assume_geometry_type(
metal::raytracing::geometry_type::triangle |
(kernel_data.bvh.have_curves ? metal::raytracing::geometry_type::curve :
metal::raytracing::geometry_type::none) |
(kernel_data.bvh.have_points ? metal::raytracing::geometry_type::bounding_box :
metal::raytracing::geometry_type::none));
// if we know we are going to get max one hit, like for random-sss-walk we can
// optimize and accept the first hit
@ -224,8 +341,10 @@ ccl_device_intersect bool scene_intersect_local(KernelGlobals kg,
metalrt_intersect.accept_any_intersection(true);
}
int blas_index = metal_ancillaries->blas_userID_to_index_lookUp[local_object];
# if defined(__METALRT_MOTION__)
intersection = metalrt_intersect.intersect(
r, metal_ancillaries->accel_struct, ~0, ray->time, metal_ancillaries->ift_local, payload);
# else
if (!(kernel_data_fetch(object_flag, local_object) & SD_OBJECT_TRANSFORM_APPLIED)) {
// transform the ray into object's local space
Transform itfm = kernel_data_fetch(objects, local_object).itfm;
@ -235,7 +354,7 @@ ccl_device_intersect bool scene_intersect_local(KernelGlobals kg,
intersection = metalrt_intersect.intersect(
r,
metal_ancillaries->blas_accel_structs[blas_index].blas,
metal_ancillaries->blas_accel_structs[local_object].blas,
metal_ancillaries->ift_local_prim,
payload);
# endif
@ -278,13 +397,13 @@ ccl_device_intersect bool scene_intersect_shadow_all(KernelGlobals kg,
metal::raytracing::ray r(ray->P, ray->D, ray->tmin, ray->tmax);
metalrt_intersector_type metalrt_intersect;
metalrt_intersect.force_opacity(metal::raytracing::forced_opacity::non_opaque);
bool triangle_only = !kernel_data.bvh.have_curves && !kernel_data.bvh.have_points;
if (triangle_only) {
metalrt_intersect.assume_geometry_type(metal::raytracing::geometry_type::triangle);
}
metalrt_intersect.assume_geometry_type(
metal::raytracing::geometry_type::triangle |
(kernel_data.bvh.have_curves ? metal::raytracing::geometry_type::curve :
metal::raytracing::geometry_type::none) |
(kernel_data.bvh.have_points ? metal::raytracing::geometry_type::bounding_box :
metal::raytracing::geometry_type::none));
MetalRTIntersectionShadowPayload payload;
payload.self = ray->self;
@ -296,24 +415,18 @@ ccl_device_intersect bool scene_intersect_shadow_all(KernelGlobals kg,
payload.result = false;
payload.state = state;
uint ray_mask = visibility & 0xFF;
if (0 == ray_mask && (visibility & ~0xFF) != 0) {
ray_mask = 0xFF;
}
typename metalrt_intersector_type::result_type intersection;
# if defined(__METALRT_MOTION__)
payload.time = ray->time;
intersection = metalrt_intersect.intersect(r,
metal_ancillaries->accel_struct,
ray_mask,
visibility,
ray->time,
metal_ancillaries->ift_shadow,
payload);
# else
intersection = metalrt_intersect.intersect(
r, metal_ancillaries->accel_struct, ray_mask, metal_ancillaries->ift_shadow, payload);
r, metal_ancillaries->accel_struct, visibility, metal_ancillaries->ift_shadow, payload);
# endif
*num_recorded_hits = payload.num_recorded_hits;
@ -347,13 +460,13 @@ ccl_device_intersect bool scene_intersect_volume(KernelGlobals kg,
metal::raytracing::ray r(ray->P, ray->D, ray->tmin, ray->tmax);
metalrt_intersector_type metalrt_intersect;
metalrt_intersect.force_opacity(metal::raytracing::forced_opacity::non_opaque);
bool triangle_only = !kernel_data.bvh.have_curves && !kernel_data.bvh.have_points;
if (triangle_only) {
metalrt_intersect.assume_geometry_type(metal::raytracing::geometry_type::triangle);
}
metalrt_intersect.assume_geometry_type(
metal::raytracing::geometry_type::triangle |
(kernel_data.bvh.have_curves ? metal::raytracing::geometry_type::curve :
metal::raytracing::geometry_type::none) |
(kernel_data.bvh.have_points ? metal::raytracing::geometry_type::bounding_box :
metal::raytracing::geometry_type::none));
MetalRTIntersectionPayload payload;
payload.self = ray->self;
@ -361,43 +474,86 @@ ccl_device_intersect bool scene_intersect_volume(KernelGlobals kg,
typename metalrt_intersector_type::result_type intersection;
uint ray_mask = visibility & 0xFF;
if (0 == ray_mask && (visibility & ~0xFF) != 0) {
ray_mask = 0xFF;
}
# if defined(__METALRT_MOTION__)
payload.time = ray->time;
intersection = metalrt_intersect.intersect(r,
metal_ancillaries->accel_struct,
ray_mask,
visibility,
ray->time,
metal_ancillaries->ift_default,
payload);
# else
intersection = metalrt_intersect.intersect(
r, metal_ancillaries->accel_struct, ray_mask, metal_ancillaries->ift_default, payload);
r, metal_ancillaries->accel_struct, visibility, metal_ancillaries->ift_default, payload);
# endif
if (intersection.type == intersection_type::none) {
return false;
}
isect->prim = payload.prim;
isect->type = payload.type;
isect->object = intersection.user_instance_id;
isect->t = intersection.distance;
if (intersection.type == intersection_type::triangle) {
else if (intersection.type == intersection_type::triangle) {
isect->prim = intersection.primitive_id + intersection.user_instance_id;
isect->type = kernel_data_fetch(objects, intersection.instance_id).primitive_type;
isect->u = intersection.triangle_barycentric_coord.x;
isect->v = intersection.triangle_barycentric_coord.y;
isect->object = intersection.instance_id;
isect->t = intersection.distance;
}
else {
isect->u = payload.u;
isect->v = payload.v;
else if (kernel_data.bvh.have_curves && intersection.type == intersection_type::curve) {
int prim = intersection.primitive_id + intersection.user_instance_id;
const KernelCurveSegment segment = kernel_data_fetch(curve_segments, prim);
isect->prim = segment.prim;
isect->type = segment.type;
isect->u = intersection.curve_parameter;
if (segment.type & PRIMITIVE_CURVE_RIBBON) {
isect->v = curve_ribbon_v(kg,
intersection.curve_parameter,
intersection.distance,
ray,
intersection.instance_id,
segment.prim,
segment.type);
}
else {
isect->v = 0.0f;
}
}
else if (kernel_data.bvh.have_points && intersection.type == intersection_type::bounding_box) {
const int object = intersection.instance_id;
const uint prim = intersection.primitive_id + intersection.user_instance_id;
const int prim_type = kernel_data_fetch(objects, intersection.instance_id).primitive_type;
isect->object = object;
if (!(kernel_data_fetch(object_flag, object) & SD_OBJECT_TRANSFORM_APPLIED)) {
float3 idir;
# if defined(__METALRT_MOTION__)
bvh_instance_motion_push(NULL, object, ray, &r.origin, &r.direction, &idir);
# else
bvh_instance_push(NULL, object, ray, &r.origin, &r.direction, &idir);
# endif
}
if (prim_type & PRIMITIVE_POINT) {
if (!point_intersect(NULL,
isect,
r.origin,
r.direction,
ray->tmin,
ray->tmax,
intersection.instance_id,
prim,
ray->time,
prim_type))
{
/* Shouldn't get here */
kernel_assert(!"Intersection mismatch");
return false;
}
return true;
}
}
return isect->type != PRIMITIVE_NONE;
return true;
}
#endif

View File

@ -27,6 +27,8 @@ using namespace metal::raytracing;
#pragma clang diagnostic ignored "-Wunused-variable"
#pragma clang diagnostic ignored "-Wsign-compare"
#pragma clang diagnostic ignored "-Wuninitialized"
#pragma clang diagnostic ignored "-Wc++17-extensions"
#pragma clang diagnostic ignored "-Wmacro-redefined"
/* Qualifiers */
@ -280,17 +282,23 @@ ccl_device_forceinline uchar4 make_uchar4(const uchar x,
# endif /* __METALRT_MOTION__ */
typedef acceleration_structure<METALRT_TAGS> metalrt_as_type;
typedef intersection_function_table<triangle_data, METALRT_TAGS> metalrt_ift_type;
typedef metal::raytracing::intersector<triangle_data, METALRT_TAGS> metalrt_intersector_type;
typedef intersection_function_table<triangle_data, curve_data, METALRT_TAGS, extended_limits>
metalrt_ift_type;
typedef metal::raytracing::intersector<triangle_data, curve_data, METALRT_TAGS, extended_limits>
metalrt_intersector_type;
# if defined(__METALRT_MOTION__)
typedef acceleration_structure<primitive_motion> metalrt_blas_as_type;
typedef intersection_function_table<triangle_data, primitive_motion> metalrt_blas_ift_type;
typedef metal::raytracing::intersector<triangle_data, primitive_motion>
metalrt_blas_intersector_type;
typedef intersection_function_table<triangle_data, curve_data, primitive_motion, extended_limits>
metalrt_blas_ift_type;
typedef metal::raytracing::
intersector<triangle_data, curve_data, primitive_motion, extended_limits>
metalrt_blas_intersector_type;
# else
typedef acceleration_structure<> metalrt_blas_as_type;
typedef intersection_function_table<triangle_data> metalrt_blas_ift_type;
typedef metal::raytracing::intersector<triangle_data> metalrt_blas_intersector_type;
typedef intersection_function_table<triangle_data, curve_data, extended_limits>
metalrt_blas_ift_type;
typedef metal::raytracing::intersector<triangle_data, curve_data, extended_limits>
metalrt_blas_intersector_type;
# endif
#endif /* __METALRT__ */
@ -326,7 +334,6 @@ struct MetalAncillaries {
metalrt_ift_type ift_local;
metalrt_blas_ift_type ift_local_prim;
constant MetalRTBlasWrapper *blas_accel_structs;
constant int *blas_userID_to_index_lookUp;
#endif
};

View File

@ -26,13 +26,13 @@ struct BoundingBoxIntersectionResult {
float distance [[distance]];
};
/* For a triangle intersection function. */
struct TriangleIntersectionResult {
/* For a primitive intersection function. */
struct PrimitiveIntersectionResult {
bool accept [[accept_intersection]];
bool continue_search [[continue_search]];
};
enum { METALRT_HIT_TRIANGLE, METALRT_HIT_BOUNDING_BOX };
enum { METALRT_HIT_TRIANGLE, METALRT_HIT_CURVE, METALRT_HIT_BOUNDING_BOX };
/* Hit functions. */
@ -40,15 +40,13 @@ template<typename TReturn, uint intersection_type>
TReturn metalrt_local_hit(constant KernelParamsMetal &launch_params_metal,
ray_data MetalKernelContext::MetalRTIntersectionLocalPayload &payload,
const uint object,
const uint primitive_id,
const uint prim,
const float2 barycentrics,
const float ray_tmax)
{
TReturn result;
# ifdef __BVH_LOCAL__
uint prim = primitive_id + kernel_data_fetch(object_prim_offset, object);
MetalKernelContext context(launch_params_metal);
if ((object != payload.local_object) || context.intersection_skip_self_local(payload.self, prim))
@ -124,7 +122,7 @@ TReturn metalrt_local_hit(constant KernelParamsMetal &launch_params_metal,
# endif
}
[[intersection(triangle, triangle_data)]] TriangleIntersectionResult
[[intersection(triangle, triangle_data, curve_data)]] PrimitiveIntersectionResult
__anyhit__cycles_metalrt_local_hit_tri_prim(
constant KernelParamsMetal &launch_params_metal [[buffer(1)]],
ray_data MetalKernelContext::MetalRTIntersectionLocalPayload &payload [[payload]],
@ -132,27 +130,43 @@ __anyhit__cycles_metalrt_local_hit_tri_prim(
float2 barycentrics [[barycentric_coord]],
float ray_tmax [[distance]])
{
uint prim = primitive_id + kernel_data_fetch(object_prim_offset, payload.local_object);
/* instance_id, aka the user_id has been removed. If we take this function we optimized the
* SSS for starting traversal from a primitive acceleration structure instead of the root of the
* global AS. this means we will always be intersecting the correct object no need for the
* user-id to check */
return metalrt_local_hit<TriangleIntersectionResult, METALRT_HIT_TRIANGLE>(
launch_params_metal, payload, payload.local_object, primitive_id, barycentrics, ray_tmax);
return metalrt_local_hit<PrimitiveIntersectionResult, METALRT_HIT_TRIANGLE>(
launch_params_metal, payload, payload.local_object, prim, barycentrics, ray_tmax);
}
[[intersection(triangle, triangle_data, METALRT_TAGS)]] TriangleIntersectionResult
[[intersection(triangle,
triangle_data,
curve_data,
METALRT_TAGS,
extended_limits)]] PrimitiveIntersectionResult
__anyhit__cycles_metalrt_local_hit_tri(
constant KernelParamsMetal &launch_params_metal [[buffer(1)]],
ray_data MetalKernelContext::MetalRTIntersectionLocalPayload &payload [[payload]],
uint instance_id [[user_instance_id]],
uint instance_id [[instance_id]],
uint primitive_id [[primitive_id]],
uint primitive_id_offset [[user_instance_id]],
float2 barycentrics [[barycentric_coord]],
float ray_tmax [[distance]])
{
return metalrt_local_hit<TriangleIntersectionResult, METALRT_HIT_TRIANGLE>(
launch_params_metal, payload, instance_id, primitive_id, barycentrics, ray_tmax);
return metalrt_local_hit<PrimitiveIntersectionResult, METALRT_HIT_TRIANGLE>(
launch_params_metal,
payload,
instance_id,
primitive_id + primitive_id_offset,
barycentrics,
ray_tmax);
}
[[intersection(bounding_box, triangle_data, METALRT_TAGS)]] BoundingBoxIntersectionResult
[[intersection(bounding_box,
triangle_data,
curve_data,
METALRT_TAGS,
extended_limits)]] BoundingBoxIntersectionResult
__anyhit__cycles_metalrt_local_hit_box(const float ray_tmax [[max_distance]])
{
/* unused function */
@ -163,7 +177,7 @@ __anyhit__cycles_metalrt_local_hit_box(const float ray_tmax [[max_distance]])
return result;
}
[[intersection(bounding_box, triangle_data)]] BoundingBoxIntersectionResult
[[intersection(bounding_box, triangle_data, curve_data)]] BoundingBoxIntersectionResult
__anyhit__cycles_metalrt_local_hit_box_prim(const float ray_tmax [[max_distance]])
{
/* unused function */
@ -180,30 +194,31 @@ bool metalrt_shadow_all_hit(constant KernelParamsMetal &launch_params_metal,
uint object,
uint prim,
const float2 barycentrics,
const float ray_tmax)
const float ray_tmax,
const float t = 0.0f,
ccl_private const Ray *ray = NULL)
{
# ifdef __SHADOW_RECORD_ALL__
# ifdef __VISIBILITY_FLAG__
const uint visibility = payload.visibility;
if ((kernel_data_fetch(objects, object).visibility & visibility) == 0) {
/* continue search */
return true;
}
# endif
const float u = barycentrics.x;
const float v = barycentrics.y;
float u = barycentrics.x;
float v = barycentrics.y;
const int prim_type = kernel_data_fetch(objects, object).primitive_type;
int type = prim_type;
# ifdef __HAIR__
if (intersection_type != METALRT_HIT_TRIANGLE) {
if ((prim_type == PRIMITIVE_CURVE_THICK || prim_type == PRIMITIVE_CURVE_RIBBON)) {
const KernelCurveSegment segment = kernel_data_fetch(curve_segments, prim);
type = segment.type;
prim = segment.prim;
int type;
/* Filter out curve end-caps. */
if (u == 0.0f || u == 1.0f) {
# ifdef __HAIR__
if constexpr (intersection_type == METALRT_HIT_CURVE) {
const KernelCurveSegment segment = kernel_data_fetch(curve_segments, prim);
type = segment.type;
prim = segment.prim;
/* Filter out curve end-caps. */
if (u == 0.0f || u == 1.0f) {
/* continue search */
return true;
}
if (type & PRIMITIVE_CURVE_RIBBON) {
MetalKernelContext context(launch_params_metal);
if (!context.curve_ribbon_accept(NULL, u, t, ray, object, prim, type)) {
/* continue search */
return true;
}
@ -211,6 +226,17 @@ bool metalrt_shadow_all_hit(constant KernelParamsMetal &launch_params_metal,
}
# endif
if constexpr (intersection_type == METALRT_HIT_BOUNDING_BOX) {
/* Point. */
type = kernel_data_fetch(objects, object).primitive_type;
u = 0.0f;
v = 0.0f;
}
if constexpr (intersection_type == METALRT_HIT_TRIANGLE) {
type = prim_type;
}
MetalKernelContext context(launch_params_metal);
if (context.intersection_skip_self_shadow(payload.self, object, prim)) {
@ -244,8 +270,9 @@ bool metalrt_shadow_all_hit(constant KernelParamsMetal &launch_params_metal,
return false;
}
# ifdef __HAIR__
/* Always use baked shadow transparency for curves. */
if (type & PRIMITIVE_CURVE) {
if constexpr (intersection_type == METALRT_HIT_CURVE) {
float throughput = payload.throughput;
throughput *= context.intersection_curve_shadow_transparency(nullptr, object, prim, type, u);
payload.throughput = throughput;
@ -260,6 +287,7 @@ bool metalrt_shadow_all_hit(constant KernelParamsMetal &launch_params_metal,
return true;
}
}
# endif
payload.num_hits += 1;
payload.num_recorded_hits += 1;
@ -305,25 +333,34 @@ bool metalrt_shadow_all_hit(constant KernelParamsMetal &launch_params_metal,
return true;
}
[[intersection(triangle, triangle_data, METALRT_TAGS)]] TriangleIntersectionResult
[[intersection(triangle,
triangle_data,
curve_data,
METALRT_TAGS,
extended_limits)]] PrimitiveIntersectionResult
__anyhit__cycles_metalrt_shadow_all_hit_tri(
constant KernelParamsMetal &launch_params_metal [[buffer(1)]],
ray_data MetalKernelContext::MetalRTIntersectionShadowPayload &payload [[payload]],
unsigned int object [[user_instance_id]],
unsigned int primitive_id [[primitive_id]],
float2 barycentrics [[barycentric_coord]],
float ray_tmax [[distance]])
const unsigned int object [[instance_id]],
const unsigned int primitive_id [[primitive_id]],
const uint primitive_id_offset [[user_instance_id]],
const float2 barycentrics [[barycentric_coord]],
const float ray_tmax [[distance]])
{
uint prim = primitive_id + kernel_data_fetch(object_prim_offset, object);
uint prim = primitive_id + primitive_id_offset;
TriangleIntersectionResult result;
PrimitiveIntersectionResult result;
result.continue_search = metalrt_shadow_all_hit<METALRT_HIT_TRIANGLE>(
launch_params_metal, payload, object, prim, barycentrics, ray_tmax);
result.accept = !result.continue_search;
return result;
}
[[intersection(bounding_box, triangle_data, METALRT_TAGS)]] BoundingBoxIntersectionResult
[[intersection(bounding_box,
triangle_data,
curve_data,
METALRT_TAGS,
extended_limits)]] BoundingBoxIntersectionResult
__anyhit__cycles_metalrt_shadow_all_hit_box(const float ray_tmax [[max_distance]])
{
/* unused function */
@ -340,40 +377,37 @@ inline TReturnType metalrt_visibility_test(
ray_data MetalKernelContext::MetalRTIntersectionPayload &payload,
const uint object,
uint prim,
const float u)
const float u,
const float t = 0.0f,
ccl_private const Ray *ray = NULL)
{
TReturnType result;
# ifdef __HAIR__
const int type = kernel_data_fetch(objects, object).primitive_type;
if (intersection_type == METALRT_HIT_BOUNDING_BOX &&
(type == PRIMITIVE_CURVE_THICK || type == PRIMITIVE_CURVE_RIBBON))
{
if constexpr (intersection_type == METALRT_HIT_CURVE) {
/* Filter out curve end-caps. */
if (u == 0.0f || u == 1.0f) {
result.accept = false;
result.continue_search = true;
return result;
}
const KernelCurveSegment segment = kernel_data_fetch(curve_segments, prim);
int type = segment.type;
prim = segment.prim;
if (type & PRIMITIVE_CURVE_RIBBON) {
MetalKernelContext context(launch_params_metal);
if (!context.curve_ribbon_accept(NULL, u, t, ray, object, prim, type)) {
result.accept = false;
result.continue_search = true;
return result;
}
}
}
# endif
uint visibility = payload.visibility;
# ifdef __VISIBILITY_FLAG__
if ((kernel_data_fetch(objects, object).visibility & visibility) == 0) {
result.accept = false;
result.continue_search = true;
return result;
}
# endif
if (intersection_type == METALRT_HIT_TRIANGLE) {
}
# ifdef __HAIR__
else {
prim = kernel_data_fetch(curve_segments, prim).prim;
}
# endif
MetalKernelContext context(launch_params_metal);
@ -411,25 +445,30 @@ inline TReturnType metalrt_visibility_test(
return result;
}
[[intersection(triangle, triangle_data, METALRT_TAGS)]] TriangleIntersectionResult
[[intersection(triangle,
triangle_data,
curve_data,
METALRT_TAGS,
extended_limits)]] PrimitiveIntersectionResult
__anyhit__cycles_metalrt_visibility_test_tri(
constant KernelParamsMetal &launch_params_metal [[buffer(1)]],
ray_data MetalKernelContext::MetalRTIntersectionPayload &payload [[payload]],
unsigned int object [[user_instance_id]],
unsigned int primitive_id [[primitive_id]])
const unsigned int object [[instance_id]],
const uint primitive_id_offset [[user_instance_id]],
const unsigned int primitive_id [[primitive_id]])
{
uint prim = primitive_id + kernel_data_fetch(object_prim_offset, object);
TriangleIntersectionResult result =
metalrt_visibility_test<TriangleIntersectionResult, METALRT_HIT_TRIANGLE>(
uint prim = primitive_id + primitive_id_offset;
PrimitiveIntersectionResult result =
metalrt_visibility_test<PrimitiveIntersectionResult, METALRT_HIT_TRIANGLE>(
launch_params_metal, payload, object, prim, 0.0f);
if (result.accept) {
payload.prim = prim;
payload.type = kernel_data_fetch(objects, object).primitive_type;
}
return result;
}
[[intersection(bounding_box, triangle_data, METALRT_TAGS)]] BoundingBoxIntersectionResult
[[intersection(bounding_box,
triangle_data,
curve_data,
METALRT_TAGS,
extended_limits)]] BoundingBoxIntersectionResult
__anyhit__cycles_metalrt_visibility_test_box(const float ray_tmax [[max_distance]])
{
/* Unused function */
@ -443,229 +482,73 @@ __anyhit__cycles_metalrt_visibility_test_box(const float ray_tmax [[max_distance
/* Primitive intersection functions. */
# ifdef __HAIR__
ccl_device_inline void metalrt_intersection_curve(
constant KernelParamsMetal &launch_params_metal,
ray_data MetalKernelContext::MetalRTIntersectionPayload &payload,
const uint object,
const uint prim,
const uint type,
const float3 ray_P,
const float3 ray_D,
float time,
const float ray_tmin,
const float ray_tmax,
thread BoundingBoxIntersectionResult &result)
[[intersection(
curve, triangle_data, curve_data, METALRT_TAGS, extended_limits)]] PrimitiveIntersectionResult
__intersection__curve(constant KernelParamsMetal &launch_params_metal [[buffer(1)]],
ray_data MetalKernelContext::MetalRTIntersectionPayload &payload [[payload]],
const uint object [[instance_id]],
const uint primitive_id [[primitive_id]],
const uint primitive_id_offset [[user_instance_id]],
float distance [[distance]],
const float3 ray_P [[origin]],
const float3 ray_D [[direction]],
float u [[curve_parameter]],
const float ray_tmin [[min_distance]],
const float ray_tmax [[max_distance]]
# if defined(__METALRT_MOTION__)
,
const float time [[time]]
# endif
)
{
# ifdef __VISIBILITY_FLAG__
const uint visibility = payload.visibility;
if ((kernel_data_fetch(objects, object).visibility & visibility) == 0) {
return;
}
uint prim = primitive_id + primitive_id_offset;
Ray ray;
ray.P = ray_P;
ray.D = ray_D;
# if defined(__METALRT_MOTION__)
ray.time = time;
# endif
Intersection isect;
isect.t = ray_tmax;
PrimitiveIntersectionResult result =
metalrt_visibility_test<PrimitiveIntersectionResult, METALRT_HIT_CURVE>(
launch_params_metal, payload, object, prim, u, distance, &ray);
MetalKernelContext context(launch_params_metal);
if (context.curve_intersect(
NULL, &isect, ray_P, ray_D, ray_tmin, isect.t, object, prim, time, type))
{
result = metalrt_visibility_test<BoundingBoxIntersectionResult, METALRT_HIT_BOUNDING_BOX>(
launch_params_metal, payload, object, prim, isect.u);
if (result.accept) {
result.distance = isect.t;
payload.u = isect.u;
payload.v = isect.v;
payload.prim = prim;
payload.type = type;
}
}
return result;
}
ccl_device_inline void metalrt_intersection_curve_shadow(
constant KernelParamsMetal &launch_params_metal,
ray_data MetalKernelContext::MetalRTIntersectionShadowPayload &payload,
const uint object,
const uint prim,
const uint type,
const float3 ray_P,
const float3 ray_D,
float time,
const float ray_tmin,
const float ray_tmax,
thread BoundingBoxIntersectionResult &result)
{
# ifdef __VISIBILITY_FLAG__
const uint visibility = payload.visibility;
if ((kernel_data_fetch(objects, object).visibility & visibility) == 0) {
return;
}
# endif
Intersection isect;
isect.t = ray_tmax;
MetalKernelContext context(launch_params_metal);
if (context.curve_intersect(
NULL, &isect, ray_P, ray_D, ray_tmin, isect.t, object, prim, time, type))
{
result.continue_search = metalrt_shadow_all_hit<METALRT_HIT_BOUNDING_BOX>(
launch_params_metal, payload, object, prim, float2(isect.u, isect.v), ray_tmax);
result.accept = !result.continue_search;
}
}
[[intersection(bounding_box, triangle_data, METALRT_TAGS)]] BoundingBoxIntersectionResult
__intersection__curve_ribbon(constant KernelParamsMetal &launch_params_metal [[buffer(1)]],
ray_data MetalKernelContext::MetalRTIntersectionPayload &payload
[[intersection(
curve, triangle_data, curve_data, METALRT_TAGS, extended_limits)]] PrimitiveIntersectionResult
__intersection__curve_shadow(constant KernelParamsMetal &launch_params_metal [[buffer(1)]],
ray_data MetalKernelContext::MetalRTIntersectionShadowPayload &payload
[[payload]],
const uint object [[user_instance_id]],
const uint object [[instance_id]],
const uint primitive_id [[primitive_id]],
const uint primitive_id_offset [[user_instance_id]],
const float3 ray_P [[origin]],
const float3 ray_D [[direction]],
float u [[curve_parameter]],
float t [[distance]],
# if defined(__METALRT_MOTION__)
const float time [[time]],
# endif
const float ray_tmin [[min_distance]],
const float ray_tmax [[max_distance]])
{
uint prim = primitive_id + kernel_data_fetch(object_prim_offset, object);
const KernelCurveSegment segment = kernel_data_fetch(curve_segments, prim);
uint prim = primitive_id + primitive_id_offset;
BoundingBoxIntersectionResult result;
result.accept = false;
result.continue_search = true;
result.distance = ray_tmax;
PrimitiveIntersectionResult result;
if (segment.type & PRIMITIVE_CURVE_RIBBON) {
metalrt_intersection_curve(launch_params_metal,
payload,
object,
segment.prim,
segment.type,
ray_P,
ray_D,
Ray ray;
ray.P = ray_P;
ray.D = ray_D;
# if defined(__METALRT_MOTION__)
payload.time,
# else
0.0f,
ray.time = time;
# endif
ray_tmin,
ray_tmax,
result);
}
return result;
}
[[intersection(bounding_box, triangle_data, METALRT_TAGS)]] BoundingBoxIntersectionResult
__intersection__curve_ribbon_shadow(
constant KernelParamsMetal &launch_params_metal [[buffer(1)]],
ray_data MetalKernelContext::MetalRTIntersectionShadowPayload &payload [[payload]],
const uint object [[user_instance_id]],
const uint primitive_id [[primitive_id]],
const float3 ray_P [[origin]],
const float3 ray_D [[direction]],
const float ray_tmin [[min_distance]],
const float ray_tmax [[max_distance]])
{
uint prim = primitive_id + kernel_data_fetch(object_prim_offset, object);
const KernelCurveSegment segment = kernel_data_fetch(curve_segments, prim);
BoundingBoxIntersectionResult result;
result.accept = false;
result.continue_search = true;
result.distance = ray_tmax;
if (segment.type & PRIMITIVE_CURVE_RIBBON) {
metalrt_intersection_curve_shadow(launch_params_metal,
payload,
object,
segment.prim,
segment.type,
ray_P,
ray_D,
# if defined(__METALRT_MOTION__)
payload.time,
# else
0.0f,
# endif
ray_tmin,
ray_tmax,
result);
}
return result;
}
[[intersection(bounding_box, triangle_data, METALRT_TAGS)]] BoundingBoxIntersectionResult
__intersection__curve_all(constant KernelParamsMetal &launch_params_metal [[buffer(1)]],
ray_data MetalKernelContext::MetalRTIntersectionPayload &payload
[[payload]],
const uint object [[user_instance_id]],
const uint primitive_id [[primitive_id]],
const float3 ray_P [[origin]],
const float3 ray_D [[direction]],
const float ray_tmin [[min_distance]],
const float ray_tmax [[max_distance]])
{
uint prim = primitive_id + kernel_data_fetch(object_prim_offset, object);
const KernelCurveSegment segment = kernel_data_fetch(curve_segments, prim);
BoundingBoxIntersectionResult result;
result.accept = false;
result.continue_search = true;
result.distance = ray_tmax;
metalrt_intersection_curve(launch_params_metal,
payload,
object,
segment.prim,
segment.type,
ray_P,
ray_D,
# if defined(__METALRT_MOTION__)
payload.time,
# else
0.0f,
# endif
ray_tmin,
ray_tmax,
result);
return result;
}
[[intersection(bounding_box, triangle_data, METALRT_TAGS)]] BoundingBoxIntersectionResult
__intersection__curve_all_shadow(
constant KernelParamsMetal &launch_params_metal [[buffer(1)]],
ray_data MetalKernelContext::MetalRTIntersectionShadowPayload &payload [[payload]],
const uint object [[user_instance_id]],
const uint primitive_id [[primitive_id]],
const float3 ray_P [[origin]],
const float3 ray_D [[direction]],
const float ray_tmin [[min_distance]],
const float ray_tmax [[max_distance]])
{
uint prim = primitive_id + kernel_data_fetch(object_prim_offset, object);
const KernelCurveSegment segment = kernel_data_fetch(curve_segments, prim);
BoundingBoxIntersectionResult result;
result.accept = false;
result.continue_search = true;
result.distance = ray_tmax;
metalrt_intersection_curve_shadow(launch_params_metal,
payload,
object,
segment.prim,
segment.type,
ray_P,
ray_D,
# if defined(__METALRT_MOTION__)
payload.time,
# else
0.0f,
# endif
ray_tmin,
ray_tmax,
result);
result.continue_search = metalrt_shadow_all_hit<METALRT_HIT_CURVE>(
launch_params_metal, payload, object, prim, float2(u, 0), ray_tmax, t, &ray);
result.accept = !result.continue_search;
return result;
}
@ -685,13 +568,6 @@ ccl_device_inline void metalrt_intersection_point(
const float ray_tmax,
thread BoundingBoxIntersectionResult &result)
{
# ifdef __VISIBILITY_FLAG__
const uint visibility = payload.visibility;
if ((kernel_data_fetch(objects, object).visibility & visibility) == 0) {
return;
}
# endif
Intersection isect;
isect.t = ray_tmax;
@ -703,10 +579,6 @@ ccl_device_inline void metalrt_intersection_point(
launch_params_metal, payload, object, prim, isect.u);
if (result.accept) {
result.distance = isect.t;
payload.u = isect.u;
payload.v = isect.v;
payload.prim = prim;
payload.type = type;
}
}
}
@ -724,13 +596,6 @@ ccl_device_inline void metalrt_intersection_point_shadow(
const float ray_tmax,
thread BoundingBoxIntersectionResult &result)
{
# ifdef __VISIBILITY_FLAG__
const uint visibility = payload.visibility;
if ((kernel_data_fetch(objects, object).visibility & visibility) == 0) {
return;
}
# endif
Intersection isect;
isect.t = ray_tmax;
@ -748,17 +613,25 @@ ccl_device_inline void metalrt_intersection_point_shadow(
}
}
[[intersection(bounding_box, triangle_data, METALRT_TAGS)]] BoundingBoxIntersectionResult
[[intersection(bounding_box,
triangle_data,
curve_data,
METALRT_TAGS,
extended_limits)]] BoundingBoxIntersectionResult
__intersection__point(constant KernelParamsMetal &launch_params_metal [[buffer(1)]],
ray_data MetalKernelContext::MetalRTIntersectionPayload &payload [[payload]],
const uint object [[user_instance_id]],
const uint object [[instance_id]],
const uint primitive_id [[primitive_id]],
const uint primitive_id_offset [[user_instance_id]],
const float3 ray_origin [[origin]],
const float3 ray_direction [[direction]],
# if defined(__METALRT_MOTION__)
const float time [[time]],
# endif
const float ray_tmin [[min_distance]],
const float ray_tmax [[max_distance]])
{
const uint prim = primitive_id + kernel_data_fetch(object_prim_offset, object);
const uint prim = primitive_id + primitive_id_offset;
const int type = kernel_data_fetch(objects, object).primitive_type;
BoundingBoxIntersectionResult result;
@ -774,7 +647,7 @@ __intersection__point(constant KernelParamsMetal &launch_params_metal [[buffer(1
ray_origin,
ray_direction,
# if defined(__METALRT_MOTION__)
payload.time,
time,
# else
0.0f,
# endif
@ -785,18 +658,26 @@ __intersection__point(constant KernelParamsMetal &launch_params_metal [[buffer(1
return result;
}
[[intersection(bounding_box, triangle_data, METALRT_TAGS)]] BoundingBoxIntersectionResult
[[intersection(bounding_box,
triangle_data,
curve_data,
METALRT_TAGS,
extended_limits)]] BoundingBoxIntersectionResult
__intersection__point_shadow(constant KernelParamsMetal &launch_params_metal [[buffer(1)]],
ray_data MetalKernelContext::MetalRTIntersectionShadowPayload &payload
[[payload]],
const uint object [[user_instance_id]],
const uint object [[instance_id]],
const uint primitive_id [[primitive_id]],
const uint primitive_id_offset [[user_instance_id]],
const float3 ray_origin [[origin]],
const float3 ray_direction [[direction]],
# if defined(__METALRT_MOTION__)
const float time [[time]],
# endif
const float ray_tmin [[min_distance]],
const float ray_tmax [[max_distance]])
{
const uint prim = primitive_id + kernel_data_fetch(object_prim_offset, object);
const uint prim = primitive_id + primitive_id_offset;
const int type = kernel_data_fetch(objects, object).primitive_type;
BoundingBoxIntersectionResult result;
@ -812,7 +693,7 @@ __intersection__point_shadow(constant KernelParamsMetal &launch_params_metal [[b
ray_origin,
ray_direction,
# if defined(__METALRT_MOTION__)
payload.time,
time,
# else
0.0f,
# endif

View File

@ -788,7 +788,7 @@ ccl_device_forceinline bool mnee_path_contribution(KernelGlobals kg,
const int diffuse_bounce = INTEGRATOR_STATE(state, path, diffuse_bounce);
const int bounce = INTEGRATOR_STATE(state, path, bounce);
/* Set diffuse bounce info . */
/* Set diffuse bounce info. */
INTEGRATOR_STATE_WRITE(state, path, diffuse_bounce) = diffuse_bounce + 1;
/* Evaluate light sample

View File

@ -31,6 +31,17 @@ struct ccl_align(8) LayerClosure
ccl_private const OSLClosure *top;
};
/* If we failed to allocate a layer-able closure, we need to zero out the albedo
* so that lower layers aren't falsely blocked.
* Therefore, to keep the code clean, set it to zero at the start and overwrite
* later if it succeeded. */
ccl_device_forceinline void osl_zero_albedo(float3 *layer_albedo)
{
if (layer_albedo != NULL) {
*layer_albedo = zero_float3();
}
}
ccl_device_forceinline bool osl_closure_skip(KernelGlobals kg,
ccl_private const ShaderData *sd,
uint32_t path_flag,
@ -182,6 +193,8 @@ ccl_device void osl_closure_dielectric_bsdf_setup(KernelGlobals kg,
ccl_private const DielectricBSDFClosure *closure,
float3 *layer_albedo)
{
osl_zero_albedo(layer_albedo);
const bool has_reflection = !is_zero(closure->reflection_tint);
const bool has_transmission = !is_zero(closure->transmission_tint);
@ -240,8 +253,13 @@ ccl_device void osl_closure_dielectric_bsdf_setup(KernelGlobals kg,
fresnel->transmission_tint = rgb_to_spectrum(closure->transmission_tint);
bsdf_microfacet_setup_fresnel_dielectric_tint(kg, bsdf, sd, fresnel, preserve_energy);
if (layer_albedo != NULL && has_reflection && !has_transmission) {
*layer_albedo = bsdf_albedo(kg, sd, (ccl_private ShaderClosure *)bsdf, true, false);
if (layer_albedo != NULL) {
if (has_reflection && !has_transmission) {
*layer_albedo = bsdf_albedo(kg, sd, (ccl_private ShaderClosure *)bsdf, true, false);
}
else {
*layer_albedo = one_float3();
}
}
}
@ -299,6 +317,8 @@ ccl_device void osl_closure_generalized_schlick_bsdf_setup(
ccl_private const GeneralizedSchlickBSDFClosure *closure,
float3 *layer_albedo)
{
osl_zero_albedo(layer_albedo);
const bool has_reflection = !is_zero(closure->reflection_tint);
const bool has_transmission = !is_zero(closure->transmission_tint);
@ -333,9 +353,6 @@ ccl_device void osl_closure_generalized_schlick_bsdf_setup(
else {
bsdf->ior = ior_from_F0(average(closure->f0));
}
if (sd->flag & SD_BACKFACING) {
bsdf->ior = 1.0f / bsdf->ior;
}
bool preserve_energy = false;
@ -373,8 +390,13 @@ ccl_device void osl_closure_generalized_schlick_bsdf_setup(
fresnel->exponent = closure->exponent;
bsdf_microfacet_setup_fresnel_generalized_schlick(kg, bsdf, sd, fresnel, preserve_energy);
if (layer_albedo != NULL && has_reflection && !has_transmission) {
*layer_albedo = bsdf_albedo(kg, sd, (ccl_private ShaderClosure *)bsdf, true, false);
if (layer_albedo != NULL) {
if (has_reflection && !has_transmission) {
*layer_albedo = bsdf_albedo(kg, sd, (ccl_private ShaderClosure *)bsdf, true, false);
}
else {
*layer_albedo = one_float3();
}
}
}
@ -387,6 +409,8 @@ ccl_device void osl_closure_microfacet_setup(KernelGlobals kg,
ccl_private const MicrofacetClosure *closure,
float3 *layer_albedo)
{
osl_zero_albedo(layer_albedo);
const int label = (closure->refract) ? LABEL_TRANSMIT : LABEL_REFLECT;
if (osl_closure_skip(kg, sd, path_flag, LABEL_GLOSSY | label)) {
return;
@ -438,8 +462,13 @@ ccl_device void osl_closure_microfacet_setup(KernelGlobals kg,
}
}
if (layer_albedo != NULL && closure->refract == 0) {
*layer_albedo = bsdf_albedo(kg, sd, (ccl_private ShaderClosure *)bsdf, true, false);
if (layer_albedo != NULL) {
if (closure->refract == 0) {
*layer_albedo = bsdf_albedo(kg, sd, (ccl_private ShaderClosure *)bsdf, true, false);
}
else {
*layer_albedo = one_float3();
}
}
}
@ -485,6 +514,8 @@ ccl_device void osl_closure_microfacet_multi_ggx_aniso_setup(
ccl_private const MicrofacetMultiGGXClosure *closure,
float3 *layer_albedo)
{
osl_zero_albedo(layer_albedo);
if (osl_closure_skip(kg, sd, path_flag, LABEL_GLOSSY | LABEL_REFLECT)) {
return;
}
@ -545,6 +576,8 @@ ccl_device void osl_closure_sheen_setup(KernelGlobals kg,
ccl_private const SheenClosure *closure,
float3 *layer_albedo)
{
osl_zero_albedo(layer_albedo);
if (osl_closure_skip(kg, sd, path_flag, LABEL_DIFFUSE)) {
return;
}

View File

@ -13,6 +13,14 @@ shader node_subsurface_scattering(color Color = 0.8,
normal Normal = N,
output closure color BSSRDF = 0)
{
BSSRDF = Color *
bssrdf(method, Normal, Scale * Radius, Color, "ior", IOR, "anisotropy", Anisotropy);
BSSRDF = Color * bssrdf(method,
Normal,
Scale * Radius,
Color,
"ior",
IOR,
"anisotropy",
Anisotropy,
"roughness",
1.0);
}

View File

@ -943,7 +943,7 @@ GHOST_TSuccess GHOST_ContextVK::initializeDrawingContext()
}
extensions_device.push_back("VK_KHR_dedicated_allocation");
extensions_device.push_back("VK_KHR_get_memory_requirements2");
/* Allow relaxed interface matching between shader stages.*/
/* Allow relaxed interface matching between shader stages. */
extensions_device.push_back("VK_KHR_maintenance4");
/* Enable MoltenVK required instance extensions. */
#ifdef VK_MVK_MOLTENVK_EXTENSION_NAME

View File

@ -5625,7 +5625,7 @@ GHOST_SystemWayland::GHOST_SystemWayland(bool background)
/* Ignore windowing requirements when running in background mode,
* as it doesn't make sense to fall back to X11 because of windowing functionality
* in background mode, also LIBDECOR is crashing in background mode `blender -b -f 1`
* for e.g. while it could be fixed, requiring the library at all makes no sense . */
* for e.g. while it could be fixed, requiring the library at all makes no sense. */
if (background) {
display_->libdecor_required = false;
}

View File

@ -100,7 +100,7 @@ extern void *(*MEM_callocN)(size_t len, const char *str) /* ATTR_MALLOC */ ATTR_
* Allocate a block of memory of size (len * size), with tag name
* str, aborting in case of integer overflows to prevent vulnerabilities.
* The memory is cleared. The name must be static, because only a
* pointer to it is stored ! */
* pointer to it is stored! */
extern void *(*MEM_calloc_arrayN)(size_t len,
size_t size,
const char *str) /* ATTR_MALLOC */ ATTR_WARN_UNUSED_RESULT
@ -108,7 +108,7 @@ extern void *(*MEM_calloc_arrayN)(size_t len,
/**
* Allocate a block of memory of size len, with tag name str. The
* name must be a static, because only a pointer to it is stored !
* name must be a static, because only a pointer to it is stored!
*/
extern void *(*MEM_mallocN)(size_t len, const char *str) /* ATTR_MALLOC */ ATTR_WARN_UNUSED_RESULT
ATTR_ALLOC_SIZE(1) ATTR_NONNULL(2);
@ -116,7 +116,7 @@ extern void *(*MEM_mallocN)(size_t len, const char *str) /* ATTR_MALLOC */ ATTR_
/**
* Allocate a block of memory of size (len * size), with tag name str,
* aborting in case of integer overflow to prevent vulnerabilities. The
* name must be a static, because only a pointer to it is stored !
* name must be a static, because only a pointer to it is stored!
*/
extern void *(*MEM_malloc_arrayN)(size_t len,
size_t size,
@ -125,7 +125,7 @@ extern void *(*MEM_malloc_arrayN)(size_t len,
/**
* Allocate an aligned block of memory of size len, with tag name str. The
* name must be a static, because only a pointer to it is stored !
* name must be a static, because only a pointer to it is stored!
*/
extern void *(*MEM_mallocN_aligned)(size_t len,
size_t alignment,

View File

@ -214,7 +214,7 @@ const UserDef U_default = {
.file_space_data =
{
.display_type = FILE_VERTICALDISPLAY,
.thumbnail_size = 128,
.thumbnail_size = 96,
.sort_type = FILE_SORT_ALPHA,
.details_flags = FILE_DETAILS_SIZE | FILE_DETAILS_DATETIME,
.flag = FILE_HIDE_DOT,

View File

@ -74,6 +74,8 @@ class Params:
"v3d_tilde_action",
# Alt-MMB axis switching 'RELATIVE' or 'ABSOLUTE' axis switching.
"v3d_alt_mmb_drag_action",
# Changes some transformers modal key-map items to avoid conflicts with navigation operations.
"use_alt_navigation",
# File selector actions on single click.
"use_file_single_click",
@ -106,8 +108,6 @@ class Params:
# Since this means with RMB select enabled in edit-mode for e.g.
# `Ctrl-LMB` would be caught by box-select instead of add/extrude.
"tool_maybe_tweak_event",
# Changes some transformers modal key-map items to avoid conflicts with navigation operations
"use_alt_navigation",
)
def __init__(
@ -131,10 +131,10 @@ class Params:
use_alt_tool_or_cursor=False,
use_alt_click_leader=False,
use_pie_click_drag=False,
use_alt_navigation=True,
use_file_single_click=False,
v3d_tilde_action='VIEW',
v3d_alt_mmb_drag_action='RELATIVE',
use_alt_navigation=True,
use_experimental_grease_pencil_version3=False,
):
from sys import platform
@ -209,6 +209,8 @@ class Params:
self.use_alt_click_leader = use_alt_click_leader
self.use_pie_click_drag = use_pie_click_drag
self.use_alt_navigation = use_alt_navigation
self.use_file_single_click = use_file_single_click
self.use_tweak_select_passthrough = not legacy
@ -235,7 +237,6 @@ class Params:
self.pie_value = 'CLICK_DRAG' if use_pie_click_drag else 'PRESS'
self.tool_tweak_event = {"type": self.tool_mouse, "value": 'CLICK_DRAG'}
self.tool_maybe_tweak_event = {"type": self.tool_mouse, "value": self.tool_maybe_tweak_value}
self.use_alt_navigation = use_alt_navigation
# ------------------------------------------------------------------------------
@ -3760,7 +3761,7 @@ def km_grease_pencil_stroke_edit_mode(params):
# Close strokes
("gpencil.stroke_cyclical_set", {"type": 'F', "value": 'PRESS'},
{"properties": [("type", 'CLOSE'), ("geometry", True)]}),
# Copy + paset
# Copy + paste.
("gpencil.copy", {"type": 'C', "value": 'PRESS', "ctrl": True}, None),
("gpencil.paste", {"type": 'V', "value": 'PRESS', "ctrl": True}, None),
# Snap
@ -6074,6 +6075,8 @@ def km_transform_modal_map(params):
{"items": items},
)
alt_without_navigaton = {} if params.use_alt_navigation else {"alt": True}
items.extend([
("CONFIRM", {"type": 'LEFTMOUSE', "value": 'PRESS', "any": True}, None),
("CONFIRM", {"type": 'RET', "value": 'PRESS', "any": True}, None),
@ -6108,24 +6111,24 @@ def km_transform_modal_map(params):
("PROPORTIONAL_SIZE_DOWN", {"type": 'PAGE_DOWN', "value": 'PRESS', "repeat": True}, None),
("PROPORTIONAL_SIZE_UP", {"type": 'PAGE_UP', "value": 'PRESS', "shift": True, "repeat": True}, None),
("PROPORTIONAL_SIZE_DOWN", {"type": 'PAGE_DOWN', "value": 'PRESS', "shift": True, "repeat": True}, None),
("PROPORTIONAL_SIZE_UP", {"type": 'WHEELDOWNMOUSE', "value": 'PRESS', "alt": not params.use_alt_navigation}, None),
("PROPORTIONAL_SIZE_DOWN", {"type": 'WHEELUPMOUSE', "value": 'PRESS', "alt": not params.use_alt_navigation}, None),
("PROPORTIONAL_SIZE_UP", {"type": 'WHEELDOWNMOUSE', "value": 'PRESS', **alt_without_navigaton}, None),
("PROPORTIONAL_SIZE_DOWN", {"type": 'WHEELUPMOUSE', "value": 'PRESS', **alt_without_navigaton}, None),
("PROPORTIONAL_SIZE_UP", {"type": 'WHEELDOWNMOUSE', "value": 'PRESS', "shift": True}, None),
("PROPORTIONAL_SIZE_DOWN", {"type": 'WHEELUPMOUSE', "value": 'PRESS', "shift": True}, None),
("PROPORTIONAL_SIZE", {"type": 'TRACKPADPAN', "value": 'ANY', "alt": not params.use_alt_navigation}, None),
("PROPORTIONAL_SIZE", {"type": 'TRACKPADPAN', "value": 'ANY', **alt_without_navigaton}, None),
("AUTOIK_CHAIN_LEN_UP", {"type": 'PAGE_UP', "value": 'PRESS', "repeat": True}, None),
("AUTOIK_CHAIN_LEN_DOWN", {"type": 'PAGE_DOWN', "value": 'PRESS', "repeat": True}, None),
("AUTOIK_CHAIN_LEN_UP", {"type": 'PAGE_UP', "value": 'PRESS', "shift": True, "repeat": True}, None),
("AUTOIK_CHAIN_LEN_DOWN", {"type": 'PAGE_DOWN', "value": 'PRESS', "shift": True, "repeat": True}, None),
("AUTOIK_CHAIN_LEN_UP", {"type": 'WHEELDOWNMOUSE', "value": 'PRESS', "alt": not params.use_alt_navigation}, None),
("AUTOIK_CHAIN_LEN_DOWN", {"type": 'WHEELUPMOUSE', "value": 'PRESS', "alt": not params.use_alt_navigation}, None),
("AUTOIK_CHAIN_LEN_UP", {"type": 'WHEELDOWNMOUSE', "value": 'PRESS', **alt_without_navigaton}, None),
("AUTOIK_CHAIN_LEN_DOWN", {"type": 'WHEELUPMOUSE', "value": 'PRESS', **alt_without_navigaton}, None),
("AUTOIK_CHAIN_LEN_UP", {"type": 'WHEELDOWNMOUSE', "value": 'PRESS', "shift": True}, None),
("AUTOIK_CHAIN_LEN_DOWN", {"type": 'WHEELUPMOUSE', "value": 'PRESS', "shift": True}, None),
("INSERTOFS_TOGGLE_DIR", {"type": 'T', "value": 'PRESS'}, None),
("NODE_ATTACH_ON", {"type": 'LEFT_ALT', "value": 'RELEASE', "any": True}, None),
("NODE_ATTACH_OFF", {"type": 'LEFT_ALT', "value": 'PRESS', "any": True}, None),
("AUTOCONSTRAIN", {"type": 'MIDDLEMOUSE', "value": 'ANY', "alt": not params.use_alt_navigation}, None),
("AUTOCONSTRAINPLANE", {"type": 'MIDDLEMOUSE', "value": 'ANY', "shift": True, "alt": not params.use_alt_navigation}, None),
("AUTOCONSTRAIN", {"type": 'MIDDLEMOUSE', "value": 'ANY', **alt_without_navigaton}, None),
("AUTOCONSTRAINPLANE", {"type": 'MIDDLEMOUSE', "value": 'ANY', "shift": True, **alt_without_navigaton}, None),
("PRECISION", {"type": 'LEFT_SHIFT', "value": 'ANY', "any": True}, None),
("PRECISION", {"type": 'RIGHT_SHIFT', "value": 'ANY', "any": True}, None),
])

View File

@ -2359,7 +2359,7 @@ def km_grease_pencil_stroke_edit_mode(params):
("gpencil.stroke_join", {"type": 'J', "value": 'PRESS', "ctrl": True}, None),
("gpencil.stroke_join", {"type": 'J', "value": 'PRESS', "shift": True, "ctrl": True},
{"properties": [("type", 'JOINCOPY')]}),
# Copy + paset
# Copy + paste.
("gpencil.copy", {"type": 'C', "value": 'PRESS', "ctrl": True}, None),
("gpencil.paste", {"type": 'V', "value": 'PRESS', "ctrl": True}, None),
# Snap

View File

@ -13,6 +13,25 @@ class ModifierButtonsPanel:
bl_options = {'HIDE_HEADER'}
class ModifierAddMenu:
MODIFIER_TYPES_TO_LABELS = {enum_it.identifier: enum_it.name
for enum_it in bpy.types.Modifier.bl_rna.properties['type'].enum_items_static}
MODIFIER_TYPES_TO_ICONS = {enum_it.identifier: enum_it.icon
for enum_it in bpy.types.Modifier.bl_rna.properties['type'].enum_items_static}
MODIFIER_TYPES_I18N_CONTEXT = bpy.types.Modifier.bl_rna.properties['type'].translation_context
@classmethod
def operator_modifier_add(cls, layout, mod_type):
layout.operator(
"object.modifier_add",
text=cls.MODIFIER_TYPES_TO_LABELS[mod_type],
# Although these are operators, the label actually comes from an (enum) property,
# so the property's translation context must be used here.
text_ctxt=cls.MODIFIER_TYPES_I18N_CONTEXT,
icon=cls.MODIFIER_TYPES_TO_ICONS[mod_type],
).type = mod_type
class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
bl_label = "Modifiers"
@ -27,7 +46,7 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
layout.template_modifiers()
class OBJECT_MT_modifier_add(Menu):
class OBJECT_MT_modifier_add(ModifierAddMenu, Menu):
bl_label = "Add Modifier"
bl_options = {'SEARCH_ON_KEY_PRESS'}
@ -36,7 +55,7 @@ class OBJECT_MT_modifier_add(Menu):
ob_type = context.object.type
geometry_nodes_supported = ob_type in {'MESH', 'CURVE', 'CURVES', 'FONT', 'SURFACE', 'VOLUME', 'POINTCLOUD'}
if geometry_nodes_supported:
layout.operator("object.modifier_add", icon='GEOMETRY_NODES', text="Geometry Nodes").type = 'NODES'
self.operator_modifier_add(layout, 'NODES')
layout.separator()
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE', 'LATTICE'}:
layout.menu("OBJECT_MT_modifier_add_edit")
@ -51,159 +70,122 @@ class OBJECT_MT_modifier_add(Menu):
layout.menu_contents("OBJECT_MT_modifier_add_root_catalogs")
class OBJECT_MT_modifier_add_edit(Menu):
class OBJECT_MT_modifier_add_edit(ModifierAddMenu, Menu):
bl_label = "Edit"
def draw(self, context):
layout = self.layout
ob_type = context.object.type
if ob_type == 'MESH':
layout.operator(
"object.modifier_add",
text="Data Transfer",
icon='MOD_DATA_TRANSFER',
).type = 'DATA_TRANSFER'
self.operator_modifier_add(layout, 'DATA_TRANSFER')
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE', 'LATTICE'}:
layout.operator("object.modifier_add", text="Mesh Cache", icon='MOD_MESHDEFORM').type = 'MESH_CACHE'
self.operator_modifier_add(layout, 'MESH_CACHE')
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE'}:
layout.operator(
"object.modifier_add",
text="Mesh Sequence Cache",
icon='MOD_MESHDEFORM',
).type = 'MESH_SEQUENCE_CACHE'
self.operator_modifier_add(layout, 'MESH_SEQUENCE_CACHE')
if ob_type == 'MESH':
layout.operator("object.modifier_add", text="Normal Edit", icon='MOD_NORMALEDIT').type = 'NORMAL_EDIT'
layout.operator(
"object.modifier_add",
text="Weighted Normal",
icon='MOD_NORMALEDIT',
).type = 'WEIGHTED_NORMAL'
layout.operator("object.modifier_add", text="UV Project", icon='MOD_UVPROJECT').type = 'UV_PROJECT'
layout.operator("object.modifier_add", text="UV Warp", icon='MOD_UVPROJECT').type = 'UV_WARP'
layout.operator(
"object.modifier_add",
text="Vertex Weight Edit",
icon='MOD_VERTEX_WEIGHT',
).type = 'VERTEX_WEIGHT_EDIT'
layout.operator(
"object.modifier_add",
text="Vertex Weight Mix",
icon='MOD_VERTEX_WEIGHT',
).type = 'VERTEX_WEIGHT_MIX'
layout.operator(
"object.modifier_add",
text="Vertex Weight Proximity",
icon='MOD_VERTEX_WEIGHT',
).type = 'VERTEX_WEIGHT_PROXIMITY'
self.operator_modifier_add(layout, 'NORMAL_EDIT')
self.operator_modifier_add(layout, 'WEIGHTED_NORMAL')
self.operator_modifier_add(layout, 'UV_PROJECT')
self.operator_modifier_add(layout, 'UV_WARP')
self.operator_modifier_add(layout, 'VERTEX_WEIGHT_EDIT')
self.operator_modifier_add(layout, 'VERTEX_WEIGHT_MIX')
self.operator_modifier_add(layout, 'VERTEX_WEIGHT_PROXIMITY')
layout.template_modifier_asset_menu_items(catalog_path=self.bl_label)
class OBJECT_MT_modifier_add_generate(Menu):
class OBJECT_MT_modifier_add_generate(ModifierAddMenu, Menu):
bl_label = "Generate"
def draw(self, context):
layout = self.layout
ob_type = context.object.type
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE'}:
layout.operator("object.modifier_add", text="Array", icon='MOD_ARRAY').type = 'ARRAY'
layout.operator("object.modifier_add", text="Bevel", icon='MOD_BEVEL').type = 'BEVEL'
self.operator_modifier_add(layout, 'ARRAY')
self.operator_modifier_add(layout, 'BEVEL')
if ob_type == 'MESH':
layout.operator("object.modifier_add", text="Boolean", icon='MOD_BOOLEAN').type = 'BOOLEAN'
self.operator_modifier_add(layout, 'BOOLEAN')
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE'}:
layout.operator("object.modifier_add", text="Build", icon='MOD_BUILD').type = 'BUILD'
layout.operator("object.modifier_add", text="Decimate", icon='MOD_DECIM').type = 'DECIMATE'
layout.operator("object.modifier_add", text="Edge Split", icon='MOD_EDGESPLIT').type = 'EDGE_SPLIT'
self.operator_modifier_add(layout, 'BUILD')
self.operator_modifier_add(layout, 'DECIMATE')
self.operator_modifier_add(layout, 'EDGE_SPLIT')
if ob_type == 'MESH':
layout.operator("object.modifier_add", text="Mask", icon='MOD_MASK').type = 'MASK'
self.operator_modifier_add(layout, 'MASK')
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE'}:
layout.operator("object.modifier_add", text="Mirror", icon='MOD_MIRROR').type = 'MIRROR'
self.operator_modifier_add(layout, 'MIRROR')
if ob_type == 'VOLUME':
layout.operator("object.modifier_add", text="Mesh to Volume", icon='VOLUME_DATA').type = 'MESH_TO_VOLUME'
self.operator_modifier_add(layout, 'MESH_TO_VOLUME')
if ob_type == 'MESH':
layout.operator("object.modifier_add", text="Multiresolution", icon='MOD_MULTIRES').type = 'MULTIRES'
self.operator_modifier_add(layout, 'MULTIRES')
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE'}:
layout.operator("object.modifier_add", text="Remesh", icon='MOD_REMESH').type = 'REMESH'
layout.operator("object.modifier_add", text="Screw", icon='MOD_SCREW').type = 'SCREW'
self.operator_modifier_add(layout, 'REMESH')
self.operator_modifier_add(layout, 'SCREW')
if ob_type == 'MESH':
layout.operator("object.modifier_add", text="Skin", icon='MOD_SKIN').type = 'SKIN'
self.operator_modifier_add(layout, 'SKIN')
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE'}:
layout.operator("object.modifier_add", text="Solidify", icon='MOD_SOLIDIFY').type = 'SOLIDIFY'
layout.operator("object.modifier_add", text="Subdivision Surface", icon='MOD_SUBSURF').type = 'SUBSURF'
layout.operator("object.modifier_add", text="Triangulate", icon='MOD_TRIANGULATE').type = 'TRIANGULATE'
self.operator_modifier_add(layout, 'SOLIDIFY')
self.operator_modifier_add(layout, 'SUBSURF')
self.operator_modifier_add(layout, 'TRIANGULATE')
if ob_type == 'MESH':
layout.operator("object.modifier_add", text="Volume to Mesh", icon='VOLUME_DATA').type = 'VOLUME_TO_MESH'
self.operator_modifier_add(layout, 'VOLUME_TO_MESH')
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE'}:
layout.operator("object.modifier_add", text="Weld", icon='AUTOMERGE_OFF').type = 'WELD'
self.operator_modifier_add(layout, 'WELD')
if ob_type == 'MESH':
layout.operator("object.modifier_add", text="Wireframe", icon='MOD_WIREFRAME').type = 'WIREFRAME'
self.operator_modifier_add(layout, 'WIREFRAME')
layout.template_modifier_asset_menu_items(catalog_path=self.bl_label)
class OBJECT_MT_modifier_add_deform(Menu):
class OBJECT_MT_modifier_add_deform(ModifierAddMenu, Menu):
bl_label = "Deform"
def draw(self, context):
layout = self.layout
ob_type = context.object.type
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE', 'LATTICE'}:
layout.operator("object.modifier_add", text="Armature", icon='MOD_ARMATURE').type = 'ARMATURE'
layout.operator("object.modifier_add", text="Cast", icon='MOD_CAST').type = 'CAST'
layout.operator("object.modifier_add", text="Curve", icon='MOD_CURVE').type = 'CURVE'
self.operator_modifier_add(layout, 'ARMATURE')
self.operator_modifier_add(layout, 'CAST')
self.operator_modifier_add(layout, 'CURVE')
if ob_type == 'MESH':
layout.operator("object.modifier_add", text="Displace", icon='MOD_DISPLACE').type = 'DISPLACE'
self.operator_modifier_add(layout, 'DISPLACE')
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE', 'LATTICE'}:
layout.operator("object.modifier_add", text="Hook", icon='HOOK').type = 'HOOK'
self.operator_modifier_add(layout, 'HOOK')
if ob_type == 'MESH':
layout.operator("object.modifier_add", text="Laplacian Deform",
icon='MOD_MESHDEFORM').type = 'LAPLACIANDEFORM'
self.operator_modifier_add(layout, 'LAPLACIANDEFORM')
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE', 'LATTICE'}:
layout.operator("object.modifier_add", text="Lattice", icon='MOD_LATTICE').type = 'LATTICE'
layout.operator("object.modifier_add", text="Mesh Deform", icon='MOD_MESHDEFORM').type = 'MESH_DEFORM'
layout.operator("object.modifier_add", text="Shrinkwrap", icon='MOD_SHRINKWRAP').type = 'SHRINKWRAP'
layout.operator("object.modifier_add", text="Simple Deform", icon='MOD_SIMPLEDEFORM').type = 'SIMPLE_DEFORM'
self.operator_modifier_add(layout, 'LATTICE')
self.operator_modifier_add(layout, 'MESH_DEFORM')
self.operator_modifier_add(layout, 'SHRINKWRAP')
self.operator_modifier_add(layout, 'SIMPLE_DEFORM')
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE'}:
layout.operator("object.modifier_add", text="Smooth", icon='MOD_SMOOTH').type = 'SMOOTH'
self.operator_modifier_add(layout, 'SMOOTH')
if ob_type == 'MESH':
layout.operator(
"object.modifier_add",
text="Smooth Corrective",
icon='MOD_SMOOTH',
).type = 'CORRECTIVE_SMOOTH'
layout.operator("object.modifier_add", text="Smooth Laplacian", icon='MOD_SMOOTH').type = 'LAPLACIANSMOOTH'
layout.operator("object.modifier_add", text="Surface Deform", icon='MOD_MESHDEFORM').type = 'SURFACE_DEFORM'
self.operator_modifier_add(layout, 'CORRECTIVE_SMOOTH')
self.operator_modifier_add(layout, 'LAPLACIANSMOOTH')
self.operator_modifier_add(layout, 'SURFACE_DEFORM')
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE', 'LATTICE'}:
layout.operator("object.modifier_add", text="Warp", icon='MOD_WARP').type = 'WARP'
layout.operator("object.modifier_add", text="Wave", icon='MOD_WAVE').type = 'WAVE'
self.operator_modifier_add(layout, 'WARP')
self.operator_modifier_add(layout, 'WAVE')
if ob_type == 'VOLUME':
layout.operator("object.modifier_add", text="Volume Displace", icon='VOLUME_DATA').type = 'VOLUME_DISPLACE'
self.operator_modifier_add(layout, 'VOLUME_DISPLACE')
layout.template_modifier_asset_menu_items(catalog_path=self.bl_label)
class OBJECT_MT_modifier_add_physics(Menu):
class OBJECT_MT_modifier_add_physics(ModifierAddMenu, Menu):
bl_label = "Physics"
def draw(self, context):
layout = self.layout
ob_type = context.object.type
if ob_type == 'MESH':
layout.operator("object.modifier_add", text="Cloth", icon='MOD_CLOTH').type = 'CLOTH'
layout.operator("object.modifier_add", text="Collision", icon='MOD_PHYSICS').type = 'COLLISION'
layout.operator("object.modifier_add", text="Dynamic Paint", icon='MOD_DYNAMICPAINT').type = 'DYNAMIC_PAINT'
layout.operator("object.modifier_add", text="Explode", icon='MOD_EXPLODE').type = 'EXPLODE'
layout.operator("object.modifier_add", text="Fluid", icon='MOD_FLUIDSIM').type = 'FLUID'
layout.operator("object.modifier_add", text="Ocean", icon='MOD_OCEAN').type = 'OCEAN'
layout.operator(
"object.modifier_add",
text="Particle Instance",
icon='MOD_PARTICLE_INSTANCE',
).type = 'PARTICLE_INSTANCE'
layout.operator(
"object.modifier_add",
text="Particle System",
icon='MOD_PARTICLES',
).type = 'PARTICLE_SYSTEM'
self.operator_modifier_add(layout, 'CLOTH')
self.operator_modifier_add(layout, 'COLLISION')
self.operator_modifier_add(layout, 'DYNAMIC_PAINT')
self.operator_modifier_add(layout, 'EXPLODE')
self.operator_modifier_add(layout, 'FLUID')
self.operator_modifier_add(layout, 'OCEAN')
self.operator_modifier_add(layout, 'PARTICLE_INSTANCE')
self.operator_modifier_add(layout, 'PARTICLE_SYSTEM')
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE', 'LATTICE'}:
layout.operator("object.modifier_add", text="Soft Body", icon='MOD_SOFT').type = 'SOFT_BODY'
self.operator_modifier_add(layout, 'SOFT_BODY')
layout.template_modifier_asset_menu_items(catalog_path=self.bl_label)

View File

@ -2,8 +2,8 @@
#
# SPDX-License-Identifier: GPL-2.0-or-later
# panels get subclassed (not registered directly)
# menus are referenced `as is`
# Panels get sub-classed (not registered directly).
# Menus are referenced as-is.
from bpy.types import Menu, UIList
from bpy.app.translations import contexts as i18n_contexts

View File

@ -849,10 +849,10 @@ classes = (
FILEBROWSER_PT_display,
FILEBROWSER_PT_filter,
FILEBROWSER_UL_dir,
FILEBROWSER_PT_bookmarks_volumes,
FILEBROWSER_PT_bookmarks_system,
FILEBROWSER_MT_bookmarks_context_menu,
FILEBROWSER_PT_bookmarks_favorites,
FILEBROWSER_PT_bookmarks_system,
FILEBROWSER_PT_bookmarks_volumes,
FILEBROWSER_PT_bookmarks_recents,
FILEBROWSER_PT_advanced_filter,
FILEBROWSER_PT_directory_path,

View File

@ -224,7 +224,7 @@ void CTX_wm_gizmo_group_set(bContext *C, struct wmGizmoGroup *gzgroup);
* \note This must be called in the same context as the poll function that created it.
*/
struct bContextPollMsgDyn_Params {
/** The result is allocated . */
/** The result is allocated. */
char *(*get_fn)(bContext *C, void *user_data);
/** Optionally free the user-data. */
void (*free_fn)(bContext *C, void *user_data);

View File

@ -34,11 +34,11 @@ struct ID;
typedef uint64_t eCustomDataMask;
/* These names are used as prefixes for UV layer names to find the associated boolean
* layers. They should never be longer than 2 chars, as MAX_CUSTOMDATA_LAYER_NAME
* layers. They should never be longer than 2 chars, as #MAX_CUSTOMDATA_LAYER_NAME
* has 4 extra bytes above what can be used for the base layer name, and these
* prefixes are placed between 2 '.'s at the start of the layer name.
* For example The uv vert selection layer of a layer named 'UVMap.001'
* will be called '.vs.UVMap.001' . */
* For example The uv vert selection layer of a layer named `UVMap.001`
* will be called `.vs.UVMap.001`. */
#define UV_VERTSEL_NAME "vs"
#define UV_EDGESEL_NAME "es"
#define UV_PINNED_NAME "pn"

View File

@ -434,7 +434,7 @@ typedef struct bNodeTreeType {
void (*localize)(struct bNodeTree *localtree, struct bNodeTree *ntree);
void (*local_merge)(struct Main *bmain, struct bNodeTree *localtree, struct bNodeTree *ntree);
/* Tree update. Overrides `nodetype->updatetreefunc` ! */
/* Tree update. Overrides `nodetype->updatetreefunc`. */
void (*update)(struct bNodeTree *ntree);
bool (*validate_link)(eNodeSocketDatatype from, eNodeSocketDatatype to);

View File

@ -217,7 +217,7 @@ bool BKE_tracking_track_has_enabled_marker_at_frame(struct MovieTrackingTrack *t
* \note frame number should be in clip space, not scene space.
*/
typedef enum eTrackClearAction {
/* Clear path from `ref_frame+1` up to the . */
/* Clear path from `ref_frame+1` up to the. */
TRACK_CLEAR_UPTO,
/* Clear path from the beginning up to `ref_frame-1`. */
TRACK_CLEAR_REMAINED,

View File

@ -1768,9 +1768,9 @@ static float nla_blend_value(const int blendmode,
default: /* TODO: Do we really want to blend by default? it seems more uses might prefer add...
*/
/* Do linear interpolation. The influence of the accumulated data (elsewhere, that is called
* dstweight) is 1 - influence, since the strip's influence is srcweight.
*/
/* Do linear interpolation. The influence of the accumulated data
* (elsewhere, that is called `dstwegiht`) is 1 - influence,
* since the strip's influence is `srcweight`. */
return lower_value * (1.0f - influence) + (strip_value * influence);
}
}

View File

@ -790,7 +790,7 @@ Mesh *curve_to_mesh_sweep(const CurvesGeometry &main,
return nullptr;
}
/* Add the position attribute later so it can be shared in some cases.*/
/* Add the position attribute later so it can be shared in some cases. */
Mesh *mesh = BKE_mesh_new_nomain(
0, offsets.edge.last(), offsets.face.last(), offsets.loop.last());
CustomData_free_layer_named(&mesh->vert_data, "position", 0);

View File

@ -1757,7 +1757,7 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
{sizeof(MRecast), "MRecast", 1, N_("Recast"), nullptr, nullptr, nullptr, nullptr},
/* 25: CD_MPOLY */ /* DEPRECATED */
{sizeof(MPoly), "MPoly", 1, N_("NGon Face"), nullptr, nullptr, nullptr, nullptr, nullptr},
/* 26: CD_MLOOP */ /* DEPRECATED*/
/* 26: CD_MLOOP */ /* DEPRECATED */
{sizeof(MLoop),
"MLoop",
1,

View File

@ -141,7 +141,7 @@ static void image_buf_fill_checker_slice(
rect = rect_orig;
rect_float = rect_float_orig;
/* 2nd pass, colored + */
/* 2nd pass, colored `+`. */
for (y = offset; y < height + offset; y++) {
float hoffs = 0.125f * floorf(y / checkerwidth);

View File

@ -2040,10 +2040,7 @@ static bool seq_convert_callback(Sequence *seq, void *userdata)
return true;
}
/* patch adrcode, so that we can map
* to different DNA variables later
* (semi-hack (tm) )
*/
/* Patch `adrcode`, so that we can map to different DNA variables later (semi-hack (tm)). */
switch (seq->type) {
case SEQ_TYPE_IMAGE:
case SEQ_TYPE_META:

View File

@ -2540,6 +2540,10 @@ void BKE_view_layer_verify_aov(RenderEngine *engine, Scene *scene, ViewLayer *vi
viewlayer_aov_make_name_unique(view_layer);
GHash *name_count = BLI_ghash_str_new(__func__);
LISTBASE_FOREACH (ViewLayerAOV *, aov, &view_layer->aovs) {
/* Disable conflict flag, so that the AOV is included when iterating over all passes below. */
aov->flag &= ~AOV_CONFLICT;
}
RE_engine_update_render_passes(
engine, scene, view_layer, bke_view_layer_verify_aov_cb, name_count);
LISTBASE_FOREACH (ViewLayerAOV *, aov, &view_layer->aovs) {

View File

@ -176,8 +176,8 @@ static int id_free(Main *bmain, void *idv, int flag, const bool use_flag_from_id
void BKE_id_free_ex(Main *bmain, void *idv, int flag, const bool use_flag_from_idtag)
{
/* ViewLayer resync needs to be delayed during Scene freeing, since internal relationships
* between the Scene's master collection and its view_layers become invalid (due to remapping .
*/
* between the Scene's master collection and its view_layers become invalid
* (due to remapping). */
BKE_layer_collection_resync_forbid();
flag = id_free(bmain, idv, flag, use_flag_from_idtag);
@ -371,8 +371,8 @@ static size_t id_delete(Main *bmain,
BKE_main_unlock(bmain);
/* ViewLayer resync needs to be delayed during Scene freeing, since internal relationships
* between the Scene's master collection and its view_layers become invalid (due to remapping .
*/
* between the Scene's master collection and its view_layers become invalid
* (due to remapping). */
BKE_layer_collection_resync_forbid();
/* In usual reversed order, such that all usage of a given ID, even 'never nullptr' ones,

View File

@ -780,7 +780,7 @@ static bool lib_query_unused_ids_tag_recurse(Main *bmain,
bmain, tag, do_local_ids, do_linked_ids, id_from, r_num_tagged))
{
/* Dependency loop case, ignore the `id_from` tag value here (as it should not be considered
* as valid yet), and presume that this is a 'valid user' case for now. . */
* as valid yet), and presume that this is a 'valid user' case for now. */
is_part_of_dependency_loop = true;
continue;
}

View File

@ -158,12 +158,14 @@ void BKE_main_free(Main *mainvar)
bool BKE_main_is_empty(Main *bmain)
{
bool result = true;
ID *id_iter;
FOREACH_MAIN_ID_BEGIN (bmain, id_iter) {
return false;
result = false;
break;
}
FOREACH_MAIN_ID_END;
return true;
return result;
}
void BKE_main_lock(Main *bmain)

View File

@ -58,7 +58,7 @@
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
# define CHECK_TYPE_INLINE(val, type) \
(void)((void)(((type)0) != (0 ? (val) : ((type)0))), _Generic((val), type : 0, const type : 0))
/* NOTE: The NONCONST version is needed for scalar types on CLANG, to avoid warnings. . */
/* NOTE: The NONCONST version is needed for scalar types on CLANG, to avoid warnings. */
# define CHECK_TYPE_INLINE_NONCONST(val, type) \
(void)((void)(((type)0) != (0 ? (val) : ((type)0))), _Generic((val), type : 0))
#else

View File

@ -290,7 +290,7 @@ MINLINE uint divide_ceil_u(uint a, uint b);
MINLINE uint64_t divide_ceil_ul(uint64_t a, uint64_t b);
/**
* Returns \a a if it is a multiple of \a b or the next multiple or \a b after \b a .
* Returns \a a if it is a multiple of \a b or the next multiple or \a b after \b a.
*/
MINLINE uint ceil_to_multiple_u(uint a, uint b);
MINLINE uint64_t ceil_to_multiple_ul(uint64_t a, uint64_t b);

View File

@ -88,7 +88,7 @@ template<typename T>
* \{ */
/**
* Transform \a v by rotation using the quaternion \a q .
* Transform \a v by rotation using the quaternion \a q.
*/
template<typename T>
[[nodiscard]] inline VecBase<T, 3> transform_point(const QuaternionBase<T> &q,

View File

@ -1054,7 +1054,7 @@ static void version_geometry_nodes_extrude_smooth_propagation(bNodeTree &ntree)
}
/* Change the action strip (if a NLA strip is preset) to HOLD instead of HOLD FORWARD to maintain
* backwards compatibility.*/
* backwards compatibility. */
static void version_nla_action_strip_hold(Main *bmain)
{
ID *id;
@ -1070,9 +1070,8 @@ static void version_nla_action_strip_hold(Main *bmain)
if (BKE_nlatrack_has_strips(&adt->nla_tracks)) {
adt->act_extendmode = NLASTRIP_EXTEND_HOLD;
}
FOREACH_MAIN_ID_END;
}
FOREACH_MAIN_ID_END;
}
void do_versions_after_linking_300(FileData * /*fd*/, Main *bmain)

View File

@ -150,7 +150,7 @@ void closure_Glossy_indirect_end(ClosureInputGlossy cl_in,
#endif
/* Apply Ray-trace reflections after occlusion since they are direct, local reflections. */
#if defined(RESOLVE_PROBE)
/* NO OP - output base radiance*/
/* NO OP - output base radiance. */
#elif defined(RESOLVE_SSR)
/* Output only ray-trace radiance. */
cl_out.radiance = cl_eval.raytrace_radiance;

View File

@ -25,7 +25,7 @@ uniform sampler2DArray utilTex;
#define NOISE_LAYER 2
#define LTC_DISK_LAYER 3 /* UNUSED */
/* Layers 4 to 20 are for BTDF Lut. */
/* Layers 4 to 20 are for BTDF LUT. */
#define lut_btdf_layer_first 4.0
#define lut_btdf_layer_count 16.0

View File

@ -163,9 +163,9 @@ class IrradianceBake {
LightProbeGridCacheFrame *read_result_packed();
private:
/** Read surfel data back to CPU into \a cache_frame . */
/** Read surfel data back to CPU into \a cache_frame. */
void read_surfels(LightProbeGridCacheFrame *cache_frame);
/** Read virtual offset back to CPU into \a cache_frame . */
/** Read virtual offset back to CPU into \a cache_frame. */
void read_virtual_offset(LightProbeGridCacheFrame *cache_frame);
};

View File

@ -683,7 +683,7 @@ void DeferredProbeLayer::begin_sync()
gbuffer_single_sided_ps_->state_set(state | DRW_STATE_CULL_BACK);
}
/* Light eval resources.*/
/* Light evaluate resources. */
{
eGPUTextureUsage usage = GPU_TEXTURE_USAGE_SHADER_READ | GPU_TEXTURE_USAGE_SHADER_WRITE;
dummy_light_tx_.ensure_2d(GPU_RGBA16F, int2(1), usage);
@ -827,7 +827,7 @@ void CapturePipeline::sync()
surface_ps_.bind_ssbo(CAPTURE_BUF_SLOT, &inst_.irradiance_cache.bake.capture_info_buf_);
surface_ps_.bind_texture(RBUFS_UTILITY_TEX_SLOT, inst_.pipelines.utility_tx);
/* TODO(fclem): Remove. Binded to get the camera data,
/* TODO(fclem): Remove. Bind to get the camera data,
* but there should be no view dependent behavior during capture. */
inst_.bind_uniform_data(&surface_ps_);
}

View File

@ -29,8 +29,6 @@ void SubsurfaceModule::end_sync()
data_.sample_len = 55;
}
precompute_samples_location();
subsurface_ps_.init();
subsurface_ps_.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_STENCIL_EQUAL |
DRW_STATE_BLEND_ADD_FULL);
@ -51,6 +49,8 @@ void SubsurfaceModule::end_sync()
void SubsurfaceModule::render(View &view, Framebuffer &fb, Texture &diffuse_light_tx)
{
precompute_samples_location();
fb.bind();
diffuse_light_tx_ = *&diffuse_light_tx;
inst_.manager->submit(subsurface_ps_, view);
@ -74,6 +74,8 @@ void SubsurfaceModule::precompute_samples_location()
data_.samples[i].y = sinf(theta) * r;
data_.samples[i].z = 1.0f / burley_pdf(d, r);
}
inst_.push_uniform_data();
}
const Vector<float> &SubsurfaceModule::transmittance_profile()

View File

@ -121,8 +121,8 @@ bool VelocityModule::step_object_sync(Object *ob,
ObjectKey &object_key,
ResourceHandle resource_handle,
int /*IDRecalcFlag*/ recalc,
ModifierData *modifier_data /*= nullptr*/,
ParticleSystem *particle_sys /*= nullptr*/)
ModifierData *modifier_data /*=nullptr*/,
ParticleSystem *particle_sys /*=nullptr*/)
{
bool has_motion = object_has_velocity(ob) || (recalc & ID_RECALC_TRANSFORM);
/* NOTE: Fragile. This will only work with 1 frame of lag since we can't record every geometry

View File

@ -155,7 +155,7 @@ void VolumeModule::begin_sync()
void VolumeModule::sync_object(Object *ob,
ObjectHandle & /*ob_handle*/,
ResourceHandle res_handle,
MaterialPass *material_pass /*= nullptr*/)
MaterialPass *material_pass /*=nullptr*/)
{
float3 size = math::to_scale(float4x4(ob->object_to_world));
/* Check if any of the axes have 0 length. (see #69070) */

View File

@ -283,7 +283,7 @@ DofSample dof_amend_history(DofNeighborhoodMinMax bbox, DofSample history, DofSa
/* More responsive. */
history.color = clamp(history.color, bbox.min.color, bbox.max.color);
#endif
/* Clamp CoC to reduce convergence time. Otherwise the result is laggy. */
/* Clamp CoC to reduce convergence time. Otherwise the result lags. */
history.coc = clamp(history.coc, bbox.min.coc, bbox.max.coc);
return history;

View File

@ -45,7 +45,7 @@ vec2 octahedral_uv_to_layer_texture_coords(vec2 octahedral_uv,
ReflectionProbeData probe_data,
vec2 texel_size)
{
/* Fix artifacts near edges. Proved one texel on each side.*/
/* Fix artifacts near edges. Proved one texel on each side. */
octahedral_uv = octahedral_uv * (1.0 - 2.0 * REFLECTION_PROBE_BORDER_SIZE * texel_size) +
REFLECTION_PROBE_BORDER_SIZE * texel_size + 0.5 * texel_size;

View File

@ -70,8 +70,8 @@ vec4 reflection_probe_eval(ClosureReflection reflection,
/* Clamped brightness. */
/* For artistic freedom this should be read from the scene/reflection probe.
* Note: EEVEE-legacy read the firefly_factor from gi_glossy_clamp.
* Note: Firefly removal should be moved to a different shader and also take SSR into
* account.*/
* Note: Firefly removal should be moved to a different shader and also take SSR into account.
*/
float luma = max(1e-8, max_v3(l_col));
const float firefly_factor = 1e16;
l_col.rgb *= 1.0 - max(0.0, luma - firefly_factor) / luma;

View File

@ -197,8 +197,8 @@ GPU_SHADER_CREATE_INFO(eevee_lightprobe_data)
.uniform_buf(IRRADIANCE_GRID_BUF_SLOT,
"IrradianceGridData",
"grids_infos_buf[IRRADIANCE_GRID_MAX]")
/* NOTE: Use uint instead of IrradianceBrickPacked because Metal needs to know the exact
* type.*/
/* NOTE: Use uint instead of IrradianceBrickPacked because Metal needs to know the exact type.
*/
.storage_buf(IRRADIANCE_BRICK_BUF_SLOT, Qualifier::READ, "uint", "bricks_infos_buf[]")
.sampler(IRRADIANCE_ATLAS_TEX_SLOT, ImageType::FLOAT_3D, "irradiance_atlas_tx");

View File

@ -97,7 +97,7 @@ class ShaderModule {
using ShaderPtr = std::unique_ptr<GPUShader, ShaderDeleter>;
/** Shared shader module across all engine instances. */
static ShaderModule *g_shader_modules[2 /*Selection Instance*/][2 /*Clipping Enabled*/];
static ShaderModule *g_shader_modules[2 /* Selection Instance. */][2 /* Clipping Enabled. */];
const SelectionType selection_type_;
/** TODO: Support clipping. This global state should be set by the overlay::Instance and switch

View File

@ -169,26 +169,26 @@ void main()
output_vert(vec2(0.0), inner_color, world_pos[1], ndc_pos[1]);
break;
}
/* Bottom outline left point*/
/* Bottom outline left point. */
case 14:
case 15:
case 18: {
output_vert(-offset, outer_color, world_pos[0], ndc_pos[0]);
break;
}
/* Bottom outline right point*/
/* Bottom outline right point. */
case 17:
case 19:
case 22: {
output_vert(-offset, outer_color, world_pos[1], ndc_pos[1]);
break;
}
/* Bottom transparent border left*/
/* Bottom transparent border left. */
case 20:
case 21: {
output_vert(offset * -2.0, vec4(colorActiveSpline.rgb, 0.0), world_pos[0], ndc_pos[0]);
}
/* Bottom transparent border right*/
/* Bottom transparent border right. */
case 23: {
output_vert(offset * -2.0, vec4(colorActiveSpline.rgb, 0.0), world_pos[1], ndc_pos[1]);
}

View File

@ -15,7 +15,7 @@ GPU_SHADER_INTERFACE_INFO(workbench_shadow_iface, "vData")
.smooth(Type::VEC4, "frontPosition")
.smooth(Type::VEC4, "backPosition");
GPU_SHADER_INTERFACE_INFO(workbench_shadow_flat_iface, "vData_flat")
.flat(Type::VEC3, "light_direction_os"); /*Workbench Next*/
.flat(Type::VEC3, "light_direction_os"); /* Workbench Next. */
/* `workbench_shadow_vert.glsl` only used by geometry shader path.
* Vertex output iface not needed by non-geometry shader variants,

View File

@ -107,7 +107,7 @@ class Instance {
case V3D_SHADING_TEXTURE_COLOR:
ATTR_FALLTHROUGH;
case V3D_SHADING_MATERIAL_COLOR:
if (::Material *_mat = BKE_object_material_get_eval(ob_ref.object, slot)) {
if (::Material *_mat = BKE_object_material_get_eval(ob_ref.object, slot + 1)) {
return Material(*_mat);
}
ATTR_FALLTHROUGH;
@ -271,8 +271,7 @@ class Instance {
continue;
}
/* Material slots start from 1. */
int material_slot = i + 1;
int material_slot = i;
Material mat = get_material(ob_ref, object_state.color_type, material_slot);
has_transparent_material = has_transparent_material || mat.is_transparent();
@ -324,11 +323,16 @@ class Instance {
void sculpt_sync(ObjectRef &ob_ref, ResourceHandle handle, const ObjectState &object_state)
{
SculptBatchFeature features = SCULPT_BATCH_DEFAULT;
if (object_state.color_type == V3D_SHADING_VERTEX_COLOR) {
features = SCULPT_BATCH_VERTEX_COLOR;
}
else if (object_state.color_type == V3D_SHADING_TEXTURE_COLOR) {
features = SCULPT_BATCH_UV;
}
if (object_state.use_per_material_batches) {
const int material_count = DRW_cache_object_material_count_get(ob_ref.object);
for (SculptBatch &batch : sculpt_batches_per_material_get(
ob_ref.object, {get_dummy_gpu_materials(material_count), material_count}))
{
for (SculptBatch &batch : sculpt_batches_get(ob_ref.object, true, features)) {
Material mat = get_material(ob_ref, object_state.color_type, batch.material_slot);
if (SCULPT_DEBUG_DRAW) {
mat.base_color = batch.debug_color();
@ -346,15 +350,7 @@ class Instance {
}
else {
Material mat = get_material(ob_ref, object_state.color_type);
SculptBatchFeature features = SCULPT_BATCH_DEFAULT;
if (object_state.color_type == V3D_SHADING_VERTEX_COLOR) {
features = SCULPT_BATCH_VERTEX_COLOR;
}
else if (object_state.color_type == V3D_SHADING_TEXTURE_COLOR) {
features = SCULPT_BATCH_UV;
}
for (SculptBatch &batch : sculpt_batches_get(ob_ref.object, features)) {
for (SculptBatch &batch : sculpt_batches_get(ob_ref.object, false, features)) {
if (SCULPT_DEBUG_DRAW) {
mat.base_color = batch.debug_color();
}
@ -395,12 +391,12 @@ class Instance {
/* Skip frustum culling. */
ResourceHandle handle = manager.resource_handle(float4x4(ob_ref.object->object_to_world));
Material mat = get_material(ob_ref, object_state.color_type, psys->part->omat);
Material mat = get_material(ob_ref, object_state.color_type, psys->part->omat - 1);
::Image *image = nullptr;
ImageUser *iuser = nullptr;
GPUSamplerState sampler_state = GPUSamplerState::default_sampler();
if (object_state.color_type == V3D_SHADING_TEXTURE_COLOR) {
get_material_image(ob_ref.object, psys->part->omat, image, iuser, sampler_state);
get_material_image(ob_ref.object, psys->part->omat - 1, image, iuser, sampler_state);
}
resources.material_buf.append(mat);
int material_index = resources.material_buf.size() - 1;
@ -470,6 +466,10 @@ class Instance {
GPU_DEPTH24_STENCIL8,
GPU_TEXTURE_USAGE_SHADER_READ |
GPU_TEXTURE_USAGE_ATTACHMENT);
fb.ensure(GPU_ATTACHMENT_TEXTURE(resources.depth_in_front_tx));
fb.bind();
GPU_framebuffer_clear_depth_stencil(fb, 1.0f, 0x00);
}
opaque_ps.draw(

View File

@ -68,7 +68,7 @@ void get_material_image(Object *ob,
{
const ::bNode *node = nullptr;
ED_object_get_active_image(ob, material_slot, &image, &iuser, &node, nullptr);
ED_object_get_active_image(ob, material_slot + 1, &image, &iuser, &node, nullptr);
if (node && image) {
switch (node->type) {
case SH_NODE_TEX_IMAGE: {

View File

@ -172,10 +172,10 @@ void OpaquePass::draw(Manager &manager,
opaque_fb.bind();
manager.submit(gbuffer_in_front_ps_, view);
}
if (resources.depth_in_front_tx.is_valid()) {
GPU_texture_copy(resources.depth_in_front_tx, resources.depth_tx);
if (resources.depth_in_front_tx.is_valid()) {
GPU_texture_copy(resources.depth_in_front_tx, resources.depth_tx);
}
}
if (!gbuffer_ps_.is_empty()) {

View File

@ -107,7 +107,6 @@ struct SceneState {
struct ObjectState {
eV3DShadingColorType color_type = V3D_SHADING_SINGLE_COLOR;
bool sculpt_pbvh = false;
bool texture_paint_mode = false;
::Image *image_paint_override = nullptr;
GPUSamplerState override_sampler_state = GPUSamplerState::default_sampler();
bool draw_shadow = false;

View File

@ -305,12 +305,12 @@ ShadowPass::~ShadowPass()
}
}
PassMain::Sub *&ShadowPass::get_pass_ptr(PassType type, bool manifold, bool cap /*= false*/)
PassMain::Sub *&ShadowPass::get_pass_ptr(PassType type, bool manifold, bool cap /*=false*/)
{
return passes_[type][manifold][cap];
}
GPUShader *ShadowPass::get_shader(bool depth_pass, bool manifold, bool cap /*= false*/)
GPUShader *ShadowPass::get_shader(bool depth_pass, bool manifold, bool cap /*=false*/)
{
GPUShader *&shader = shaders_[depth_pass][manifold][cap];

View File

@ -20,7 +20,7 @@
namespace blender::workbench {
void SceneState::init(Object *camera_ob /*= nullptr*/)
void SceneState::init(Object *camera_ob /*=nullptr*/)
{
bool reset_taa = reset_taa_next_sample;
reset_taa_next_sample = false;
@ -197,32 +197,42 @@ static const CustomData *get_vert_custom_data(const Mesh *mesh)
ObjectState::ObjectState(const SceneState &scene_state, Object *ob)
{
sculpt_pbvh = false;
texture_paint_mode = false;
image_paint_override = nullptr;
override_sampler_state = GPUSamplerState::default_sampler();
draw_shadow = false;
const DRWContextState *draw_ctx = DRW_context_state_get();
const bool is_active = (ob == draw_ctx->obact);
/* TODO(@pragma37): Is the double check needed?
* If it is, wouldn't be needed for sculpt_pbvh too? */
const bool is_render = DRW_state_is_image_render() && (draw_ctx->v3d == nullptr);
color_type = (eV3DShadingColorType)scene_state.shading.color_type;
if (!(is_active && DRW_object_use_hide_faces(ob))) {
draw_shadow = (ob->dtx & OB_DRAW_NO_SHADOW_CAST) == 0 && scene_state.draw_shadows;
}
image_paint_override = nullptr;
override_sampler_state = GPUSamplerState::default_sampler();
sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->rv3d) &&
!DRW_state_is_image_render();
draw_shadow = scene_state.draw_shadows && (ob->dtx & OB_DRAW_NO_SHADOW_CAST) == 0 &&
!is_active && !sculpt_pbvh && !DRW_object_use_hide_faces(ob);
color_type = (eV3DShadingColorType)scene_state.shading.color_type;
bool has_color = false;
bool has_uv = false;
if (ob->type == OB_MESH) {
const Mesh *me = static_cast<Mesh *>(ob->data);
const CustomData *cd_vdata = get_vert_custom_data(me);
const CustomData *cd_ldata = get_loop_custom_data(me);
has_color = (CustomData_has_layer(cd_vdata, CD_PROP_COLOR) ||
CustomData_has_layer(cd_vdata, CD_PROP_BYTE_COLOR) ||
CustomData_has_layer(cd_ldata, CD_PROP_COLOR) ||
CustomData_has_layer(cd_ldata, CD_PROP_BYTE_COLOR));
has_uv = CustomData_has_layer(cd_ldata, CD_PROP_FLOAT2);
}
if (color_type == V3D_SHADING_TEXTURE_COLOR && (!has_uv || ob->dt < OB_TEXTURE)) {
color_type = V3D_SHADING_MATERIAL_COLOR;
}
else if (color_type == V3D_SHADING_VERTEX_COLOR && !has_color) {
color_type = V3D_SHADING_OBJECT_COLOR;
}
if (sculpt_pbvh) {
/* Shadows are unsupported in sculpt mode. We could revert to the slow
* method in this case but I'm not sure if it's a good idea given that
* sculpted meshes are heavy to begin with. */
draw_shadow = false;
if (color_type == V3D_SHADING_TEXTURE_COLOR && BKE_pbvh_type(ob->sculpt->pbvh) != PBVH_FACES) {
/* Force use of material color for sculpt. */
color_type = V3D_SHADING_MATERIAL_COLOR;
@ -236,59 +246,25 @@ ObjectState::ObjectState(const SceneState &scene_state, Object *ob)
C, &scene_state.scene->toolsettings->paint_mode, ob, color_type);
}
}
else if (ob->type == OB_MESH) {
const Mesh *me = static_cast<Mesh *>(ob->data);
const CustomData *cd_vdata = get_vert_custom_data(me);
const CustomData *cd_ldata = get_loop_custom_data(me);
bool has_color = (CustomData_has_layer(cd_vdata, CD_PROP_COLOR) ||
CustomData_has_layer(cd_vdata, CD_PROP_BYTE_COLOR) ||
CustomData_has_layer(cd_ldata, CD_PROP_COLOR) ||
CustomData_has_layer(cd_ldata, CD_PROP_BYTE_COLOR));
bool has_uv = CustomData_has_layer(cd_ldata, CD_PROP_FLOAT2);
if (color_type == V3D_SHADING_TEXTURE_COLOR) {
if (ob->dt < OB_TEXTURE || !has_uv) {
color_type = V3D_SHADING_MATERIAL_COLOR;
else if (ob->type == OB_MESH && !DRW_state_is_scene_render()) {
/* Force texture or vertex mode if object is in paint mode. */
const bool is_vertpaint_mode = is_active && (scene_state.object_mode == CTX_MODE_PAINT_VERTEX);
const bool is_texpaint_mode = is_active && (scene_state.object_mode == CTX_MODE_PAINT_TEXTURE);
if (is_vertpaint_mode && has_color) {
color_type = V3D_SHADING_VERTEX_COLOR;
}
else if (is_texpaint_mode && has_uv) {
color_type = V3D_SHADING_TEXTURE_COLOR;
const ImagePaintSettings *imapaint = &scene_state.scene->toolsettings->imapaint;
if (imapaint->mode == IMAGEPAINT_MODE_IMAGE) {
image_paint_override = imapaint->canvas;
override_sampler_state.extend_x = GPU_SAMPLER_EXTEND_MODE_REPEAT;
override_sampler_state.extend_yz = GPU_SAMPLER_EXTEND_MODE_REPEAT;
const bool use_linear_filter = imapaint->interp == IMAGEPAINT_INTERP_LINEAR;
override_sampler_state.set_filtering_flag_from_test(GPU_SAMPLER_FILTERING_LINEAR,
use_linear_filter);
}
}
else if (color_type == V3D_SHADING_VERTEX_COLOR && !has_color) {
color_type = V3D_SHADING_OBJECT_COLOR;
}
if (!is_render) {
/* Force texture or vertex mode if object is in paint mode. */
const bool is_vertpaint_mode = is_active &&
(scene_state.object_mode == CTX_MODE_PAINT_VERTEX);
const bool is_texpaint_mode = is_active &&
(scene_state.object_mode == CTX_MODE_PAINT_TEXTURE);
if (is_vertpaint_mode && has_color) {
color_type = V3D_SHADING_VERTEX_COLOR;
}
else if (is_texpaint_mode && has_uv) {
color_type = V3D_SHADING_TEXTURE_COLOR;
texture_paint_mode = true;
const ImagePaintSettings *imapaint = &scene_state.scene->toolsettings->imapaint;
if (imapaint->mode == IMAGEPAINT_MODE_IMAGE) {
image_paint_override = imapaint->canvas;
override_sampler_state.extend_x = GPU_SAMPLER_EXTEND_MODE_REPEAT;
override_sampler_state.extend_yz = GPU_SAMPLER_EXTEND_MODE_REPEAT;
const bool use_linear_filter = imapaint->interp == IMAGEPAINT_INTERP_LINEAR;
override_sampler_state.set_filtering_flag_from_test(GPU_SAMPLER_FILTERING_LINEAR,
use_linear_filter);
}
}
}
}
else {
if (color_type == V3D_SHADING_TEXTURE_COLOR) {
color_type = V3D_SHADING_MATERIAL_COLOR;
}
else if (color_type == V3D_SHADING_VERTEX_COLOR) {
color_type = V3D_SHADING_OBJECT_COLOR;
}
}
use_per_material_batches = image_paint_override == nullptr && ELEM(color_type,

View File

@ -247,8 +247,7 @@ static void grease_pencil_geom_batch_ensure(GreasePencil &grease_pencil, int cfr
total_points_num += curves.points_num();
/* One vertex is stored before and after as padding. Cyclic strokes have one extra
* vertex.*/
/* One vertex is stored before and after as padding. Cyclic strokes have one extra vertex. */
total_verts_num += curves.points_num() + num_cyclic + curves.curves_num() * 2;
total_triangles_num += (curves.points_num() + num_cyclic) * 2;
total_triangles_num += drawing->triangles().size();

View File

@ -152,7 +152,7 @@ static Vector<SculptBatch> sculpt_batches_get_ex(
return data.batches;
}
Vector<SculptBatch> sculpt_batches_get(Object *ob, SculptBatchFeature features)
Vector<SculptBatch> sculpt_batches_get(Object *ob, bool per_material, SculptBatchFeature features)
{
PBVHAttrReq attrs[16] = {};
int attrs_len = 0;
@ -193,7 +193,8 @@ Vector<SculptBatch> sculpt_batches_get(Object *ob, SculptBatchFeature features)
}
}
return sculpt_batches_get_ex(ob, features & SCULPT_BATCH_WIREFRAME, false, attrs, attrs_len);
return sculpt_batches_get_ex(
ob, features & SCULPT_BATCH_WIREFRAME, per_material, attrs, attrs_len);
}
Vector<SculptBatch> sculpt_batches_per_material_get(Object *ob,

View File

@ -32,9 +32,9 @@ enum SculptBatchFeature {
ENUM_OPERATORS(SculptBatchFeature, SCULPT_BATCH_UV);
/** Used by engines that don't use GPUMaterials, like the Workbench and Overlay engines. */
Vector<SculptBatch> sculpt_batches_get(Object *ob, SculptBatchFeature features);
Vector<SculptBatch> sculpt_batches_get(Object *ob, bool per_material, SculptBatchFeature features);
/** Used by EEVEE and Workbench Material/Texture modes. */
/** Used by EEVEE. */
Vector<SculptBatch> sculpt_batches_per_material_get(Object *ob,
MutableSpan<GPUMaterial *> materials);

View File

@ -294,7 +294,7 @@ float get_homogenous_z_offset(float vs_z, float hs_w, float vs_offset)
#define DRW_BASE_FROM_SET (1 << 3)
#define DRW_BASE_ACTIVE (1 << 4)
/* Wire Color Types, matching eV3DShadingColorType.*/
/* Wire Color Types, matching eV3DShadingColorType. */
#define V3D_SHADING_SINGLE_COLOR 2
#define V3D_SHADING_OBJECT_COLOR 4
#define V3D_SHADING_RANDOM_COLOR 1

View File

@ -4370,7 +4370,7 @@ void ED_keymap_animchannels(wmKeyConfig *keyconf)
{
/* TODO: check on a poll callback for this, to get hotkeys into menus. */
WM_keymap_ensure(keyconf, "Animation Channels", 0, 0);
WM_keymap_ensure(keyconf, "Animation Channels", SPACE_EMPTY, RGN_TYPE_WINDOW);
}
/** \} */

View File

@ -138,7 +138,7 @@ static bool actedit_get_context(bAnimContext *ac, SpaceAction *saction)
switch (saction->mode) {
case SACTCONT_ACTION: /* 'Action Editor' */
/* if not pinned, sync with active object */
if (/*saction->pin == 0*/ true) {
if (/* `saction->pin == 0` */ true) {
if (ac->obact && ac->obact->adt) {
saction->action = ac->obact->adt->action;
}
@ -158,7 +158,7 @@ static bool actedit_get_context(bAnimContext *ac, SpaceAction *saction)
ac->data = actedit_get_shapekeys(ac);
/* if not pinned, sync with active object */
if (/*saction->pin == 0*/ true) {
if (/* `saction->pin == 0` */ true) {
Key *key = (Key *)ac->data;
if (key && key->adt) {

View File

@ -1907,7 +1907,7 @@ void ED_operatortypes_marker()
void ED_keymap_marker(wmKeyConfig *keyconf)
{
WM_keymap_ensure(keyconf, "Markers", 0, 0);
WM_keymap_ensure(keyconf, "Markers", SPACE_EMPTY, RGN_TYPE_WINDOW);
}
/** \} */

View File

@ -695,7 +695,7 @@ void ED_operatortypes_anim()
void ED_keymap_anim(wmKeyConfig *keyconf)
{
WM_keymap_ensure(keyconf, "Animation", 0, 0);
WM_keymap_ensure(keyconf, "Animation", SPACE_EMPTY, RGN_TYPE_WINDOW);
}
/** \} */

View File

@ -179,11 +179,11 @@ void ED_keymap_armature(wmKeyConfig *keyconf)
/* Armature ------------------------ */
/* only set in editmode armature, by space_view3d listener */
keymap = WM_keymap_ensure(keyconf, "Armature", 0, 0);
keymap = WM_keymap_ensure(keyconf, "Armature", SPACE_EMPTY, RGN_TYPE_WINDOW);
keymap->poll = ED_operator_editarmature;
/* Pose ------------------------ */
/* only set in posemode, by space_view3d listener */
keymap = WM_keymap_ensure(keyconf, "Pose", 0, 0);
keymap = WM_keymap_ensure(keyconf, "Pose", SPACE_EMPTY, RGN_TYPE_WINDOW);
keymap->poll = ED_operator_posemode;
}

View File

@ -47,7 +47,7 @@ static CLG_LogRef LOG = {"ed.undo.armature"};
/* Utility functions. */
/**
* Remaps editbone collection membership.
* Remaps edit-bone collection membership.
*
* This is intended to be used in combination with ED_armature_ebone_listbase_copy()
* and ANIM_bonecoll_listbase_copy() to make a full duplicate of both edit

View File

@ -271,7 +271,8 @@ void ED_asset_shelf_region_init(wmWindowManager *wm, ARegion *region)
UI_view2d_region_reinit(&region->v2d, V2D_COMMONVIEW_PANELS_UI, region->winx, region->winy);
wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "View2D Buttons List", 0, 0);
wmKeyMap *keymap = WM_keymap_ensure(
wm->defaultconf, "View2D Buttons List", SPACE_EMPTY, RGN_TYPE_WINDOW);
WM_event_add_keymap_handler(&region->handlers, keymap);
region->v2d.scroll = V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HIDE;
@ -473,7 +474,8 @@ void ED_asset_shelf_header_region(const bContext *C, ARegion *region)
int ED_asset_shelf_header_region_size()
{
/* A little smaller than a regular header. */
/* The asset shelf tends to look like a separate area. Making the shelf header smaller than a
* normal header helps a bit. */
return ED_area_headersize() * 0.85f;
}
@ -689,7 +691,6 @@ static void asset_shelf_header_draw(const bContext *C, Header *header)
uiItemSpacer(layout);
uiItemR(layout, &shelf_ptr, "search_filter", UI_ITEM_NONE, "", ICON_VIEWZOOM);
uiItemS(layout);
uiItemPopoverPanel(layout, C, "ASSETSHELF_PT_display", "", ICON_IMGDISPLAY);
}

View File

@ -149,11 +149,11 @@ void ED_operatormacros_curve()
void ED_keymap_curve(wmKeyConfig *keyconf)
{
/* only set in editmode font, by space_view3d listener */
wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Font", 0, 0);
wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Font", SPACE_EMPTY, RGN_TYPE_WINDOW);
keymap->poll = ED_operator_editfont;
/* only set in editmode curve, by space_view3d listener */
keymap = WM_keymap_ensure(keyconf, "Curve", 0, 0);
keymap = WM_keymap_ensure(keyconf, "Curve", SPACE_EMPTY, RGN_TYPE_WINDOW);
keymap->poll = ED_operator_editsurfcurve;
curve_pen_modal_keymap(keyconf);

View File

@ -3720,7 +3720,7 @@ static void subdividenurb(Object *obedit, View3D *v3d, int number_cuts)
}
}
if (sel) { /* V ! */
if (sel) { /* V direction. */
bpn = bpnew = static_cast<BPoint *>(
MEM_mallocN((sel + nu->pntsv) * nu->pntsu * sizeof(BPoint), "subdivideNurb4"));
bp = nu->bp;
@ -3768,7 +3768,7 @@ static void subdividenurb(Object *obedit, View3D *v3d, int number_cuts)
}
}
if (sel) { /* U ! */
if (sel) { /* U direction. */
/* Inserting U points is sort of 'default' Flat curves only get
* U points inserted in them. */
bpn = bpnew = static_cast<BPoint *>(

View File

@ -1254,6 +1254,6 @@ void ED_keymap_curves(wmKeyConfig *keyconf)
{
using namespace blender::ed::curves;
/* Only set in editmode curves, by space_view3d listener. */
wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Curves", 0, 0);
wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Curves", SPACE_EMPTY, RGN_TYPE_WINDOW);
keymap->poll = editable_curves_poll;
}

View File

@ -440,14 +440,16 @@ static void run_node_group_ui(bContext *C, wmOperator *op)
static bool run_node_ui_poll(wmOperatorType * /*ot*/, PointerRNA *ptr)
{
bool result = false;
RNA_STRUCT_BEGIN (ptr, prop) {
int flag = RNA_property_flag(prop);
if ((flag & PROP_HIDDEN) == 0) {
return true;
result = true;
break;
}
}
RNA_STRUCT_END;
return false;
return result;
}
static std::string run_node_group_get_name(wmOperatorType * /*ot*/, PointerRNA *ptr)

View File

@ -37,7 +37,7 @@
/* Generic Drawing Keymap - Annotations */
static void ed_keymap_gpencil_general(wmKeyConfig *keyconf)
{
WM_keymap_ensure(keyconf, "Grease Pencil", 0, 0);
WM_keymap_ensure(keyconf, "Grease Pencil", SPACE_EMPTY, RGN_TYPE_WINDOW);
}
/* ==================== */
@ -314,7 +314,8 @@ static bool gpencil_stroke_weightmode_smear_poll(bContext *C)
/* Stroke Editing Keymap - Only when editmode is enabled */
static void ed_keymap_gpencil_editing(wmKeyConfig *keyconf)
{
wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Edit Mode", 0, 0);
wmKeyMap *keymap = WM_keymap_ensure(
keyconf, "Grease Pencil Stroke Edit Mode", SPACE_EMPTY, RGN_TYPE_WINDOW);
/* set poll callback - so that this keymap only gets enabled when stroke editmode is enabled */
keymap->poll = gpencil_stroke_editmode_poll;
@ -323,7 +324,8 @@ static void ed_keymap_gpencil_editing(wmKeyConfig *keyconf)
/* Stroke Curve Editing Keymap - Only when editmode is enabled and in curve edit mode */
static void ed_keymap_gpencil_curve_editing(wmKeyConfig *keyconf)
{
wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Curve Edit Mode", 0, 0);
wmKeyMap *keymap = WM_keymap_ensure(
keyconf, "Grease Pencil Stroke Curve Edit Mode", SPACE_EMPTY, RGN_TYPE_WINDOW);
/* set poll callback - so that this keymap only gets enabled when curve editmode is enabled */
keymap->poll = gpencil_stroke_editmode_curve_poll;
@ -332,28 +334,32 @@ static void ed_keymap_gpencil_curve_editing(wmKeyConfig *keyconf)
/* keys for draw with a drawing brush (no fill) */
static void ed_keymap_gpencil_painting_draw(wmKeyConfig *keyconf)
{
wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Paint (Draw brush)", 0, 0);
wmKeyMap *keymap = WM_keymap_ensure(
keyconf, "Grease Pencil Stroke Paint (Draw brush)", SPACE_EMPTY, RGN_TYPE_WINDOW);
keymap->poll = gpencil_stroke_paintmode_draw_poll;
}
/* keys for draw with a eraser brush (erase) */
static void ed_keymap_gpencil_painting_erase(wmKeyConfig *keyconf)
{
wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Paint (Erase)", 0, 0);
wmKeyMap *keymap = WM_keymap_ensure(
keyconf, "Grease Pencil Stroke Paint (Erase)", SPACE_EMPTY, RGN_TYPE_WINDOW);
keymap->poll = gpencil_stroke_paintmode_erase_poll;
}
/* keys for draw with a fill brush */
static void ed_keymap_gpencil_painting_fill(wmKeyConfig *keyconf)
{
wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Paint (Fill)", 0, 0);
wmKeyMap *keymap = WM_keymap_ensure(
keyconf, "Grease Pencil Stroke Paint (Fill)", SPACE_EMPTY, RGN_TYPE_WINDOW);
keymap->poll = gpencil_stroke_paintmode_fill_poll;
}
/* keys for draw with a tint brush */
static void ed_keymap_gpencil_painting_tint(wmKeyConfig *keyconf)
{
wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Paint (Tint)", 0, 0);
wmKeyMap *keymap = WM_keymap_ensure(
keyconf, "Grease Pencil Stroke Paint (Tint)", SPACE_EMPTY, RGN_TYPE_WINDOW);
keymap->poll = gpencil_stroke_paintmode_tint_poll;
}
@ -361,7 +367,8 @@ static void ed_keymap_gpencil_painting_tint(wmKeyConfig *keyconf)
static void ed_keymap_gpencil_painting(wmKeyConfig *keyconf)
{
/* set poll callback - so that this keymap only gets enabled when stroke paintmode is enabled */
wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Paint Mode", 0, 0);
wmKeyMap *keymap = WM_keymap_ensure(
keyconf, "Grease Pencil Stroke Paint Mode", SPACE_EMPTY, RGN_TYPE_WINDOW);
keymap->poll = gpencil_stroke_paintmode_poll;
}
@ -369,7 +376,8 @@ static void ed_keymap_gpencil_painting(wmKeyConfig *keyconf)
static void ed_keymap_gpencil_sculpting(wmKeyConfig *keyconf)
{
/* set poll callback - so that this keymap only gets enabled when stroke sculptmode is enabled */
wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Sculpt Mode", 0, 0);
wmKeyMap *keymap = WM_keymap_ensure(
keyconf, "Grease Pencil Stroke Sculpt Mode", SPACE_EMPTY, RGN_TYPE_WINDOW);
keymap->poll = gpencil_stroke_sculptmode_poll;
}
@ -377,124 +385,144 @@ static void ed_keymap_gpencil_sculpting(wmKeyConfig *keyconf)
static void ed_keymap_gpencil_weightpainting(wmKeyConfig *keyconf)
{
/* set poll callback - so that this keymap only gets enabled when stroke sculptmode is enabled */
wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Weight Mode", 0, 0);
wmKeyMap *keymap = WM_keymap_ensure(
keyconf, "Grease Pencil Stroke Weight Mode", SPACE_EMPTY, RGN_TYPE_WINDOW);
keymap->poll = gpencil_stroke_weightmode_poll;
}
static void ed_keymap_gpencil_vertexpainting(wmKeyConfig *keyconf)
{
/* set poll callback - so that this keymap only gets enabled when stroke vertex is enabled */
wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Vertex Mode", 0, 0);
wmKeyMap *keymap = WM_keymap_ensure(
keyconf, "Grease Pencil Stroke Vertex Mode", SPACE_EMPTY, RGN_TYPE_WINDOW);
keymap->poll = gpencil_stroke_vertexmode_poll;
}
/* keys for vertex with a draw brush */
static void ed_keymap_gpencil_vertexpainting_draw(wmKeyConfig *keyconf)
{
wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Vertex (Draw)", 0, 0);
wmKeyMap *keymap = WM_keymap_ensure(
keyconf, "Grease Pencil Stroke Vertex (Draw)", SPACE_EMPTY, RGN_TYPE_WINDOW);
keymap->poll = gpencil_stroke_vertexmode_draw_poll;
}
/* keys for vertex with a blur brush */
static void ed_keymap_gpencil_vertexpainting_blur(wmKeyConfig *keyconf)
{
wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Vertex (Blur)", 0, 0);
wmKeyMap *keymap = WM_keymap_ensure(
keyconf, "Grease Pencil Stroke Vertex (Blur)", SPACE_EMPTY, RGN_TYPE_WINDOW);
keymap->poll = gpencil_stroke_vertexmode_blur_poll;
}
/* keys for vertex with a average brush */
static void ed_keymap_gpencil_vertexpainting_average(wmKeyConfig *keyconf)
{
wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Vertex (Average)", 0, 0);
wmKeyMap *keymap = WM_keymap_ensure(
keyconf, "Grease Pencil Stroke Vertex (Average)", SPACE_EMPTY, RGN_TYPE_WINDOW);
keymap->poll = gpencil_stroke_vertexmode_average_poll;
}
/* keys for vertex with a smear brush */
static void ed_keymap_gpencil_vertexpainting_smear(wmKeyConfig *keyconf)
{
wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Vertex (Smear)", 0, 0);
wmKeyMap *keymap = WM_keymap_ensure(
keyconf, "Grease Pencil Stroke Vertex (Smear)", SPACE_EMPTY, RGN_TYPE_WINDOW);
keymap->poll = gpencil_stroke_vertexmode_smear_poll;
}
/* keys for vertex with a replace brush */
static void ed_keymap_gpencil_vertexpainting_replace(wmKeyConfig *keyconf)
{
wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Vertex (Replace)", 0, 0);
wmKeyMap *keymap = WM_keymap_ensure(
keyconf, "Grease Pencil Stroke Vertex (Replace)", SPACE_EMPTY, RGN_TYPE_WINDOW);
keymap->poll = gpencil_stroke_vertexmode_replace_poll;
}
/* keys for sculpt with a smooth brush */
static void ed_keymap_gpencil_sculptpainting_smooth(wmKeyConfig *keyconf)
{
wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Sculpt (Smooth)", 0, 0);
wmKeyMap *keymap = WM_keymap_ensure(
keyconf, "Grease Pencil Stroke Sculpt (Smooth)", SPACE_EMPTY, RGN_TYPE_WINDOW);
keymap->poll = gpencil_stroke_sculptmode_smooth_poll;
}
/* keys for sculpt with a thickness brush */
static void ed_keymap_gpencil_sculptpainting_thickness(wmKeyConfig *keyconf)
{
wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Sculpt (Thickness)", 0, 0);
wmKeyMap *keymap = WM_keymap_ensure(
keyconf, "Grease Pencil Stroke Sculpt (Thickness)", SPACE_EMPTY, RGN_TYPE_WINDOW);
keymap->poll = gpencil_stroke_sculptmode_thickness_poll;
}
/* keys for sculpt with a strength brush */
static void ed_keymap_gpencil_sculptpainting_strength(wmKeyConfig *keyconf)
{
wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Sculpt (Strength)", 0, 0);
wmKeyMap *keymap = WM_keymap_ensure(
keyconf, "Grease Pencil Stroke Sculpt (Strength)", SPACE_EMPTY, RGN_TYPE_WINDOW);
keymap->poll = gpencil_stroke_sculptmode_strength_poll;
}
/* keys for sculpt with a grab brush */
static void ed_keymap_gpencil_sculptpainting_grab(wmKeyConfig *keyconf)
{
wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Sculpt (Grab)", 0, 0);
wmKeyMap *keymap = WM_keymap_ensure(
keyconf, "Grease Pencil Stroke Sculpt (Grab)", SPACE_EMPTY, RGN_TYPE_WINDOW);
keymap->poll = gpencil_stroke_sculptmode_grab_poll;
}
/* keys for sculpt with a push brush */
static void ed_keymap_gpencil_sculptpainting_push(wmKeyConfig *keyconf)
{
wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Sculpt (Push)", 0, 0);
wmKeyMap *keymap = WM_keymap_ensure(
keyconf, "Grease Pencil Stroke Sculpt (Push)", SPACE_EMPTY, RGN_TYPE_WINDOW);
keymap->poll = gpencil_stroke_sculptmode_push_poll;
}
/* keys for sculpt with a twist brush */
static void ed_keymap_gpencil_sculptpainting_twist(wmKeyConfig *keyconf)
{
wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Sculpt (Twist)", 0, 0);
wmKeyMap *keymap = WM_keymap_ensure(
keyconf, "Grease Pencil Stroke Sculpt (Twist)", SPACE_EMPTY, RGN_TYPE_WINDOW);
keymap->poll = gpencil_stroke_sculptmode_twist_poll;
}
/* keys for sculpt with a pinch brush */
static void ed_keymap_gpencil_sculptpainting_pinch(wmKeyConfig *keyconf)
{
wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Sculpt (Pinch)", 0, 0);
wmKeyMap *keymap = WM_keymap_ensure(
keyconf, "Grease Pencil Stroke Sculpt (Pinch)", SPACE_EMPTY, RGN_TYPE_WINDOW);
keymap->poll = gpencil_stroke_sculptmode_pinch_poll;
}
/* keys for sculpt with a randomize brush */
static void ed_keymap_gpencil_sculptpainting_randomize(wmKeyConfig *keyconf)
{
wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Sculpt (Randomize)", 0, 0);
wmKeyMap *keymap = WM_keymap_ensure(
keyconf, "Grease Pencil Stroke Sculpt (Randomize)", SPACE_EMPTY, RGN_TYPE_WINDOW);
keymap->poll = gpencil_stroke_sculptmode_randomize_poll;
}
/* keys for sculpt with a clone brush */
static void ed_keymap_gpencil_sculptpainting_clone(wmKeyConfig *keyconf)
{
wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Sculpt (Clone)", 0, 0);
wmKeyMap *keymap = WM_keymap_ensure(
keyconf, "Grease Pencil Stroke Sculpt (Clone)", SPACE_EMPTY, RGN_TYPE_WINDOW);
keymap->poll = gpencil_stroke_sculptmode_clone_poll;
}
/* keys for weight with a draw brush */
static void ed_keymap_gpencil_weightpainting_draw(wmKeyConfig *keyconf)
{
wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Weight (Draw)", 0, 0);
wmKeyMap *keymap = WM_keymap_ensure(
keyconf, "Grease Pencil Stroke Weight (Draw)", SPACE_EMPTY, RGN_TYPE_WINDOW);
keymap->poll = gpencil_stroke_weightmode_draw_poll;
}
/* keys for weight with a blur brush */
static void ed_keymap_gpencil_weightpainting_blur(wmKeyConfig *keyconf)
{
wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Weight (Blur)", 0, 0);
wmKeyMap *keymap = WM_keymap_ensure(
keyconf, "Grease Pencil Stroke Weight (Blur)", SPACE_EMPTY, RGN_TYPE_WINDOW);
keymap->poll = gpencil_stroke_weightmode_blur_poll;
}
/* keys for weight with a average brush */
static void ed_keymap_gpencil_weightpainting_average(wmKeyConfig *keyconf)
{
wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Weight (Average)", 0, 0);
wmKeyMap *keymap = WM_keymap_ensure(
keyconf, "Grease Pencil Stroke Weight (Average)", SPACE_EMPTY, RGN_TYPE_WINDOW);
keymap->poll = gpencil_stroke_weightmode_average_poll;
}
/* keys for weight with a smear brush */
static void ed_keymap_gpencil_weightpainting_smear(wmKeyConfig *keyconf)
{
wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Stroke Weight (Smear)", 0, 0);
wmKeyMap *keymap = WM_keymap_ensure(
keyconf, "Grease Pencil Stroke Weight (Smear)", SPACE_EMPTY, RGN_TYPE_WINDOW);
keymap->poll = gpencil_stroke_weightmode_smear_poll;
}

View File

@ -508,7 +508,7 @@ static void gpencil_brush_angle(bGPdata *gpd, Brush *brush, tGPspoint *pt, const
/* angle vector of the brush with full thickness */
const float v0[2] = {cos(angle), sin(angle)};
/* Apply to first point (only if there are 2 points because before no data to do it ) */
/* Apply to first point (only if there are 2 points because before no data to do it). */
if (gpd->runtime.sbuffer_used == 1) {
sub_v2_v2v2(mvec, mval, (pt - 1)->m_xy);
normalize_v2(mvec);

View File

@ -83,13 +83,15 @@ bool grease_pencil_painting_poll(bContext *C)
static void keymap_grease_pencil_editing(wmKeyConfig *keyconf)
{
wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Edit Mode", 0, 0);
wmKeyMap *keymap = WM_keymap_ensure(
keyconf, "Grease Pencil Edit Mode", SPACE_EMPTY, RGN_TYPE_WINDOW);
keymap->poll = editable_grease_pencil_poll;
}
static void keymap_grease_pencil_painting(wmKeyConfig *keyconf)
{
wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Grease Pencil Paint Mode", 0, 0);
wmKeyMap *keymap = WM_keymap_ensure(
keyconf, "Grease Pencil Paint Mode", SPACE_EMPTY, RGN_TYPE_WINDOW);
keymap->poll = grease_pencil_painting_poll;
}

View File

@ -38,6 +38,52 @@ void set_selected_frames_type(bke::greasepencil::Layer &layer,
}
}
static float get_snapped_frame_number(const float frame_number,
Scene &scene,
const eEditKeyframes_Snap mode)
{
switch (mode) {
case SNAP_KEYS_CURFRAME: /* Snap to current frame. */
return scene.r.cfra;
case SNAP_KEYS_NEARSEC: /* Snap to nearest second. */
{
float secf = (scene.r.frs_sec / scene.r.frs_sec_base);
return floorf(frame_number / secf + 0.5f) * secf;
}
case SNAP_KEYS_NEARMARKER: /* Snap to nearest marker. */
return ED_markers_find_nearest_marker_time(&scene.markers, frame_number);
default:
break;
}
return frame_number;
}
bool snap_selected_frames(GreasePencil &grease_pencil,
bke::greasepencil::Layer &layer,
Scene &scene,
const eEditKeyframes_Snap mode)
{
bool changed = false;
blender::Map<int, int> frame_number_destinations;
for (auto [frame_number, frame] : layer.frames().items()) {
if (!frame.is_selected()) {
continue;
}
const int snapped = round_fl_to_int(
get_snapped_frame_number(float(frame_number), scene, mode));
if (snapped != frame_number) {
frame_number_destinations.add(frame_number, snapped);
changed = true;
}
}
if (changed) {
grease_pencil.move_frames(layer, frame_number_destinations);
}
return changed;
}
static int get_mirrored_frame_number(const int frame_number,
const Scene &scene,
const eEditKeyframes_Mirror mode,

View File

@ -50,16 +50,21 @@ namespace blender::ed::greasepencil {
void set_selected_frames_type(bke::greasepencil::Layer &layer,
const eBezTriple_KeyframeType key_type);
/* Creates duplicate frames for each selected frame in the layer. The duplicates are stored in the
* LayerTransformData structure of the layer runtime data. This function also unselects the
* selected frames, while keeping the duplicates selected. */
bool duplicate_selected_frames(GreasePencil &grease_pencil, bke::greasepencil::Layer &layer);
bool snap_selected_frames(GreasePencil &grease_pencil,
bke::greasepencil::Layer &layer,
Scene &scene,
const eEditKeyframes_Snap mode);
bool mirror_selected_frames(GreasePencil &grease_pencil,
bke::greasepencil::Layer &layer,
Scene &scene,
const eEditKeyframes_Mirror mode);
/* Creates duplicate frames for each selected frame in the layer. The duplicates are stored in the
* LayerTransformData structure of the layer runtime data. This function also deselects the
* selected frames, while keeping the duplicates selected. */
bool duplicate_selected_frames(GreasePencil &grease_pencil, bke::greasepencil::Layer &layer);
bool remove_all_selected_frames(GreasePencil &grease_pencil, bke::greasepencil::Layer &layer);
void select_layer_channel(GreasePencil &grease_pencil, bke::greasepencil::Layer *layer);

View File

@ -3341,7 +3341,8 @@ void ui_but_range_set_soft(uiBut *but)
if (but->rnaprop) {
const PropertyType type = RNA_property_type(but->rnaprop);
const PropertySubType subtype = RNA_property_subtype(but->rnaprop);
double softmin, softmax /*, step, precision*/;
double softmin, softmax;
// double step, precision; /* UNUSED. */
double value_min;
double value_max;

View File

@ -138,7 +138,7 @@ static char *ui_drop_material_tooltip(bContext *C,
void ED_dropboxes_ui()
{
ListBase *lb = WM_dropboxmap_find("User Interface", SPACE_EMPTY, 0);
ListBase *lb = WM_dropboxmap_find("User Interface", SPACE_EMPTY, RGN_TYPE_WINDOW);
WM_dropbox_add(lb, "UI_OT_view_drop", ui_view_drop_poll, nullptr, nullptr, ui_view_drop_tooltip);
WM_dropbox_add(lb,

View File

@ -279,10 +279,10 @@ static void ui_selectcontext_apply(bContext *C,
/**
* Ideally we would only respond to events which are expected to be used for multi button editing
* (additionally checking if this is a mouse[wheel] or returnkey event to avoid the ALT conflict
* (additionally checking if this is a mouse[wheel] or return-key event to avoid the ALT conflict
* with button array pasting, see #108096, but unfortunately wheel events are not part of
* win->eventstate with modifiers held down. Instead, the conflict is avoided by specifically
* filtering out CTRL ALT V in ui_apply_but(). */
* `win->eventstate` with modifiers held down. Instead, the conflict is avoided by specifically
* filtering out CTRL ALT V in #ui_apply_but(). */
# define IS_ALLSELECT_EVENT(event) (((event)->modifier & KM_ALT) != 0)
/** just show a tinted color so users know its activated */
@ -2268,9 +2268,9 @@ static void ui_apply_but(
{
wmWindow *win = CTX_wm_window(C);
wmEvent *event = win->eventstate;
/* May have been enabled before activating, dont do for array pasting. */
/* May have been enabled before activating, don't do for array pasting. */
if (data->select_others.is_enabled || IS_ALLSELECT_EVENT(event)) {
/* See comment for IS_ALLSELECT_EVENT why this needs to be filtered here. */
/* See comment for #IS_ALLSELECT_EVENT why this needs to be filtered here. */
const bool is_array_paste = (event->val == KM_PRESS) &&
(event->modifier & (KM_CTRL | KM_OSKEY)) &&
(event->modifier & KM_SHIFT) == 0 && (event->type == EVT_VKEY);

View File

@ -98,6 +98,20 @@ enum RadialDirection {
UI_RADIAL_NW = 7,
};
/** Next direction (clockwise). */
#define UI_RADIAL_DIRECTION_NEXT(dir) RadialDirection((int(dir) + 1) % (int(UI_RADIAL_NW) + 1))
/** Previous direction (counter-clockwise). */
#define UI_RADIAL_DIRECTION_PREV(dir) \
RadialDirection(((int(dir) + int(UI_RADIAL_NW))) % (int(UI_RADIAL_NW) + 1))
/** Store a mask for diagonal directions. */
#define UI_RADIAL_MASK_ALL_DIAGONAL \
((1 << int(UI_RADIAL_NE)) | (1 << int(UI_RADIAL_SE)) | (1 << int(UI_RADIAL_SW)) | \
(1 << int(UI_RADIAL_NW)))
#define UI_RADIAL_MASK_ALL_AXIS_ALIGNED \
((1 << int(UI_RADIAL_N)) | (1 << int(UI_RADIAL_S)) | (1 << int(UI_RADIAL_E)) | \
(1 << int(UI_RADIAL_W)))
extern const char ui_radial_dir_order[8];
extern const char ui_radial_dir_to_numpad[8];
extern const short ui_radial_dir_to_angle[8];
@ -124,8 +138,6 @@ extern const short ui_radial_dir_to_angle[8];
/** #PieMenuData.flags */
enum {
/** Pie menu item collision is detected at 90 degrees. */
UI_PIE_DEGREES_RANGE_LARGE = (1 << 0),
/** Use initial center of pie menu to calculate direction. */
UI_PIE_INITIAL_DIRECTION = (1 << 1),
/** Pie menu is drag style. */
@ -429,6 +441,8 @@ struct PieMenuData {
const char *title;
int icon;
/** A mask combining the directions of all buttons in the pie menu (excluding separators). */
int pie_dir_mask;
float pie_dir[2];
float pie_center_init[2];
float pie_center_spawned[2];

View File

@ -2173,7 +2173,8 @@ void uiItemFullR(uiLayout *layout,
icon = (enum_value & value) ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT;
}
else {
icon = (enum_value == value) ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT;
/* Only a single value can be chosen, so display as radio buttons. */
icon = (enum_value == value) ? ICON_RADIOBUT_ON : ICON_RADIOBUT_OFF;
}
}
}
@ -3985,7 +3986,6 @@ static void ui_litem_layout_radial(uiLayout *litem)
{
int itemh, itemw;
int itemnum = 0;
int totitems = 0;
/* For the radial layout we will use Matt Ebb's design
* for radiation, see http://mattebb.com/weblog/radiation/
@ -3998,14 +3998,7 @@ static void ui_litem_layout_radial(uiLayout *litem)
int minx = x, miny = y, maxx = x, maxy = y;
/* first count total items */
LISTBASE_FOREACH (uiItem *, item, &litem->items) {
totitems++;
}
if (totitems < 5) {
litem->root->block->pie_data.flags |= UI_PIE_DEGREES_RANGE_LARGE;
}
litem->root->block->pie_data.pie_dir_mask = 0;
LISTBASE_FOREACH (uiItem *, item, &litem->items) {
/* not all button types are drawn in a radial menu, do filtering here */
@ -4033,6 +4026,10 @@ static void ui_litem_layout_radial(uiLayout *litem)
bitem->but->emboss = UI_EMBOSS_RADIAL;
bitem->but->drawflag |= UI_BUT_ICON_LEFT;
}
if (!ELEM(bitem->but->type, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE)) {
litem->root->block->pie_data.pie_dir_mask |= 1 << int(dir);
}
}
ui_item_size(item, &itemw, &itemh);

View File

@ -2631,7 +2631,7 @@ void ED_operatortypes_ui()
void ED_keymap_ui(wmKeyConfig *keyconf)
{
WM_keymap_ensure(keyconf, "User Interface", 0, 0);
WM_keymap_ensure(keyconf, "User Interface", SPACE_EMPTY, RGN_TYPE_WINDOW);
eyedropper_modal_keymap(keyconf);
eyedropper_colorband_modal_keymap(keyconf);

View File

@ -180,21 +180,56 @@ void ui_but_pie_dir(RadialDirection dir, float vec[2])
static bool ui_but_isect_pie_seg(const uiBlock *block, const uiBut *but)
{
const float angle_range = (block->pie_data.flags & UI_PIE_DEGREES_RANGE_LARGE) ? M_PI_4 :
M_PI_4 / 2.0;
float vec[2];
if (block->pie_data.flags & UI_PIE_INVALID_DIR) {
return false;
}
ui_but_pie_dir(but->pie_dir, vec);
/* Plus/minus 45 degrees: `cosf(DEG2RADF(45)) == M_SQRT1_2`. */
const float angle_4th_cos = M_SQRT1_2;
/* Plus/minus 22.5 degrees: `cosf(DEG2RADF(22.5))`. */
const float angle_8th_cos = 0.9238795f;
if (saacos(dot_v2v2(vec, block->pie_data.pie_dir)) < angle_range) {
/* Use a large bias so edge-cases fall back to comparing with the adjacent direction. */
const float eps_bias = 1e-4;
float but_dir[2];
ui_but_pie_dir(but->pie_dir, but_dir);
const float angle_but_cos = dot_v2v2(but_dir, block->pie_data.pie_dir);
/* Outside range (with bias). */
if (angle_but_cos < angle_4th_cos - eps_bias) {
return false;
}
/* Inside range (with bias). */
if (angle_but_cos > angle_8th_cos + eps_bias) {
return true;
}
return false;
/* Check if adjacent direction is closer (with tie breaker). */
RadialDirection dir_adjacent_8th, dir_adjacent_4th;
if (angle_signed_v2v2(but_dir, block->pie_data.pie_dir) < 0.0f) {
dir_adjacent_8th = UI_RADIAL_DIRECTION_PREV(but->pie_dir);
dir_adjacent_4th = UI_RADIAL_DIRECTION_PREV(dir_adjacent_8th);
}
else {
dir_adjacent_8th = UI_RADIAL_DIRECTION_NEXT(but->pie_dir);
dir_adjacent_4th = UI_RADIAL_DIRECTION_NEXT(dir_adjacent_8th);
}
const bool has_8th_adjacent = block->pie_data.pie_dir_mask & (1 << int(dir_adjacent_8th));
/* Compare with the adjacent direction (even if there is no button). */
const RadialDirection dir_adjacent = has_8th_adjacent ? dir_adjacent_8th : dir_adjacent_4th;
float but_dir_adjacent[2];
ui_but_pie_dir(dir_adjacent, but_dir_adjacent);
const float angle_adjacent_cos = dot_v2v2(but_dir_adjacent, block->pie_data.pie_dir);
/* Tie breaker, so one of the buttons is always selected. */
if (UNLIKELY(angle_but_cos == angle_adjacent_cos)) {
return but->pie_dir > dir_adjacent;
}
return angle_but_cos > angle_adjacent_cos;
}
bool ui_but_contains_pt(const uiBut *but, float mx, float my)

View File

@ -2876,6 +2876,7 @@ static bool ui_layout_operator_properties_only_booleans(const bContext *C,
PointerRNA ptr = RNA_pointer_create(&wm->id, op->type->srna, op->properties);
bool all_booleans = true;
RNA_STRUCT_BEGIN (&ptr, prop) {
if (RNA_property_flag(prop) & PROP_HIDDEN) {
continue;
@ -2885,10 +2886,14 @@ static bool ui_layout_operator_properties_only_booleans(const bContext *C,
continue;
}
if (RNA_property_type(prop) != PROP_BOOLEAN) {
return false;
all_booleans = false;
break;
}
}
RNA_STRUCT_END;
if (all_booleans == false) {
return false;
}
}
return true;

View File

@ -1957,7 +1957,7 @@ static void widget_draw_text(const uiFontStyle *fstyle,
}
}
/* If not editing and indeterminate, show dash.*/
/* If not editing and indeterminate, show dash. */
if (but->drawflag & UI_BUT_INDETERMINATE && !but->editstr &&
ELEM(but->type,
UI_BTYPE_MENU,
@ -5309,7 +5309,10 @@ void ui_draw_pie_center(uiBlock *block)
const int subd = 40;
const float angle = atan2f(pie_dir[1], pie_dir[0]);
const float range = (block->pie_data.flags & UI_PIE_DEGREES_RANGE_LARGE) ? M_PI_2 : M_PI_4;
/* Use a smaller range if there are both axis aligned & diagonal buttons. */
const bool has_aligned = (block->pie_data.pie_dir_mask & UI_RADIAL_MASK_ALL_AXIS_ALIGNED) != 0;
const bool has_diagonal = (block->pie_data.pie_dir_mask & UI_RADIAL_MASK_ALL_DIAGONAL) != 0;
const float range = (has_aligned && has_diagonal) ? M_PI_4 : M_PI_2;
GPU_matrix_push();
GPU_matrix_translate_2f(cx, cy);

View File

@ -2344,7 +2344,7 @@ void ED_operatortypes_view2d()
void ED_keymap_view2d(wmKeyConfig *keyconf)
{
WM_keymap_ensure(keyconf, "View2D", 0, 0);
WM_keymap_ensure(keyconf, "View2D", SPACE_EMPTY, RGN_TYPE_WINDOW);
}
/** \} */

View File

@ -29,6 +29,6 @@ void ED_operatortypes_lattice()
void ED_keymap_lattice(wmKeyConfig *keyconf)
{
wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Lattice", 0, 0);
wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Lattice", SPACE_EMPTY, RGN_TYPE_WINDOW);
keymap->poll = ED_operator_editlattice;
}

View File

@ -163,7 +163,7 @@ void ED_operatortypes_mask()
void ED_keymap_mask(wmKeyConfig *keyconf)
{
wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Mask Editing", 0, 0);
wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Mask Editing", SPACE_EMPTY, RGN_TYPE_WINDOW);
keymap->poll = ED_maskedit_poll;
}

View File

@ -358,7 +358,7 @@ void ED_operatormacros_mesh()
void ED_keymap_mesh(wmKeyConfig *keyconf)
{
wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Mesh", 0, 0);
wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Mesh", SPACE_EMPTY, RGN_TYPE_WINDOW);
keymap->poll = ED_operator_editmesh;
knifetool_modal_keymap(keyconf);

View File

@ -47,6 +47,6 @@ void ED_operatormacros_metaball()
void ED_keymap_metaball(wmKeyConfig *keyconf)
{
wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Metaball", 0, 0);
wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Metaball", SPACE_EMPTY, RGN_TYPE_WINDOW);
keymap->poll = ED_operator_editmball;
}

View File

@ -593,7 +593,7 @@ static int add_hook_object(const bContext *C,
/* matrix calculus */
/* vert x (obmat x hook->world_to_object) x hook->object_to_world x ob->world_to_object */
/* (parentinv ) */
/* (parentinv) */
Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
BKE_object_transform_copy(object_eval, ob);

View File

@ -10,6 +10,7 @@
#include <cstdlib>
#include "DNA_object_types.h"
#include "DNA_space_types.h"
#include "BKE_context.h"
@ -334,10 +335,10 @@ void ED_keymap_object(wmKeyConfig *keyconf)
wmKeyMap *keymap;
/* Objects, Regardless of Mode -------------------------------------------------- */
keymap = WM_keymap_ensure(keyconf, "Object Non-modal", 0, 0);
keymap = WM_keymap_ensure(keyconf, "Object Non-modal", SPACE_EMPTY, RGN_TYPE_WINDOW);
/* Object Mode ---------------------------------------------------------------- */
/* NOTE: this keymap gets disabled in non-object-mode. */
keymap = WM_keymap_ensure(keyconf, "Object Mode", 0, 0);
keymap = WM_keymap_ensure(keyconf, "Object Mode", SPACE_EMPTY, RGN_TYPE_WINDOW);
keymap->poll = object_mode_poll;
}

View File

@ -8,6 +8,8 @@
#include <cstdlib>
#include "DNA_space_types.h"
#include "WM_api.hh"
#include "ED_physics.hh"
@ -86,7 +88,7 @@ static void operatortypes_particle()
static void keymap_particle(wmKeyConfig *keyconf)
{
wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Particle", 0, 0);
wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Particle", SPACE_EMPTY, RGN_TYPE_WINDOW);
keymap->poll = PE_poll;
}

View File

@ -993,7 +993,7 @@ static void region_azone_edge(const ScrArea *area, AZone *az, const ARegion *reg
* the content, so move it a bit. */
const int overlap_padding =
/* Header-like regions are usually thin and there's not much padding around them,
* applying an offset would make the edge overlap buttons.*/
* applying an offset would make the edge overlap buttons. */
(!RGN_TYPE_IS_HEADER_ANY(region->regiontype) &&
/* Is the region background transparent? */
region->overlap && region_background_is_transparent(area, region)) ?
@ -1736,10 +1736,11 @@ static void ed_default_handlers(
/* XXX: it would be good to have bound-box checks for some of these. */
if (flag & ED_KEYMAP_UI) {
wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "User Interface", 0, 0);
wmKeyMap *keymap = WM_keymap_ensure(
wm->defaultconf, "User Interface", SPACE_EMPTY, RGN_TYPE_WINDOW);
WM_event_add_keymap_handler(handlers, keymap);
ListBase *dropboxes = WM_dropboxmap_find("User Interface", 0, 0);
ListBase *dropboxes = WM_dropboxmap_find("User Interface", SPACE_EMPTY, RGN_TYPE_WINDOW);
WM_event_add_dropbox_handler(handlers, dropboxes);
/* user interface widgets */
@ -1761,22 +1762,22 @@ static void ed_default_handlers(
}
if (flag & ED_KEYMAP_VIEW2D) {
/* 2d-viewport handling+manipulation */
wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "View2D", 0, 0);
wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "View2D", SPACE_EMPTY, RGN_TYPE_WINDOW);
WM_event_add_keymap_handler(handlers, keymap);
}
if (flag & ED_KEYMAP_ANIMATION) {
wmKeyMap *keymap;
/* time-markers */
keymap = WM_keymap_ensure(wm->defaultconf, "Markers", 0, 0);
keymap = WM_keymap_ensure(wm->defaultconf, "Markers", SPACE_EMPTY, RGN_TYPE_WINDOW);
WM_event_add_keymap_handler_poll(handlers, keymap, event_in_markers_region);
/* time-scrub */
keymap = WM_keymap_ensure(wm->defaultconf, "Time Scrub", 0, 0);
keymap = WM_keymap_ensure(wm->defaultconf, "Time Scrub", SPACE_EMPTY, RGN_TYPE_WINDOW);
WM_event_add_keymap_handler_poll(handlers, keymap, ED_time_scrub_event_in_region);
/* frame changing and timeline operators (for time spaces) */
keymap = WM_keymap_ensure(wm->defaultconf, "Animation", 0, 0);
keymap = WM_keymap_ensure(wm->defaultconf, "Animation", SPACE_EMPTY, RGN_TYPE_WINDOW);
WM_event_add_keymap_handler(handlers, keymap);
}
if (flag & ED_KEYMAP_TOOL) {
@ -1791,27 +1792,31 @@ static void ed_default_handlers(
}
if (flag & ED_KEYMAP_FRAMES) {
/* frame changing/jumping (for all spaces) */
wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "Frames", 0, 0);
wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "Frames", SPACE_EMPTY, RGN_TYPE_WINDOW);
WM_event_add_keymap_handler(handlers, keymap);
}
if (flag & ED_KEYMAP_HEADER) {
/* standard keymap for headers regions */
wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "Region Context Menu", 0, 0);
wmKeyMap *keymap = WM_keymap_ensure(
wm->defaultconf, "Region Context Menu", SPACE_EMPTY, RGN_TYPE_WINDOW);
WM_event_add_keymap_handler(handlers, keymap);
}
if (flag & ED_KEYMAP_FOOTER) {
/* standard keymap for footer regions */
wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "Region Context Menu", 0, 0);
wmKeyMap *keymap = WM_keymap_ensure(
wm->defaultconf, "Region Context Menu", SPACE_EMPTY, RGN_TYPE_WINDOW);
WM_event_add_keymap_handler(handlers, keymap);
}
if (flag & ED_KEYMAP_NAVBAR) {
/* standard keymap for Navigation bar regions */
wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "Region Context Menu", 0, 0);
wmKeyMap *keymap = WM_keymap_ensure(
wm->defaultconf, "Region Context Menu", SPACE_EMPTY, RGN_TYPE_WINDOW);
WM_event_add_keymap_handler(&region->handlers, keymap);
}
if (flag & ED_KEYMAP_ASSET_SHELF) {
/* standard keymap for asset shelf regions */
wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "Asset Shelf", 0, 0);
wmKeyMap *keymap = WM_keymap_ensure(
wm->defaultconf, "Asset Shelf", SPACE_EMPTY, RGN_TYPE_WINDOW);
WM_event_add_keymap_handler(&region->handlers, keymap);
}
@ -1824,120 +1829,157 @@ static void ed_default_handlers(
* For now, it's easier to just include all,
* since you hardly want one without the others.
*/
wmKeyMap *keymap_general = WM_keymap_ensure(wm->defaultconf, "Grease Pencil", 0, 0);
WM_event_add_keymap_handler(handlers, keymap_general);
wmKeyMap *keymap_curve_edit = WM_keymap_ensure(
wm->defaultconf, "Grease Pencil Stroke Curve Edit Mode", 0, 0);
WM_event_add_keymap_handler(handlers, keymap_curve_edit);
wmKeyMap *keymap_edit = WM_keymap_ensure(
wm->defaultconf, "Grease Pencil Stroke Edit Mode", 0, 0);
WM_event_add_keymap_handler(handlers, keymap_edit);
wmKeyMap *keymap_paint = WM_keymap_ensure(
wm->defaultconf, "Grease Pencil Stroke Paint Mode", 0, 0);
WM_event_add_keymap_handler(handlers, keymap_paint);
wmKeyMap *keymap_paint_draw = WM_keymap_ensure(
wm->defaultconf, "Grease Pencil Stroke Paint (Draw brush)", 0, 0);
WM_event_add_keymap_handler(handlers, keymap_paint_draw);
wmKeyMap *keymap_paint_erase = WM_keymap_ensure(
wm->defaultconf, "Grease Pencil Stroke Paint (Erase)", 0, 0);
WM_event_add_keymap_handler(handlers, keymap_paint_erase);
wmKeyMap *keymap_paint_fill = WM_keymap_ensure(
wm->defaultconf, "Grease Pencil Stroke Paint (Fill)", 0, 0);
WM_event_add_keymap_handler(handlers, keymap_paint_fill);
wmKeyMap *keymap_paint_tint = WM_keymap_ensure(
wm->defaultconf, "Grease Pencil Stroke Paint (Tint)", 0, 0);
WM_event_add_keymap_handler(handlers, keymap_paint_tint);
wmKeyMap *keymap_sculpt = WM_keymap_ensure(
wm->defaultconf, "Grease Pencil Stroke Sculpt Mode", 0, 0);
WM_event_add_keymap_handler(handlers, keymap_sculpt);
wmKeyMap *keymap_vertex = WM_keymap_ensure(
wm->defaultconf, "Grease Pencil Stroke Vertex Mode", 0, 0);
WM_event_add_keymap_handler(handlers, keymap_vertex);
wmKeyMap *keymap_vertex_draw = WM_keymap_ensure(
wm->defaultconf, "Grease Pencil Stroke Vertex (Draw)", 0, 0);
WM_event_add_keymap_handler(handlers, keymap_vertex_draw);
wmKeyMap *keymap_vertex_blur = WM_keymap_ensure(
wm->defaultconf, "Grease Pencil Stroke Vertex (Blur)", 0, 0);
WM_event_add_keymap_handler(handlers, keymap_vertex_blur);
wmKeyMap *keymap_vertex_average = WM_keymap_ensure(
wm->defaultconf, "Grease Pencil Stroke Vertex (Average)", 0, 0);
WM_event_add_keymap_handler(handlers, keymap_vertex_average);
wmKeyMap *keymap_vertex_smear = WM_keymap_ensure(
wm->defaultconf, "Grease Pencil Stroke Vertex (Smear)", 0, 0);
WM_event_add_keymap_handler(handlers, keymap_vertex_smear);
wmKeyMap *keymap_vertex_replace = WM_keymap_ensure(
wm->defaultconf, "Grease Pencil Stroke Vertex (Replace)", 0, 0);
WM_event_add_keymap_handler(handlers, keymap_vertex_replace);
wmKeyMap *keymap_sculpt_smooth = WM_keymap_ensure(
wm->defaultconf, "Grease Pencil Stroke Sculpt (Smooth)", 0, 0);
WM_event_add_keymap_handler(handlers, keymap_sculpt_smooth);
wmKeyMap *keymap_sculpt_thickness = WM_keymap_ensure(
wm->defaultconf, "Grease Pencil Stroke Sculpt (Thickness)", 0, 0);
WM_event_add_keymap_handler(handlers, keymap_sculpt_thickness);
wmKeyMap *keymap_sculpt_strength = WM_keymap_ensure(
wm->defaultconf, "Grease Pencil Stroke Sculpt (Strength)", 0, 0);
WM_event_add_keymap_handler(handlers, keymap_sculpt_strength);
wmKeyMap *keymap_sculpt_grab = WM_keymap_ensure(
wm->defaultconf, "Grease Pencil Stroke Sculpt (Grab)", 0, 0);
WM_event_add_keymap_handler(handlers, keymap_sculpt_grab);
wmKeyMap *keymap_sculpt_push = WM_keymap_ensure(
wm->defaultconf, "Grease Pencil Stroke Sculpt (Push)", 0, 0);
WM_event_add_keymap_handler(handlers, keymap_sculpt_push);
wmKeyMap *keymap_sculpt_twist = WM_keymap_ensure(
wm->defaultconf, "Grease Pencil Stroke Sculpt (Twist)", 0, 0);
WM_event_add_keymap_handler(handlers, keymap_sculpt_twist);
wmKeyMap *keymap_sculpt_pinch = WM_keymap_ensure(
wm->defaultconf, "Grease Pencil Stroke Sculpt (Pinch)", 0, 0);
WM_event_add_keymap_handler(handlers, keymap_sculpt_pinch);
wmKeyMap *keymap_sculpt_randomize = WM_keymap_ensure(
wm->defaultconf, "Grease Pencil Stroke Sculpt (Randomize)", 0, 0);
WM_event_add_keymap_handler(handlers, keymap_sculpt_randomize);
wmKeyMap *keymap_sculpt_clone = WM_keymap_ensure(
wm->defaultconf, "Grease Pencil Stroke Sculpt (Clone)", 0, 0);
WM_event_add_keymap_handler(handlers, keymap_sculpt_clone);
wmKeyMap *keymap_weight = WM_keymap_ensure(
wm->defaultconf, "Grease Pencil Stroke Weight Mode", 0, 0);
WM_event_add_keymap_handler(handlers, keymap_weight);
wmKeyMap *keymap_weight_draw = WM_keymap_ensure(
wm->defaultconf, "Grease Pencil Stroke Weight (Draw)", 0, 0);
WM_event_add_keymap_handler(handlers, keymap_weight_draw);
wmKeyMap *keymap_weight_blur = WM_keymap_ensure(
wm->defaultconf, "Grease Pencil Stroke Weight (Blur)", 0, 0);
WM_event_add_keymap_handler(handlers, keymap_weight_blur);
wmKeyMap *keymap_weight_average = WM_keymap_ensure(
wm->defaultconf, "Grease Pencil Stroke Weight (Average)", 0, 0);
WM_event_add_keymap_handler(handlers, keymap_weight_average);
wmKeyMap *keymap_weight_smear = WM_keymap_ensure(
wm->defaultconf, "Grease Pencil Stroke Weight (Smear)", 0, 0);
WM_event_add_keymap_handler(handlers, keymap_weight_smear);
{
wmKeyMap *keymap = WM_keymap_ensure(
wm->defaultconf, "Grease Pencil", SPACE_EMPTY, RGN_TYPE_WINDOW);
WM_event_add_keymap_handler(handlers, keymap);
}
{
wmKeyMap *keymap = WM_keymap_ensure(
wm->defaultconf, "Grease Pencil Stroke Curve Edit Mode", SPACE_EMPTY, RGN_TYPE_WINDOW);
WM_event_add_keymap_handler(handlers, keymap);
}
{
wmKeyMap *keymap = WM_keymap_ensure(
wm->defaultconf, "Grease Pencil Stroke Edit Mode", SPACE_EMPTY, RGN_TYPE_WINDOW);
WM_event_add_keymap_handler(handlers, keymap);
}
{
wmKeyMap *keymap = WM_keymap_ensure(
wm->defaultconf, "Grease Pencil Stroke Paint Mode", SPACE_EMPTY, RGN_TYPE_WINDOW);
WM_event_add_keymap_handler(handlers, keymap);
}
{
wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf,
"Grease Pencil Stroke Paint (Draw brush)",
SPACE_EMPTY,
RGN_TYPE_WINDOW);
WM_event_add_keymap_handler(handlers, keymap);
}
{
wmKeyMap *keymap = WM_keymap_ensure(
wm->defaultconf, "Grease Pencil Stroke Paint (Erase)", SPACE_EMPTY, RGN_TYPE_WINDOW);
WM_event_add_keymap_handler(handlers, keymap);
}
{
wmKeyMap *keymap = WM_keymap_ensure(
wm->defaultconf, "Grease Pencil Stroke Paint (Fill)", SPACE_EMPTY, RGN_TYPE_WINDOW);
WM_event_add_keymap_handler(handlers, keymap);
}
{
wmKeyMap *keymap = WM_keymap_ensure(
wm->defaultconf, "Grease Pencil Stroke Paint (Tint)", SPACE_EMPTY, RGN_TYPE_WINDOW);
WM_event_add_keymap_handler(handlers, keymap);
}
{
wmKeyMap *keymap = WM_keymap_ensure(
wm->defaultconf, "Grease Pencil Stroke Sculpt Mode", SPACE_EMPTY, RGN_TYPE_WINDOW);
WM_event_add_keymap_handler(handlers, keymap);
}
{
wmKeyMap *keymap = WM_keymap_ensure(
wm->defaultconf, "Grease Pencil Stroke Vertex Mode", SPACE_EMPTY, RGN_TYPE_WINDOW);
WM_event_add_keymap_handler(handlers, keymap);
}
{
wmKeyMap *keymap = WM_keymap_ensure(
wm->defaultconf, "Grease Pencil Stroke Vertex (Draw)", SPACE_EMPTY, RGN_TYPE_WINDOW);
WM_event_add_keymap_handler(handlers, keymap);
}
{
wmKeyMap *keymap = WM_keymap_ensure(
wm->defaultconf, "Grease Pencil Stroke Vertex (Blur)", SPACE_EMPTY, RGN_TYPE_WINDOW);
WM_event_add_keymap_handler(handlers, keymap);
}
{
wmKeyMap *keymap = WM_keymap_ensure(
wm->defaultconf, "Grease Pencil Stroke Vertex (Average)", SPACE_EMPTY, RGN_TYPE_WINDOW);
WM_event_add_keymap_handler(handlers, keymap);
}
{
wmKeyMap *keymap = WM_keymap_ensure(
wm->defaultconf, "Grease Pencil Stroke Vertex (Smear)", SPACE_EMPTY, RGN_TYPE_WINDOW);
WM_event_add_keymap_handler(handlers, keymap);
}
{
wmKeyMap *keymap = WM_keymap_ensure(
wm->defaultconf, "Grease Pencil Stroke Vertex (Replace)", SPACE_EMPTY, RGN_TYPE_WINDOW);
WM_event_add_keymap_handler(handlers, keymap);
}
{
wmKeyMap *keymap = WM_keymap_ensure(
wm->defaultconf, "Grease Pencil Stroke Sculpt (Smooth)", SPACE_EMPTY, RGN_TYPE_WINDOW);
WM_event_add_keymap_handler(handlers, keymap);
}
{
wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf,
"Grease Pencil Stroke Sculpt (Thickness)",
SPACE_EMPTY,
RGN_TYPE_WINDOW);
WM_event_add_keymap_handler(handlers, keymap);
}
{
wmKeyMap *keymap = WM_keymap_ensure(
wm->defaultconf, "Grease Pencil Stroke Sculpt (Strength)", SPACE_EMPTY, RGN_TYPE_WINDOW);
WM_event_add_keymap_handler(handlers, keymap);
}
{
wmKeyMap *keymap = WM_keymap_ensure(
wm->defaultconf, "Grease Pencil Stroke Sculpt (Grab)", SPACE_EMPTY, RGN_TYPE_WINDOW);
WM_event_add_keymap_handler(handlers, keymap);
}
{
wmKeyMap *keymap = WM_keymap_ensure(
wm->defaultconf, "Grease Pencil Stroke Sculpt (Push)", SPACE_EMPTY, RGN_TYPE_WINDOW);
WM_event_add_keymap_handler(handlers, keymap);
}
{
wmKeyMap *keymap = WM_keymap_ensure(
wm->defaultconf, "Grease Pencil Stroke Sculpt (Twist)", SPACE_EMPTY, RGN_TYPE_WINDOW);
WM_event_add_keymap_handler(handlers, keymap);
}
{
wmKeyMap *keymap = WM_keymap_ensure(
wm->defaultconf, "Grease Pencil Stroke Sculpt (Pinch)", SPACE_EMPTY, RGN_TYPE_WINDOW);
WM_event_add_keymap_handler(handlers, keymap);
}
{
wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf,
"Grease Pencil Stroke Sculpt (Randomize)",
SPACE_EMPTY,
RGN_TYPE_WINDOW);
WM_event_add_keymap_handler(handlers, keymap);
}
{
wmKeyMap *keymap = WM_keymap_ensure(
wm->defaultconf, "Grease Pencil Stroke Sculpt (Clone)", SPACE_EMPTY, RGN_TYPE_WINDOW);
WM_event_add_keymap_handler(handlers, keymap);
}
{
wmKeyMap *keymap = WM_keymap_ensure(
wm->defaultconf, "Grease Pencil Stroke Weight Mode", SPACE_EMPTY, RGN_TYPE_WINDOW);
WM_event_add_keymap_handler(handlers, keymap);
}
{
wmKeyMap *keymap = WM_keymap_ensure(
wm->defaultconf, "Grease Pencil Stroke Weight (Draw)", SPACE_EMPTY, RGN_TYPE_WINDOW);
WM_event_add_keymap_handler(handlers, keymap);
}
{
wmKeyMap *keymap = WM_keymap_ensure(
wm->defaultconf, "Grease Pencil Stroke Weight (Blur)", SPACE_EMPTY, RGN_TYPE_WINDOW);
WM_event_add_keymap_handler(handlers, keymap);
}
{
wmKeyMap *keymap = WM_keymap_ensure(
wm->defaultconf, "Grease Pencil Stroke Weight (Average)", SPACE_EMPTY, RGN_TYPE_WINDOW);
WM_event_add_keymap_handler(handlers, keymap);
}
{
wmKeyMap *keymap = WM_keymap_ensure(
wm->defaultconf, "Grease Pencil Stroke Weight (Smear)", SPACE_EMPTY, RGN_TYPE_WINDOW);
WM_event_add_keymap_handler(handlers, keymap);
}
}
}
@ -3272,7 +3314,8 @@ void ED_region_panels_init(wmWindowManager *wm, ARegion *region)
{
UI_view2d_region_reinit(&region->v2d, V2D_COMMONVIEW_PANELS_UI, region->winx, region->winy);
wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "View2D Buttons List", 0, 0);
wmKeyMap *keymap = WM_keymap_ensure(
wm->defaultconf, "View2D Buttons List", SPACE_EMPTY, RGN_TYPE_WINDOW);
WM_event_add_keymap_handler(&region->handlers, keymap);
}

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