WIP: Brush assets project #106303

Draft
Julian Eisel wants to merge 358 commits from brush-assets-project into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
17 changed files with 160 additions and 99 deletions
Showing only changes of commit 2ac6f8d455 - Show all commits

View File

@ -633,12 +633,6 @@ void BKE_library_make_local(
void BKE_id_tag_set_atomic(ID *id, int tag);
void BKE_id_tag_clear_atomic(ID *id, int tag);
/**
* Check that given ID pointer actually is in G_MAIN.
* Main intended use is for debug asserts in places we cannot easily get rid of #G_Main.
*/
bool BKE_id_is_in_global_main(ID *id);
bool BKE_id_can_be_asset(const ID *id);
/**

View File

@ -518,8 +518,10 @@ int set_listbasepointers(Main *main, ListBase *lb[]);
* Use this in operator and draw code instead of assuming the main
* in the context owns datablocks. Some datablock can be part of
* main datablocks from asset libraries instead.
*
* Optionally can verify membership of global_main, but this is expensive.
*/
Main *BKE_main_from_id(Main *global_main, const ID *id);
Main *BKE_main_from_id(Main *global_main, const ID *id, bool verify = false);
#define MAIN_VERSION_FILE_ATLEAST(main, ver, subver) \
((main)->versionfile > (ver) || \

View File

@ -2131,13 +2131,6 @@ void BKE_id_tag_clear_atomic(ID *id, int tag)
atomic_fetch_and_and_int32(&id->tag, ~tag);
}
bool BKE_id_is_in_global_main(ID *id)
{
/* We do not want to fail when id is nullptr here, even though this is a bit strange behavior...
*/
return (id == nullptr || BLI_findindex(which_libbase(G_MAIN, GS(id->name)), id) != -1);
}
bool BKE_id_can_be_asset(const ID *id)
{
return !ID_IS_LINKED(id) && !ID_IS_OVERRIDE_LIBRARY(id) &&

View File

@ -24,7 +24,7 @@
#include "DNA_ID.h"
#include "BKE_asset_weak_reference.hh"
#include "BKE_asset.hh"
#include "BKE_bpath.hh"
#include "BKE_global.hh"
#include "BKE_idtype.hh"
@ -963,7 +963,25 @@ int set_listbasepointers(Main *bmain, ListBase *lb[/*INDEX_ID_MAX*/])
return (INDEX_ID_MAX - 1);
}
Main *BKE_main_from_id(Main *global_main, const ID *id)
Main *BKE_main_from_id(Main *global_main, const ID *id, const bool verify)
{
return (id->tag & LIB_TAG_ASSET_MAIN) ? BKE_asset_weak_reference_main(id) : global_main;
if (id == nullptr || (id->tag & LIB_TAG_NO_MAIN)) {
return nullptr;
}
if (id->tag & LIB_TAG_ASSET_MAIN) {
return BKE_asset_weak_reference_main(id);
}
if (verify) {
/* This is rather expensive, so don't do by default and assume valid input. */
if (BLI_findindex(which_libbase(global_main, GS(id->name)), id) == -1) {
return nullptr;
}
}
else {
/* Debug assert, especially for places that pass in G_MAIN. */
BLI_assert(BLI_findindex(which_libbase(global_main, GS(id->name)), id) != -1);
}
return global_main;
}

View File

@ -1263,16 +1263,30 @@ static char *rna_def_property_set_func(
else {
rna_print_data_get(f, dp);
PointerPropertyRNA *pprop = (PointerPropertyRNA *)dp->prop;
StructRNA *type = (pprop->type) ? rna_find_struct((const char *)pprop->type) : nullptr;
if (prop->flag & PROP_ID_SELF_CHECK) {
/* No pointers to self allowed. */
rna_print_id_get(f, dp);
fprintf(f, " if (id == value.data) {\n");
fprintf(f, " return;\n");
fprintf(f, " }\n");
}
/* TODO: check here for wrong linking between regular and asset main? */
if (type && (type->flag & STRUCT_ID)) {
/* Can only assign pointers between datablocks in the same main database. */
fprintf(f, " if (value.data) {\n");
fprintf(f, " Main *owner_main = BKE_main_from_id(G_MAIN, ptr->owner_id);\n");
fprintf(f, " Main *value_main = BKE_main_from_id(G_MAIN, (ID *)value.data);\n");
fprintf(f, " if (owner_main && owner_main != value_main) {\n");
fprintf(f, " return;\n");
fprintf(f, " }\n");
fprintf(f, " }\n");
}
if (prop->flag & PROP_ID_REFCOUNT) {
/* Perform reference counting. */
fprintf(f, "\n if (data->%s) {\n", dp->dnaname);
fprintf(f, " id_us_min((ID *)data->%s);\n", dp->dnaname);
fprintf(f, " }\n");
@ -1280,14 +1294,11 @@ static char *rna_def_property_set_func(
fprintf(f, " id_us_plus((ID *)value.data);\n");
fprintf(f, " }\n");
}
else {
PointerPropertyRNA *pprop = (PointerPropertyRNA *)dp->prop;
StructRNA *type = (pprop->type) ? rna_find_struct((const char *)pprop->type) : nullptr;
if (type && (type->flag & STRUCT_ID)) {
fprintf(f, " if (value.data) {\n");
fprintf(f, " id_lib_extern((ID *)value.data);\n");
fprintf(f, " }\n");
}
else if (type && (type->flag & STRUCT_ID)) {
/* Still mark linked data as used if not reference counting. */
fprintf(f, " if (value.data) {\n");
fprintf(f, " id_lib_extern((ID *)value.data);\n");
fprintf(f, " }\n");
}
fprintf(f, " *(void **)&data->%s = value.data;\n", dp->dnaname);
@ -4861,6 +4872,7 @@ static void rna_generate(BlenderRNA *brna, FILE *f, const char *filename, const
fprintf(f, "#include \"BLI_utildefines.h\"\n\n");
fprintf(f, "#include \"BKE_context.hh\"\n");
fprintf(f, "#include \"BKE_global.hh\"\n");
fprintf(f, "#include \"BKE_lib_id.hh\"\n");
fprintf(f, "#include \"BKE_main.hh\"\n");
fprintf(f, "#include \"BKE_report.hh\"\n");

View File

@ -289,9 +289,6 @@ void rna_ID_name_set(PointerRNA *ptr, const char *value)
Main *id_main = BKE_main_from_id(G_MAIN, id);
BKE_main_namemap_remove_name(id_main, id, id->name + 2);
BLI_strncpy_utf8(id->name + 2, value, sizeof(id->name) - 2);
/* TODO: add BKE_id_is_in_editable_main? */
/* TODO: this does update immediately in the asset shelf. */
BLI_assert(BKE_id_is_in_global_main(id) || (id->tag & LIB_TAG_ASSET_MAIN));
BKE_libblock_ensure_unique_name(id_main, id);
if (GS(id->name) == ID_OB) {
@ -300,6 +297,8 @@ void rna_ID_name_set(PointerRNA *ptr, const char *value)
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
}
}
/* TODO: this does not update immediately in the asset shelf. */
}
static int rna_ID_name_editable(const PointerRNA *ptr, const char **r_info)
@ -325,8 +324,7 @@ static int rna_ID_name_editable(const PointerRNA *ptr, const char **r_info)
return 0;
}
}
/* TODO: add BKE_id_is_in_editable_main? */
else if (!(BKE_id_is_in_global_main(id) || (id->tag & LIB_TAG_ASSET_MAIN))) {
else if (BKE_main_from_id(G_MAIN, id, true) == nullptr) {
if (r_info) {
*r_info = N_("Datablocks not in global Main data-base cannot be renamed");
}
@ -1156,18 +1154,20 @@ int rna_IDMaterials_assign_int(PointerRNA *ptr, int key, const PointerRNA *assig
{
ID *id = ptr->owner_id;
short *totcol = BKE_id_material_len_p(id);
Material *mat_id = (Material *)assign_ptr->owner_id;
if (totcol && (key >= 0 && key < *totcol)) {
Main *id_main = BKE_main_from_id(G_MAIN, id);
/* TODO: BKE_id_is_in_editable_main? */
BLI_assert(BKE_id_is_in_global_main(id));
BLI_assert(BKE_id_is_in_global_main(&mat_id->id));
BKE_id_material_assign(id_main, id, mat_id, key + 1);
return 1;
}
else {
Material *mat = (Material *)assign_ptr->owner_id;
if (!(totcol && (key >= 0 && key < *totcol))) {
return 0;
}
Main *id_main = BKE_main_from_id(G_MAIN, id);
if (mat) {
if (id_main != BKE_main_from_id(G_MAIN, &mat->id)) {
return 0;
}
}
BKE_id_material_assign(id_main, id, mat, key + 1);
return 1;
}
static void rna_IDMaterials_append_id(ID *id, Main *bmain, Material *ma)
@ -1219,8 +1219,6 @@ static void rna_Library_filepath_set(PointerRNA *ptr, const char *value)
{
Library *lib = (Library *)ptr->data;
Main *id_main = BKE_main_from_id(G_MAIN, &lib->id);
/* TODO: BKE_id_is_in_editable_main? */
BLI_assert(BKE_id_is_in_global_main(&lib->id));
BKE_library_filepath_set(id_main, lib, value);
}

View File

@ -2143,7 +2143,8 @@ static bool rna_property_editable_do(const PointerRNA *ptr,
return false;
}
if (ID_IS_OVERRIDE_LIBRARY(id)) {
const bool is_liboverride_system = BKE_lib_override_library_is_system_defined(G_MAIN, id);
Main *main = BKE_main_from_id(G_MAIN, id);
const bool is_liboverride_system = BKE_lib_override_library_is_system_defined(main, id);
if (!RNA_property_overridable_get(ptr, prop_orig)) {
if (r_info != nullptr && (*r_info)[0] == '\0') {
*r_info = N_("Can't edit this property from an override data-block");
@ -2341,7 +2342,11 @@ bool RNA_property_update_check(PropertyRNA *prop)
void RNA_property_update(bContext *C, PointerRNA *ptr, PropertyRNA *prop)
{
rna_property_update(C, CTX_data_main(C), CTX_data_scene(C), ptr, prop);
Main *main = CTX_data_main(C);
if (ptr->owner_id) {
main = BKE_main_from_id(main, ptr->owner_id);
}
rna_property_update(C, main, CTX_data_scene(C), ptr, prop);
}
void RNA_property_update_main(Main *bmain, Scene *scene, PointerRNA *ptr, PropertyRNA *prop)

View File

@ -791,28 +791,36 @@ static void rna_EditBone_name_set(PointerRNA *ptr, const char *value)
{
bArmature *arm = (bArmature *)ptr->owner_id;
EditBone *ebone = (EditBone *)ptr->data;
char oldname[sizeof(ebone->name)], newname[sizeof(ebone->name)];
Main *main = BKE_main_from_id(G_MAIN, &arm->id);
if (main == nullptr) {
return;
}
char oldname[sizeof(ebone->name)], newname[sizeof(ebone->name)];
/* need to be on the stack */
STRNCPY_UTF8(newname, value);
STRNCPY(oldname, ebone->name);
BLI_assert(BKE_id_is_in_global_main(&arm->id));
ED_armature_bone_rename(G_MAIN, arm, oldname, newname);
ED_armature_bone_rename(main, arm, oldname, newname);
}
static void rna_Bone_name_set(PointerRNA *ptr, const char *value)
{
bArmature *arm = (bArmature *)ptr->owner_id;
Bone *bone = (Bone *)ptr->data;
char oldname[sizeof(bone->name)], newname[sizeof(bone->name)];
Main *main = BKE_main_from_id(G_MAIN, &arm->id);
if (main == nullptr) {
return;
}
char oldname[sizeof(bone->name)], newname[sizeof(bone->name)];
/* need to be on the stack */
STRNCPY_UTF8(newname, value);
STRNCPY(oldname, bone->name);
BLI_assert(BKE_id_is_in_global_main(&arm->id));
ED_armature_bone_rename(G_MAIN, arm, oldname, newname);
ED_armature_bone_rename(main, arm, oldname, newname);
}
static void rna_EditBone_connected_check(EditBone *ebone)

View File

@ -86,18 +86,23 @@ static void rna_Image_source_set(PointerRNA *ptr, int value)
{
Image *ima = (Image *)ptr->owner_id;
if (value != ima->source) {
ima->source = value;
BLI_assert(BKE_id_is_in_global_main(&ima->id));
BKE_image_signal(G_MAIN, ima, nullptr, IMA_SIGNAL_SRC_CHANGE);
if (ima->source == IMA_SRC_TILED) {
BKE_image_signal(G_MAIN, ima, nullptr, IMA_SIGNAL_RELOAD);
}
DEG_id_tag_update(&ima->id, 0);
DEG_id_tag_update(&ima->id, ID_RECALC_EDITORS | ID_RECALC_SOURCE);
DEG_relations_tag_update(G_MAIN);
if (value == ima->source) {
return;
}
ima->source = value;
Main *main = BKE_main_from_id(G_MAIN, &ima->id);
if (main == nullptr) {
return;
}
BKE_image_signal(main, ima, nullptr, IMA_SIGNAL_SRC_CHANGE);
if (ima->source == IMA_SRC_TILED) {
BKE_image_signal(main, ima, nullptr, IMA_SIGNAL_RELOAD);
}
DEG_id_tag_update(&ima->id, 0);
DEG_id_tag_update(&ima->id, ID_RECALC_EDITORS | ID_RECALC_SOURCE);
DEG_relations_tag_update(main);
}
static void rna_Image_reload_update(Main *bmain, Scene * /*scene*/, PointerRNA *ptr)

View File

@ -27,7 +27,6 @@
# include "BKE_action.h"
# include "BKE_armature.hh"
# include "BKE_asset.hh"
# include "BKE_brush.hh"
# include "BKE_camera.h"
# include "BKE_collection.hh"
@ -126,11 +125,10 @@ static void rna_Main_ID_remove(Main *bmain,
id->name + 2);
return;
}
/* TODO: also check reverse case somehow? */
if (bmain != BKE_main_from_id(bmain, id)) {
BKE_reportf(reports,
RPT_ERROR,
"%s '%s' is part of a difference main database and should be removed from there",
"%s '%s' is part of a different main database and should be removed from there",
BKE_idtype_idcode_to_name(GS(id->name)),
id->name + 2);
return;

View File

@ -556,6 +556,14 @@ static void rna_Object_data_set(PointerRNA *ptr, PointerRNA value, ReportList *r
return;
}
Main *ob_main = BKE_main_from_id(G_MAIN, &ob->id);
if (id) {
if (ob_main != BKE_main_from_id(G_MAIN, id)) {
BKE_report(reports, RPT_ERROR, "Can't assign object data from different main database");
return;
}
}
if (ob->type == OB_EMPTY) {
if (ob->data) {
id_us_min(static_cast<ID *>(ob->data));
@ -568,7 +576,7 @@ static void rna_Object_data_set(PointerRNA *ptr, PointerRNA value, ReportList *r
}
}
else if (ob->type == OB_MESH) {
BKE_mesh_assign_object(G_MAIN, ob, reinterpret_cast<Mesh *>(id));
BKE_mesh_assign_object(ob_main, ob, reinterpret_cast<Mesh *>(id));
}
else {
if (ob->data) {
@ -580,13 +588,13 @@ static void rna_Object_data_set(PointerRNA *ptr, PointerRNA value, ReportList *r
id_us_plus(id);
ob->data = id;
BKE_object_materials_test(G_MAIN, ob, id);
BKE_object_materials_test(ob_main, ob, id);
if (GS(id->name) == ID_CU_LEGACY) {
BKE_curve_type_test(ob);
}
else if (ob->type == OB_ARMATURE) {
BKE_pose_rebuild(G_MAIN, ob, static_cast<bArmature *>(ob->data), true);
BKE_pose_rebuild(ob_main, ob, static_cast<bArmature *>(ob->data), true);
}
}
}
@ -1147,17 +1155,23 @@ static PointerRNA rna_Object_active_material_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, &RNA_Material, ma);
}
static void rna_Object_active_material_set(PointerRNA *ptr,
PointerRNA value,
ReportList * /*reports*/)
static void rna_Object_active_material_set(PointerRNA *ptr, PointerRNA value, ReportList *reports)
{
Object *ob = reinterpret_cast<Object *>(ptr->owner_id);
Material *mat = reinterpret_cast<Material *>(value.data);
DEG_id_tag_update(static_cast<ID *>(value.data), 0);
BLI_assert(BKE_id_is_in_global_main(&ob->id));
BLI_assert(BKE_id_is_in_global_main(static_cast<ID *>(value.data)));
BKE_object_material_assign(
G_MAIN, ob, static_cast<Material *>(value.data), ob->actcol, BKE_MAT_ASSIGN_EXISTING);
Main *ob_main = BKE_main_from_id(G_MAIN, &ob->id);
if (mat) {
Main *mat_main = BKE_main_from_id(G_MAIN, &mat->id);
if (ob_main != mat_main) {
BKE_report(reports, RPT_ERROR, "Can't assign material from other main database");
return;
}
}
DEG_id_tag_update(&mat->id, 0);
BKE_object_material_assign(ob_main, ob, mat, ob->actcol, BKE_MAT_ASSIGN_EXISTING);
if (ob->type == OB_GPENCIL_LEGACY) {
/* Notifying material property in top-bar. */
@ -1381,17 +1395,21 @@ static PointerRNA rna_MaterialSlot_material_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, &RNA_Material, ma);
}
static void rna_MaterialSlot_material_set(PointerRNA *ptr,
PointerRNA value,
ReportList * /*reports*/)
static void rna_MaterialSlot_material_set(PointerRNA *ptr, PointerRNA value, ReportList *reports)
{
Object *ob = reinterpret_cast<Object *>(ptr->owner_id);
int index = rna_MaterialSlot_index(ptr);
Material *mat = reinterpret_cast<Material *>(value.data);
BLI_assert(BKE_id_is_in_global_main(&ob->id));
BLI_assert(BKE_id_is_in_global_main(static_cast<ID *>(value.data)));
BKE_object_material_assign(
G_MAIN, ob, static_cast<Material *>(value.data), index + 1, BKE_MAT_ASSIGN_EXISTING);
Main *ob_main = BKE_main_from_id(G_MAIN, &ob->id);
if (mat) {
if (ob_main != BKE_main_from_id(G_MAIN, &mat->id)) {
BKE_report(reports, RPT_ERROR, "Can't assign material from other main database");
return;
}
}
int index = rna_MaterialSlot_index(ptr);
BKE_object_material_assign(ob_main, ob, mat, index + 1, BKE_MAT_ASSIGN_EXISTING);
}
static bool rna_MaterialSlot_material_poll(PointerRNA *ptr, PointerRNA value)

View File

@ -245,6 +245,11 @@ static float rna_PoseChannel_length_get(PointerRNA *ptr)
static void rna_PoseChannel_name_set(PointerRNA *ptr, const char *value)
{
Object *ob = (Object *)ptr->owner_id;
Main *main = BKE_main_from_id(G_MAIN, &ob->id);
if (main == nullptr) {
return;
}
bPoseChannel *pchan = (bPoseChannel *)ptr->data;
char oldname[sizeof(pchan->name)], newname[sizeof(pchan->name)];
@ -252,9 +257,7 @@ static void rna_PoseChannel_name_set(PointerRNA *ptr, const char *value)
STRNCPY_UTF8(newname, value);
STRNCPY(oldname, pchan->name);
BLI_assert(BKE_id_is_in_global_main(&ob->id));
BLI_assert(BKE_id_is_in_global_main(static_cast<ID *>(ob->data)));
ED_armature_bone_rename(G_MAIN, static_cast<bArmature *>(ob->data), oldname, newname);
ED_armature_bone_rename(main, static_cast<bArmature *>(ob->data), oldname, newname);
}
/* See rna_Bone_update_renamed() */

View File

@ -1843,8 +1843,11 @@ void rna_ViewLayer_name_set(PointerRNA *ptr, const char *value)
{
Scene *scene = (Scene *)ptr->owner_id;
ViewLayer *view_layer = (ViewLayer *)ptr->data;
BLI_assert(BKE_id_is_in_global_main(&scene->id));
BKE_view_layer_rename(G_MAIN, scene, view_layer, value);
Main *main = BKE_main_from_id(G_MAIN, &scene->id);
if (main == nullptr) {
return;
}
BKE_view_layer_rename(main, scene, view_layer, value);
}
static void rna_SceneRenderView_name_set(PointerRNA *ptr, const char *value)

View File

@ -1720,9 +1720,13 @@ static void rna_SpaceImageEditor_image_set(PointerRNA *ptr,
PointerRNA value,
ReportList * /*reports*/)
{
BLI_assert(BKE_id_is_in_global_main(static_cast<ID *>(value.data)));
SpaceImage *sima = static_cast<SpaceImage *>(ptr->data);
ED_space_image_set(G_MAIN, sima, (Image *)value.data, false);
Image *image = reinterpret_cast<Image *>(value.data);
Main *main = BKE_main_from_id(G_MAIN, &image->id);
if (main == nullptr) {
return;
}
ED_space_image_set(main, sima, image, false);
}
static void rna_SpaceImageEditor_mask_set(PointerRNA *ptr,

View File

@ -20,6 +20,7 @@
#include "BKE_customdata.hh"
#include "BKE_global.hh"
#include "BKE_lib_id.hh"
#include "BKE_main.hh"
#include "BKE_mesh.hh"
#include "BKE_mesh_runtime.hh"
#include "BKE_object.hh"
@ -1226,8 +1227,7 @@ static PyObject *bpy_bmesh_to_mesh(BPy_BMesh *self, PyObject *args)
* anything in this case. */
}
else {
BLI_assert(BKE_id_is_in_global_main(&mesh->id));
bmain = G_MAIN; /* XXX UGLY! */
bmain = BKE_main_from_id(G_MAIN, &mesh->id); /* XXX UGLY! */
params.calc_object_remap = true;
}

View File

@ -18,7 +18,7 @@
#include "BLI_utildefines.h"
#include "BKE_global.hh"
#include "BKE_lib_id.hh" /* For #BKE_id_is_in_global_main. */
#include "BKE_main.hh"
#include "BKE_scene.hh"
#include "DNA_view3d_types.h"
@ -456,9 +456,8 @@ static PyObject *pygpu_offscreen_draw_view3d(BPyGPUOffScreen *self, PyObject *ar
return nullptr;
}
BLI_assert(BKE_id_is_in_global_main(&scene->id));
depsgraph = BKE_scene_ensure_depsgraph(G_MAIN, scene, view_layer);
Main *main = BKE_main_from_id(G_MAIN, &scene->id);
depsgraph = BKE_scene_ensure_depsgraph(main, scene, view_layer);
/* Disable 'bgl' state since it interfere with off-screen drawing, see: #84402. */
const bool is_bgl = GPU_bgl_get();

View File

@ -31,6 +31,7 @@
#include "BKE_global.hh"
#include "BKE_idtype.hh"
#include "BKE_lib_id.hh"
#include "BKE_main.hh"
#include "BKE_report.hh"
#include "RNA_access.hh"
@ -381,9 +382,9 @@ PyObject *pyrna_struct_keyframe_insert(BPy_StructRNA *self, PyObject *args, PyOb
}
else {
ID *id = self->ptr.owner_id;
Main *main = BKE_main_from_id(G_MAIN, id);
BLI_assert(BKE_id_is_in_global_main(id));
result = (blender::animrig::insert_keyframe(G_MAIN,
result = (blender::animrig::insert_keyframe(main,
&reports,
id,
nullptr,