There were at least three copies of those: - OB_RECALC* family of flags, which are rudiment of an old dependency graph system. - PSYS_RECALC* which were used by old dependency graph system as a separate set since the graph itself did not handle particle systems. - DEG_TAG_* which was used to tag IDs. Now there is a single set, which defines what can be tagged and queried for an update. It also has some aggregate flags to make queries simpler. Lets once and for all solve the madness of those flags, stick to a single set, which will not overlap with anything or require any extra conversion. Technically, shouldn't be measurable user difference, but some of the agregate flags for few dependency graph components did change. Fixes T58632: Particle don't update rotation settings
382 lines
15 KiB
C
382 lines
15 KiB
C
/*
|
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
* Contributor(s): Campbell Barton
|
|
*
|
|
* ***** END GPL LICENSE BLOCK *****
|
|
*/
|
|
|
|
/** \file blender/makesrna/intern/rna_collection.c
|
|
* \ingroup RNA
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include "DNA_collection_types.h"
|
|
|
|
#include "BLI_utildefines.h"
|
|
|
|
#include "RNA_define.h"
|
|
|
|
#include "rna_internal.h"
|
|
|
|
#include "WM_types.h"
|
|
|
|
#ifdef RNA_RUNTIME
|
|
|
|
#include "DNA_scene_types.h"
|
|
#include "DNA_object_types.h"
|
|
|
|
#include "DEG_depsgraph.h"
|
|
#include "DEG_depsgraph_build.h"
|
|
|
|
#include "BKE_collection.h"
|
|
#include "BKE_global.h"
|
|
#include "BKE_layer.h"
|
|
|
|
#include "WM_api.h"
|
|
|
|
#include "RNA_access.h"
|
|
|
|
static void rna_Collection_all_objects_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
|
|
{
|
|
Collection *collection = (Collection *)ptr->data;
|
|
ListBase collection_objects = BKE_collection_object_cache_get(collection);
|
|
rna_iterator_listbase_begin(iter, &collection_objects, NULL);
|
|
}
|
|
|
|
static PointerRNA rna_Collection_all_objects_get(CollectionPropertyIterator *iter)
|
|
{
|
|
ListBaseIterator *internal = &iter->internal.listbase;
|
|
|
|
/* we are actually iterating a ObjectBase list, so override get */
|
|
Base *base = (Base *)internal->link;
|
|
return rna_pointer_inherit_refine(&iter->parent, &RNA_Object, base->object);
|
|
}
|
|
|
|
static void rna_Collection_objects_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
|
|
{
|
|
Collection *collection = (Collection *)ptr->data;
|
|
rna_iterator_listbase_begin(iter, &collection->gobject, NULL);
|
|
}
|
|
|
|
static PointerRNA rna_Collection_objects_get(CollectionPropertyIterator *iter)
|
|
{
|
|
ListBaseIterator *internal = &iter->internal.listbase;
|
|
|
|
/* we are actually iterating a ObjectBase list, so override get */
|
|
CollectionObject *cob = (CollectionObject *)internal->link;
|
|
return rna_pointer_inherit_refine(&iter->parent, &RNA_Object, cob->ob);
|
|
}
|
|
|
|
static void rna_Collection_objects_link(Collection *collection, Main *bmain, ReportList *reports, Object *object)
|
|
{
|
|
if (!BKE_collection_object_add(bmain, collection, object)) {
|
|
BKE_reportf(reports, RPT_ERROR, "Object '%s' already in collection '%s'", object->id.name + 2, collection->id.name + 2);
|
|
return;
|
|
}
|
|
|
|
DEG_id_tag_update(&collection->id, ID_RECALC_COPY_ON_WRITE);
|
|
DEG_relations_tag_update(bmain);
|
|
WM_main_add_notifier(NC_OBJECT | ND_DRAW, &object->id);
|
|
}
|
|
|
|
static void rna_Collection_objects_unlink(Collection *collection, Main *bmain, ReportList *reports, Object *object)
|
|
{
|
|
if (!BKE_collection_object_remove(bmain, collection, object, false)) {
|
|
BKE_reportf(reports, RPT_ERROR, "Object '%s' not in collection '%s'", object->id.name + 2, collection->id.name + 2);
|
|
return;
|
|
}
|
|
|
|
DEG_id_tag_update(&collection->id, ID_RECALC_COPY_ON_WRITE);
|
|
DEG_relations_tag_update(bmain);
|
|
WM_main_add_notifier(NC_OBJECT | ND_DRAW, &object->id);
|
|
}
|
|
|
|
static bool rna_Collection_objects_override_apply(
|
|
Main *bmain,
|
|
PointerRNA *ptr_dst, PointerRNA *UNUSED(ptr_src), PointerRNA *UNUSED(ptr_storage),
|
|
PropertyRNA *UNUSED(prop_dst), PropertyRNA *UNUSED(prop_src), PropertyRNA *UNUSED(prop_storage),
|
|
const int UNUSED(len_dst), const int UNUSED(len_src), const int UNUSED(len_storage),
|
|
PointerRNA *ptr_item_dst, PointerRNA *ptr_item_src, PointerRNA *UNUSED(ptr_item_storage),
|
|
IDOverrideStaticPropertyOperation *opop)
|
|
{
|
|
(void)opop;
|
|
BLI_assert(opop->operation == IDOVERRIDESTATIC_OP_REPLACE &&
|
|
"Unsupported RNA override operation on collections' objects");
|
|
|
|
Collection *coll_dst = ptr_dst->id.data;
|
|
|
|
if (ptr_item_dst->type == NULL || ptr_item_src->type == NULL) {
|
|
BLI_assert(0 && "invalid source or destination object.");
|
|
return false;
|
|
}
|
|
|
|
Object *ob_dst = ptr_item_dst->data;
|
|
Object *ob_src = ptr_item_src->data;
|
|
|
|
CollectionObject *cob_dst = BLI_findptr(&coll_dst->gobject, ob_dst, offsetof(CollectionObject, ob));
|
|
|
|
if (cob_dst == NULL) {
|
|
BLI_assert(0 && "Could not find destination object in destination collection!");
|
|
return false;
|
|
}
|
|
|
|
/* XXX TODO We most certainly rather want to have a 'swap object pointer in collection' util in BKE_collection...
|
|
* This is only temp auick dirty test! */
|
|
id_us_min(&cob_dst->ob->id);
|
|
cob_dst->ob = ob_src;
|
|
id_us_plus(&cob_dst->ob->id);
|
|
|
|
if (BKE_collection_is_in_scene(coll_dst)) {
|
|
BKE_main_collection_sync(bmain);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
|
|
static void rna_Collection_children_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
|
|
{
|
|
Collection *collection = (Collection *)ptr->data;
|
|
rna_iterator_listbase_begin(iter, &collection->children, NULL);
|
|
}
|
|
|
|
static PointerRNA rna_Collection_children_get(CollectionPropertyIterator *iter)
|
|
{
|
|
ListBaseIterator *internal = &iter->internal.listbase;
|
|
|
|
/* we are actually iterating a CollectionChild list, so override get */
|
|
CollectionChild *child = (CollectionChild *)internal->link;
|
|
return rna_pointer_inherit_refine(&iter->parent, &RNA_Collection, child->collection);
|
|
}
|
|
|
|
static void rna_Collection_children_link(Collection *collection, Main *bmain, ReportList *reports, Collection *child)
|
|
{
|
|
if (!BKE_collection_child_add(bmain, collection, child)) {
|
|
BKE_reportf(reports, RPT_ERROR, "Collection '%s' already in collection '%s'", child->id.name + 2, collection->id.name + 2);
|
|
return;
|
|
}
|
|
|
|
DEG_id_tag_update(&collection->id, ID_RECALC_COPY_ON_WRITE);
|
|
DEG_relations_tag_update(bmain);
|
|
WM_main_add_notifier(NC_OBJECT | ND_DRAW, &child->id);
|
|
}
|
|
|
|
static void rna_Collection_children_unlink(Collection *collection, Main *bmain, ReportList *reports, Collection *child)
|
|
{
|
|
if (!BKE_collection_child_remove(bmain, collection, child)) {
|
|
BKE_reportf(reports, RPT_ERROR, "Collection '%s' not in collection '%s'", child->id.name + 2, collection->id.name + 2);
|
|
return;
|
|
}
|
|
|
|
DEG_id_tag_update(&collection->id, ID_RECALC_COPY_ON_WRITE);
|
|
DEG_relations_tag_update(bmain);
|
|
WM_main_add_notifier(NC_OBJECT | ND_DRAW, &child->id);
|
|
}
|
|
|
|
static bool rna_Collection_children_override_apply(
|
|
Main *bmain,
|
|
PointerRNA *ptr_dst, PointerRNA *UNUSED(ptr_src), PointerRNA *UNUSED(ptr_storage),
|
|
PropertyRNA *UNUSED(prop_dst), PropertyRNA *UNUSED(prop_src), PropertyRNA *UNUSED(prop_storage),
|
|
const int UNUSED(len_dst), const int UNUSED(len_src), const int UNUSED(len_storage),
|
|
PointerRNA *ptr_item_dst, PointerRNA *ptr_item_src, PointerRNA *UNUSED(ptr_item_storage),
|
|
IDOverrideStaticPropertyOperation *opop)
|
|
{
|
|
(void)opop;
|
|
BLI_assert(opop->operation == IDOVERRIDESTATIC_OP_REPLACE &&
|
|
"Unsupported RNA override operation on collections' objects");
|
|
|
|
Collection *coll_dst = ptr_dst->id.data;
|
|
|
|
if (ptr_item_dst->type == NULL || ptr_item_src->type == NULL) {
|
|
BLI_assert(0 && "invalid source or destination sub-collection.");
|
|
return false;
|
|
}
|
|
|
|
Collection *subcoll_dst = ptr_item_dst->data;
|
|
Collection *subcoll_src = ptr_item_src->data;
|
|
|
|
CollectionChild *collchild_dst = BLI_findptr(&coll_dst->children, subcoll_dst, offsetof(CollectionChild, collection));
|
|
|
|
if (collchild_dst == NULL) {
|
|
BLI_assert(0 && "Could not find destination sub-collection in destination collection!");
|
|
return false;
|
|
}
|
|
|
|
/* XXX TODO We most certainly rather want to have a 'swap object pointer in collection' util in BKE_collection...
|
|
* This is only temp auick dirty test! */
|
|
id_us_min(&collchild_dst->collection->id);
|
|
collchild_dst->collection = subcoll_src;
|
|
id_us_plus(&collchild_dst->collection->id);
|
|
|
|
BKE_collection_object_cache_free(coll_dst);
|
|
BKE_main_collection_sync(bmain);
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
|
|
static void rna_Collection_flag_update(Main *bmain, Scene *scene, PointerRNA *ptr)
|
|
{
|
|
Collection *collection = (Collection *)ptr->data;
|
|
BKE_collection_object_cache_free(collection);
|
|
BKE_main_collection_sync(bmain);
|
|
|
|
DEG_id_tag_update(&collection->id, ID_RECALC_COPY_ON_WRITE);
|
|
DEG_relations_tag_update(bmain);
|
|
WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, scene);
|
|
}
|
|
|
|
#else
|
|
|
|
/* collection.objects */
|
|
static void rna_def_collection_objects(BlenderRNA *brna, PropertyRNA *cprop)
|
|
{
|
|
StructRNA *srna;
|
|
FunctionRNA *func;
|
|
PropertyRNA *parm;
|
|
|
|
RNA_def_property_srna(cprop, "CollectionObjects");
|
|
srna = RNA_def_struct(brna, "CollectionObjects", NULL);
|
|
RNA_def_struct_sdna(srna, "Collection");
|
|
RNA_def_struct_ui_text(srna, "Collection Objects", "Collection of collection objects");
|
|
|
|
/* add object */
|
|
func = RNA_def_function(srna, "link", "rna_Collection_objects_link");
|
|
RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_MAIN);
|
|
RNA_def_function_ui_description(func, "Add this object to a collection");
|
|
parm = RNA_def_pointer(func, "object", "Object", "", "Object to add");
|
|
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
|
|
|
|
/* remove object */
|
|
func = RNA_def_function(srna, "unlink", "rna_Collection_objects_unlink");
|
|
RNA_def_function_ui_description(func, "Remove this object from a collection");
|
|
RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_MAIN);
|
|
parm = RNA_def_pointer(func, "object", "Object", "", "Object to remove");
|
|
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
|
|
}
|
|
|
|
/* collection.children */
|
|
static void rna_def_collection_children(BlenderRNA *brna, PropertyRNA *cprop)
|
|
{
|
|
StructRNA *srna;
|
|
FunctionRNA *func;
|
|
PropertyRNA *parm;
|
|
|
|
RNA_def_property_srna(cprop, "CollectionChildren");
|
|
srna = RNA_def_struct(brna, "CollectionChildren", NULL);
|
|
RNA_def_struct_sdna(srna, "Collection");
|
|
RNA_def_struct_ui_text(srna, "Collection Children", "Collection of child collections");
|
|
|
|
/* add child */
|
|
func = RNA_def_function(srna, "link", "rna_Collection_children_link");
|
|
RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_MAIN);
|
|
RNA_def_function_ui_description(func, "Add this collection as child of this collection");
|
|
parm = RNA_def_pointer(func, "child", "Collection", "", "Collection to add");
|
|
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
|
|
|
|
/* remove child */
|
|
func = RNA_def_function(srna, "unlink", "rna_Collection_children_unlink");
|
|
RNA_def_function_ui_description(func, "Remove this child collection from a collection");
|
|
RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_MAIN);
|
|
parm = RNA_def_pointer(func, "child", "Collection", "", "Collection to remove");
|
|
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
|
|
}
|
|
|
|
|
|
void RNA_def_collections(BlenderRNA *brna)
|
|
{
|
|
StructRNA *srna;
|
|
PropertyRNA *prop;
|
|
|
|
srna = RNA_def_struct(brna, "Collection", "ID");
|
|
/* XXX: CAN WE RENAME TO Collection? */
|
|
RNA_def_struct_sdna(srna, "Group"); /* it is actually Collection but for 2.8 the dna is patched! */
|
|
RNA_def_struct_ui_text(srna, "Collection", "Collection of Object data-blocks");
|
|
RNA_def_struct_ui_icon(srna, ICON_GROUP);
|
|
/* this is done on save/load in readfile.c, removed if no objects are in the collection and not in a scene */
|
|
RNA_def_struct_clear_flag(srna, STRUCT_ID_REFCOUNT);
|
|
|
|
prop = RNA_def_property(srna, "instance_offset", PROP_FLOAT, PROP_TRANSLATION);
|
|
RNA_def_property_float_sdna(prop, NULL, "dupli_ofs");
|
|
RNA_def_property_ui_text(prop, "Instance Offset", "Offset from the origin to use when instancing");
|
|
RNA_def_property_ui_range(prop, -10000.0, 10000.0, 10, RNA_TRANSLATION_PREC_DEFAULT);
|
|
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
|
|
|
|
prop = RNA_def_property(srna, "objects", PROP_COLLECTION, PROP_NONE);
|
|
RNA_def_property_struct_type(prop, "Object");
|
|
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC);
|
|
RNA_def_property_override_funcs(prop, NULL, NULL, "rna_Collection_objects_override_apply");
|
|
RNA_def_property_ui_text(prop, "Objects", "Objects that are directly in this collection");
|
|
RNA_def_property_collection_funcs(prop, "rna_Collection_objects_begin",
|
|
"rna_iterator_listbase_next",
|
|
"rna_iterator_listbase_end",
|
|
"rna_Collection_objects_get",
|
|
NULL, NULL, NULL, NULL);
|
|
rna_def_collection_objects(brna, prop);
|
|
|
|
prop = RNA_def_property(srna, "all_objects", PROP_COLLECTION, PROP_NONE);
|
|
RNA_def_property_struct_type(prop, "Object");
|
|
RNA_def_property_ui_text(prop, "All Objects", "Objects that are in this collection and its child collections");
|
|
RNA_def_property_collection_funcs(prop, "rna_Collection_all_objects_begin",
|
|
"rna_iterator_listbase_next",
|
|
"rna_iterator_listbase_end",
|
|
"rna_Collection_all_objects_get",
|
|
NULL, NULL, NULL, NULL);
|
|
|
|
prop = RNA_def_property(srna, "children", PROP_COLLECTION, PROP_NONE);
|
|
RNA_def_property_struct_type(prop, "Collection");
|
|
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC);
|
|
RNA_def_property_override_funcs(prop, NULL, NULL, "rna_Collection_children_override_apply");
|
|
RNA_def_property_ui_text(prop, "Children", "Collections that are immediate children of this collection");
|
|
RNA_def_property_collection_funcs(prop, "rna_Collection_children_begin",
|
|
"rna_iterator_listbase_next",
|
|
"rna_iterator_listbase_end",
|
|
"rna_Collection_children_get",
|
|
NULL, NULL, NULL, NULL);
|
|
rna_def_collection_children(brna, prop);
|
|
|
|
/* Flags */
|
|
prop = RNA_def_property(srna, "hide_select", PROP_BOOLEAN, PROP_NONE);
|
|
RNA_def_property_boolean_sdna(prop, NULL, "flag", COLLECTION_RESTRICT_SELECT);
|
|
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC);
|
|
RNA_def_property_ui_icon(prop, ICON_RESTRICT_SELECT_OFF, -1);
|
|
RNA_def_property_ui_text(prop, "Disable Select", "Disable collection for viewport selection");
|
|
RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_Collection_flag_update");
|
|
|
|
prop = RNA_def_property(srna, "hide_viewport", PROP_BOOLEAN, PROP_NONE);
|
|
RNA_def_property_boolean_sdna(prop, NULL, "flag", COLLECTION_RESTRICT_VIEW);
|
|
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC);
|
|
RNA_def_property_ui_icon(prop, ICON_RESTRICT_VIEW_OFF, -1);
|
|
RNA_def_property_ui_text(prop, "Disable Viewport", "Disable collection in viewport");
|
|
RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_Collection_flag_update");
|
|
|
|
prop = RNA_def_property(srna, "hide_render", PROP_BOOLEAN, PROP_NONE);
|
|
RNA_def_property_boolean_sdna(prop, NULL, "flag", COLLECTION_RESTRICT_RENDER);
|
|
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC);
|
|
RNA_def_property_ui_icon(prop, ICON_RESTRICT_RENDER_OFF, -1);
|
|
RNA_def_property_ui_text(prop, "Disable Render", "Disable collection in renders");
|
|
RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_Collection_flag_update");
|
|
}
|
|
|
|
#endif
|