WIP: Brush assets project #106303
|
@ -279,5 +279,5 @@ StatementMacros:
|
|||
MacroBlockBegin: "^OSL_CLOSURE_STRUCT_BEGIN$"
|
||||
MacroBlockEnd: "^OSL_CLOSURE_STRUCT_END$"
|
||||
|
||||
# Ensure lew line at the end of source files.
|
||||
# Ensure new line at the end of source files.
|
||||
InsertNewlineAtEOF: True
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <mutex>
|
||||
|
||||
#include "BLI_bit_span.hh"
|
||||
#include "BLI_index_mask_fwd.hh"
|
||||
#include "BLI_kdopbvh.h"
|
||||
#include "BLI_math_vector_types.hh"
|
||||
#include "BLI_span.hh"
|
||||
|
@ -114,6 +115,13 @@ BVHTree *BKE_bvhtree_from_mesh_get(BVHTreeFromMesh *data,
|
|||
BVHCacheType bvh_cache_type,
|
||||
int tree_type);
|
||||
|
||||
/**
|
||||
* Build a bvh tree from the triangles in the mesh that correspond to the faces in the given mask.
|
||||
*/
|
||||
void BKE_bvhtree_from_mesh_tris_init(const Mesh &mesh,
|
||||
const blender::IndexMask &faces_mask,
|
||||
BVHTreeFromMesh &r_data);
|
||||
|
||||
/**
|
||||
* Frees data allocated by a call to `bvhtree_from_mesh_*`.
|
||||
*/
|
||||
|
|
|
@ -109,6 +109,14 @@ struct IDTypeInfo {
|
|||
*/
|
||||
uint64_t id_filter;
|
||||
|
||||
/**
|
||||
* Known types of ID dependencies.
|
||||
*
|
||||
* Used by #BKE_library_id_can_use_filter_id, together with additional runtime heuristics, to
|
||||
* generate a filter value containing only ID types that given ID could be using.
|
||||
*/
|
||||
uint64_t dependencies_id_types;
|
||||
|
||||
/**
|
||||
* Define the position of this data-block type in the virtual list of all data in a Main that is
|
||||
* returned by `set_listbasepointers()`.
|
||||
|
@ -337,6 +345,24 @@ bool BKE_idtype_idcode_append_is_reusable(short idcode);
|
|||
*/
|
||||
short BKE_idtype_idcode_from_name(const char *idtype_name);
|
||||
|
||||
/**
|
||||
* Convert an \a idcode into an \a idtype_index (e.g. #ID_OB -> #INDEX_ID_OB).
|
||||
*/
|
||||
int BKE_idtype_idcode_to_index(short idcode);
|
||||
/**
|
||||
* Convert an \a idfilter into an \a idtype_index (e.g. #FILTER_ID_OB -> #INDEX_ID_OB).
|
||||
*/
|
||||
int BKE_idtype_idfilter_to_index(uint64_t idfilter);
|
||||
|
||||
/**
|
||||
* Convert an \a idtype_index into an \a idcode (e.g. #INDEX_ID_OB -> #ID_OB).
|
||||
*/
|
||||
short BKE_idtype_index_to_idcode(int idtype_index);
|
||||
/**
|
||||
* Convert an \a idtype_index into an \a idfilter (e.g. #INDEX_ID_OB -> #FILTER_ID_OB).
|
||||
*/
|
||||
uint64_t BKE_idtype_index_to_idfilter(int idtype_index);
|
||||
|
||||
/**
|
||||
* Convert an \a idcode into an \a idfilter (e.g. #ID_OB -> #FILTER_ID_OB).
|
||||
*/
|
||||
|
@ -344,16 +370,7 @@ uint64_t BKE_idtype_idcode_to_idfilter(short idcode);
|
|||
/**
|
||||
* Convert an \a idfilter into an \a idcode (e.g. #FILTER_ID_OB -> #ID_OB).
|
||||
*/
|
||||
short BKE_idtype_idcode_from_idfilter(uint64_t idfilter);
|
||||
|
||||
/**
|
||||
* Convert an \a idcode into an index (e.g. #ID_OB -> #INDEX_ID_OB).
|
||||
*/
|
||||
int BKE_idtype_idcode_to_index(short idcode);
|
||||
/**
|
||||
* Get an \a idcode from an index (e.g. #INDEX_ID_OB -> #ID_OB).
|
||||
*/
|
||||
short BKE_idtype_idcode_from_index(int index);
|
||||
short BKE_idtype_idfilter_to_idcode(uint64_t idfilter);
|
||||
|
||||
/**
|
||||
* Return an ID code and steps the index forward 1.
|
||||
|
@ -361,7 +378,7 @@ short BKE_idtype_idcode_from_index(int index);
|
|||
* \param index: start as 0.
|
||||
* \return the code, 0 when all codes have been returned.
|
||||
*/
|
||||
short BKE_idtype_idcode_iter_step(int *index);
|
||||
short BKE_idtype_idcode_iter_step(int *idtype_index);
|
||||
|
||||
/* Some helpers/wrappers around callbacks defined in #IDTypeInfo, dealing e.g. with embedded IDs.
|
||||
* XXX Ideally those would rather belong to #BKE_lib_id, but using callback function pointers makes
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
#include <array>
|
||||
|
||||
struct IDTypeInfo;
|
||||
struct LibraryForeachIDData;
|
||||
struct Main;
|
||||
|
||||
|
@ -299,7 +300,9 @@ bool BKE_library_id_can_use_idtype(ID *owner_id, short id_type_used);
|
|||
/**
|
||||
* Given the owner_id return the type of id_types it can use as a filter_id.
|
||||
*/
|
||||
uint64_t BKE_library_id_can_use_filter_id(const ID *owner_id, const bool include_ui);
|
||||
uint64_t BKE_library_id_can_use_filter_id(const ID *owner_id,
|
||||
const bool include_ui,
|
||||
const IDTypeInfo *owner_id_type = nullptr);
|
||||
|
||||
/**
|
||||
* Check whether given ID is used locally (i.e. by another non-linked ID).
|
||||
|
|
|
@ -290,6 +290,17 @@ inline int face_triangles_num(const int face_size)
|
|||
return face_size - 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the range of triangles that belong to the given face.
|
||||
*/
|
||||
inline IndexRange face_triangles_range(OffsetIndices<int> faces, int face_i)
|
||||
{
|
||||
const IndexRange face = faces[face_i];
|
||||
/* This is the same as #poly_to_tri_count which is not included here. */
|
||||
const int start_triangle = face.start() - face_i * 2;
|
||||
return IndexRange(start_triangle, face_triangles_num(face.size()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the index of the edge's vertex that is not the \a vert.
|
||||
*/
|
||||
|
|
|
@ -268,6 +268,7 @@ static AssetTypeInfo AssetType_AC = {
|
|||
IDTypeInfo IDType_ID_AC = {
|
||||
/*id_code*/ ID_AC,
|
||||
/*id_filter*/ FILTER_ID_AC,
|
||||
/*dependencies_id_types*/ 0,
|
||||
/*main_listbase_index*/ INDEX_ID_AC,
|
||||
/*struct_size*/ sizeof(bAction),
|
||||
/*name*/ "Action",
|
||||
|
|
|
@ -475,6 +475,8 @@ static void armature_undo_preserve(BlendLibReader * /*reader*/, ID *id_new, ID *
|
|||
IDTypeInfo IDType_ID_AR = {
|
||||
/*id_code*/ ID_AR,
|
||||
/*id_filter*/ FILTER_ID_AR,
|
||||
/* IDProps of armature bones can use any type of ID. */
|
||||
/*dependencies_id_types*/ FILTER_ID_ALL,
|
||||
/*main_listbase_index*/ INDEX_ID_AR,
|
||||
/*struct_size*/ sizeof(bArmature),
|
||||
/*name*/ "Armature",
|
||||
|
|
|
@ -426,6 +426,8 @@ static AssetTypeInfo AssetType_BR = {
|
|||
IDTypeInfo IDType_ID_BR = {
|
||||
/*id_code*/ ID_BR,
|
||||
/*id_filter*/ FILTER_ID_BR,
|
||||
/*dependencies_id_types*/
|
||||
(FILTER_ID_BR | FILTER_ID_IM | FILTER_ID_PC | FILTER_ID_TE | FILTER_ID_MA),
|
||||
/*main_listbase_index*/ INDEX_ID_BR,
|
||||
/*struct_size*/ sizeof(Brush),
|
||||
/*name*/ "Brush",
|
||||
|
|
|
@ -932,6 +932,53 @@ BVHTree *BKE_bvhtree_from_mesh_get(BVHTreeFromMesh *data,
|
|||
return data->tree;
|
||||
}
|
||||
|
||||
void BKE_bvhtree_from_mesh_tris_init(const Mesh &mesh,
|
||||
const blender::IndexMask &faces_mask,
|
||||
BVHTreeFromMesh &r_data)
|
||||
{
|
||||
using namespace blender;
|
||||
using namespace blender::bke;
|
||||
|
||||
const Span<float3> positions = mesh.vert_positions();
|
||||
const Span<int2> edges = mesh.edges();
|
||||
const Span<int> corner_verts = mesh.corner_verts();
|
||||
const OffsetIndices faces = mesh.faces();
|
||||
const Span<int3> corner_tris = mesh.corner_tris();
|
||||
bvhtree_from_mesh_setup_data(nullptr,
|
||||
BVHTREE_FROM_CORNER_TRIS,
|
||||
positions,
|
||||
edges,
|
||||
corner_verts,
|
||||
corner_tris,
|
||||
nullptr,
|
||||
&r_data);
|
||||
|
||||
int tris_num = 0;
|
||||
faces_mask.foreach_index(
|
||||
[&](const int i) { tris_num += mesh::face_triangles_num(faces[i].size()); });
|
||||
|
||||
int active_num = -1;
|
||||
BVHTree *tree = bvhtree_new_common(0.0f, 2, 6, tris_num, active_num);
|
||||
r_data.tree = tree;
|
||||
if (tree == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
faces_mask.foreach_index([&](const int face_i) {
|
||||
const IndexRange triangles_range = mesh::face_triangles_range(faces, face_i);
|
||||
for (const int tri_i : triangles_range) {
|
||||
float co[3][3];
|
||||
copy_v3_v3(co[0], positions[corner_verts[corner_tris[tri_i][0]]]);
|
||||
copy_v3_v3(co[1], positions[corner_verts[corner_tris[tri_i][1]]]);
|
||||
copy_v3_v3(co[2], positions[corner_verts[corner_tris[tri_i][2]]]);
|
||||
|
||||
BLI_bvhtree_insert(tree, tri_i, co[0], 3);
|
||||
}
|
||||
});
|
||||
|
||||
BLI_bvhtree_balance(tree);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
|
|
@ -121,6 +121,7 @@ static void cache_file_blend_read_data(BlendDataReader *reader, ID *id)
|
|||
IDTypeInfo IDType_ID_CF = {
|
||||
/*id_code*/ ID_CF,
|
||||
/*id_filter*/ FILTER_ID_CF,
|
||||
/*dependencies_id_types*/ 0,
|
||||
/*main_listbase_index*/ INDEX_ID_CF,
|
||||
/*struct_size*/ sizeof(CacheFile),
|
||||
/*name*/ "CacheFile",
|
||||
|
|
|
@ -229,6 +229,7 @@ static void camera_blend_read_data(BlendDataReader *reader, ID *id)
|
|||
IDTypeInfo IDType_ID_CA = {
|
||||
/*id_code*/ ID_CA,
|
||||
/*id_filter*/ FILTER_ID_CA,
|
||||
/*dependencies_id_types*/ FILTER_ID_OB | FILTER_ID_IM,
|
||||
/*main_listbase_index*/ INDEX_ID_CA,
|
||||
/*struct_size*/ sizeof(Camera),
|
||||
/*name*/ "Camera",
|
||||
|
|
|
@ -352,6 +352,7 @@ static void collection_blend_read_after_liblink(BlendLibReader * /*reader*/, ID
|
|||
IDTypeInfo IDType_ID_GR = {
|
||||
/*id_code*/ ID_GR,
|
||||
/*id_filter*/ FILTER_ID_GR,
|
||||
/*dependencies_id_types*/ FILTER_ID_OB | FILTER_ID_GR,
|
||||
/*main_listbase_index*/ INDEX_ID_GR,
|
||||
/*struct_size*/ sizeof(Collection),
|
||||
/*name*/ "Collection",
|
||||
|
|
|
@ -271,6 +271,7 @@ static void curve_blend_read_data(BlendDataReader *reader, ID *id)
|
|||
IDTypeInfo IDType_ID_CU_LEGACY = {
|
||||
/*id_code*/ ID_CU_LEGACY,
|
||||
/*id_filter*/ FILTER_ID_CU_LEGACY,
|
||||
/*dependencies_id_types*/ FILTER_ID_OB | FILTER_ID_MA | FILTER_ID_VF | FILTER_ID_KE,
|
||||
/*main_listbase_index*/ INDEX_ID_CU_LEGACY,
|
||||
/*struct_size*/ sizeof(Curve),
|
||||
/*name*/ "Curve",
|
||||
|
|
|
@ -133,6 +133,7 @@ static void curves_blend_read_data(BlendDataReader *reader, ID *id)
|
|||
IDTypeInfo IDType_ID_CV = {
|
||||
/*id_code*/ ID_CV,
|
||||
/*id_filter*/ FILTER_ID_CV,
|
||||
/*dependencies_id_types*/ FILTER_ID_MA | FILTER_ID_OB,
|
||||
/*main_listbase_index*/ INDEX_ID_CV,
|
||||
/*struct_size*/ sizeof(Curves),
|
||||
/*name*/ "Curves",
|
||||
|
|
|
@ -264,6 +264,7 @@ static void greasepencil_blend_read_data(BlendDataReader *reader, ID *id)
|
|||
IDTypeInfo IDType_ID_GD_LEGACY = {
|
||||
/*id_code*/ ID_GD_LEGACY,
|
||||
/*id_filter*/ FILTER_ID_GD_LEGACY,
|
||||
/*dependencies_id_types*/ FILTER_ID_MA,
|
||||
/*main_listbase_index*/ INDEX_ID_GD_LEGACY,
|
||||
/*struct_size*/ sizeof(bGPdata),
|
||||
/*name*/ "GPencil",
|
||||
|
|
|
@ -214,6 +214,7 @@ static void grease_pencil_blend_read_data(BlendDataReader *reader, ID *id)
|
|||
IDTypeInfo IDType_ID_GP = {
|
||||
/*id_code*/ ID_GP,
|
||||
/*id_filter*/ FILTER_ID_GP,
|
||||
/*dependencies_id_types*/ FILTER_ID_GP | FILTER_ID_MA,
|
||||
/*main_listbase_index*/ INDEX_ID_GP,
|
||||
/*struct_size*/ sizeof(GreasePencil),
|
||||
/*name*/ "GreasePencil",
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
* \ingroup bke
|
||||
*/
|
||||
|
||||
#include <array>
|
||||
#include <cstring>
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
@ -45,14 +46,17 @@ bool BKE_idtype_cache_key_cmp(const void *key_a_v, const void *key_b_v)
|
|||
(key_a->identifier != key_b->identifier);
|
||||
}
|
||||
|
||||
static IDTypeInfo *id_types[INDEX_ID_MAX] = {nullptr};
|
||||
static std::array<IDTypeInfo *, INDEX_ID_MAX> id_types;
|
||||
|
||||
static void id_type_init()
|
||||
{
|
||||
int init_types_num = 0;
|
||||
|
||||
#define INIT_TYPE(_id_code) \
|
||||
{ \
|
||||
BLI_assert(IDType_##_id_code.main_listbase_index == INDEX_##_id_code); \
|
||||
id_types[INDEX_##_id_code] = &IDType_##_id_code; \
|
||||
init_types_num++; \
|
||||
} \
|
||||
(void)0
|
||||
|
||||
|
@ -97,9 +101,12 @@ static void id_type_init()
|
|||
INIT_TYPE(ID_VO);
|
||||
INIT_TYPE(ID_GP);
|
||||
|
||||
/* Special naughty boy... */
|
||||
/* Special case. */
|
||||
BLI_assert(IDType_ID_LINK_PLACEHOLDER.main_listbase_index == INDEX_ID_NULL);
|
||||
id_types[INDEX_ID_NULL] = &IDType_ID_LINK_PLACEHOLDER;
|
||||
init_types_num++;
|
||||
|
||||
BLI_assert_msg(init_types_num == INDEX_ID_MAX, "Some IDTypeInfo initialization is missing");
|
||||
|
||||
#undef INIT_TYPE
|
||||
}
|
||||
|
@ -112,10 +119,11 @@ void BKE_idtype_init()
|
|||
|
||||
const IDTypeInfo *BKE_idtype_get_info_from_idtype_index(const int idtype_index)
|
||||
{
|
||||
if (idtype_index >= 0 && idtype_index < ARRAY_SIZE(id_types) &&
|
||||
id_types[idtype_index] != nullptr && id_types[idtype_index]->name[0] != '\0')
|
||||
{
|
||||
return id_types[idtype_index];
|
||||
if (idtype_index >= 0 && idtype_index < int(id_types.size())) {
|
||||
const IDTypeInfo *id_type = id_types[size_t(idtype_index)];
|
||||
if (id_type && id_type->name[0] != '\0') {
|
||||
return id_type;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
|
@ -133,9 +141,9 @@ const IDTypeInfo *BKE_idtype_get_info_from_id(const ID *id)
|
|||
|
||||
static const IDTypeInfo *idtype_get_info_from_name(const char *idtype_name)
|
||||
{
|
||||
for (int i = ARRAY_SIZE(id_types); i--;) {
|
||||
if (id_types[i] != nullptr && STREQ(idtype_name, id_types[i]->name)) {
|
||||
return id_types[i];
|
||||
for (const IDTypeInfo *id_type : id_types) {
|
||||
if (id_type && STREQ(idtype_name, id_type->name)) {
|
||||
return id_type;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -208,124 +216,6 @@ bool BKE_idtype_idcode_append_is_reusable(const short idcode)
|
|||
return false;
|
||||
}
|
||||
|
||||
uint64_t BKE_idtype_idcode_to_idfilter(const short idcode)
|
||||
{
|
||||
#define CASE_IDFILTER(_id) \
|
||||
case ID_##_id: \
|
||||
return FILTER_ID_##_id
|
||||
|
||||
#define CASE_IDFILTER_NONE(_id) \
|
||||
case ID_##_id: \
|
||||
return 0
|
||||
|
||||
switch ((ID_Type)idcode) {
|
||||
CASE_IDFILTER(AC);
|
||||
CASE_IDFILTER(AR);
|
||||
CASE_IDFILTER(BR);
|
||||
CASE_IDFILTER(CA);
|
||||
CASE_IDFILTER(CF);
|
||||
CASE_IDFILTER(CU_LEGACY);
|
||||
CASE_IDFILTER(GD_LEGACY);
|
||||
CASE_IDFILTER(GP);
|
||||
CASE_IDFILTER(GR);
|
||||
CASE_IDFILTER(CV);
|
||||
CASE_IDFILTER(IM);
|
||||
CASE_IDFILTER_NONE(IP);
|
||||
CASE_IDFILTER(KE);
|
||||
CASE_IDFILTER(LA);
|
||||
CASE_IDFILTER(LI);
|
||||
CASE_IDFILTER(LP);
|
||||
CASE_IDFILTER(LS);
|
||||
CASE_IDFILTER(LT);
|
||||
CASE_IDFILTER(MA);
|
||||
CASE_IDFILTER(MB);
|
||||
CASE_IDFILTER(MC);
|
||||
CASE_IDFILTER(ME);
|
||||
CASE_IDFILTER(MSK);
|
||||
CASE_IDFILTER(NT);
|
||||
CASE_IDFILTER(OB);
|
||||
CASE_IDFILTER(PA);
|
||||
CASE_IDFILTER(PAL);
|
||||
CASE_IDFILTER(PC);
|
||||
CASE_IDFILTER(PT);
|
||||
CASE_IDFILTER(SCE);
|
||||
CASE_IDFILTER(SCR);
|
||||
CASE_IDFILTER(SO);
|
||||
CASE_IDFILTER(SPK);
|
||||
CASE_IDFILTER(TE);
|
||||
CASE_IDFILTER(TXT);
|
||||
CASE_IDFILTER(VF);
|
||||
CASE_IDFILTER(VO);
|
||||
CASE_IDFILTER(WM);
|
||||
CASE_IDFILTER(WO);
|
||||
CASE_IDFILTER(WS);
|
||||
}
|
||||
|
||||
BLI_assert_unreachable();
|
||||
return 0;
|
||||
|
||||
#undef CASE_IDFILTER
|
||||
#undef CASE_IDFILTER_NONE
|
||||
}
|
||||
|
||||
short BKE_idtype_idcode_from_idfilter(const uint64_t idfilter)
|
||||
{
|
||||
#define CASE_IDFILTER(_id) \
|
||||
case FILTER_ID_##_id: \
|
||||
return ID_##_id
|
||||
|
||||
#define CASE_IDFILTER_NONE(_id) (void)0
|
||||
|
||||
switch (idfilter) {
|
||||
CASE_IDFILTER(AC);
|
||||
CASE_IDFILTER(AR);
|
||||
CASE_IDFILTER(BR);
|
||||
CASE_IDFILTER(CA);
|
||||
CASE_IDFILTER(CF);
|
||||
CASE_IDFILTER(CU_LEGACY);
|
||||
CASE_IDFILTER(GD_LEGACY);
|
||||
CASE_IDFILTER(GP);
|
||||
CASE_IDFILTER(GR);
|
||||
CASE_IDFILTER(CV);
|
||||
CASE_IDFILTER(IM);
|
||||
CASE_IDFILTER_NONE(IP);
|
||||
CASE_IDFILTER(KE);
|
||||
CASE_IDFILTER(LA);
|
||||
CASE_IDFILTER(LI);
|
||||
CASE_IDFILTER(LP);
|
||||
CASE_IDFILTER(LS);
|
||||
CASE_IDFILTER(LT);
|
||||
CASE_IDFILTER(MA);
|
||||
CASE_IDFILTER(MB);
|
||||
CASE_IDFILTER(MC);
|
||||
CASE_IDFILTER(ME);
|
||||
CASE_IDFILTER(MSK);
|
||||
CASE_IDFILTER(NT);
|
||||
CASE_IDFILTER(OB);
|
||||
CASE_IDFILTER(PA);
|
||||
CASE_IDFILTER(PAL);
|
||||
CASE_IDFILTER(PC);
|
||||
CASE_IDFILTER(PT);
|
||||
CASE_IDFILTER(SCE);
|
||||
CASE_IDFILTER(SCR);
|
||||
CASE_IDFILTER(SO);
|
||||
CASE_IDFILTER(SPK);
|
||||
CASE_IDFILTER(TE);
|
||||
CASE_IDFILTER(TXT);
|
||||
CASE_IDFILTER(VF);
|
||||
CASE_IDFILTER(VO);
|
||||
CASE_IDFILTER(WM);
|
||||
CASE_IDFILTER(WO);
|
||||
CASE_IDFILTER(WS);
|
||||
}
|
||||
|
||||
BLI_assert_unreachable();
|
||||
return 0;
|
||||
|
||||
#undef CASE_IDFILTER
|
||||
#undef CASE_IDFILTER_NONE
|
||||
}
|
||||
|
||||
int BKE_idtype_idcode_to_index(const short idcode)
|
||||
{
|
||||
#define CASE_IDINDEX(_id) \
|
||||
|
@ -385,68 +275,98 @@ int BKE_idtype_idcode_to_index(const short idcode)
|
|||
#undef CASE_IDINDEX
|
||||
}
|
||||
|
||||
short BKE_idtype_idcode_from_index(const int index)
|
||||
int BKE_idtype_idfilter_to_index(const uint64_t id_filter)
|
||||
{
|
||||
#define CASE_IDCODE(_id) \
|
||||
case INDEX_ID_##_id: \
|
||||
return ID_##_id
|
||||
#define CASE_IDINDEX(_id) \
|
||||
case FILTER_ID_##_id: \
|
||||
return INDEX_ID_##_id
|
||||
|
||||
switch (index) {
|
||||
CASE_IDCODE(AC);
|
||||
CASE_IDCODE(AR);
|
||||
CASE_IDCODE(BR);
|
||||
CASE_IDCODE(CA);
|
||||
CASE_IDCODE(CF);
|
||||
CASE_IDCODE(CU_LEGACY);
|
||||
CASE_IDCODE(GD_LEGACY);
|
||||
CASE_IDCODE(GP);
|
||||
CASE_IDCODE(GR);
|
||||
CASE_IDCODE(CV);
|
||||
CASE_IDCODE(IM);
|
||||
CASE_IDCODE(IP);
|
||||
CASE_IDCODE(KE);
|
||||
CASE_IDCODE(LA);
|
||||
CASE_IDCODE(LI);
|
||||
CASE_IDCODE(LS);
|
||||
CASE_IDCODE(LT);
|
||||
CASE_IDCODE(MA);
|
||||
CASE_IDCODE(MB);
|
||||
CASE_IDCODE(MC);
|
||||
CASE_IDCODE(ME);
|
||||
CASE_IDCODE(MSK);
|
||||
CASE_IDCODE(NT);
|
||||
CASE_IDCODE(OB);
|
||||
CASE_IDCODE(PA);
|
||||
CASE_IDCODE(PAL);
|
||||
CASE_IDCODE(PC);
|
||||
CASE_IDCODE(PT);
|
||||
CASE_IDCODE(LP);
|
||||
CASE_IDCODE(SCE);
|
||||
CASE_IDCODE(SCR);
|
||||
CASE_IDCODE(SPK);
|
||||
CASE_IDCODE(SO);
|
||||
CASE_IDCODE(TE);
|
||||
CASE_IDCODE(TXT);
|
||||
CASE_IDCODE(VF);
|
||||
CASE_IDCODE(VO);
|
||||
CASE_IDCODE(WM);
|
||||
CASE_IDCODE(WO);
|
||||
CASE_IDCODE(WS);
|
||||
switch (id_filter) {
|
||||
CASE_IDINDEX(AC);
|
||||
CASE_IDINDEX(AR);
|
||||
CASE_IDINDEX(BR);
|
||||
CASE_IDINDEX(CA);
|
||||
CASE_IDINDEX(CF);
|
||||
CASE_IDINDEX(CU_LEGACY);
|
||||
CASE_IDINDEX(GD_LEGACY);
|
||||
CASE_IDINDEX(GP);
|
||||
CASE_IDINDEX(GR);
|
||||
CASE_IDINDEX(CV);
|
||||
CASE_IDINDEX(IM);
|
||||
CASE_IDINDEX(IP);
|
||||
CASE_IDINDEX(KE);
|
||||
CASE_IDINDEX(LA);
|
||||
CASE_IDINDEX(LI);
|
||||
CASE_IDINDEX(LS);
|
||||
CASE_IDINDEX(LT);
|
||||
CASE_IDINDEX(MA);
|
||||
CASE_IDINDEX(MB);
|
||||
CASE_IDINDEX(MC);
|
||||
CASE_IDINDEX(ME);
|
||||
CASE_IDINDEX(MSK);
|
||||
CASE_IDINDEX(NT);
|
||||
CASE_IDINDEX(OB);
|
||||
CASE_IDINDEX(PA);
|
||||
CASE_IDINDEX(PAL);
|
||||
CASE_IDINDEX(PC);
|
||||
CASE_IDINDEX(PT);
|
||||
CASE_IDINDEX(LP);
|
||||
CASE_IDINDEX(SCE);
|
||||
CASE_IDINDEX(SCR);
|
||||
CASE_IDINDEX(SPK);
|
||||
CASE_IDINDEX(SO);
|
||||
CASE_IDINDEX(TE);
|
||||
CASE_IDINDEX(TXT);
|
||||
CASE_IDINDEX(VF);
|
||||
CASE_IDINDEX(VO);
|
||||
CASE_IDINDEX(WM);
|
||||
CASE_IDINDEX(WO);
|
||||
CASE_IDINDEX(WS);
|
||||
}
|
||||
|
||||
/* Special naughty boy... */
|
||||
if (index == INDEX_ID_NULL) {
|
||||
return ID_LINK_PLACEHOLDER;
|
||||
}
|
||||
/* No handling of #ID_LINK_PLACEHOLDER or #INDEX_ID_NULL here. */
|
||||
|
||||
return -1;
|
||||
|
||||
#undef CASE_IDCODE
|
||||
#undef CASE_IDINDEX
|
||||
}
|
||||
|
||||
short BKE_idtype_idcode_iter_step(int *index)
|
||||
short BKE_idtype_index_to_idcode(const int idtype_index)
|
||||
{
|
||||
return (*index < ARRAY_SIZE(id_types)) ? BKE_idtype_idcode_from_index((*index)++) : 0;
|
||||
const IDTypeInfo *id_type = BKE_idtype_get_info_from_idtype_index(idtype_index);
|
||||
if (id_type) {
|
||||
return id_type->id_code;
|
||||
}
|
||||
|
||||
BLI_assert_unreachable();
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint64_t BKE_idtype_index_to_idfilter(const int idtype_index)
|
||||
{
|
||||
const IDTypeInfo *id_type = BKE_idtype_get_info_from_idtype_index(idtype_index);
|
||||
if (id_type) {
|
||||
return id_type->id_filter;
|
||||
}
|
||||
|
||||
BLI_assert_unreachable();
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t BKE_idtype_idcode_to_idfilter(const short idcode)
|
||||
{
|
||||
return BKE_idtype_index_to_idfilter(BKE_idtype_idcode_to_index(idcode));
|
||||
}
|
||||
|
||||
short BKE_idtype_idfilter_to_idcode(const uint64_t idfilter)
|
||||
{
|
||||
return BKE_idtype_index_to_idcode(BKE_idtype_idfilter_to_index(idfilter));
|
||||
}
|
||||
|
||||
short BKE_idtype_idcode_iter_step(int *idtype_index)
|
||||
{
|
||||
return (*idtype_index < int(id_types.size())) ? BKE_idtype_index_to_idcode((*idtype_index)++) :
|
||||
0;
|
||||
}
|
||||
|
||||
void BKE_idtype_id_foreach_cache(ID *id,
|
||||
|
|
|
@ -440,6 +440,7 @@ constexpr IDTypeInfo get_type_info()
|
|||
IDTypeInfo info{};
|
||||
info.id_code = ID_IM;
|
||||
info.id_filter = FILTER_ID_IM;
|
||||
info.dependencies_id_types = 0;
|
||||
info.main_listbase_index = INDEX_ID_IM;
|
||||
info.struct_size = sizeof(Image);
|
||||
info.name = "Image";
|
||||
|
|
|
@ -156,7 +156,8 @@ static void ipo_blend_read_data(BlendDataReader *reader, ID *id)
|
|||
|
||||
IDTypeInfo IDType_ID_IP = {
|
||||
/*id_code*/ ID_IP,
|
||||
/*id_filter*/ 0,
|
||||
/*id_filter*/ FILTER_ID_IP,
|
||||
/*dependencies_id_types*/ 0,
|
||||
/*main_listbase_index*/ INDEX_ID_IP,
|
||||
/*struct_size*/ sizeof(Ipo),
|
||||
/*name*/ "Ipo",
|
||||
|
|
|
@ -191,6 +191,8 @@ static void shapekey_blend_read_after_liblink(BlendLibReader * /*reader*/, ID *i
|
|||
IDTypeInfo IDType_ID_KE = {
|
||||
/*id_code*/ ID_KE,
|
||||
/*id_filter*/ FILTER_ID_KE,
|
||||
/* Warning! key->from, could be more types in future? */
|
||||
/*dependencies_id_types*/ FILTER_ID_ME | FILTER_ID_CU_LEGACY | FILTER_ID_LT,
|
||||
/*main_listbase_index*/ INDEX_ID_KE,
|
||||
/*struct_size*/ sizeof(Key),
|
||||
/*name*/ "Key",
|
||||
|
|
|
@ -158,6 +158,7 @@ static void lattice_blend_read_data(BlendDataReader *reader, ID *id)
|
|||
IDTypeInfo IDType_ID_LT = {
|
||||
/*id_code*/ ID_LT,
|
||||
/*id_filter*/ FILTER_ID_LT,
|
||||
/*dependencies_id_types*/ FILTER_ID_KE,
|
||||
/*main_listbase_index*/ INDEX_ID_LT,
|
||||
/*struct_size*/ sizeof(Lattice),
|
||||
/*name*/ "Lattice",
|
||||
|
|
|
@ -84,6 +84,7 @@ static CLG_LogRef LOG = {"bke.lib_id"};
|
|||
IDTypeInfo IDType_ID_LINK_PLACEHOLDER = {
|
||||
/*id_code*/ ID_LINK_PLACEHOLDER,
|
||||
/*id_filter*/ 0,
|
||||
/*dependencies_id_types*/ 0,
|
||||
/*main_listbase_index*/ INDEX_ID_NULL,
|
||||
/*struct_size*/ sizeof(ID),
|
||||
/*name*/ "LinkPlaceholder",
|
||||
|
|
|
@ -396,28 +396,24 @@ void BKE_library_update_ID_link_user(ID *id_dst, ID *id_src, const int cb_flag)
|
|||
}
|
||||
}
|
||||
|
||||
uint64_t BKE_library_id_can_use_filter_id(const ID *owner_id, const bool include_ui)
|
||||
uint64_t BKE_library_id_can_use_filter_id(const ID *owner_id,
|
||||
const bool include_ui,
|
||||
const IDTypeInfo *owner_id_type)
|
||||
{
|
||||
/* any type of ID can be used in custom props. */
|
||||
if (owner_id->properties) {
|
||||
return FILTER_ID_ALL;
|
||||
}
|
||||
const short id_type_owner = GS(owner_id->name);
|
||||
|
||||
/* IDProps of armature bones and nodes, and bNode->id can use virtually any type of ID. */
|
||||
if (ELEM(id_type_owner, ID_NT, ID_AR)) {
|
||||
return FILTER_ID_ALL;
|
||||
}
|
||||
|
||||
/* Screen UI IDs can also link to virtually any ID (through e.g. the Outliner). */
|
||||
if (include_ui && id_type_owner == ID_SCR) {
|
||||
/* When including UI data (i.e. editors), Screen UI IDs can also link to virtually any ID
|
||||
* (through e.g. the Outliner). */
|
||||
if (include_ui && GS(owner_id->name) == ID_SCR) {
|
||||
return FILTER_ID_ALL;
|
||||
}
|
||||
|
||||
/* Casting to non const.
|
||||
* TODO(jbakker): We should introduce a ntree_id_has_tree function as we are actually not
|
||||
* interested in the result. */
|
||||
if (ntreeFromID((ID *)owner_id)) {
|
||||
if (ntreeFromID(const_cast<ID *>(owner_id))) {
|
||||
return FILTER_ID_ALL;
|
||||
}
|
||||
|
||||
|
@ -431,118 +427,21 @@ uint64_t BKE_library_id_can_use_filter_id(const ID *owner_id, const bool include
|
|||
return FILTER_ID_ALL;
|
||||
}
|
||||
|
||||
switch ((ID_Type)id_type_owner) {
|
||||
case ID_LI:
|
||||
return FILTER_ID_LI;
|
||||
case ID_SCE:
|
||||
return FILTER_ID_OB | FILTER_ID_WO | FILTER_ID_SCE | FILTER_ID_MC | FILTER_ID_MA |
|
||||
FILTER_ID_GR | FILTER_ID_TXT | FILTER_ID_LS | FILTER_ID_MSK | FILTER_ID_SO |
|
||||
FILTER_ID_GD_LEGACY | FILTER_ID_BR | FILTER_ID_PAL | FILTER_ID_IM | FILTER_ID_NT;
|
||||
case ID_OB:
|
||||
/* Could be more specific, but simpler to just always say 'yes' here. */
|
||||
return FILTER_ID_ALL;
|
||||
case ID_ME:
|
||||
return FILTER_ID_ME | FILTER_ID_MA | FILTER_ID_IM | FILTER_ID_KE;
|
||||
case ID_CU_LEGACY:
|
||||
return FILTER_ID_OB | FILTER_ID_MA | FILTER_ID_VF | FILTER_ID_KE;
|
||||
case ID_MB:
|
||||
return FILTER_ID_MA;
|
||||
case ID_MA:
|
||||
return FILTER_ID_TE | FILTER_ID_GR;
|
||||
case ID_TE:
|
||||
return FILTER_ID_IM | FILTER_ID_OB;
|
||||
case ID_LT:
|
||||
return 0;
|
||||
case ID_LA:
|
||||
return FILTER_ID_TE | FILTER_ID_KE;
|
||||
case ID_CA:
|
||||
return FILTER_ID_OB | FILTER_ID_IM;
|
||||
case ID_KE:
|
||||
/* Warning! key->from, could be more types in future? */
|
||||
return FILTER_ID_ME | FILTER_ID_CU_LEGACY | FILTER_ID_LT;
|
||||
case ID_SCR:
|
||||
return FILTER_ID_SCE;
|
||||
case ID_WO:
|
||||
return FILTER_ID_TE;
|
||||
case ID_SPK:
|
||||
return FILTER_ID_SO;
|
||||
case ID_GR:
|
||||
return FILTER_ID_OB | FILTER_ID_GR;
|
||||
case ID_NT:
|
||||
/* Could be more specific, but node.id has no type restriction... */
|
||||
return FILTER_ID_ALL;
|
||||
case ID_BR:
|
||||
return FILTER_ID_BR | FILTER_ID_IM | FILTER_ID_PC | FILTER_ID_TE | FILTER_ID_MA;
|
||||
case ID_PA:
|
||||
return FILTER_ID_OB | FILTER_ID_GR | FILTER_ID_TE;
|
||||
case ID_MC:
|
||||
return FILTER_ID_GD_LEGACY | FILTER_ID_IM;
|
||||
case ID_MSK:
|
||||
/* WARNING! mask->parent.id, not typed. */
|
||||
return FILTER_ID_MC;
|
||||
case ID_LS:
|
||||
return FILTER_ID_TE | FILTER_ID_OB;
|
||||
case ID_LP:
|
||||
return FILTER_ID_IM;
|
||||
case ID_GD_LEGACY:
|
||||
return FILTER_ID_MA;
|
||||
case ID_GP:
|
||||
return FILTER_ID_GP | FILTER_ID_MA;
|
||||
case ID_WS:
|
||||
return FILTER_ID_SCE;
|
||||
case ID_CV:
|
||||
return FILTER_ID_MA | FILTER_ID_OB;
|
||||
case ID_PT:
|
||||
return FILTER_ID_MA;
|
||||
case ID_VO:
|
||||
return FILTER_ID_MA;
|
||||
case ID_WM:
|
||||
return FILTER_ID_SCE | FILTER_ID_WS;
|
||||
case ID_IM:
|
||||
case ID_VF:
|
||||
case ID_TXT:
|
||||
case ID_SO:
|
||||
case ID_AR:
|
||||
case ID_AC:
|
||||
case ID_PAL:
|
||||
case ID_PC:
|
||||
case ID_CF:
|
||||
/* Those types never use/reference other IDs... */
|
||||
return 0;
|
||||
case ID_IP:
|
||||
/* Deprecated... */
|
||||
return 0;
|
||||
if (!owner_id_type) {
|
||||
owner_id_type = BKE_idtype_get_info_from_id(owner_id);
|
||||
}
|
||||
if (owner_id_type) {
|
||||
return owner_id_type->dependencies_id_types;
|
||||
}
|
||||
|
||||
BLI_assert_unreachable();
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool BKE_library_id_can_use_idtype(ID *owner_id, const short id_type_used)
|
||||
{
|
||||
/* any type of ID can be used in custom props. */
|
||||
if (owner_id->properties) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const short id_type_owner = GS(owner_id->name);
|
||||
/* Exception for ID_LI as they don't exist as a filter. */
|
||||
if (id_type_used == ID_LI) {
|
||||
return id_type_owner == ID_LI;
|
||||
}
|
||||
|
||||
/* Exception: ID_KE aren't available as filter_id. */
|
||||
if (id_type_used == ID_KE) {
|
||||
return ELEM(id_type_owner, ID_ME, ID_CU_LEGACY, ID_LT);
|
||||
}
|
||||
|
||||
/* Exception: ID_SCR aren't available as filter_id. */
|
||||
if (id_type_used == ID_SCR) {
|
||||
return ELEM(id_type_owner, ID_WS);
|
||||
}
|
||||
|
||||
const IDTypeInfo *owner_id_type = BKE_idtype_get_info_from_id(owner_id);
|
||||
const uint64_t filter_id_type_used = BKE_idtype_idcode_to_idfilter(id_type_used);
|
||||
const uint64_t can_be_used = BKE_library_id_can_use_filter_id(owner_id, false);
|
||||
const uint64_t can_be_used = BKE_library_id_can_use_filter_id(owner_id, false, owner_id_type);
|
||||
return (can_be_used & filter_id_type_used) != 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -81,6 +81,7 @@ static void library_blend_read_data(BlendDataReader * /*reader*/, ID *id)
|
|||
IDTypeInfo IDType_ID_LI = {
|
||||
/*id_code*/ ID_LI,
|
||||
/*id_filter*/ FILTER_ID_LI,
|
||||
/*dependencies_id_types*/ FILTER_ID_LI,
|
||||
/*main_listbase_index*/ INDEX_ID_LI,
|
||||
/*struct_size*/ sizeof(Library),
|
||||
/*name*/ "Library",
|
||||
|
|
|
@ -152,6 +152,7 @@ static void light_blend_read_data(BlendDataReader *reader, ID *id)
|
|||
IDTypeInfo IDType_ID_LA = {
|
||||
/*id_code*/ ID_LA,
|
||||
/*id_filter*/ FILTER_ID_LA,
|
||||
/*dependencies_id_types*/ FILTER_ID_TE,
|
||||
/*main_listbase_index*/ INDEX_ID_LA,
|
||||
/*struct_size*/ sizeof(Light),
|
||||
/*name*/ "Light",
|
||||
|
|
|
@ -53,6 +53,7 @@ static void lightprobe_blend_write(BlendWriter *writer, ID *id, const void *id_a
|
|||
IDTypeInfo IDType_ID_LP = {
|
||||
/*id_code*/ ID_LP,
|
||||
/*id_filter*/ FILTER_ID_LP,
|
||||
/*dependencies_id_types*/ FILTER_ID_IM,
|
||||
/*main_listbase_index*/ INDEX_ID_LP,
|
||||
/*struct_size*/ sizeof(LightProbe),
|
||||
/*name*/ "LightProbe",
|
||||
|
|
|
@ -643,6 +643,7 @@ static void linestyle_blend_read_data(BlendDataReader *reader, ID *id)
|
|||
IDTypeInfo IDType_ID_LS = {
|
||||
/*id_code*/ ID_LS,
|
||||
/*id_filter*/ FILTER_ID_LS,
|
||||
/*dependencies_id_types*/ FILTER_ID_TE | FILTER_ID_OB,
|
||||
/*main_listbase_index*/ INDEX_ID_LS,
|
||||
/*struct_size*/ sizeof(FreestyleLineStyle),
|
||||
/*name*/ "FreestyleLineStyle",
|
||||
|
|
|
@ -184,6 +184,7 @@ static void mask_blend_read_data(BlendDataReader *reader, ID *id)
|
|||
IDTypeInfo IDType_ID_MSK = {
|
||||
/*id_code*/ ID_MSK,
|
||||
/*id_filter*/ FILTER_ID_MSK,
|
||||
/*dependencies_id_types*/ FILTER_ID_MC, /* WARNING! mask->parent.id, not typed. */
|
||||
/*main_listbase_index*/ INDEX_ID_MSK,
|
||||
/*struct_size*/ sizeof(Mask),
|
||||
/*name*/ "Mask",
|
||||
|
|
|
@ -231,6 +231,7 @@ static void material_blend_read_data(BlendDataReader *reader, ID *id)
|
|||
IDTypeInfo IDType_ID_MA = {
|
||||
/*id_code*/ ID_MA,
|
||||
/*id_filter*/ FILTER_ID_MA,
|
||||
/*dependencies_id_types*/ FILTER_ID_TE | FILTER_ID_GR,
|
||||
/*main_listbase_index*/ INDEX_ID_MA,
|
||||
/*struct_size*/ sizeof(Material),
|
||||
/*name*/ "Material",
|
||||
|
|
|
@ -140,6 +140,7 @@ static void metaball_blend_read_data(BlendDataReader *reader, ID *id)
|
|||
IDTypeInfo IDType_ID_MB = {
|
||||
/*id_code*/ ID_MB,
|
||||
/*id_filter*/ FILTER_ID_MB,
|
||||
/*dependencies_id_types*/ FILTER_ID_MA,
|
||||
/*main_listbase_index*/ INDEX_ID_MB,
|
||||
/*struct_size*/ sizeof(MetaBall),
|
||||
/*name*/ "Metaball",
|
||||
|
|
|
@ -383,6 +383,7 @@ static void mesh_blend_read_data(BlendDataReader *reader, ID *id)
|
|||
IDTypeInfo IDType_ID_ME = {
|
||||
/*id_code*/ ID_ME,
|
||||
/*id_filter*/ FILTER_ID_ME,
|
||||
/*dependencies_id_types*/ FILTER_ID_ME | FILTER_ID_MA | FILTER_ID_IM | FILTER_ID_KE,
|
||||
/*main_listbase_index*/ INDEX_ID_ME,
|
||||
/*struct_size*/ sizeof(Mesh),
|
||||
/*name*/ "Mesh",
|
||||
|
|
|
@ -279,6 +279,7 @@ static void movieclip_blend_read_data(BlendDataReader *reader, ID *id)
|
|||
IDTypeInfo IDType_ID_MC = {
|
||||
/*id_code*/ ID_MC,
|
||||
/*id_filter*/ FILTER_ID_MC,
|
||||
/*dependencies_id_types*/ FILTER_ID_GD_LEGACY | FILTER_ID_IM,
|
||||
/*main_listbase_index*/ INDEX_ID_MC,
|
||||
/*struct_size*/ sizeof(MovieClip),
|
||||
/*name*/ "MovieClip",
|
||||
|
|
|
@ -1272,6 +1272,8 @@ static AssetTypeInfo AssetType_NT = {
|
|||
IDTypeInfo IDType_ID_NT = {
|
||||
/*id_code*/ ID_NT,
|
||||
/*id_filter*/ FILTER_ID_NT,
|
||||
/* IDProps of nodes, and #bNode.id, can use any type of ID. */
|
||||
/*dependencies_id_types*/ FILTER_ID_ALL,
|
||||
/*main_listbase_index*/ INDEX_ID_NT,
|
||||
/*struct_size*/ sizeof(bNodeTree),
|
||||
/*name*/ "NodeTree",
|
||||
|
|
|
@ -1077,6 +1077,8 @@ static AssetTypeInfo AssetType_OB = {
|
|||
IDTypeInfo IDType_ID_OB = {
|
||||
/*id_code*/ ID_OB,
|
||||
/*id_filter*/ FILTER_ID_OB,
|
||||
/* Could be more specific, but simpler to just always say 'yes' here. */
|
||||
/*dependencies_id_types*/ FILTER_ID_ALL,
|
||||
/*main_listbase_index*/ INDEX_ID_OB,
|
||||
/*struct_size*/ sizeof(Object),
|
||||
/*name*/ "Object",
|
||||
|
|
|
@ -147,6 +147,7 @@ static void palette_undo_preserve(BlendLibReader * /*reader*/, ID *id_new, ID *i
|
|||
IDTypeInfo IDType_ID_PAL = {
|
||||
/*id_code*/ ID_PAL,
|
||||
/*id_filter*/ FILTER_ID_PAL,
|
||||
/*dependencies_id_types*/ 0,
|
||||
/*main_listbase_index*/ INDEX_ID_PAL,
|
||||
/*struct_size*/ sizeof(Palette),
|
||||
/*name*/ "Palette",
|
||||
|
@ -214,6 +215,7 @@ static void paint_curve_blend_read_data(BlendDataReader *reader, ID *id)
|
|||
IDTypeInfo IDType_ID_PC = {
|
||||
/*id_code*/ ID_PC,
|
||||
/*id_filter*/ FILTER_ID_PC,
|
||||
/*dependencies_id_types*/ 0,
|
||||
/*main_listbase_index*/ INDEX_ID_PC,
|
||||
/*struct_size*/ sizeof(PaintCurve),
|
||||
/*name*/ "PaintCurve",
|
||||
|
|
|
@ -379,6 +379,7 @@ static void particle_settings_blend_read_after_liblink(BlendLibReader * /*reader
|
|||
IDTypeInfo IDType_ID_PA = {
|
||||
/*id_code*/ ID_PA,
|
||||
/*id_filter*/ FILTER_ID_PA,
|
||||
/*dependencies_id_types*/ FILTER_ID_OB | FILTER_ID_GR | FILTER_ID_TE,
|
||||
/*main_listbase_index*/ INDEX_ID_PA,
|
||||
/*struct_size*/ sizeof(ParticleSettings),
|
||||
/*name*/ "ParticleSettings",
|
||||
|
|
|
@ -146,6 +146,7 @@ static void pointcloud_blend_read_data(BlendDataReader *reader, ID *id)
|
|||
IDTypeInfo IDType_ID_PT = {
|
||||
/*id_code*/ ID_PT,
|
||||
/*id_filter*/ FILTER_ID_PT,
|
||||
/*dependencies_id_types*/ FILTER_ID_MA,
|
||||
/*main_listbase_index*/ INDEX_ID_PT,
|
||||
/*struct_size*/ sizeof(PointCloud),
|
||||
/*name*/ "PointCloud",
|
||||
|
|
|
@ -1604,6 +1604,10 @@ constexpr IDTypeInfo get_type_info()
|
|||
IDTypeInfo info{};
|
||||
info.id_code = ID_SCE;
|
||||
info.id_filter = FILTER_ID_SCE;
|
||||
info.dependencies_id_types = (FILTER_ID_OB | FILTER_ID_WO | FILTER_ID_SCE | FILTER_ID_MC |
|
||||
FILTER_ID_MA | FILTER_ID_GR | FILTER_ID_TXT | FILTER_ID_LS |
|
||||
FILTER_ID_MSK | FILTER_ID_SO | FILTER_ID_GD_LEGACY | FILTER_ID_BR |
|
||||
FILTER_ID_PAL | FILTER_ID_IM | FILTER_ID_NT);
|
||||
info.main_listbase_index = INDEX_ID_SCE;
|
||||
info.struct_size = sizeof(Scene);
|
||||
info.name = "Scene";
|
||||
|
|
|
@ -159,6 +159,9 @@ static void screen_blend_read_after_liblink(BlendLibReader *reader, ID *id)
|
|||
IDTypeInfo IDType_ID_SCR = {
|
||||
/*id_code*/ ID_SCR,
|
||||
/*id_filter*/ FILTER_ID_SCR,
|
||||
/* NOTE: Can actually link to any ID type through UI (e.g. Outliner Editor). This is handled
|
||||
separately though. */
|
||||
/*dependencies_id_types*/ FILTER_ID_SCE,
|
||||
/*main_listbase_index*/ INDEX_ID_SCR,
|
||||
/*struct_size*/ sizeof(bScreen),
|
||||
/*name*/ "Screen",
|
||||
|
|
|
@ -189,6 +189,7 @@ static void sound_blend_read_data(BlendDataReader *reader, ID *id)
|
|||
IDTypeInfo IDType_ID_SO = {
|
||||
/*id_code*/ ID_SO,
|
||||
/*id_filter*/ FILTER_ID_SO,
|
||||
/*dependencies_id_types*/ 0,
|
||||
/*main_listbase_index*/ INDEX_ID_SO,
|
||||
/*struct_size*/ sizeof(bSound),
|
||||
/*name*/ "Sound",
|
||||
|
|
|
@ -51,6 +51,7 @@ static void speaker_blend_write(BlendWriter *writer, ID *id, const void *id_addr
|
|||
IDTypeInfo IDType_ID_SPK = {
|
||||
/*id_code*/ ID_SPK,
|
||||
/*id_filter*/ FILTER_ID_SPK,
|
||||
/*dependencies_id_types*/ FILTER_ID_SO,
|
||||
/*main_listbase_index*/ INDEX_ID_SPK,
|
||||
/*struct_size*/ sizeof(Speaker),
|
||||
/*name*/ "Speaker",
|
||||
|
|
|
@ -222,6 +222,7 @@ static void text_blend_read_data(BlendDataReader *reader, ID *id)
|
|||
IDTypeInfo IDType_ID_TXT = {
|
||||
/*id_code*/ ID_TXT,
|
||||
/*id_filter*/ FILTER_ID_TXT,
|
||||
/*dependencies_id_types*/ 0,
|
||||
/*main_listbase_index*/ INDEX_ID_TXT,
|
||||
/*struct_size*/ sizeof(Text),
|
||||
/*name*/ "Text",
|
||||
|
|
|
@ -188,6 +188,7 @@ static void texture_blend_read_data(BlendDataReader *reader, ID *id)
|
|||
IDTypeInfo IDType_ID_TE = {
|
||||
/*id_code*/ ID_TE,
|
||||
/*id_filter*/ FILTER_ID_TE,
|
||||
/*dependencies_id_types*/ FILTER_ID_IM | FILTER_ID_OB,
|
||||
/*main_listbase_index*/ INDEX_ID_TE,
|
||||
/*struct_size*/ sizeof(Tex),
|
||||
/*name*/ "Texture",
|
||||
|
|
|
@ -163,6 +163,7 @@ static void vfont_blend_read_data(BlendDataReader *reader, ID *id)
|
|||
IDTypeInfo IDType_ID_VF = {
|
||||
/*id_code*/ ID_VF,
|
||||
/*id_filter*/ FILTER_ID_VF,
|
||||
/*dependencies_id_types*/ 0,
|
||||
/*main_listbase_index*/ INDEX_ID_VF,
|
||||
/*struct_size*/ sizeof(VFont),
|
||||
/*name*/ "Font",
|
||||
|
|
|
@ -273,6 +273,7 @@ static void volume_blend_read_after_liblink(BlendLibReader * /*reader*/, ID *id)
|
|||
IDTypeInfo IDType_ID_VO = {
|
||||
/*id_code*/ ID_VO,
|
||||
/*id_filter*/ FILTER_ID_VO,
|
||||
/*dependencies_id_types*/ FILTER_ID_MA,
|
||||
/*main_listbase_index*/ INDEX_ID_VO,
|
||||
/*struct_size*/ sizeof(Volume),
|
||||
/*name*/ "Volume",
|
||||
|
|
|
@ -169,6 +169,7 @@ static void workspace_blend_read_after_liblink(BlendLibReader *reader, ID *id)
|
|||
IDTypeInfo IDType_ID_WS = {
|
||||
/*id_code*/ ID_WS,
|
||||
/*id_filter*/ FILTER_ID_WS,
|
||||
/*dependencies_id_types*/ FILTER_ID_SCE,
|
||||
/*main_listbase_index*/ INDEX_ID_WS,
|
||||
/*struct_size*/ sizeof(WorkSpace),
|
||||
/*name*/ "WorkSpace",
|
||||
|
|
|
@ -177,6 +177,7 @@ static void world_blend_read_data(BlendDataReader *reader, ID *id)
|
|||
IDTypeInfo IDType_ID_WO = {
|
||||
/*id_code*/ ID_WO,
|
||||
/*id_filter*/ FILTER_ID_WO,
|
||||
/*dependencies_id_types*/ FILTER_ID_TE,
|
||||
/*main_listbase_index*/ INDEX_ID_WO,
|
||||
/*struct_size*/ sizeof(World),
|
||||
/*name*/ "World",
|
||||
|
|
|
@ -44,7 +44,8 @@ static void draw_node_input(bContext *C,
|
|||
BLI_assert(socket.typeinfo != nullptr);
|
||||
/* Ignore disabled sockets and linked sockets and sockets without a `draw` callback. */
|
||||
if (!socket.is_available() || (socket.flag & (SOCK_IS_LINKED | SOCK_HIDE_VALUE)) ||
|
||||
socket.typeinfo->draw == nullptr || ELEM(socket.type, SOCK_GEOMETRY, SOCK_MATRIX))
|
||||
socket.typeinfo->draw == nullptr ||
|
||||
ELEM(socket.type, SOCK_GEOMETRY, SOCK_MATRIX, SOCK_SHADER))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -2024,6 +2024,17 @@ static int paint_mask_gesture_line_exec(bContext *C, wmOperator *op)
|
|||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static int face_set_gesture_box_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
{
|
||||
const View3D *v3d = CTX_wm_view3d(C);
|
||||
const Base *base = CTX_data_active_base(C);
|
||||
if (!BKE_base_is_visible(v3d, base)) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
return WM_gesture_box_invoke(C, op, event);
|
||||
}
|
||||
|
||||
static int face_set_gesture_box_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
SculptGestureContext *sgcontext = sculpt_gesture_init_from_box(C, op);
|
||||
|
@ -2036,6 +2047,17 @@ static int face_set_gesture_box_exec(bContext *C, wmOperator *op)
|
|||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static int face_set_gesture_lasso_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
{
|
||||
const View3D *v3d = CTX_wm_view3d(C);
|
||||
const Base *base = CTX_data_active_base(C);
|
||||
if (!BKE_base_is_visible(v3d, base)) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
return WM_gesture_lasso_invoke(C, op, event);
|
||||
}
|
||||
|
||||
static int face_set_gesture_lasso_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
SculptGestureContext *sgcontext = sculpt_gesture_init_from_lasso(C, op);
|
||||
|
@ -2228,7 +2250,7 @@ void SCULPT_OT_face_set_lasso_gesture(wmOperatorType *ot)
|
|||
ot->idname = "SCULPT_OT_face_set_lasso_gesture";
|
||||
ot->description = "Add face set within the lasso as you move the brush";
|
||||
|
||||
ot->invoke = WM_gesture_lasso_invoke;
|
||||
ot->invoke = face_set_gesture_lasso_invoke;
|
||||
ot->modal = WM_gesture_lasso_modal;
|
||||
ot->exec = face_set_gesture_lasso_exec;
|
||||
|
||||
|
@ -2247,7 +2269,7 @@ void SCULPT_OT_face_set_box_gesture(wmOperatorType *ot)
|
|||
ot->idname = "SCULPT_OT_face_set_box_gesture";
|
||||
ot->description = "Add face set within the box as you move the brush";
|
||||
|
||||
ot->invoke = WM_gesture_box_invoke;
|
||||
ot->invoke = face_set_gesture_box_invoke;
|
||||
ot->modal = WM_gesture_box_modal;
|
||||
ot->exec = face_set_gesture_box_exec;
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "BKE_collision.h"
|
||||
#include "BKE_colortools.hh"
|
||||
#include "BKE_context.hh"
|
||||
#include "BKE_layer.hh"
|
||||
#include "BKE_mesh.hh"
|
||||
#include "BKE_modifier.hh"
|
||||
#include "BKE_paint.hh"
|
||||
|
@ -1530,6 +1531,12 @@ static int sculpt_cloth_filter_invoke(bContext *C, wmOperator *op, const wmEvent
|
|||
Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
|
||||
SculptSession *ss = ob->sculpt;
|
||||
|
||||
const View3D *v3d = CTX_wm_view3d(C);
|
||||
const Base *base = CTX_data_active_base(C);
|
||||
if (!BKE_base_is_visible(v3d, base)) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
const eSculptClothFilterType filter_type = eSculptClothFilterType(RNA_enum_get(op->ptr, "type"));
|
||||
|
||||
/* Update the active vertex */
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "BKE_colortools.hh"
|
||||
#include "BKE_context.hh"
|
||||
#include "BKE_customdata.hh"
|
||||
#include "BKE_layer.hh"
|
||||
#include "BKE_mesh.hh"
|
||||
#include "BKE_mesh_fair.hh"
|
||||
#include "BKE_mesh_mapping.hh"
|
||||
|
@ -557,6 +558,12 @@ static int sculpt_face_set_create_exec(bContext *C, wmOperator *op)
|
|||
|
||||
const CreateMode mode = CreateMode(RNA_enum_get(op->ptr, "mode"));
|
||||
|
||||
const View3D *v3d = CTX_wm_view3d(C);
|
||||
const Base *base = CTX_data_active_base(C);
|
||||
if (!BKE_base_is_visible(v3d, base)) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
if (BKE_pbvh_type(ss.pbvh) == PBVH_BMESH) {
|
||||
/* Dyntopo not supported. */
|
||||
return OPERATOR_CANCELLED;
|
||||
|
@ -780,6 +787,12 @@ static int sculpt_face_set_init_exec(bContext *C, wmOperator *op)
|
|||
|
||||
const InitMode mode = InitMode(RNA_enum_get(op->ptr, "mode"));
|
||||
|
||||
const View3D *v3d = CTX_wm_view3d(C);
|
||||
const Base *base = CTX_data_active_base(C);
|
||||
if (!BKE_base_is_visible(v3d, base)) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
BKE_sculpt_update_object_for_edit(depsgraph, ob, false);
|
||||
|
||||
/* Dyntopo not supported. */
|
||||
|
@ -1126,6 +1139,12 @@ static int sculpt_face_set_change_visibility_invoke(bContext *C,
|
|||
Object *ob = CTX_data_active_object(C);
|
||||
SculptSession *ss = ob->sculpt;
|
||||
|
||||
const View3D *v3d = CTX_wm_view3d(C);
|
||||
const Base *base = CTX_data_active_base(C);
|
||||
if (!BKE_base_is_visible(v3d, base)) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
/* Update the active vertex and Face Set using the cursor position to avoid relying on the paint
|
||||
* cursor updates. */
|
||||
SculptCursorGeometryInfo sgi;
|
||||
|
@ -1174,6 +1193,12 @@ static int sculpt_face_sets_randomize_colors_exec(bContext *C, wmOperator * /*op
|
|||
Object *ob = CTX_data_active_object(C);
|
||||
SculptSession *ss = ob->sculpt;
|
||||
|
||||
const View3D *v3d = CTX_wm_view3d(C);
|
||||
const Base *base = CTX_data_active_base(C);
|
||||
if (!BKE_base_is_visible(v3d, base)) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
/* Dyntopo not supported. */
|
||||
if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
|
||||
return OPERATOR_CANCELLED;
|
||||
|
@ -1546,6 +1571,12 @@ static int sculpt_face_set_edit_invoke(bContext *C, wmOperator *op, const wmEven
|
|||
Object *ob = CTX_data_active_object(C);
|
||||
SculptSession *ss = ob->sculpt;
|
||||
|
||||
const View3D *v3d = CTX_wm_view3d(C);
|
||||
const Base *base = CTX_data_active_base(C);
|
||||
if (!BKE_base_is_visible(v3d, base)) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
BKE_sculpt_update_object_for_edit(depsgraph, ob, false);
|
||||
|
||||
/* Update the current active Face Set and Vertex as the operator can be used directly from the
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "DNA_userdef_types.h"
|
||||
|
||||
#include "BKE_context.hh"
|
||||
#include "BKE_layer.hh"
|
||||
#include "BKE_paint.hh"
|
||||
#include "BKE_pbvh_api.hh"
|
||||
|
||||
|
@ -330,6 +331,11 @@ static int sculpt_color_filter_init(bContext *C, wmOperator *op)
|
|||
SculptSession *ss = ob->sculpt;
|
||||
View3D *v3d = CTX_wm_view3d(C);
|
||||
|
||||
const Base *base = CTX_data_active_base(C);
|
||||
if (!BKE_base_is_visible(v3d, base)) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
int mval[2];
|
||||
RNA_int_get_array(op->ptr, "start_mouse", mval);
|
||||
float mval_fl[2] = {float(mval[0]), float(mval[1])};
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "BLI_task.h"
|
||||
|
||||
#include "BKE_context.hh"
|
||||
#include "BKE_layer.hh"
|
||||
#include "BKE_paint.hh"
|
||||
#include "BKE_pbvh_api.hh"
|
||||
|
||||
|
@ -160,6 +161,12 @@ static int sculpt_mask_filter_exec(bContext *C, wmOperator *op)
|
|||
const Scene *scene = CTX_data_scene(C);
|
||||
int filter_type = RNA_enum_get(op->ptr, "filter_type");
|
||||
|
||||
const View3D *v3d = CTX_wm_view3d(C);
|
||||
const Base *base = CTX_data_active_base(C);
|
||||
if (!BKE_base_is_visible(v3d, base)) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
MultiresModifierData *mmd = BKE_sculpt_multires_active(scene, ob);
|
||||
BKE_sculpt_mask_layers_ensure(CTX_data_depsgraph_pointer(C), CTX_data_main(C), ob, mmd);
|
||||
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
|
||||
#include "BKE_brush.hh"
|
||||
#include "BKE_context.hh"
|
||||
#include "BKE_layer.hh"
|
||||
#include "BKE_modifier.hh"
|
||||
#include "BKE_object_types.hh"
|
||||
#include "BKE_paint.hh"
|
||||
#include "BKE_pbvh_api.hh"
|
||||
|
@ -948,6 +950,13 @@ static int sculpt_mesh_filter_start(bContext *C, wmOperator *op)
|
|||
Object *ob = CTX_data_active_object(C);
|
||||
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
|
||||
Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
|
||||
|
||||
const View3D *v3d = CTX_wm_view3d(C);
|
||||
const Base *base = CTX_data_active_base(C);
|
||||
if (!BKE_base_is_visible(v3d, base)) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
int mval[2];
|
||||
RNA_int_get_array(op->ptr, "start_mouse", mval);
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include "BKE_ccg.h"
|
||||
#include "BKE_context.hh"
|
||||
#include "BKE_layer.hh"
|
||||
#include "BKE_multires.hh"
|
||||
#include "BKE_paint.hh"
|
||||
#include "BKE_pbvh_api.hh"
|
||||
|
@ -80,6 +81,12 @@ static int sculpt_mask_init_exec(bContext *C, wmOperator *op)
|
|||
SculptSession *ss = ob->sculpt;
|
||||
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
|
||||
|
||||
const View3D *v3d = CTX_wm_view3d(C);
|
||||
const Base *base = CTX_data_active_base(C);
|
||||
if (!BKE_base_is_visible(v3d, base)) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
const int mode = RNA_enum_get(op->ptr, "mode");
|
||||
|
||||
MultiresModifierData *mmd = BKE_sculpt_multires_active(CTX_data_scene(C), ob);
|
||||
|
|
|
@ -638,6 +638,12 @@ static int sculpt_sample_color_invoke(bContext *C, wmOperator *op, const wmEvent
|
|||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
const View3D *v3d = CTX_wm_view3d(C);
|
||||
const Base *base = CTX_data_active_base(C);
|
||||
if (!BKE_base_is_visible(v3d, base)) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
BKE_sculpt_update_object_for_edit(CTX_data_depsgraph_pointer(C), ob, false);
|
||||
|
||||
/* No color attribute? Set color to white. */
|
||||
|
@ -902,14 +908,19 @@ static int sculpt_mask_by_color_invoke(bContext *C, wmOperator *op, const wmEven
|
|||
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
|
||||
Object *ob = CTX_data_active_object(C);
|
||||
SculptSession *ss = ob->sculpt;
|
||||
View3D *v3d = CTX_wm_view3d(C);
|
||||
|
||||
{
|
||||
View3D *v3d = CTX_wm_view3d(C);
|
||||
if (v3d && v3d->shading.type == OB_SOLID) {
|
||||
v3d->shading.color_type = V3D_SHADING_VERTEX_COLOR;
|
||||
}
|
||||
}
|
||||
|
||||
const Base *base = CTX_data_active_base(C);
|
||||
if (!BKE_base_is_visible(v3d, base)) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
/* Color data is not available in multi-resolution or dynamic topology. */
|
||||
if (!SCULPT_handles_colors_report(ss, op->reports)) {
|
||||
return OPERATOR_CANCELLED;
|
||||
|
@ -1067,6 +1078,12 @@ static int sculpt_bake_cavity_exec(bContext *C, wmOperator *op)
|
|||
Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
|
||||
const Brush *brush = BKE_paint_brush(&sd->paint);
|
||||
|
||||
const View3D *v3d = CTX_wm_view3d(C);
|
||||
const Base *base = CTX_data_active_base(C);
|
||||
if (!BKE_base_is_visible(v3d, base)) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
MultiresModifierData *mmd = BKE_sculpt_multires_active(CTX_data_scene(C), ob);
|
||||
BKE_sculpt_mask_layers_ensure(depsgraph, CTX_data_main(C), ob, mmd);
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "BKE_brush.hh"
|
||||
#include "BKE_context.hh"
|
||||
#include "BKE_kelvinlet.h"
|
||||
#include "BKE_layer.hh"
|
||||
#include "BKE_paint.hh"
|
||||
#include "BKE_pbvh_api.hh"
|
||||
|
||||
|
@ -385,6 +386,12 @@ static int sculpt_set_pivot_position_exec(bContext *C, wmOperator *op)
|
|||
|
||||
int mode = RNA_enum_get(op->ptr, "mode");
|
||||
|
||||
const View3D *v3d = CTX_wm_view3d(C);
|
||||
const Base *base = CTX_data_active_base(C);
|
||||
if (!BKE_base_is_visible(v3d, base)) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
BKE_sculpt_update_object_for_edit(depsgraph, ob, false);
|
||||
|
||||
/* Pivot to center. */
|
||||
|
|
|
@ -2151,8 +2151,8 @@ static void unused_message_gen(std::string &message,
|
|||
(is_first) ? "" : ", ",
|
||||
num_tagged[i],
|
||||
(num_tagged[i] > 1) ?
|
||||
IFACE_(BKE_idtype_idcode_to_name_plural(BKE_idtype_idcode_from_index(i))) :
|
||||
IFACE_(BKE_idtype_idcode_to_name(BKE_idtype_idcode_from_index(i))));
|
||||
IFACE_(BKE_idtype_idcode_to_name_plural(BKE_idtype_index_to_idcode(i))) :
|
||||
IFACE_(BKE_idtype_idcode_to_name(BKE_idtype_index_to_idcode(i))));
|
||||
is_first = false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1492,7 +1492,20 @@ static void drawTransformView(const bContext * /*C*/, ARegion *region, void *arg
|
|||
GPU_line_width(1.0f);
|
||||
|
||||
drawConstraint(t);
|
||||
drawPropCircle(t);
|
||||
|
||||
switch (t->spacetype) {
|
||||
case SPACE_GRAPH:
|
||||
case SPACE_ACTION:
|
||||
/* Different visualization because the proportional editing in these editors only looks at
|
||||
* the x-axis. */
|
||||
drawPropRange(t);
|
||||
break;
|
||||
|
||||
default:
|
||||
drawPropCircle(t);
|
||||
break;
|
||||
}
|
||||
|
||||
drawSnapping(t);
|
||||
|
||||
if (region == t->region && t->mode_info && t->mode_info->draw_fn) {
|
||||
|
|
|
@ -904,15 +904,6 @@ void drawPropCircle(TransInfo *t)
|
|||
else if (t->spacetype == SPACE_IMAGE) {
|
||||
GPU_matrix_scale_2f(1.0f / t->aspect[0], 1.0f / t->aspect[1]);
|
||||
}
|
||||
else if (ELEM(t->spacetype, SPACE_GRAPH, SPACE_ACTION)) {
|
||||
/* only scale y */
|
||||
float xscale, yscale;
|
||||
UI_view2d_scale_get(&t->region->v2d, &xscale, &yscale);
|
||||
|
||||
const float fac_scale = xscale / yscale;
|
||||
GPU_matrix_scale_2f(1.0f, fac_scale);
|
||||
GPU_matrix_translate_2f(0.0f, (t->center_global[1] / fac_scale) - t->center_global[1]);
|
||||
}
|
||||
|
||||
eGPUDepthTest depth_test_enabled = GPU_depth_test_get();
|
||||
if (depth_test_enabled) {
|
||||
|
@ -947,6 +938,40 @@ void drawPropCircle(TransInfo *t)
|
|||
}
|
||||
}
|
||||
|
||||
void drawPropRange(TransInfo *t)
|
||||
{
|
||||
if ((t->flag & T_PROP_EDIT) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
|
||||
|
||||
immBindBuiltinProgram(GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR);
|
||||
|
||||
float viewport[4];
|
||||
GPU_viewport_size_get_f(viewport);
|
||||
GPU_blend(GPU_BLEND_ALPHA);
|
||||
|
||||
immUniform2fv("viewportSize", &viewport[2]);
|
||||
|
||||
View2D *v2d = &t->region->v2d;
|
||||
const float x1 = t->center_global[0] - t->prop_size;
|
||||
const float y1 = v2d->cur.ymin;
|
||||
const float x2 = t->center_global[0] + t->prop_size;
|
||||
const float y2 = v2d->cur.ymax;
|
||||
|
||||
immUniform1f("lineWidth", 3.0f * U.pixelsize);
|
||||
immUniformThemeColorShadeAlpha(TH_GRID, -20, 255);
|
||||
imm_draw_box_wire_3d(pos, x1, y1, x2, y2);
|
||||
|
||||
immUniform1f("lineWidth", 1.0f * U.pixelsize);
|
||||
immUniformThemeColorShadeAlpha(TH_GRID, 20, 255);
|
||||
imm_draw_box_wire_3d(pos, x1, y1, x2, y2);
|
||||
|
||||
immUnbindProgram();
|
||||
GPU_blend(GPU_BLEND_NONE);
|
||||
}
|
||||
|
||||
static void drawObjectConstraint(TransInfo *t)
|
||||
{
|
||||
/* Draw the first one lighter because that's the one who controls the others.
|
||||
|
|
|
@ -41,6 +41,10 @@ void drawConstraint(TransInfo *t);
|
|||
* Called from drawview.c, as an extra per-window draw option.
|
||||
*/
|
||||
void drawPropCircle(TransInfo *t);
|
||||
/**
|
||||
* Draws two lines to indicate a proportional editing range that is only defined in one axis.
|
||||
*/
|
||||
void drawPropRange(TransInfo *t);
|
||||
void startConstraint(TransInfo *t);
|
||||
void stopConstraint(TransInfo *t);
|
||||
void initSelectConstraint(TransInfo *t);
|
||||
|
|
|
@ -1209,6 +1209,7 @@ typedef enum IDRecalcFlag {
|
|||
#define FILTER_ID_WM (1ULL << 38)
|
||||
#define FILTER_ID_LI (1ULL << 39)
|
||||
#define FILTER_ID_GP (1ULL << 40)
|
||||
#define FILTER_ID_IP (1ULL << 41)
|
||||
|
||||
#define FILTER_ID_ALL \
|
||||
(FILTER_ID_AC | FILTER_ID_AR | FILTER_ID_BR | FILTER_ID_CA | FILTER_ID_CU_LEGACY | \
|
||||
|
@ -1217,7 +1218,8 @@ typedef enum IDRecalcFlag {
|
|||
FILTER_ID_NT | FILTER_ID_OB | FILTER_ID_PA | FILTER_ID_PAL | FILTER_ID_PC | FILTER_ID_SCE | \
|
||||
FILTER_ID_SPK | FILTER_ID_SO | FILTER_ID_TE | FILTER_ID_TXT | FILTER_ID_VF | FILTER_ID_WO | \
|
||||
FILTER_ID_CF | FILTER_ID_WS | FILTER_ID_LP | FILTER_ID_CV | FILTER_ID_PT | FILTER_ID_VO | \
|
||||
FILTER_ID_SIM | FILTER_ID_KE | FILTER_ID_SCR | FILTER_ID_WM | FILTER_ID_LI | FILTER_ID_GP)
|
||||
FILTER_ID_SIM | FILTER_ID_KE | FILTER_ID_SCR | FILTER_ID_WM | FILTER_ID_LI | FILTER_ID_GP | \
|
||||
FILTER_ID_IP)
|
||||
|
||||
/**
|
||||
* This enum defines the index assigned to each type of IDs in the array returned by
|
||||
|
|
|
@ -82,9 +82,7 @@ enum {
|
|||
* };
|
||||
*
|
||||
* // Access all triangles in a given face.
|
||||
* const IndexRange face = faces[i];
|
||||
* const Span<int3> corner_tris = corner_tris.slice(poly_to_tri_count(i, face.start()),
|
||||
* bke::mesh::face_triangles_num(face.size()));
|
||||
* const Span<int3> corner_tris = corner_tris.slice(face_triangles_range(faces, i));
|
||||
* \endcode
|
||||
*
|
||||
* It may also be useful to check whether or not two vertices of a triangle form an edge in the
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
|
||||
#include "RNA_enum_types.hh"
|
||||
|
||||
#include "BLI_task.hh"
|
||||
|
||||
#include "node_geometry_util.hh"
|
||||
|
||||
namespace blender::nodes::node_geo_sample_nearest_surface_cc {
|
||||
|
@ -29,12 +31,22 @@ static void node_declare(NodeDeclarationBuilder &b)
|
|||
const eCustomDataType data_type = eCustomDataType(node->custom1);
|
||||
b.add_input(data_type, "Value").hide_value().field_on_all();
|
||||
}
|
||||
b.add_input<decl::Int>("Group ID")
|
||||
.hide_value()
|
||||
.field_on_all()
|
||||
.description(
|
||||
"Splits the faces of the input mesh into groups which can be sampled individually");
|
||||
b.add_input<decl::Vector>("Sample Position").implicit_field(implicit_field_inputs::position);
|
||||
b.add_input<decl::Int>("Sample Group ID").hide_value().supports_field();
|
||||
|
||||
if (node != nullptr) {
|
||||
const eCustomDataType data_type = eCustomDataType(node->custom1);
|
||||
b.add_output(data_type, "Value").dependent_field({2});
|
||||
b.add_output(data_type, "Value").dependent_field({3, 4});
|
||||
}
|
||||
b.add_output<decl::Bool>("Is Valid")
|
||||
.dependent_field({3, 4})
|
||||
.description(
|
||||
"Whether the sampling was successfull. It can fail when the sampled group is empty");
|
||||
}
|
||||
|
||||
static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
|
||||
|
@ -64,46 +76,105 @@ static void node_gather_link_searches(GatherLinkSearchOpParams ¶ms)
|
|||
}
|
||||
}
|
||||
|
||||
static void get_closest_mesh_tris(const Mesh &mesh,
|
||||
const VArray<float3> &positions,
|
||||
const IndexMask &mask,
|
||||
const MutableSpan<int> r_tri_indices,
|
||||
const MutableSpan<float> r_distances_sq,
|
||||
const MutableSpan<float3> r_positions)
|
||||
{
|
||||
BLI_assert(mesh.faces_num > 0);
|
||||
BVHTreeFromMesh tree_data;
|
||||
BKE_bvhtree_from_mesh_get(&tree_data, &mesh, BVHTREE_FROM_CORNER_TRIS, 2);
|
||||
get_closest_in_bvhtree(tree_data, positions, mask, r_tri_indices, r_distances_sq, r_positions);
|
||||
free_bvhtree_from_mesh(&tree_data);
|
||||
}
|
||||
|
||||
class SampleNearestSurfaceFunction : public mf::MultiFunction {
|
||||
private:
|
||||
GeometrySet source_;
|
||||
Array<BVHTreeFromMesh> bvh_trees_;
|
||||
VectorSet<int> group_indices_;
|
||||
|
||||
public:
|
||||
SampleNearestSurfaceFunction(GeometrySet geometry) : source_(std::move(geometry))
|
||||
SampleNearestSurfaceFunction(GeometrySet geometry, const Field<int> &group_id_field)
|
||||
: source_(std::move(geometry))
|
||||
{
|
||||
source_.ensure_owns_direct_data();
|
||||
static const mf::Signature signature = []() {
|
||||
mf::Signature signature;
|
||||
mf::SignatureBuilder builder{"Sample Nearest Surface", signature};
|
||||
builder.single_input<float3>("Position");
|
||||
builder.single_input<int>("Sample ID");
|
||||
builder.single_output<int>("Triangle Index");
|
||||
builder.single_output<float3>("Sample Position");
|
||||
builder.single_output<bool>("Is Valid", mf::ParamFlag::SupportsUnusedOutput);
|
||||
return signature;
|
||||
}();
|
||||
this->set_signature(&signature);
|
||||
|
||||
const Mesh &mesh = *source_.get_mesh();
|
||||
|
||||
/* Compute group ids on mesh. */
|
||||
bke::MeshFieldContext field_context{mesh, bke::AttrDomain::Face};
|
||||
FieldEvaluator field_evaluator{field_context, mesh.faces_num};
|
||||
field_evaluator.add(group_id_field);
|
||||
field_evaluator.evaluate();
|
||||
VArraySpan<int> group_ids_span = field_evaluator.get_evaluated<int>(0);
|
||||
|
||||
/* Compute an #IndexMask for every unique group id. */
|
||||
group_indices_.add_multiple(group_ids_span);
|
||||
const int groups_num = group_indices_.size();
|
||||
IndexMaskMemory memory;
|
||||
Array<IndexMask> group_masks(groups_num);
|
||||
IndexMask::from_groups<int>(
|
||||
IndexMask(mesh.faces_num),
|
||||
memory,
|
||||
[&](const int i) { return group_indices_.index_of(group_ids_span[i]); },
|
||||
group_masks);
|
||||
|
||||
/* Construct BVH tree for each group. */
|
||||
bvh_trees_.reinitialize(groups_num);
|
||||
threading::parallel_for(IndexRange(groups_num), 16, [&](const IndexRange range) {
|
||||
for (const int group_i : range) {
|
||||
const IndexMask &group_mask = group_masks[group_i];
|
||||
BVHTreeFromMesh &bvh = bvh_trees_[group_i];
|
||||
if (group_mask.size() == mesh.faces_num) {
|
||||
BKE_bvhtree_from_mesh_get(&bvh, &mesh, BVHTREE_FROM_CORNER_TRIS, 2);
|
||||
}
|
||||
else {
|
||||
BKE_bvhtree_from_mesh_tris_init(mesh, group_mask, bvh);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
~SampleNearestSurfaceFunction()
|
||||
{
|
||||
for (BVHTreeFromMesh &tree : bvh_trees_) {
|
||||
free_bvhtree_from_mesh(&tree);
|
||||
}
|
||||
}
|
||||
|
||||
void call(const IndexMask &mask, mf::Params params, mf::Context /*context*/) const override
|
||||
{
|
||||
const VArray<float3> &positions = params.readonly_single_input<float3>(0, "Position");
|
||||
MutableSpan<int> triangle_index = params.uninitialized_single_output<int>(1, "Triangle Index");
|
||||
const VArray<int> &sample_ids = params.readonly_single_input<int>(1, "Sample ID");
|
||||
MutableSpan<int> triangle_index = params.uninitialized_single_output<int>(2, "Triangle Index");
|
||||
MutableSpan<float3> sample_position = params.uninitialized_single_output<float3>(
|
||||
2, "Sample Position");
|
||||
const Mesh &mesh = *source_.get_mesh();
|
||||
get_closest_mesh_tris(mesh, positions, mask, triangle_index, {}, sample_position);
|
||||
3, "Sample Position");
|
||||
MutableSpan<bool> is_valid_span = params.uninitialized_single_output_if_required<bool>(
|
||||
4, "Is Valid");
|
||||
|
||||
mask.foreach_index([&](const int i) {
|
||||
const float3 position = positions[i];
|
||||
const int sample_id = sample_ids[i];
|
||||
const int group_index = group_indices_.index_of_try(sample_id);
|
||||
if (group_index == -1) {
|
||||
triangle_index[i] = -1;
|
||||
sample_position[i] = float3(0, 0, 0);
|
||||
if (!is_valid_span.is_empty()) {
|
||||
is_valid_span[i] = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
const BVHTreeFromMesh &bvh = bvh_trees_[group_index];
|
||||
BVHTreeNearest nearest;
|
||||
nearest.dist_sq = FLT_MAX;
|
||||
BLI_bvhtree_find_nearest(
|
||||
bvh.tree, position, &nearest, bvh.nearest_callback, const_cast<BVHTreeFromMesh *>(&bvh));
|
||||
triangle_index[i] = nearest.index;
|
||||
sample_position[i] = nearest.co;
|
||||
if (!is_valid_span.is_empty()) {
|
||||
is_valid_span[i] = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ExecutionHints get_execution_hints() const override
|
||||
|
@ -133,10 +204,13 @@ static void node_geo_exec(GeoNodeExecParams params)
|
|||
}
|
||||
|
||||
auto nearest_op = FieldOperation::Create(
|
||||
std::make_shared<SampleNearestSurfaceFunction>(geometry),
|
||||
{params.extract_input<Field<float3>>("Sample Position")});
|
||||
std::make_shared<SampleNearestSurfaceFunction>(geometry,
|
||||
params.extract_input<Field<int>>("Group ID")),
|
||||
{params.extract_input<Field<float3>>("Sample Position"),
|
||||
params.extract_input<Field<int>>("Sample Group ID")});
|
||||
Field<int> triangle_indices(nearest_op, 0);
|
||||
Field<float3> nearest_positions(nearest_op, 1);
|
||||
Field<bool> is_valid(nearest_op, 2);
|
||||
|
||||
Field<float3> bary_weights = Field<float3>(FieldOperation::Create(
|
||||
std::make_shared<bke::mesh_surface_sample::BaryWeightFromPositionFn>(geometry),
|
||||
|
@ -148,6 +222,7 @@ static void node_geo_exec(GeoNodeExecParams params)
|
|||
{triangle_indices, bary_weights});
|
||||
|
||||
params.set_output("Value", GField(sample_op));
|
||||
params.set_output("Is Valid", is_valid);
|
||||
}
|
||||
|
||||
static void node_rna(StructRNA *srna)
|
||||
|
|
|
@ -247,6 +247,7 @@ static void window_manager_blend_read_after_liblink(BlendLibReader *reader, ID *
|
|||
IDTypeInfo IDType_ID_WM = {
|
||||
/*id_code*/ ID_WM,
|
||||
/*id_filter*/ FILTER_ID_WM,
|
||||
/*dependencies_id_types*/ FILTER_ID_SCE | FILTER_ID_WS,
|
||||
/*main_listbase_index*/ INDEX_ID_WM,
|
||||
/*struct_size*/ sizeof(wmWindowManager),
|
||||
/*name*/ "WindowManager",
|
||||
|
|
Loading…
Reference in New Issue