Python

General debates and discussion about the Guild of Writers and Age creation

Postby Jonnee » Mon Dec 04, 2006 1:02 am

Hello Age Builders!

My next age is coming soon. Creation works fine, but I need help in writing the python scripts.
Robert The Rebuilder gave me a script that opens a door after pressing a button. You can see it here. It works fine and I use it alot in my Jo'nae age. :D
Now I have to seek for your's assistance:
Somebody please may modify the script for me, so that I can open two doors with it after pressing the button? One door should slide down and the other door should slide up on the Z axis. (like the Bahro Cave door)
My python skills are not well enough for doing it by my own, and I don't want to ask Robert again for help. He's pretty busy with other things... B)
I would be very thankful.

And then I'd like to have another script:
In the Functionality Check Age are some pistons that slide up and down continuously. I checked the FuncChk01Clickables.py and also tried to modify the script for my own use, but did not have any success.
My idea is a floating rock in the sky that slides slow up and down. Just as a visual effect.
Who can write that script for me please, so that I can import it easily to the main python file? The rock should slide 10 seconds up, stay there for 3 seconds, then slide down in 10 seconds, stay there 3 seconds too and then it repeats the movement.

Phew... That's alot. Image
But ill will be worth your's assistance, because there's coming something really huuuuuge. Image

Thank you very much and have a good week!
Greetings, Jonnee
User avatar
Jonnee
 
Posts: 266
Joined: Fri Nov 16, 2007 9:45 pm

Postby Robert The Rebuilder » Tue Dec 05, 2006 6:20 pm

Christmas came early this year, Jonee!

Here's the code to do what you asked; in this example, it is a modification of FuncChk01.py, which moves the piston in the same manner as your rock. I make use of the sin() function, in order to have a smooth start and stop.

Note: I only listed the functions that were necessary for accomplishing this, for brevity's sake. You can replace them in your own copy of FuncChk01.py to see the piston doing this; then you can borrow code from it and place it into your age's script.

Code: Select all
    def __init__(self):
        ptResponder.__init__(self)
        self.id = 1570000
        self.version = 1
        self.Piston1Obj = None
        self.AgeName = None
        self.MovePistonInterval = .03
        self.MovePistonTimerId = 1
        self.ClearR = 0
        self.ClearG = 0
        self.ClearB = 0
        self.PistonScalar = 1
        # Set the middle position to the center z value of the piston
        self.MiddlePistonZ = 5
        # Set the z scalar to how high you want the piston to move
        self.ZScalar = 2
        # Variables for the piston movement cycle
        self.cycleStartTime = 0
        self.goingUpDuration = 10
        self.stayingUpDuration = 3
        self.goingDownDuration = 10
        self.stayingDownDuration = 3
        self.cycleTotalDuration = self.goingUpDuration + self.stayingUpDuration + self.goingDownDuration + self.stayingDownDuration
        

    def OnFirstUpdate(self):
        self.AgeName = PtGetAgeName()
        print 'FuncChk01.OnFirstUpdate(): AgeName=', self.AgeName

    def OnServerInitComplete(self):
        print 'FuncChk01.OnServerInitComplete()'
        # Set the background color
        PtSetClearColor(self.ClearR,self.ClearG,self.ClearB)
        # Obtain the piston object
        self.Piston1Obj = PtFindSceneobject("Piston1", self.AgeName)
        # Mark the start of the up-pause-down-pause cycle
        self.cycleStartTime = time.clock()
        # Register a timer callback for moving the piston objects
        PtAtTimeCallback(self.key, self.MovePistonInterval, self.MovePistonTimerId)

    def OnTimer(self, id):
        # Check for the piston timer
        if (id == self.MovePistonTimerId):
            portionOfCycle = time.clock() - self.cycleStartTime
            if (portionOfCycle > self.cycleTotalDuration):
                portionOfCycle -= self.cycleTotalDuration
                self.cycleStartTime += self.cycleTotalDuration
            # Four phases of cycle:
            # I. going up (10 seconds): -1 to 1, or sin(-PI/2) to sin(PI/2)
            # II. staying up (3 seconds)
            # III. going down (10 seconds): 1 to -1, or sin(PI/2) to sin(-PI/2)
            # IV. staying down (3 seconds)
            # Which phase are we in now?
            if (portionOfCycle < self.goingUpDuration):
                print 'In phase I'
                # Map the time to the interval [-PI/2,PI/2] and turn it into a zOffset
                value = math.pi * ((portionOfCycle/self.goingUpDuration) - 0.5)
                zOffset = self.ZScalar * math.sin(value)
            elif (portionOfCycle < (self.goingUpDuration + self.stayingUpDuration)):
                print 'In phase II'
                # Hold the piston up at the top
                zOffset = self.ZScalar
            elif (portionOfCycle < (self.goingUpDuration + self.stayingUpDuration + self.goingDownDuration)):
                print 'In phase III'
                # Subtract off the durations of the first two phases
                portionOfCycle -= (self.goingUpDuration + self.stayingUpDuration)
                # Map the time to the interval [PI/2,-PI/2] and turn it into a zOffset
                value = -math.pi * ((portionOfCycle/self.goingDownDuration) - 0.5)
                zOffset = self.ZScalar * math.sin(value)
            else:
                print 'In phase IV'
                # Hold the piston at the bottom
                zOffset = -self.ZScalar
            print 'zOffset = ', zOffset
            # Warp the piston to the new height
            pistonPos = self.Piston1Obj.position()
            newPistonPos = ptPoint3(pistonPos.getX(),pistonPos.getY(),zOffset + self.MiddlePistonZ)
            self.Piston1Obj.physics.warp(newPistonPos)
            # Register for another piston update
            PtAtTimeCallback(self.key, self.MovePistonInterval, self.MovePistonTimerId)



Looking forward to seeing your new age!
Can we rebuild it? Yes, we can - here's how.

MOULagain KI# 1299

Myst Movie coming soon - spread the word!
User avatar
Robert The Rebuilder
 
Posts: 1383
Joined: Sat Sep 29, 2007 7:24 am
Location: Virginia, US

Postby Jonnee » Tue Dec 05, 2006 11:54 pm

Whow. That's overwhelming! :D
Thank you very, very much for reworking the script for me. I will try it as soon as possible.
First preview screenshots of the new age will follow soon too. You'll like them! Definitly. B)

Greetings from far away Berlin...
Jonnee

EDIT:
Screenshots are now available at the H'Uru forum.
User avatar
Jonnee
 
Posts: 266
Joined: Fri Nov 16, 2007 9:45 pm

Postby Jonnee » Sat Dec 09, 2006 6:24 am

Hello, Robert!

I tried it, but I get an error when I want to pack the files.

What does this mean and how can I avoid it?:

Out file not created
File "D:/Programme/Ubi Soft/Cyan Worlds/Uru - Ages Beyond Myst/Python/Src/FuncChk01.py", line 12
def __init__(self):
^
SyntaxError: unindent does not match any outer indentation level
User avatar
Jonnee
 
Posts: 266
Joined: Fri Nov 16, 2007 9:45 pm

Postby Drakmyth » Sat Dec 09, 2006 1:35 pm

Wow, a question I can possibly answer :lol:

Instead of using curly braces ( { and } ) to determine hierarchy within code, or using keywords (end if, fi, end with, wend, etc.), Python uses indentation only. This means that if a line has even one too many/few spaces before it, it will choke. This is why it is strongly recommended to use the tab key instead of spaces, it guarentees things line up. I haven't seen the Python file so I couldn't tell you exactly where the error lies, but something right around that line in the code should be indented wrong, (probably only by one space). As for the ^ telling you where the error is, it is generally near (though not on) the correct line and almost never on the correct character.

The error unindent does not match any outer indentation level tells me that the end of a code block is misaligned, not the beginning. take something along the lines of this example.

Code: Select all
for (int i = 0; i < myArray.size(); i++)
    if (i <= 5)
        System.out.println("Hello World!");
   end if


Now this is actually a pretty bad example because this is written in an incorrect java/visual basic crossbreed to serve my purpose. See if you can follow me though.

The line for (int i = 0; i < myArray.size(); i++) is all the way against the left side of the screen; there are no spaces before it.
The line if (i <= 5) has 4 spaces before it, this would tell python that this is a new block of code nested inside the FOR loop (which, I believe, does need to be indented).
The line System.out.println("Hello World!"); has 8 spaces in front of it, showing that it is nested into the IF statement (in python I believe this is also necessary to indent).
The final line end if has 3 spaces in front of it. However, this line is supposed to indicate the end if the IF statement 2 lines above. Python does not actually have an "end if" command, it checks this by comparing the amount of spaces before the line. Since the "end if" line has 3 spaces and there are no lines above it indenting 3 lines, you get the unindent does not match any outer indentation level error.


Assuming that you are not unimaginably confused by now (which I think I would be if I read this), it becomes apparent that the problem is one of your lines is indented wrong. Double check to make sure every line has a partner line (a line with the same amount of beginning spaces). If one doesn't, that is probably what's causing the error and just add or subtract lines to get it to partner with the line it's supposed to.

EDIT:
I looked at the code posted above and I see it is all indented correctly. It may have been a problem with the copy/paste not aligning right. Same error, just letting you know. I also modified my example to be put in a code block so spaces are kept instead of using *'s.
"The maniacal laugh of Drakmyth is not bound by the Ages!" ~ Talashar
Party time kiddies... I'm back!
User avatar
Drakmyth
 
Posts: 8
Joined: Fri Nov 16, 2007 9:45 pm
Location: Chillin'

Postby Jonnee » Sun Dec 10, 2006 12:56 am

Ahhh. nice. B)
Now I understand the meaning of that "outer indentation level".
But for me everything looks fine, don't see where the error is. Maybe I forgot a whole passage??
Still need help, don't get it running.... :rolleyes:
User avatar
Jonnee
 
Posts: 266
Joined: Fri Nov 16, 2007 9:45 pm

Postby Robert The Rebuilder » Sun Dec 10, 2006 8:35 pm

Jonnee:

Can you post a link to your age's .py file? Another set of eyes might be able to identify the problem.
Can we rebuild it? Yes, we can - here's how.

MOULagain KI# 1299

Myst Movie coming soon - spread the word!
User avatar
Robert The Rebuilder
 
Posts: 1383
Joined: Sat Sep 29, 2007 7:24 am
Location: Virginia, US

Postby Jonnee » Mon Dec 11, 2006 5:18 am

Code: Select all
# emacs-mode: -*- python-*-
from Plasma import *
from PlasmaTypes import *
from PlasmaKITypes import *
from PlasmaVaultConstants import *
from PlasmaNetConstants import *
import PlasmaControlKeys
import xLocalization
import string
import time
import ConfigParser

class Piston1(ptModifier,):
    __module__ = __name__
    __module__ = __name__
    __module__ = __name__
    __module__ = __name__
    __module__ = __name__
    __module__ = __name__
    __module__ = __name__


   def __init__(self):
       ptResponder.__init__(self)
       self.id = 1570000
       self.version = 1
       self.Piston1Obj = None
       self.AgeName = None
       self.MovePistonInterval = .03
       self.MovePistonTimerId = 1
       self.ClearR = 0
       self.ClearG = 0.2
       self.ClearB = 0
       self.PistonScalar = 1
       # Set the middle position to the center z value of the piston
       self.MiddlePistonZ = 110
       # Set the z scalar to how high you want the piston to move
       self.ZScalar = 5
       # Variables for the piston movement cycle
       self.cycleStartTime = 0
       self.goingUpDuration = 10
       self.stayingUpDuration = 3
       self.goingDownDuration = 10
       self.stayingDownDuration = 3
       self.cycleTotalDuration = self.goingUpDuration + self.stayingUpDuration + self.goingDownDuration + self.stayingDownDuration
      

   def OnFirstUpdate(self):
       self.AgeName = PtGetAgeName()
       print 'FuncChk01.OnFirstUpdate(): AgeName=', self.AgeName

   def OnServerInitComplete(self):
       print 'JonaeHood.OnServerInitComplete()'
       # Set the background color
       PtSetClearColor(self.ClearR,self.ClearG,self.ClearB)
       # Obtain the piston object
       self.Piston1Obj = PtFindSceneobject("Piston1", self.AgeName)
       # Mark the start of the up-pause-down-pause cycle
       self.cycleStartTime = time.clock()
       # Register a timer callback for moving the piston objects
       PtAtTimeCallback(self.key, self.MovePistonInterval, self.MovePistonTimerId)

   def OnTimer(self, id):
       # Check for the piston timer
       if (id == self.MovePistonTimerId):
           portionOfCycle = time.clock() - self.cycleStartTime
           if (portionOfCycle > self.cycleTotalDuration):
               portionOfCycle -= self.cycleTotalDuration
               self.cycleStartTime += self.cycleTotalDuration
           # Four phases of cycle:
           # I. going up (10 seconds): -1 to 1, or sin(-PI/2) to sin(PI/2)
           # II. staying up (3 seconds)
           # III. going down (10 seconds): 1 to -1, or sin(PI/2) to sin(-PI/2)
           # IV. staying down (3 seconds)
           # Which phase are we in now?
           if (portionOfCycle < self.goingUpDuration):
               print 'In phase I'
               # Map the time to the interval [-PI/2,PI/2] and turn it into a zOffset
               value = math.pi * ((portionOfCycle/self.goingUpDuration) - 0.5)
               zOffset = self.ZScalar * math.sin(value)
           elif (portionOfCycle < (self.goingUpDuration + self.stayingUpDuration)):
               print 'In phase II'
               # Hold the piston up at the top
               zOffset = self.ZScalar
           elif (portionOfCycle < (self.goingUpDuration + self.stayingUpDuration + self.goingDownDuration)):
               print 'In phase III'
               # Subtract off the durations of the first two phases
               portionOfCycle -= (self.goingUpDuration + self.stayingUpDuration)
               # Map the time to the interval [PI/2,-PI/2] and turn it into a zOffset
               value = -math.pi * ((portionOfCycle/self.goingDownDuration) - 0.5)
               zOffset = self.ZScalar * math.sin(value)
           else:
               print 'In phase IV'
               # Hold the piston at the bottom
               zOffset = -self.ZScalar
           print 'zOffset = ', zOffset
           # Warp the piston to the new height
           pistonPos = self.Piston1Obj.position()
           newPistonPos = ptPoint3(pistonPos.getX(),pistonPos.getY(),zOffset + self.MiddlePistonZ)
           self.Piston1Obj.physics.warp(newPistonPos)
           # Register for another piston update
           PtAtTimeCallback(self.key, self.MovePistonInterval, self.MovePistonTimerId)




