Skip to content

Archive

Category: Python

Opiates

Maybe it’s the weather; or maybe I’m bored. I was just thinking – why am I still doing all my Objective C coding with XCode? Is it that good? Meeehh.

Seriously, I used to type less code. In fact I was annoyed enough with your average off the shelf IDE that I used to write all my code using my own tools. While it’s gonna take more than a rain check for me to pick up ee-ide and integrate with ObjC, there’s something left from this bygone era – the urge to meta-program.

Sidekick wanted

So putting aside the more interesting question (what do I want to analyze? What would I use meta-programming for?) I found myself wondering once again: if not java, what am I supposed to write my utilities in?

I’m pretty used to Objective C by now, but it’s not the kind of language that I want to use to write rough and ready utilities. Python comes to mind. I have this unqualified connection with Python: using it to write our blender scripts, suffering from the lack of straight OO semantics, irked by the lack of typing and compile time checking, amused by the syntactic sugar (e.g. sequences), encouraged by the no-nonsense, generous approach to standard libraries.

I prepared a bunch of references to skim through. I think I’ll be going old school, approaching utilities with the command line before (hopefully) integrating with XCode.

Yea that’s it for today. My refs are below. Just basic stuff.

References

Varied tutorials for working with files

And some n00b references to run our py scripts:

 

These days I’m working on urban environments in Blender. Urban environments can be easily broken down into modules and series – cloning the same objects over and over to create roads, floor tilings, buildings and so forth…

Duplicating modules by hand is tedious even if you don’t care about millimeter accuracy. So I thought I’d write a little script to do simple tilings.

The script duplicates the active object several times and merges the result into a single object. The original module or ’tile’ is preserved. This script will run with Blender 2.49 and can be easily modified (for example, if you want to add padding between copies or don’t want to merge the result)

What we need to know

To retrieve the active object:

scene=Scene.GetCurrent()
active=scene.objects.active

Initially I thought about duplicating vertex data directly as I want the tiles to be part of the same object. But duplicating the object first may be safer and offers more flexibility.

We can use the following command to duplicate active objects:

Object.Duplicate() # duplicate, link mesh data
Object.Duplicate(mesh=1) # duplicate, clone mesh data

To tile clones edge to edge, we’ll need to know the extent of the object:

dimX=obj.getBoundBox()[6][0]-obj.getBoundBox()[0][0]
dimY=obj.getBoundBox()[6][1]-obj.getBoundBox()[0][1]
dimZ=obj.getBoundBox()[6][2]-obj.getBoundBox()[0][2]

Once we have duplicated and moved our objects we can merge them together using join(). This function is a member of the object class and will join the target with all objects in a given array:

arr=[]
arr.append(anObject)
obj.join(arr)

join() doesn’t delete merged objects; usually we want to delete all clones after merging. To remove an object from the scene, we can use the following command:

scene.unlink(anObj)

Reminder… to iterate in python:

for x in range(N) # e.g range 10 iterates from zero to 9

If you’re in a hurry, a modal UI provides the quick and dirty way to input data from the user:

numX = Blender.Draw.PupMenu(“X dupli%t|1|2″)

This gets the user to input either ’1′ or ’2′.

Complete Source Code

#!BPY

“”" Registration info for Blender menus:

Name: ‘Tile v0.0′

Blender: 249

Group: ‘Object’

Tip: ‘Tile an object along x,y,z axis and merge’

“”"

import Blender

import bpy

from Blender import *

# TILE V0.0 – A SIMPLE SCRIPT FOR TILING AND MERGING THE RESULT

# LICENSE: LGPL

def copy_and_merge(nx,ny,nz):

scene=Blender.Scene.GetCurrent()

target=scene.objects.active

dimX=target.getBoundBox()[6][0]-target.getBoundBox()[0][0]

dimY=target.getBoundBox()[6][1]-target.getBoundBox()[0][1]

dimZ=target.getBoundBox()[6][2]-target.getBoundBox()[0][2]

