forked from blender/blender
me-main #1
@ -35,19 +35,10 @@ def draw_node_group_add_menu(context, layout):
|
|||||||
if node_tree:
|
if node_tree:
|
||||||
from nodeitems_builtins import node_tree_group_type
|
from nodeitems_builtins import node_tree_group_type
|
||||||
|
|
||||||
def contains_group(nodetree, group):
|
|
||||||
if nodetree == group:
|
|
||||||
return True
|
|
||||||
for node in nodetree.nodes:
|
|
||||||
if node.bl_idname in node_tree_group_type.values() and node.node_tree is not None:
|
|
||||||
if contains_group(node.node_tree, group):
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
groups = [
|
groups = [
|
||||||
group for group in context.blend_data.node_groups
|
group for group in context.blend_data.node_groups
|
||||||
if (group.bl_idname == node_tree.bl_idname and
|
if (group.bl_idname == node_tree.bl_idname and
|
||||||
not contains_group(group, node_tree) and
|
not group.contains_tree(node_tree) and
|
||||||
not group.name.startswith('.'))
|
not group.name.startswith('.'))
|
||||||
]
|
]
|
||||||
if groups:
|
if groups:
|
||||||
|
@ -76,21 +76,11 @@ def node_group_items(context):
|
|||||||
|
|
||||||
yield NodeItemCustom(draw=lambda self, layout, context: layout.separator())
|
yield NodeItemCustom(draw=lambda self, layout, context: layout.separator())
|
||||||
|
|
||||||
def contains_group(nodetree, group):
|
|
||||||
if nodetree == group:
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
for node in nodetree.nodes:
|
|
||||||
if node.bl_idname in node_tree_group_type.values() and node.node_tree is not None:
|
|
||||||
if contains_group(node.node_tree, group):
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
for group in context.blend_data.node_groups:
|
for group in context.blend_data.node_groups:
|
||||||
if group.bl_idname != ntree.bl_idname:
|
if group.bl_idname != ntree.bl_idname:
|
||||||
continue
|
continue
|
||||||
# filter out recursive groups
|
# filter out recursive groups
|
||||||
if contains_group(group, ntree):
|
if group.contains_tree(ntree):
|
||||||
continue
|
continue
|
||||||
# filter out hidden nodetrees
|
# filter out hidden nodetrees
|
||||||
if group.name.startswith('.'):
|
if group.name.startswith('.'):
|
||||||
|
@ -504,7 +504,13 @@ struct bNodeTree *ntreeFromID(struct ID *id);
|
|||||||
void ntreeFreeLocalNode(struct bNodeTree *ntree, struct bNode *node);
|
void ntreeFreeLocalNode(struct bNodeTree *ntree, struct bNode *node);
|
||||||
void ntreeFreeLocalTree(struct bNodeTree *ntree);
|
void ntreeFreeLocalTree(struct bNodeTree *ntree);
|
||||||
struct bNode *ntreeFindType(struct bNodeTree *ntree, int type);
|
struct bNode *ntreeFindType(struct bNodeTree *ntree, int type);
|
||||||
bool ntreeHasTree(const struct bNodeTree *ntree, const struct bNodeTree *lookup);
|
|
||||||
|
/**
|
||||||
|
* Check recursively if a node tree contains another.
|
||||||
|
*/
|
||||||
|
bool ntreeContainsTree(const struct bNodeTree *tree_to_search_in,
|
||||||
|
const struct bNodeTree *tree_to_search_for);
|
||||||
|
|
||||||
void ntreeUpdateAllNew(struct Main *main);
|
void ntreeUpdateAllNew(struct Main *main);
|
||||||
void ntreeUpdateAllUsers(struct Main *main, struct ID *id);
|
void ntreeUpdateAllUsers(struct Main *main, struct ID *id);
|
||||||
|
|
||||||
|
@ -3457,21 +3457,41 @@ bNode *ntreeFindType(bNodeTree *ntree, int type)
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ntreeHasTree(const bNodeTree *ntree, const bNodeTree *lookup)
|
static bool ntree_contains_tree_exec(const bNodeTree *tree_to_search_in,
|
||||||
|
const bNodeTree *tree_to_search_for,
|
||||||
|
Set<const bNodeTree *> &already_passed)
|
||||||
{
|
{
|
||||||
if (ntree == lookup) {
|
if (tree_to_search_in == tree_to_search_for) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
for (const bNode *node : ntree->all_nodes()) {
|
|
||||||
if (ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP) && node->id) {
|
tree_to_search_in->ensure_topology_cache();
|
||||||
if (ntreeHasTree((bNodeTree *)node->id, lookup)) {
|
for (const bNode *node_group : tree_to_search_in->group_nodes()) {
|
||||||
|
const bNodeTree *sub_tree_search_in = reinterpret_cast<const bNodeTree *>(node_group->id);
|
||||||
|
if (!sub_tree_search_in) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!already_passed.add(sub_tree_search_in)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (ntree_contains_tree_exec(sub_tree_search_in, tree_to_search_for, already_passed)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ntreeContainsTree(const bNodeTree *tree_to_search_in, const bNodeTree *tree_to_search_for)
|
||||||
|
{
|
||||||
|
if (tree_to_search_in == tree_to_search_for) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<const bNodeTree *> already_passed;
|
||||||
|
return ntree_contains_tree_exec(tree_to_search_in, tree_to_search_for, already_passed);
|
||||||
|
}
|
||||||
|
|
||||||
bNodeLink *nodeFindLink(bNodeTree *ntree, const bNodeSocket *from, const bNodeSocket *to)
|
bNodeLink *nodeFindLink(bNodeTree *ntree, const bNodeSocket *from, const bNodeSocket *to)
|
||||||
{
|
{
|
||||||
LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) {
|
LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) {
|
||||||
|
@ -715,7 +715,7 @@ void ED_node_set_active(
|
|||||||
if ((node->flag & NODE_ACTIVE_TEXTURE) && !was_active_texture) {
|
if ((node->flag & NODE_ACTIVE_TEXTURE) && !was_active_texture) {
|
||||||
/* If active texture changed, free glsl materials. */
|
/* If active texture changed, free glsl materials. */
|
||||||
LISTBASE_FOREACH (Material *, ma, &bmain->materials) {
|
LISTBASE_FOREACH (Material *, ma, &bmain->materials) {
|
||||||
if (ma->nodetree && ma->use_nodes && ntreeHasTree(ma->nodetree, ntree)) {
|
if (ma->nodetree && ma->use_nodes && ntreeContainsTree(ma->nodetree, ntree)) {
|
||||||
GPU_material_free(&ma->gpumaterial);
|
GPU_material_free(&ma->gpumaterial);
|
||||||
|
|
||||||
/* Sync to active texpaint slot, otherwise we can end up painting on a different slot
|
/* Sync to active texpaint slot, otherwise we can end up painting on a different slot
|
||||||
@ -734,7 +734,7 @@ void ED_node_set_active(
|
|||||||
}
|
}
|
||||||
|
|
||||||
LISTBASE_FOREACH (World *, wo, &bmain->worlds) {
|
LISTBASE_FOREACH (World *, wo, &bmain->worlds) {
|
||||||
if (wo->nodetree && wo->use_nodes && ntreeHasTree(wo->nodetree, ntree)) {
|
if (wo->nodetree && wo->use_nodes && ntreeContainsTree(wo->nodetree, ntree)) {
|
||||||
GPU_material_free(&wo->gpumaterial);
|
GPU_material_free(&wo->gpumaterial);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1094,24 +1094,6 @@ void NODE_OT_group_make(wmOperatorType *ot)
|
|||||||
/** \name Group Insert Operator
|
/** \name Group Insert Operator
|
||||||
* \{ */
|
* \{ */
|
||||||
|
|
||||||
static bool node_tree_contains_tree_recursive(const bNodeTree &ntree_to_search_in,
|
|
||||||
const bNodeTree &ntree_to_search_for)
|
|
||||||
{
|
|
||||||
if (&ntree_to_search_in == &ntree_to_search_for) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
ntree_to_search_in.ensure_topology_cache();
|
|
||||||
for (const bNode *node : ntree_to_search_in.group_nodes()) {
|
|
||||||
if (node->id) {
|
|
||||||
if (node_tree_contains_tree_recursive(*reinterpret_cast<bNodeTree *>(node->id),
|
|
||||||
ntree_to_search_for)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int node_group_insert_exec(bContext *C, wmOperator *op)
|
static int node_group_insert_exec(bContext *C, wmOperator *op)
|
||||||
{
|
{
|
||||||
SpaceNode *snode = CTX_wm_space_node(C);
|
SpaceNode *snode = CTX_wm_space_node(C);
|
||||||
@ -1133,7 +1115,7 @@ static int node_group_insert_exec(bContext *C, wmOperator *op)
|
|||||||
if (!group->is_group() || group->id == nullptr) {
|
if (!group->is_group() || group->id == nullptr) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (node_tree_contains_tree_recursive(*reinterpret_cast<bNodeTree *>(group->id), *ngroup)) {
|
if (ntreeContainsTree(reinterpret_cast<bNodeTree *>(group->id), ngroup)) {
|
||||||
BKE_reportf(
|
BKE_reportf(
|
||||||
op->reports, RPT_WARNING, "Can not insert group '%s' in '%s'", group->name, gnode->name);
|
op->reports, RPT_WARNING, "Can not insert group '%s' in '%s'", group->name, gnode->name);
|
||||||
return OPERATOR_CANCELLED;
|
return OPERATOR_CANCELLED;
|
||||||
|
@ -1435,6 +1435,11 @@ static void rna_NodeTree_active_output_set(PointerRNA *ptr, int value)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool rna_NodeTree_contains_tree(bNodeTree *tree, bNodeTree *sub_tree)
|
||||||
|
{
|
||||||
|
return ntreeContainsTree(tree, sub_tree);
|
||||||
|
}
|
||||||
|
|
||||||
static bNodeSocket *rna_NodeTree_inputs_new(
|
static bNodeSocket *rna_NodeTree_inputs_new(
|
||||||
bNodeTree *ntree, Main *bmain, ReportList *reports, const char *type, const char *name)
|
bNodeTree *ntree, Main *bmain, ReportList *reports, const char *type, const char *name)
|
||||||
{
|
{
|
||||||
@ -12719,6 +12724,16 @@ static void rna_def_nodetree(BlenderRNA *brna)
|
|||||||
parm = RNA_def_pointer(func, "context", "Context", "", "");
|
parm = RNA_def_pointer(func, "context", "Context", "", "");
|
||||||
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
|
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
|
||||||
|
|
||||||
|
func = RNA_def_function(srna, "contains_tree", "rna_NodeTree_contains_tree");
|
||||||
|
RNA_def_function_ui_description(
|
||||||
|
func,
|
||||||
|
"Check if the node tree contains another. Used to avoid creating recursive node groups");
|
||||||
|
parm = RNA_def_pointer(
|
||||||
|
func, "sub_tree", "NodeTree", "Node Tree", "Node tree for recursive check");
|
||||||
|
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
|
||||||
|
parm = RNA_def_property(func, "contained", PROP_BOOLEAN, PROP_NONE);
|
||||||
|
RNA_def_function_return(func, parm);
|
||||||
|
|
||||||
/* registration */
|
/* registration */
|
||||||
prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE);
|
prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE);
|
||||||
RNA_def_property_string_sdna(prop, NULL, "typeinfo->idname");
|
RNA_def_property_string_sdna(prop, NULL, "typeinfo->idname");
|
||||||
|
Loading…
Reference in New Issue
Block a user