Deleted

Removed for now

this is strange, because I am an amateur python scripter and I can make scripts easy in blender…

This is what put me off when trying to do some basic scripting myself. I´m sure there´s a good reason for it, but it´s pretty hard to get your head around.

Things wont run because of being in the wrong context

That is because you are trying to leverage tool based code solutions for generation. This is just a guess. If you are trying to make a Tool, (that runs in the tool panel) that is what bpy.ops is for and the panel will provide the context. If you are running a script in the editor or a handler, bpy.data manipulations make better sense.

I would suggest that you find every line of code, in your script, that has bpy.ops in it and replace it with a function/def that performs the same operation but acts upon bpy.data instead.

bpy.data makes a lot of sense and is easy to navigate and requires no special mode or context to operate upon.

Click on the link in my signature to view my posted scripts. I have a large library of defs that perform operations similar to many of the bpy.ops functions but operate upon bpy.data instead. Grab the more recent code, 2.66 or better.

If you post your script or example errors I’m sure people would help.

Here is an example of creating a mesh in a variable without worrying about context or edit state.


import bpy
from mathutils import Vector, Matrix

def returnSingleTriangleMesh(passedName):
    me = bpy.data.meshes.get (passedName)
    if me == None:
        vp_points = []
        vp_faces = []
        vp_objects = []
        vp_D1 = Vector([0.06, 0.08, 0.0])
        vp_D2 = Vector([0.06, -0.08, 0.0])
        vp_D3 = Vector([-0.1, 0.0, 0.0])
        vp_scale = 6.0
        c = 0
    
        # Single triangle object at world origin.
        dd = Vector([0.0,0.0,0.0])
        vp_points.append(dd+vp_D1*vp_scale)
        vp_points.append(dd+vp_D2*vp_scale)
        vp_points.append(dd+vp_D3*vp_scale)
        vp_faces.append([c,c+1,c+2])        
    
        me = bpy.data.meshes.new(passedName)
        me.from_pydata(vp_points,[],vp_faces)
    else:
        # Just use the existing mesh.
        pass
    
    # Make sure all verts are deselected.
    for v in me.vertices:
        v.select = False
    me.update()
    return me

me = returnSingleTriangleMesh("mytriangle")

An just because I have created a mesh, it does not exist in the scene yet, it does reside within bpy.data, however, because of “bpy.data.meshes.new”.

I am kind of in the same boat as you with Houdini and Maya. I don’t know where to start and I just wish those programs worked more like Blender.

The fact that you imply the developers at BI should update the documentation, after your woeful recounting of you experiences should have alerted you to the fact that this is hypocritical and a very apathetic perspective to hold. Shame on you (and learn the definition of open source)

Im importing pyqt via threading so i can consistently have the same gui and pyqt/pyside logic across maya and houdini. Im using this script to make rendering easier with 3delight in this case.

For example I have a dropdown for “open” which i want to open a file after I choose it. I know I could do this from the blender main menu. Im looking to get a file chooser dialog, choose a file, return it and then open it.

nothing has worked. I get messages like “cancelled” or nothing will happen.

def ops_openScene(self):
        bpy.ops.buttons.file_browse(filepath='C:/Users/aleks/Documents/maya/projects/default/scenes/objs/teapot.obj')

        #bpy.data.window_managers["WinMan"]

        # aleks = bpy.ops.buttons.file_browse()
        # print(aleks)
        
        #bpy.ops.wm.open_mainfile()

on to the block list you go !

The API is unlike anything you will encounter, and it will annoy you. You’ll probably get over it, though. You need to read more code.

This is a big deal. Its always been like this. Im not going to make any changes to the documentation - someone getting paid at the BI should do that. I mean, its embarrassing! No examples! Maya docs have examples for everything, on every page.

There aren’t that many “someones” at the BF that are paid (I believe it’s only three part-time devs) and API docs isn’t really at the top of the agenda. The API doc is pretty much autogenerated (as is the API, for the most part). There are some examples, but certainly not for everything. The best way I came up with is to just grep functions e.g. in the addons directory if you want to see how they’re used.

Things need to change. The way it is right now is not right.

This has probably been said about every piece of software, ever. Will you be the one who sets things straight? Probably not. You’ll have to deal with it or find some better use for your time.

on to the block list you go !

Ignoring people is… ignorant.

Have you looked at the templates in the Text Editor? There are examples of how to bring up the file browser. IMO looking at the API is not a good way to learn coding Blender, it should be more for a reference. The best way is to look at code that already does sthings similar to what you’re trying to do. Coding for Blender is possibly the easiest coding based thing I’ve ever learned.

