UI: Asset Shelf (Experimental Feature) #104831

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

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
145 changed files with 20455 additions and 20067 deletions
Showing only changes of commit 4b4cf6da9a - Show all commits

View File

@ -0,0 +1,15 @@
diff --git a/extern/vulkan_memory_allocator/vk_mem_alloc.h b/extern/vulkan_memory_allocator/vk_mem_alloc.h
index 60f572038c0..63a9994ba46 100644
--- a/extern/vulkan_memory_allocator/vk_mem_alloc.h
+++ b/extern/vulkan_memory_allocator/vk_mem_alloc.h
@@ -13371,8 +13371,8 @@ bool VmaDefragmentationContext_T::IncrementCounters(VkDeviceSize bytes)
// Early return when max found
if (++m_PassStats.allocationsMoved >= m_MaxPassAllocations || m_PassStats.bytesMoved >= m_MaxPassBytes)
{
- VMA_ASSERT(m_PassStats.allocationsMoved == m_MaxPassAllocations ||
- m_PassStats.bytesMoved == m_MaxPassBytes && "Exceeded maximal pass threshold!");
+ VMA_ASSERT((m_PassStats.allocationsMoved == m_MaxPassAllocations ||
+ m_PassStats.bytesMoved == m_MaxPassBytes) && "Exceeded maximal pass threshold!");
return true;
}
return false;

File diff suppressed because it is too large Load Diff

View File

@ -161,7 +161,10 @@ ccl_device_inline void osl_eval_nodes(KernelGlobals kg,
/* shadeindex = */ 0);
# endif
if (globals.Ci) {
if constexpr (type == SHADER_TYPE_DISPLACEMENT) {
sd->P = globals.P;
}
else if (globals.Ci) {
flatten_closure_tree(kg, sd, path_flag, globals.Ci);
}
}

View File

@ -23,7 +23,10 @@
#include "subd/patch_table.h"
#include "subd/split.h"
#include "kernel/osl/globals.h"
#ifdef WITH_OSL
# include "kernel/osl/globals.h"
# include "kernel/osl/services.h"
#endif
#include "util/foreach.h"
#include "util/log.h"
@ -1671,6 +1674,7 @@ void GeometryManager::device_update_displacement_images(Device *device,
TaskPool pool;
ImageManager *image_manager = scene->image_manager;
set<int> bump_images;
bool has_osl_node = false;
foreach (Geometry *geom, scene->geometry) {
if (geom->is_modified()) {
/* Geometry-level check for hair shadow transparency.
@ -1690,6 +1694,9 @@ void GeometryManager::device_update_displacement_images(Device *device,
continue;
}
foreach (ShaderNode *node, shader->graph->nodes) {
if (node->special_type == SHADER_SPECIAL_TYPE_OSL) {
has_osl_node = true;
}
if (node->special_type != SHADER_SPECIAL_TYPE_IMAGE_SLOT) {
continue;
}
@ -1705,6 +1712,28 @@ void GeometryManager::device_update_displacement_images(Device *device,
}
}
}
#ifdef WITH_OSL
/* If any OSL node is used for displacement, it may reference a texture. But it's
* unknown which ones, so have to load them all. */
if (has_osl_node) {
set<OSLRenderServices *> services_shared;
device->foreach_device([&services_shared](Device *sub_device) {
OSLGlobals *og = (OSLGlobals *)sub_device->get_cpu_osl_memory();
services_shared.insert(og->services);
});
for (OSLRenderServices *services : services_shared) {
for (auto it = services->textures.begin(); it != services->textures.end(); ++it) {
if (it->second->handle.get_manager() == image_manager) {
const int slot = it->second->handle.svm_slot();
bump_images.insert(slot);
}
}
}
}
#endif
foreach (int slot, bump_images) {
pool.push(function_bind(
&ImageManager::device_update_slot, image_manager, device, scene, slot, &progress));

@ -1 +1 @@
Subproject commit fe59d382b4fd2047920208fa92d39fc1361d9242
Subproject commit 534bf3b76c3b5f3bcd21641f1d53c1062bedcdbe

View File

@ -4421,6 +4421,11 @@ def km_weight_paint_vertex_selection(params):
("view3d.select_lasso", {"type": params.action_mouse, "value": 'CLICK_DRAG', "shift": True, "ctrl": True},
{"properties": [("mode", 'SUB')]}),
("view3d.select_circle", {"type": 'C', "value": 'PRESS'}, None),
("paint.vert_select_linked", {"type": 'L', "value": 'PRESS', "ctrl": True}, None),
("paint.vert_select_linked_pick", {"type": 'L', "value": 'PRESS'},
{"properties": [("select", True)]}),
("paint.vert_select_linked_pick", {"type": 'L', "value": 'PRESS', "shift": True},
{"properties": [("select", False)]}),
])
return keymap
@ -5048,7 +5053,7 @@ def km_sculpt(params):
{"properties": [
("target", "MASK"),
("falloff_type", "GEODESIC"),
("invert", True),
("invert", False),
("use_auto_mask", False),
("use_mask_preserve", True),
]}),

View File

@ -2972,6 +2972,11 @@ def km_weight_paint_vertex_selection(params):
("paint.vert_select_hide", {"type": 'H', "value": 'PRESS', "shift": True},
{"properties": [("unselected", True)]}),
("paint.face_vert_reveal", {"type": 'H', "value": 'PRESS', "alt": True}, None),
("paint.vert_select_linked", {"type": 'L', "value": 'PRESS', "ctrl": True}, None),
("paint.vert_select_linked_pick", {"type": 'L', "value": 'PRESS'},
{"properties": [("select", True)]}),
("paint.vert_select_linked_pick", {"type": 'L', "value": 'PRESS', "shift": True},
{"properties": [("select", False)]}),
])
return keymap

View File

@ -1,6 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-or-later
from bpy.types import Panel
from bpy.app.translations import contexts as i18n_contexts
class ObjectConstraintPanel:
@ -398,7 +397,7 @@ class ConstraintButtonsPanel:
sub.prop(con, "invert_z", text="Z", toggle=True)
row.label(icon='BLANK1')
layout.prop(con, "mix_mode", text="Mix", text_ctxt=i18n_contexts.constraint)
layout.prop(con, "mix_mode", text="Mix")
self.space_template(layout, con)
@ -489,7 +488,7 @@ class ConstraintButtonsPanel:
self.target_template(layout, con)
layout.prop(con, "remove_target_shear")
layout.prop(con, "mix_mode", text="Mix", text_ctxt=i18n_contexts.constraint)
layout.prop(con, "mix_mode", text="Mix")
self.space_template(layout, con)
@ -514,7 +513,7 @@ class ConstraintButtonsPanel:
subsub.prop(con, "eval_time", text="")
row.prop_decorator(con, "eval_time")
layout.prop(con, "mix_mode", text="Mix", text_ctxt=i18n_contexts.constraint)
layout.prop(con, "mix_mode", text="Mix")
self.draw_influence(layout, con)
@ -1025,7 +1024,7 @@ class ConstraintButtonsSubPanel:
col.prop(con, "to_min_z" + ext, text="Min")
col.prop(con, "to_max_z" + ext, text="Max")
layout.prop(con, "mix_mode" + ext, text="Mix", text_ctxt=i18n_contexts.constraint)
layout.prop(con, "mix_mode" + ext, text="Mix")
def draw_armature_bones(self, context):
layout = self.layout

View File

@ -605,7 +605,7 @@ class USERPREF_PT_system_cycles_devices(SystemPanel, CenterAlignMixIn, Panel):
class USERPREF_PT_system_gpu_backend(SystemPanel, CenterAlignMixIn, Panel):
bl_label = "GPU Back end"
bl_label = "GPU Backend"
@classmethod
def poll(cls, _context):

View File

@ -2038,6 +2038,7 @@ class VIEW3D_MT_select_paint_mask_vertex(Menu):
layout.separator()
layout.operator("paint.vert_select_ungrouped", text="Ungrouped Vertices")
layout.operator("paint.vert_select_linked", text="Select Linked")
class VIEW3D_MT_select_edit_curves(Menu):
@ -6195,14 +6196,15 @@ class VIEW3D_PT_shading_compositor(Panel):
def draw(self, context):
shading = context.space_data.shading
import sys
is_macos = sys.platform == "darwin"
import gpu
is_supported = (gpu.capabilities.compute_shader_support_get()
and gpu.capabilities.shader_image_load_store_support_get())
row = self.layout.row()
row.active = not is_macos
row.active = is_supported
row.prop(shading, "use_compositor", expand=True)
if is_macos and shading.use_compositor != "DISABLED":
self.layout.label(text="Compositor not supported on MacOS", icon='ERROR')
if shading.use_compositor != "DISABLED" and not is_supported:
self.layout.label(text="Compositor not supported on this platform", icon='ERROR')
class VIEW3D_PT_gizmo_display(Panel):

View File