glue_cl = None
glue_inst = None
glue_params = None
glue_paramKeys = None
try:
    x = glue_verbose
except NameError:
    glue_verbose = 0

def glue_getClass():
    global glue_cl
    if (glue_cl == None):
        try:
            cl = eval(glue_name)
            if issubclass(cl, ptModifier):
                glue_cl = cl
            elif glue_verbose:
                print ('Class %s is not derived from modifier' % cl.__name__)
        except NameError:
            if glue_verbose:
                try:
                    print ('Could not find class %s' % glue_name)
                except NameError:
                    print 'Filename/classname not set!'
    return glue_cl



def glue_getInst():
    global glue_inst
    if (type(glue_inst) == type(None)):
        cl = glue_getClass()
        if (cl != None):
            glue_inst = cl()
    return glue_inst



def glue_delInst():
    global glue_inst
    global glue_cl
    global glue_paramKeys
    global glue_params
    if (type(glue_inst) != type(None)):
        del glue_inst
    glue_cl = None
    glue_params = None
    glue_paramKeys = None



def glue_getVersion():
    inst = glue_getInst()
    ver = inst.version
    glue_delInst()
    return ver



def glue_findAndAddAttribs(obj, glue_params):
    if isinstance(obj, ptAttribute):
        if glue_params.has_key(obj.id):
            if glue_verbose:
                print 'WARNING: Duplicate attribute ids!'
                print ('%s has id %d which is already defined in %s' % (obj.name,
                 obj.id,
                 glue_params[obj.id].name))
        else:
            glue_params[obj.id] = obj
    elif (type(obj) == type([])):
        for o in obj:
            glue_findAndAddAttribs(o, glue_params)

    elif (type(obj) == type({})):
        for o in obj.values():
            glue_findAndAddAttribs(o, glue_params)

    elif (type(obj) == type(())):
        for o in obj:
            glue_findAndAddAttribs(o, glue_params)




def glue_getParamDict():
    global glue_paramKeys
    global glue_params
    if (type(glue_params) == type(None)):
        glue_params = {}
        gd = globals()
        for obj in gd.values():
            glue_findAndAddAttribs(obj, glue_params)

        glue_paramKeys = glue_params.keys()
        glue_paramKeys.sort()
        glue_paramKeys.reverse()
    return glue_params



def glue_getClassName():
    cl = glue_getClass()
    if (cl != None):
        return cl.__name__
    if glue_verbose:
        print ('Class not found in %s.py' % glue_name)
    return None



def glue_getBlockID():
    inst = glue_getInst()
    if (inst != None):
        return inst.id
    if glue_verbose:
        print ('Instance could not be created in %s.py' % glue_name)
    return None



def glue_getNumParams():
    pd = glue_getParamDict()
    if (pd != None):
        return len(pd)
    if glue_verbose:
        print ('No attributes found in %s.py' % glue_name)
    return 0



