7
$\begingroup$

I have try to make an UI Panel with my operator, but i can not create a panel with the 2 choices (axis and widht).

I can create a button who launch a menu in the tools pannel, and the operator works fine with this :

layout = self.layout
layout.operator(ChooseAxis.bl_idname)

But i want to have exactly this menu in the UI panel, not in tools, so I have try to write this :

layout.prop(obj, "axis")
layout.prop(obj, "newdim")

But that doesn't works, values ​​are modifiable but are ignored and do not modify the object.

How can i have the operator directly on the UI Panel ? (Not a button to launch the operator, but the operator himself with its Properties.)

Moreover, how i can keep the object size value when i launch the operator ? Because when i launch it, it the default value of the newdim property is set to 1 (for example), the object is directly resized. Is it possible to have a default="object actual value" ?

here the entire script with the ui panel created :

from bpy import *
import bpy
from bpy.props import FloatProperty, EnumProperty

class ProportionalDimensions(bpy.types.Panel):
    """Creates a Panel in the Object UI window"""
    bl_label = "Proportional Dimensions"
    bl_idname = "prop_dim"
    bl_space_type = "VIEW_3D"
    bl_region_type = "UI"
    #bl_context = "object"

def draw(self, context):
    obj = context.object

    #row = layout.row()
    #row.label(text="Active object is: " + obj.name)

    layout = self.layout
    layout.operator(ChooseAxis.bl_idname)

    layout.prop(obj, "axis")
    layout.prop(obj, "newdim")


class ChooseAxis(bpy.types.Operator):
    bl_idname = "object.choose_axis"
    bl_label = "Choose_the_Right_Axis"
    bl_description = "This is to choose the axis"
    bl_options = {'REGISTER', 'UNDO'}

axis  = EnumProperty(
        name="Axis",
        description="Axis selection",
        items= [('x', "X", ""),('y', "Y", ""),('z', "Z","")],
        default='x'
        )

newdim = FloatProperty(
        name="Width",
        description="Scale",
        min=0.01, max=100.0,
        default=1,
        )
# your code
def scale(self, axis, new_dim):
    ob = bpy.context.active_object
    d = ob.dimensions

    x = d[0]
    y = d[1]
    z = d[2]

    scale =  axis

    if( scale == "x"):
        indice = 0
    elif( scale == "y"):
        indice = 1
    else:
        indice = 2

    old_dim = d[indice] 
    factor = new_dim / old_dim

    scale_x = ob.scale[0]
    scale_y = ob.scale[1]
    scale_z = ob.scale[2]

    ob.scale[0] = scale_x * factor
    ob.scale[1] = scale_y * factor
    ob.scale[2] = scale_z * factor

def execute(self, context):
    self.scale(self.axis,self.newdim)
    return {'FINISHED'}

def register():
    bpy.utils.register_class(ProportionalDimensions)
    bpy.utils.register_class(ChooseAxis)


def unregister():
    bpy.utils.unregister_class(ProportionalDimensions)
    bpy.utils.unregister_class(ChooseAxis)

if __name__ == "__main__":
    register()
$\endgroup$
15
$\begingroup$

You usually run an operator and adjust the settings afterwards in the Redo panel, or the operator should prompt the user before execution using invoke_props_dialog():

import bpy

class SimpleOperator(bpy.types.Operator):
    bl_label = "Simple Operator"
    bl_idname = "object.simple_operator"

    my_enum = bpy.props.EnumProperty(
        items=(
            ('ONE', "One", ""),
            ('TWO', "Two", ""),
            ('THREE', "Three", "")
        ),
        default='ONE'
    )

    def invoke(self, context, event):
        wm = context.window_manager
        return wm.invoke_props_dialog(self)

    def execute(self, context):
        self.report({'INFO'}, self.my_enum)
        return {'FINISHED'}


def register():
    bpy.utils.register_module(__name__)

def unregister():
    bpy.utils.unregister_module(__name__)

if __name__ == "__main__":
    register()

    bpy.ops.object.simple_operator('INVOKE_DEFAULT')

If you really want to display UI elements in a panel to be set before clicking the button, you will have to register global properties and pass them to the according operator properties (you can't add operator properties to a panel).

import bpy

class SimpleOperator(bpy.types.Operator):
    bl_label = "Simple Operator"
    bl_idname = "object.simple_operator"

    my_enum = bpy.props.EnumProperty(
        items=(
            ('ONE', "One", ""),
            ('TWO', "Two", ""),
            ('THREE', "Three", "")
        ),
        default='ONE'
    )

    def execute(self, context):
        self.report({'INFO'}, self.my_enum)
        return {'FINISHED'}


class HelloWorldPanel(bpy.types.Panel):
    """Creates a Panel in the Object properties window"""
    bl_label = "Hello World Panel"
    bl_idname = "OBJECT_PT_hello"
    bl_space_type = 'PROPERTIES'
    bl_region_type = 'WINDOW'
    bl_context = "object"

    def draw(self, context):
        layout = self.layout

        ob = context.object

        row = layout.row()
        row.prop(ob, "my_global_enum", expand=True)

        props = layout.operator(SimpleOperator.bl_idname)
        props.my_enum = ob.my_global_enum


def register():
    bpy.utils.register_module(__name__)

    bpy.types.Object.my_global_enum = bpy.props.EnumProperty(
        items=(
            ('ONE', "One", ""),
            ('TWO', "Two", ""),
            ('THREE', "Three", "")
        ),
        default='TWO'
    )


def unregister():
    bpy.utils.unregister_module(__name__)
    del bpy.types.Object.my_global_enum


if __name__ == "__main__":
    register()
| improve this answer | |
$\endgroup$
  • $\begingroup$ Thank you, the first way works fine and launch au modal. But the second way doesn't works. I post a new question with the second method transpose in my case. $\endgroup$ – Fabrice Oct 13 '14 at 12:42
  • 1
    $\begingroup$ You can set a default value for the global property, but you can't really base it on another property, because you can't access the context at registration time of an addon (it will work for scripts you run via the text editor however) $\endgroup$ – CodeManX Oct 13 '14 at 12:56
  • $\begingroup$ Note that you can use a PointerProperty instead of creating each property separately. See blender.stackexchange.com/questions/6975/… $\endgroup$ – Coburn Sep 13 '15 at 6:13
  • 1
    $\begingroup$ I'm not sure what you mean, you still need to register individual properties. A pointer property helps to organize them to avoid name conflicts. $\endgroup$ – CodeManX Sep 13 '15 at 9:13
  • $\begingroup$ Looking back I don't know why I wrote that either, lol. $\endgroup$ – Coburn Dec 1 '17 at 22:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.