I can't find any low-level way to un-group the nodes. Consider that ops.node.group_ungroup()
does a lot of things for free (keeps the references/data of the nodes, removes the input and output node, keeps the connections etc.) so I'd suggest to write your own operator and just call it within the Node Editor either by using spacebar or creating a button.
import bpy
def main(operator, context):
space = context.space_data
node_tree = space.node_tree
node_active = context.active_node
node_selected = context.selected_nodes
if node_active.type == 'GROUP':
bpy.ops.node.group_ungroup()
class NodeOperator(bpy.types.Operator):
"""Tooltip"""
bl_idname = "node.simple_operator"
bl_label = "Simple Node Operator"
@classmethod
def poll(cls, context):
space = context.space_data
return space.type == 'NODE_EDITOR'
def execute(self, context):
main(self, context)
return {'FINISHED'}
def register():
bpy.utils.register_class(NodeOperator)
def unregister():
bpy.utils.unregister_class(NodeOperator)
if __name__ == "__main__":
register()
In case there is no way around calling bpy.ops.node.group_ungroup()
within the Node Editor, you can switch the current area.
Example based on: poll() failed, context incorrect? - Example: bpy.ops.view3d.background_image_add()
import bpy
def main(operator, context):
area = context.area
old_type = area.type
# Set the area to NODE_EDITOR
area.type = 'NODE_EDITOR'
space = context.space_data
node_tree = space.node_tree
node_active = context.active_node
node_selected = context.selected_nodes
if node_active.type == 'GROUP':
bpy.ops.node.group_ungroup()
# Reset properties area
area.type = old_type
class NodeOperator(bpy.types.Operator):
"""Tooltip"""
bl_idname = "node.simple_operator"
bl_label = "Simple Node Operator"
'''
@classmethod
def poll(cls, context):
space = context.space_data
return space.type == 'NODE_EDITOR'
'''
def execute(self, context):
main(self, context)
return {'FINISHED'}
class LayoutDemoPanel(bpy.types.Panel):
"""Creates a Panel in the scene context of the properties editor"""
bl_label = "Layout Demo"
bl_idname = "SCENE_PT_layout"
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "scene"
def draw(self, context):
layout = self.layout
scene = context.scene
layout.operator(NodeOperator.bl_idname)
def register():
bpy.utils.register_class(NodeOperator)
bpy.utils.register_class(LayoutDemoPanel)
def unregister():
bpy.utils.unregister_class(NodeOperator)
bpy.utils.unregister_class(LayoutDemoPanel)
if __name__ == "__main__":
register()
group_ungroup()
. BTW: I don't get why people always want to avoid bpy.ops*. $\endgroup$