remapping from Toolshelf to...Where?

hi,
it appears the mapping of object or add mesh scripts is wrong.
when a script opens in the toolbox, if you move the object the script dissapears.
this is not suitable for Renderer scripts, Add_Mesh scripts & higher level scripts that you may want to run, do some tweaks in the 3d view then, make some adjustments in the script menu.

so how to solve this problem?
do we map the scripts to the properties window, or map them to the Properties panel.
does this highlight the need for a separate window for some scripts?
what would be the best way to handle this?

Any opinions on this would be greatly appreciated.

Add mesh scripts are surely the same as the “native” add functions… so it’s not new… except for the easy tweaking enabled by the undo/redo loop… (which as you note is onlyapplicable to the last operation…

so in this case what you’re asking for is a history that allows you to go to previous steps and make changes… Personally I hate history as it always is ultimately disappointing, consumes lots of memory and usually seems to lead to unstablity… but many would disagree with me.

A renderer is a differnt thing, and usually would have its own panels… (chosen from the renderer pulldown: i’d expect it to replace the scene, materials,texture and render properties tabs to ones geared for the specialties of the renderer…) that mechanism is already in place…

Other scripts that don’t just “run once” would get either custom panels or just access custom properties stored in the appropriate data blocks to allow for persistent settings… eg storing names and custom colours for layers in the scene data block… this could then be accessed by adding a permanent new panel to the scenetab in properties… so you could set visibility, name/rename the layers to something meaningful etc etc…

Beyond that I guess that we wait for custom space types… I’d love to write a “spreadsheet” editor (each object in the scene gets it’s own row,each column could be data (eg light intensity, r,g,b, cone angles etc… multi select cells to edit the properties and allow maths on them…)

I’d also like to write a central material/texture editor which gives an overview of all the materials and texture datablocks in the scene for quick editing…

both of these wouldn’t fit in f6, and because of context changes don’t belong in the properties area either…

MichaelW, whilst you have some points,
it’s been described to me as not a bug but a design flaw/problem.
if i create a gear, it cannot even be scaled or moved to get a better view.
the transform tools take the place of the script, it’s gone.
so if i wanted to change anything it’s too late.
previously, this was not an issue, an example would be the ant landscape script.
you can create an object, scale it, add some effects, rotate it, add more effects, then you close the script.
I’m just looking for ideas atm on how to fix this, even if it is short term.

there was a script not long ago that was able to get back the buttons in tool panel to re edit when selecting a custom object in scene

so i think there is a way to do that !

have you seen it a few weeks ago ?

salutations

no, i did not see it…
but i will look. :slight_smile:

MichaelW, whilst you have some points,
it’s been described to me as not a bug but a design flaw/problem.

well, it’s just the same as when adding a sphere… you can’;t move that and then edit its parameters…

if i create a gear, it cannot even be scaled or moved to get a better view.
the transform tools take the place of the script, it’s gone.
so if i wanted to change anything it’s too late.
But you can pan zoom and rotate the view to get a better view… and as in 2.49 you could always “undo”

previously, this was not an issue, an example would be the ant landscape script.
you can create an object, scale it, add some effects, rotate it, add more effects, then you close the script.
I’m just looking for ideas atm on how to fix this, even if it is short term.

Hmm, I don’t know that script, but yes, i think i see what you mean:

the “tree from curves” script comes to mind… and you’re right that it would be quite a design issue to port that right now…

It certainly shouldn’t be a permanent panel in the tools. numerics or properties areas… it has more in kin with a modifier… and yet you can’t do those in python. And even if you could then it wouldn’t fit all the function in that script… and my suggestion of a custom space type (when they return) doesn’t seem to be a real fit either…

Perhaps you could add a custom property to an object when you first run the operator: (say "treefromcurves) and then you only draw the panels that have functions relating to “treefromcurves” in the object tab if the “context active object” has that property…

that way only “tree from curves” objects get the special panels rather than having a cluttered mess all the time…I think that could be done right now and would prove an elegant solution to having too much clutter…

Finally, you could have an “apply” function that removes the property and makes any changes permanent…

Can you “set” the view of the properties window in a script?

hmm, it could be possible to do a workaround.
my main issue is that the scripts are not persistent in the toolshelf,
maybe a new panel type there, that is empty until you activate a script.
adding a button to turn off the script would not be hard, if linked to the Add-Ons registering system.
or even a refresh for the panel?
so the tool shelf could be Toolshelf/Object tools/Operator/Scripts…

ok i found the script and there seems to be and edit mode for created object

but i did not save the web page for this one !

but here is the code for it


 
import bpy
import Mathutils
from math import cos,sin,pi
from bpy.props import IntProperty, FloatProperty, BoolProperty
def add_gem(r1, r2, seg, h1, h2):
    """
    r1 = pavillion radius
    r2 = crown radius
    seg = number of segments
    h1 = pavillion height
    h2 = crown height
    Generates the vertices and faces of the gem
    """
    
    tot_verts = 2 + 4 * seg
    tot_faces = 6 * seg
    a = 2*pi/seg                   # angle between segments
    offset = a/2.0                 # middle between segments
    
    r3 = ((r1+r2)/2.0)/cos(offset) # middle of crown
    r4 = (r1/2.0)/cos(offset)      # middle of pavillion
    h3 = h2/2.0                    # middle of crown height
    h4 = -h1/2.0                   # middle of pavillion height
    verts = [0,0,-h1,0,0,h2]
    for i in range(seg):
        s1 = sin(i*a)
        s2 = sin(offset+i*a)
        c1 = cos(i*a)
        c2 = cos(offset+i*a)
        verts.extend([ r4*s1,r4*c1,h4,r1*s2,r1*c2,0, 
                       r3*s1,r3*c1,h3,r2*s2,r2*c2,h2 ])  
    faces = []
    
    for index in range(seg):
        i = index*4
        j = ((index+1)%seg)*4
        faces.extend([0,   j+2, i+3, i+2])
        faces.extend([i+3, j+2, j+3, i+3])
        faces.extend([i+3, j+3, j+4, i+3])
        faces.extend([i+3, j+4, i+5, i+4])
        faces.extend([i+5, j+4, j+5, i+5])
        faces.extend([i+5, j+5, 1  , i+5])
    return verts, faces, tot_verts, tot_faces
       
class Parameter_Panel_Gem(bpy.types.Panel):
    bl_space_type = "VIEW_3D"
    bl_region_type = "TOOLS"
    bl_context = "objectmode"
    bl_label = "Gem parameters"
    def poll(self, context):
        # only show this panel if the object selected has propertie "Gem"
        try:
            return "Gem" in context.object
        except TypeError: return False
    def draw(self,context):
        layout = self.layout
        layout.operator("Gem_Parameter_Edit", text="Edit")
class EditGem(bpy.types.Operator):
    """Reapply the operator"""
    bl_idname = "Gem_Parameter_Edit"
    bl_label = "Edit Gem"
    def invoke(self,context,event):
        # invoke the adding operator again,
        #  only this time with the Edit property = true
        ob = context.active_object    
        bpy.ops.mesh.primitive_gem_add(Edit = True, 
                   segments=ob["Segments"],
                   pav_radius = ob["pav_radius"],
                   crown_radius = ob["tab_radius"],
                   crown_height = ob["tab_height"],
                   pav_height = ob["pav_height"])
        return {'FINISHED'}
class AddGem(bpy.types.Operator):
    """Add a diamond gem"""
    bl_idname = "mesh.primitive_gem_add"
    bl_label = "Add Gem"
    bl_description = "Create an offset faceted gem."
    bl_register = True
    bl_undo = True
    Edit = BoolProperty(name = "", description = "", 
           default = False, options = {'HIDDEN'})   # whether to add or update
    segments = IntProperty(name = "Segments", 
           description="Longitudial segmentation", 
           default=8, min=3, max=265)
    pav_radius = FloatProperty(name = "Radius",
           description="Radius of the gem",
           default = 1.0, min = 0.01, max = 100.0)
    crown_radius = FloatProperty(name = "Table Radius",
           description = "Radius of the table(top).",
           default = 0.6, min = 0.01, max = 100.0)
    crown_height = FloatProperty(name = "Table height",
           description = "Height of the top half.",
           default = 0.35, min = 0.01, max = 100.0)
    pav_height = FloatProperty(name = "Pavillion height",
           description = "Height of bottom half.",
           default = 0.8, min = 0.01, max = 100.0)
        
    def execute(self, context):
        # create mesh
        verts, faces, nV, nF = add_gem(self.properties.pav_radius,
               self.properties.crown_radius,
               self.properties.segments,
               self.properties.pav_height,
               self.properties.crown_height)
    
        mesh = bpy.data.meshes.new("Gem")
        mesh.add_geometry(nV,0,nF)
        mesh.verts.foreach_set("co",verts)
        mesh.faces.foreach_set("verts_raw",faces)
        mesh.update()
        if self.properties.Edit:
            # only update
            ob_new = context.active_object
            bpy.ops.object.mode_set(mode='EDIT')
            bpy.ops.mesh.select_all(action='SELECT')
            bpy.ops.mesh.delete(type = 'VERT')
            bpy.ops.object.mode_set(mode='OBJECT')
            
            ob_new.data = mesh
            
            scene = context.scene
    
            # ugh
            for ob in scene.objects:
                ob.selected = False
            
            ob_new.selected = True
            scene.objects.active = ob_new
            bpy.ops.object.shade_flat()
        else:
            # create new object
            scene = context.scene
    
            # ugh
            for ob in scene.objects:
                ob.selected = False
    
            ob_new = bpy.data.objects.new("Gem",'MESH')
            ob_new.data = mesh
            scene.objects.link(ob_new)
            ob_new.selected = True
    
            ob_new.location = scene.cursor_location
    
            obj_act = scene.objects.active
    
            if obj_act and obj_act.mode == 'EDIT':
                # if the mesh is added in edit mode, add the mesh to the
                #  excisting mesh
                bpy.ops.object.mode_set(mode='OBJECT')
    
                obj_act.selected = True
                scene.update() # apply location
    
                bpy.ops.object.join() # join into the active.
    
                bpy.ops.object.mode_set(mode='EDIT')
            else:
                # add new object and make faces flat
                scene.objects.active = ob_new
                bpy.ops.object.shade_flat()
                if context.user_preferences.edit.enter_edit_mode:
                    bpy.ops.object.mode_set(mode='EDIT')
        # add custom properties to the object to make the edit parameters
        #  thingy work
        ob_new["Gem"] = 1
        ob_new["Segments"] = self.properties.segments
        ob_new["pav_radius"] = self.properties.pav_radius 
        ob_new["tab_radius"] = self.properties.crown_radius
        ob_new["pav_height"] = self.properties.pav_height
        ob_new["tab_height"] = self.properties.crown_height
        return {'FINISHED'}
# register all operators and panels
bpy.types.register(AddGem)
bpy.types.register(Parameter_Panel_Gem)
bpy.types.register(EditGem)
# add primitive_mesh_add menu item
menu_func = (lambda self, context: self.layout.operator(AddGem.bl_idname,
                                        text="Gem", icon='MOD_BEVEL'))
bpy.types.INFO_MT_mesh_add.append(menu_func)
if __name__ == "__main__":
    bpy.ops.mesh.primitive_gem_add()if you save this code in the .blender/scripts/op folder, it adds a menu
 
 
 

hope you can copy it

don’t remember what the web page was for this one cause i did not save it!

seems that the panle will be visible only when cteated object by this script are selected
and then you can go into edit mode

if you find the web page for this let me know i’ll save it this time

salutations

hi RickyBlender.
Thanks, that’s a great workaround.
I’ll test it on some other scripts.
here’s a quick hack i did to get the script working for tests.


import bpy
import Mathutils
from math import cos,sin,pi
from bpy.props import IntProperty, FloatProperty, BoolProperty
def add_gem(r1, r2, seg, h1, h2):
    """
    r1 = pavillion radius
    r2 = crown radius
    seg = number of segments
    h1 = pavillion height
    h2 = crown height
    Generates the vertices and faces of the gem
    """
    
    tot_verts = 2 + 4 * seg
    tot_faces = 6 * seg
    a = 2*pi/seg                   # angle between segments
    offset = a/2.0                 # middle between segments
    
    r3 = ((r1+r2)/2.0)/cos(offset) # middle of crown
    r4 = (r1/2.0)/cos(offset)      # middle of pavillion
    h3 = h2/2.0                    # middle of crown height
    h4 = -h1/2.0                   # middle of pavillion height
    verts = [0,0,-h1,0,0,h2]
    for i in range(seg):
        s1 = sin(i*a)
        s2 = sin(offset+i*a)
        c1 = cos(i*a)
        c2 = cos(offset+i*a)
        verts.extend([ r4*s1,r4*c1,h4,r1*s2,r1*c2,0, 
                       r3*s1,r3*c1,h3,r2*s2,r2*c2,h2 ])  
    faces = []
    
    for index in range(seg):
        i = index*4
        j = ((index+1)%seg)*4
        faces.extend([0,   j+2, i+3, i+2])
        faces.extend([i+3, j+2, j+3, i+3])
        faces.extend([i+3, j+3, j+4, i+3])
        faces.extend([i+3, j+4, i+5, i+4])
        faces.extend([i+5, j+4, j+5, i+5])
        faces.extend([i+5, j+5, 1  , i+5])
    return verts, faces, tot_verts, tot_faces
       
class Parameter_Panel_Gem(bpy.types.Panel):
    bl_space_type = "VIEW_3D"
    bl_region_type = "TOOLS"
    bl_context = "objectmode"
    bl_label = "Gem parameters"
    def poll(self, context):
        # only show this panel if the object selected has propertie "Gem"
        try:
            return "Gem" in context.object
        except TypeError: return False
    def draw(self,context):
        layout = self.layout
        layout.operator("Gem_Parameter_Edit", text="Edit")
class EditGem(bpy.types.Operator):
    """Reapply the operator"""
    bl_idname = "Gem_Parameter_Edit"
    bl_label = "Edit Gem"
    def invoke(self,context,event):
        # invoke the adding operator again,
        #  only this time with the Edit property = true
        ob = context.active_object    
        bpy.ops.mesh.primitive_gem_add(Edit = True, 
                   segments=ob["Segments"],
                   pav_radius = ob["pav_radius"],
                   crown_radius = ob["tab_radius"],
                   crown_height = ob["tab_height"],
                   pav_height = ob["pav_height"])
        return {'FINISHED'}
class AddGem(bpy.types.Operator):
    """Add a diamond gem"""
    bl_idname = "mesh.primitive_gem_add"
    bl_label = "Add Gem"
    bl_description = "Create an offset faceted gem."
    bl_register = True
    bl_undo = True
    Edit = BoolProperty(name = "", description = "", 
           default = False, options = {'HIDDEN'})   # whether to add or update
    segments = IntProperty(name = "Segments", 
           description="Longitudial segmentation", 
           default=8, min=3, max=265)
    pav_radius = FloatProperty(name = "Radius",
           description="Radius of the gem",
           default = 1.0, min = 0.01, max = 100.0)
    crown_radius = FloatProperty(name = "Table Radius",
           description = "Radius of the table(top).",
           default = 0.6, min = 0.01, max = 100.0)
    crown_height = FloatProperty(name = "Table height",
           description = "Height of the top half.",
           default = 0.35, min = 0.01, max = 100.0)
    pav_height = FloatProperty(name = "Pavillion height",
           description = "Height of bottom half.",
           default = 0.8, min = 0.01, max = 100.0)
        
    def execute(self, context):
        # create mesh
        verts, faces, nV, nF = add_gem(self.properties.pav_radius,
               self.properties.crown_radius,
               self.properties.segments,
               self.properties.pav_height,
               self.properties.crown_height)
    
        mesh = bpy.data.meshes.new("Gem")
        mesh.add_geometry(nV,0,nF)
        mesh.verts.foreach_set("co",verts)
        mesh.faces.foreach_set("verts_raw",faces)
        mesh.update()
        if self.properties.Edit:
            # only update
            ob_new = context.active_object
            bpy.ops.object.mode_set(mode='EDIT')
            bpy.ops.mesh.select_all(action='SELECT')
            bpy.ops.mesh.delete(type = 'VERT')
            bpy.ops.object.mode_set(mode='OBJECT')
            
            ob_new.data = mesh
            
            scene = context.scene
    
            # ugh
            for ob in scene.objects:
                ob.selected = False
            
            ob_new.selected = True
            scene.objects.active = ob_new
            bpy.ops.object.shade_flat()
        else:
            # create new object
            scene = context.scene
    
            # ugh
            for ob in scene.objects:
                ob.selected = False
    
            ob_new = bpy.data.objects.new("Gem", MESH)
            ob_new.data = mesh
            scene.objects.link(ob_new)
            ob_new.selected = True
    
            ob_new.location = scene.cursor_location
    
            obj_act = scene.objects.active
    
            if obj_act and obj_act.mode == 'EDIT':
                # if the mesh is added in edit mode, add the mesh to the
                #  excisting mesh
                bpy.ops.object.mode_set(mode='OBJECT')
    
                obj_act.selected = True
                scene.update() # apply location
    
                bpy.ops.object.join() # join into the active.
    
                bpy.ops.object.mode_set(mode='EDIT')
            else:
                # add new object and make faces flat
                scene.objects.active = ob_new
                bpy.ops.object.shade_flat()
                if context.user_preferences.edit.enter_edit_mode:
                    bpy.ops.object.mode_set(mode='EDIT')
        # add custom properties to the object to make the edit parameters
        #  thingy work
        ob_new["Gem"] = 1
        ob_new["Segments"] = self.properties.segments
        ob_new["pav_radius"] = self.properties.pav_radius 
        ob_new["tab_radius"] = self.properties.crown_radius
        ob_new["pav_height"] = self.properties.pav_height
        ob_new["tab_height"] = self.properties.crown_height
        return {'FINISHED'}
# register all operators and panels
bpy.types.register(AddGem)
bpy.types.register(Parameter_Panel_Gem)
bpy.types.register(EditGem)
# add primitive_mesh_add menu item
menu_func = (lambda self, context: self.layout.operator(AddGem.bl_idname,
                                        text="Gem", icon='MOD_BEVEL'))
bpy.types.INFO_MT_mesh_add.append(menu_func)
#if __name__ == "__main__":
 #   bpy.ops.mesh.primitive_gem_add()if you save this code in the .blender/scripts/op folder, it adds a menu

this runs from the text editor.
once you have run the script, press ‘S’ to scale the gem,
the menu disappears.
then in the toolshelf, search for gem.
there will be two buttons, add gem or edit gem.
pressing edit gem redraws the ‘gem menu’ & lets you return to editing the object.
not the best workflow, but atm i think it’s worth adding this to the other add_mesh scripts.
that should give a reasonable template for add_mesh scripts. for now…

I think you’re very script centric (naturally):wink:

Don’t think of it as “scripts are not persistent”, rather “operators are not persistent”… and operators are just “one off” tools that you activate, tweak and then move on…

they can be written in python or c… an operator is an operator…

anything that doesn’t fit with that definition is a candidate for being someplace else on the interface…

so, in each case you have to decide: should it be a attached to an existing data block as custom data? if so it should go in the properties panel on the appropriate tab… (and my last suggestion in my previous post would certainly help prevent that area becoming too cluttered…

If it shouldn’t be an operator and isn’t just about custom properties for objects then should it be a space type? If so, that’s tough right now, but on the agenda…

If it doesn’t fit into those then should it be broken down a bit into a “suite”
(a mix of operators and property panels…) could be tough and requires the most thought on the part of the script writer…

Maybe the “render engine” selector should be put to other purposes… as it sets up the whole UI for a suite of controls for a specific workflow…

…or maybe you’re right and the cleanest option would be a return of the “2.49 script window”… without an example case of why what I suggest wouldn’t work I’d remain un-convinced…

Without talking specifics it’s hard to see!

Personally i hate the silly operator properties box at the bottom of the toolshelf… way too small… and always use F6… I’d love to have an “operator” space type so that I can size my interface appropriately… but I guess that has it’s own set of issues with context… and still wouldn’t be persistent… That is limited to adding to the tool area (destructive to the default setup) or using the properties area where it can be additional…

BTW I would’nt have thought that what I suggested for the tree from curves script was a workaround, rather an appropriate solution…

Hey Michael do you think in your understanding of how operators work it would be possible to add some sort of pinning to the operators panel? This way you could run a script then pin the operators panel then move, scale, rotate or whatever, but still be able to go back and edit the scripts properties.

I to agree that panel is just to small and cumbersome to use very effectively. Personally, I think I would prefer an operators tab in the properties panel, maybe with a preferences option to automatically go to it after calling an operator. Until then f6 will do.

0knowledge… as metaandrocto says, it’s a design flaw/problem (I’d prefer to have said design decision) but once you use another operator you can’t go back to an earlier one…

that’d need a history… The design problem with history is that changing something that happened earlier will often trash more recent edits… do you allow that? do you clear the more recent edits? do you just disallow the change? How should this communicate to the user?

you can already see this with the modifier list… some modifiers must be first… some cannot be applied unless earlier ones are also applied…

imagine creating a sphere, moving and scaling it and then extruding some faces… now, if you go back to the sphere and change the number of divisions what happens to the extrusion?

Make it simpler… create a sphere and then translate some points… then go back and change divisions… still a problem…

so in some ways it’s much clearer for the user to just rely on undo…

I guess to solve part of this problem you just make translation, scale and rotation a part of the “add object” primatives… where the transforms are part of the creation of an object (eg maya)

But I think that many people (eg broken) are interested in adding a history and are “looking into it”