WIP: Experiment: Geometry Nodes: support baking individual simulations #112179
|
@ -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()
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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++;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]];
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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),
|
||||
])
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
||||
|
|
|
@ -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_);
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]);
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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: {
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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];
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -271,7 +271,8 @@ void ED_asset_shelf_region_init(wmWindowManager *wm, ARegion *region)
|
|||
|
||||
UI_view2d_region_reinit(®ion->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(®ion->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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 *>(
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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(®ion->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(®ion->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(®ion->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(®ion->handlers, keymap);
|
||||
}
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue