Replace an object by another primitive

Hi there,

I have a problem with a script I wrote, but I’m not sure it’s a blender bug so I simplified the question and the code to expose it here:

suppose an empty scene with only one selected cube.
I write a script to delete the selected object and create a cone instead:
(don’t care about ‘house’ or ‘homa’ words, it comes from the original script)


import bpy
import math
from mathutils import Vector, Matrix
from bpy.props import *
 
class OBJECT_PT_ArToKi_HoMa_bug(bpy.types.Panel):
    bl_label = "tmaes - bug"
    bl_space_type = "PROPERTIES"
    bl_region_type = "WINDOW"
    bl_context = "object"
    

 
# Interface Buttons etc... 
    
    def draw(self, context):
        layout = self.layout 
        obj = bpy.context.object
        scene = bpy.context.scene
        
        row = layout.row() 
        row.operator("object.homa_modify_house",text="Tranform cube to cone")

         


class OBJECT_OT_HoMa_modify_house(bpy.types.Operator):
    bl_label = "HoMa modify House"
    bl_idname = "object.homa_modify_house"
    bl_description = "Transforms cube to cone."
    @classmethod
    def poll(cls, context):
        return context.active_object is not None

    def execute(self, context):

        scene = bpy.context.scene
        obj = bpy.context.object
        ver = obj.data.vertices
        edg = obj.data.edges
        num = len(edg)
       
        
        bpy.ops.object.delete(use_global=False)
        bpy.ops.mesh.primitive_cone_add(
            True,             
            )            
        return {'FINISHED'}  
    

        

# registering and menu integration  
def register():
    bpy.utils.register_class(OBJECT_PT_ArToKi_HoMa_bug)
    bpy.utils.register_class(OBJECT_OT_HoMa_modify_house)    
 
# unregistering and removing menus
def unregister():
    bpy.utils.unregister_class(OBJECT_PT_ArToKi_HoMa_bug)
    bpy.utils.unregister_class(OBJECT_OT_HoMa_modify_house)
 
if __name__ == "__main__":
    register()

Result: a button in the Object panel that deletes the cube and creates a cone, with editable settings (thanks to the True param in bpy.ops.mesh.primitive_cone_add).

But Why oooh Why, when I edit those settings, does the initial cube reappear???

Thanks in advance for your help…

sample file: bug_tmaes.zip (1.14 MB)


tmaes

What version of Blender are you using? When I try to run it on 2.62 I get error related to the “primitive_cone_add” call. That method does not have any way to simply pass a boolean value to it.

The operator settings on the side panel are for ‘add cone’ and not for your operator so when you edit them it undos the last operation and redoes the add cone operation.

You need to register your operator in the undo stack (and add properties to edit) or something like that.

Hi and thanks already,

I use 2.63.13 from graphicall.org the boolean value is a new feature to call properties panel at creation
http://www.blender.org/documentation/blender_python_api_2_63_13/bpy.ops.html

@uncle entity we wrote at the same time, I’ll explore your suggestion asap… seems hard for my little brain but with time i’ll succeed :wink:

So thank you Uncle Entity, I don’t think I understood all the register/undo stack thing…
But I found the pieces of code needed to make it work here is the same example, with register and undo, and the radius2 property of the created cone and it works…
And the boolean parameter doesn’t seem to be useful using this method.

Thanks again!


import bpy
import math
from mathutils import Vector, Matrix
from bpy.props import *
 
class OBJECT_PT_ArToKi_HoMa_bug(bpy.types.Panel):
    bl_label = "tmaes - bug"
    bl_space_type = "PROPERTIES"
    bl_region_type = "WINDOW"
    bl_context = "object"
    

 
# Interface Buttons etc... 
    
    def draw(self, context):
        layout = self.layout 
        obj = bpy.context.object
        scene = bpy.context.scene
        
        row = layout.row() 
        row.operator("object.homa_modify_house",text="Tranform cube to cone")

         


class OBJECT_OT_HoMa_modify_house(bpy.types.Operator):
    bl_label = "HoMa modify House"
    bl_idname = "object.homa_modify_house"
    bl_description = "Transforms cube to cone."
    bl_options = {'REGISTER', 'UNDO'}
    
    radius2 = FloatProperty(
        name="Radius2",
        description="Cone radius2",
        min=0.01, max=100.0,
        default=1.0,
        )
        
    @classmethod
    def poll(cls, context):
        return context.active_object is not None

    def execute(self, context):

        scene = bpy.context.scene
        obj = bpy.context.object
        ver = obj.data.vertices
        edg = obj.data.edges
        num = len(edg)
       
        
        bpy.ops.object.delete(use_global=False)
        bpy.ops.mesh.primitive_cone_add(
            radius2=self.radius2,            
            )            
        return {'FINISHED'}  
    

        

# registering and menu integration  
def register():
    bpy.utils.register_class(OBJECT_PT_ArToKi_HoMa_bug)
    bpy.utils.register_class(OBJECT_OT_HoMa_modify_house)    
 
# unregistering and removing menus
def unregister():
    bpy.utils.unregister_class(OBJECT_PT_ArToKi_HoMa_bug)
    bpy.utils.unregister_class(OBJECT_OT_HoMa_modify_house)
 
if __name__ == "__main__":
    register()

So hi again…
after testing I have the impression to ‘turn arround myself’…
Your solution of registering etc works but I need to pass parameters I passed before without problems and now its very difficult.

In brief isn’t there a way to avoid the undo part of the behavior you described here: (ie clean the desired stack point)?

so when you edit them it undos the last operation and redoes the add cone operation
edit:
I found a method I don’t know if its clean:
added:
bpy.ops.ed.undo_push(message=“Add an undo step function may be moved)
after object deletion and the undo part doesn’t happend anymore.


import bpy
import math
from mathutils import Vector, Matrix
from bpy.props import *
 
class OBJECT_PT_ArToKi_HoMa_bug(bpy.types.Panel):
    bl_label = "tmaes - bug"
    bl_space_type = "PROPERTIES"
    bl_region_type = "WINDOW"
    bl_context = "object"
    

 
# Interface Buttons etc... 
    
    def draw(self, context):
        layout = self.layout 
        obj = bpy.context.object
        scene = bpy.context.scene
        
        row = layout.row() 
        row.operator("object.homa_modify_house",text="Tranform cube to cone")

         


class OBJECT_OT_HoMa_modify_house(bpy.types.Operator):
    bl_label = "HoMa modify House"
    bl_idname = "object.homa_modify_house"
    bl_description = "Transforms cube to cone."
    @classmethod
    def poll(cls, context):
        return context.active_object is not None

    def execute(self, context):

        scene = bpy.context.scene
        obj = bpy.context.object
        ver = obj.data.vertices
        edg = obj.data.edges
        num = len(edg)
       
        
        bpy.ops.object.delete(use_global=False)
        bpy.ops.ed.undo_push(<i>message="Add an undo step *function may be moved*"</i>)
        bpy.ops.mesh.primitive_cone_add(
            True,             
            )            
        return {'FINISHED'}  
    

        

# registering and menu integration  
def register():
    bpy.utils.register_class(OBJECT_PT_ArToKi_HoMa_bug)
    bpy.utils.register_class(OBJECT_OT_HoMa_modify_house)    
 
# unregistering and removing menus
def unregister():
    bpy.utils.unregister_class(OBJECT_PT_ArToKi_HoMa_bug)
    bpy.utils.unregister_class(OBJECT_OT_HoMa_modify_house)
 
if __name__ == "__main__":
    register()