# Tag Info

37

Most operators cause implicit scene updates. It means that every object in the scene is checked and updated if necessary. If you add e.g. mesh primitives using bpy.ops.mesh.primitive_cube_add() in a loop, every iteration creates a new cube, starts a scene update and Blender iterates over all objects in the scene and updates objects if it has to. If you ...

35

For a comprehensive description of operators and their use see: https://docs.blender.org/api/current/bpy.types.Operator.html For a quick run-down poll, checked before running the operator, which will never run when poll fails, used to check if an operator can run, menu items will be greyed out and if key bindings should be ignored. invoke, Think of this as ...

20

When calling an operator via bpy.ops.* without any execution context the execute() method of the respective operator runs by default. If the operator provides any kind of 'user interaction' like a 'confirmation dialog' in this case, then you can pass 'INVOKE_DEFAULT' as execution context when calling the operator which will also run its invoke() method: ...

18

Delete removes vertices/edges/faces and leaves nothing/a hole in their place. Dissolve combines faces into one big face (ngon) or removes edges only as a separator between faces. Dissolving an edge between two vertices can be reversed by re-connecting them by pressing J with both vertices selected. Limited dissolve dissolves (combines into big NGons) all ...

18

Lots of bpy.ops operators depend on the context (selected objects, active shape key index, etc.), therefore I think some are more suitable to be used interactively than in a script. I'd use bpy.ops judiciously rather than avoiding it wholesale. For example, I find creating constraint through a posebone's constraints.new easier to read, and independent from ...

18

The operator bpy.ops.object.duplicate() will duplicate the selected objects and then make the new duplicate objects selected while de-selecting the original objects. The operator is designed for user interaction which actually leaves the user moving the new duplicates when it is done (when started through the gui). A better way to create a copy of an object ...

14

There are 2 ways you can do this: Standard API (bpy) - the most straightforward is to set each object in editmode and run the tool. Notice I'm not using bpy.data.objects, This will operate on all objects in your blend file, not just your scene, instead use bpy.context.scene.objects. import bpy scene = bpy.context.scene for ob in scene.objects: if ob....

