S2A.py - the Sensor-To-Actuator library - 1.8

Hello all,

Version 1.8 S2A.blend

  • Bugfix: removed incompatibility to Python 3.0 (firstBodyToValue).

Version 1.7 S2A.blend

  • Added S2A.hitObjectListToBoolean - to mark/unmark hit objects.
  • Bugfixes (again) regarding firstBodyToValue.

Version 1.6 S2A.blend

  • Bugfixes for firstBodyToValue.

Version 1.3 S2A.blend

  • added function transfer.

Version 1.2

  • It is 2.5 compatible now.

Everybody know there are some limits with the logic bricks when working with sensor output that is not limited to True and False.
I had the idea to provide an easy to use library that can be used by Non-Python-experts as well.


[INDENT]S2A - the Sensor-To-Actuator library
[/INDENT]Why S2A? Just to make it shorter. The function names are long enought.
Attached you can find a demo file containig the S2A.py module and showing how it works.

The functions must be applied to a Python Module controller.
The common structure of the function name is:<sensorVariableName>+To+<actuatorVariableName>
or
<sensorVariableName>+ToPosition - to set the position of the actuator owners
or
<sensorVariableName>+ToAlign - to align the actuator owners to the sensors vector
Currently following functions are defined:

  • hitObjectToObject
  • closestHitObjectToObject
  • hitNormalToAlign
  • rayDirectionToAlign
  • hitPositionToPosition
  • rayTargetToPosition
  • raySourceToPosition
  • firstBodyToValue (1.1)
  • transfer (1.3)
  • hitObjectListToBoolean (1.7)

Please see the module source for more details. Especially on what sensors/actuators they can be used. Alternative you can see the Game Engine API.
If you have ideas for more, please post it here.

S2A - Documentation
Additionaly an html documentation is prepared with epydoc. It contains the browsable source code as well.



download S2A.html.zip.blend (27.3 KB)
Thanks to Sunjay03 for hosting the S2A API.

For offline use it is zipped with an additional “.blend”. If you want to use it:

  • remove the .blend
  • extract it to a folder
  • open index.html with a browser.

Here is the complete S2A.py version 1.1.
Do not apply it as a script. Apply it as module. See the top post for examples.

1.1

  • more documentation for epydoc
  • added firstBodyToValue

''' 
The Sensor-To-Actuator library
==============================

This module provides functions to transfer parameters from sensors
to actuators, sets position or aligns to a vector
'''

__version__ = "1.1"
__author__ = "Monster"
__package__ = "S2A"

#=============
# getValueOfPositive
#=============
def __getValueOfPositive(cont, attribute):
    '''
    Finds one positive sensor with hitObject.
    
    @param cont: the calling controller
    @param attribute: the sensors attribute to be read
    @return: the value of the sensors attribute
    '''
    for sensor in cont.sensors:
        if sensor.positive:
            try:
                return getattr(sensor, attribute)
            except AttributeError:
                continue

#=============
# getValueOf
#=============
def __getValueOf(cont, attribute):
    '''
    Finds one sensor with hitObject.
    
    @param cont: the calling controller
    @param attribute: the sensors attribute to be read
    @return: the value of the sensors attribute
    '''
    for sensor in cont.sensors:
        try:
            return getattr(sensor, attribute)
        except AttributeError:
            continue
                
#=============
# setValueTo
#=============
def __setValueTo(cont, attribute, value):
    '''Configure and activate all actuators.'''
    for actuator in cont.actuators:
        try:
            setattr(actuator, attribute, value)
        except AttributeError:
            pass # ignore
        cont.activate(actuator)

#=============
# getParam
#=============
def __getParam(obj, propName, default=None):
    '''Retrieves the property from the object. If not present returns default.'''
    try:
        return obj[propName]
    except KeyError:
        return default

#=============
# hitObjectToObject
#=============
def hitObjectToObject(cont):
    '''
    Takes the hitObject parameter of the sensor and 
    puts it to the object parameter of the actuator.
    
    Supported sensor types:
    =======================
        - MouseFocus
        - Near
        - Touch
        - Radar
        - Ray
        
    Supported actuator types:
    =========================
        - Camera
        - Parent
        - TrackTo
    
    The actuators will be activated. 
    @param cont: controller running this function
    '''
    hitObject = __getValueOfPositive(cont, "hitObject")
    if hitObject == None:
        return    
                
    __setValueTo(cont, "object", hitObject)

#=============
# closestHitObjectToObject
#=============
def closestHitObjectToObject(cont):
    '''
    Takes the hitObjectList parameter of the sensor and 
    puts the closest object from that list 
    to the object parameter of the actuator.
    
    Supported sensor types:
    =======================
        - Near
        - Touch
        - Radar
        
    Supported actuator types:
    =========================
        - TrackTo
        - Camera
        - Parent
    
    The actuators will be activated if one sensor is positive. 
    
    @param cont: controller running this function
    '''
    hitObjectList = __getValueOfPositive(cont, "hitObjectList")
    if hitObjectList == None:
        return    

    closestObject = hitObjectList[0]
    closestDistance = closestObject.getDistanceTo(cont.owner)
    for hitObject in hitObjectList:
        distance = hitObject.getDistanceTo(cont.owner)
        if distance &lt; closestDistance:
            closestObject = hitObject
            closestDistance = distance

    __setValueTo(cont, "object", closestObject)


#=============
# hitNormalToAlign
#=============
def hitNormalToAlign(cont):
    '''
    Takes the hitNormal parameter of the sensor and 
    aligns the orientation of the actuator owners accordingly.

    Supported sensor types:
    =======================
        - Mouse over
        - Mouse over any
        - Ray
        
    Supported actuator types:
    =========================
        - any

    The actuators will not be activated or changed.
    
    @keyword axis: (optional) the axis you want to align
            - 0 = X axis
            - 1 = Y axis
            - 2 = Z axis (default)
    @type axis: integer
    @keyword factor: (optional) only rotate a feaction of the distance to the target vector (0.0 - 1.0)
    @type factor: float
    @param cont: controller running this function
    '''
    hitNormal = __getValueOfPositive(cont, "hitNormal")
    if hitNormal == None:
        return
    
    axis = __getParam(cont.owner, "axis", 0)
    factor = __getParam(cont.owner, "factor", 1.0)
    
    for actuator in cont.actuators:
        actuator.owner.alignAxisToVect(hitNormal, axis, factor)
        
#=============
# rayDirectionToAlign
#=============
def rayDirectionToAlign(cont):
    '''
    Takes the rayDirection parameter of the sensor and 
    aligns the orientation of the actuator owners accordingly.
        
    Supported sensor types:
    =======================
        - Mouse over
        - Mouse over any
        - Ray
        
    Supported actuator types:
    =========================
        - any

    The actuators will not be activated or changed.
    
    @keyword axis: (optional) the axis you want to align
            - 0 = X axis
            - 1 = Y axis
            - 2 = Z axis (default)
    @type axis: integer
    @keyword factor: (optional) only rotate a feaction of the distance to the target vector (0.0 - 1.0)
    @type factor: float
    @param cont: controller running this function
    '''
    rayDirection = __getValueOfPositive(cont, "rayDirection")
    if rayDirection == None:
        return
    
    axis = __getParam(cont.owner, "axis", 0)
    factor = __getParam(cont.owner, "factor", 1.0)
    
    for actuator in cont.actuators:
        actuator.owner.alignAxisToVect(rayDirection, axis, factor)
        
#=============
# hitPositionToPosition
#=============
def hitPositionToPosition(cont):
    '''
    Takes the hitPosition parameter of the sensor and 
    sets the position of the actuator owners accordingly.

    Supported sensor types:
    =======================
        - MouseFocus
        - Ray
        
    Supported actuator types:
    =========================
        - any
    
    The actuators will not be activated or changed.    
    @param cont: controller running this function
    '''
    hitPosition = __getValueOfPositive(cont, "hitPosition")
    if hitPosition == None:
        return
    
    for actuator in cont.actuators:
        actuator.owner.worldPosition = hitPosition

#=============
# rayTargetToPosition
#=============
def rayTargetToPosition(cont):
    '''
    Takes the rayTarget parameter of the sensor and 
    sets the position of the actuator owners accordingly.

    Supported sensor types:
    =======================
        - MouseFocus
        
    Supported actuator types:
    =========================
        - any
    
    The actuators will not be activated or changed.    
    @param cont: controller running this function
    '''
    rayTarget = __getValueOf(cont, "rayTarget")
    if rayTarget == None:
        return
    
    for actuator in cont.actuators:
        actuator.owner.worldPosition = rayTarget

#=============
# raySourceToPosition
#=============
def raySourceToPosition(cont):
    '''
    Takes the raySource parameter of the sensor and 
    sets the position of the actuator owners accordingly.

    Supported sensor types:
    =======================
        - MouseFocus
        
    Supported actuator types:
    =========================
        - any
    
    The actuators will not be activated or changed.    
    @param cont: controller running this function
    '''
    raySource = __getValueOf(cont, "raySource")
    if raySource == None:
        return
    
    for actuator in cont.actuators:
        actuator.owner.worldPosition = raySource

#=============
# firstBodyToValue
#=============
def firstBodyToValue(cont):
    '''
    Puts the values of the first body of the sensor to
    the actuators variables value
    
    Supported sensor types:
    =======================
        - NetworkMessage
        
    Supported actuator types:
    =========================
        - Property
    
    The actuators will be activated. 
    @param cont: controller running this function
    '''
    bodies = __getValueOf(cont, "bodies")
    if bodies == None:
        return
    
    __setValueTo(cont, "value", bodies[0])

I hope it helps
Monster

This is a brilliant example of how to extend logic bricks using python. The getValueOf() function really improves usability, great job.

