[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