Skip to content

Archive

Tag: Python

It might turn out that my first impressions on wxPython will be somehow biased. Well, not because there seems to be a decent, comprehensive tutorial readily available

…but because the tutorial focuses on putting a very simple text editor together, and that’s where I’d like to start (see source code on the wx man pages).

Although wxPython isn’t bundled with Python itself, it installs easily on windows. The tutorial is comprehensive and readily addresses essential questions (GUI creation, layout, events).

I just picked the source code and skimmed through it while reformatting it. Superficially, there are similarities with tkinter. While reformatting I noticed stuff that looks strange to a python beginner (that, I am):

def askUserForFilename(self, **dialogOptions):
        dialog = wx.FileDialog(self, **dialogOptions)

This looks like a ‘double pointer’; I have no idea what it might be.

dialog = wx.MessageDialog(self, 'A sample editor\n'
            'in wxPython', 'About Sample Editor', wx.OK)

This may just be a way to continue a string on the next line (notice there’s no comma at end of line)

Anyways, I fired up this stuff (the reformatted version) and got an output window flashing on the screen and disappearing. Not good. So I went back to their ‘hello world’ and found they use…

wx.App(False)

… to avoid routing stdout to a separate window.

The mini text editor seems to be working like a charm. In the meantime, I haven’t learned much.

wxPython wins hands up for the  first three hours of use. It doesn’t mean much. Just a way to say, the docs seem fairly usable compared to tkinter, with lots of examples to play with and a nice tutorial.

Aside, I encountered an issue both with tkinter and wxPython: stdout doesn’t print until I exit the app. Maybe it does if we route the output to a separate window. Still not great.

I guess that’s it for now. However unfair I’m likely set to have a closer look at wxPython before anything else.

I’ve been idling (quite not literally) for more than a year over how I would progress my work on programming/coding tools.

One idea that stuck is that I’d be happier if my tool(s) included a scripting facility – rather than ‘step backwards’ and have to write an extension/module for every other need I run across.

If I think hard, I guess that’s where Python really came to mind. Then of course there is a choice:

  1. I could port some of my tools to Python entirely (including the gui).
  2. I could keep my tools (mainly, ee-ide) in java and provide some level of integration with Python.

I’m not overly fond of the second solution (and I’m having ‘post-thoughts’ about the whole ‘need scripting facilities’ idea even while I’m writing this).  Learning new stuff is nice. Integrating technologies is cool. In the meantime, the ‘some of level of integration’ casual talk is probably hiding costs that need to be measured against what could turn out to be a quick, clean and somehow progressive rewrite.

So I decided to try a couple of py GUI libraries (not incidentally chosen)

Round 1 – tkinter

I’ve used the following references

After messing with this stuff for a while, I found pretty much what I would like to start with, a page explaining step by step how to make a notepad like text editor with tkinter.

This is what I got so far (35% battery left on my eepc)

from Tkinter import *

class GUI(Frame):
    def __init__(self,master=None):
            Frame.__init__(self,master)
            self.vbar=Scrollbar()
            self.text = Text(self, yscrollcommand=self.vbar.set)
            self.vbar.config(command=self.text.yview)
            self.vbar.pack(side=RIGHT,fill=Y)
            self.text.pack(side=LEFT,fill=BOTH)
            self.pack(fill=BOTH)
            self.text.bind("<Any-KeyPress>",self.onKeyPress)

    def onKeyPress(self,event):
        #print "bummer"
        self.text.insert(END, "bummer")

if __name__ == "__main__":
    guiFrame = GUI()
    guiFrame.mainloop()

First Impressions

I haven’t fallen in love with tkinter yet. The library itself doesn’t seem absolutely worse than another, but the docs I found are often unsuitable for ‘learning by practice’.

Don’t get me wrong, I like reading conceptual overviews and reference material (no… seriously). What lures me into doing just that and learning a library in depth is usually a bunch of seriously good code samples assorted with no-nonsense explanations.

Binding the scroll-bar to the text has been a minor pain. Yea, it’s just two lines of code. Compared to making a scrollpane and just adding the text component to it, it feels unwieldy, which brings me to another source of unease: I’m not always clear about how components get added, let alone how to remove them.

I also had to fiddle quite a bit to get the layout right. I had the scroll-bar not resizing and the text component filling the screen, and other weird stuff…

Please note I’m not judging the library, just how easily I got around it after 2-3 hours coding.