And like Atom said, stay away from bpy.ops as much as possible unless you are making a tool(and maybe even then).

I also find this just a little strange (I had to unhide abc123’s post to read that he said that). I’m a pretty amateur programmer too, but I’ve wrapped my mind just enough around the API to write a slew of scripts that do some moderately complicated things and have proven to be really useful to me. As far as ‘context’ limitations, I agree with you, that’s kind of a pain. But it’s not insurmountable, you can override context if necessary (thanks to codemanX for the link) - http://www.blender.org/documentation/blender_python_api_2_67_1/bpy.ops.html#overriding-context

I don’t know that I would use the word ‘shackled’ if I were asked, but maybe ‘hindered’. I don’t know why it was done this way, but I’m sure there was a good reason.

I have to agree that starting out it is daunting to learn.
It takes awhile to get your head around it, but once you do it is not that bad.

The context issue irritated me a lot.
When you are learning you want to be able to cobble some code together by calling bpy.ops…
Sometimes you need to call bpy.ops, but in general, I agree try to use bpy.data… to do things instead.

I put this together to get rid of the context problem:


#Pass this function the following 'area.type' to get the needed override:
#INFO, DOPESHEET_EDITOR, CONSOLE, OUTLINER, NODE_EDITO, VIEW_3D, IMAGE_EDITOR, 
#CLIP_EDITOR, TIMELINE, TEXT_EDITOR, DOPESHEET_EDITOR, PROPERTIES, etc.


def context_override(area_type):
    for window in bpy.context.window_manager.windows:
        screen = window.screen
        
        for area in screen.areas:
            if area.type == area_type:
                for region in area.regions:
                    if region.type == 'WINDOW':
                        override = {'window': window,
                                    'screen': screen,
                                    'area': area,
                                    'region': region,
                                    'blend_data': bpy.context.blend_data}
                        
                        return override

When you want to make something happen with bpy.ops… use it like this:

bpy.ops.node.group_make( context_override('NODE_EDITOR') )

Just pick the area type from the list above. I didn’t include them all, but you get the idea.
It works very well.

Update
I’ve been getting some problems and complaints from ‘PyContext’ when working in the the 3D View.
I called:

bpy.ops.object.mode_set(get_override('VIEW_3D'), mode = 'OBJECT')

If there was an object selected or active it complained and/or threw an error.

This resolved it:

def get_override(area_type):
    for window in bpy.context.window_manager.windows:
        screen = window.screen
        
        for area in screen.areas:
            if area.type == area_type:
                for region in area.regions:
                    if region.type == 'WINDOW':
                        override = {'window': window,
                                    'screen': screen,
                                    'area': area,
                                    'region': region,
                                    'blend_data': bpy.context.blend_data,
                                    'scene' : bpy.context.scene}
                        
                        if (area_type == 'VIEW_3D'):
                            if bpy.context.object != None:
                                override.update({'object': bpy.context.object})
                            if bpy.context.active_object != None:
                                override.update({'active_object': bpy.context.active_object})
                        
                        return override

This context issue seems unnecessary. Why did the developers code Blender this way?

As it has been said, bpy.ops are meant to be called from the UI and depend highly on the state the program is currently in. A script run from the 3D viewport might fail when run from the python interpreter or the text editor.
Unfortunately, a lot of functionality is only available through operators, so you have to worry about when your code actually gets called. The whole API is a bit too UI-centric.

As for the amateur/beginner vs. advanced thing:
When you’re a beginner, everything you learn will be challenging, if you’re advanced, you expect to be able to “jump right in” because you’re used to your knowledge carrying over. Blender isn’t like that. It wasn’t designed by people with a common software engineering background.

I agree. I’m not a TD, but I have more than 20 years experience programming in multiple languages.

I really don’t understand the attitude toward documentation amongst the Blender crowd. Instead of shaming people for pointing out the obvious, they might consider contributing to the docs, especially in BP.

I tried to write what I thought would be a very useful script based on Brian Horgan’s bhGhost, but after several weeks of not finding documentation or the docs were just wrong, I packed it in.

required contexts for every operator in the docs - that appears utopic. And it wouldn’t even mean that you can use ops, some operators ignore overriden contexts (and there are reasons for it I don’t quite understand, but there are). A good way to figure out contexts however seems to be: bpy.ops..({}) - so an empty custom context, which will force blender to write pycontext warnings to the console. You can start to build the required context and see if more pycontext warnings appear. Note that not every pycontext warning actually means that a certain context member is required, especially window/screen/area stuff. But bases often are (and if they are missing, blender will crash) - you can find them here: bpy.context.scene.object_bases, you might have to filter them.