@ -153,6 +153,14 @@ bool BKE_collection_object_remove(struct Main *bmain,
struct Collection *collection,
struct Object *object,
bool free_us);
/**
* Replace one object with another in a collection (managing user counts).
*/
bool BKE_collection_object_replace(struct Main *bmain,
struct Collection *collection,
struct Object *ob_old,
struct Object *ob_new);
/**
* Move object from a collection into another
*

View File

@ -128,17 +128,6 @@ class CurvesGeometry : public ::CurvesGeometry {
CurvesGeometry &operator=(CurvesGeometry &&other);
~CurvesGeometry();
static CurvesGeometry &wrap(::CurvesGeometry &dna_struct)
{
CurvesGeometry *geometry = reinterpret_cast<CurvesGeometry *>(&dna_struct);
return *geometry;
}
static const CurvesGeometry &wrap(const ::CurvesGeometry &dna_struct)
{
const CurvesGeometry *geometry = reinterpret_cast<const CurvesGeometry *>(&dna_struct);
return *geometry;
}
/* --------------------------------------------------------------------
* Accessors.
*/
@ -408,6 +397,8 @@ class CurvesGeometry : public ::CurvesGeometry {
}
};
static_assert(sizeof(blender::bke::CurvesGeometry) == sizeof(::CurvesGeometry));
/**
* Used to propagate deformation data through modifier evaluation so that sculpt tools can work on
* evaluated data.
@ -966,3 +957,12 @@ struct CurvesSurfaceTransforms {
};
} // namespace blender::bke
inline blender::bke::CurvesGeometry &CurvesGeometry::wrap()
{
return *reinterpret_cast<blender::bke::CurvesGeometry *>(this);
}
inline const blender::bke::CurvesGeometry &CurvesGeometry::wrap() const
{
return *reinterpret_cast<const blender::bke::CurvesGeometry *>(this);
}

View File

@ -112,7 +112,7 @@ static std::optional<blender::bke::MutableAttributeAccessor> get_attribute_acces
}
case ID_CV: {
Curves &curves_id = reinterpret_cast<Curves &>(id);
CurvesGeometry &curves = CurvesGeometry::wrap(curves_id.geometry);
CurvesGeometry &curves = curves_id.geometry.wrap();
return curves.attributes_for_write();
}
default: {

View File

@ -1214,6 +1214,28 @@ bool BKE_collection_object_remove(Main *bmain,
return true;
}
bool BKE_collection_object_replace(Main *bmain,
Collection *collection,
Object *ob_old,
Object *ob_new)
{
CollectionObject *cob = BLI_findptr(
&collection->gobject, ob_old, offsetof(CollectionObject, ob));
if (cob == NULL) {
return false;
}
id_us_min(&cob->ob->id);
cob->ob = ob_new;
id_us_plus(&cob->ob->id);
if (BKE_collection_is_in_scene(collection)) {
BKE_main_collection_sync(bmain);
}
return true;
}
/**
* Remove object from all collections of scene
* \param collection_skip: Don't remove base from this collection.

View File

@ -601,7 +601,7 @@ GeometryDeformation get_evaluated_curves_deformation(const Depsgraph &depsgraph,
{
BLI_assert(ob_orig.type == OB_CURVES);
const Curves &curves_id_orig = *static_cast<const Curves *>(ob_orig.data);
const CurvesGeometry &curves_orig = CurvesGeometry::wrap(curves_id_orig.geometry);
const CurvesGeometry &curves_orig = curves_id_orig.geometry.wrap();
const int points_num = curves_orig.points_num();
GeometryDeformation deformation;
@ -643,7 +643,7 @@ GeometryDeformation get_evaluated_curves_deformation(const Depsgraph &depsgraph,
if (curves_component_eval != nullptr) {
const Curves *curves_id_eval = curves_component_eval->get_for_read();
if (curves_id_eval != nullptr) {
const CurvesGeometry &curves_eval = CurvesGeometry::wrap(curves_id_eval->geometry);
const CurvesGeometry &curves_eval = curves_id_eval->geometry.wrap();
if (curves_eval.points_num() == points_num) {
deformation.positions = curves_eval.positions();
}

View File

@ -82,7 +82,7 @@ Curves *curve_legacy_to_curves(const Curve &curve_legacy, const ListBase &nurbs_
const Vector<const Nurb *> src_curves(nurbs_list);
Curves *curves_id = curves_new_nomain(0, src_curves.size());
CurvesGeometry &curves = CurvesGeometry::wrap(curves_id->geometry);
CurvesGeometry &curves = curves_id->geometry.wrap();
MutableAttributeAccessor curves_attributes = curves.attributes_for_write();
MutableSpan<int8_t> types = curves.curve_types_for_write();

View File

@ -70,8 +70,8 @@ static void curves_copy_data(Main * /*bmain*/, ID *id_dst, const ID *id_src, con
const Curves *curves_src = (const Curves *)id_src;
curves_dst->mat = static_cast<Material **>(MEM_dupallocN(curves_src->mat));
const bke::CurvesGeometry &src = bke::CurvesGeometry::wrap(curves_src->geometry);
bke::CurvesGeometry &dst = bke::CurvesGeometry::wrap(curves_dst->geometry);
const bke::CurvesGeometry &src = curves_src->geometry.wrap();
bke::CurvesGeometry &dst = curves_dst->geometry.wrap();
/* We need special handling here because the generic ID management code has already done a
* shallow copy from the source to the destination, and because the copy-on-write functionality
@ -103,7 +103,7 @@ static void curves_free_data(ID *id)
Curves *curves = (Curves *)id;
BKE_animdata_free(&curves->id, false);
blender::bke::CurvesGeometry::wrap(curves->geometry).~CurvesGeometry();
curves->geometry.wrap().~CurvesGeometry();
BKE_curves_batch_cache_free(curves);
@ -174,7 +174,7 @@ static void curves_blend_read_data(BlendDataReader *reader, ID *id)
curves->geometry.runtime = MEM_new<blender::bke::CurvesGeometryRuntime>(__func__);
/* Recalculate curve type count cache that isn't saved in files. */
blender::bke::CurvesGeometry::wrap(curves->geometry).update_curve_types();
curves->geometry.wrap().update_curve_types();
/* Materials */
BLO_read_pointer_array(reader, (void **)&curves->mat);
@ -247,8 +247,7 @@ BoundBox *BKE_curves_boundbox_get(Object *ob)
if (ob->runtime.bb == nullptr) {
ob->runtime.bb = MEM_cnew<BoundBox>(__func__);
const blender::bke::CurvesGeometry &curves = blender::bke::CurvesGeometry::wrap(
curves_id->geometry);
const blender::bke::CurvesGeometry &curves = curves_id->geometry.wrap();
float3 min(FLT_MAX);
float3 max(-FLT_MAX);
@ -372,7 +371,7 @@ Curves *curves_new_nomain(const int points_num, const int curves_num)
BLI_assert(points_num >= 0);
BLI_assert(curves_num >= 0);
Curves *curves_id = static_cast<Curves *>(BKE_id_new_nomain(ID_CV, nullptr));
CurvesGeometry &curves = CurvesGeometry::wrap(curves_id->geometry);
CurvesGeometry &curves = curves_id->geometry.wrap();
curves.resize(points_num, curves_num);
return curves_id;
}
@ -380,7 +379,7 @@ Curves *curves_new_nomain(const int points_num, const int curves_num)
Curves *curves_new_nomain_single(const int points_num, const CurveType type)
{
Curves *curves_id = curves_new_nomain(points_num, 1);
CurvesGeometry &curves = CurvesGeometry::wrap(curves_id->geometry);
CurvesGeometry &curves = curves_id->geometry.wrap();
curves.offsets_for_write().last() = points_num;
curves.fill_curve_types(type);
return curves_id;
@ -389,7 +388,7 @@ Curves *curves_new_nomain_single(const int points_num, const CurveType type)
Curves *curves_new_nomain(CurvesGeometry curves)
{
Curves *curves_id = static_cast<Curves *>(BKE_id_new_nomain(ID_CV, nullptr));
bke::CurvesGeometry::wrap(curves_id->geometry) = std::move(curves);
curves_id->geometry.wrap() = std::move(curves);
return curves_id;
}

View File

@ -48,7 +48,7 @@ void GeometryComponentEditData::remember_deformed_curve_positions_if_necessary(
if (curves_id == nullptr) {
return;
}
const bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id->geometry);
const bke::CurvesGeometry &curves = curves_id->geometry.wrap();
const int points_num = curves.points_num();
if (points_num != edit_component.curves_edit_hints_->curves_id_orig.geometry.point_num) {
return;

View File

@ -55,7 +55,7 @@ GeometryFieldContext::GeometryFieldContext(const GeometryComponent &component,
case GEO_COMPONENT_TYPE_CURVE: {
const CurveComponent &curve_component = static_cast<const CurveComponent &>(component);
const Curves *curves = curve_component.get_for_read();
geometry_ = curves ? &CurvesGeometry::wrap(curves->geometry) : nullptr;
geometry_ = curves ? &curves->geometry.wrap() : nullptr;
break;
}
case GEO_COMPONENT_TYPE_POINT_CLOUD: {
@ -560,8 +560,7 @@ std::optional<eAttrDomain> try_detect_field_domain(const GeometryComponent &comp
}
else if (const auto *curves_field_input = dynamic_cast<const CurvesFieldInput *>(
&field_input)) {
if (!handle_domain(
curves_field_input->preferred_domain(CurvesGeometry::wrap(curves->geometry)))) {
if (!handle_domain(curves_field_input->preferred_domain(curves->geometry.wrap()))) {
return std::nullopt;
}
}

View File

@ -227,7 +227,7 @@ bool GeometrySet::compute_boundbox_without_instances(float3 *r_min, float3 *r_ma
have_minmax |= BKE_volume_min_max(volume, *r_min, *r_max);
}
if (const Curves *curves_id = this->get_curves_for_read()) {
const bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id->geometry);
const bke::CurvesGeometry &curves = curves_id->geometry.wrap();
have_minmax |= curves.bounds_min_max(*r_min, *r_max);
}
return have_minmax;

View File

@ -802,8 +802,7 @@ static Mesh *mesh_new_from_evaluated_curve_type_object(const Object *evaluated_o
}
if (const Curves *curves = get_evaluated_curves_from_object(evaluated_object)) {
const blender::bke::AnonymousAttributePropagationInfo propagation_info;
return blender::bke::curve_to_wire_mesh(blender::bke::CurvesGeometry::wrap(curves->geometry),
propagation_info);
return blender::bke::curve_to_wire_mesh(curves->geometry.wrap(), propagation_info);
}
return nullptr;
}

View File

@ -1228,12 +1228,19 @@ void BKE_mesh_legacy_face_set_from_generic(Mesh *mesh,
blender::MutableSpan<CustomDataLayer> poly_layers)
{
using namespace blender;
void *faceset_data = nullptr;
for (CustomDataLayer &layer : poly_layers) {
if (StringRef(layer.name) == ".sculpt_face_set") {
layer.type = CD_SCULPT_FACE_SETS;
faceset_data = layer.data;
layer.data = nullptr;
CustomData_free_layer_named(&mesh->pdata, ".sculpt_face_set", mesh->totpoly);
break;
}
}
CustomData_update_typemap(&mesh->pdata);
if (faceset_data != nullptr) {
CustomData_add_layer(
&mesh->pdata, CD_SCULPT_FACE_SETS, CD_ASSIGN, faceset_data, mesh->totpoly);
}
}
void BKE_mesh_legacy_face_set_to_generic(Mesh *mesh)
@ -1242,13 +1249,19 @@ void BKE_mesh_legacy_face_set_to_generic(Mesh *mesh)
if (mesh->attributes().contains(".sculpt_face_set")) {
return;
}
for (CustomDataLayer &layer : MutableSpan(mesh->pdata.layers, mesh->pdata.totlayer)) {
if (layer.type == CD_SCULPT_FACE_SETS) {
BLI_strncpy(layer.name, ".sculpt_face_set", sizeof(layer.name));
layer.type = CD_PROP_INT32;
void *faceset_data = nullptr;
for (const int i : IndexRange(mesh->pdata.totlayer)) {
if (mesh->pdata.layers[i].type == CD_SCULPT_FACE_SETS) {
faceset_data = mesh->pdata.layers[i].data;
mesh->pdata.layers[i].data = nullptr;
CustomData_free_layer(&mesh->pdata, CD_SCULPT_FACE_SETS, mesh->totpoly, i);
break;
}
}
CustomData_update_typemap(&mesh->pdata);
if (faceset_data != nullptr) {
CustomData_add_layer_named(
&mesh->pdata, CD_PROP_INT32, CD_ASSIGN, faceset_data, mesh->totpoly, ".sculpt_face_set");
}
}
/** \} */

View File

@ -922,7 +922,11 @@ void ntreeBlendReadLib(BlendLibReader *reader, bNodeTree *ntree)
* to match the static layout. */
if (!BLO_read_lib_is_undo(reader)) {
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
node_verify_sockets(ntree, node, false);
/* Don't update node groups here because they may depend on other node groups which are not
* fully versioned yet and don't have `typeinfo` pointers set. */
if (node->type != NODE_GROUP) {
node_verify_sockets(ntree, node, false);
}
}
}
}
@ -1075,7 +1079,7 @@ IDTypeInfo IDType_ID_NT = {
static void node_add_sockets_from_type(bNodeTree *ntree, bNode *node, bNodeType *ntype)
{
if (ntype->declare != nullptr) {
if (ntype->declare || ntype->declare_dynamic) {
node_verify_sockets(ntree, node, true);
return;
}
@ -3587,31 +3591,43 @@ static void update_socket_declarations(ListBase *sockets,
}
}
static void reset_socket_declarations(ListBase *sockets)
{
LISTBASE_FOREACH (bNodeSocket *, socket, sockets) {
socket->runtime->declaration = nullptr;
}
}
void nodeSocketDeclarationsUpdate(bNode *node)
{
BLI_assert(node->runtime->declaration != nullptr);
update_socket_declarations(&node->inputs, node->runtime->declaration->inputs);
update_socket_declarations(&node->outputs, node->runtime->declaration->outputs);
if (node->runtime->declaration->skip_updating_sockets) {
reset_socket_declarations(&node->inputs);
reset_socket_declarations(&node->outputs);
}
else {
update_socket_declarations(&node->inputs, node->runtime->declaration->inputs);
update_socket_declarations(&node->outputs, node->runtime->declaration->outputs);
}
}
bool nodeDeclarationEnsureOnOutdatedNode(bNodeTree * /*ntree*/, bNode *node)
bool nodeDeclarationEnsureOnOutdatedNode(bNodeTree *ntree, bNode *node)
{
if (node->runtime->declaration != nullptr) {
return false;
}
if (node->typeinfo->declare == nullptr) {
return false;
}
if (node->typeinfo->declare_dynamic) {
node->runtime->declaration = new blender::nodes::NodeDeclaration();
blender::nodes::build_node_declaration(*node->typeinfo, *node->runtime->declaration);
blender::nodes::build_node_declaration_dynamic(*ntree, *node, *node->runtime->declaration);
return true;
}
else {
if (node->typeinfo->declare) {
/* Declaration should have been created in #nodeRegisterType. */
BLI_assert(node->typeinfo->fixed_declaration != nullptr);
node->runtime->declaration = node->typeinfo->fixed_declaration;
return true;
}
return true;
return false;
}
bool nodeDeclarationEnsure(bNodeTree *ntree, bNode *node)

View File

@ -476,11 +476,12 @@ static const AVCodec *get_av1_encoder(
const AVCodec *codec = NULL;
switch (context->ffmpeg_preset) {
case FFM_PRESET_BEST:
/* Default to libaom-av1 for BEST preset due to it performing better than rav1e in terms of
* video quality (VMAF scores). Fallback to rav1e if libaom-av1 isn't available. */
codec = avcodec_find_encoder_by_name("libaom-av1");
/* libaom-av1 may produce better VMAF-scoring videos in serveral cases, but there are cases
* where using a different encoder is desireable, such as in T103849. */
codec = avcodec_find_encoder_by_name("librav1e");
if (!codec) {
codec = avcodec_find_encoder_by_name("librav1e");
/* Fallback to libaom-av1 if librav1e is not found. */
codec = avcodec_find_encoder_by_name("libaom-av1");
}
break;
case FFM_PRESET_REALTIME:

View File

@ -174,6 +174,18 @@ template<typename T, int Size> struct VecBase : public vec_struct_base<T, Size>
}
}
/** Swizzling. */
template<BLI_ENABLE_IF_VEC(Size, >= 3)> VecBase<T, 2> xy() const
{
return *reinterpret_cast<const VecBase<T, 2> *>(this);
}
template<BLI_ENABLE_IF_VEC(Size, >= 4)> VecBase<T, 3> xyz() const
{
return *reinterpret_cast<const VecBase<T, 3> *>(this);
}
#undef BLI_ENABLE_IF_VEC
/** Conversion from pointers (from C-style vectors). */

View File

@ -26,33 +26,33 @@ typedef NodeOperation SocketReader;
class OpenCLDevice : public Device {
private:
/**
* \brief opencl context
* \brief OPENCL context
*/
cl_context context_;
/**
* \brief opencl device
* \brief OPENCL device
*/
cl_device_id device_;
/**
* \brief opencl program
* \brief OPENCL program
*/
cl_program program_;
/**
* \brief opencl command queue
* \brief OPENCL command queue
*/
cl_command_queue queue_;
/**
* \brief opencl vendor ID
* \brief OPENCL vendor ID
*/
cl_int vendor_id_;
public:
/**
* \brief constructor with opencl device
* \brief constructor with OPENCL device
* \param context:
* \param device:
* \param program:

View File

@ -230,7 +230,7 @@ static void compositor_engine_draw(void *data)
if (GPU_backend_get_type() == GPU_BACKEND_METAL) {
/* NOTE(Metal): Isolate Compositor compute work in individual command buffer to improve
* workload scheduling. When expensive compositor nodes are in the graph, these can stall out
* the GPU for extended periods of time and suboptimally schedule work for execution. */
* the GPU for extended periods of time and sub-optimally schedule work for execution. */
GPU_flush();
}
else {
@ -241,11 +241,11 @@ static void compositor_engine_draw(void *data)
}
#endif
/* Exceute Compositor render commands. */
/* Execute Compositor render commands. */
compositor_data->instance_data->draw();
#if defined(__APPLE__)
/* NOTE(Metal): Following previous flush to break commmand stream, with compositor command
/* NOTE(Metal): Following previous flush to break command stream, with compositor command
* buffers potentially being heavy, we avoid issuing subsequent commands until compositor work
* has completed. If subsequent work is prematurely queued up, the subsequent command buffers
* will be blocked behind compositor work and may trigger a command buffer time-out error. As a

View File

@ -644,21 +644,24 @@ void OVERLAY_light_cache_populate(OVERLAY_Data *vedata, Object *ob)
DRW_buffer_add_entry(cb->light_sun, color, &instdata);
}
else if (la->type == LA_SPOT) {
/* Previous implementation was using the clipend distance as cone size.
/* Previous implementation was using the clip-end distance as cone size.
* We cannot do this anymore so we use a fixed size of 10. (see T72871) */
const float3 scale_vec = {10.0f, 10.0f, 10.0f};
rescale_m4(instdata.mat, scale_vec);
/* For cycles and eevee the spot attenuation is
* y = (1/(1 + x^2) - a)/((1 - a) b)
/* For cycles and EEVEE the spot attenuation is:
* `y = (1/sqrt(1 + x^2) - a)/((1 - a) b)`
* x being the tangent of the angle between the light direction and the generatrix of the cone.
* We solve the case where spot attenuation y = 1 and y = 0
* root for y = 1 is (-1 - c) / c
* root for y = 0 is (1 - a) / a
* root for y = 1 is sqrt(1/c^2 - 1)
* root for y = 0 is sqrt(1/a^2 - 1)
* and use that to position the blend circle. */
float a = cosf(la->spotsize * 0.5f);
float b = la->spotblend;
float c = a * b - a - b;
float a2 = a * a;
float c2 = c * c;
/* Optimized version or root1 / root0 */
instdata.spot_blend = sqrtf((-a - c * a) / (c - c * a));
instdata.spot_blend = sqrtf((a2 - a2 * c2) / (c2 - a2 * c2));
instdata.spot_cosine = a;
/* HACK: We pack the area size in alpha color. This is decoded by the shader. */
color[3] = -max_ff(la->radius, FLT_MIN);

View File

@ -33,7 +33,7 @@ void OVERLAY_sculpt_curves_cache_init(OVERLAY_Data *vedata)
static bool everything_selected(const Curves &curves_id)
{
using namespace blender;
const bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id.geometry);
const bke::CurvesGeometry &curves = curves_id.geometry.wrap();
const VArray<bool> selection = curves.attributes().lookup_or_default<bool>(
".selection", ATTR_DOMAIN_POINT, true);
return selection.is_single() && selection.get_internal_single();

View File

@ -131,7 +131,7 @@ static void populate_cache_for_geometry(Object &object,
}
case OB_CURVES_LEGACY: {
Curve *curve = static_cast<Curve *>(object.data);
const bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curve->curve_eval->geometry);
const bke::CurvesGeometry &curves = curve->curve_eval->geometry.wrap();
if (curves.attributes().contains(".viewer")) {
GPUBatch *batch = DRW_cache_curve_edge_wire_viewer_attribute_get(&object);
DRW_shgroup_uniform_float_copy(pd.viewer_attribute_curve_grp, "opacity", opacity);
@ -141,7 +141,7 @@ static void populate_cache_for_geometry(Object &object,
}
case OB_CURVES: {
Curves *curves_id = static_cast<Curves *>(object.data);
const bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id->geometry);
const bke::CurvesGeometry &curves = curves_id->geometry.wrap();
if (curves.attributes().contains(".viewer")) {
bool is_point_domain;
GPUVertBuf **texture = DRW_curves_texture_for_evaluated_attribute(

View File

@ -213,11 +213,10 @@ static CurveRenderData *curve_render_data_create(Curve *cu,
if (types & CU_DATATYPE_WIRE) {
if (rdata->curve_eval != nullptr) {
curve_eval_render_wire_verts_edges_len_get(
blender::bke::CurvesGeometry::wrap(rdata->curve_eval->geometry),
&rdata->wire.curve_len,
&rdata->wire.vert_len,
&rdata->wire.edge_len);
curve_eval_render_wire_verts_edges_len_get(rdata->curve_eval->geometry.wrap(),
&rdata->wire.curve_len,
&rdata->wire.vert_len,
&rdata->wire.edge_len);
}
}
@ -473,8 +472,7 @@ static void curve_create_curves_pos(CurveRenderData *rdata, GPUVertBuf *vbo_curv
GPU_vertbuf_init_with_format(vbo_curves_pos, &format);
GPU_vertbuf_data_alloc(vbo_curves_pos, vert_len);
const blender::bke::CurvesGeometry &curves = blender::bke::CurvesGeometry::wrap(
rdata->curve_eval->geometry);
const blender::bke::CurvesGeometry &curves = rdata->curve_eval->geometry.wrap();
const Span<float3> positions = curves.evaluated_positions();
GPU_vertbuf_attr_fill(vbo_curves_pos, attr_id.pos, positions.data());
}
@ -495,7 +493,7 @@ static void curve_create_attribute(CurveRenderData *rdata, GPUVertBuf *vbo_attr)
GPU_vertbuf_init_with_format(vbo_attr, &format);
GPU_vertbuf_data_alloc(vbo_attr, vert_len);
const bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(rdata->curve_eval->geometry);
const bke::CurvesGeometry &curves = rdata->curve_eval->geometry.wrap();
curves.ensure_can_interpolate_to_evaluated();
const VArraySpan<ColorGeometry4f> colors = curves.attributes().lookup<ColorGeometry4f>(
".viewer", ATTR_DOMAIN_POINT);
@ -519,7 +517,7 @@ static void curve_create_curves_lines(CurveRenderData *rdata, GPUIndexBuf *ibo_c
GPUIndexBufBuilder elb;
GPU_indexbuf_init_ex(&elb, GPU_PRIM_LINE_STRIP, index_len, vert_len);
const bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(rdata->curve_eval->geometry);
const bke::CurvesGeometry &curves = rdata->curve_eval->geometry.wrap();
const OffsetIndices points_by_curve = curves.evaluated_points_by_curve();
const VArray<bool> cyclic = curves.cyclic();

View File

@ -237,7 +237,7 @@ static void curves_batch_cache_fill_segments_proc_pos(
{
using namespace blender;
/* TODO: use hair radius layer if available. */
const bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id.geometry);
const bke::CurvesGeometry &curves = curves_id.geometry.wrap();
const OffsetIndices points_by_curve = curves.points_by_curve();
const Span<float3> positions = curves.positions();
@ -305,7 +305,7 @@ static void curves_batch_cache_ensure_edit_points_pos(const Curves &curves_id,
CurvesBatchCache &cache)
{
using namespace blender;
const bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id.geometry);
const bke::CurvesGeometry &curves = curves_id.geometry.wrap();
static GPUVertFormat format_pos = {0};
static uint pos;
@ -324,7 +324,7 @@ static void curves_batch_cache_ensure_edit_points_data(const Curves &curves_id,
CurvesBatchCache &cache)
{
using namespace blender;
const bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id.geometry);
const bke::CurvesGeometry &curves = curves_id.geometry.wrap();
static GPUVertFormat format_data = {0};
static uint color;
@ -361,7 +361,7 @@ static void curves_batch_cache_ensure_edit_points_data(const Curves &curves_id,
static void curves_batch_cache_ensure_edit_lines(const Curves &curves_id, CurvesBatchCache &cache)
{
using namespace blender;
const bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id.geometry);
const bke::CurvesGeometry &curves = curves_id.geometry.wrap();
const int vert_len = curves.points_num();
const int curve_len = curves.curves_num();
@ -432,8 +432,7 @@ static void curves_batch_ensure_attribute(const Curves &curves,
request.domain == ATTR_DOMAIN_POINT ? curves.geometry.point_num :
curves.geometry.curve_num);
const bke::AttributeAccessor attributes =
bke::CurvesGeometry::wrap(curves.geometry).attributes();
const bke::AttributeAccessor attributes = curves.geometry.wrap().attributes();
/* TODO(@kevindietrich): float4 is used for scalar attributes as the implicit conversion done
* by OpenGL to vec4 for a scalar `s` will produce a `vec4(s, 0, 0, 1)`. However, following
@ -463,8 +462,7 @@ static void curves_batch_cache_fill_strands_data(const Curves &curves_id,
GPUVertBufRaw &data_step,
GPUVertBufRaw &seg_step)
{
const blender::bke::CurvesGeometry &curves = blender::bke::CurvesGeometry::wrap(
curves_id.geometry);
const blender::bke::CurvesGeometry &curves = curves_id.geometry.wrap();
const blender::OffsetIndices points_by_curve = curves.points_by_curve();
for (const int i : IndexRange(curves.curves_num())) {
@ -694,8 +692,7 @@ static void request_attribute(Curves &curves, const char *name)
DRW_Attributes attributes{};
blender::bke::CurvesGeometry &curves_geometry = blender::bke::CurvesGeometry::wrap(
curves.geometry);
blender::bke::CurvesGeometry &curves_geometry = curves.geometry.wrap();
std::optional<blender::bke::AttributeMetaData> meta_data =
curves_geometry.attributes().lookup_meta_data(name);
if (!meta_data) {

View File

@ -327,8 +327,7 @@ DRWShadingGroup *DRW_shgroup_curves_create_sub(Object *object,
/* Use the radius of the root and tip of the first curve for now. This is a workaround that we
* use for now because we can't use a per-point radius yet. */
const blender::bke::CurvesGeometry &curves = blender::bke::CurvesGeometry::wrap(
curves_id.geometry);
const blender::bke::CurvesGeometry &curves = curves_id.geometry.wrap();
if (curves.curves_num() >= 1) {
blender::VArray<float> radii = curves.attributes().lookup_or_default(
"radius", ATTR_DOMAIN_POINT, 0.005f);

View File

@ -929,7 +929,7 @@ static bool acf_group_setting_valid(bAnimContext *ac,
return (ac->spacetype == SPACE_GRAPH);
case ACHANNEL_SETTING_ALWAYS_VISIBLE:
return (ac->spacetype == SPACE_GRAPH);
return ELEM(ac->spacetype, SPACE_ACTION, SPACE_GRAPH);
default: /* always supported */
return true;
@ -4434,7 +4434,7 @@ void ANIM_channel_draw(
* - in Grease Pencil mode, color swatches for layer color
*/
if (ac->sl) {
if ((ac->spacetype == SPACE_GRAPH) &&
if (ELEM(ac->spacetype, SPACE_ACTION, SPACE_GRAPH) &&
(acf->has_setting(ac, ale, ACHANNEL_SETTING_VISIBLE) ||
acf->has_setting(ac, ale, ACHANNEL_SETTING_ALWAYS_VISIBLE))) {
/* for F-Curves, draw color-preview of curve left to the visibility icon */
@ -5177,7 +5177,7 @@ void ANIM_channel_draw_widgets(const bContext *C,
* - in Grease Pencil mode, color swatches for layer color
*/
if (ac->sl) {
if ((ac->spacetype == SPACE_GRAPH) &&
if (ELEM(ac->spacetype, SPACE_ACTION, SPACE_GRAPH) &&
(acf->has_setting(ac, ale, ACHANNEL_SETTING_VISIBLE) ||
acf->has_setting(ac, ale, ACHANNEL_SETTING_ALWAYS_VISIBLE))) {
/* Pin toggle. */

View File

@ -8,7 +8,7 @@
float (*ED_curves_point_normals_array_create(const Curves *curves_id))[3]
{
using namespace blender;
const bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id->geometry);
const bke::CurvesGeometry &curves = curves_id->geometry.wrap();
const int size = curves.points_num();
float3 *data = static_cast<float3 *>(MEM_malloc_arrayN(size, sizeof(float3), __func__));

View File

@ -238,7 +238,7 @@ static void try_convert_single_object(Object &curves_ob,
return;
}
Curves &curves_id = *static_cast<Curves *>(curves_ob.data);
CurvesGeometry &curves = CurvesGeometry::wrap(curves_id.geometry);
CurvesGeometry &curves = curves_id.geometry.wrap();
if (curves_id.surface == nullptr) {
return;
}
@ -521,7 +521,7 @@ static int curves_convert_from_particle_system_exec(bContext *C, wmOperator * /*
Object *ob_new = BKE_object_add(&bmain, &scene, &view_layer, OB_CURVES, psys_eval->name);
Curves *curves_id = static_cast<Curves *>(ob_new->data);
BKE_object_apply_mat4(ob_new, ob_from_orig->object_to_world, true, false);
bke::CurvesGeometry::wrap(curves_id->geometry) = particles_to_curves(*ob_from_eval, *psys_eval);
curves_id->geometry.wrap() = particles_to_curves(*ob_from_eval, *psys_eval);
DEG_relations_tag_update(&bmain);
WM_main_add_notifier(NC_OBJECT | ND_DRAW, nullptr);
@ -562,7 +562,7 @@ static void snap_curves_to_surface_exec_object(Object &curves_ob,
bool *r_missing_uvs)
{
Curves &curves_id = *static_cast<Curves *>(curves_ob.data);
CurvesGeometry &curves = CurvesGeometry::wrap(curves_id.geometry);
CurvesGeometry &curves = curves_id.geometry.wrap();
const Mesh &surface_mesh = *static_cast<const Mesh *>(surface_ob.data);
const Span<float3> surface_positions = surface_mesh.vert_positions();
@ -774,7 +774,7 @@ static int curves_set_selection_domain_exec(bContext *C, wmOperator *op)
curves_id->selection_domain = domain;
CurvesGeometry &curves = CurvesGeometry::wrap(curves_id->geometry);
CurvesGeometry &curves = curves_id->geometry.wrap();
bke::MutableAttributeAccessor attributes = curves.attributes_for_write();
if (curves.points_num() == 0) {
continue;
@ -830,7 +830,7 @@ static void CURVES_OT_set_selection_domain(wmOperatorType *ot)
static bool has_anything_selected(const Span<Curves *> curves_ids)
{
return std::any_of(curves_ids.begin(), curves_ids.end(), [](const Curves *curves_id) {
return has_anything_selected(CurvesGeometry::wrap(curves_id->geometry));
return has_anything_selected(curves_id->geometry.wrap());
});
}
@ -846,9 +846,7 @@ static int select_all_exec(bContext *C, wmOperator *op)
for (Curves *curves_id : unique_curves) {
/* (De)select all the curves. */
select_all(CurvesGeometry::wrap(curves_id->geometry),
eAttrDomain(curves_id->selection_domain),
action);
select_all(curves_id->geometry.wrap(), eAttrDomain(curves_id->selection_domain), action);
/* Use #ID_RECALC_GEOMETRY instead of #ID_RECALC_SELECT because it is handled as a generic
* attribute for now. */
@ -881,7 +879,7 @@ static int select_random_exec(bContext *C, wmOperator *op)
const float probability = RNA_float_get(op->ptr, "probability");
for (Curves *curves_id : unique_curves) {
CurvesGeometry &curves = CurvesGeometry::wrap(curves_id->geometry);
CurvesGeometry &curves = curves_id->geometry.wrap();
select_random(curves, eAttrDomain(curves_id->selection_domain), uint32_t(seed), probability);
/* Use #ID_RECALC_GEOMETRY instead of #ID_RECALC_SELECT because it is handled as a generic
@ -952,7 +950,7 @@ static int select_end_exec(bContext *C, wmOperator *op)
const int amount = RNA_int_get(op->ptr, "amount");
for (Curves *curves_id : unique_curves) {
CurvesGeometry &curves = CurvesGeometry::wrap(curves_id->geometry);
CurvesGeometry &curves = curves_id->geometry.wrap();
select_ends(curves, eAttrDomain(curves_id->selection_domain), amount, end_points);
/* Use #ID_RECALC_GEOMETRY instead of #ID_RECALC_SELECT because it is handled as a generic

View File

@ -52,7 +52,7 @@ static IndexMask retrieve_selected_curves(const bke::CurvesGeometry &curves,
IndexMask retrieve_selected_curves(const Curves &curves_id, Vector<int64_t> &r_indices)
{
const bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id.geometry);
const bke::CurvesGeometry &curves = curves_id.geometry.wrap();
return retrieve_selected_curves(curves, r_indices);
}
@ -67,7 +67,7 @@ IndexMask retrieve_selected_points(const bke::CurvesGeometry &curves, Vector<int
IndexMask retrieve_selected_points(const Curves &curves_id, Vector<int64_t> &r_indices)
{
const bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id.geometry);
const bke::CurvesGeometry &curves = curves_id.geometry.wrap();
return retrieve_selected_points(curves, r_indices);
}

View File

@ -60,7 +60,7 @@ static bool step_encode(bContext *C, Main *bmain, UndoStep *us_p)
StepObject &object = us->objects[i];
object.obedit_ref.ptr = ob;
object.geometry = bke::CurvesGeometry::wrap(curves_id.geometry);
object.geometry = curves_id.geometry.wrap();
}
});
MEM_SAFE_FREE(objects);
@ -86,7 +86,7 @@ static void step_decode(
Curves &curves_id = *static_cast<Curves *>(object.obedit_ref.ptr->data);
/* Overwrite the curves geometry. */
bke::CurvesGeometry::wrap(curves_id.geometry) = object.geometry;
curves_id.geometry.wrap() = object.geometry;
DEG_id_tag_update(&curves_id.id, ID_RECALC_GEOMETRY);
}

View File

@ -8,7 +8,7 @@
*
* 2D Gizmo
*
* \brief Rectangular gizmo acting as a 'cage' around its content.
* \brief Rectangular or circular gizmo acting as a 'cage' around its content.
* Interacting scales or translates the gizmo.
*/
@ -41,6 +41,8 @@
#include "../gizmo_library_intern.h"
#define GIZMO_MARGIN_OFFSET_SCALE 1.5f
/* The same as in `draw_cache.c` */
#define CIRCLE_RESOL 32
static bool gizmo_calc_rect_view_scale(const wmGizmo *gz, const float dims[2], float scale[2])
{
@ -345,7 +347,7 @@ static void cage2d_draw_box_interaction(const float color[4],
}
case ED_GIZMO_CAGE2D_PART_TRANSLATE:
if (draw_options & ED_GIZMO_CAGE2D_DRAW_FLAG_XFORM_CENTER_HANDLE) {
if (draw_options & ED_GIZMO_CAGE_DRAW_FLAG_XFORM_CENTER_HANDLE) {
ARRAY_SET_ITEMS(verts[0], -margin[0] / 2, -margin[1] / 2);
ARRAY_SET_ITEMS(verts[1], margin[0] / 2, margin[1] / 2);
ARRAY_SET_ITEMS(verts[2], -margin[0] / 2, margin[1] / 2);
@ -472,12 +474,12 @@ static void imm_draw_point_aspect_2d(
}
}
static void cage2d_draw_circle_wire(const rctf *r,
const float margin[2],
const float color[3],
const int transform_flag,
const int draw_options,
const float line_width)
static void cage2d_draw_rect_wire(const rctf *r,
const float margin[2],
const float color[3],
const int transform_flag,
const int draw_options,
const float line_width)
{
/* NOTE(Metal): Prefer using 3D coordinates with 3D shader input, even if rendering 2D gizmo's.
*/
@ -506,7 +508,7 @@ static void cage2d_draw_circle_wire(const rctf *r,
immVertex3f(pos, r->xmin, r->ymin, 0.0f);
immEnd();
if (transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_ROTATE) {
if (transform_flag & ED_GIZMO_CAGE_XFORM_FLAG_ROTATE) {
immBegin(GPU_PRIM_LINES, 4);
immVertex3f(pos, BLI_rctf_cent_x(r), r->ymax, 0.0f);
immVertex3f(pos, BLI_rctf_cent_x(r), r->ymax + margin[1], 0.0f);
@ -516,8 +518,8 @@ static void cage2d_draw_circle_wire(const rctf *r,
immEnd();
}
if (transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE) {
if (draw_options & ED_GIZMO_CAGE2D_DRAW_FLAG_XFORM_CENTER_HANDLE) {
if (transform_flag & ED_GIZMO_CAGE_XFORM_FLAG_TRANSLATE) {
if (draw_options & ED_GIZMO_CAGE_DRAW_FLAG_XFORM_CENTER_HANDLE) {
const float rad[2] = {margin[0] / 2, margin[1] / 2};
const float center[2] = {BLI_rctf_cent_x(r), BLI_rctf_cent_y(r)};
@ -533,11 +535,31 @@ static void cage2d_draw_circle_wire(const rctf *r,
immUnbindProgram();
}
static void cage2d_draw_circle_handles(const rctf *r,
const float margin[2],
const float color[3],
const int transform_flag,
bool solid)
static void cage2d_draw_circle_wire(const float color[3],
const float size[2],
const float margin,
const float line_width)
{
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR);
immUniformColor3fv(color);
float viewport[4];
GPU_viewport_size_get_f(viewport);
immUniform2fv("viewportSize", &viewport[2]);
immUniform1f("lineWidth", line_width * U.pixelsize + margin);
imm_draw_circle_wire_aspect_3d(pos, 0.0f, 0.0f, size[0], size[1], CIRCLE_RESOL);
immUnbindProgram();
}
static void cage2d_draw_rect_handles(const rctf *r,
const float margin[2],
const float color[3],
const int transform_flag,
bool solid)
{
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
void (*circle_fn)(uint, float, float, float, float, int) = (solid) ?
@ -557,7 +579,7 @@ static void cage2d_draw_circle_handles(const rctf *r,
imm_draw_point_aspect_2d(pos, r->xmin, r->ymax, rad[0], rad[1], solid);
}
if (transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_ROTATE) {
if (transform_flag & ED_GIZMO_CAGE_XFORM_FLAG_ROTATE) {
const float handle[2] = {
BLI_rctf_cent_x(r),
r->ymax + (margin[1] * GIZMO_MARGIN_OFFSET_SCALE),
@ -609,39 +631,46 @@ static void gizmo_cage2d_draw_intern(wmGizmo *gz,
if (select) {
/* Expand for hot-spot. */
const float size[2] = {size_real[0] + margin[0] / 2, size_real[1] + margin[1] / 2};
if (draw_style == ED_GIZMO_CAGE2D_STYLE_CIRCLE) {
/* Only scaling is needed for now. */
GPU_select_load_id(select_id | ED_GIZMO_CAGE2D_PART_SCALE);
cage2d_draw_circle_wire(
gz->color, size_real, 0.5f * (margin[0] + margin[1]), gz->line_width);
}
else {
if (transform_flag & ED_GIZMO_CAGE_XFORM_FLAG_SCALE) {
int scale_parts[] = {
ED_GIZMO_CAGE2D_PART_SCALE_MIN_X,
ED_GIZMO_CAGE2D_PART_SCALE_MAX_X,
ED_GIZMO_CAGE2D_PART_SCALE_MIN_Y,
ED_GIZMO_CAGE2D_PART_SCALE_MAX_Y,
if (transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE) {
int scale_parts[] = {
ED_GIZMO_CAGE2D_PART_SCALE_MIN_X,
ED_GIZMO_CAGE2D_PART_SCALE_MAX_X,
ED_GIZMO_CAGE2D_PART_SCALE_MIN_Y,
ED_GIZMO_CAGE2D_PART_SCALE_MAX_Y,
ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MIN_Y,
ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MAX_Y,
ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MIN_Y,
ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MAX_Y,
};
for (int i = 0; i < ARRAY_SIZE(scale_parts); i++) {
GPU_select_load_id(select_id | scale_parts[i]);
cage2d_draw_box_interaction(
gz->color, scale_parts[i], size, margin, gz->line_width, true, draw_options);
ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MIN_Y,
ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MAX_Y,
ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MIN_Y,
ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MAX_Y,
};
for (int i = 0; i < ARRAY_SIZE(scale_parts); i++) {
GPU_select_load_id(select_id | scale_parts[i]);
cage2d_draw_box_interaction(
gz->color, scale_parts[i], size, margin, gz->line_width, true, draw_options);
}
}
if (transform_flag & ED_GIZMO_CAGE_XFORM_FLAG_TRANSLATE) {
const int transform_part = ED_GIZMO_CAGE2D_PART_TRANSLATE;
GPU_select_load_id(select_id | transform_part);
cage2d_draw_box_interaction(
gz->color, transform_part, size, margin, gz->line_width, true, draw_options);
}
if (transform_flag & ED_GIZMO_CAGE_XFORM_FLAG_ROTATE) {
cage2d_draw_box_interaction(gz->color,
ED_GIZMO_CAGE2D_PART_ROTATE,
size_real,
margin,
gz->line_width,
true,
draw_options);
}
}
if (transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE) {
const int transform_part = ED_GIZMO_CAGE2D_PART_TRANSLATE;
GPU_select_load_id(select_id | transform_part);
cage2d_draw_box_interaction(
gz->color, transform_part, size, margin, gz->line_width, true, draw_options);
}
if (transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_ROTATE) {
cage2d_draw_box_interaction(gz->color,
ED_GIZMO_CAGE2D_PART_ROTATE,
size_real,
margin,
gz->line_width,
true,
draw_options);
}
}
else {
@ -665,7 +694,7 @@ static void gizmo_cage2d_draw_intern(wmGizmo *gz,
if (gz->highlight_part == ED_GIZMO_CAGE2D_PART_TRANSLATE) {
/* Only show if we're drawing the center handle
* otherwise the entire rectangle is the hot-spot. */
if (draw_options & ED_GIZMO_CAGE2D_DRAW_FLAG_XFORM_CENTER_HANDLE) {
if (draw_options & ED_GIZMO_CAGE_DRAW_FLAG_XFORM_CENTER_HANDLE) {
show = true;
}
}
@ -678,7 +707,7 @@ static void gizmo_cage2d_draw_intern(wmGizmo *gz,
gz->color, gz->highlight_part, size_real, margin, gz->line_width, false, draw_options);
}
if (transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_ROTATE) {
if (transform_flag & ED_GIZMO_CAGE_XFORM_FLAG_ROTATE) {
cage2d_draw_box_interaction(gz->color,
ED_GIZMO_CAGE2D_PART_ROTATE,
size_real,
@ -688,25 +717,31 @@ static void gizmo_cage2d_draw_intern(wmGizmo *gz,
draw_options);
}
}
else if (draw_style == ED_GIZMO_CAGE2D_STYLE_CIRCLE) {
else {
float color[4], black[3] = {0, 0, 0};
gizmo_color_get(gz, highlight, color);
GPU_blend(GPU_BLEND_ALPHA);
float outline_line_width = gz->line_width + 3.0f;
cage2d_draw_circle_wire(&r, margin, black, transform_flag, draw_options, outline_line_width);
cage2d_draw_circle_wire(&r, margin, color, transform_flag, draw_options, gz->line_width);
/* corner gizmos */
cage2d_draw_circle_handles(&r, margin, color, transform_flag, true);
cage2d_draw_circle_handles(&r, margin, (const float[3]){0, 0, 0}, transform_flag, false);
if (draw_style == ED_GIZMO_CAGE2D_STYLE_RECTANGLE) {
cage2d_draw_rect_wire(&r, margin, black, transform_flag, draw_options, outline_line_width);
cage2d_draw_rect_wire(&r, margin, color, transform_flag, draw_options, gz->line_width);
/* corner gizmos */
cage2d_draw_rect_handles(&r, margin, color, transform_flag, true);
cage2d_draw_rect_handles(&r, margin, black, transform_flag, false);
}
else if (draw_style == ED_GIZMO_CAGE2D_STYLE_CIRCLE) {
cage2d_draw_circle_wire(black, size_real, 0.0f, outline_line_width);
cage2d_draw_circle_wire(color, size_real, 0.0f, gz->line_width);
}
else {
BLI_assert(0);
}
GPU_blend(GPU_BLEND_NONE);
}
else {
BLI_assert(0);
}
}
GPU_matrix_pop();
@ -781,9 +816,9 @@ static int gizmo_cage2d_test_select(bContext *C, wmGizmo *gz, const int mval[2])
const int transform_flag = RNA_enum_get(gz->ptr, "transform");
const int draw_options = RNA_enum_get(gz->ptr, "draw_options");
if (transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE) {
if (transform_flag & ED_GIZMO_CAGE_XFORM_FLAG_TRANSLATE) {
rctf r;
if (draw_options & ED_GIZMO_CAGE2D_DRAW_FLAG_XFORM_CENTER_HANDLE) {
if (draw_options & ED_GIZMO_CAGE_DRAW_FLAG_XFORM_CENTER_HANDLE) {
r.xmin = -margin[0] / 2;
r.ymin = -margin[1] / 2;
r.xmax = margin[0] / 2;
@ -802,8 +837,7 @@ static int gizmo_cage2d_test_select(bContext *C, wmGizmo *gz, const int mval[2])
}
/* if gizmo does not have a scale intersection, don't do it */
if (transform_flag &
(ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE | ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE_UNIFORM)) {
if (transform_flag & (ED_GIZMO_CAGE_XFORM_FLAG_SCALE | ED_GIZMO_CAGE_XFORM_FLAG_SCALE_UNIFORM)) {
const rctf r_xmin = {
.xmin = -size[0],
.ymin = -size[1],
@ -855,7 +889,7 @@ static int gizmo_cage2d_test_select(bContext *C, wmGizmo *gz, const int mval[2])
}
}
if (transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_ROTATE) {
if (transform_flag & ED_GIZMO_CAGE_XFORM_FLAG_ROTATE) {
/* Rotate:
* (*) <-- hot spot is here!
* +---+
@ -1056,7 +1090,7 @@ static int gizmo_cage2d_modal(bContext *C,
float pivot[2];
bool constrain_axis[2] = {false};
if (transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE) {
if (transform_flag & ED_GIZMO_CAGE_XFORM_FLAG_TRANSLATE) {
gizmo_rect_pivot_from_scale_part(gz->highlight_part, pivot, constrain_axis);
}
else {
@ -1082,7 +1116,7 @@ static int gizmo_cage2d_modal(bContext *C,
scale[i] = 1.0f + ((delta_curr[i] - delta_orig[i]) / len_v3(data->orig_matrix_offset[i]));
if ((transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE_SIGNED) == 0) {
if ((transform_flag & ED_GIZMO_CAGE_XFORM_FLAG_SCALE_SIGNED) == 0) {
if (sign != signum_i(scale[i])) {
scale[i] = 0.0f;
}
@ -1090,7 +1124,7 @@ static int gizmo_cage2d_modal(bContext *C,
}
}
if (transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE_UNIFORM) {
if (transform_flag & ED_GIZMO_CAGE_XFORM_FLAG_SCALE_UNIFORM) {
if (constrain_axis[0] == false && constrain_axis[1] == false) {
scale[1] = scale[0] = (scale[1] + scale[0]) / 2.0f;
}
@ -1189,22 +1223,19 @@ static void GIZMO_GT_cage_2d(wmGizmoType *gzt)
/* rna */
static EnumPropertyItem rna_enum_draw_style[] = {
{ED_GIZMO_CAGE2D_STYLE_BOX, "BOX", 0, "Box", ""},
{ED_GIZMO_CAGE2D_STYLE_RECTANGLE, "RECTANGLE", 0, "Rectangle", ""},
{ED_GIZMO_CAGE2D_STYLE_CIRCLE, "CIRCLE", 0, "Circle", ""},
{0, NULL, 0, NULL, NULL},
};
static EnumPropertyItem rna_enum_transform[] = {
{ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE, "TRANSLATE", 0, "Move", ""},
{ED_GIZMO_CAGE2D_XFORM_FLAG_ROTATE, "ROTATE", 0, "Rotate", ""},
{ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE, "SCALE", 0, "Scale", ""},
{ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE_UNIFORM, "SCALE_UNIFORM", 0, "Scale Uniform", ""},
{ED_GIZMO_CAGE_XFORM_FLAG_TRANSLATE, "TRANSLATE", 0, "Move", ""},
{ED_GIZMO_CAGE_XFORM_FLAG_ROTATE, "ROTATE", 0, "Rotate", ""},
{ED_GIZMO_CAGE_XFORM_FLAG_SCALE, "SCALE", 0, "Scale", ""},
{ED_GIZMO_CAGE_XFORM_FLAG_SCALE_UNIFORM, "SCALE_UNIFORM", 0, "Scale Uniform", ""},
{0, NULL, 0, NULL, NULL},
};
static EnumPropertyItem rna_enum_draw_options[] = {
{ED_GIZMO_CAGE2D_DRAW_FLAG_XFORM_CENTER_HANDLE,
"XFORM_CENTER_HANDLE",
0,
"Center Handle",
""},
{ED_GIZMO_CAGE_DRAW_FLAG_XFORM_CENTER_HANDLE, "XFORM_CENTER_HANDLE", 0, "Center Handle", ""},
{0, NULL, 0, NULL, NULL},
};
static float unit_v2[2] = {1.0f, 1.0f};
@ -1214,13 +1245,13 @@ static void GIZMO_GT_cage_2d(wmGizmoType *gzt)
RNA_def_enum(gzt->srna,
"draw_style",
rna_enum_draw_style,
ED_GIZMO_CAGE2D_STYLE_CIRCLE,
ED_GIZMO_CAGE2D_STYLE_RECTANGLE,
"Draw Style",
"");
RNA_def_enum_flag(gzt->srna,
"draw_options",
rna_enum_draw_options,
ED_GIZMO_CAGE2D_DRAW_FLAG_XFORM_CENTER_HANDLE,
ED_GIZMO_CAGE_DRAW_FLAG_XFORM_CENTER_HANDLE,
"Draw Options",
"");

View File

@ -6,9 +6,9 @@
*
* \name Cage Gizmo
*
* 2D Gizmo
* 3D Gizmo
*
* \brief Rectangular gizmo acting as a 'cage' around its content.
* \brief Cuboid gizmo acting as a 'cage' around its content.
* Interacting scales or translates the gizmo.
*/
@ -111,7 +111,7 @@ static void gizmo_rect_pivot_from_scale_part(int part, float r_pt[3], bool r_con
/* -------------------------------------------------------------------- */
/** \name Box Draw Style
*
* Useful for 3D views, see: #ED_GIZMO_CAGE2D_STYLE_BOX
* Useful for 3D views, see: #ED_GIZMO_CAGE3D_STYLE_BOX
* \{ */
static void cage3d_draw_box_corners(const float r[3],
@ -180,7 +180,7 @@ static void cage3d_draw_box_interaction(const RegionView3D *rv3d,
/* -------------------------------------------------------------------- */
/** \name Circle Draw Style
*
* Useful for 2D views, see: #ED_GIZMO_CAGE2D_STYLE_CIRCLE
* Useful for 2D views, see: #ED_GIZMO_CAGE3D_STYLE_CIRCLE
* \{ */
static void imm_draw_point_aspect_3d(uint pos, const float co[3], const float rad[3], bool solid)
@ -213,8 +213,8 @@ static void cage3d_draw_circle_wire(const float r[3],
imm_draw_cube_wire_3d(pos, (const float[3]){0}, r);
#if 0
if (transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE) {
if (draw_options & ED_GIZMO_CAGE2D_DRAW_FLAG_XFORM_CENTER_HANDLE) {
if (transform_flag & ED_GIZMO_CAGE_XFORM_FLAG_TRANSLATE) {
if (draw_options & ED_GIZMO_CAGE_DRAW_FLAG_XFORM_CENTER_HANDLE) {
const float rad[2] = {margin[0] / 2, margin[1] / 2};
const float center[2] = {0.0f, 0.0f};
@ -316,7 +316,7 @@ static void gizmo_cage3d_draw_intern(
const float size[3] = {UNPACK3(size_real)};
#endif
if (transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE) {
if (transform_flag & ED_GIZMO_CAGE_XFORM_FLAG_SCALE) {
for (int i = ED_GIZMO_CAGE3D_PART_SCALE_MIN_X_MIN_Y_MIN_Z;
i <= ED_GIZMO_CAGE3D_PART_SCALE_MAX_X_MAX_Y_MAX_Z;
i++) {
@ -327,7 +327,7 @@ static void gizmo_cage3d_draw_intern(
cage3d_draw_box_interaction(rv3d, matrix_final, gz->color, i, size, margin);
}
}
if (transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE) {
if (transform_flag & ED_GIZMO_CAGE_XFORM_FLAG_TRANSLATE) {
const int transform_part = ED_GIZMO_CAGE3D_PART_TRANSLATE;
GPU_select_load_id(select_id | transform_part);
cage3d_draw_box_interaction(rv3d, matrix_final, gz->color, transform_part, size, margin);
@ -342,7 +342,7 @@ static void gizmo_cage3d_draw_intern(
.ymax = size_real[1],
};
#endif
if (draw_style == ED_GIZMO_CAGE2D_STYLE_BOX) {
if (draw_style == ED_GIZMO_CAGE3D_STYLE_BOX) {
float color[4], black[3] = {0, 0, 0};
gizmo_color_get(gz, highlight, color);
@ -356,7 +356,7 @@ static void gizmo_cage3d_draw_intern(
if (gz->highlight_part == ED_GIZMO_CAGE3D_PART_TRANSLATE) {
/* Only show if we're drawing the center handle
* otherwise the entire rectangle is the hot-spot. */
if (draw_options & ED_GIZMO_CAGE2D_DRAW_FLAG_XFORM_CENTER_HANDLE) {
if (draw_options & ED_GIZMO_CAGE_DRAW_FLAG_XFORM_CENTER_HANDLE) {
show = true;
}
}
@ -369,7 +369,7 @@ static void gizmo_cage3d_draw_intern(
rv3d, matrix_final, gz->color, gz->highlight_part, size_real, margin);
}
}
else if (draw_style == ED_GIZMO_CAGE2D_STYLE_CIRCLE) {
else if (draw_style == ED_GIZMO_CAGE3D_STYLE_CIRCLE) {
float color[4], black[3] = {0, 0, 0};
gizmo_color_get(gz, highlight, color);
@ -515,7 +515,7 @@ static int gizmo_cage3d_modal(bContext *C,
float pivot[3];
bool constrain_axis[3] = {false};
if (transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE) {
if (transform_flag & ED_GIZMO_CAGE_XFORM_FLAG_TRANSLATE) {
gizmo_rect_pivot_from_scale_part(gz->highlight_part, pivot, constrain_axis);
}
else {
@ -542,7 +542,7 @@ static int gizmo_cage3d_modal(bContext *C,
scale[i] = 1.0f + ((delta_curr[i] - delta_orig[i]) / len_v3(data->orig_matrix_offset[i]));
if ((transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE_SIGNED) == 0) {
if ((transform_flag & ED_GIZMO_CAGE_XFORM_FLAG_SCALE_SIGNED) == 0) {
if (sign != signum_i(scale[i])) {
scale[i] = 0.0f;
}
@ -550,7 +550,7 @@ static int gizmo_cage3d_modal(bContext *C,
}
}
if (transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE_UNIFORM) {
if (transform_flag & ED_GIZMO_CAGE_XFORM_FLAG_SCALE_UNIFORM) {
if (constrain_axis[0] == false && constrain_axis[1] == false) {
scale[1] = scale[0] = (scale[1] + scale[0]) / 2.0f;
}
@ -647,22 +647,18 @@ static void GIZMO_GT_cage_3d(wmGizmoType *gzt)
/* rna */
static EnumPropertyItem rna_enum_draw_style[] = {
{ED_GIZMO_CAGE2D_STYLE_BOX, "BOX", 0, "Box", ""},
{ED_GIZMO_CAGE2D_STYLE_CIRCLE, "CIRCLE", 0, "Circle", ""},
{ED_GIZMO_CAGE3D_STYLE_BOX, "BOX", 0, "Box", ""},
{ED_GIZMO_CAGE3D_STYLE_CIRCLE, "CIRCLE", 0, "Circle", ""},
{0, NULL, 0, NULL, NULL},
};
static EnumPropertyItem rna_enum_transform[] = {
{ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE, "TRANSLATE", 0, "Move", ""},
{ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE, "SCALE", 0, "Scale", ""},
{ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE_UNIFORM, "SCALE_UNIFORM", 0, "Scale Uniform", ""},
{ED_GIZMO_CAGE_XFORM_FLAG_TRANSLATE, "TRANSLATE", 0, "Move", ""},
{ED_GIZMO_CAGE_XFORM_FLAG_SCALE, "SCALE", 0, "Scale", ""},
{ED_GIZMO_CAGE_XFORM_FLAG_SCALE_UNIFORM, "SCALE_UNIFORM", 0, "Scale Uniform", ""},
{0, NULL, 0, NULL, NULL},
};
static EnumPropertyItem rna_enum_draw_options[] = {
{ED_GIZMO_CAGE2D_DRAW_FLAG_XFORM_CENTER_HANDLE,
"XFORM_CENTER_HANDLE",
0,
"Center Handle",
""},
{ED_GIZMO_CAGE_DRAW_FLAG_XFORM_CENTER_HANDLE, "XFORM_CENTER_HANDLE", 0, "Center Handle", ""},
{0, NULL, 0, NULL, NULL},
};
static float unit_v3[3] = {1.0f, 1.0f, 1.0f};
@ -672,13 +668,13 @@ static void GIZMO_GT_cage_3d(wmGizmoType *gzt)
RNA_def_enum(gzt->srna,
"draw_style",
rna_enum_draw_style,
ED_GIZMO_CAGE2D_STYLE_CIRCLE,
ED_GIZMO_CAGE3D_STYLE_CIRCLE,
"Draw Style",
"");
RNA_def_enum_flag(gzt->srna,
"draw_options",
rna_enum_draw_options,
ED_GIZMO_CAGE2D_DRAW_FLAG_XFORM_CENTER_HANDLE,
ED_GIZMO_CAGE_DRAW_FLAG_XFORM_CENTER_HANDLE,
"Draw Options",
"");

View File

@ -97,40 +97,52 @@ void ED_gizmo_arrow3d_set_range_fac(struct wmGizmo *gz, float range_fac);
/* Cage Gizmo */
enum {
ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE = (1 << 0), /* Translates */
ED_GIZMO_CAGE2D_XFORM_FLAG_ROTATE = (1 << 1), /* Rotates */
ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE = (1 << 2), /* Scales */
ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE_UNIFORM = (1 << 3), /* Scales uniformly */
ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE_SIGNED = (1 << 4), /* Negative scale allowed */
ED_GIZMO_CAGE_XFORM_FLAG_TRANSLATE = (1 << 0), /* Translates */
ED_GIZMO_CAGE_XFORM_FLAG_ROTATE = (1 << 1), /* Rotates */
ED_GIZMO_CAGE_XFORM_FLAG_SCALE = (1 << 2), /* Scales */
ED_GIZMO_CAGE_XFORM_FLAG_SCALE_UNIFORM = (1 << 3), /* Scales uniformly */
ED_GIZMO_CAGE_XFORM_FLAG_SCALE_SIGNED = (1 << 4), /* Negative scale allowed */
};
/* draw_style */
enum {
/** Display the hover region (edge or corner) of the underlying rectangle. */
ED_GIZMO_CAGE2D_STYLE_BOX = 0,
ED_GIZMO_CAGE2D_STYLE_CIRCLE = 1,
/** Display a rectangular wire plus dots on four corners while hovering. */
ED_GIZMO_CAGE2D_STYLE_RECTANGLE,
/** Display a circular wire while hovering. */
ED_GIZMO_CAGE2D_STYLE_CIRCLE,
};
enum {
ED_GIZMO_CAGE3D_STYLE_BOX = 0,
ED_GIZMO_CAGE3D_STYLE_CIRCLE = 1,
};
/* draw_options */
enum {
/** Draw a central handle (instead of having the entire area selectable)
* Needed for large rectangles that we don't want to swallow all events. */
ED_GIZMO_CAGE2D_DRAW_FLAG_XFORM_CENTER_HANDLE = (1 << 0),
ED_GIZMO_CAGE_DRAW_FLAG_XFORM_CENTER_HANDLE = (1 << 0),
};
/** #wmGizmo.highlight_part */
enum {
ED_GIZMO_CAGE2D_PART_TRANSLATE = 0,
ED_GIZMO_CAGE2D_PART_SCALE_MIN_X = 1,
ED_GIZMO_CAGE2D_PART_SCALE_MAX_X = 2,
ED_GIZMO_CAGE2D_PART_SCALE_MIN_Y = 3,
ED_GIZMO_CAGE2D_PART_SCALE_MAX_Y = 4,
/* Corners */
ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MIN_Y = 5,
ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MAX_Y = 6,
ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MIN_Y = 7,
ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MAX_Y = 8,
ED_GIZMO_CAGE2D_PART_ROTATE = 9,
ED_GIZMO_CAGE2D_PART_SCALE,
/* Edges */
ED_GIZMO_CAGE2D_PART_SCALE_MIN_X,
ED_GIZMO_CAGE2D_PART_SCALE_MAX_X,
ED_GIZMO_CAGE2D_PART_SCALE_MIN_Y,
ED_GIZMO_CAGE2D_PART_SCALE_MAX_Y,
/* Corners */
ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MIN_Y,
ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MAX_Y,
ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MIN_Y,
ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MAX_Y,
ED_GIZMO_CAGE2D_PART_ROTATE,
};
/** #wmGizmo.highlight_part */

View File

@ -437,7 +437,13 @@ void paintvert_select_ungrouped(struct Object *ob, bool extend, bool flush_flags
*/
void paintvert_flush_flags(struct Object *ob);
void paintvert_tag_select_update(struct bContext *C, struct Object *ob);
/* Select vertices that are connected to already selected vertices. */
void paintvert_select_linked(struct bContext *C, struct Object *ob);
/* Select vertices that are linked to the vertex under the given region space coordinates. */
void paintvert_select_linked_pick(struct bContext *C,
struct Object *ob,
const int region_coordinates[2],
bool select);
void paintvert_hide(struct bContext *C, struct Object *ob, bool unselected);
void paintvert_reveal(struct bContext *C, struct Object *ob, bool select);

View File

@ -6,9 +6,11 @@
#include "MEM_guardedalloc.h"
#include "BLI_atomic_disjoint_set.hh"
#include "BLI_bitmap.h"
#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "BLI_task.hh"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
@ -536,6 +538,92 @@ void paintvert_flush_flags(Object *ob)
BKE_mesh_batch_cache_dirty_tag(me, BKE_MESH_BATCH_DIRTY_ALL);
}
static void paintvert_select_linked_vertices(bContext *C,
Object *ob,
const blender::Span<int> vertex_indices,
const bool select)
{
using namespace blender;
Mesh *mesh = BKE_mesh_from_object(ob);
if (mesh == nullptr || mesh->totpoly == 0) {
return;
}
/* AtomicDisjointSet is used to store connection information in vertex indices. */
AtomicDisjointSet islands(mesh->totvert);
const Span<MEdge> edges = mesh->edges();
/* By calling join() on the vertices of all edges, the AtomicDisjointSet contains information on
* which parts of the mesh are connected. */
threading::parallel_for(edges.index_range(), 1024, [&](const IndexRange range) {
for (const MEdge &edge : edges.slice(range)) {
islands.join(edge.v1, edge.v2);
}
});
bke::MutableAttributeAccessor attributes = mesh->attributes_for_write();
bke::SpanAttributeWriter<bool> select_vert = attributes.lookup_or_add_for_write_span<bool>(
".select_vert", ATTR_DOMAIN_POINT);
Set<int> selected_roots;
for (const int i : vertex_indices) {
const int root = islands.find_root(i);
selected_roots.add(root);
}
threading::parallel_for(select_vert.span.index_range(), 1024, [&](const IndexRange range) {
for (const int i : range) {
const int root = islands.find_root(i);
if (selected_roots.contains(root)) {
select_vert.span[i] = select;
}
}
});
select_vert.finish();
paintvert_flush_flags(ob);
paintvert_tag_select_update(C, ob);
}
void paintvert_select_linked_pick(bContext *C,
Object *ob,
const int region_coordinates[2],
const bool select)
{
uint index = uint(-1);
if (!ED_mesh_pick_vert(
C, ob, region_coordinates, ED_MESH_PICK_DEFAULT_VERT_DIST, true, &index)) {
return;
}
paintvert_select_linked_vertices(C, ob, {int(index)}, select);
}
void paintvert_select_linked(bContext *C, Object *ob)
{
Mesh *mesh = BKE_mesh_from_object(ob);
if (mesh == nullptr || mesh->totpoly == 0) {
return;
}
blender::bke::MutableAttributeAccessor attributes = mesh->attributes_for_write();
blender::bke::SpanAttributeWriter<bool> select_vert =
attributes.lookup_or_add_for_write_span<bool>(".select_vert", ATTR_DOMAIN_POINT);
blender::Vector<int> indices;
for (const int i : select_vert.span.index_range()) {
if (!select_vert.span[i]) {
continue;
}
indices.append(i);
}
select_vert.finish();
paintvert_select_linked_vertices(C, ob, indices, true);
}
void paintvert_tag_select_update(bContext *C, Object *ob)
{
DEG_id_tag_update(static_cast<ID *>(ob->data), ID_RECALC_COPY_ON_WRITE | ID_RECALC_SELECT);

View File

@ -245,8 +245,8 @@ static void gizmo_mesh_placement_setup(const bContext *C, wmGizmoGroup *gzgroup)
RNA_enum_set(ggd->cage->ptr,
"transform",
ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE | ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE |
ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE_SIGNED);
ED_GIZMO_CAGE_XFORM_FLAG_SCALE | ED_GIZMO_CAGE_XFORM_FLAG_TRANSLATE |
ED_GIZMO_CAGE_XFORM_FLAG_SCALE_SIGNED);
WM_gizmo_set_flag(ggd->cage, WM_GIZMO_DRAW_VALUE, true);

View File

@ -2048,7 +2048,7 @@ static int object_curves_random_add_exec(bContext *C, wmOperator *op)
Object *object = ED_object_add_type(C, OB_CURVES, nullptr, loc, rot, false, local_view_bits);
Curves *curves_id = static_cast<Curves *>(object->data);
bke::CurvesGeometry::wrap(curves_id->geometry) = ed::curves::primitive_random_sphere(500, 8);
curves_id->geometry.wrap() = ed::curves::primitive_random_sphere(500, 8);
return OPERATOR_FINISHED;
}
@ -3091,8 +3091,7 @@ static int object_convert_exec(bContext *C, wmOperator *op)
newob->data = new_curves;
newob->type = OB_CURVES;
blender::bke::CurvesGeometry::wrap(
new_curves->geometry) = blender::bke::CurvesGeometry::wrap(curves_eval->geometry);
new_curves->geometry.wrap() = curves_eval->geometry.wrap();
BKE_object_material_from_eval_data(bmain, newob, &curves_eval->id);
BKE_object_free_derived_caches(newob);
@ -3392,8 +3391,7 @@ static int object_convert_exec(bContext *C, wmOperator *op)
else if (const Curves *curves_eval = geometry.get_curves_for_read()) {
bke::AnonymousAttributePropagationInfo propagation_info;
propagation_info.propagate_all = false;
Mesh *mesh = bke::curve_to_wire_mesh(bke::CurvesGeometry::wrap(curves_eval->geometry),
propagation_info);
Mesh *mesh = bke::curve_to_wire_mesh(curves_eval->geometry.wrap(), propagation_info);
BKE_mesh_nomain_to_mesh(mesh, new_mesh, newob);
BKE_object_material_from_eval_data(bmain, newob, &curves_eval->id);
}

View File

@ -1075,13 +1075,10 @@ static bool modifier_apply_obdata(
Curves &curves_eval = *geometry_set.get_curves_for_write();
/* Anonymous attributes shouldn't be available on the applied geometry. */
blender::bke::CurvesGeometry::wrap(curves_eval.geometry)
.attributes_for_write()
.remove_anonymous();
curves_eval.geometry.wrap().attributes_for_write().remove_anonymous();
/* Copy the relevant information to the original. */
blender::bke::CurvesGeometry::wrap(curves.geometry) = std::move(
blender::bke::CurvesGeometry::wrap(curves_eval.geometry));
curves.geometry.wrap() = std::move(curves_eval.geometry.wrap());
Main *bmain = DEG_get_bmain(depsgraph);
BKE_object_material_from_eval_data(bmain, ob, &curves_eval.id);
}

View File

@ -944,8 +944,8 @@ static int apply_objects_internal(bContext *C,
}
else if (ob->type == OB_CURVES) {
Curves &curves = *static_cast<Curves *>(ob->data);
blender::bke::CurvesGeometry::wrap(curves.geometry).transform(mat);
blender::bke::CurvesGeometry::wrap(curves.geometry).calculate_bezier_auto_handles();
curves.geometry.wrap().transform(mat);
curves.geometry.wrap().calculate_bezier_auto_handles();
}
else if (ob->type == OB_POINTCLOUD) {
PointCloud &pointcloud = *static_cast<PointCloud *>(ob->data);
@ -1674,7 +1674,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
else if (ob->type == OB_CURVES) {
using namespace blender;
Curves &curves_id = *static_cast<Curves *>(ob->data);
bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id.geometry);
bke::CurvesGeometry &curves = curves_id.geometry.wrap();
if (ELEM(centermode, ORIGIN_TO_CENTER_OF_MASS_SURFACE, ORIGIN_TO_CENTER_OF_MASS_VOLUME) ||
!ELEM(around, V3D_AROUND_CENTER_BOUNDS, V3D_AROUND_CENTER_MEDIAN)) {
BKE_report(

View File

@ -117,7 +117,7 @@ struct AddOperationExecutor {
curves_ob_orig_ = CTX_data_active_object(&C);
curves_id_orig_ = static_cast<Curves *>(curves_ob_orig_->data);
curves_orig_ = &CurvesGeometry::wrap(curves_id_orig_->geometry);
curves_orig_ = &curves_id_orig_->geometry.wrap();
if (curves_id_orig_->surface == nullptr || curves_id_orig_->surface->type != OB_MESH) {
report_missing_surface(stroke_extension.reports);

View File

@ -177,7 +177,7 @@ std::optional<CurvesBrush3D> sample_curves_3d_brush(const Depsgraph &depsgraph,
const float brush_radius_re)
{
const Curves &curves_id = *static_cast<Curves *>(curves_object.data);
const CurvesGeometry &curves = CurvesGeometry::wrap(curves_id.geometry);
const CurvesGeometry &curves = curves_id.geometry.wrap();
Object *surface_object = curves_id.surface;
Object *surface_object_eval = DEG_get_evaluated_object(&depsgraph, surface_object);

View File

@ -117,7 +117,7 @@ struct CombOperationExecutor {
curves_ob_orig_ = CTX_data_active_object(&C);
curves_id_orig_ = static_cast<Curves *>(curves_ob_orig_->data);
curves_orig_ = &CurvesGeometry::wrap(curves_id_orig_->geometry);
curves_orig_ = &curves_id_orig_->geometry.wrap();
if (curves_orig_->curves_num() == 0) {
return;
}

View File

@ -94,7 +94,7 @@ struct DeleteOperationExecutor {
object_ = CTX_data_active_object(&C);
curves_id_ = static_cast<Curves *>(object_->data);
curves_ = &CurvesGeometry::wrap(curves_id_->geometry);
curves_ = &curves_id_->geometry.wrap();
selected_curve_indices_.clear();
curve_selection_ = curves::retrieve_selected_curves(*curves_id_, selected_curve_indices_);

View File

@ -102,7 +102,7 @@ struct DensityAddOperationExecutor {
self_ = &self;
curves_ob_orig_ = CTX_data_active_object(&C);
curves_id_orig_ = static_cast<Curves *>(curves_ob_orig_->data);
curves_orig_ = &CurvesGeometry::wrap(curves_id_orig_->geometry);
curves_orig_ = &curves_id_orig_->geometry.wrap();
if (stroke_extension.is_first) {
self_->original_curve_num_ = curves_orig_->curves_num();
@ -540,7 +540,7 @@ struct DensitySubtractOperationExecutor {
object_ = CTX_data_active_object(&C);
curves_id_ = static_cast<Curves *>(object_->data);
curves_ = &CurvesGeometry::wrap(curves_id_->geometry);
curves_ = &curves_id_->geometry.wrap();
if (curves_->curves_num() == 0) {
return;
}
@ -834,7 +834,7 @@ static bool use_add_density_mode(const BrushStrokeMode brush_mode,
if (surface_ob_eval == nullptr) {
return true;
}
const CurvesGeometry &curves = CurvesGeometry::wrap(curves_id_orig.geometry);
const CurvesGeometry &curves = curves_id_orig.geometry.wrap();
if (curves.curves_num() <= 1) {
return true;
}

View File

@ -278,7 +278,7 @@ struct CurvesEffectOperationExecutor {
object_ = CTX_data_active_object(&C);
curves_id_ = static_cast<Curves *>(object_->data);
curves_ = &CurvesGeometry::wrap(curves_id_->geometry);
curves_ = &curves_id_->geometry.wrap();
if (curves_->curves_num() == 0) {
return;
}

View File

@ -362,7 +362,7 @@ static int select_random_exec(bContext *C, wmOperator *op)
const auto next_bool_random_value = [&]() { return rng.get_float() <= probability; };
for (Curves *curves_id : unique_curves) {
CurvesGeometry &curves = CurvesGeometry::wrap(curves_id->geometry);
CurvesGeometry &curves = curves_id->geometry.wrap();
const bool was_anything_selected = curves::has_anything_selected(curves);
bke::SpanAttributeWriter<float> attribute = float_selection_ensure(*curves_id);
@ -581,7 +581,7 @@ static int select_grow_update(bContext *C, wmOperator *op, const float mouse_dif
for (std::unique_ptr<GrowOperatorDataPerCurve> &curve_op_data : op_data.per_curve) {
Curves &curves_id = *curve_op_data->curves_id;
CurvesGeometry &curves = CurvesGeometry::wrap(curves_id.geometry);
CurvesGeometry &curves = curves_id.geometry.wrap();
const float distance = curve_op_data->pixel_to_distance_factor * mouse_diff_x;
bke::SpanAttributeWriter<float> selection = float_selection_ensure(curves_id);
@ -629,7 +629,7 @@ static void select_grow_invoke_per_curve(const Curves &curves_id,
const RegionView3D &rv3d,
GrowOperatorDataPerCurve &curve_op_data)
{
const CurvesGeometry &curves = CurvesGeometry::wrap(curves_id.geometry);
const CurvesGeometry &curves = curves_id.geometry.wrap();
const Span<float3> positions = curves.positions();
if (const bke::GAttributeReader original_selection = curves.attributes().lookup(".selection")) {
@ -773,7 +773,7 @@ static int select_grow_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* Undo operator by resetting the selection to the original value. */
for (std::unique_ptr<GrowOperatorDataPerCurve> &curve_op_data : op_data.per_curve) {
Curves &curves_id = *curve_op_data->curves_id;
CurvesGeometry &curves = CurvesGeometry::wrap(curves_id.geometry);
CurvesGeometry &curves = curves_id.geometry.wrap();
bke::MutableAttributeAccessor attributes = curves.attributes_for_write();
attributes.remove(".selection");

View File

@ -90,7 +90,7 @@ struct PinchOperationExecutor {
object_ = CTX_data_active_object(&C);
curves_id_ = static_cast<Curves *>(object_->data);
curves_ = &CurvesGeometry::wrap(curves_id_->geometry);
curves_ = &curves_id_->geometry.wrap();
if (curves_->curves_num() == 0) {
return;
}

View File

@ -87,7 +87,7 @@ struct PuffOperationExecutor {
object_ = CTX_data_active_object(&C);
curves_id_ = static_cast<Curves *>(object_->data);
curves_ = &CurvesGeometry::wrap(curves_id_->geometry);
curves_ = &curves_id_->geometry.wrap();
if (curves_->curves_num() == 0) {
return;
}

View File

@ -13,7 +13,7 @@ namespace blender::ed::sculpt_paint {
bke::SpanAttributeWriter<float> float_selection_ensure(Curves &curves_id)
{
/* TODO: Use a generic attribute conversion utility instead of this function. */
bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id.geometry);
bke::CurvesGeometry &curves = curves_id.geometry.wrap();
bke::MutableAttributeAccessor attributes = curves.attributes_for_write();
if (const auto meta_data = attributes.lookup_meta_data(".selection")) {

View File

@ -83,7 +83,7 @@ struct SelectionPaintOperationExecutor {
object_ = CTX_data_active_object(&C);
curves_id_ = static_cast<Curves *>(object_->data);
curves_ = &CurvesGeometry::wrap(curves_id_->geometry);
curves_ = &curves_id_->geometry.wrap();
if (curves_->curves_num() == 0) {
return;
}

View File

@ -131,7 +131,7 @@ struct SlideOperationExecutor {
curves_ob_orig_ = CTX_data_active_object(&C);
curves_id_orig_ = static_cast<Curves *>(curves_ob_orig_->data);
curves_orig_ = &CurvesGeometry::wrap(curves_id_orig_->geometry);
curves_orig_ = &curves_id_orig_->geometry.wrap();
if (curves_id_orig_->surface == nullptr || curves_id_orig_->surface->type != OB_MESH) {
report_missing_surface(stroke_extension.reports);
return;

View File

@ -66,7 +66,7 @@ struct SmoothOperationExecutor {
object_ = CTX_data_active_object(&C);
curves_id_ = static_cast<Curves *>(object_->data);
curves_ = &CurvesGeometry::wrap(curves_id_->geometry);
curves_ = &curves_id_->geometry.wrap();
if (curves_->curves_num() == 0) {
return;
}

View File

@ -118,7 +118,7 @@ struct SnakeHookOperatorExecutor {
falloff_shape_ = static_cast<eBrushFalloffShape>(brush_->falloff_shape);
curves_id_ = static_cast<Curves *>(object_->data);
curves_ = &CurvesGeometry::wrap(curves_id_->geometry);
curves_ = &curves_id_->geometry.wrap();
if (curves_->curves_num() == 0) {
return;
}

View File

@ -383,6 +383,8 @@ void PAINT_OT_face_vert_reveal(struct wmOperatorType *ot);
void PAINT_OT_vert_select_all(struct wmOperatorType *ot);
void PAINT_OT_vert_select_ungrouped(struct wmOperatorType *ot);
void PAINT_OT_vert_select_hide(struct wmOperatorType *ot);
void PAINT_OT_vert_select_linked(struct wmOperatorType *ot);
void PAINT_OT_vert_select_linked_pick(struct wmOperatorType *ot);
bool vert_paint_poll(struct bContext *C);
bool mask_paint_poll(struct bContext *C);

View File

@ -1457,6 +1457,8 @@ void ED_operatortypes_paint(void)
WM_operatortype_append(PAINT_OT_vert_select_all);
WM_operatortype_append(PAINT_OT_vert_select_ungrouped);
WM_operatortype_append(PAINT_OT_vert_select_hide);
WM_operatortype_append(PAINT_OT_vert_select_linked);
WM_operatortype_append(PAINT_OT_vert_select_linked_pick);
/* vertex */
WM_operatortype_append(PAINT_OT_vertex_paint_toggle);

View File

@ -733,6 +733,53 @@ void PAINT_OT_vert_select_ungrouped(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
}
static int paintvert_select_linked_exec(bContext *C, wmOperator *UNUSED(op))
{
paintvert_select_linked(C, CTX_data_active_object(C));
ED_region_tag_redraw(CTX_wm_region(C));
return OPERATOR_FINISHED;
}
void PAINT_OT_vert_select_linked(wmOperatorType *ot)
{
ot->name = "Select Linked Vertices";
ot->description = "Select linked vertices";
ot->idname = "PAINT_OT_vert_select_linked";
ot->exec = paintvert_select_linked_exec;
ot->poll = vert_paint_poll;
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int paintvert_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
const bool select = RNA_boolean_get(op->ptr, "select");
view3d_operator_needs_opengl(C);
paintvert_select_linked_pick(C, CTX_data_active_object(C), event->mval, select);
ED_region_tag_redraw(CTX_wm_region(C));
return OPERATOR_FINISHED;
}
void PAINT_OT_vert_select_linked_pick(wmOperatorType *ot)
{
ot->name = "Select Linked Vertices Pick";
ot->description = "Select linked vertices under the cursor";
ot->idname = "PAINT_OT_vert_select_linked_pick";
ot->invoke = paintvert_select_linked_pick_invoke;
ot->poll = vert_paint_poll;
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
RNA_def_boolean(ot->srna,
"select",
true,
"Select",
"Whether to select or deselect linked vertices under the cursor");
}
static int face_select_hide_exec(bContext *C, wmOperator *op)
{
const bool unselected = RNA_boolean_get(op->ptr, "unselected");

View File

@ -517,11 +517,12 @@ static bool mask_expand_normal_floodfill_cb(
static float *sculpt_expand_normal_falloff_create(Sculpt *sd,
Object *ob,
const PBVHVertRef v,
const float edge_sensitivity)
const float edge_sensitivity,
const int blur_steps)
{
SculptSession *ss = ob->sculpt;
const int totvert = SCULPT_vertex_count_get(ss);
float *dists = static_cast<float *>(MEM_malloc_arrayN(totvert, sizeof(float), __func__));
float *dists = static_cast<float *>(MEM_calloc_arrayN(totvert, sizeof(float), __func__));
float *edge_factor = static_cast<float *>(MEM_callocN(sizeof(float) * totvert, __func__));
for (int i = 0; i < totvert; i++) {
edge_factor[i] = 1.0f;
@ -540,7 +541,7 @@ static float *sculpt_expand_normal_falloff_create(Sculpt *sd,
SCULPT_floodfill_execute(ss, &flood, mask_expand_normal_floodfill_cb, &fdata);
SCULPT_floodfill_free(&flood);
for (int repeat = 0; repeat < 2; repeat++) {
for (int repeat = 0; repeat < blur_steps; repeat++) {
for (int i = 0; i < totvert; i++) {
PBVHVertRef vertex = BKE_pbvh_index_to_vertex(ss->pbvh, i);
@ -550,10 +551,17 @@ static float *sculpt_expand_normal_falloff_create(Sculpt *sd,
avg += dists[ni.index];
}
SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
dists[i] = avg / ni.size;
if (ni.size > 0.0f) {
dists[i] = avg / ni.size;
}
}
}
for (int i = 0; i < totvert; i++) {
dists[i] = 1.0 - dists[i];
}
MEM_SAFE_FREE(edge_factor);
return dists;
@ -1049,7 +1057,11 @@ static void sculpt_expand_falloff_factors_from_vertex_and_symm_create(
break;
case SCULPT_EXPAND_FALLOFF_NORMALS:
expand_cache->vert_falloff = sculpt_expand_normal_falloff_create(
sd, ob, v, SCULPT_EXPAND_NORMALS_FALLOFF_EDGE_SENSITIVITY);
sd,
ob,
v,
SCULPT_EXPAND_NORMALS_FALLOFF_EDGE_SENSITIVITY,
expand_cache->normal_falloff_blur_steps);
break;
case SCULPT_EXPAND_FALLOFF_SPHERICAL:
expand_cache->vert_falloff = sculpt_expand_spherical_falloff_create(ob, v);
@ -2066,6 +2078,7 @@ static void sculpt_expand_cache_initial_config_set(bContext *C,
ExpandCache *expand_cache)
{
/* RNA properties. */
expand_cache->normal_falloff_blur_steps = RNA_int_get(op->ptr, "normal_falloff_smooth");
expand_cache->invert = RNA_boolean_get(op->ptr, "invert");
expand_cache->preserve = RNA_boolean_get(op->ptr, "use_mask_preserve");
expand_cache->auto_mask = RNA_boolean_get(op->ptr, "use_auto_mask");
@ -2415,4 +2428,13 @@ void SCULPT_OT_expand(wmOperatorType *ot)
false,
"Auto Create",
"Fill in mask if nothing is already masked");
ot->prop = RNA_def_int(ot->srna,
"normal_falloff_smooth",
2,
0,
10,
"Normal Smooth",
"Blurring steps for normal falloff",
0,
10);
}

View File

@ -1303,8 +1303,8 @@ static bool sculpt_face_set_edit_is_operation_valid(SculptSession *ss,
if (mode == SCULPT_FACE_SET_EDIT_DELETE_GEOMETRY) {
if (BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS) {
/* Modification of base mesh geometry requires special remapping of multires displacement,
* which does not happen here.
/* Modification of base mesh geometry requires special remapping of multi-resolution
* displacement, which does not happen here.
* Disable delete operation. It can be supported in the future by doing similar displacement
* data remapping as what happens in the mesh edit mode. */
return false;
@ -1318,9 +1318,9 @@ static bool sculpt_face_set_edit_is_operation_valid(SculptSession *ss,
if (ELEM(mode, SCULPT_FACE_SET_EDIT_FAIR_POSITIONS, SCULPT_FACE_SET_EDIT_FAIR_TANGENCY)) {
if (BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS) {
/* TODO: Multires topology representation using grids and duplicates can't be used directly
* by the fair algorithm. Multires topology needs to be exposed in a different way or
* converted to a mesh for this operation. */
/* TODO: Multi-resolution topology representation using grids and duplicates can't be used
* directly by the fair algorithm. Multi-resolution topology needs to be exposed in a
* different way or converted to a mesh for this operation. */
return false;
}
}

View File

@ -822,6 +822,7 @@ typedef struct ExpandCache {
float (*original_colors)[4];
bool check_islands;
int normal_falloff_blur_steps;
} ExpandCache;
/** \} */

View File

@ -2984,7 +2984,7 @@ static int filelist_readjob_list_dir(FileListReadJob *job_params,
entry->relpath = current_relpath_append(job_params, files[i].relname);
entry->st = files[i].s;
BLI_path_join(full_path, FILE_MAX, root, entry->relpath);
BLI_path_join(full_path, FILE_MAX, root, files[i].relname);
char *target = full_path;
/* Set initial file type and attributes. */

View File

@ -389,10 +389,7 @@ static bool draw_fcurve_handles_check(SpaceGraph *sipo, FCurve *fcu)
(fcu->flag & FCURVE_INT_VALUES) ||
#endif
/* group that curve belongs to is not editable */
((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED)) ||
/* Do not show handles if there is only 1 keyframe,
* otherwise they all clump together in an ugly ball. */
(fcu->totvert <= 1)) {
((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED))) {
return false;
}
return true;
@ -707,7 +704,7 @@ static void draw_fcurve_curve_samples(bAnimContext *ac,
const uint shdr_pos,
const bool draw_extrapolation)
{
if (!draw_extrapolation && fcu->totvert == 1) {
if (!draw_extrapolation) {
return;
}
@ -820,7 +817,7 @@ static bool fcurve_can_use_simple_bezt_drawing(FCurve *fcu)
static void draw_fcurve_curve_bezts(
bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d, uint pos, const bool draw_extrapolation)
{
if (!draw_extrapolation && fcu->totvert == 1) {
if (!draw_extrapolation) {
return;
}
@ -852,7 +849,7 @@ static void draw_fcurve_curve_bezts(
/* y-value depends on the interpolation */
if ((fcu->extend == FCURVE_EXTRAPOLATE_CONSTANT) || (prevbezt->ipo == BEZT_IPO_CONST) ||
(fcu->totvert == 1)) {
(prevbezt->ipo == BEZT_IPO_LIN && fcu->totvert == 1)) {
/* just extend across the first keyframe's value */
v1[1] = prevbezt->vec[1][1];
}
@ -971,7 +968,8 @@ static void draw_fcurve_curve_bezts(
/* y-value depends on the interpolation */
if ((fcu->extend == FCURVE_EXTRAPOLATE_CONSTANT) || (fcu->flag & FCURVE_INT_VALUES) ||
(prevbezt->ipo == BEZT_IPO_CONST) || (fcu->totvert == 1)) {
(prevbezt->ipo == BEZT_IPO_CONST) ||
(prevbezt->ipo == BEZT_IPO_LIN && fcu->totvert == 1)) {
/* based on last keyframe's value */
v1[1] = prevbezt->vec[1][1];
}

View File

@ -210,8 +210,8 @@ static void get_nearest_fcurve_verts_list(bAnimContext *ac, const int mval[2], L
unit_scale,
offset);
/* handles - only do them if they're visible */
if (fcurve_handle_sel_check(sipo, bezt1) && (fcu->totvert > 1)) {
/* Handles. */
if (fcurve_handle_sel_check(sipo, bezt1)) {
/* first handle only visible if previous segment had handles */
if ((!prevbezt && (bezt1->ipo == BEZT_IPO_BEZ)) ||
(prevbezt && (prevbezt->ipo == BEZT_IPO_BEZ))) {

View File

@ -117,7 +117,7 @@ static void WIDGETGROUP_node_transform_setup(const bContext * /*C*/, wmGizmoGrou
RNA_enum_set(wwrapper->gizmo->ptr,
"transform",
ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE | ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE_UNIFORM);
ED_GIZMO_CAGE_XFORM_FLAG_TRANSLATE | ED_GIZMO_CAGE_XFORM_FLAG_SCALE_UNIFORM);
gzgroup->customdata = wwrapper;
}
@ -323,7 +323,7 @@ static void WIDGETGROUP_node_crop_setup(const bContext * /*C*/, wmGizmoGroup *gz
RNA_enum_set(crop_group->border->ptr,
"transform",
ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE | ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE);
ED_GIZMO_CAGE_XFORM_FLAG_TRANSLATE | ED_GIZMO_CAGE_XFORM_FLAG_SCALE);
gzgroup->customdata = crop_group;
}

View File

@ -3594,7 +3594,7 @@ static int sequencer_scene_frame_range_update_exec(bContext *C, wmOperator *UNUS
static bool sequencer_scene_frame_range_update_poll(bContext *C)
{
Editing *ed = SEQ_editing_get(CTX_data_scene(C));
return (ed->act_seq != NULL && (ed->act_seq->type & SEQ_TYPE_SCENE) != 0);
return (ed != NULL && ed->act_seq != NULL && (ed->act_seq->type & SEQ_TYPE_SCENE) != 0);
}
void SEQUENCER_OT_scene_frame_range_update(wmOperatorType *ot)

View File

@ -413,7 +413,7 @@ static void WIDGETGROUP_camera_view_setup(const bContext *UNUSED(C), wmGizmoGrou
RNA_enum_set(viewgroup->border->ptr,
"transform",
ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE | ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE);
ED_GIZMO_CAGE_XFORM_FLAG_TRANSLATE | ED_GIZMO_CAGE_XFORM_FLAG_SCALE);
/* Box style is more subtle in this case. */
RNA_enum_set(viewgroup->border->ptr, "draw_style", ED_GIZMO_CAGE2D_STYLE_BOX);
@ -470,7 +470,7 @@ static void WIDGETGROUP_camera_view_refresh(const bContext *C, wmGizmoGroup *gzg
RNA_enum_set(viewgroup->border->ptr,
"transform",
ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE | ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE);
ED_GIZMO_CAGE_XFORM_FLAG_TRANSLATE | ED_GIZMO_CAGE_XFORM_FLAG_SCALE);
if (rv3d->persp == RV3D_CAMOB) {
viewgroup->state.edit_border = &scene->r.border;

View File

@ -120,7 +120,7 @@ static void WIDGETGROUP_empty_image_setup(const bContext *UNUSED(C), wmGizmoGrou
__func__);
igzgroup->gizmo = WM_gizmo_new("GIZMO_GT_cage_2d", gzgroup, NULL);
wmGizmo *gz = igzgroup->gizmo;
RNA_enum_set(gz->ptr, "transform", ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE);
RNA_enum_set(gz->ptr, "transform", ED_GIZMO_CAGE_XFORM_FLAG_SCALE);
gzgroup->customdata = igzgroup;
@ -143,8 +143,8 @@ static void WIDGETGROUP_empty_image_refresh(const bContext *C, wmGizmoGroup *gzg
RNA_enum_set(gz->ptr,
"transform",
ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE | ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE |
ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE_UNIFORM);
ED_GIZMO_CAGE_XFORM_FLAG_TRANSLATE | ED_GIZMO_CAGE_XFORM_FLAG_SCALE |
ED_GIZMO_CAGE_XFORM_FLAG_SCALE_UNIFORM);
igzgroup->state.ob = ob;

View File

@ -179,7 +179,7 @@ static void WIDGETGROUP_light_area_setup(const bContext *UNUSED(C), wmGizmoGroup
wmGizmoWrapper *wwrapper = MEM_mallocN(sizeof(wmGizmoWrapper), __func__);
wwrapper->gizmo = WM_gizmo_new("GIZMO_GT_cage_2d", gzgroup, NULL);
wmGizmo *gz = wwrapper->gizmo;
RNA_enum_set(gz->ptr, "transform", ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE);
RNA_enum_set(gz->ptr, "transform", ED_GIZMO_CAGE_XFORM_FLAG_SCALE);
gzgroup->customdata = wwrapper;
@ -201,9 +201,9 @@ static void WIDGETGROUP_light_area_refresh(const bContext *C, wmGizmoGroup *gzgr
copy_m4_m4(gz->matrix_basis, ob->object_to_world);
int flag = ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE;
int flag = ED_GIZMO_CAGE_XFORM_FLAG_SCALE;
if (ELEM(la->area_shape, LA_AREA_SQUARE, LA_AREA_DISK)) {
flag |= ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE_UNIFORM;
flag |= ED_GIZMO_CAGE_XFORM_FLAG_SCALE_UNIFORM;
}
RNA_enum_set(gz->ptr, "transform", flag);

View File

@ -33,7 +33,7 @@ static void createTransCurvesVerts(bContext * /*C*/, TransInfo *t)
for (const int i : trans_data_contrainers.index_range()) {
TransDataContainer &tc = trans_data_contrainers[i];
Curves *curves_id = static_cast<Curves *>(tc.obedit->data);
bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id->geometry);
bke::CurvesGeometry &curves = curves_id->geometry.wrap();
selection_per_object[i] = ed::curves::retrieve_selected_points(curves,
selected_indices_per_object[i]);
@ -51,7 +51,7 @@ static void createTransCurvesVerts(bContext * /*C*/, TransInfo *t)
continue;
}
Curves *curves_id = static_cast<Curves *>(tc.obedit->data);
bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id->geometry);
bke::CurvesGeometry &curves = curves_id->geometry.wrap();
IndexMask selected_indices = selection_per_object[i];
float mtx[3][3], smtx[3][3];
@ -82,7 +82,7 @@ static void recalcData_curves(TransInfo *t)
Span<TransDataContainer> trans_data_contrainers(t->data_container, t->data_container_len);
for (const TransDataContainer &tc : trans_data_contrainers) {
Curves *curves_id = static_cast<Curves *>(tc.obedit->data);
bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id->geometry);
bke::CurvesGeometry &curves = curves_id->geometry.wrap();
curves.calculate_bezier_auto_handles();
curves.tag_positions_changed();

View File

@ -210,8 +210,8 @@ static GizmoGroup2D *gizmogroup2d_init(wmGizmoGroup *gzgroup)
RNA_enum_set(ggd->cage->ptr,
"transform",
ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE | ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE |
ED_GIZMO_CAGE2D_XFORM_FLAG_ROTATE);
ED_GIZMO_CAGE_XFORM_FLAG_TRANSLATE | ED_GIZMO_CAGE_XFORM_FLAG_SCALE |
ED_GIZMO_CAGE_XFORM_FLAG_ROTATE);
return ggd;
}

View File

@ -2159,9 +2159,8 @@ static void WIDGETGROUP_xform_cage_setup(const bContext *UNUSED(C), wmGizmoGroup
xgzgroup->gizmo = WM_gizmo_new_ptr(gzt_cage, gzgroup, NULL);
wmGizmo *gz = xgzgroup->gizmo;
RNA_enum_set(gz->ptr,
"transform",
ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE | ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE);
RNA_enum_set(
gz->ptr, "transform", ED_GIZMO_CAGE_XFORM_FLAG_SCALE | ED_GIZMO_CAGE_XFORM_FLAG_TRANSLATE);
gz->color[0] = 1;
gz->color_hi[0] = 1;

View File

@ -159,12 +159,14 @@ VolumeGrid *volume_grid_add_from_mesh(Volume *volume,
interior_band_width,
density);
/* Merge the generated grid. Should be cheap because grid has just been created. */
grid->merge(*mesh_grid);
if (mesh_grid != nullptr) {
/* Merge the generated grid. Should be cheap because grid has just been created. */
grid->merge(*mesh_grid);
/* Change transform so that the index space is correctly transformed to object space. */
grid->transform().postScale(voxel_size);
}
/* Set class to "Fog Volume". */
grid->setGridClass(openvdb::GRID_FOG_VOLUME);
/* Change transform so that the index space is correctly transformed to object space. */
grid->transform().postScale(voxel_size);
return c_grid;
}
} // namespace blender::geometry

View File

@ -1197,7 +1197,7 @@ static AllCurvesInfo preprocess_curves(const GeometrySet &geometry_set,
for (const int curve_index : info.realize_info.index_range()) {
RealizeCurveInfo &curve_info = info.realize_info[curve_index];
const Curves *curves_id = info.order[curve_index];
const bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id->geometry);
const bke::CurvesGeometry &curves = curves_id->geometry.wrap();
curve_info.curves = curves_id;
/* Access attributes. */
@ -1258,7 +1258,7 @@ static void execute_realize_curve_task(const RealizeInstancesOptions &options,
{
const RealizeCurveInfo &curves_info = *task.curve_info;
const Curves &curves_id = *curves_info.curves;
const bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id.geometry);
const bke::CurvesGeometry &curves = curves_id.geometry.wrap();
const IndexRange dst_point_range{task.start_indices.point, curves.points_num()};
const IndexRange dst_curve_range{task.start_indices.curve, curves.curves_num()};
@ -1347,7 +1347,7 @@ static void execute_realize_curve_tasks(const RealizeInstancesOptions &options,
/* Allocate new curves data-block. */
Curves *dst_curves_id = bke::curves_new_nomain(points_num, curves_num);
bke::CurvesGeometry &dst_curves = bke::CurvesGeometry::wrap(dst_curves_id->geometry);
bke::CurvesGeometry &dst_curves = dst_curves_id->geometry.wrap();
dst_curves.offsets_for_write().last() = points_num;
CurveComponent &dst_component = r_realized_geometry.get_component_for_write<CurveComponent>();
dst_component.replace(dst_curves_id);

View File

@ -260,6 +260,7 @@ static void empty_panel_draw(const bContext *UNUSED(C), Panel *panel)
static void random_panel_draw(const bContext *UNUSED(C), Panel *panel)
{
uiLayout *layout = panel->layout;
uiLayout *col;
PointerRNA *ptr = gpencil_modifier_panel_get_property_pointers(panel, NULL);
int mode = RNA_enum_get(ptr, "mode");
@ -270,22 +271,24 @@ static void random_panel_draw(const bContext *UNUSED(C), Panel *panel)
uiItemR(layout, ptr, "random_offset", 0, IFACE_("Offset"), ICON_NONE);
uiItemR(layout, ptr, "random_rotation", 0, IFACE_("Rotation"), ICON_NONE);
uiItemR(layout, ptr, "random_scale", 0, IFACE_("Scale"), ICON_NONE);
col = uiLayoutColumn(layout, true);
switch (mode) {
case GP_OFFSET_RANDOM:
uiItemR(layout, ptr, "use_uniform_random_scale", 0, NULL, ICON_NONE);
uiItemR(layout, ptr, "seed", 0, NULL, ICON_NONE);
break;
case GP_OFFSET_STROKE:
uiItemR(layout, ptr, "stroke_step", 0, IFACE_("Stroke Step"), ICON_NONE);
uiItemR(layout, ptr, "stroke_start_offset", 0, IFACE_("Offset"), ICON_NONE);
uiItemR(col, ptr, "stroke_step", 0, IFACE_("Stroke Step"), ICON_NONE);
uiItemR(col, ptr, "stroke_start_offset", 0, IFACE_("Offset"), ICON_NONE);
break;
case GP_OFFSET_MATERIAL:
uiItemR(layout, ptr, "stroke_step", 0, IFACE_("Material Step"), ICON_NONE);
uiItemR(layout, ptr, "stroke_start_offset", 0, IFACE_("Offset"), ICON_NONE);
uiItemR(col, ptr, "stroke_step", 0, IFACE_("Material Step"), ICON_NONE);
uiItemR(col, ptr, "stroke_start_offset", 0, IFACE_("Offset"), ICON_NONE);
break;
case GP_OFFSET_LAYER:
uiItemR(layout, ptr, "stroke_step", 0, IFACE_("Layer Step"), ICON_NONE);
uiItemR(layout, ptr, "stroke_start_offset", 0, IFACE_("Offset"), ICON_NONE);
uiItemR(col, ptr, "stroke_step", 0, IFACE_("Layer Step"), ICON_NONE);
uiItemR(col, ptr, "stroke_start_offset", 0, IFACE_("Offset"), ICON_NONE);
break;
}
gpencil_modifier_panel_end(layout, ptr);

View File

@ -72,6 +72,8 @@ void imm_draw_circle_fill_aspect_2d(
* Use this version when #GPUVertFormat has a vec3 position.
*/
void imm_draw_circle_wire_3d(uint pos, float x, float y, float radius, int nsegments);
void imm_draw_circle_wire_aspect_3d(
uint pos, float x, float y, float radius_x, float radius_y, int nsegments);
void imm_draw_circle_dashed_3d(uint pos, float x, float y, float radius, int nsegments);
void imm_draw_circle_fill_3d(uint pos, float x, float y, float radius, int nsegments);

View File

@ -179,6 +179,7 @@ void imm_draw_circle_wire_aspect_2d(
{
imm_draw_circle(GPU_PRIM_LINE_LOOP, shdr_pos, x, y, radius_x, radius_y, nsegments);
}
void imm_draw_circle_fill_aspect_2d(
uint shdr_pos, float x, float y, float radius_x, float radius_y, int nsegments)
{
@ -329,19 +330,24 @@ void imm_draw_disk_partial_fill_3d(uint pos,
GPU_PRIM_TRI_STRIP, pos, x, y, z, rad_inner, rad_outer, nsegments, start, sweep);
}
static void imm_draw_circle_3D(
GPUPrimType prim_type, uint pos, float x, float y, float radius, int nsegments)
static void imm_draw_circle_3D(GPUPrimType prim_type,
uint pos,
float x,
float y,
float radius_x,
float radius_y,
int nsegments)
{
if (prim_type == GPU_PRIM_LINE_LOOP) {
/* NOTE(Metal/AMD): For small primitives, line list more efficient than line strip. */
immBegin(GPU_PRIM_LINES, nsegments * 2);
const float angle = (float)(2 * M_PI) / (float)nsegments;
float xprev = cosf(-angle) * radius;
float yprev = sinf(-angle) * radius;
float xprev = cosf(-angle) * radius_x;
float yprev = sinf(-angle) * radius_y;
const float alpha = 2.0f * cosf(angle);
float xr = radius;
float xr = radius_x;
float yr = 0;
for (int i = 0; i < nsegments; i++) {
@ -349,21 +355,23 @@ static void imm_draw_circle_3D(
if (i) {
immVertex3f(pos, x + xr, y + yr, 0.0f);
}
/* cos[(n + 1)a] = 2cos(a)cos(na) - cos[(n - 1)a]. */
const float xnext = alpha * xr - xprev;
/* sin[(n + 1)a] = 2cos(a)sin(na) - sin[(n - 1)a]. */
const float ynext = alpha * yr - yprev;
xprev = xr;
yprev = yr;
xr = xnext;
yr = ynext;
}
immVertex3f(pos, x + radius, y, 0.0f);
immVertex3f(pos, x + radius_x, y, 0.0f);
immEnd();
}
else {
immBegin(prim_type, nsegments);
for (int i = 0; i < nsegments; i++) {
float angle = (float)(2 * M_PI) * ((float)i / (float)nsegments);
immVertex3f(pos, x + radius * cosf(angle), y + radius * sinf(angle), 0.0f);
immVertex3f(pos, x + radius_x * cosf(angle), y + radius_y * sinf(angle), 0.0f);
}
immEnd();
}
@ -371,17 +379,23 @@ static void imm_draw_circle_3D(
void imm_draw_circle_wire_3d(uint pos, float x, float y, float radius, int nsegments)
{
imm_draw_circle_3D(GPU_PRIM_LINE_LOOP, pos, x, y, radius, nsegments);
imm_draw_circle_3D(GPU_PRIM_LINE_LOOP, pos, x, y, radius, radius, nsegments);
}
void imm_draw_circle_wire_aspect_3d(
uint shdr_pos, float x, float y, float radius_x, float radius_y, int nsegments)
{
imm_draw_circle_3D(GPU_PRIM_LINE_LOOP, shdr_pos, x, y, radius_x, radius_y, nsegments);
}
void imm_draw_circle_dashed_3d(uint pos, float x, float y, float radius, int nsegments)
{
imm_draw_circle_3D(GPU_PRIM_LINES, pos, x, y, radius, nsegments / 2);
imm_draw_circle_3D(GPU_PRIM_LINES, pos, x, y, radius, radius, nsegments / 2);
}
void imm_draw_circle_fill_3d(uint pos, float x, float y, float radius, int nsegments)
{
imm_draw_circle_3D(GPU_PRIM_TRI_FAN, pos, x, y, radius, nsegments);
imm_draw_circle_3D(GPU_PRIM_TRI_FAN, pos, x, y, radius, radius, nsegments);
}
void imm_draw_box_wire_2d(uint pos, float x1, float y1, float x2, float y2)

View File

@ -68,7 +68,6 @@ class ShaderInterface {
public:
ShaderInterface();
ShaderInterface(const shader::ShaderCreateInfo &info);
virtual ~ShaderInterface();
void debug_print();

View File

@ -1202,7 +1202,7 @@ bool MTLContext::ensure_uniform_buffer_bindings(
BLI_assert(buffer_index >= 0 && buffer_index < MTL_MAX_BUFFER_BINDINGS);
/* For compute, we must always re-bind the push constant block as other compute
* operations may have assigned reources over the top, outside of the compiled
* operations may have assigned resources over the top, outside of the compiled
* compute shader path. */
/* Bind push constant data. */
BLI_assert(this->pipeline_state.active_shader->get_push_constant_data() != nullptr);

View File

@ -309,7 +309,7 @@ class MTLSafeFreeList {
* Performs a lockless list insert. */
void insert_buffer(gpu::MTLBuffer *buffer);
/* Whether we need ot start a new safe free list, or can carry on using the existing one. */
/* Whether we need to start a new safe free list, or can carry on using the existing one. */
bool should_flush();
/* Increments command buffer reference count. */

View File

@ -225,7 +225,7 @@ static void extract_and_replace_clipping_distances(std::string &vertex_source,
continue;
}
/* Extract ID betwen zero and 9. */
/* Extract ID between zero and 9. */
if ((*c >= '0') && (*c <= '9')) {
char clip_distance_id = ((*c) - '0');
auto found = std::find(
@ -314,9 +314,9 @@ static void replace_matrix_constructors(std::string &str)
/* Replace matrix constructors with GLSL-compatible constructors for Metal.
* Base matrix constructors e.g. mat3x3 do not have as many overload variants as GLSL.
* To add compatibility, we declare custom constuctors e.g. MAT3x3 in mtl_shader_defines.msl.
* To add compatibility, we declare custom constructors e.g. MAT3x3 in `mtl_shader_defines.msl`.
* If the GLSL syntax matches, we map mat3x3(..) -> MAT3x3(..) and implement a custom
* constructor. This supports both mat3(..) and mat3x3(..) style sytax.*/
* constructor. This supports both mat3(..) and mat3x3(..) style syntax. */
char *current_str_begin = &*str.begin();
char *current_str_end = &*str.end();
@ -335,7 +335,7 @@ static void replace_matrix_constructors(std::string &str)
continue;
}
/* Possible multiple dimensional matrix constructor. Verify if next char is a dim*/
/* Possible multiple dimensional matrix constructor. Verify if next char is a dim. */
c++;
if (*c == 'x') {
c++;
@ -601,7 +601,7 @@ void extract_shared_memory_blocks(MSLGeneratorInterface &msl_iface,
new_shared_block.type_name = std::string(buf);
/* Read var-name.
* Varname can either come right before the final semi-colon, or
* `varname` can either come right before the final semi-colon, or
* with following array syntax.
* spaces may exist before closing symbol. */
c = c_next_space + 1;
@ -3017,7 +3017,7 @@ std::string MSLGeneratorInterface::generate_msl_fragment_output_population()
std::string MSLGeneratorInterface::generate_msl_texture_vars(ShaderStage shader_stage)
{
/* NOTE: Shader stage must be a singualr stage index. Compound stage is not valid for this
/* NOTE: Shader stage must be a singular stage index. Compound stage is not valid for this
* function. */
BLI_assert(shader_stage == ShaderStage::VERTEX || shader_stage == ShaderStage::FRAGMENT ||
shader_stage == ShaderStage::COMPUTE);

View File

@ -209,6 +209,48 @@ static void test_gpu_shader_compute_ibo()
}
GPU_TEST(gpu_shader_compute_ibo)
static void test_gpu_shader_compute_ssbo()
{
if (!GPU_compute_shader_support()) {
/* We can't test as a the platform does not support compute shaders. */
std::cout << "Skipping compute shader test: platform not supported";
return;
}
static constexpr uint SIZE = 128;
/* Build compute shader. */
GPUShader *shader = GPU_shader_create_from_info_name("gpu_compute_ibo_test");
EXPECT_NE(shader, nullptr);
GPU_shader_bind(shader);
/* Construct IBO. */
GPUStorageBuf *ssbo = GPU_storagebuf_create_ex(
SIZE * sizeof(uint32_t), nullptr, GPU_USAGE_DEVICE_ONLY, __func__);
GPU_storagebuf_bind(ssbo, GPU_shader_get_ssbo(shader, "out_indices"));
/* Dispatch compute task. */
GPU_compute_dispatch(shader, SIZE, 1, 1);
/* Check if compute has been done. */
GPU_memory_barrier(GPU_BARRIER_SHADER_STORAGE);
/* Download the index buffer. */
uint32_t data[SIZE];
GPU_storagebuf_read(ssbo, data);
for (int index = 0; index < SIZE; index++) {
uint32_t expected = index;
EXPECT_EQ(data[index], expected);
}
/* Cleanup. */
GPU_shader_unbind();
GPU_storagebuf_free(ssbo);
GPU_shader_free(shader);
}
GPU_TEST(gpu_shader_compute_ssbo)
static void test_gpu_shader_ssbo_binding()
{
if (!GPU_compute_shader_support()) {

View File

@ -1,4 +1,5 @@
void main() {
void main()
{
int index = int(gl_GlobalInvocationID.x);
vec4 pos = vec4(gl_GlobalInvocationID.x);
imageStore(img_output, index, pos);

View File

@ -1,4 +1,5 @@
void main() {
void main()
{
vec4 pixel = vec4(1.0, 0.5, 0.2, 1.0);
imageStore(img_output, ivec2(gl_GlobalInvocationID.xy), pixel);
}

View File

@ -1,2 +1,3 @@
void main () {
void main()
{
}

View File

@ -1,4 +1,5 @@
void main() {
void main()
{
uint store_index = int(gl_GlobalInvocationID.x);
out_indices[store_index] = store_index;
}

View File

@ -1,4 +1,5 @@
void main() {
void main()
{
uint index = gl_GlobalInvocationID.x;
vec4 pos = vec4(gl_GlobalInvocationID.x);
out_positions[index] = pos;

View File

@ -521,7 +521,9 @@ static char *glsl_patch_get()
static std::string combine_sources(Span<const char *> sources)
{
char *sources_combined = BLI_string_join_arrayN((const char **)sources.data(), sources.size());
return std::string(sources_combined);
std::string result(sources_combined);
MEM_freeN(sources_combined);
return result;
}
Vector<uint32_t> VKShader::compile_glsl_to_spirv(Span<const char *> sources,

View File

@ -5,8 +5,7 @@
* \ingroup bgpencil
*/
#include "BLI_float4x4.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_math_matrix.hh"
#include "BLI_path_util.h"
#include "BLI_span.hh"
@ -78,13 +77,12 @@ void GpencilIO::prepare_camera_params(Scene *scene, const GpencilIOParams *ipara
BKE_camera_params_compute_viewplane(&params, rd->xsch, rd->ysch, rd->xasp, rd->yasp);
BKE_camera_params_compute_matrix(&params);
float viewmat[4][4];
invert_m4_m4(viewmat, cam_ob->object_to_world);
float4x4 viewmat = math::invert(float4x4(cam_ob->object_to_world));
mul_m4_m4m4(persmat_, params.winmat, viewmat);
persmat_ = float4x4(params.winmat) * viewmat;
}
else {
unit_m4(persmat_);
persmat_ = float4x4::identity();
}
winx_ = params_.region->winx;
@ -131,8 +129,7 @@ void GpencilIO::create_object_list()
Scene *scene = CTX_data_scene(params_.C);
ViewLayer *view_layer = CTX_data_view_layer(params_.C);
float3 camera_z_axis;
copy_v3_v3(camera_z_axis, rv3d_->viewinv[2]);
float3 camera_z_axis = float3(rv3d_->viewinv[2]);
ob_list_.clear();
BKE_view_layer_synced_ensure(scene, view_layer);
@ -150,9 +147,11 @@ void GpencilIO::create_object_list()
continue;
}
float3 object_position = float3(object->object_to_world[3]);
/* Save z-depth from view to sort from back to front. */
if (is_camera_) {
float camera_z = dot_v3v3(camera_z_axis, object->object_to_world[3]);
float camera_z = math::dot(camera_z_axis, object_position);
ObjectZ obz = {camera_z, object};
ob_list_.append(obz);
}
@ -160,10 +159,10 @@ void GpencilIO::create_object_list()
float zdepth = 0;
if (rv3d_) {
if (rv3d_->is_persp) {
zdepth = ED_view3d_calc_zfac(rv3d_, object->object_to_world[3]);
zdepth = ED_view3d_calc_zfac(rv3d_, object_position);
}
else {
zdepth = -dot_v3v3(rv3d_->viewinv[2], object->object_to_world[3]);
zdepth = -math::dot(camera_z_axis, object_position);
}
ObjectZ obz = {zdepth * -1.0f, object};
ob_list_.append(obz);
@ -184,13 +183,13 @@ void GpencilIO::filepath_set(const char *filepath)
bool GpencilIO::gpencil_3D_point_to_screen_space(const float3 co, float2 &r_co)
{
float3 parent_co = diff_mat_ * co;
float3 parent_co = math::transform_point(diff_mat_, co);
float2 screen_co;
eV3DProjTest test = (eV3DProjTest)(V3D_PROJ_RET_OK);
if (ED_view3d_project_float_global(params_.region, parent_co, screen_co, test) ==
V3D_PROJ_RET_OK) {
if (!ELEM(V2D_IS_CLIPPED, screen_co[0], screen_co[1])) {
copy_v2_v2(r_co, screen_co);
r_co = screen_co;
/* Invert X axis. */
if (invert_axis_[0]) {
r_co[0] = winx_ - r_co[0];
@ -200,8 +199,8 @@ bool GpencilIO::gpencil_3D_point_to_screen_space(const float3 co, float2 &r_co)
r_co[1] = winy_ - r_co[1];
}
/* Apply offset and scale. */
sub_v2_v2(r_co, &offset_.x);
mul_v2_fl(r_co, camera_ratio_);
r_co -= offset_;
r_co *= camera_ratio_;
return true;
}
@ -223,12 +222,10 @@ bool GpencilIO::gpencil_3D_point_to_screen_space(const float3 co, float2 &r_co)
float2 GpencilIO::gpencil_3D_point_to_render_space(const float3 co)
{
float3 parent_co = diff_mat_ * co;
float3 parent_co = math::transform_point(diff_mat_, co);
float2 r_co;
mul_v2_project_m4_v3(&r_co.x, persmat_, &parent_co.x);
r_co.x = (r_co.x + 1.0f) / 2.0f * float(render_x_);
r_co.y = (r_co.y + 1.0f) / 2.0f * float(render_y_);
float2 r_co = float2(math::project_point(persmat_, parent_co));
r_co = ((r_co + 1.0f) / 2.0f) * float2(render_x_, render_y_);
/* Invert X axis. */
if (invert_axis_[0]) {
@ -260,7 +257,7 @@ float GpencilIO::stroke_point_radius_get(bGPDlayer *gpl, bGPDstroke *gps)
/* Radius. */
bGPDstroke *gps_perimeter = BKE_gpencil_stroke_perimeter_from_view(
rv3d_->viewmat, gpd_, gpl, gps, 3, diff_mat_.values, 0.0f);
rv3d_->viewmat, gpd_, gpl, gps, 3, diff_mat_.ptr(), 0.0f);
pt = &gps_perimeter->points[0];
const float2 screen_ex = gpencil_3D_point_to_2D(&pt->x);
@ -274,7 +271,7 @@ float GpencilIO::stroke_point_radius_get(bGPDlayer *gpl, bGPDstroke *gps)
void GpencilIO::prepare_layer_export_matrix(Object *ob, bGPDlayer *gpl)
{
BKE_gpencil_layer_transform_matrix_get(depsgraph_, ob, gpl, diff_mat_.values);
BKE_gpencil_layer_transform_matrix_get(depsgraph_, ob, gpl, diff_mat_.ptr());
diff_mat_ = diff_mat_ * float4x4(gpl->layer_invmat);
}
@ -283,23 +280,21 @@ void GpencilIO::prepare_stroke_export_colors(Object *ob, bGPDstroke *gps)
MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1);
/* Stroke color. */
copy_v4_v4(stroke_color_, gp_style->stroke_rgba);
avg_opacity_ = 0.0f;
/* Get average vertex color and apply. */
float avg_color[4] = {0.0f, 0.0f, 0.0f, 0.0f};
float4 avg_color = {0.0f, 0.0f, 0.0f, 0.0f};
for (const bGPDspoint &pt : Span(gps->points, gps->totpoints)) {
add_v4_v4(avg_color, pt.vert_color);
avg_color += pt.vert_color;
avg_opacity_ += pt.strength;
}
mul_v4_v4fl(avg_color, avg_color, 1.0f / float(gps->totpoints));
interp_v3_v3v3(stroke_color_, stroke_color_, avg_color, avg_color[3]);
avg_color /= float(gps->totpoints);
avg_opacity_ /= float(gps->totpoints);
stroke_color_ = math::interpolate(float4(gp_style->stroke_rgba), avg_color, avg_color[3]);
/* Fill color. */
copy_v4_v4(fill_color_, gp_style->fill_rgba);
/* Apply vertex color for fill. */
interp_v3_v3v3(fill_color_, fill_color_, gps->vert_color_fill, gps->vert_color_fill[3]);
fill_color_ = math::interpolate(
float4(gp_style->fill_rgba), float4(gps->vert_color_fill), gps->vert_color_fill[3]);
}
float GpencilIO::stroke_average_opacity_get()
@ -329,7 +324,7 @@ void GpencilIO::selected_objects_boundbox_calc()
if (gpl->flag & GP_LAYER_HIDE) {
continue;
}
BKE_gpencil_layer_transform_matrix_get(depsgraph_, ob_eval, gpl, diff_mat_.values);
BKE_gpencil_layer_transform_matrix_get(depsgraph_, ob_eval, gpl, diff_mat_.ptr());
bGPDframe *gpf = gpl->actframe;
if (gpf == nullptr) {
@ -341,15 +336,14 @@ void GpencilIO::selected_objects_boundbox_calc()
continue;
}
for (const bGPDspoint &pt : MutableSpan(gps->points, gps->totpoints)) {
const float2 screen_co = gpencil_3D_point_to_2D(&pt.x);
minmax_v2v2_v2(min, max, screen_co);
math::min_max(gpencil_3D_point_to_2D(&pt.x), min, max);
}
}
}
}
/* Add small gap. */
add_v2_fl(min, gap * -1.0f);
add_v2_fl(max, gap);
min -= gap;
max += gap;
select_boundbox_.xmin = min[0];
select_boundbox_.ymin = min[1];

View File

@ -6,7 +6,7 @@
* \ingroup bgpencil
*/
#include "BLI_float4x4.hh"
#include "BLI_math_matrix_types.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_vector.hh"
@ -67,7 +67,7 @@ class GpencilIO {
int cfra_;
float stroke_color_[4], fill_color_[4];
float4 stroke_color_, fill_color_;
/* Geometry functions. */
/** Convert to screen-space. */
@ -104,7 +104,7 @@ class GpencilIO {
rctf select_boundbox_;
/* Camera matrix. */
float persmat_[4][4];
float4x4 persmat_;
};
} // namespace blender::io::gpencil

View File

@ -193,7 +193,7 @@ void GpencilExporterPDF::export_gpencil_layers()
}
else {
bGPDstroke *gps_perimeter = BKE_gpencil_stroke_perimeter_from_view(
rv3d_->viewmat, gpd_, gpl, gps_duplicate, 3, diff_mat_.values, 0.0f);
rv3d_->viewmat, gpd_, gpl, gps_duplicate, 3, diff_mat_.ptr(), 0.0f);
/* Sample stroke. */
if (params_.stroke_sample > 0.0f) {

View File

@ -219,7 +219,7 @@ void GpencilExporterSVG::export_gpencil_layers()
}
else {
bGPDstroke *gps_perimeter = BKE_gpencil_stroke_perimeter_from_view(
rv3d_->viewmat, gpd_, gpl, gps_duplicate, 3, diff_mat_.values, 0.0f);
rv3d_->viewmat, gpd_, gpl, gps_duplicate, 3, diff_mat_.ptr(), 0.0f);
/* Sample stroke. */
if (params_.stroke_sample > 0.0f) {

View File

@ -104,6 +104,12 @@ typedef struct IDPropertyUIDataString {
/** For #IDP_UI_DATA_TYPE_ID. */
typedef struct IDPropertyUIDataID {
IDPropertyUIData base;
/**
* #ID_Type. This type type is not enforced. It is just a hint to the ui for what kind of ID is
* expected. If this is zero, any id type is expected.
*/
short id_type;
char _pad[6];
} IDPropertyUIDataID;
typedef struct IDPropertyData {

View File

@ -17,6 +17,7 @@ extern "C" {
#ifdef __cplusplus
namespace blender::bke {
class CurvesGeometry;
class CurvesGeometryRuntime;
} // namespace blender::bke
using CurvesGeometryRuntimeHandle = blender::bke::CurvesGeometryRuntime;
@ -134,6 +135,11 @@ typedef struct CurvesGeometry {
* Runtime data for curves, stored as a pointer to allow defining this as a C++ class.
*/
CurvesGeometryRuntimeHandle *runtime;
#ifdef __cplusplus
blender::bke::CurvesGeometry &wrap();
const blender::bke::CurvesGeometry &wrap() const;
#endif
} CurvesGeometry;
/**

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