Guess I’ll be on my way trying wxPython next – let’s read this page first as it seems somehow un-intimidating, giving guidance about choosing a Python GUI.

from Tkinter import *

class GUI(Frame):
def __init__(self,master=None):
Frame.__init__(self,master)
self.vbar=Scrollbar()
self.text = Text(self, yscrollcommand=self.vbar.set)
self.vbar.config(command=self.text.yview)
self.vbar.pack(side=RIGHT,fill=Y)
self.text.pack(side=LEFT,fill=BOTH)
self.pack(fill=BOTH)
self.text.bind(“<Any-KeyPress>”,self.onKeyPress)

def onKeyPress(self,event):
#print “bummer”
self.text.insert(END, “bummer”)

if __name__ == “__main__”:
guiFrame = GUI()
guiFrame.mainloop()

In Blender, Actions contain information about ‘reusable animations’ that can be combined to generate complex animated scenes. Actions can also be used to create catalogues of animations associated with game assets.

I might have suggested before that a 3D artist may prefer to keep several avatar models in the same blender file. Keeping models in separate files makes it (not impossible yet) more difficult to share geometry and materials between models. For the designer, ‘sharing’ may not be a very high level concept, more something like ‘copy, paste and modify’. Nice, fast and simple.

Blender actions are created while posing armatures. Unfortunately, there is not a clear way to retain the connection between an action and the armature first used to generate this action. Here’s a little experiment that illustrates this:

1. Create an armature A with a bone named ‘Bone’. Create an action X for this armature.
2. Create an armature B with a bone named ‘Bone’ (same name). Make action X current in B.
2. Observe the result.

Essentially, Blender Actions are lists of keyframes ‘per channel’; a channel is just a name; the name binds bone names. Any armature can use any action, and this will be ‘effective’ as long as the names match.
That may be powerful. Not great when we want to export per character keyframes for each action.

At this point, we may consider loading a config file listing actions for each actor, or design a little script letting us retain the original armature <> action binding when creating new actions (I think that can be done and integrated nicely with Blender). But I won’t illustrate any of the above this time. I just fallback to a naming convention for my actions, something like:

myActor.jump
myActor.nod

Since all actions are dumped in the same list, this also allows quickly locating per character actions in the Blender interface.

Let’s not learn all about Python Strings

Instead, try this:

z='funbot.jump'
p=z.split('.')
p[0] # prints 'funbot'
p[1] # prints 'jump'

Now we can match each action to a character ‘owning’ this action. You can learn more about actions and *stuff* in previous articles on this blog.

My current export script for character animation requires a naming convention for binding a character to it’s armature.  Also, the script only exports the currently selected mesh.

In this article, I illustrate how to examine a Blender scene to discover assets; I also show how to find the armature modifier associated with an animated character.

In outline, this is how to structure a script to export an asset library:

  • Iterate all objects in the scene
  • Retain only Mesh objects.
  • For each mesh object, check whether this object uses an armature; if so, assume the object is a kind of actor or character.
  • Export mesh objects as appropriate (You can learn how to do this from previous articles on this blog)

Interactive session

Let’s try the following:

s=Blender.Scene.GetCurrent()
s.objects
for x in s.objects:
	x.type

(After typing ‘x.type’ in the interactive console, press enter twice to effect the loop)

This will print the type of each object in the order they are stored in the scene. We only want to export Mesh objects. Pick any Mesh object using an armature. (in my case, index 1 in the object list).

object=s.objects[1]
for x in object.modifiers:
	if(x.type==Modifier.Types.ARMATURE):
		x

This will print something like:

[Modifier "Armature", Type "Armature"]

That’s all we need to identify actors and props in a Blender Scene.

In Blender, an Action is a sequence of key frames representing a character gesture (walking, jumping, slashing, falling, etc…). Actions are used as building blocks in Blender’s non linear animation (NLA) editor. We can use actions to create ‘animation catalogues’. An export script using actions might be used to batch export all animations for one or several characters, so we can update our game assets whenever we need, which simplifies and enhances flow.

Interactive Scripting Session

For this session, I have created a little robot – ‘funbot’ and an armature for it.
I then create two actions and detach them from the funbot. To take advantage of actions, we need to make each action current, i.e. for every action we attach the action to the armature and export all frames or key frames (either the armature frames/keyframes or the deformed mesh) before moving to the next action. Time for scripting:

