Forum Moderators: Staff
Poser Python Scripting F.A.Q (Last Updated: 2024 Sep 18 2:50 am)
Well, I can see why you'd have a problem with the change you made. Props are actors so they are a sub-part of a figure. What you've got here looks like it should have tanked immediately. I'll take a look at the script and see if I can make some suggestions. If it's a simple change I'll re-do the script. Check back.
Heres a fix. One quirk is that hair items might be affected by the script below. Need to go back and figure out how to filter out hair items. The scene.Actors() is supposed to return only props. Since hair can be a smart prop it's probably getting lumped in. I'm going to set up a page on my website Monday night or Tuesday just for scripts and I'll post this one there. I've only posted the critical changes below starting from after the imports... scene = poser.Scene() actors = scene.Actors() for actor in actors: try: geom = actor.Geometry() except: # do anything so we don't have a syntax error... x = 1 else: if actor.IsProp(): verts = geom.Vertices() norms = geom.Normals() i = 0 for vert in verts: # do buling here # keep this inside if prop check actor.MarkGeomChanged() scene.DrawAll() What you want to do is use the scene.Actors() which returns all non-figure actors in the scene. Then do an if actor.IsProp() check to eliminate lights, magnets, etc.
Off-Topic Style Notes and Grief-Saving Tips for jbrugion: >>try: >>geom = actor.Geometry() >>except: >># do anything so we don't have a syntax error... >>x = 1 ... "pass" is Python for "do nothing." It's easier to comprehend than a (supposedly) harmless assignment (x = 1) and explanatory comment. Using it might also save hours of unproductive weeping and cursing when 'x' turns out not to be quite as unused as you thought or when some reckless person (possibly me) modifies your script to introduce a 'new' variable they call 'x' and now wonders why it keeps getting set to 1 under such MYSTERIOUS circumstances. At the same time, specifying the exception type you expect (especially when you're going to tolerate it and aren't absolutely certain that the tried code can only throw one type of exception) makes the code more expressive and much less likely to baffle you when it throws something unexpected and intolerable. In this case, as well, I'm pretty sure you'd find out in testing (if not in coding) that a syntax error is not the exception you should really expect. (I'm ignorant regards the Geometry() method or I wouldn't express any doubt.) Left as a comment, it'll just sit there confusing the innocent. Reminding You: "Presentation is Everything," -Jud.
I agree with you about the usage of pass vs x=1 but I didn't write the original script, Curious Labs did. FYI for all listeners, the reason you have to wrap the Geometry() method with an exception handler is that is doesn't always return a value of 'None' if there is no geometry present. That's a quirk (as opposed to a bug) that CL is aware of and may fix later. For now, it's the only one, besides hand rolled file I/O , that I'm aware of that you really need to wrap with a try. For ScottA - go to http://home.earthlink.net/~redink3d/bulgePropsNormal.py This version works on my machine (WOMM). Beware that it also affects hair. Need to set a conditional for that. Will hopefully post a better looking version with a gui later this week/weekend.
Thanks JB. That script works great. Just so you know. I edit that script a lot to change the strength of the bulge. I have to manually edit this line: rndMagnitude = 0.02 It would be nice if I could change the setting with a slider,buttons,list box or something similar without needing to hack the script. Thanks for the help. ScottA
jbrugion, Yikes! Sorry for the misdirection. If I'd known, I'd have promoted what I said from a tip-of-the-day to a vigorous headslap for CL. Many thanks for introducing me to the concept of code "quirk." (I can hear myself saying: "It's an idiosyncratic little program, full of unusual takes on modern life. Think of it as a Rebel and not something that just crashed your Macintosh taking the disk directory structure with it. The Mac is very high-strung and sensitive itself, as you know, and has its own issues..." Yes, I like this idea! I like it very much.) FYI (can't get out of tip-of-the-day mode), exceptions turn out to be useful in one's own code on a pretty much daily basis, particularly dealing with lists. try: mylist.remove(whatever) except ValueError: #wasn't there. pass is preferred by some to searching the list first to avoid the exception you get when 'whatever' isn't on the list. It's certainly faster. Specifying the exception type doesn't add much to readability or safety in this case, but it's not a bad habit to get into. Ah, I see what you folks are saying about whitespace. The post also eats anything that even looks like an HTML tag (and I'm pretty sure there really isn't a sarcasm /sarcasm tag in HTML)
Attached Link: http://home.earthlink.net/~redink3d/bulgePropsNormal.py
I'm using the script jbrugion posted for me. ScottAWell, I got it to work, sorta. In the current form, the bulge script isn't very amiable to use with a TkInter slider. The problem is that as the slider is moved (either direction), each step of the slider is acted on and the effect is cumulative. I was using a hair prop as a target. It was kinda funny watching it grow to a point where it looked like the poor P4NF figure was being attacked by the hairball from hell. ;-) I'll tinker with it some but it looks like a full re-write of the logic flow is necessary.
Attached Link: http://bushi3d.com/PythonScripts/BulgeProp.py
I realized that I made a mistake on how I implemented the TkInter version of rbrugion's BulgeProp script. I re-did the slider so that it just runs free (it's very fast this way) and added a Go! button that pulls the current value of the slider. The results are cumulative so use small increments to check the effect. I'm thinking of adding an un-do button which would make it more useful. Try it on the standard female hair props for some interesting results.If I can throw my two cents in. What I would suggest is a gui like this: a list box that gives the scene prop actors after selecting an actor then slider then bulges the prop in and out interactively. Move the slider right and it gets bigger, move it left and it gets smaller. In the inner works you simply save off the orignal geometry state of the prop at selection and recompute off the base geometry every time the slider value changes. Set the initial value of the slider in the middle and you can positive and negative bulge prop. Add a "save" or ok button to save off the new prop with a popup to ask what to save it as. If anyone's interested in this I'll see if I can implement this tonight or over the weekend. Bushi- are you using a Mac? I'm getting some extra CR-LF crap on every line of your script when I save it from Netscape.
Absolutely fantastic script Bushi. Thank you. An undo function would make this thing perfect! I love the way you set up that slider control. This thing should be useful. It does some cool things to the hair like you said. And it could take making trans maps for them into a new level of usefulness. Nice work. ScottA
Bushi, jb: Maybe I'm way off here (and if so, I apologize) because I'm not all that experienced in using python & Tk (at least like this). Wouldn't your script still run "free" if instead of a "go" button, you had the processing part of the script tied to a "mouseUp" function that was part of the slider move? What I'm getting at is, if you wanted to, the "go" click could be eliminated and still save processing cycles. You move the slider with a mouseclick, and when it's released, the update is initiated. Haven't tried it, just a thought. I didn't have time to look at or code this myself. --
servo - No, your not off base at all. I'm pretty new to Python and TkInter. I'm certain there are lots of ways of doing this stuff different and better then I've done them. I'm just going with what I've figured out so far. If you do have a chance to look at the code and improve it please do show an example. I learn best by seeing other folks coding examples. :-)
You can use the callback (command = ...) option on the Tk scale to get a notification that the scale value has changed. Example below. NOTE: the callback has to expect an argument when it's called: a string representing the new value of the scale. This useful piece of info is missing from the current Tkinter docs and buried in Grayson's very nice book, but it's in the Tk/Tcl manual. There are just some spots with Tkinter where you have to go that far. Regards,
from Tkinter import *
def report(value):
print 'value received %s' % value
def TestScale():
root = Tk()
s = Scale(root, orient = HORIZONTAL, from_ = 0, to = 255, command = report)
s.set(100)
s.pack()
root.protocol("WM_DELETE_WINDOW",root.quit)
root.mainloop()
root.destroy()
jcarp - Yes, I used an interrupt-handler similiar to this the first time through. The basic problem though is that the process to change the vertices takes a ton of cycles so the scale action is pretty erratic. Thanks for passing that along, it is appreciated. Turn-about is fair play so take a look in the Grayson book at the 'after' method. (Lutz - Programming Python has a better section on it.) I've recently started using it with scales and it works quite well. No Go! button to activate a process and the scale runs free so it's fast.
bushi, Glad you've got it worked out. I've used 'after' in a different context, but turnabout is indeed fair play (and welcome). I thought repeatdelay and repeatinterval options on the Scale would do the same thing (control the sampling rate). I don't know if that's true, and it may not provide you with any advantage to 'after.' But, it might be slightly simpler.
I see now that 'repeatdelay' and 'repeatinterval' don't do what I thought. I'm completely clueless as to what they actually do. And in coming to this conclusion, I find the Scale widget appears to have the unusual property (for a widget) of not taking event bindings. I now have way more questions than I have answers. Thanx.
OK, if you care, here's the deal. The repeatdelay and repeatinterval options control moving the slider when mousebutton-1 is held down in the trough. And, like any other widget, event bindings only apply when the widget has focus. If I'd put my hack-your-way-to-an-answer test widget in a frame I might have seen that. I believe none of this is relevant to the desired behavior of your widget, which was to change values gracefully while being dragged, which you have long since solved. BTW, in the course of this nonsense I found a reference for Tkinter that fills in some gaps, and which I'll post in a new thread.
jcarp - Yes, I took a similiar path when initially looking into to scales and came to the same outcome. That's what got me interested in some type of free-running timer interrupt. As you found, the RDelay sets how long you have to hold the mouse down 'in the trough' to start auto-repeating. The RInterval sets how often the auto-repeat occurs. With the 'after' interrupt-handler, you can use the scale.get() method to find the current value of the scale. I'd be interested in seeing the new reference for TkInter you've found. I'm still trying to figure out how to allocate a group of checkbuttons at runtime. In this case, the number of checkbuttons is determined by the number of MTs. I have had little luck finding examples that work the way I want.
bushi, Not to beat a dead horse, but another way to do it is to put a check into the handler and only do the action if a certain amount of time has expired. The action then gets done iff the scale value changes AND the grace time is up. This burns a few cycles doing the check every time the value changes, but that shouldn't make any practical difference. Exercise left to reader (unless reader howls loudly). Also, there is servo's original recommendation. You can bind the 'ButtonRelease-1' event to the scale and do the action only on release. Poser sliders don't operate like this, so it's probably not what you want. (And again, example left to reader unless whining heard.) I think you'll like the Tkintr reference. The author's filled in a lot of stuff missing from F. Lundh's Intro and Grayson's book. And done an excellent job from what I've seen so far. I'm very happy to have tripped over it. Don't understand your problem with dynamic allocation of buttons. If it's an example you want, tell me what you want to do and I'll take a whack at it. I don't have PPP, so if you could make it generic that would make life easier. Also you might look at the Pmw widget collection and documentation, if you already haven't. It's really convenient for a lot of things, especially when it comes to repackaging widgets in combination. Here's snippet that shows adding multiple selection check buttons to a collection. Buttons, after adding, can be referenced by label name ('Whole Word' for example) or positionally (the 'Regular Expression' checkbox is button 0, 'Whole Word' is button 1, ...):
[snip...]
self.options = Pmw.RadioSelect(self.dialog.interior(),
buttontype = 'checkbutton',
orient = 'vertical',
selectmode = 'multiple')
self.options.add('Regular Expression')
self.options.add('Whole Word')
self.options.add('Match Case')
self.options.add('Wrap Around')
self.options.pack()
[...snip]
jcarp - Yes, I have looked at the PMW module widgets. It's a really useful collection that's certain. At this point though, I'm trying to avoid adding extra mods as much as possible. This is simply because I don't want to add an extra level of complexity for users to deal with (downloading, installing etc.) in the scripts I'm publishing. As to dymanically allocating checkbuttons, the problem is pretty simple. I just haven't figured out how to do it correctly. In non-Poser terms, say you had a list of items. This list changes every time you run the script since it's being derived from a file. All the elements that make up the list are of the same type, just the number of elements changes. So the question is how do I allocate a checkbutton for each element in the list when I run the script? All of the checkbuttons will be located in a single sub-frame that will be displayed when the user clicks on button in the main frame. I think I have a direction to go in since I've been working a bit more with classes and that looks like a healthy avenue to explore.
bushi, You are, of course, very wise in avoiding Pmw in this context, for all the reasons you mention. You can, though, look to Pmw for hints on packaging Tk widgets. I suspect you're pretty much home on check buttons, but I'll give a simple example a shot (and I can learn how Tk buttons really work at the same time). Who knows, maybe even today. The basic idea's going to be: allocate a button for each item on the list and give yourself some way to associate the button with the list item. Something like:
buttonlist = []
for item in arbitrarylist:
abutton = Checkbutton(...)
buttonlist.append(abutton)
#now the buttons on buttonlist correspond to the items
#on arbitrarylist. item arbitrarylist[i] is for button buttonlist[i].
#To display:
for button in buttonlist:
button.pack(...) #or grid() or place()
Anyway, I'll come back with something that actually works. As a class, even. Soon. Soon, I tell you. Of course, if I'm like totally not getting what you need to see, let me know at your earliest convenience.
Yes, this looks like it's going in the right direction. I've been building some classes using just list items. I haven't tried it at all using TkInter widgets but this example looks as I expected it should for widgets. Could you explain the grid() a bit. I haven't seen that method but I suspect that it helps to put the buttons in proper rows and columns. Right?
Attached Link: http://www.pythonware.com/library/tkinter/introduction/grid.htm
Yes, exactly. Grid() is a geometry manager like pack(). It lets you lay out the window in rows and columns. You can say: widget.grid(column = x, row = y), for all the widgets in your frame. Pack(), for me anyway, becomes more like either a puzzle or a Frame factory explosion when I have more than 3 widgets to lay out. Grayson's chapter 5 has a much better explanation in section 5.3 than I can provide. Lundh's intro section on grid() is also real good, and I've included the link. grid() simplifies life a good deal, and I'll use it in the button list example, should I ever actually get started on that. Two opportunities for frustration with grid(): you can't mix it with pack() with the same Tk master. Your application will hang if you do. Also, getting a widget displayed with grid() to expand when you resize the window is a two-step process: use the 'sticky' option in grid() and the rowconfigure() and columnconfigure() methods of the geometry master (frame or Toplevel, for example). As a practical matter, once you understand those two things, it's a much nicer method than pack() in most circumstances.Attached Link: http://home1.gte.net/judcarp/cblscript.htm
bushi -- Here's my try at a checkbutton list. I hope there's something here that helps you along. The design problem the list has to solve is how to package a button's indicator variable with the button. I've chosen to encapsulate button and variable in a class. It seems straightforward to me, although there are more concise ways to do the same thing. Notice, however, that this adds a level of indirection for getting at the button (see the 'turnred()' test routine for an illustration.) You can easily avoid this by making ButtonEntry() a subclass of CheckButton(). I thought it might complicate things if I did, and it *does* illustrate a recurring software design problem. I slammed everything into the same frame to illustrate the grid() method. I think you can see from the code in the TestCL() routine and the showall() method the needless complications this causes. Apologies for the lame example program humor. I notice also that I've started to use 'foobar' example file names. I think it's time somebody took me to the Horse Hospital (i.e., shot me). Finally, I'm using Python v. 2.0. I tried to avoid anything not in v. 1.5.2, but if I failed, let me know.Shoot (speaking of the Horse Hospital), I realize i've probably solved more problem than you actually had. If you just want to keep the button with the arbitrary list item, all you really need is the ButtonEntry class in the script above. As in:
m = Frame()
itemsandbuttons = []
for item in arbitrarylist:
mylabel = ...
b = ButtonEntry(m, text = mylabel)
b.getbutton().grid()
itemsandbuttons.append((b, item))
I'm not sure keeping the buttons on their own list necessarily does anything for you. You be the judge.
jcarp - Hey, that's very cool! Thanks for taking the time to put these examples together for me. It'll take a day or two for me to pick apart the cblscript and I'm certain I'll have some questions. I can tell though that it's exactly what I was looking for. Time to crank up PythonWin and put it through it's paces. Thanks again! :-)
This site uses cookies to deliver the best experience. Our own cookies make user accounts and other features possible. Third-party cookies are used to display relevant ads and to analyze how Renderosity is used. By using our site, you acknowledge that you have read and understood our Terms of Service, including our Cookie Policy and our Privacy Policy.
Hey Guys. I have no idea how to program with Python. But I need something that seems to me kinda simple. There is currently a bulge script that will bulge out poser figure's. I can alter that script to get a better bulging out of it. But the problem is. This thing only works with figures. I need a bulge script for props. I tried simply replacing the: figs = scene.Figures() with figs = scene.Props() But it didn't work. Can this be done by modifying the current bulge script somehow? ScottA