13

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=( ...

11

To add it it to the toolbar, simply have your class inherit from bpy.types.Panel, and call the class functions, the key one being draw(). You choose a space_type, a region_type and the context in which the panel should be shown. You can also reference the example below the one you are using. BlenderCookie also has a tutorial that covers this. See the ...

10

After the operator already registered, all you need now is to add one more class that inherits from bpy.types.Panel Example class SimpleOperatorVisibility(bpy.types.Panel): bl_label = "Simple Operator" bl_space_type = "VIEW_3D" bl_region_type = "TOOLS" def draw (self, context): layout=self.layout col=layout.column() ...

10

The operator name is bpy.ops.view3d.view_selected(). See my answer here for additional information on this and also how to quickly reach the online manual and the API reference. Here are the accompanying docs for the operator. Hover over a button and you should see a short description etc.. This can be useful for getting operator names. You can go to ...

9

First of all there are cases where redo doesn't make any sense (render, save, open), in those cases simply running the operator again is fine. Operators have their own internal data which is used to execute an action, in most cases this is sufficient to store all information needed to redo an action (make use of the F6 popup, or be called from a Python ...

9

What you are looking for probably, is running a timer alongside the modal operator, so you can check the serial data whenever the operator gets executed with a timer event. There already is a code template in blender, that shows you how to do this. Look for the Template menu entry at the bottom of the Text Editor and select Python > Operator Modal Timer ...

9

When you switch back to Object Mode, you can set the 'Origin to Geometry'. With all the objects still selected, int the 3D view port, Go to : 'Object' -> 'Transform' -> 'Origin to Geometry' Then the origin will be centered on the meshes physical center.

8

What you are looking for is to create a modal operator. From the Wiki: A modal operator defines a Operator.modal function which running, handling events until it returns {'FINISHED'} or {'CANCELLED'}. Grab, Rotate, Scale and Fly-Mode are examples of modal operators. They are especially useful for interactive tools, your operator can have its own ...

8

short answer: bgl.glPointSize(5) bgl.glBegin(bgl.GL_POINTS) less shorter answer: Open template operator_modal_draw.py In draw_callback_px(self, context) I call my function DrawByVertices("points", verts2d, [0.5, 1, 0.1, 0.5]) where verts2d are screen coordinates [(screen.x, screen.y), ..] in my case derived from vector3 like this from bpy_extras....

8

As of this commit, thanks to @p2or and @brecht, the bpy.ops.ui.copy_data_path_button() operator now allows to copy the full data-path of the active property under the mouse cursor to the clipboard which can be used to assign custom values to the active property (only available in latest versions). Simplified version of the provided example in the patch (...

7

Objects constructed with bpy.ops.mesh.primitive_* are automatically active. If there's no selection-changing operations immediately after object creation, you can access it through bpy.context.active_object or bpy.context.object.

7

You can use static members (class variables) to store information in the operator. Here's an example that adds a panel and an operator. The operator increases a class variable to reflect how often it has been called. This number is drawn in a panel in the Scene tab of the Properties Edtior: import bpy class HelloWorldPanel(bpy.types.Panel): """Creates ...

7

The actual operator class is only accessible if it's defined in the same script, or imported from another file. It's not a standard Python class however, because it is derived from the Operator type: import bpy class PrimitiveManipulatorOperator(bpy.types.Operator): bl_idname = "object.primitive_manipulator" bl_label = "Primitive Manipulator" ...

7

After looking through the api documentation, it does not appear that there is a direct way to know which contexts an operator will work in. Therefore, one way to determine this is to call an operator's poll method in every context to see if the operator will work (brute forcing it). Using this approach, the bpy.ops.sequencer.duplicate will work in the '...

7

While your Operator.check(...) method returns True the popup will redraw. Simple return True method used in bpy.types.Operator Dialog Box example. Setting the boolean prop, my_bool, to True reveals more in draw method. import bpy class DialogOperator(bpy.types.Operator): bl_idname = "object.dialog_operator" bl_label = "Simple Dialog Operator" ...

6

You can find out (part of) the context you are in by: cont = bpy.context.area.type print(str(cont)) This in itself will help you determine where you are (contextually speaking). Determining where you need to be is another story. Each operation that you do in Blender requires that you be in the correct context. The way I think of context is, what window (...

6

No, at least operators don't have the notion of a final state. I can see in some cases you may want to setup a tools options, then perform some action once the options are set. You could use a pop-up dialog 1 (as image-new does), but then you dont get feedback when changing values. Some script writers add toggles to their operators that perform some extra ...

6

I'll just quote ideasman42: When possible I would avoid using bpy.ops, These wrap tools in a way that relies on the context and dont have a good way to pass args and return results to scripts. If there is an alternative (as with bmesh), it's better integrated into python, and you don't have to worry about active object, modes, visible layers etc.

6

If event.type is LEFTMOUSE, how could it be MOUSEMOVE at the same time? (exclude quantum mechanics) The modal() method is called for every event, so you need to "remember" the left mouse state for the subsequent calls on MOUSEMOVE events: import bpy from bpy.props import IntProperty, FloatProperty class ModalOperator(bpy.types.Operator): """Move an ...

6

AFAIK it's so that you can check in a script whether an operator executed properly or not, by inspecting its return value. For Blender itself it doesn't matter, but it starts to become relevant when you use one operator from another. For example: result = bpy.ops.object.delete() if result == {'FINISHED'}: # Can also do: if 'FINISHED' in result: ...

6

In your modal operator you can test object.mode for which mode the object is in - example: import bpy bpy.context.active_object.mode # = 'OBJECT' bpy.ops.object.mode_set(mode='EDIT') bpy.context.active_object.mode # = 'EDIT' There is no callback, you will need to test this on 'tab' event or always to be sure..

6

You can use OpenGL's feature for stippled lines to draw dotted / dashed lines: import bpy import bgl import blf def draw_callback_px(self, context): bgl.glPushAttrib(bgl.GL_ENABLE_BIT) # glPushAttrib is done to return everything to normal after drawing bgl.glLineStipple(1, 0x9999) bgl.glEnable(bgl.GL_LINE_STIPPLE) font_id = 0 # XXX, ...

6

For Operator Error Reports Catching Errors is handled separately, this example catches the error report and prints it as a string. import bpy try: bpy.ops.object.vertex_group_add() except RuntimeError as ex: error_report = "\n".join(ex.args) print("Caught error:", error_report) For Operator Info Reports Python can temporarily redirect the ...

Only top voted, non community-wiki answers of a minimum length are eligible