#retrieve the action dictionary
actions=Blender.Armature.NLA.GetActions()

#get an action named 'nod' (as defined by your animator)
action=actions.get("nod")

#the following prints '[Action "nod"]'
armature=Object.Get("FunBotArmature")

#this makes the action current for the armature,
#so we can playback the action and record it.
action.setActive(armature)

#even if you call this, the window won't update, but the underlying
#model does, which is what we need for export.
scene=Blender.Scene.GetCurrent()
scene.update(1)

The above script does nearly everything we need related to actions – giving access to all defined actions within a blender file, it retrieves an action by name, applies it to the correct armature and updates the scene; at this point we’re nearly ready to iterate action frames and export the model and/or armature to a file (see my interactive session on exporting meshes deformed using an armature)

Just one more thing we need is knowing the number of frames in the animation. We can actually get better than just the number of frames – instead, we can get the list of keyframes, in ascending order:

#get the list of keyframes
keys=action.getFrameNumbers()
#print all keyframe indices, like ' [1,11,24,36,] '
list(keys)
#print the length of the animation
keys[len(keys)-1]

Using this, we can choose to either export only keyframes (use less memory), or all frames in the animation (OK for really simple animations and models).

Before I forget… for some reason the Blender APIDoc doesn’t just turn up whenever I google it. Here it is.

Just a while back I published a weeny export script and matching C/Objective C code that can be used to export mesh data from blender to OpenGL vertex arrays.

To export animated characters, we need to do either of two things:

  1. Export Armature key frames or frames, along with their attachment to target objects; then apply the deformation either in real time, or maybe just before we need to animate the model. The upside is that this is memory savvy. The downside is that if your game engine can’t handle your exported armatures (I don’t know how likely to happen this might be) or you don’t use a game engine, you’ll have to work out deformations yourself, starting from a fairly complex high level model.
  2. Export ready mesh key-frames or frames, with the armature effect already applied. The downside is that this requires a lot more memory.

My hunch is that how much ‘a lot more’ matters really depends how large your models are and what kind of platform you’re running on. I plan running on the iPhone/iTouch with isometric views. This means that my 3D sprites will be small – hence require less polygons. For some animations, a little compression (e.g. retaining unchanged coordinates from a previous frame) can be considered if needed, never mind sharing geometry across models.

In this article I show how to force modifiers to be applied before exporting mesh data – one way to attach an armature in blender is via modifiers. This is a good opportunity to try interactive scripting with Blender, making learning scripting easy and fun :)

Effecting the modifier stack also means that you can export complex operations applied to your object, not just armature modifiers.

Give back to Caesar what belongs to  Chicken – I borrowed this technique from the Blender to Panda3D export script – Chicken exports to Panda3D’s *.egg format,

***Believe it or not, *.egg came first, then Chicken somehow assisted the birth of this tutorial.

An Interactive Scripting Session

First I make a triangle pointing up in the z x plane, ensuring x==0 for the middle vertex. I add an armature – just one bone – aligned on the z axis and pose it to drag the top vertex to the right, about 1 unit. Finally I add the armature as modifier. I think this is important, afaik this wouldn’t work if the armature parented
the mesh. Then I type the following in the scripting console:

scene=Blender.Scene.getCurrent()
obj =scene.objects[1]
mesh=obj.getData(mesh=1)

# next line prints coord without deformation
mesh.verts[2].co.x

# this is where the magic happens
# getFromObject implicitly applies all modifiers.
tmesh.getFromObject(obj,0,1)

#next line prints coord with deformation
tmesh.verts[2].co.x

OK, this shows that we can export the deformed mesh. Now we need to get each
frame. So I insert a keyframe for the rotation of the bone (pose mode),
go 10 frames further and pose with the tip of the bone pointing right.

First, let’s repeat the first experiment,
browsing to frame 11 (left/right arrow keys)

tmesh.getFromObject(obj,0,1)
tmesh.verts[2].co.x

This shows that the script is, by default,
querying the current frame.
I found a command to change the frame:

context = scene.getRenderingContext()
# set the current frame
context.currentFrame(3)
scene.update(1)
tmesh.getFromObject(obj,0,1)
tmesh.verts[2].co.x

If you repeat this operation using the frame value, you will see that the vertex coordinate moves at every frame.

Next time I’ll look into exporting several actions for a given character.