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.
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 < 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])
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
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.
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.
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
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.
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
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
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.
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:
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.