[Bf-blender-cvs] [d1e59b29c91] temp-collection-asssets: Initial bounding box based snapping for collection drag & drop
Julian Eisel
noreply at git.blender.org
Sat Jan 8 15:22:45 CET 2022
Commit: d1e59b29c9198f547daaf1d194b301290714b567
Author: Julian Eisel
Date: Sat Jan 8 15:21:37 2022 +0100
Branches: temp-collection-asssets
https://developer.blender.org/rBd1e59b29c9198f547daaf1d194b301290714b567
Initial bounding box based snapping for collection drag & drop
===================================================================
M source/blender/blenkernel/BKE_collection.h
M source/blender/blenkernel/intern/collection.c
M source/blender/editors/space_view3d/space_view3d.c
M source/blender/windowmanager/WM_api.h
M source/blender/windowmanager/intern/wm_dragdrop.c
===================================================================
diff --git a/source/blender/blenkernel/BKE_collection.h b/source/blender/blenkernel/BKE_collection.h
index 402bffea91d..900ea594972 100644
--- a/source/blender/blenkernel/BKE_collection.h
+++ b/source/blender/blenkernel/BKE_collection.h
@@ -39,6 +39,7 @@ struct BlendDataReader;
struct BlendExpander;
struct BlendLibReader;
struct BlendWriter;
+struct BoundBox;
struct Collection;
struct Library;
struct Main;
@@ -211,6 +212,20 @@ void BKE_collection_object_cache_free(struct Collection *collection);
struct Base *BKE_collection_or_layer_objects(const struct ViewLayer *view_layer,
struct Collection *collection);
+/* Dimensions. */
+
+/**
+ * Calculate the axis-aligned bounding box (in global space) of all objects in this collection,
+ * excluding empties (but including lamps, cameras, curves, etc.).
+ */
+void BKE_collection_boundbox_calc(const struct Collection *collection,
+ struct BoundBox *r_boundbox);
+/**
+ * Calculate the axis-aligned dimensions of all objects in this collection, excluding
+ * empties (but including lamps, cameras, curves, etc.).
+ */
+void BKE_collection_dimensions_calc(const struct Collection *collection, float r_vec[3]);
+
/* Editing. */
/**
diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c
index e6ce4eb9440..76d46591dd7 100644
--- a/source/blender/blenkernel/intern/collection.c
+++ b/source/blender/blenkernel/intern/collection.c
@@ -26,11 +26,13 @@
#include "BLI_blenlib.h"
#include "BLI_iterator.h"
#include "BLI_listbase.h"
+#include "BLI_math.h"
#include "BLI_math_base.h"
#include "BLI_threads.h"
#include "BLT_translation.h"
#include "BKE_anim_data.h"
+#include "BKE_asset.h"
#include "BKE_collection.h"
#include "BKE_icons.h"
#include "BKE_idprop.h"
@@ -366,6 +368,40 @@ static void collection_blend_read_expand(BlendExpander *expander, ID *id)
BKE_collection_blend_read_expand(expander, collection);
}
+static IDProperty *collection_asset_dimensions_property(Collection *collection)
+{
+ float dimensions[3];
+ BKE_collection_dimensions_calc(collection, dimensions);
+ if (is_zero_v3(dimensions)) {
+ return NULL;
+ }
+
+ IDPropertyTemplate idprop = {0};
+ idprop.array.len = ARRAY_SIZE(dimensions);
+ idprop.array.type = IDP_FLOAT;
+
+ IDProperty *property = IDP_New(IDP_ARRAY, &idprop, "dimensions");
+ memcpy(IDP_Array(property), dimensions, sizeof(dimensions));
+
+ return property;
+}
+
+static void collection_asset_pre_save(void *asset_ptr, struct AssetMetaData *asset_data)
+{
+ Collection *collection = (Collection *)asset_ptr;
+ BLI_assert(GS(collection->id.name) == ID_GR);
+
+ /* Update dimensions hint for the asset. */
+ IDProperty *dimensions_prop = collection_asset_dimensions_property(collection);
+ if (dimensions_prop) {
+ BKE_asset_metadata_idprop_ensure(asset_data, dimensions_prop);
+ }
+}
+
+AssetTypeInfo AssetType_GR = {
+ /* pre_save_fn */ collection_asset_pre_save,
+};
+
IDTypeInfo IDType_ID_GR = {
.id_code = ID_GR,
.id_filter = FILTER_ID_GR,
@@ -375,7 +411,7 @@ IDTypeInfo IDType_ID_GR = {
.name_plural = "collections",
.translation_context = BLT_I18NCONTEXT_ID_COLLECTION,
.flags = IDTYPE_FLAGS_NO_ANIMDATA,
- .asset_type_info = NULL,
+ .asset_type_info = &AssetType_GR,
.init_data = collection_init_data,
.copy_data = collection_copy_data,
@@ -851,6 +887,92 @@ Base *BKE_collection_or_layer_objects(const ViewLayer *view_layer, Collection *c
/** \} */
+/* -------------------------------------------------------------------- */
+/** \name Collection Dimensions
+ * \{ */
+
+/**
+ * \param with_instances: Include the objects of instance collections.
+ * \param with_empties: Include the location of empties in the bounding box.
+ * \param instance_mat: The transform matrix of the object instancing this collection. Pass the
+ * unit matrix if the collection is not an instance.
+ */
+static void collection_geometry_boundbox_calc_recursive(const Collection *collection,
+ const bool with_instances,
+ const bool with_empties,
+ float instance_mat[4][4],
+ float r_min[3],
+ float r_max[3])
+{
+ LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) {
+ if (with_instances && cob->ob->instance_collection) {
+ float this_instance_collection_mat[4][4];
+ unit_m4(this_instance_collection_mat);
+ sub_v3_v3(this_instance_collection_mat[3], cob->ob->instance_collection->instance_offset);
+ mul_m4_m4m4(this_instance_collection_mat, cob->ob->obmat, instance_mat);
+
+ collection_geometry_boundbox_calc_recursive(cob->ob->instance_collection,
+ with_instances,
+ with_empties,
+ this_instance_collection_mat,
+ r_min,
+ r_max);
+ }
+
+ /* Empties don't contribute to the dimensions. */
+ if (!with_empties && (cob->ob->type == OB_EMPTY)) {
+ continue;
+ }
+
+ BoundBox *bb_object = BKE_object_boundbox_get(cob->ob);
+ if (bb_object) {
+ float obmat[4][4];
+ mul_m4_m4m4(obmat, cob->ob->obmat, instance_mat);
+
+ BKE_boundbox_minmax(bb_object, obmat, r_min, r_max);
+ }
+ else {
+ minmax_v3v3_v3(r_min, r_max, cob->ob->obmat[3]);
+ }
+ }
+
+ LISTBASE_FOREACH (CollectionChild *, child, &collection->children) {
+ collection_geometry_boundbox_calc_recursive(
+ child->collection, with_instances, with_empties, instance_mat, r_min, r_max);
+ }
+}
+
+static void collection_boundbox_min_max(const Collection *collection,
+ float r_min[3],
+ float r_max[3])
+{
+ INIT_MINMAX(r_min, r_max);
+
+ /* The matrix of the */
+ float instance_collection_mat[4][4];
+ unit_m4(instance_collection_mat);
+
+ collection_geometry_boundbox_calc_recursive(
+ collection, true, false, instance_collection_mat, r_min, r_max);
+}
+
+void BKE_collection_boundbox_calc(const Collection *collection, BoundBox *r_boundbox)
+{
+ float min[3], max[3];
+ collection_boundbox_min_max(collection, min, max);
+ BKE_boundbox_init_from_minmax(r_boundbox, min, max);
+}
+
+/* TODO invisible objects (either in scene or in viewport)? */
+void BKE_collection_dimensions_calc(const Collection *collection, float r_vec[3])
+{
+ float min[3], max[3];
+ collection_boundbox_min_max(collection, min, max);
+ sub_v3_v3v3(r_vec, max, min);
+}
+
+/** \} */
+
/* -------------------------------------------------------------------- */
/** \name Scene Master Collection
* \{ */
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index 8822ea6af3b..ae580f82d8e 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -24,6 +24,7 @@
#include <stdio.h>
#include <string.h>
+#include "DNA_collection_types.h"
#include "DNA_defaults.h"
#include "DNA_gpencil_types.h"
#include "DNA_lightprobe_types.h"
@@ -500,7 +501,7 @@ static bool view3d_drop_id_in_main_region_poll(bContext *C,
return WM_drag_is_ID_type(drag, id_type);
}
-static void view3d_ob_drop_draw_activate(struct wmDropBox *drop, wmDrag *drag)
+static void view3d_boundbox_drop_draw_activate(struct wmDropBox *drop, wmDrag *drag)
{
V3DSnapCursorState *state = drop->draw_data;
if (state) {
@@ -513,16 +514,30 @@ static void view3d_ob_drop_draw_activate(struct wmDropBox *drop, wmDrag *drag)
return;
}
+ const int drag_id_type = WM_drag_get_ID_type(drag);
+ if (!ELEM(drag_id_type, ID_OB, ID_GR)) {
+ return;
+ }
+
state = drop->draw_data = ED_view3d_cursor_snap_active();
state->draw_plane = true;
float dimensions[3] = {0.0f};
if (drag->type == WM_DRAG_ID) {
- Object *ob = (Object *)WM_drag_get_local_ID(drag, ID_OB);
- BKE_object_dimensions_get(ob, dimensions);
+ if (drag_id_type == ID_OB) {
+ Object *ob = (Object *)WM_drag_get_local_ID(drag, ID_OB);
+ BKE_object_dimensions_get(ob, dimensions);
+ }
+ else if (drag_id_type == ID_GR) {
+ struct Collection *collection = (struct Collection *)WM_drag_get_local_ID(drag, ID_GR);
+ BKE_collection_dimensions_calc(collection, dimensions);
+ }
+ else {
+ BLI_assert_unreachable();
+ }
}
else {
- struct AssetMetaData *meta_data = WM_drag_get_asset_meta_data(drag, ID_OB);
+ struct AssetMetaData *meta_data = WM_drag_get_asset_meta_data(drag, drag_id_type);
IDProperty *dimensions_prop = BKE_asset_metadata_idprop_find(meta_data, "dimensions");
if (dimensions_prop) {
copy_v3_v3(dimensions, IDP_Array(dimensions_prop));
@@ -536,7 +551,7 @@ static void view3d_ob_drop_draw_activate(struct wmDropBox *drop, wmDrag *drag)
}
}
-static void view3d_ob_drop_draw_deactivate(struct wmDropBox *drop, wmDrag *UNUSED(drag))
+static void view3d_boundbox_drop_draw_deactivate(struct wmDropBox *drop, wmDrag *UNUSED(drag))
{
V3DSnapCursorState *state = drop->draw_data;
if (state) {
@@ -680,30 +695,37 @@ static bool view3d_volume_drop_poll(bContext *UNUSED(C),
return (drag->type == WM_DRAG_PATH) && (drag->icon == ICON_FILE_VOLUME);
}
-static void view3d_ob_drop_matrix_from_snap(V3DSnapCursorState *snap_state,
- Object *ob,
- float obmat_final[4][4])
+static void view3d_drop_matrix_from_snap(V3DSnapCursorState *snap_state,
+ const BoundBox *bb,
+ const float base_mat[4][4],
+ float r_mat_final[4][4])
{
V3DSnapCursorData *snap_data;
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list