def glue_getParam(number):
    pd = glue_getParamDict()
    if (pd != None):
        if (type(glue_paramKeys) == type([])):
            if ((number >= 0) and (number < len(glue_paramKeys))):
                return pd[glue_paramKeys[number]].getdef()
            else:
                print ('glue_getParam: Error! %d out of range of attribute list' % number)
        else:
            pl = pd.values()
            if ((number >= 0) and (number < len(pl))):
                return pl[number].getdef()
            elif glue_verbose:
                print ('glue_getParam: Error! %d out of range of attribute list' % number)
    if glue_verbose:
        print 'GLUE: Attribute list error'
    return None



def glue_setParam(id, value):
    pd = glue_getParamDict()
    if (pd != None):
        if pd.has_key(id):
            try:
                pd[id].__setvalue__(value)
            except AttributeError:
                if isinstance(pd[id], ptAttributeList):
                    try:
                        if (type(pd[id].value) != type([])):
                            pd[id].value = []
                    except AttributeError:
                        pd[id].value = []
                    pd[id].value.append(value)
                else:
                    pd[id].value = value
        elif glue_verbose:
            print "setParam: can't find id=",
            print id
    else:
        print 'setParma: Something terribly has gone wrong. Head for the cover.'



def glue_isNamedAttribute(id):
    pd = glue_getParamDict()
    if (pd != None):
        try:
            if isinstance(pd[id], ptAttribNamedActivator):
                return 1
            if isinstance(pd[id], ptAttribNamedResponder):
                return 2
        except KeyError:
            if glue_verbose:
                print ('Could not find id=%d attribute' % id)
    return 0



def glue_isMultiModifier():
    inst = glue_getInst()
    if isinstance(inst, ptMultiModifier):
        return 1
    return 0



def glue_getVisInfo(number):
    pd = glue_getParamDict()
    if (pd != None):
        if (type(glue_paramKeys) == type([])):
            if ((number >= 0) and (number < len(glue_paramKeys))):
                return pd[glue_paramKeys[number]].getVisInfo()
            else:
                print ('glue_getVisInfo: Error! %d out of range of attribute list' % number)
        else:
            pl = pd.values()
            if ((number >= 0) and (number < len(pl))):
                return pl[number].getVisInfo()
            elif glue_verbose:
                print ('glue_getVisInfo: Error! %d out of range of attribute list' % number)
    if glue_verbose:
        print 'GLUE: Attribute list error'
    return None



# local variables:
# tab-width: 4
User avatar
Jonnee
 
Posts: 266
Joined: Fri Nov 16, 2007 9:45 pm

Postby Robert The Rebuilder » Mon Dec 11, 2006 9:40 am

Jonnee:

Thanks for posting it. To fix the compiler error, insert one more space before each "def ..." statement - for a total of three spaces. I tried it on a copy of Piston1.py that I made from your post, and it compiles.
Can we rebuild it? Yes, we can - here's how.

MOULagain KI# 1299

Myst Movie coming soon - spread the word!
User avatar
Robert The Rebuilder
 
Posts: 1383
Joined: Sat Sep 29, 2007 7:24 am
Location: Virginia, US

Postby Jonnee » Mon Dec 11, 2006 1:05 pm

Yes, it compiles now. Image
So... I just went to the JonaeHood to see how my three pistons move - but they don't do so. :blink:

Mmmhh, what did we forget?
I've created three different python files (Piston1, 2 and 3) and changed the names and values in it.
I've imported the files to my JonaeHoodObject.py and compiled all to my JonaeHood.py.
Code: Select all
# emacs-mode: -*- python-*-
from Plasma import *
from PlasmaTypes import *
from PlasmaKITypes import *
from PlasmaVaultConstants import *
from PlasmaNetConstants import *
import PlasmaControlKeys
import xLocalization
import string
import time
import ConfigParser
import JonaeHood_Movements
import JonaeHood_Movements2
import JonaeHood_Movements3
import JonaeHood_Movements4
import Piston1
import Piston2
import Piston3
.......

That's the procedure that worked everytime before.
Compiling works well and Elfview doesn't show me any errors.
Do the objects in the blender file need any properties?
User avatar
Jonnee
 
Posts: 266
Joined: Fri Nov 16, 2007 9:45 pm

Next

Return to General Discussion

Who is online

Users browsing this forum: No registered users and 0 guests

cron