clones=[]

for x in range(nx):

for y in range(ny):

for z in range(nz):

Object.Duplicate(mesh=1)

clone=scene.objects.active

clone.LocX+=dimX*x

clone.LocY+=dimY*y

clone.LocZ+=dimZ*z

clones.append(clone)

clone.select(0)

target.select(1)

first=clones.pop()

first.join(clones)

for k in clones: scene.unlink(k)

# ————————————–
# Get the number of copies from the user and run the script

numX = Blender.Draw.PupMenu(“X dupli%t|1|2|3|4|5|5|6|7|8|9|10″)

numY = Blender.Draw.PupMenu(“Y dupli%t|1|2|3|4|5|5|6|7|8|9|10″)

numZ = Blender.Draw.PupMenu(“Z dupli%t|1|2|3|4|5|5|6|7|8|9|10″)

copy_and_merge(numX,numY,numZ)

# END ————————————

This is it. Modifying the script just a little can help you make staircases, fences and all kind of stuff, so I think it’s a nice introduction to how scripting can help generating scenes quickly and easily.

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()

The Payload…

Python is installed by default on OS X, open your terminal and type ‘python’ – this will display a version number, e.g. 2.6.1 or the like.  This usually means your OS bundled version of python is out of date. Also, it doesn’t have anything like a small IDE to get started, or make it easy to launch python files. So maybe we need something better.

www.python.org/download/

Unless you can’t access the download link above, you have no reason to get it from cnet or activestate.

Installing (OS X)

Don’t do what I did (see Appendix). Open a terminal window, cd to the extracted stuff, and type this sequence of commands:

./configure –enable-framework (1)
make
make test
sudo make install
(1) [DOT][SLASH]configure[SPACE][DASH][DASH]enable[DASH]framework
This will configure a make file, then run it, then test the output, then install Python and IDLE! It will take time but it worked (Saturday, November 27 2010).
Finally check your Applications directory. You should have a Python 3.1 folder with IDLE and a Python launcher (makes your python files double-clickable).

Quick Python tutorials

The official python homepage is more accessible than the download link (sigh). It’s nice to learn, maybe not the fastest way to get productive.

An informit python tutorial takes you through the basics of python, starting with explaining HTF you run a python script, surely we don’t want to do everything in ‘interactive mode’, right?

Object Python

A couple of nice tutorials from Voidspace (whatever that is…) and IBM.

Give me an IDE!

While the tests are running, note that there’s a couple of endless lists of python IDEs:

Notable?

  • IDLE. You can’t miss it because it ships with your python install
  • Need I mention you can get an eclipse plugin for python? Maybe not.
  • Komodo maybe. It’s not free.
  • Spyder. Seems like a python IDE in python and it’s supposed to be Mat-lab like.

Appendix – Don’t do this.

Installing on Windows was easy. I don’t really think there’s a lot more to it than just double clicking. Done it quite a while back.
Installing on OS X isn’t too hard. I used TheUnarchiver to extract. Then I saw there was a README file with a couple of quizzical lines:

./configure
make
make test
sudo make install

./configure
make
make test
sudo make install

I blissfully ignored this and double clicked a file called install-sh. Nothing interesting happened, so I opened a terminal window instead, cd (browse) to the extracted folder and type the commands one by one (they take time to complete, please read on…). For the record, make test spat out something like:

Python build finished, but the necessary bits to build these modules were not found:
_gdbm              ossaudiodev        readline
spwd
To find the necessary bits, look in setup.py in detect_modules() for the module’s name.

I decided to ignore it. Make test displayed other errors. Looks like a kind of python self test. Well, not everything is perfect.
The overall feel (took more than 30 minutes) is that the whole thing is being built and tested from the ground up. I’d say everything went perfectly smooth except for the worrying output…
and the fact that this doesn’t generate any of the standard install for OS X. No MacPython folder. No easy to launch IDLE thing… Sigh.