Compositor: add new node: Kuwahara filter #107015
|
@ -79,6 +79,7 @@ struct CCLShadowContext
|
||||||
#endif
|
#endif
|
||||||
IntegratorShadowState isect_s;
|
IntegratorShadowState isect_s;
|
||||||
float throughput;
|
float throughput;
|
||||||
|
float max_t;
|
||||||
bool opaque_hit;
|
bool opaque_hit;
|
||||||
numhit_t max_hits;
|
numhit_t max_hits;
|
||||||
numhit_t num_hits;
|
numhit_t num_hits;
|
||||||
|
@ -314,7 +315,7 @@ ccl_device_forceinline void kernel_embree_filter_occluded_shadow_all_func_impl(
|
||||||
/* Current implementation in Cycles assumes only single-ray intersection queries. */
|
/* Current implementation in Cycles assumes only single-ray intersection queries. */
|
||||||
assert(args->N == 1);
|
assert(args->N == 1);
|
||||||
|
|
||||||
RTCRay *ray = (RTCRay *)args->ray;
|
const RTCRay *ray = (RTCRay *)args->ray;
|
||||||
RTCHit *hit = (RTCHit *)args->hit;
|
RTCHit *hit = (RTCHit *)args->hit;
|
||||||
#if EMBREE_MAJOR_VERSION >= 4
|
#if EMBREE_MAJOR_VERSION >= 4
|
||||||
CCLShadowContext *ctx = (CCLShadowContext *)(args->context);
|
CCLShadowContext *ctx = (CCLShadowContext *)(args->context);
|
||||||
|
@ -367,42 +368,51 @@ ccl_device_forceinline void kernel_embree_filter_occluded_shadow_all_func_impl(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Test if we need to record this transparent intersection. */
|
numhit_t isect_index = ctx->num_recorded_hits;
|
||||||
const numhit_t max_record_hits = min(ctx->max_hits, numhit_t(INTEGRATOR_SHADOW_ISECT_SIZE));
|
|
||||||
if (ctx->num_recorded_hits < max_record_hits) {
|
|
||||||
/* If maximum number of hits was reached, replace the intersection with the
|
|
||||||
* highest distance. We want to find the N closest intersections. */
|
|
||||||
const numhit_t num_recorded_hits = min(ctx->num_recorded_hits, max_record_hits);
|
|
||||||
numhit_t isect_index = num_recorded_hits;
|
|
||||||
if (num_recorded_hits + 1 >= max_record_hits) {
|
|
||||||
float max_t = INTEGRATOR_STATE_ARRAY(ctx->isect_s, shadow_isect, 0, t);
|
|
||||||
numhit_t max_recorded_hit = numhit_t(0);
|
|
||||||
|
|
||||||
for (numhit_t i = numhit_t(1); i < num_recorded_hits; ++i) {
|
|
||||||
const float isect_t = INTEGRATOR_STATE_ARRAY(ctx->isect_s, shadow_isect, i, t);
|
|
||||||
if (isect_t > max_t) {
|
|
||||||
max_recorded_hit = i;
|
|
||||||
max_t = isect_t;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (num_recorded_hits >= max_record_hits) {
|
|
||||||
isect_index = max_recorded_hit;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Limit the ray distance and stop counting hits beyond this. */
|
|
||||||
ray->tfar = max(current_isect.t, max_t);
|
|
||||||
}
|
|
||||||
|
|
||||||
integrator_state_write_shadow_isect(ctx->isect_s, ¤t_isect, isect_index);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Always increase the number of recorded hits, even beyond the maximum,
|
/* Always increase the number of recorded hits, even beyond the maximum,
|
||||||
* so that we can detect this and trace another ray if needed. */
|
* so that we can detect this and trace another ray if needed.
|
||||||
|
* More details about the related logic can be found in implementation of
|
||||||
|
* "shadow_intersections_has_remaining" and "integrate_transparent_shadow"
|
||||||
|
* functions. */
|
||||||
++ctx->num_recorded_hits;
|
++ctx->num_recorded_hits;
|
||||||
|
|
||||||
/* This tells Embree to continue tracing. */
|
/* This tells Embree to continue tracing. */
|
||||||
*args->valid = 0;
|
*args->valid = 0;
|
||||||
|
|
||||||
|
const numhit_t max_record_hits = min(ctx->max_hits, numhit_t(INTEGRATOR_SHADOW_ISECT_SIZE));
|
||||||
|
/* If the maximum number of hits was reached, replace the furthest intersection
|
||||||
|
* with a closer one so we get the N closest intersections. */
|
||||||
|
if (isect_index >= max_record_hits) {
|
||||||
|
/* When recording only N closest hits, max_t will always only decrease.
|
||||||
|
* So let's test if we are already not meeting criteria and can skip max_t recalculation. */
|
||||||
|
if (current_isect.t >= ctx->max_t) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
float max_t = INTEGRATOR_STATE_ARRAY(ctx->isect_s, shadow_isect, 0, t);
|
||||||
|
numhit_t max_recorded_hit = numhit_t(0);
|
||||||
|
|
||||||
|
for (numhit_t i = numhit_t(1); i < max_record_hits; ++i) {
|
||||||
|
const float isect_t = INTEGRATOR_STATE_ARRAY(ctx->isect_s, shadow_isect, i, t);
|
||||||
|
if (isect_t > max_t) {
|
||||||
|
max_recorded_hit = i;
|
||||||
|
max_t = isect_t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
isect_index = max_recorded_hit;
|
||||||
|
|
||||||
|
/* Limit the ray distance and avoid processing hits beyond this. */
|
||||||
|
ctx->max_t = max_t;
|
||||||
|
|
||||||
|
/* If it's further away than max_t, we don't record this transparent intersection. */
|
||||||
|
if (current_isect.t >= max_t) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
integrator_state_write_shadow_isect(ctx->isect_s, ¤t_isect, isect_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
ccl_device_forceinline void kernel_embree_filter_occluded_local_func_impl(
|
ccl_device_forceinline void kernel_embree_filter_occluded_local_func_impl(
|
||||||
|
|
|
@ -350,7 +350,7 @@ def main():
|
||||||
if name.rpartition(".")[2].isdigit():
|
if name.rpartition(".")[2].isdigit():
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if not ob_eval.data.attributes.active_color:
|
if (not hasattr(ob_eval.data, 'attributes')) or not ob_eval.data.attributes.active_color:
|
||||||
print("Skipping:", name, "(no vertex colors)")
|
print("Skipping:", name, "(no vertex colors)")
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
|
|
@ -1836,6 +1836,10 @@ def km_graph_editor(params):
|
||||||
("graph.delete", {"type": 'DEL', "value": 'PRESS'}, {"properties": [("confirm", False)]}),
|
("graph.delete", {"type": 'DEL', "value": 'PRESS'}, {"properties": [("confirm", False)]}),
|
||||||
("graph.duplicate_move", {"type": 'D', "value": 'PRESS', "shift": True}, None),
|
("graph.duplicate_move", {"type": 'D', "value": 'PRESS', "shift": True}, None),
|
||||||
("graph.keyframe_insert", {"type": 'I', "value": 'PRESS'}, None),
|
("graph.keyframe_insert", {"type": 'I', "value": 'PRESS'}, None),
|
||||||
|
("graph.keyframe_jump", {"type": 'UP_ARROW', "value": 'PRESS', "repeat": True},
|
||||||
|
{"properties": [("next", True)]}),
|
||||||
|
("graph.keyframe_jump", {"type": 'DOWN_ARROW', "value": 'PRESS', "repeat": True},
|
||||||
|
{"properties": [("next", False)]}),
|
||||||
("graph.click_insert", {"type": params.action_mouse, "value": 'CLICK', "ctrl": True}, None),
|
("graph.click_insert", {"type": params.action_mouse, "value": 'CLICK', "ctrl": True}, None),
|
||||||
("graph.click_insert", {"type": params.action_mouse, "value": 'CLICK', "shift": True, "ctrl": True},
|
("graph.click_insert", {"type": params.action_mouse, "value": 'CLICK', "shift": True, "ctrl": True},
|
||||||
{"properties": [("extend", True)]}),
|
{"properties": [("extend", True)]}),
|
||||||
|
|
|
@ -3111,7 +3111,7 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel):
|
||||||
*_tools_annotate,
|
*_tools_annotate,
|
||||||
],
|
],
|
||||||
'EDIT_GPENCIL': [
|
'EDIT_GPENCIL': [
|
||||||
*_tools_gpencil_select,
|
*_tools_select,
|
||||||
_defs_view3d_generic.cursor,
|
_defs_view3d_generic.cursor,
|
||||||
None,
|
None,
|
||||||
*_tools_transform,
|
*_tools_transform,
|
||||||
|
|
|
@ -38,6 +38,13 @@ typedef struct AssetTypeInfo {
|
||||||
struct AssetMetaData *BKE_asset_metadata_create(void);
|
struct AssetMetaData *BKE_asset_metadata_create(void);
|
||||||
void BKE_asset_metadata_free(struct AssetMetaData **asset_data);
|
void BKE_asset_metadata_free(struct AssetMetaData **asset_data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a copy of the #AssetMetaData so that it can be assigned to another asset.
|
||||||
|
*
|
||||||
|
* The caller becomes the owner of the returned pointer.
|
||||||
|
*/
|
||||||
|
struct AssetMetaData *BKE_asset_metadata_copy(const struct AssetMetaData *source);
|
||||||
|
|
||||||
struct AssetTagEnsureResult {
|
struct AssetTagEnsureResult {
|
||||||
struct AssetTag *tag;
|
struct AssetTag *tag;
|
||||||
/* Set to false if a tag of this name was already present. */
|
/* Set to false if a tag of this name was already present. */
|
||||||
|
|
|
@ -51,5 +51,8 @@ struct GeometryDeformation {
|
||||||
GeometryDeformation get_evaluated_curves_deformation(const Object *ob_eval, const Object &ob_orig);
|
GeometryDeformation get_evaluated_curves_deformation(const Object *ob_eval, const Object &ob_orig);
|
||||||
GeometryDeformation get_evaluated_curves_deformation(const Depsgraph &depsgraph,
|
GeometryDeformation get_evaluated_curves_deformation(const Depsgraph &depsgraph,
|
||||||
const Object &ob_orig);
|
const Object &ob_orig);
|
||||||
|
GeometryDeformation get_evaluated_grease_pencil_drawing_deformation(const Object *ob_eval,
|
||||||
|
const Object &ob_orig,
|
||||||
|
int drawing_index);
|
||||||
|
|
||||||
} // namespace blender::bke::crazyspace
|
} // namespace blender::bke::crazyspace
|
||||||
|
|
|
@ -39,6 +39,38 @@ void BKE_asset_metadata_free(AssetMetaData **asset_data)
|
||||||
*asset_data = nullptr;
|
*asset_data = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AssetMetaData *BKE_asset_metadata_copy(const AssetMetaData *source)
|
||||||
|
{
|
||||||
|
AssetMetaData *copy = BKE_asset_metadata_create();
|
||||||
|
|
||||||
|
copy->local_type_info = source->local_type_info;
|
||||||
|
|
||||||
|
if (source->properties) {
|
||||||
|
copy->properties = IDP_CopyProperty(source->properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
BKE_asset_metadata_catalog_id_set(copy, source->catalog_id, source->catalog_simple_name);
|
||||||
|
|
||||||
|
if (source->author) {
|
||||||
|
copy->author = BLI_strdup(source->author);
|
||||||
|
}
|
||||||
|
if (source->description) {
|
||||||
|
copy->description = BLI_strdup(source->description);
|
||||||
|
}
|
||||||
|
if (source->copyright) {
|
||||||
|
copy->copyright = BLI_strdup(source->copyright);
|
||||||
|
}
|
||||||
|
if (source->license) {
|
||||||
|
copy->license = BLI_strdup(source->license);
|
||||||
|
}
|
||||||
|
|
||||||
|
BLI_duplicatelist(©->tags, &source->tags);
|
||||||
|
copy->active_tag = source->active_tag;
|
||||||
|
copy->tot_tags = source->tot_tags;
|
||||||
|
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
AssetMetaData::~AssetMetaData()
|
AssetMetaData::~AssetMetaData()
|
||||||
{
|
{
|
||||||
if (properties) {
|
if (properties) {
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "BKE_curves.hh"
|
#include "BKE_curves.hh"
|
||||||
#include "BKE_editmesh.h"
|
#include "BKE_editmesh.h"
|
||||||
#include "BKE_geometry_set.hh"
|
#include "BKE_geometry_set.hh"
|
||||||
|
#include "BKE_grease_pencil.hh"
|
||||||
#include "BKE_lib_id.h"
|
#include "BKE_lib_id.h"
|
||||||
#include "BKE_mesh.hh"
|
#include "BKE_mesh.hh"
|
||||||
#include "BKE_mesh_wrapper.h"
|
#include "BKE_mesh_wrapper.h"
|
||||||
|
@ -662,4 +663,37 @@ GeometryDeformation get_evaluated_curves_deformation(const Depsgraph &depsgraph,
|
||||||
return get_evaluated_curves_deformation(ob_eval, ob_orig);
|
return get_evaluated_curves_deformation(ob_eval, ob_orig);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GeometryDeformation get_evaluated_grease_pencil_drawing_deformation(const Object *ob_eval,
|
||||||
|
const Object &ob_orig,
|
||||||
|
const int drawing_index)
|
||||||
|
{
|
||||||
|
BLI_assert(ob_orig.type == OB_GREASE_PENCIL);
|
||||||
|
const GreasePencil &grease_pencil_orig = *static_cast<const GreasePencil *>(ob_orig.data);
|
||||||
|
|
||||||
|
GreasePencilDrawingBase *drawing_base = grease_pencil_orig.drawings()[drawing_index];
|
||||||
|
|
||||||
|
GeometryDeformation deformation;
|
||||||
|
if (drawing_base->type == GP_DRAWING) {
|
||||||
|
GreasePencilDrawing *drawing = reinterpret_cast<GreasePencilDrawing *>(drawing_base);
|
||||||
|
/* Use the undeformed positions by default. */
|
||||||
|
deformation.positions = drawing->geometry.wrap().positions();
|
||||||
|
}
|
||||||
|
else if (drawing_base->type == GP_DRAWING_REFERENCE) {
|
||||||
|
/* TODO */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ob_eval == nullptr) {
|
||||||
|
return deformation;
|
||||||
|
}
|
||||||
|
const GeometrySet *geometry_eval = ob_eval->runtime.geometry_set_eval;
|
||||||
|
if (geometry_eval == nullptr) {
|
||||||
|
return deformation;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: Read `GeometryComponentEditData` from `geometry_eval` and populate deformation with it.
|
||||||
|
*/
|
||||||
|
|
||||||
|
return deformation;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace blender::bke::crazyspace
|
} // namespace blender::bke::crazyspace
|
||||||
|
|
|
@ -1061,7 +1061,7 @@ enum ForeachDrawingMode {
|
||||||
static void foreach_drawing_ex(GreasePencil &grease_pencil,
|
static void foreach_drawing_ex(GreasePencil &grease_pencil,
|
||||||
int frame,
|
int frame,
|
||||||
ForeachDrawingMode mode,
|
ForeachDrawingMode mode,
|
||||||
blender::FunctionRef<void(GreasePencilDrawing &)> function)
|
blender::FunctionRef<void(int, GreasePencilDrawing &)> function)
|
||||||
{
|
{
|
||||||
using namespace blender::bke::greasepencil;
|
using namespace blender::bke::greasepencil;
|
||||||
|
|
||||||
|
@ -1089,7 +1089,7 @@ static void foreach_drawing_ex(GreasePencil &grease_pencil,
|
||||||
GreasePencilDrawingBase *drawing_base = drawings[index];
|
GreasePencilDrawingBase *drawing_base = drawings[index];
|
||||||
if (drawing_base->type == GP_DRAWING) {
|
if (drawing_base->type == GP_DRAWING) {
|
||||||
GreasePencilDrawing *drawing = reinterpret_cast<GreasePencilDrawing *>(drawing_base);
|
GreasePencilDrawing *drawing = reinterpret_cast<GreasePencilDrawing *>(drawing_base);
|
||||||
function(*drawing);
|
function(index, *drawing);
|
||||||
}
|
}
|
||||||
else if (drawing_base->type == GP_DRAWING_REFERENCE) {
|
else if (drawing_base->type == GP_DRAWING_REFERENCE) {
|
||||||
/* TODO */
|
/* TODO */
|
||||||
|
@ -1098,13 +1098,13 @@ static void foreach_drawing_ex(GreasePencil &grease_pencil,
|
||||||
}
|
}
|
||||||
|
|
||||||
void GreasePencil::foreach_visible_drawing(
|
void GreasePencil::foreach_visible_drawing(
|
||||||
int frame, blender::FunctionRef<void(GreasePencilDrawing &)> function)
|
int frame, blender::FunctionRef<void(int, GreasePencilDrawing &)> function)
|
||||||
{
|
{
|
||||||
foreach_drawing_ex(*this, frame, VISIBLE, function);
|
foreach_drawing_ex(*this, frame, VISIBLE, function);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GreasePencil::foreach_editable_drawing(
|
void GreasePencil::foreach_editable_drawing(
|
||||||
int frame, blender::FunctionRef<void(GreasePencilDrawing &)> function)
|
int frame, blender::FunctionRef<void(int, GreasePencilDrawing &)> function)
|
||||||
{
|
{
|
||||||
foreach_drawing_ex(*this, frame, EDITABLE, function);
|
foreach_drawing_ex(*this, frame, EDITABLE, function);
|
||||||
}
|
}
|
||||||
|
|
|
@ -204,7 +204,8 @@ static void grease_pencil_geom_batch_ensure(GreasePencil &grease_pencil, int cfr
|
||||||
/* Get the visible drawings. */
|
/* Get the visible drawings. */
|
||||||
Vector<const GreasePencilDrawing *> drawings;
|
Vector<const GreasePencilDrawing *> drawings;
|
||||||
grease_pencil.foreach_visible_drawing(
|
grease_pencil.foreach_visible_drawing(
|
||||||
cfra, [&](GreasePencilDrawing &drawing) { drawings.append(&drawing); });
|
cfra,
|
||||||
|
[&](int /*drawing_index*/, GreasePencilDrawing &drawing) { drawings.append(&drawing); });
|
||||||
|
|
||||||
/* First, count how many vertices and triangles are needed for the whole object. Also record the
|
/* First, count how many vertices and triangles are needed for the whole object. Also record the
|
||||||
* offsets into the curves for the vertices and triangles. */
|
* offsets into the curves for the vertices and triangles. */
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
struct AssetMetaData;
|
||||||
struct ID;
|
struct ID;
|
||||||
struct Main;
|
struct Main;
|
||||||
struct bContext;
|
struct bContext;
|
||||||
|
@ -42,6 +43,18 @@ void ED_asset_generate_preview(const struct bContext *C, struct ID *id);
|
||||||
*/
|
*/
|
||||||
bool ED_asset_clear_id(struct ID *id);
|
bool ED_asset_clear_id(struct ID *id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy the asset metadata to the given destination ID.
|
||||||
|
*
|
||||||
|
* The copy is assigned to \a destination, any pre-existing asset metadata is
|
||||||
|
* freed before that. If \a destination was not yet marked as asset, it will be
|
||||||
|
* after this call.
|
||||||
|
*
|
||||||
|
* \return true when the copy succeeded, false otherwise. The only reason for
|
||||||
|
* failure is when \a destination is of a type that cannot be an asset.
|
||||||
|
*/
|
||||||
|
bool ED_asset_copy_to_id(const struct AssetMetaData *asset_data, struct ID *destination);
|
||||||
|
|
||||||
void ED_assets_pre_save(struct Main *bmain);
|
void ED_assets_pre_save(struct Main *bmain);
|
||||||
|
|
||||||
bool ED_asset_can_mark_single_from_context(const struct bContext *C);
|
bool ED_asset_can_mark_single_from_context(const struct bContext *C);
|
||||||
|
|
|
@ -27,6 +27,9 @@
|
||||||
#include "ED_asset_mark_clear.h"
|
#include "ED_asset_mark_clear.h"
|
||||||
#include "ED_asset_type.h"
|
#include "ED_asset_type.h"
|
||||||
|
|
||||||
|
#include "WM_api.h"
|
||||||
|
#include "WM_types.h"
|
||||||
|
|
||||||
bool ED_asset_mark_id(ID *id)
|
bool ED_asset_mark_id(ID *id)
|
||||||
{
|
{
|
||||||
if (id->asset_data) {
|
if (id->asset_data) {
|
||||||
|
@ -96,3 +99,16 @@ bool ED_asset_can_mark_single_from_context(const bContext *C)
|
||||||
}
|
}
|
||||||
return ED_asset_type_is_supported(id);
|
return ED_asset_type_is_supported(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ED_asset_copy_to_id(const struct AssetMetaData *asset_data, struct ID *destination)
|
||||||
|
{
|
||||||
|
if (!BKE_id_can_be_asset(destination)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (destination->asset_data) {
|
||||||
|
BKE_asset_metadata_free(&destination->asset_data);
|
||||||
|
}
|
||||||
|
destination->asset_data = BKE_asset_metadata_copy(asset_data);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
|
@ -48,10 +48,11 @@ static int select_all_exec(bContext *C, wmOperator *op)
|
||||||
Object *object = CTX_data_active_object(C);
|
Object *object = CTX_data_active_object(C);
|
||||||
GreasePencil &grease_pencil = *static_cast<GreasePencil *>(object->data);
|
GreasePencil &grease_pencil = *static_cast<GreasePencil *>(object->data);
|
||||||
|
|
||||||
grease_pencil.foreach_editable_drawing(scene->r.cfra, [action](GreasePencilDrawing &drawing) {
|
grease_pencil.foreach_editable_drawing(
|
||||||
// TODO: Support different selection domains.
|
scene->r.cfra, [action](int /*drawing_index*/, GreasePencilDrawing &drawing) {
|
||||||
blender::ed::curves::select_all(drawing.geometry.wrap(), ATTR_DOMAIN_POINT, action);
|
// TODO: Support different selection domains.
|
||||||
});
|
blender::ed::curves::select_all(drawing.geometry.wrap(), ATTR_DOMAIN_POINT, action);
|
||||||
|
});
|
||||||
|
|
||||||
/* Use #ID_RECALC_GEOMETRY instead of #ID_RECALC_SELECT because it is handled as a generic
|
/* Use #ID_RECALC_GEOMETRY instead of #ID_RECALC_SELECT because it is handled as a generic
|
||||||
* attribute for now. */
|
* attribute for now. */
|
||||||
|
|
|
@ -2408,7 +2408,10 @@ void uiTemplateImage(uiLayout *layout,
|
||||||
struct PointerRNA *userptr,
|
struct PointerRNA *userptr,
|
||||||
bool compact,
|
bool compact,
|
||||||
bool multiview);
|
bool multiview);
|
||||||
void uiTemplateImageSettings(uiLayout *layout, struct PointerRNA *imfptr, bool color_management);
|
void uiTemplateImageSettings(uiLayout *layout,
|
||||||
|
struct PointerRNA *imfptr,
|
||||||
|
bool color_management,
|
||||||
|
bool show_z_buffer);
|
||||||
void uiTemplateImageStereo3d(uiLayout *layout, struct PointerRNA *stereo3d_format_ptr);
|
void uiTemplateImageStereo3d(uiLayout *layout, struct PointerRNA *stereo3d_format_ptr);
|
||||||
void uiTemplateImageViews(uiLayout *layout, struct PointerRNA *imaptr);
|
void uiTemplateImageViews(uiLayout *layout, struct PointerRNA *imaptr);
|
||||||
void uiTemplateImageFormatViews(uiLayout *layout,
|
void uiTemplateImageFormatViews(uiLayout *layout,
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
#include "interface_intern.hh"
|
#include "interface_intern.hh"
|
||||||
|
|
||||||
#include "RNA_access.h"
|
#include "RNA_access.h"
|
||||||
|
#include "RNA_path.h"
|
||||||
#include "RNA_prototypes.h"
|
#include "RNA_prototypes.h"
|
||||||
|
|
||||||
#ifdef WITH_PYTHON
|
#ifdef WITH_PYTHON
|
||||||
|
@ -344,7 +345,10 @@ static bUserMenuItem *ui_but_user_menu_find(bContext *C, uiBut *but, bUserMenu *
|
||||||
}
|
}
|
||||||
if (but->rnaprop) {
|
if (but->rnaprop) {
|
||||||
char *member_id_data_path = WM_context_path_resolve_full(C, &but->rnapoin);
|
char *member_id_data_path = WM_context_path_resolve_full(C, &but->rnapoin);
|
||||||
const char *prop_id = RNA_property_identifier(but->rnaprop);
|
/* Ignore the actual array index [pass -1] since the index is handled separately. */
|
||||||
|
const char *prop_id = RNA_property_is_idprop(but->rnaprop) ?
|
||||||
|
RNA_path_property_py(&but->rnapoin, but->rnaprop, -1) :
|
||||||
|
RNA_property_identifier(but->rnaprop);
|
||||||
bUserMenuItem *umi = (bUserMenuItem *)ED_screen_user_menu_item_find_prop(
|
bUserMenuItem *umi = (bUserMenuItem *)ED_screen_user_menu_item_find_prop(
|
||||||
&um->items, member_id_data_path, prop_id, but->rnaindex);
|
&um->items, member_id_data_path, prop_id, but->rnaindex);
|
||||||
MEM_freeN(member_id_data_path);
|
MEM_freeN(member_id_data_path);
|
||||||
|
@ -419,7 +423,10 @@ static void ui_but_user_menu_add(bContext *C, uiBut *but, bUserMenu *um)
|
||||||
else if (but->rnaprop) {
|
else if (but->rnaprop) {
|
||||||
/* NOTE: 'member_id' may be a path. */
|
/* NOTE: 'member_id' may be a path. */
|
||||||
char *member_id_data_path = WM_context_path_resolve_full(C, &but->rnapoin);
|
char *member_id_data_path = WM_context_path_resolve_full(C, &but->rnapoin);
|
||||||
const char *prop_id = RNA_property_identifier(but->rnaprop);
|
/* Ignore the actual array index [pass -1] since the index is handled separately. */
|
||||||
|
const char *prop_id = RNA_property_is_idprop(but->rnaprop) ?
|
||||||
|
RNA_path_property_py(&but->rnapoin, but->rnaprop, -1) :
|
||||||
|
RNA_property_identifier(but->rnaprop);
|
||||||
/* NOTE: ignore 'drawstr', use property idname always. */
|
/* NOTE: ignore 'drawstr', use property idname always. */
|
||||||
ED_screen_user_menu_item_add_prop(&um->items, "", member_id_data_path, prop_id, but->rnaindex);
|
ED_screen_user_menu_item_add_prop(&um->items, "", member_id_data_path, prop_id, but->rnaindex);
|
||||||
MEM_freeN(member_id_data_path);
|
MEM_freeN(member_id_data_path);
|
||||||
|
|
|
@ -3180,6 +3180,12 @@ static int keyframe_jump_exec(bContext *C, wmOperator *op)
|
||||||
return OPERATOR_FINISHED;
|
return OPERATOR_FINISHED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool keyframe_jump_poll(bContext *C)
|
||||||
|
{
|
||||||
|
/* There is a keyframe jump operator specifically for the Graph Editor. */
|
||||||
|
return ED_operator_screenactive_norender(C) && CTX_wm_area(C)->spacetype != SPACE_GRAPH;
|
||||||
|
}
|
||||||
|
|
||||||
static void SCREEN_OT_keyframe_jump(wmOperatorType *ot)
|
static void SCREEN_OT_keyframe_jump(wmOperatorType *ot)
|
||||||
{
|
{
|
||||||
ot->name = "Jump to Keyframe";
|
ot->name = "Jump to Keyframe";
|
||||||
|
@ -3188,7 +3194,7 @@ static void SCREEN_OT_keyframe_jump(wmOperatorType *ot)
|
||||||
|
|
||||||
ot->exec = keyframe_jump_exec;
|
ot->exec = keyframe_jump_exec;
|
||||||
|
|
||||||
ot->poll = ED_operator_screenactive_norender;
|
ot->poll = keyframe_jump_poll;
|
||||||
ot->flag = OPTYPE_UNDO_GROUPED;
|
ot->flag = OPTYPE_UNDO_GROUPED;
|
||||||
ot->undo_group = "Frame Change";
|
ot->undo_group = "Frame Change";
|
||||||
|
|
||||||
|
|
|
@ -218,7 +218,7 @@ static void screenshot_draw(bContext *UNUSED(C), wmOperator *op)
|
||||||
/* image template */
|
/* image template */
|
||||||
PointerRNA ptr;
|
PointerRNA ptr;
|
||||||
RNA_pointer_create(NULL, &RNA_ImageFormatSettings, &scd->im_format, &ptr);
|
RNA_pointer_create(NULL, &RNA_ImageFormatSettings, &scd->im_format, &ptr);
|
||||||
uiTemplateImageSettings(layout, &ptr, false);
|
uiTemplateImageSettings(layout, &ptr, false, true);
|
||||||
|
|
||||||
/* main draw call */
|
/* main draw call */
|
||||||
uiDefAutoButsRNA(
|
uiDefAutoButsRNA(
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
#include "BKE_global.h"
|
#include "BKE_global.h"
|
||||||
#include "BKE_nla.h"
|
#include "BKE_nla.h"
|
||||||
#include "BKE_report.h"
|
#include "BKE_report.h"
|
||||||
|
#include "BKE_scene.h"
|
||||||
|
|
||||||
#include "DEG_depsgraph_build.h"
|
#include "DEG_depsgraph_build.h"
|
||||||
|
|
||||||
|
@ -2179,6 +2180,104 @@ void GRAPH_OT_frame_jump(wmOperatorType *ot)
|
||||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool find_closest_frame(const FCurve *fcu,
|
||||||
|
const float frame,
|
||||||
|
const bool next,
|
||||||
|
float *closest_frame)
|
||||||
|
{
|
||||||
|
bool replace;
|
||||||
|
int bezt_index = BKE_fcurve_bezt_binarysearch_index(fcu->bezt, frame, fcu->totvert, &replace);
|
||||||
|
|
||||||
|
BezTriple *bezt;
|
||||||
|
if (next) {
|
||||||
|
if (replace) {
|
||||||
|
bezt_index++;
|
||||||
|
}
|
||||||
|
if (bezt_index > fcu->totvert - 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bezt = &fcu->bezt[bezt_index];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (bezt_index - 1 < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bezt = &fcu->bezt[bezt_index - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
*closest_frame = bezt->vec[1][0];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int keyframe_jump_exec(bContext *C, wmOperator *op)
|
||||||
|
{
|
||||||
|
bAnimContext ac;
|
||||||
|
Scene *scene = CTX_data_scene(C);
|
||||||
|
|
||||||
|
bool next = RNA_boolean_get(op->ptr, "next");
|
||||||
|
|
||||||
|
/* Get editor data. */
|
||||||
|
if (ANIM_animdata_get_context(C, &ac) == 0) {
|
||||||
|
return OPERATOR_CANCELLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
ListBase anim_data = {NULL, NULL};
|
||||||
|
int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FCURVESONLY |
|
||||||
|
ANIMFILTER_NODUPLIS);
|
||||||
|
if (U.animation_flag & USER_ANIM_ONLY_SHOW_SELECTED_CURVE_KEYS) {
|
||||||
|
filter |= ANIMFILTER_SEL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
|
||||||
|
|
||||||
|
float closest_frame = next ? FLT_MAX : -FLT_MAX;
|
||||||
|
bool found = false;
|
||||||
|
|
||||||
|
const float current_frame = BKE_scene_frame_get(scene);
|
||||||
|
LISTBASE_FOREACH (bAnimListElem *, ale, &anim_data) {
|
||||||
|
const FCurve *fcu = ale->key_data;
|
||||||
|
if (!fcu->bezt) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
float closest_fcu_frame;
|
||||||
|
if (!find_closest_frame(fcu, current_frame, next, &closest_fcu_frame)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ((next && closest_fcu_frame < closest_frame) ||
|
||||||
|
(!next && closest_fcu_frame > closest_frame)) {
|
||||||
|
closest_frame = closest_fcu_frame;
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found) {
|
||||||
|
BKE_report(op->reports, RPT_INFO, "No more keyframes to jump to in this direction");
|
||||||
|
return OPERATOR_CANCELLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
BKE_scene_frame_set(scene, closest_frame);
|
||||||
|
|
||||||
|
/* Set notifier that things have changed. */
|
||||||
|
WM_event_add_notifier(C, NC_SCENE | ND_FRAME, ac.scene);
|
||||||
|
return OPERATOR_FINISHED;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GRAPH_OT_keyframe_jump(wmOperatorType *ot)
|
||||||
|
{
|
||||||
|
ot->name = "Jump to Keyframe";
|
||||||
|
ot->description = "Jump to previous/next keyframe";
|
||||||
|
ot->idname = "GRAPH_OT_keyframe_jump";
|
||||||
|
|
||||||
|
ot->exec = keyframe_jump_exec;
|
||||||
|
|
||||||
|
ot->poll = graphkeys_framejump_poll;
|
||||||
|
ot->flag = OPTYPE_UNDO_GROUPED;
|
||||||
|
ot->undo_group = "Frame Change";
|
||||||
|
|
||||||
|
/* properties */
|
||||||
|
RNA_def_boolean(ot->srna, "next", true, "Next Keyframe", "");
|
||||||
|
}
|
||||||
|
|
||||||
/* snap 2D cursor value to the average value of selected keyframe */
|
/* snap 2D cursor value to the average value of selected keyframe */
|
||||||
static int graphkeys_snap_cursor_value_exec(bContext *C, wmOperator *UNUSED(op))
|
static int graphkeys_snap_cursor_value_exec(bContext *C, wmOperator *UNUSED(op))
|
||||||
{
|
{
|
||||||
|
|
|
@ -131,6 +131,7 @@ void GRAPH_OT_extrapolation_type(struct wmOperatorType *ot);
|
||||||
void GRAPH_OT_easing_type(struct wmOperatorType *ot);
|
void GRAPH_OT_easing_type(struct wmOperatorType *ot);
|
||||||
|
|
||||||
void GRAPH_OT_frame_jump(struct wmOperatorType *ot);
|
void GRAPH_OT_frame_jump(struct wmOperatorType *ot);
|
||||||
|
void GRAPH_OT_keyframe_jump(struct wmOperatorType *ot);
|
||||||
void GRAPH_OT_snap_cursor_value(struct wmOperatorType *ot);
|
void GRAPH_OT_snap_cursor_value(struct wmOperatorType *ot);
|
||||||
void GRAPH_OT_snap(struct wmOperatorType *ot);
|
void GRAPH_OT_snap(struct wmOperatorType *ot);
|
||||||
void GRAPH_OT_equalize_handles(struct wmOperatorType *ot);
|
void GRAPH_OT_equalize_handles(struct wmOperatorType *ot);
|
||||||
|
|
|
@ -449,6 +449,7 @@ void graphedit_operatortypes(void)
|
||||||
WM_operatortype_append(GRAPH_OT_equalize_handles);
|
WM_operatortype_append(GRAPH_OT_equalize_handles);
|
||||||
WM_operatortype_append(GRAPH_OT_mirror);
|
WM_operatortype_append(GRAPH_OT_mirror);
|
||||||
WM_operatortype_append(GRAPH_OT_frame_jump);
|
WM_operatortype_append(GRAPH_OT_frame_jump);
|
||||||
|
WM_operatortype_append(GRAPH_OT_keyframe_jump);
|
||||||
WM_operatortype_append(GRAPH_OT_snap_cursor_value);
|
WM_operatortype_append(GRAPH_OT_snap_cursor_value);
|
||||||
WM_operatortype_append(GRAPH_OT_handle_type);
|
WM_operatortype_append(GRAPH_OT_handle_type);
|
||||||
WM_operatortype_append(GRAPH_OT_interpolation_type);
|
WM_operatortype_append(GRAPH_OT_interpolation_type);
|
||||||
|
|
|
@ -962,7 +962,10 @@ void uiTemplateImage(uiLayout *layout,
|
||||||
UI_block_funcN_set(block, NULL, NULL, NULL);
|
UI_block_funcN_set(block, NULL, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void uiTemplateImageSettings(uiLayout *layout, PointerRNA *imfptr, bool color_management)
|
void uiTemplateImageSettings(uiLayout *layout,
|
||||||
|
PointerRNA *imfptr,
|
||||||
|
bool color_management,
|
||||||
|
bool show_z_buffer)
|
||||||
{
|
{
|
||||||
ImageFormatData *imf = imfptr->data;
|
ImageFormatData *imf = imfptr->data;
|
||||||
ID *id = imfptr->owner_id;
|
ID *id = imfptr->owner_id;
|
||||||
|
@ -1014,7 +1017,7 @@ void uiTemplateImageSettings(uiLayout *layout, PointerRNA *imfptr, bool color_ma
|
||||||
uiItemR(col, imfptr, "exr_codec", 0, NULL, ICON_NONE);
|
uiItemR(col, imfptr, "exr_codec", 0, NULL, ICON_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (BKE_imtype_supports_zbuf(imf->imtype)) {
|
if (BKE_imtype_supports_zbuf(imf->imtype) && show_z_buffer) {
|
||||||
uiItemR(col, imfptr, "use_zbuffer", 0, NULL, ICON_NONE);
|
uiItemR(col, imfptr, "use_zbuffer", 0, NULL, ICON_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2007,7 +2007,7 @@ static void image_save_as_draw(bContext *UNUSED(C), wmOperator *op)
|
||||||
|
|
||||||
/* Image format settings. */
|
/* Image format settings. */
|
||||||
RNA_pointer_create(NULL, &RNA_ImageFormatSettings, &isd->opts.im_format, &imf_ptr);
|
RNA_pointer_create(NULL, &RNA_ImageFormatSettings, &isd->opts.im_format, &imf_ptr);
|
||||||
uiTemplateImageSettings(layout, &imf_ptr, save_as_render);
|
uiTemplateImageSettings(layout, &imf_ptr, save_as_render, true);
|
||||||
|
|
||||||
if (!save_as_render) {
|
if (!save_as_render) {
|
||||||
PointerRNA linear_settings_ptr = RNA_pointer_get(&imf_ptr, "linear_colorspace_settings");
|
PointerRNA linear_settings_ptr = RNA_pointer_get(&imf_ptr, "linear_colorspace_settings");
|
||||||
|
|
|
@ -53,6 +53,7 @@
|
||||||
#include "BKE_crazyspace.hh"
|
#include "BKE_crazyspace.hh"
|
||||||
#include "BKE_curve.h"
|
#include "BKE_curve.h"
|
||||||
#include "BKE_editmesh.h"
|
#include "BKE_editmesh.h"
|
||||||
|
#include "BKE_grease_pencil.hh"
|
||||||
#include "BKE_layer.h"
|
#include "BKE_layer.h"
|
||||||
#include "BKE_mball.h"
|
#include "BKE_mball.h"
|
||||||
#include "BKE_mesh.hh"
|
#include "BKE_mesh.hh"
|
||||||
|
@ -1171,6 +1172,43 @@ static bool do_lasso_select_meta(ViewContext *vc,
|
||||||
return data.is_changed;
|
return data.is_changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool do_lasso_select_grease_pencil(ViewContext *vc,
|
||||||
|
const int mcoords[][2],
|
||||||
|
const int mcoords_len,
|
||||||
|
const eSelectOp sel_op)
|
||||||
|
{
|
||||||
|
using namespace blender;
|
||||||
|
const Object *ob_eval = DEG_get_evaluated_object(vc->depsgraph,
|
||||||
|
const_cast<Object *>(vc->obedit));
|
||||||
|
GreasePencil &grease_pencil = *static_cast<GreasePencil *>(vc->obedit->data);
|
||||||
|
|
||||||
|
bool changed = false;
|
||||||
|
grease_pencil.foreach_editable_drawing(
|
||||||
|
vc->scene->r.cfra, [&](int drawing_index, GreasePencilDrawing &drawing) {
|
||||||
|
bke::crazyspace::GeometryDeformation deformation =
|
||||||
|
bke::crazyspace::get_evaluated_grease_pencil_drawing_deformation(
|
||||||
|
ob_eval, *vc->obedit, drawing_index);
|
||||||
|
|
||||||
|
/* TODO: Support different selection domains. */
|
||||||
|
changed = ed::curves::select_lasso(
|
||||||
|
*vc,
|
||||||
|
drawing.geometry.wrap(),
|
||||||
|
deformation.positions,
|
||||||
|
ATTR_DOMAIN_POINT,
|
||||||
|
Span<int2>(reinterpret_cast<const int2 *>(mcoords), mcoords_len),
|
||||||
|
sel_op);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (changed) {
|
||||||
|
/* Use #ID_RECALC_GEOMETRY instead of #ID_RECALC_SELECT because it is handled as a
|
||||||
|
* generic attribute for now. */
|
||||||
|
DEG_id_tag_update(static_cast<ID *>(vc->obedit->data), ID_RECALC_GEOMETRY);
|
||||||
|
WM_event_add_notifier(vc->C, NC_GEOM | ND_DATA, vc->obedit->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
struct LassoSelectUserData_ForMeshVert {
|
struct LassoSelectUserData_ForMeshVert {
|
||||||
LassoSelectUserData lasso_data;
|
LassoSelectUserData lasso_data;
|
||||||
blender::MutableSpan<bool> select_vert;
|
blender::MutableSpan<bool> select_vert;
|
||||||
|
@ -1388,6 +1426,10 @@ static bool view3d_lasso_select(bContext *C,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case OB_GREASE_PENCIL: {
|
||||||
|
changed = do_lasso_select_grease_pencil(vc, mcoords, mcoords_len, sel_op);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
BLI_assert_msg(0, "lasso select on incorrect object type");
|
BLI_assert_msg(0, "lasso select on incorrect object type");
|
||||||
break;
|
break;
|
||||||
|
@ -3097,6 +3139,112 @@ static bool ed_curves_select_pick(bContext &C, const int mval[2], const SelectPi
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ClosestGreasePencilDrawing {
|
||||||
|
GreasePencilDrawing *drawing = nullptr;
|
||||||
|
blender::ed::curves::FindClosestData elem = {};
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cursor selection for all Grease Pencil curves in edit mode.
|
||||||
|
*
|
||||||
|
* \returns true if the selection changed.
|
||||||
|
*/
|
||||||
|
static bool ed_grease_pencil_select_pick(bContext *C,
|
||||||
|
const int mval[2],
|
||||||
|
const SelectPick_Params ¶ms)
|
||||||
|
{
|
||||||
|
using namespace blender;
|
||||||
|
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
|
||||||
|
ViewContext vc;
|
||||||
|
/* Setup view context for argument to callbacks. */
|
||||||
|
ED_view3d_viewcontext_init(C, &vc, depsgraph);
|
||||||
|
|
||||||
|
/* Collect editable drawings. */
|
||||||
|
const Object *ob_eval = DEG_get_evaluated_object(vc.depsgraph, const_cast<Object *>(vc.obedit));
|
||||||
|
GreasePencil &grease_pencil = *static_cast<GreasePencil *>(vc.obedit->data);
|
||||||
|
Vector<GreasePencilDrawing *> drawings;
|
||||||
|
Vector<int> drawing_indices;
|
||||||
|
grease_pencil.foreach_editable_drawing(vc.scene->r.cfra,
|
||||||
|
[&](int drawing_index, GreasePencilDrawing &drawing) {
|
||||||
|
drawings.append(&drawing);
|
||||||
|
drawing_indices.append(drawing_index);
|
||||||
|
});
|
||||||
|
|
||||||
|
/* TODO: Support different selection domains. */
|
||||||
|
const eAttrDomain selection_domain = ATTR_DOMAIN_POINT;
|
||||||
|
|
||||||
|
const ClosestGreasePencilDrawing closest = threading::parallel_reduce(
|
||||||
|
drawings.index_range(),
|
||||||
|
1L,
|
||||||
|
ClosestGreasePencilDrawing(),
|
||||||
|
[&](const IndexRange range, const ClosestGreasePencilDrawing &init) {
|
||||||
|
ClosestGreasePencilDrawing new_closest = init;
|
||||||
|
for (const int i : range) {
|
||||||
|
/* Get deformation by modifiers. */
|
||||||
|
bke::crazyspace::GeometryDeformation deformation =
|
||||||
|
bke::crazyspace::get_evaluated_grease_pencil_drawing_deformation(
|
||||||
|
ob_eval, *vc.obedit, drawing_indices[i]);
|
||||||
|
std::optional<ed::curves::FindClosestData> new_closest_elem =
|
||||||
|
ed::curves::closest_elem_find_screen_space(vc,
|
||||||
|
*vc.obedit,
|
||||||
|
drawings[i]->geometry.wrap(),
|
||||||
|
deformation.positions,
|
||||||
|
selection_domain,
|
||||||
|
mval,
|
||||||
|
new_closest.elem);
|
||||||
|
if (new_closest_elem) {
|
||||||
|
new_closest.elem = *new_closest_elem;
|
||||||
|
new_closest.drawing = drawings[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new_closest;
|
||||||
|
},
|
||||||
|
[](const ClosestGreasePencilDrawing &a, const ClosestGreasePencilDrawing &b) {
|
||||||
|
return (a.elem.distance < b.elem.distance) ? a : b;
|
||||||
|
});
|
||||||
|
|
||||||
|
std::atomic<bool> deselected = false;
|
||||||
|
if (params.deselect_all || params.sel_op == SEL_OP_SET) {
|
||||||
|
threading::parallel_for(drawings.index_range(), 1L, [&](const IndexRange range) {
|
||||||
|
for (const int i : range) {
|
||||||
|
bke::CurvesGeometry &curves = drawings[i]->geometry.wrap();
|
||||||
|
if (ed::curves::has_anything_selected(curves)) {
|
||||||
|
bke::GSpanAttributeWriter selection = ed::curves::ensure_selection_attribute(
|
||||||
|
curves, selection_domain, CD_PROP_BOOL);
|
||||||
|
ed::curves::fill_selection_false(selection.span);
|
||||||
|
selection.finish();
|
||||||
|
|
||||||
|
deselected = true;
|
||||||
|
|
||||||
|
/* Use #ID_RECALC_GEOMETRY instead of #ID_RECALC_SELECT because it is handled as a
|
||||||
|
* generic attribute for now. */
|
||||||
|
DEG_id_tag_update(&grease_pencil.id, ID_RECALC_GEOMETRY);
|
||||||
|
WM_event_add_notifier(C, NC_GEOM | ND_DATA, &grease_pencil);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!closest.drawing) {
|
||||||
|
return deselected;
|
||||||
|
}
|
||||||
|
|
||||||
|
bke::GSpanAttributeWriter selection = ed::curves::ensure_selection_attribute(
|
||||||
|
closest.drawing->geometry.wrap(), selection_domain, CD_PROP_BOOL);
|
||||||
|
ed::curves::apply_selection_operation_at_index(
|
||||||
|
selection.span, closest.elem.index, params.sel_op);
|
||||||
|
selection.finish();
|
||||||
|
|
||||||
|
/* Use #ID_RECALC_GEOMETRY instead of #ID_RECALC_SELECT because it is handled as a
|
||||||
|
* generic attribute for now. */
|
||||||
|
if (!deselected) {
|
||||||
|
DEG_id_tag_update(&grease_pencil.id, ID_RECALC_GEOMETRY);
|
||||||
|
WM_event_add_notifier(C, NC_GEOM | ND_DATA, &grease_pencil);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static int view3d_select_exec(bContext *C, wmOperator *op)
|
static int view3d_select_exec(bContext *C, wmOperator *op)
|
||||||
{
|
{
|
||||||
Scene *scene = CTX_data_scene(C);
|
Scene *scene = CTX_data_scene(C);
|
||||||
|
@ -3193,6 +3341,9 @@ static int view3d_select_exec(bContext *C, wmOperator *op)
|
||||||
else if (obedit->type == OB_CURVES) {
|
else if (obedit->type == OB_CURVES) {
|
||||||
changed = ed_curves_select_pick(*C, mval, params);
|
changed = ed_curves_select_pick(*C, mval, params);
|
||||||
}
|
}
|
||||||
|
else if (obedit->type == OB_GREASE_PENCIL) {
|
||||||
|
changed = ed_grease_pencil_select_pick(C, mval, params);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (obact && obact->mode & OB_MODE_PARTICLE_EDIT) {
|
else if (obact && obact->mode & OB_MODE_PARTICLE_EDIT) {
|
||||||
changed = PE_mouse_particles(C, mval, ¶ms);
|
changed = PE_mouse_particles(C, mval, ¶ms);
|
||||||
|
@ -4028,6 +4179,32 @@ static bool do_pose_box_select(bContext *C,
|
||||||
return changed_multi;
|
return changed_multi;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool do_grease_pencil_box_select(ViewContext *vc, const rcti *rect, const eSelectOp sel_op)
|
||||||
|
{
|
||||||
|
using namespace blender;
|
||||||
|
Scene *scene = vc->scene;
|
||||||
|
const Object *ob_eval = DEG_get_evaluated_object(vc->depsgraph,
|
||||||
|
const_cast<Object *>(vc->obedit));
|
||||||
|
GreasePencil &grease_pencil = *static_cast<GreasePencil *>(vc->obedit->data);
|
||||||
|
|
||||||
|
bool changed = false;
|
||||||
|
grease_pencil.foreach_editable_drawing(
|
||||||
|
scene->r.cfra, [&](int drawing_index, GreasePencilDrawing &drawing) {
|
||||||
|
bke::crazyspace::GeometryDeformation deformation =
|
||||||
|
bke::crazyspace::get_evaluated_grease_pencil_drawing_deformation(
|
||||||
|
ob_eval, *vc->obedit, drawing_index);
|
||||||
|
changed |= ed::curves::select_box(
|
||||||
|
*vc, drawing.geometry.wrap(), deformation.positions, ATTR_DOMAIN_POINT, *rect, sel_op);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (changed) {
|
||||||
|
DEG_id_tag_update(&grease_pencil.id, ID_RECALC_GEOMETRY);
|
||||||
|
WM_event_add_notifier(vc->C, NC_GEOM | ND_DATA, &grease_pencil);
|
||||||
|
}
|
||||||
|
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
static int view3d_box_select_exec(bContext *C, wmOperator *op)
|
static int view3d_box_select_exec(bContext *C, wmOperator *op)
|
||||||
{
|
{
|
||||||
using namespace blender;
|
using namespace blender;
|
||||||
|
@ -4113,6 +4290,10 @@ static int view3d_box_select_exec(bContext *C, wmOperator *op)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case OB_GREASE_PENCIL: {
|
||||||
|
changed = do_grease_pencil_box_select(&vc, &rect, sel_op);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
BLI_assert_msg(0, "box select on incorrect object type");
|
BLI_assert_msg(0, "box select on incorrect object type");
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -428,13 +428,11 @@ static void test_texture_roundtrip__GPU_DATA_FLOAT__GPU_RGB9_E5()
|
||||||
GPU_TEST(texture_roundtrip__GPU_DATA_FLOAT__GPU_RGB9_E5);
|
GPU_TEST(texture_roundtrip__GPU_DATA_FLOAT__GPU_RGB9_E5);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if RUN_UNSUPPORTED
|
|
||||||
static void test_texture_roundtrip__GPU_DATA_FLOAT__GPU_DEPTH_COMPONENT32F()
|
static void test_texture_roundtrip__GPU_DATA_FLOAT__GPU_DEPTH_COMPONENT32F()
|
||||||
{
|
{
|
||||||
texture_create_upload_read_with_bias<GPU_DEPTH_COMPONENT32F, GPU_DATA_FLOAT>(0.0f);
|
texture_create_upload_read_with_bias<GPU_DEPTH_COMPONENT32F, GPU_DATA_FLOAT>(0.0f);
|
||||||
}
|
}
|
||||||
GPU_TEST(texture_roundtrip__GPU_DATA_FLOAT__GPU_DEPTH_COMPONENT32F);
|
GPU_TEST(texture_roundtrip__GPU_DATA_FLOAT__GPU_DEPTH_COMPONENT32F);
|
||||||
#endif
|
|
||||||
|
|
||||||
#if RUN_COMPONENT_UNIMPLEMENTED
|
#if RUN_COMPONENT_UNIMPLEMENTED
|
||||||
static void test_texture_roundtrip__GPU_DATA_FLOAT__GPU_DEPTH_COMPONENT24()
|
static void test_texture_roundtrip__GPU_DATA_FLOAT__GPU_DEPTH_COMPONENT24()
|
||||||
|
@ -622,7 +620,6 @@ static void test_texture_roundtrip__GPU_DATA_UINT__GPU_R32UI()
|
||||||
}
|
}
|
||||||
GPU_TEST(texture_roundtrip__GPU_DATA_UINT__GPU_R32UI);
|
GPU_TEST(texture_roundtrip__GPU_DATA_UINT__GPU_R32UI);
|
||||||
|
|
||||||
#if RUN_UNSUPPORTED
|
|
||||||
static void test_texture_roundtrip__GPU_DATA_UINT__GPU_DEPTH32F_STENCIL8()
|
static void test_texture_roundtrip__GPU_DATA_UINT__GPU_DEPTH32F_STENCIL8()
|
||||||
{
|
{
|
||||||
texture_create_upload_read<GPU_DEPTH32F_STENCIL8, GPU_DATA_UINT, uint32_t>();
|
texture_create_upload_read<GPU_DEPTH32F_STENCIL8, GPU_DATA_UINT, uint32_t>();
|
||||||
|
@ -634,7 +631,6 @@ static void test_texture_roundtrip__GPU_DATA_UINT__GPU_DEPTH24_STENCIL8()
|
||||||
texture_create_upload_read<GPU_DEPTH24_STENCIL8, GPU_DATA_UINT, uint32_t>();
|
texture_create_upload_read<GPU_DEPTH24_STENCIL8, GPU_DATA_UINT, uint32_t>();
|
||||||
}
|
}
|
||||||
GPU_TEST(texture_roundtrip__GPU_DATA_UINT__GPU_DEPTH24_STENCIL8);
|
GPU_TEST(texture_roundtrip__GPU_DATA_UINT__GPU_DEPTH24_STENCIL8);
|
||||||
#endif
|
|
||||||
|
|
||||||
#if RUN_UNSUPPORTED
|
#if RUN_UNSUPPORTED
|
||||||
static void test_texture_roundtrip__GPU_DATA_UINT__GPU_RGB8UI()
|
static void test_texture_roundtrip__GPU_DATA_UINT__GPU_RGB8UI()
|
||||||
|
@ -656,7 +652,6 @@ static void test_texture_roundtrip__GPU_DATA_UINT__GPU_RGB32UI()
|
||||||
GPU_TEST(texture_roundtrip__GPU_DATA_UINT__GPU_RGB32UI);
|
GPU_TEST(texture_roundtrip__GPU_DATA_UINT__GPU_RGB32UI);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if RUN_COMPONENT_UNIMPLEMENTED
|
|
||||||
static void test_texture_roundtrip__GPU_DATA_UINT__GPU_DEPTH_COMPONENT32F()
|
static void test_texture_roundtrip__GPU_DATA_UINT__GPU_DEPTH_COMPONENT32F()
|
||||||
{
|
{
|
||||||
texture_create_upload_read<GPU_DEPTH_COMPONENT32F, GPU_DATA_UINT, uint32_t>();
|
texture_create_upload_read<GPU_DEPTH_COMPONENT32F, GPU_DATA_UINT, uint32_t>();
|
||||||
|
@ -669,6 +664,7 @@ static void test_texture_roundtrip__GPU_DATA_UINT__GPU_DEPTH_COMPONENT24()
|
||||||
}
|
}
|
||||||
GPU_TEST(texture_roundtrip__GPU_DATA_UINT__GPU_DEPTH_COMPONENT24);
|
GPU_TEST(texture_roundtrip__GPU_DATA_UINT__GPU_DEPTH_COMPONENT24);
|
||||||
|
|
||||||
|
#if RUN_COMPONENT_UNIMPLEMENTED
|
||||||
static void test_texture_roundtrip__GPU_DATA_UINT__GPU_DEPTH_COMPONENT16()
|
static void test_texture_roundtrip__GPU_DATA_UINT__GPU_DEPTH_COMPONENT16()
|
||||||
{
|
{
|
||||||
texture_create_upload_read<GPU_DEPTH_COMPONENT16, GPU_DATA_UINT, uint32_t>();
|
texture_create_upload_read<GPU_DEPTH_COMPONENT16, GPU_DATA_UINT, uint32_t>();
|
||||||
|
@ -718,13 +714,11 @@ static void test_texture_roundtrip__GPU_DATA_UBYTE__GPU_R8()
|
||||||
}
|
}
|
||||||
GPU_TEST(texture_roundtrip__GPU_DATA_UBYTE__GPU_R8);
|
GPU_TEST(texture_roundtrip__GPU_DATA_UBYTE__GPU_R8);
|
||||||
|
|
||||||
#if RUN_SRGB_UNIMPLEMENTED
|
|
||||||
static void test_texture_roundtrip__GPU_DATA_UBYTE__GPU_SRGB8_A8()
|
static void test_texture_roundtrip__GPU_DATA_UBYTE__GPU_SRGB8_A8()
|
||||||
{
|
{
|
||||||
texture_create_upload_read<GPU_SRGB8_A8, GPU_DATA_UBYTE, uint8_t>();
|
texture_create_upload_read<GPU_SRGB8_A8, GPU_DATA_UBYTE, uint8_t>();
|
||||||
}
|
}
|
||||||
GPU_TEST(texture_roundtrip__GPU_DATA_UBYTE__GPU_SRGB8_A8);
|
GPU_TEST(texture_roundtrip__GPU_DATA_UBYTE__GPU_SRGB8_A8);
|
||||||
#endif
|
|
||||||
|
|
||||||
#if RUN_UNSUPPORTED
|
#if RUN_UNSUPPORTED
|
||||||
static void test_texture_roundtrip__GPU_DATA_UBYTE__GPU_RGB8I()
|
static void test_texture_roundtrip__GPU_DATA_UBYTE__GPU_RGB8I()
|
||||||
|
|
|
@ -73,6 +73,18 @@ void VKBackend::platform_init(const VKDevice &device)
|
||||||
driver_version.c_str());
|
driver_version.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VKBackend::detect_workarounds(VKDevice &device)
|
||||||
|
{
|
||||||
|
VKWorkarounds workarounds;
|
||||||
|
|
||||||
|
/* AMD GPUs don't support texture formats that use are aligned to 24 or 48 bits. */
|
||||||
|
if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_ANY)) {
|
||||||
|
workarounds.not_aligned_pixel_formats = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
device.workarounds_ = workarounds;
|
||||||
|
}
|
||||||
|
|
||||||
void VKBackend::platform_exit()
|
void VKBackend::platform_exit()
|
||||||
{
|
{
|
||||||
GPG.clear();
|
GPG.clear();
|
||||||
|
@ -174,7 +186,7 @@ shaderc::Compiler &VKBackend::get_shaderc_compiler()
|
||||||
return shaderc_compiler_;
|
return shaderc_compiler_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VKBackend::capabilities_init(const VKDevice &device)
|
void VKBackend::capabilities_init(VKDevice &device)
|
||||||
{
|
{
|
||||||
const VkPhysicalDeviceProperties &properties = device.physical_device_properties_get();
|
const VkPhysicalDeviceProperties &properties = device.physical_device_properties_get();
|
||||||
const VkPhysicalDeviceLimits &limits = properties.limits;
|
const VkPhysicalDeviceLimits &limits = properties.limits;
|
||||||
|
@ -205,6 +217,8 @@ void VKBackend::capabilities_init(const VKDevice &device)
|
||||||
GCaps.max_varying_floats = limits.maxVertexOutputComponents;
|
GCaps.max_varying_floats = limits.maxVertexOutputComponents;
|
||||||
GCaps.max_shader_storage_buffer_bindings = limits.maxPerStageDescriptorStorageBuffers;
|
GCaps.max_shader_storage_buffer_bindings = limits.maxPerStageDescriptorStorageBuffers;
|
||||||
GCaps.max_compute_shader_storage_blocks = limits.maxPerStageDescriptorStorageBuffers;
|
GCaps.max_compute_shader_storage_blocks = limits.maxPerStageDescriptorStorageBuffers;
|
||||||
|
|
||||||
|
detect_workarounds(device);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace blender::gpu
|
} // namespace blender::gpu
|
||||||
|
|
|
@ -88,9 +88,10 @@ class VKBackend : public GPUBackend {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void platform_init(const VKDevice &device);
|
static void platform_init(const VKDevice &device);
|
||||||
static void capabilities_init(const VKDevice &device);
|
static void capabilities_init(VKDevice &device);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static void detect_workarounds(VKDevice &device);
|
||||||
static void platform_init();
|
static void platform_init();
|
||||||
static void platform_exit();
|
static void platform_exit();
|
||||||
|
|
||||||
|
|
|
@ -201,15 +201,28 @@ void VKCommandBuffer::copy(VKTexture &dst_texture,
|
||||||
}
|
}
|
||||||
|
|
||||||
void VKCommandBuffer::blit(VKTexture &dst_texture,
|
void VKCommandBuffer::blit(VKTexture &dst_texture,
|
||||||
VKTexture &src_buffer,
|
VKTexture &src_texture,
|
||||||
|
Span<VkImageBlit> regions)
|
||||||
|
{
|
||||||
|
blit(dst_texture,
|
||||||
|
dst_texture.current_layout_get(),
|
||||||
|
src_texture,
|
||||||
|
src_texture.current_layout_get(),
|
||||||
|
regions);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VKCommandBuffer::blit(VKTexture &dst_texture,
|
||||||
|
VkImageLayout dst_layout,
|
||||||
|
VKTexture &src_texture,
|
||||||
|
VkImageLayout src_layout,
|
||||||
Span<VkImageBlit> regions)
|
Span<VkImageBlit> regions)
|
||||||
{
|
{
|
||||||
ensure_no_active_framebuffer();
|
ensure_no_active_framebuffer();
|
||||||
vkCmdBlitImage(vk_command_buffer_,
|
vkCmdBlitImage(vk_command_buffer_,
|
||||||
src_buffer.vk_image_handle(),
|
src_texture.vk_image_handle(),
|
||||||
src_buffer.current_layout_get(),
|
src_layout,
|
||||||
dst_texture.vk_image_handle(),
|
dst_texture.vk_image_handle(),
|
||||||
dst_texture.current_layout_get(),
|
dst_layout,
|
||||||
regions.size(),
|
regions.size(),
|
||||||
regions.data(),
|
regions.data(),
|
||||||
VK_FILTER_NEAREST);
|
VK_FILTER_NEAREST);
|
||||||
|
|
|
@ -165,6 +165,11 @@ class VKCommandBuffer : NonCopyable, NonMovable {
|
||||||
void copy(VKTexture &dst_texture, VKBuffer &src_buffer, Span<VkBufferImageCopy> regions);
|
void copy(VKTexture &dst_texture, VKBuffer &src_buffer, Span<VkBufferImageCopy> regions);
|
||||||
void copy(VKTexture &dst_texture, VKTexture &src_texture, Span<VkImageCopy> regions);
|
void copy(VKTexture &dst_texture, VKTexture &src_texture, Span<VkImageCopy> regions);
|
||||||
void blit(VKTexture &dst_texture, VKTexture &src_texture, Span<VkImageBlit> regions);
|
void blit(VKTexture &dst_texture, VKTexture &src_texture, Span<VkImageBlit> regions);
|
||||||
|
void blit(VKTexture &dst_texture,
|
||||||
|
VkImageLayout dst_layout,
|
||||||
|
VKTexture &src_texture,
|
||||||
|
VkImageLayout src_layout,
|
||||||
|
Span<VkImageBlit> regions);
|
||||||
void pipeline_barrier(VkPipelineStageFlags source_stages,
|
void pipeline_barrier(VkPipelineStageFlags source_stages,
|
||||||
VkPipelineStageFlags destination_stages);
|
VkPipelineStageFlags destination_stages);
|
||||||
void pipeline_barrier(Span<VkImageMemoryBarrier> image_memory_barriers);
|
void pipeline_barrier(Span<VkImageMemoryBarrier> image_memory_barriers);
|
||||||
|
|
|
@ -32,6 +32,9 @@ enum class ConversionType {
|
||||||
FLOAT_TO_SNORM16,
|
FLOAT_TO_SNORM16,
|
||||||
SNORM16_TO_FLOAT,
|
SNORM16_TO_FLOAT,
|
||||||
|
|
||||||
|
FLOAT_TO_UNORM32,
|
||||||
|
UNORM32_TO_FLOAT,
|
||||||
|
|
||||||
UI32_TO_UI16,
|
UI32_TO_UI16,
|
||||||
UI16_TO_UI32,
|
UI16_TO_UI32,
|
||||||
|
|
||||||
|
@ -239,6 +242,7 @@ static ConversionType type_of_conversion_uint(eGPUTextureFormat device_format)
|
||||||
case GPU_RGBA32UI:
|
case GPU_RGBA32UI:
|
||||||
case GPU_RG32UI:
|
case GPU_RG32UI:
|
||||||
case GPU_R32UI:
|
case GPU_R32UI:
|
||||||
|
case GPU_DEPTH_COMPONENT24:
|
||||||
return ConversionType::PASS_THROUGH;
|
return ConversionType::PASS_THROUGH;
|
||||||
|
|
||||||
case GPU_RGBA16UI:
|
case GPU_RGBA16UI:
|
||||||
|
@ -252,6 +256,10 @@ static ConversionType type_of_conversion_uint(eGPUTextureFormat device_format)
|
||||||
case GPU_R8UI:
|
case GPU_R8UI:
|
||||||
return ConversionType::UI32_TO_UI8;
|
return ConversionType::UI32_TO_UI8;
|
||||||
|
|
||||||
|
case GPU_DEPTH_COMPONENT32F:
|
||||||
|
case GPU_DEPTH32F_STENCIL8:
|
||||||
|
return ConversionType::UNORM32_TO_FLOAT;
|
||||||
|
|
||||||
case GPU_RGBA8I:
|
case GPU_RGBA8I:
|
||||||
case GPU_RGBA8:
|
case GPU_RGBA8:
|
||||||
case GPU_RGBA16I:
|
case GPU_RGBA16I:
|
||||||
|
@ -276,7 +284,6 @@ static ConversionType type_of_conversion_uint(eGPUTextureFormat device_format)
|
||||||
case GPU_RGB10_A2:
|
case GPU_RGB10_A2:
|
||||||
case GPU_RGB10_A2UI:
|
case GPU_RGB10_A2UI:
|
||||||
case GPU_R11F_G11F_B10F:
|
case GPU_R11F_G11F_B10F:
|
||||||
case GPU_DEPTH32F_STENCIL8:
|
|
||||||
case GPU_DEPTH24_STENCIL8:
|
case GPU_DEPTH24_STENCIL8:
|
||||||
case GPU_SRGB8_A8:
|
case GPU_SRGB8_A8:
|
||||||
case GPU_RGBA8_SNORM:
|
case GPU_RGBA8_SNORM:
|
||||||
|
@ -304,8 +311,6 @@ static ConversionType type_of_conversion_uint(eGPUTextureFormat device_format)
|
||||||
case GPU_RGBA8_DXT5:
|
case GPU_RGBA8_DXT5:
|
||||||
case GPU_SRGB8:
|
case GPU_SRGB8:
|
||||||
case GPU_RGB9_E5:
|
case GPU_RGB9_E5:
|
||||||
case GPU_DEPTH_COMPONENT32F:
|
|
||||||
case GPU_DEPTH_COMPONENT24:
|
|
||||||
case GPU_DEPTH_COMPONENT16:
|
case GPU_DEPTH_COMPONENT16:
|
||||||
return ConversionType::UNSUPPORTED;
|
return ConversionType::UNSUPPORTED;
|
||||||
}
|
}
|
||||||
|
@ -396,6 +401,7 @@ static ConversionType type_of_conversion_ubyte(eGPUTextureFormat device_format)
|
||||||
case GPU_RG8:
|
case GPU_RG8:
|
||||||
case GPU_R8UI:
|
case GPU_R8UI:
|
||||||
case GPU_R8:
|
case GPU_R8:
|
||||||
|
case GPU_SRGB8_A8:
|
||||||
return ConversionType::PASS_THROUGH;
|
return ConversionType::PASS_THROUGH;
|
||||||
|
|
||||||
case GPU_RGBA8I:
|
case GPU_RGBA8I:
|
||||||
|
@ -427,7 +433,6 @@ static ConversionType type_of_conversion_ubyte(eGPUTextureFormat device_format)
|
||||||
case GPU_R11F_G11F_B10F:
|
case GPU_R11F_G11F_B10F:
|
||||||
case GPU_DEPTH32F_STENCIL8:
|
case GPU_DEPTH32F_STENCIL8:
|
||||||
case GPU_DEPTH24_STENCIL8:
|
case GPU_DEPTH24_STENCIL8:
|
||||||
case GPU_SRGB8_A8:
|
|
||||||
case GPU_RGBA8_SNORM:
|
case GPU_RGBA8_SNORM:
|
||||||
case GPU_RGBA16_SNORM:
|
case GPU_RGBA16_SNORM:
|
||||||
case GPU_RGB8UI:
|
case GPU_RGB8UI:
|
||||||
|
@ -523,6 +528,7 @@ static ConversionType reversed(ConversionType type)
|
||||||
CASE_PAIR(FLOAT, SNORM8)
|
CASE_PAIR(FLOAT, SNORM8)
|
||||||
CASE_PAIR(FLOAT, UNORM16)
|
CASE_PAIR(FLOAT, UNORM16)
|
||||||
CASE_PAIR(FLOAT, SNORM16)
|
CASE_PAIR(FLOAT, SNORM16)
|
||||||
|
CASE_PAIR(FLOAT, UNORM32)
|
||||||
CASE_PAIR(UI32, UI16)
|
CASE_PAIR(UI32, UI16)
|
||||||
CASE_PAIR(I32, I16)
|
CASE_PAIR(I32, I16)
|
||||||
CASE_PAIR(UI32, UI8)
|
CASE_PAIR(UI32, UI8)
|
||||||
|
@ -632,6 +638,7 @@ template<typename InnerType> struct SignedNormalized {
|
||||||
|
|
||||||
template<typename InnerType> struct UnsignedNormalized {
|
template<typename InnerType> struct UnsignedNormalized {
|
||||||
static_assert(std::is_same<InnerType, uint8_t>() || std::is_same<InnerType, uint16_t>() ||
|
static_assert(std::is_same<InnerType, uint8_t>() || std::is_same<InnerType, uint16_t>() ||
|
||||||
|
std::is_same<InnerType, uint32_t>() ||
|
||||||
std::is_same<InnerType, DepthComponent24>());
|
std::is_same<InnerType, DepthComponent24>());
|
||||||
InnerType value;
|
InnerType value;
|
||||||
|
|
||||||
|
@ -645,15 +652,24 @@ template<typename InnerType> struct UnsignedNormalized {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr int32_t scalar()
|
static constexpr uint32_t scalar()
|
||||||
{
|
{
|
||||||
|
if constexpr (std::is_same<InnerType, DepthComponent24>()) {
|
||||||
return (1 << (used_byte_size() * 8)) - 1;
|
return (1 << (used_byte_size() * 8)) - 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return std::numeric_limits<InnerType>::max();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr int32_t max()
|
static constexpr uint32_t max()
|
||||||
{
|
{
|
||||||
return ((1 << (used_byte_size() * 8)) - 1);
|
if constexpr (std::is_same<InnerType, DepthComponent24>()) {
|
||||||
|
return (1 << (used_byte_size() * 8)) - 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return std::numeric_limits<InnerType>::max();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -674,15 +690,15 @@ template<typename StorageType> void convert(F32 &dst, const SignedNormalized<Sto
|
||||||
|
|
||||||
template<typename StorageType> void convert(UnsignedNormalized<StorageType> &dst, const F32 &src)
|
template<typename StorageType> void convert(UnsignedNormalized<StorageType> &dst, const F32 &src)
|
||||||
{
|
{
|
||||||
static constexpr int32_t scalar = UnsignedNormalized<StorageType>::scalar();
|
static constexpr uint32_t scalar = UnsignedNormalized<StorageType>::scalar();
|
||||||
static constexpr int32_t max = scalar;
|
static constexpr uint32_t max = scalar;
|
||||||
dst.value = (clamp_i((src.value * scalar), 0, max));
|
dst.value = (clamp_f((src.value * scalar), 0, max));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename StorageType> void convert(F32 &dst, const UnsignedNormalized<StorageType> &src)
|
template<typename StorageType> void convert(F32 &dst, const UnsignedNormalized<StorageType> &src)
|
||||||
{
|
{
|
||||||
static constexpr int32_t scalar = UnsignedNormalized<StorageType>::scalar();
|
static constexpr uint32_t scalar = UnsignedNormalized<StorageType>::scalar();
|
||||||
dst.value = float(int32_t(src.value)) / scalar;
|
dst.value = float(uint32_t(src.value)) / scalar;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy the contents of src to dst with out performing any actual conversion. */
|
/* Copy the contents of src to dst with out performing any actual conversion. */
|
||||||
|
@ -860,6 +876,15 @@ static void convert_buffer(void *dst_memory,
|
||||||
dst_memory, src_memory, buffer_size, device_format);
|
dst_memory, src_memory, buffer_size, device_format);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ConversionType::FLOAT_TO_UNORM32:
|
||||||
|
convert_per_component<UnsignedNormalized<uint32_t>, F32>(
|
||||||
|
dst_memory, src_memory, buffer_size, device_format);
|
||||||
|
break;
|
||||||
|
case ConversionType::UNORM32_TO_FLOAT:
|
||||||
|
convert_per_component<F32, UnsignedNormalized<uint32_t>>(
|
||||||
|
dst_memory, src_memory, buffer_size, device_format);
|
||||||
|
break;
|
||||||
|
|
||||||
case ConversionType::FLOAT_TO_HALF:
|
case ConversionType::FLOAT_TO_HALF:
|
||||||
convert_per_component<F16, F32>(dst_memory, src_memory, buffer_size, device_format);
|
convert_per_component<F16, F32>(dst_memory, src_memory, buffer_size, device_format);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -15,6 +15,17 @@
|
||||||
#include "vk_descriptor_pools.hh"
|
#include "vk_descriptor_pools.hh"
|
||||||
|
|
||||||
namespace blender::gpu {
|
namespace blender::gpu {
|
||||||
|
class VKBackend;
|
||||||
|
|
||||||
|
struct VKWorkarounds {
|
||||||
|
/**
|
||||||
|
* Some devices don't support pixel formats that are aligned to 24 and 48 bits.
|
||||||
|
* In this case we need to use a different texture format.
|
||||||
|
*
|
||||||
|
* If set to true we should work around this issue by using a different texture format.
|
||||||
|
*/
|
||||||
|
bool not_aligned_pixel_formats = false;
|
||||||
|
};
|
||||||
|
|
||||||
class VKDevice : public NonCopyable {
|
class VKDevice : public NonCopyable {
|
||||||
private:
|
private:
|
||||||
|
@ -35,6 +46,9 @@ class VKDevice : public NonCopyable {
|
||||||
/** Functions of vk_ext_debugutils for this device/instance. */
|
/** Functions of vk_ext_debugutils for this device/instance. */
|
||||||
debug::VKDebuggingTools debugging_tools_;
|
debug::VKDebuggingTools debugging_tools_;
|
||||||
|
|
||||||
|
/* Workarounds */
|
||||||
|
VKWorkarounds workarounds_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
VkPhysicalDevice physical_device_get() const
|
VkPhysicalDevice physical_device_get() const
|
||||||
{
|
{
|
||||||
|
@ -95,11 +109,19 @@ class VKDevice : public NonCopyable {
|
||||||
std::string vendor_name() const;
|
std::string vendor_name() const;
|
||||||
std::string driver_version() const;
|
std::string driver_version() const;
|
||||||
|
|
||||||
|
const VKWorkarounds &workarounds_get() const
|
||||||
|
{
|
||||||
|
return workarounds_;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void init_physical_device_properties();
|
void init_physical_device_properties();
|
||||||
void init_debug_callbacks();
|
void init_debug_callbacks();
|
||||||
void init_memory_allocator();
|
void init_memory_allocator();
|
||||||
void init_descriptor_pools();
|
void init_descriptor_pools();
|
||||||
|
|
||||||
|
/* During initialization the backend requires access to update the workarounds. */
|
||||||
|
friend VKBackend;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace blender::gpu
|
} // namespace blender::gpu
|
||||||
|
|
|
@ -914,6 +914,7 @@ bool VKShader::finalize_descriptor_set_layouts(VkDevice vk_device,
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
debug::object_label(layout_, name_get());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,7 +127,7 @@ void VKStateManager::image_unbind(Texture *tex)
|
||||||
|
|
||||||
void VKStateManager::image_unbind_all()
|
void VKStateManager::image_unbind_all()
|
||||||
{
|
{
|
||||||
for (TextureBinding &binding : texture_bindings_) {
|
for (ImageBinding &binding : image_bindings_) {
|
||||||
binding.texture = nullptr;
|
binding.texture = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,56 @@ void VKTexture::init(VkImage vk_image, VkImageLayout layout)
|
||||||
|
|
||||||
void VKTexture::generate_mipmap()
|
void VKTexture::generate_mipmap()
|
||||||
{
|
{
|
||||||
NOT_YET_IMPLEMENTED
|
if (mipmaps_ <= 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ensure_allocated();
|
||||||
|
|
||||||
|
VKContext &context = *VKContext::get();
|
||||||
|
VKCommandBuffer &command_buffer = context.command_buffer_get();
|
||||||
|
layout_ensure(context, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||||
|
|
||||||
|
for (int src_mipmap : IndexRange(mipmaps_ - 1)) {
|
||||||
|
int dst_mipmap = src_mipmap + 1;
|
||||||
|
int3 src_size(1);
|
||||||
|
int3 dst_size(1);
|
||||||
|
mip_size_get(src_mipmap, src_size);
|
||||||
|
mip_size_get(dst_mipmap, dst_size);
|
||||||
|
|
||||||
|
layout_ensure(context,
|
||||||
|
IndexRange(src_mipmap, 1),
|
||||||
|
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||||
|
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
|
||||||
|
|
||||||
|
VkImageBlit image_blit = {};
|
||||||
|
image_blit.srcOffsets[0] = {0, 0, 0};
|
||||||
|
image_blit.srcOffsets[1] = {src_size.x, src_size.y, src_size.z};
|
||||||
|
image_blit.srcSubresource.aspectMask = to_vk_image_aspect_flag_bits(format_);
|
||||||
|
image_blit.srcSubresource.mipLevel = src_mipmap;
|
||||||
|
image_blit.srcSubresource.baseArrayLayer = 0;
|
||||||
|
image_blit.srcSubresource.layerCount = layer_count();
|
||||||
|
|
||||||
|
image_blit.dstOffsets[0] = {0, 0, 0};
|
||||||
|
image_blit.dstOffsets[1] = {dst_size.x, dst_size.y, dst_size.z};
|
||||||
|
image_blit.dstSubresource.aspectMask = to_vk_image_aspect_flag_bits(format_);
|
||||||
|
image_blit.dstSubresource.mipLevel = dst_mipmap;
|
||||||
|
image_blit.dstSubresource.baseArrayLayer = 0;
|
||||||
|
image_blit.dstSubresource.layerCount = layer_count();
|
||||||
|
|
||||||
|
command_buffer.blit(*this,
|
||||||
|
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||||
|
*this,
|
||||||
|
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||||
|
Span<VkImageBlit>(&image_blit, 1));
|
||||||
|
}
|
||||||
|
/* Ensure that all mipmap levels are in `VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL`. All miplevels are
|
||||||
|
* except the last one. */
|
||||||
|
layout_ensure(context,
|
||||||
|
IndexRange(mipmaps_ - 1, 1),
|
||||||
|
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||||
|
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
|
||||||
|
current_layout_set(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VKTexture::copy_to(Texture *tex)
|
void VKTexture::copy_to(Texture *tex)
|
||||||
|
@ -151,10 +200,6 @@ void *VKTexture::read(int mip, eGPUDataFormat format)
|
||||||
void VKTexture::update_sub(
|
void VKTexture::update_sub(
|
||||||
int mip, int offset[3], int extent_[3], eGPUDataFormat format, const void *data)
|
int mip, int offset[3], int extent_[3], eGPUDataFormat format, const void *data)
|
||||||
{
|
{
|
||||||
if (mip != 0) {
|
|
||||||
NOT_YET_IMPLEMENTED;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!is_allocated()) {
|
if (!is_allocated()) {
|
||||||
allocate();
|
allocate();
|
||||||
}
|
}
|
||||||
|
@ -220,6 +265,15 @@ bool VKTexture::init_internal()
|
||||||
* at this moment, so we cannot initialize here. The initialization is postponed until the
|
* at this moment, so we cannot initialize here. The initialization is postponed until the
|
||||||
* allocation of the texture on the device. */
|
* allocation of the texture on the device. */
|
||||||
|
|
||||||
|
const VKDevice &device = VKBackend::get().device_get();
|
||||||
|
const VKWorkarounds &workarounds = device.workarounds_get();
|
||||||
|
if (format_ == GPU_DEPTH_COMPONENT24 && workarounds.not_aligned_pixel_formats) {
|
||||||
|
format_ = GPU_DEPTH_COMPONENT32F;
|
||||||
|
}
|
||||||
|
if (format_ == GPU_DEPTH24_STENCIL8 && workarounds.not_aligned_pixel_formats) {
|
||||||
|
format_ = GPU_DEPTH32F_STENCIL8;
|
||||||
|
}
|
||||||
|
|
||||||
/* TODO: return false when texture format isn't supported. */
|
/* TODO: return false when texture format isn't supported. */
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -330,7 +384,7 @@ bool VKTexture::allocate()
|
||||||
image_info.extent.width = extent[0];
|
image_info.extent.width = extent[0];
|
||||||
image_info.extent.height = extent[1];
|
image_info.extent.height = extent[1];
|
||||||
image_info.extent.depth = extent[2];
|
image_info.extent.depth = extent[2];
|
||||||
image_info.mipLevels = 1;
|
image_info.mipLevels = max_ii(mipmaps_, 1);
|
||||||
image_info.arrayLayers = 1;
|
image_info.arrayLayers = 1;
|
||||||
image_info.format = to_vk_format(format_);
|
image_info.format = to_vk_format(format_);
|
||||||
/* Some platforms (NVIDIA) requires that attached textures are always tiled optimal.
|
/* Some platforms (NVIDIA) requires that attached textures are always tiled optimal.
|
||||||
|
@ -449,16 +503,27 @@ void VKTexture::layout_ensure(VKContext &context, const VkImageLayout requested_
|
||||||
if (current_layout == requested_layout) {
|
if (current_layout == requested_layout) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
layout_ensure(context, IndexRange(0, VK_REMAINING_MIP_LEVELS), current_layout, requested_layout);
|
||||||
|
current_layout_set(requested_layout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VKTexture::layout_ensure(VKContext &context,
|
||||||
|
const IndexRange mipmap_range,
|
||||||
|
const VkImageLayout current_layout,
|
||||||
|
const VkImageLayout requested_layout)
|
||||||
|
{
|
||||||
|
BLI_assert(is_allocated());
|
||||||
VkImageMemoryBarrier barrier{};
|
VkImageMemoryBarrier barrier{};
|
||||||
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
||||||
barrier.oldLayout = current_layout;
|
barrier.oldLayout = current_layout;
|
||||||
barrier.newLayout = requested_layout;
|
barrier.newLayout = requested_layout;
|
||||||
barrier.image = vk_image_;
|
barrier.image = vk_image_;
|
||||||
barrier.subresourceRange.aspectMask = to_vk_image_aspect_flag_bits(format_);
|
barrier.subresourceRange.aspectMask = to_vk_image_aspect_flag_bits(format_);
|
||||||
barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
|
barrier.subresourceRange.baseMipLevel = uint32_t(mipmap_range.start());
|
||||||
|
barrier.subresourceRange.levelCount = uint32_t(mipmap_range.size());
|
||||||
|
barrier.subresourceRange.baseArrayLayer = 0;
|
||||||
barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
|
barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
|
||||||
context.command_buffer_get().pipeline_barrier(Span<VkImageMemoryBarrier>(&barrier, 1));
|
context.command_buffer_get().pipeline_barrier(Span<VkImageMemoryBarrier>(&barrier, 1));
|
||||||
current_layout_set(requested_layout);
|
|
||||||
}
|
}
|
||||||
/** \} */
|
/** \} */
|
||||||
|
|
||||||
|
|
|
@ -111,6 +111,17 @@ class VKTexture : public Texture {
|
||||||
*/
|
*/
|
||||||
void layout_ensure(VKContext &context, VkImageLayout requested_layout);
|
void layout_ensure(VKContext &context, VkImageLayout requested_layout);
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* Internal function to ensure the layout of a single mipmap level. Note that the caller is
|
||||||
|
* responsible to update the current_layout of the image at the end of the operation and make
|
||||||
|
* sure that all mipmap levels are in that given layout.
|
||||||
|
*/
|
||||||
|
void layout_ensure(VKContext &context,
|
||||||
|
IndexRange mipmap_range,
|
||||||
|
VkImageLayout current_layout,
|
||||||
|
VkImageLayout requested_layout);
|
||||||
|
|
||||||
/** \} */
|
/** \} */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,11 @@
|
||||||
|
|
||||||
namespace blender::gpu {
|
namespace blender::gpu {
|
||||||
|
|
||||||
|
VKUniformBuffer::~VKUniformBuffer()
|
||||||
|
{
|
||||||
|
unbind();
|
||||||
|
}
|
||||||
|
|
||||||
void VKUniformBuffer::update(const void *data)
|
void VKUniformBuffer::update(const void *data)
|
||||||
{
|
{
|
||||||
if (!buffer_.is_allocated()) {
|
if (!buffer_.is_allocated()) {
|
||||||
|
@ -68,8 +73,10 @@ void VKUniformBuffer::bind_as_ssbo(int slot)
|
||||||
|
|
||||||
void VKUniformBuffer::unbind()
|
void VKUniformBuffer::unbind()
|
||||||
{
|
{
|
||||||
VKContext &context = *VKContext::get();
|
VKContext *context = VKContext::get();
|
||||||
context.state_manager_get().uniform_buffer_unbind(this);
|
if (context) {
|
||||||
|
context->state_manager_get().uniform_buffer_unbind(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace blender::gpu
|
} // namespace blender::gpu
|
||||||
|
|
|
@ -21,6 +21,7 @@ class VKUniformBuffer : public UniformBuf, NonCopyable {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
VKUniformBuffer(int size, const char *name) : UniformBuf(size, name) {}
|
VKUniformBuffer(int size, const char *name) : UniformBuf(size, name) {}
|
||||||
|
~VKUniformBuffer();
|
||||||
|
|
||||||
void update(const void *data) override;
|
void update(const void *data) override;
|
||||||
void clear_to_zero() override;
|
void clear_to_zero() override;
|
||||||
|
|
|
@ -119,9 +119,9 @@ void VKVertexBuffer::resize_data()
|
||||||
|
|
||||||
void VKVertexBuffer::release_data()
|
void VKVertexBuffer::release_data()
|
||||||
{
|
{
|
||||||
if (should_unbind_) {
|
VKContext *context = VKContext::get();
|
||||||
VKContext &context = *VKContext::get();
|
if (should_unbind_ && context) {
|
||||||
context.state_manager_get().texel_buffer_unbind(this);
|
context->state_manager_get().texel_buffer_unbind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vk_buffer_view_ != VK_NULL_HANDLE) {
|
if (vk_buffer_view_ != VK_NULL_HANDLE) {
|
||||||
|
|
|
@ -453,9 +453,9 @@ typedef struct GreasePencil {
|
||||||
void remove_drawing(int index);
|
void remove_drawing(int index);
|
||||||
|
|
||||||
void foreach_visible_drawing(int frame,
|
void foreach_visible_drawing(int frame,
|
||||||
blender::FunctionRef<void(GreasePencilDrawing &)> function);
|
blender::FunctionRef<void(int, GreasePencilDrawing &)> function);
|
||||||
void foreach_editable_drawing(int frame,
|
void foreach_editable_drawing(int frame,
|
||||||
blender::FunctionRef<void(GreasePencilDrawing &)> function);
|
blender::FunctionRef<void(int, GreasePencilDrawing &)> function);
|
||||||
|
|
||||||
bool bounds_min_max(blender::float3 &min, blender::float3 &max) const;
|
bool bounds_min_max(blender::float3 &min, blender::float3 &max) const;
|
||||||
|
|
||||||
|
|
|
@ -725,6 +725,38 @@ static void rna_ID_asset_clear(ID *id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void rna_ID_asset_data_set(PointerRNA *ptr, PointerRNA value, struct ReportList *reports)
|
||||||
|
{
|
||||||
|
ID *destination = ptr->data;
|
||||||
|
|
||||||
|
/* Avoid marking as asset by assigning. This should be done wiht .asset_mark(). This is just for
|
||||||
|
* clarity of the API, and to accomodate future changes. */
|
||||||
|
if (destination->asset_data == NULL) {
|
||||||
|
BKE_report(reports,
|
||||||
|
RPT_ERROR,
|
||||||
|
"Asset data can only be assigned to assets. Use asset_mark() to mark as an asset");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const AssetMetaData *asset_data = value.data;
|
||||||
|
if (asset_data == NULL) {
|
||||||
|
/* Avoid clearing the asset data on assets. Un-marking as asset should be done with
|
||||||
|
* .asset_clear(). This is just for clarity of the API, and to accomodate future changes. */
|
||||||
|
BKE_report(reports, RPT_ERROR, "Asset data cannot be None");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool assigned_ok = ED_asset_copy_to_id(asset_data, destination);
|
||||||
|
if (!assigned_ok) {
|
||||||
|
BKE_reportf(
|
||||||
|
reports, RPT_ERROR, "'%s' is of a type that cannot be an asset", destination->name + 2);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
WM_main_add_notifier(NC_ASSET | NA_EDITED, NULL);
|
||||||
|
WM_main_add_notifier(NC_ID | NA_EDITED, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static ID *rna_ID_override_create(ID *id, Main *bmain, bool remap_local_usages)
|
static ID *rna_ID_override_create(ID *id, Main *bmain, bool remap_local_usages)
|
||||||
{
|
{
|
||||||
if (!ID_IS_OVERRIDABLE_LIBRARY(id)) {
|
if (!ID_IS_OVERRIDABLE_LIBRARY(id)) {
|
||||||
|
@ -2131,7 +2163,8 @@ static void rna_def_ID(BlenderRNA *brna)
|
||||||
RNA_def_property_override_flag(prop, PROPOVERRIDE_NO_COMPARISON);
|
RNA_def_property_override_flag(prop, PROPOVERRIDE_NO_COMPARISON);
|
||||||
|
|
||||||
prop = RNA_def_property(srna, "asset_data", PROP_POINTER, PROP_NONE);
|
prop = RNA_def_property(srna, "asset_data", PROP_POINTER, PROP_NONE);
|
||||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
RNA_def_property_flag(prop, PROP_EDITABLE);
|
||||||
|
RNA_def_property_pointer_funcs(prop, NULL, "rna_ID_asset_data_set", NULL, NULL);
|
||||||
RNA_def_property_override_flag(prop, PROPOVERRIDE_NO_COMPARISON);
|
RNA_def_property_override_flag(prop, PROPOVERRIDE_NO_COMPARISON);
|
||||||
RNA_def_property_ui_text(prop, "Asset Data", "Additional data for an asset data-block");
|
RNA_def_property_ui_text(prop, "Asset Data", "Additional data for an asset data-block");
|
||||||
|
|
||||||
|
|
|
@ -1637,6 +1637,7 @@ void RNA_api_ui_layout(StructRNA *srna)
|
||||||
parm = RNA_def_pointer(func, "image_settings", "ImageFormatSettings", "", "");
|
parm = RNA_def_pointer(func, "image_settings", "ImageFormatSettings", "", "");
|
||||||
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
|
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
|
||||||
RNA_def_boolean(func, "color_management", false, "", "Show color management settings");
|
RNA_def_boolean(func, "color_management", false, "", "Show color management settings");
|
||||||
|
RNA_def_boolean(func, "show_z_buffer", true, "", "Show option to save z-buffer");
|
||||||
|
|
||||||
func = RNA_def_function(srna, "template_image_stereo_3d", "uiTemplateImageStereo3d");
|
func = RNA_def_function(srna, "template_image_stereo_3d", "uiTemplateImageStereo3d");
|
||||||
RNA_def_function_ui_description(func, "User interface for setting image stereo 3d options");
|
RNA_def_function_ui_description(func, "User interface for setting image stereo 3d options");
|
||||||
|
|
|
@ -305,9 +305,11 @@ static void node_composit_buts_file_output_ex(uiLayout *layout, bContext *C, Poi
|
||||||
const bool multilayer = RNA_enum_get(&imfptr, "file_format") == R_IMF_IMTYPE_MULTILAYER;
|
const bool multilayer = RNA_enum_get(&imfptr, "file_format") == R_IMF_IMTYPE_MULTILAYER;
|
||||||
const bool is_exr = RNA_enum_get(&imfptr, "file_format") == R_IMF_IMTYPE_OPENEXR;
|
const bool is_exr = RNA_enum_get(&imfptr, "file_format") == R_IMF_IMTYPE_OPENEXR;
|
||||||
const bool is_multiview = (scene->r.scemode & R_MULTIVIEW) != 0;
|
const bool is_multiview = (scene->r.scemode & R_MULTIVIEW) != 0;
|
||||||
|
/* Unclear where to get z-information from, so deactivate it. */
|
||||||
|
const bool show_z_buffer = false;
|
||||||
|
|
||||||
node_composit_buts_file_output(layout, C, ptr);
|
node_composit_buts_file_output(layout, C, ptr);
|
||||||
uiTemplateImageSettings(layout, &imfptr, true);
|
uiTemplateImageSettings(layout, &imfptr, true, show_z_buffer);
|
||||||
|
|
||||||
/* disable stereo output for multilayer, too much work for something that no one will use */
|
/* disable stereo output for multilayer, too much work for something that no one will use */
|
||||||
/* if someone asks for that we can implement it */
|
/* if someone asks for that we can implement it */
|
||||||
|
@ -430,7 +432,7 @@ static void node_composit_buts_file_output_ex(uiLayout *layout, bContext *C, Poi
|
||||||
const bool use_color_management = RNA_boolean_get(&active_input_ptr, "save_as_render");
|
const bool use_color_management = RNA_boolean_get(&active_input_ptr, "save_as_render");
|
||||||
|
|
||||||
col = uiLayoutColumn(layout, false);
|
col = uiLayoutColumn(layout, false);
|
||||||
uiTemplateImageSettings(col, &imfptr, use_color_management);
|
uiTemplateImageSettings(col, &imfptr, use_color_management, show_z_buffer);
|
||||||
|
|
||||||
if (is_multiview) {
|
if (is_multiview) {
|
||||||
col = uiLayoutColumn(layout, false);
|
col = uiLayoutColumn(layout, false);
|
||||||
|
|
Loading…
Reference in New Issue