Yes, very nice, thank you Monster!!!
And a good example too, to demonstrate that instead of trying to transform the GE in something “pretentious” , it would be better to add more options to the existing Logic Bricks!
Bye

Thanks everyone :)!

I updated S2A to version 1.1.

New feature:
Have you ever wondered why the NetworkMessageActuator let you store a property in the message body but the NetworkMessageSensor can’t retrieve it?

The brand new firstBodyToValue let you extract the body content to a property. Just connect a property actuator and set the “Prop:” field. “Assign” mode or “Add” mode both work very well. See the demo blend for a test.

But be carefull: It only takes the value of the first body of the sensors queue. Any further bodies are ignored!

Documentation:
It now supports epydoc. This makes the script somehow larger but provides a more detailed documentation. I added the epydoc output as html to the top post. Please look there for instructions how to extract it.

Have fun
Monster

The “Demo” file is still the 1.0 version…?!

Hi OTO,
you are right… I thought I uploaded the 1.1 demo file but it is still 1.0 :frowning:

I will fix that, when I’m on the PC with the right file.

Thanks for the info

Hi monster,

if you want to create a PDF file open the html file, click print and select the printer named “Adobe PDF”, after clicking print you will be prompted for a save location, and then the html will be saved as a PDF. If you don’t have a printer called Adobe PDF, try downloading and installing the latest adobe reader, that might work.

This is a good idea.
My thoughts were more in the direction using epydocs directly, but this requires LaTex. The PDF-Print should be fine.

Thanks

Updated the demo file to 1.1 at the top post.
:slight_smile:

Great Job Monster!
This is really great!!!

If you don’t have anywhere to host your docs, I could always do it. :wink:

They are very impressive! :smiley:

EDIT: Hey Monster. Check it out here: docs.sunjay-varma.com/s2a

Hey Sunjay03,

that’s really cool :), thanks for that. Just going to add the link to the top post.

:yes:
Monster

Cool. This looks like it could be very useful.

Thanks Monster.

Hey monster,
I’m really newb at this, but how can I copy the module S2A.closestHitObjectToObject from your file into mine? Is it already in the .py script or something cause It won’t work in my file.
Thanks :wink:

*edit
Already found what I was doing wrong sorry. :wink:

you need some of the other function from the file :).

If you just want to use it as snippet, fill the variable hitObjectList with sensor.hitObjectList.
closestObject contains the reference to the final object.

New version 1.3 now.

The new member function allows to apply a property value to an item of an actuator.

For example you have a property “x” and you want to set it’s value in a motion actuator vor the X position.

You need:
a property sensor (recommended: change mode True Pulse) with a name e.g.“Xchanged”
a Python controller MODULE mode: S2A.transfer
a motion actuator with a special name

Configuration
by actuators name

        &lt;attribute&gt;[&lt;index&gt;]=&lt;sensorName&gt;.&lt;attribute&gt;[&lt;index&gt;]    

special format for property sensors:
<attribute>[<index>]=<sensorName>

attribute = attribute found in the BGE API for the sensor/actuator
Exceptions:
Loc is translated to dLoc
Rot is translated to dRot

This is to match the visible labels at the motion actuator logic brick.
Attention:
This function does not activate the actuator. It just sets the configuration.
The actuator must be activated/deactivated by other controllers.

Example:
e.g. Loc[1]=Xchanged
this means dLoc with index 0 gets the value of the property setup in sensor Xchanged

which is equal to the python code


value = cont.sensors["Xchanged"]
dLoc = cont.actuator["Loc[1]=Xchanged"].dLoc
dLoc[1] = value
cont.actuator["Loc[1]=Xchanged"].dLoc = dloc

Attachments

S2A.blend (64.4 KB)

Fixed the firstBodyToValue.
The value from body is now surrounded by " to let it be interpreted as string. Otherwise the property actuator thinks it is a property name.

Sending numbers via message still works as before.

Attachments

S2A.blend (61.7 KB)

Added

  • S2A.hitObjectListToBoolean - to mark/unmark hit objects


(example with near sensor)

triggered by

  • near
  • radar
  • collision
  • touch

Attachments

S2A.blend (71.3 KB)

New Version 1.8.

  • Bugfix: removed incompatibility to 3.0

Attachments

S2A.blend (72 KB)

It seems some user have problems to use the S2A.
So I created this mini tutorial (BGE 2.60):

Sender:



Please note the True Pulse on the Property Change Sensor. It is needed to send another message when the property changes within the next frame. Otherwise it would send a message after the next break.

I do not recommend the usage of an always (True Pulse) sensor. This forces the message actuator to constantly send messages around.
An special case is when the property changes at (nearly) every frame. In this case an always sensor is more efficient than a property sensor. But ONLY in this case!

To change the property apply an logic you want. This is an example:


Recipient:



Please note the True Pulse on the Message Sensor. It is needed to process the message received within the next frame. Otherwise it process them do that.

Monster