Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'release/scripts/textplugin_convert_ge.py')
-rw-r--r--release/scripts/textplugin_convert_ge.py863
1 files changed, 863 insertions, 0 deletions
diff --git a/release/scripts/textplugin_convert_ge.py b/release/scripts/textplugin_convert_ge.py
new file mode 100644
index 00000000000..f3b44cdb14b
--- /dev/null
+++ b/release/scripts/textplugin_convert_ge.py
@@ -0,0 +1,863 @@
+#!BPY
+"""
+Name: 'Convert BGE 2.49'
+Blender: 246
+Group: 'TextPlugin'
+Shortcut: ''
+Tooltip: 'Attemps to update deprecated usage of game engine API.'
+"""
+
+#
+# Copyright 2009 Alex Fraser <alex@phatcore.com>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+#
+# This script updates game engine scripts that were designed for pre-2.49
+# versions of Blender to run with the new API. Deprecated function calls are
+# listed in attributeRenameDict. This script searches for instances of the keys
+# in a target script and re-writes them.
+#
+# Some deprecated functions are complicated to re-write. The most common
+# conversions have been implemented, but some have not. Running this will reduce
+# the number of deprecation warnings in your scripts, but may not eliminate them
+# entirely.
+#
+# NOTE: The conversion is not guaranteed to be perfect. It is strongly
+# recommended that you review all changes after running this script.
+#
+# TODO: The following attributes are either ambiguous or need special processing
+# to handle parameters. Deprecated attributes that map to multiple target
+# attributes will require a refactor of the main conversion loop in the
+# convert248to249 function: currently, it doesn't allow any conversion to
+# advance the row index by more than one.
+#
+# getLinearVelocity (KX_SCA_AddObjectActuator, KX_ObjectActuator)
+# Conflicts with KX_GameObject.
+# Maps to multiple attributes.
+# setLinearVelocity (KX_SCA_AddObjectActuator, KX_ObjectActuator)
+# Conflicts with KX_GameObject.
+# Maps to multiple attributes.
+# getAngularVelocity (KX_SCA_AddObjectActuator, KX_ObjectActuator)
+# Conflicts with KX_GameObject.
+# Maps to multiple attributes.
+# setAngularVelocity (KX_SCA_AddObjectActuator, KX_ObjectActuator)
+# Conflicts with KX_GameObject.
+# Maps to multiple attributes.
+# setAction (BL_ShapeActionActuator, BL_ActionActuator)
+# `reset' argument has no conversion target.
+# set (KX_VisibilityActuator, KX_IpoActuator)
+# Different numbers of arguments.
+# Arguments map to multiple attributes.
+# getIndex (SCA_JoystickSensor)
+# Incompatible values: Old = 1-based index; new = 0-based.
+# getMesh (KX_SCA_ReplaceMeshActuator)
+# Return types differ. Need to call object.name.
+# getObject (KX_SCA_AddObjectActuator, KX_CameraActuator,
+# KX_TrackToActuator, KX_ParentActuator)
+# Default return type differs between classes.
+# setIndex (SCA_JoystickSensor)
+# Incompatible values: Old = 1-based index; new = 0-based.
+# setObject (KX_SCA_AddObjectActuator, KX_CameraActuator,
+# KX_TrackToActuator, KX_ParentActuator)
+# Incompatible types: Old = KX_GameObject or String; new =
+# KX_GameObject.
+# setOperation (KX_SCA_DynamicActuator, KX_StateActuator)
+# Ambiguous: different target names.
+# getDRot (KX_ObjectActuator)
+# Maps to multiple attributes.
+# setDRot (KX_ObjectActuator)
+# Arguments map to multiple attributes.
+# getDLoc (KX_ObjectActuator)
+# Maps to multiple attributes.
+# setDLoc (KX_ObjectActuator)
+# Arguments map to multiple attributes.
+# getTorque (KX_ObjectActuator)
+# Maps to multiple attributes.
+# setTorque (KX_ObjectActuator)
+# Arguments map to multiple attributes.
+# getForce (KX_ObjectActuator)
+# Maps to multiple attributes.
+# setForce (KX_ObjectActuator)
+# Arguments map to multiple attributes.
+# position (KX_GameObject)
+# Conflicts with KX_SoundActuator.
+# orientation (KX_GameObject)
+# Conflicts with KX_SoundActuator.
+#
+
+import string
+import re
+
+COMMENTCHAR = '#'
+
+class ParseError(Exception): pass
+class ConversionError(Exception): pass
+
+def findBalancedParens(lines, row, col, openChar = '(', closeChar = ')'):
+ """Finds a balanced pair of parentheses, searching from lines[row][col].
+ The opening parenthesis must be on the starting line.
+
+ Returns two tuples containing the row and column of the opening paren, and
+ the row and column of the matching paren.
+
+ Throws a ParseError if the first character is not openChar, or if a matching
+ paren cannot be found."""
+
+ #
+ # Find the opening coordinates.
+ #
+ oRow = row
+ oCol = col
+ line = lines[oRow]
+ while oCol < len(line):
+ if line[oCol] == openChar:
+ break
+ elif line[oCol] == COMMENTCHAR:
+ break
+ oCol = oCol + 1
+
+ if oCol >= len(line) or line[oCol] != openChar or not re.match(r'^\s*$', line[col:oCol]):
+ raise ParseError, "Can't find opening parenthesis. '%s'" % openChar
+
+ #
+ # Find the closing coordinates.
+ #
+ eRow = oRow
+ eCol = oCol + 1
+ level = 1
+ while eRow < len(lines) and level > 0:
+ line = lines[eRow]
+ while eCol < len(line) and level > 0:
+ c = line[eCol]
+ if c == openChar:
+ # Found a nested paren.
+ level = level + 1
+ elif c == closeChar:
+ # Exiting one level of nesting.
+ level = level - 1
+ if level == 0:
+ # Back to top level!
+ return (oRow, oCol), (eRow, eCol)
+ elif c == COMMENTCHAR:
+ # Comment. Skip the rest of the line.
+ break
+ eCol = eCol + 1
+ eRow = eRow + 1
+ eCol = 0
+ raise ParseError, "Couldn't find closing parenthesis."
+
+def findLastAssignment(lines, row, attrName):
+ """Finds the most recent assignment of `attrName' before `row'. Returns
+ everything after the '=' sign or None, if there was no match."""
+ contRegex = re.compile(r'[^#]*?' + # Don't search in comments.
+ attrName +
+ r'\s*=\s*(.*)') # Assignment
+
+ cRow = row - 1
+ while cRow >= 0:
+ match = contRegex.search(lines[cRow])
+ if match:
+ return match.group(1)
+ cRow = cRow - 1
+ return None
+
+def replaceSubstr(s, start, end, newSubStr):
+ """Replace the contents of `s' between `start' and `end' with
+ `newSubStr'."""
+ return s[:start] + newSubStr + s[end:]
+
+def replaceNextParens(lines, row, colStart, newOpenChar, newCloseChar,
+ oldOpenChar = '(', oldCloseChar = ')'):
+ """Replace the next set of parentheses with different characters. The
+ opening parenthesis must be located on line `row', and on or after
+ `colStart'. The closing parenthesis may be on the same line or any following
+ line. The strings are edited in-place.
+
+ Throws a ParseError if the set of parentheses can't be found. In this case,
+ the strings in `lines' will be untouched."""
+ try:
+ pOpen, pClose = findBalancedParens(lines, row, colStart, oldOpenChar,
+ oldCloseChar)
+ except ParseError:
+ raise
+
+ # Replacement may change string length. Replace closing paren first.
+ r, c = pClose
+ lines[r] = replaceSubstr(lines[r], c, c + 1, newCloseChar)
+ # Replace opening paren.
+ r, c = pOpen
+ lines[r] = replaceSubstr(lines[r], c, c + 1, newOpenChar)
+
+def replaceSimpleGetter(lines, row, colStart, colEnd, newName):
+ """Replace a call to a simple getter function with a reference to a
+ property, e.g. foo.getBar() -> foo.bar
+
+ The function identifier being replaced must be on line `row' and
+ between `colStart' and `colEnd'. The opening parenthesis must follow
+ immediately (whitespace is allowed). The closing parenthesis may be on the
+ same or following lines.
+
+ Throws a ConversionError if the parentheses can't be found. In this case
+ the content of `lines' will be untouched."""
+ try:
+ replaceNextParens(lines, row, colEnd, newOpenChar = '', newCloseChar = '')
+ except ParseError:
+ raise ConversionError, ("Deprecated function reference.")
+
+ lines[row] = replaceSubstr(lines[row], colStart, colEnd, newName)
+
+def replaceSimpleSetter(lines, row, colStart, colEnd, newName):
+ """Replace a call to a simple setter function with a reference to a
+ property, e.g. foo.setBar(baz) -> foo.bar = baz
+
+ The function identifier being replaced must be on line `row' and
+ between `colStart' and `colEnd'. The opening parenthesis must follow
+ immediately (whitespace is allowed). The closing parenthesis may be on the
+ same or following lines.
+
+ Throws a ConversionError if the parentheses can't be found. In this case
+ the content of `lines' will be untouched."""
+ try:
+ replaceNextParens(lines, row, colEnd, newOpenChar = '', newCloseChar = '')
+ except ParseError:
+ raise ConversionError, ("Deprecated function reference.")
+
+ lines[row] = replaceSubstr(lines[row], colStart, colEnd, newName + ' = ')
+
+def replaceArgsWithListSetter(lines, row, colStart, colEnd, newName):
+ """Replace a call to a multi-agument setter function with a reference to a
+ list property, e.g. foo.setBar(baz, bazZ) -> foo.bar = [baz, bazZ]
+
+ The function identifier being replaced must be on line `row' and
+ between `colStart' and `colEnd'. The opening parenthesis must follow
+ immediately (whitespace is allowed). The closing parenthesis may be on the
+ same or following lines.
+
+ Throws a ConversionError if the parentheses can't be found. In this case
+ the content of `lines' will be untouched."""
+ try:
+ replaceNextParens(lines, row, colEnd, newOpenChar = '[', newCloseChar = ']')
+ except ParseError:
+ raise ConversionError, ("Deprecated function reference.")
+
+ lines[row] = replaceSubstr(lines[row], colStart, colEnd, newName + ' = ')
+
+
+def replaceKeyedGetter(lines, row, colStart, colEnd, newName):
+ """Replace a call to a keyed getter function with a reference to a
+ property, e.g. foo.getBar(baz) -> foo.bar[baz]
+
+ The function identifier being replaced must be on line `row' and
+ between `colStart' and `colEnd'. The opening parenthesis must follow
+ immediately (whitespace is allowed). The closing parenthesis may be on the
+ same or following lines.
+
+ Throws a ConversionError if the parentheses can't be found. In this case
+ the content of `lines' will be untouched."""
+ try:
+ replaceNextParens(lines, row, colEnd, newOpenChar = '[', newCloseChar = ']')
+ except ParseError:
+ raise ConversionError, ("Deprecated function reference.")
+
+ lines[row] = replaceSubstr(lines[row], colStart, colEnd, newName)
+
+def replaceGetXYPosition(lines, row, colStart, colEnd, axis):
+ '''SCA_MouseSensor.getXPosition; SCA_MouseSensor.getYPosition.
+ This is like a keyed getter, but the key is embedded in the attribute
+ name.
+
+ Throws a ConversionError if the parentheses can't be found. In this case
+ the content of `lines' will be untouched.'''
+ try:
+ (openRow, openCol), (closeRow, closeCol) = findBalancedParens(lines,
+ row, colEnd)
+ except ParseError:
+ raise ConversionError, "Deprecated function reference."
+ if closeRow != row:
+ raise ConversionError, "Can't modify multiple lines."
+
+ lines[row] = replaceSubstr(lines[row], openCol, closeCol + 1,
+ "[%s]" % axis)
+
+ lines[row] = replaceSubstr(lines[row], colStart, colEnd, 'position')
+
+def replaceRename(lines, row, colStart, colEnd, newName):
+ """Replace an identifier with another, e.g.
+ foo.getBar() -> foo.getBaz()
+ foo.bar -> foo.baz
+
+ The identifier being replaced must be on line `row' and between `colStart'
+ and `colEnd'."""
+ lines[row] = replaceSubstr(lines[row], colStart, colEnd, newName)
+
+def replaceAddActiveActuator(lines, row, colStart, colEnd, closure):
+ '''Extra work needs to be done here to find out the name of the controller,
+ and whether the actuator should be activated or deactivated.
+
+ Throws a ConversionError if the actuator, controller or condition can't be
+ found. In this case the content of `lines' will be untouched.'''
+ try:
+ (openRow, openCol), (closeRow, closeCol) = findBalancedParens(lines, row, colEnd)
+ except ParseError:
+ ConversionError, "Can't find arguments."
+
+ if closeRow != openRow:
+ raise ConversionError, ("Can't perform conversion: arguments span multiple lines.")
+
+ args = lines[row][openCol + 1:closeCol]
+ match = re.search(r'([a-zA-Z_]\w*)' # Actuator identifier
+ r',\s*'
+ r'([0-9a-zA-Z_]\w*)', # Condition (boolean)
+ args)
+ if not match:
+ raise ConversionError, "Can't find arguments."
+
+ actuator = match.group(1)
+ condition = match.group(2)
+ controller = None
+
+ assn = findLastAssignment(lines, row, actuator)
+ if assn:
+ match = re.search(r'([a-zA-Z_]\w*)' # Controller identifier
+ r'\s*\.\s*' # Dot
+ r'(actuators\s*\[|getActuator\s*\()', # Dictionary/getter identifier
+ assn)
+ if match:
+ controller = match.group(1)
+
+ if not controller:
+ raise ConversionError, "Can't find actuator's controller."
+
+ gameLogicStart = lines[row].rfind("GameLogic", 0, colStart)
+ if gameLogicStart < 0:
+ raise ConversionError, "Can't find GameLogic identifier."
+
+ newExpr = None
+ if condition in ['1', 'True']:
+ newExpr = "%s.activate(%s)" % (controller, actuator)
+ elif condition in ['0', 'False']:
+ newExpr = "%s.deactivate(%s)" % (controller, actuator)
+ else:
+ newExpr = "(lambda: %s and (%s.activate(%s) or True) or %s.deactivate(%s))()" % (
+ condition, controller, actuator, controller, actuator)
+ lines[row] = replaceSubstr(lines[row], gameLogicStart, closeCol + 1, newExpr)
+
+def getObject(line, attributeStart):
+ '''Get the object that an attribute belongs to. `attributeStart' is the
+ index of the first character of the attribute name in the string `line'.
+ Returns: the identifier preceding `attributeStart', or None if one can't be
+ found.'''
+ match = re.search(r'([a-zA-Z_]\w*)\s*\.\s*$', line[0:attributeStart])
+ if not match:
+ return None
+ return match.group(1)
+
+def replaceGetActuator(lines, row, colStart, colEnd, closure):
+ '''getActuator is ambiguous: it could belong to SCA_IController or
+ SCA_ActuatorSensor. Try to resolve and then convert.
+
+ Raises a ConversionError if the parentheses can't be found, or if the
+ ambiguity can't be resolved.'''
+ # Get the name of the object this attribute is attached to.
+ obName = getObject(lines[row], colStart)
+ if obName:
+ # Try to find out whether the object is a controller.
+ assn = findLastAssignment(lines, row, obName)
+ if assn and re.search(r'GameLogic\s*\.\s*getCurrentController', assn):
+ # It is (probably) a controller!
+ replaceKeyedGetter(lines, row, colStart, colEnd, 'actuators')
+ return
+
+ raise ConversionError, "Ambiguous: addActiveActuator -> actuators[key] (SCA_IController) or actuator (SCA_ActuatorSensor)."
+
+def replaceSetOrientation(lines, row, colStart, colEnd, closure):
+ '''setOrientation is ambiguous: it could belong to KX_SoundActuator or
+ KX_GameObject. Try to resolve and then convert. If the type can't be
+ determined, it is assumed to be a KX_GameObject. Currently, only the
+ conversion for KX_GameObject is implemented.
+
+ Raises a ConversionError if the parentheses can't be found, or if the
+ object is found to be a KX_SoundActuator.'''
+ # Get the name of the object this attribute is attached to.
+ obName = getObject(lines[row], colStart)
+ if obName:
+ # Try to find out whether the object is an actuator.
+ assn = findLastAssignment(lines, row, obName)
+ if assn:
+ match = re.search(r'([a-zA-Z_]\w*)' # Controller identifier
+ r'\s*\.\s*' # Dot
+ r'(actuators\s*\[|getActuator\s*\()', # Dictionary/getter identifier
+ assn)
+ if match:
+ # It's probably a KX_SoundActuator.
+ raise ConversionError, "Not implemented: Can't convert arguments to matrix."
+
+ # It's probably a KX_GameObject.
+ replaceSimpleSetter(lines, row, colStart, colEnd, 'localOrientation')
+
+def replaceSetPosition(lines, row, colStart, colEnd, closure):
+ '''setPosition is ambiguous: it could belong to KX_SoundActuator or
+ KX_GameObject. Try to resolve and then convert. If the type can't be
+ determined, it is assumed to be a KX_GameObject.
+
+ Raises a ConversionError if the parentheses can't be found.'''
+ # Get the name of the object this attribute is attached to.
+ obName = getObject(lines[row], colStart)
+ if obName:
+ # Try to find out whether the object is an actuator.
+ assn = findLastAssignment(lines, row, obName)
+ if assn:
+ match = re.search(r'([a-zA-Z_]\w*)' # Controller identifier
+ r'\s*\.\s*' # Dot
+ r'(actuators\s*\[|getActuator\s*\()', # Dictionary/getter identifier
+ assn)
+ if match:
+ # It's probably a KX_SoundActuator.
+ replaceSimpleSetter(lines, row, colStart, colEnd, 'position')
+
+ # It's probably a KX_GameObject.
+ replaceSimpleSetter(lines, row, colStart, colEnd, 'localPosition')
+
+def replaceSplitProperty(lines, row, colStart, colEnd, (newGetter, newSetter)):
+ '''Some property attributes behave differently when being written to or read
+ from. Try to determine the operation, and replace accordingly. E.G.
+ o.position = foo -> o.localPosition = foo # set
+ foo = o.position -> foo = o.worldPosition # get
+
+ This implementation can not handle cases where the object is returned from
+ a function, e.g.
+ foo = bar.getObject().position # Error!
+
+ Raises a ConversionError if the operation can't be determined, or if the
+ object is returned from a function.'''
+ assnRegex = re.compile(r'(=\s*)?' # Getter
+ r'[a-zA-Z_]\w*' # Object identifier
+ r'\.([a-zA-Z_][a-zA-Z0-9_.]*)+' # Trailing attributes
+ r'(\s*=)?') # Setter
+ match = assnRegex.search(lines[row])
+
+ if not match:
+ raise ConversionError, "Can't determine operation (getting or setting)."
+
+ setting = False
+ getting = False
+ if match.group(1):
+ getting = True
+ if match.group(3):
+ setting = True
+ if (getting and setting) or ((not getting) and (not setting)):
+ raise ConversionError, "Can't determine operation (getting or setting)."
+
+ if getting:
+ replaceRename(lines, row, colStart, colEnd, newGetter)
+ else:
+ replaceRename(lines, row, colStart, colEnd, newSetter)
+
+def notImplemented(lines, row, colStart, colEnd, classNames):
+ message = "Conversion not implemented. See documentation for " +\
+ string.join(classNames, ', ')
+ raise ConversionError, message
+
+#
+# Deprecated attribute information. The format is:
+# deprecatedAttributeName: (conversionFunction, closure)
+# Usually the closure will be the name of the superceding attribute.
+#
+# Since each deprecated attribute can appear in this dictionary only once, it is
+# the conversion function's responsibility to resolve ambiguity.
+#
+attributeRenameDict = {
+ # Special cases
+ 'addActiveActuator': (replaceAddActiveActuator, None), #
+ 'getActuator': (replaceGetActuator, None), # SCA_IController, SCA_ActuatorSensor
+ 'getXPosition': (replaceGetXYPosition, '0'), # SCA_MouseSensor
+ 'getYPosition': (replaceGetXYPosition, '1'), # SCA_MouseSensor
+ 'setOrientation': (replaceSetOrientation, None), # KX_GameObject, KX_SoundActuator
+ 'setPosition': (replaceSetPosition, None), # KX_GameObject, KX_SoundActuator
+
+ # Keyed getters/setters
+ 'getSensor': (replaceKeyedGetter, 'sensors'), # SCA_IController
+
+ # Multi-arg -> List setter
+ 'setAxis': (replaceArgsWithListSetter, 'axis'), # SCA_JoystickSensor
+ 'setForceLimitX': (replaceArgsWithListSetter, 'forceLimitX'), # KX_ObjectActuator
+ 'setForceLimitY': (replaceArgsWithListSetter, 'forceLimitY'), # KX_ObjectActuator
+ 'setForceLimitZ': (replaceArgsWithListSetter, 'forceLimitZ'), # KX_ObjectActuator
+ 'setHat': (replaceArgsWithListSetter, 'hat'), # SCA_JoystickSensor
+ 'setPID': (replaceArgsWithListSetter, 'pid'), # KX_ObjectActuator
+ 'setVelocity': (replaceArgsWithListSetter, 'velocity'), # KX_SoundActuator
+
+ # Straight rename
+ 'getButtonValue': (replaceRename, 'getButtonActiveList'), # SCA_JoystickSensor
+
+ # Split properties
+ 'scaling': (replaceSplitProperty, ('worldScaling', 'localScaling')), # KX_GameObject
+
+ # Simple getters/setters
+ 'getSensors': (replaceSimpleGetter, 'sensors'), # SCA_IController
+ 'getActuators': (replaceSimpleGetter, 'actuators'), # SCA_IController
+ 'enableViewport': (replaceSimpleSetter, 'useViewport'), # KX_Camera
+ 'getAction': (replaceSimpleGetter, 'action'), # BL_ShapeActionActuator, BL_ActionActuator
+ 'getAxis': (replaceSimpleGetter, 'axis'), # SCA_JoystickSensor
+ 'getAxisValue': (replaceSimpleGetter, 'axisValues'), # SCA_JoystickSensor
+ 'getBlendin': (replaceSimpleGetter, 'blendIn'), # BL_ShapeActionActuator, BL_ActionActuator
+ 'getBodies': (replaceSimpleGetter, 'bodies'), # KX_NetworkMessageSensor
+ 'getButton': (replaceSimpleGetter, 'button'), # SCA_JoystickSensor
+ 'getCamera': (replaceSimpleGetter, 'camera'), # KX_SceneActuator
+ 'getConeOrigin': (replaceSimpleGetter, 'coneOrigin'), # KX_RadarSensor
+ 'getConeTarget': (replaceSimpleGetter, 'coneTarget'), # KX_RadarSensor
+ 'getContinue': (replaceSimpleGetter, 'useContinue'), # BL_ActionActuator
+ 'getCurrentlyPressedKeys': (replaceSimpleGetter, 'events'), # SCA_KeyboardSensor
+ 'getDamping': (replaceSimpleGetter, 'damping'), # KX_ObjectActuator
+ 'getDelay': (replaceSimpleGetter, 'delay'), # SCA_DelaySensor
+ 'getDistribution': (replaceSimpleGetter, 'distribution'), # SCA_RandomActuator
+ 'getDuration': (replaceSimpleGetter, 'duration'), # SCA_DelaySensor
+ 'getEnd': (replaceSimpleGetter, 'frameEnd'), # BL_ShapeActionActuator, KX_IpoActuator, BL_ActionActuator
+ 'getExecutePriority': (replaceSimpleGetter, 'executePriority'), # SCA_ILogicBrick
+ 'getFile': (replaceSimpleGetter, 'fileName'), # KX_GameActuator
+ 'getFilename': (replaceSimpleGetter, 'fileName'), # KX_SoundActuator
+ 'getForceIpoActsLocal': (replaceSimpleGetter, 'useIpoLocal'), # KX_IpoActuator
+ 'getForceLimitX': (replaceSimpleGetter, 'forceLimitX'), # KX_ObjectActuator
+ 'getForceLimitY': (replaceSimpleGetter, 'forceLimitY'), # KX_ObjectActuator
+ 'getForceLimitZ': (replaceSimpleGetter, 'forceLimitZ'), # KX_ObjectActuator
+ 'getFrame': (replaceSimpleGetter, 'frame'), # BL_ShapeActionActuator, BL_ActionActuator
+ 'getFrameMessageCount': (replaceSimpleGetter, 'frameMessageCount'), # KX_NetworkMessageSensor
+ 'getFrameProperty': (replaceSimpleGetter, 'framePropName'), # BL_ShapeActionActuator, BL_ActionActuator
+ 'getFrequency': (replaceSimpleGetter, 'frequency'), # SCA_ISensor
+ 'getGain': (replaceSimpleGetter, 'volume'), # KX_SoundActuator, KX_CDActuator
+ 'getHat': (replaceSimpleGetter, 'hat'), # SCA_JoystickSensor
+ 'getHeight': (replaceSimpleGetter, 'height'), # KX_CameraActuator
+ 'getHitNormal': (replaceSimpleGetter, 'hitNormal'), # KX_MouseFocusSensor, KX_RaySensor
+ 'getHitObject': (replaceSimpleGetter, 'hitObject'), # KX_MouseFocusSensor, KX_RaySensor, KX_TouchSensor
+ 'getHitObjectList': (replaceSimpleGetter, 'hitObjectList'), # KX_TouchSensor
+ 'getHitPosition': (replaceSimpleGetter, 'hitPosition'), # KX_MouseFocusSensor, KX_RaySensor
+ 'getHold1': (replaceSimpleGetter, 'hold1'), # SCA_KeyboardSensor
+ 'getHold2': (replaceSimpleGetter, 'hold2'), # SCA_KeyboardSensor
+ 'getInvert': (replaceSimpleGetter, 'invert'), # SCA_ISensor
+ 'getIpoAdd': (replaceSimpleGetter, 'useIpoAdd'), # KX_IpoActuator
+ 'getIpoAsForce': (replaceSimpleGetter, 'useIpoAsForce'), # KX_IpoActuator
+ 'getKey': (replaceSimpleGetter, 'key'), # SCA_KeyboardSensor
+ 'getLastCreatedObject': (replaceSimpleGetter, 'objectLastCreated'), # KX_SCA_AddObjectActuator
+ 'getLevel': (replaceSimpleGetter, 'level'), # SCA_ISensor
+ 'getLightList': (replaceSimpleGetter, 'lights'), # KX_Scene
+ 'getLooping': (replaceSimpleGetter, 'looping'), # KX_SoundActuator
+ 'getMass': (replaceSimpleGetter, 'mass'), # KX_GameObject
+ 'getMax': (replaceSimpleGetter, 'max'), # KX_CameraActuator
+ 'getMin': (replaceSimpleGetter, 'min'), # KX_CameraActuator
+ 'getName': (replaceSimpleGetter, 'name'), # KX_Scene
+ 'getNumAxes': (replaceSimpleGetter, 'numAxis'), # SCA_JoystickSensor
+ 'getNumButtons': (replaceSimpleGetter, 'numButtons'), # SCA_JoystickSensor
+ 'getNumHats': (replaceSimpleGetter, 'numHats'), # SCA_JoystickSensor
+ 'getObjectList': (replaceSimpleGetter, 'objects'), # KX_Scene
+ 'getOperation': (replaceSimpleGetter, 'mode'), # KX_SCA_DynamicActuator
+ 'getOrientation': (replaceSimpleGetter, 'worldOrientation'), # KX_GameObject
+ 'getOwner': (replaceSimpleGetter, 'owner'), # SCA_ILogicBrick
+ 'getPara1': (replaceSimpleGetter, 'para1'), # SCA_RandomActuator
+ 'getPara2': (replaceSimpleGetter, 'para2'), # SCA_RandomActuator
+ 'getParent': (replaceSimpleGetter, 'parent'), # KX_GameObject
+ 'getPID': (replaceSimpleGetter, 'pid'), # KX_ObjectActuator
+ 'getPitch': (replaceSimpleGetter, 'pitch'), # KX_SoundActuator
+ 'getPosition': (replaceSimpleGetter, 'worldPosition'), # KX_GameObject
+ 'getPressedKeys': (replaceSimpleGetter, 'events'), # SCA_KeyboardSensor
+ 'getPriority': (replaceSimpleGetter, 'priority'), # BL_ShapeActionActuator, BL_ActionActuator
+ 'getProjectionMatrix': (replaceSimpleGetter, 'projection_matrix'), # KX_Camera
+ 'getProperty': (replaceSimpleGetter, 'propName'), # SCA_PropertySensor, SCA_RandomActuator, SCA_PropertyActuator
+ 'getRayDirection': (replaceSimpleGetter, 'rayDirection'), # KX_MouseFocusSensor, KX_RaySensor
+ 'getRaySource': (replaceSimpleGetter, 'raySource'), # KX_MouseFocusSensor
+ 'getRayTarget': (replaceSimpleGetter, 'rayTarget'), # KX_MouseFocusSensor
+ 'getRepeat': (replaceSimpleGetter, 'repeat'), # SCA_DelaySensor
+ 'getRollOffFactor': (replaceSimpleGetter, 'rollOffFactor'), # KX_SoundActuator
+ 'getScene': (replaceSimpleGetter, 'scene'), # KX_SceneActuator
+ 'getScript': (replaceSimpleGetter, 'script'), # SCA_PythonController
+ 'getSeed': (replaceSimpleGetter, 'seed'), # SCA_RandomActuator
+ 'getStart': (replaceSimpleGetter, 'frameStart'), # BL_ShapeActionActuator, KX_IpoActuator, BL_ActionActuator
+ 'getState': (replaceSimpleGetter, 'state'), # SCA_IController, KX_GameObject
+ 'getSubject': (replaceSimpleGetter, 'subject'), # KX_NetworkMessageSensor
+ 'getSubjects': (replaceSimpleGetter, 'subjects'), # KX_NetworkMessageSensor
+ 'getThreshold': (replaceSimpleGetter, 'threshold'), # SCA_JoystickSensor
+ 'getTime': (replaceSimpleGetter, 'time'), # KX_SCA_AddObjectActuator, KX_TrackToActuator
+ 'getTouchMaterial': (replaceSimpleGetter, 'useMaterial'), # KX_TouchSensor
+ 'getType': (replaceSimpleGetter, 'mode'), # SCA_PropertySensor
+ 'getUse3D': (replaceSimpleGetter, 'use3D'), # KX_TrackToActuator
+ 'getUseNegPulseMode': (replaceSimpleGetter, 'useNegPulseMode'), # SCA_ISensor
+ 'getUsePosPulseMode': (replaceSimpleGetter, 'usePosPulseMode'), # SCA_ISensor
+ 'getUseRestart': (replaceSimpleGetter, 'useRestart'), # KX_SceneActuator
+ 'getValue': (replaceSimpleGetter, 'value'), # SCA_PropertySensor, SCA_PropertyActuator
+ 'getVisible': (replaceSimpleGetter, 'visible'), # KX_GameObject
+ 'getXY': (replaceSimpleGetter, 'useXY'), # KX_CameraActuator
+ 'isConnected': (replaceSimpleGetter, 'connected'), # SCA_JoystickSensor
+ 'isPositive': (replaceSimpleGetter, 'positive'), # SCA_ISensor
+ 'isTriggered': (replaceSimpleGetter, 'triggered'), # SCA_ISensor
+ 'setActuator': (replaceSimpleSetter, 'actuator'), # SCA_ActuatorSensor
+ 'setBlendin': (replaceSimpleSetter, 'blendIn'), # BL_ShapeActionActuator, BL_ActionActuator
+ 'setBlendtime': (replaceSimpleSetter, 'blendTime'), # BL_ShapeActionActuator, BL_ActionActuator
+ 'setBodyType': (replaceSimpleSetter, 'usePropBody'), # KX_NetworkMessageActuator
+ 'setBody': (replaceSimpleSetter, 'body'), # KX_NetworkMessageActuator
+ 'setButton': (replaceSimpleSetter, 'button'), # SCA_JoystickSensor
+ 'setCamera': (replaceSimpleSetter, 'camera'), # KX_SceneActuator
+ 'setContinue': (replaceSimpleSetter, 'useContinue'), # BL_ActionActuator
+ 'setDamping': (replaceSimpleSetter, 'damping'), # KX_ObjectActuator
+ 'setDelay': (replaceSimpleSetter, 'delay'), # SCA_DelaySensor
+ 'setDuration': (replaceSimpleSetter, 'duration'), # SCA_DelaySensor
+ 'setEnd': (replaceSimpleSetter, 'frameEnd'), # BL_ShapeActionActuator, KX_IpoActuator, BL_ActionActuator
+ 'setExecutePriority': (replaceSimpleSetter, 'executePriority'), # SCA_ILogicBrick
+ 'setFile': (replaceSimpleSetter, 'fileName'), # KX_GameActuator
+ 'setFilename': (replaceSimpleSetter, 'fileName'), # KX_SoundActuator
+ 'setForceIpoActsLocal': (replaceSimpleSetter, 'useIpoLocal'), # KX_IpoActuator
+ 'setFrame': (replaceSimpleSetter, 'frame'), # BL_ShapeActionActuator, BL_ActionActuator
+ 'setFrameProperty': (replaceSimpleSetter, 'framePropName'), # BL_ShapeActionActuator, BL_ActionActuator
+ 'setFrequency': (replaceSimpleSetter, 'frequency'), # SCA_ISensor
+ 'setGain': (replaceSimpleSetter, 'volume'), # KX_SoundActuator, KX_CDActuator
+ 'setHeight': (replaceSimpleSetter, 'height'), # KX_CameraActuator
+ 'setHold1': (replaceSimpleSetter, 'hold1'), # SCA_KeyboardSensor
+ 'setHold2': (replaceSimpleSetter, 'hold2'), # SCA_KeyboardSensor
+ 'setInvert': (replaceSimpleSetter, 'invert'), # SCA_ISensor
+ 'setIpoAdd': (replaceSimpleSetter, 'useIpoAdd'), # KX_IpoActuator
+ 'setIpoAsForce': (replaceSimpleSetter, 'useIpoAsForce'), # KX_IpoActuator
+ 'setKey': (replaceSimpleSetter, 'key'), # SCA_KeyboardSensor
+ 'setLevel': (replaceSimpleSetter, 'level'), # SCA_ISensor
+ 'setLooping': (replaceSimpleSetter, 'looping'), # KX_SoundActuator
+ 'setMask': (replaceSimpleSetter, 'mask'), # KX_StateActuator
+ 'setMax': (replaceSimpleSetter, 'max'), # KX_CameraActuator
+ 'setMesh': (replaceSimpleSetter, 'mesh'), # KX_SCA_ReplaceMeshActuator
+ 'setMin': (replaceSimpleSetter, 'min'), # KX_CameraActuator
+ 'setPitch': (replaceSimpleSetter, 'pitch'), # KX_SoundActuator
+ 'setPriority': (replaceSimpleSetter, 'priority'), # BL_ShapeActionActuator, BL_ActionActuator
+ 'setProjectionMatrix': (replaceSimpleSetter, 'projection_matrix'), # KX_Camera
+ 'setProperty': (replaceSimpleSetter, 'propName'), # KX_IpoActuator, SCA_PropertySensor, SCA_RandomActuator, SCA_PropertyActuator
+ 'setRepeat': (replaceSimpleSetter, 'repeat'), # SCA_DelaySensor
+ 'setRollOffFactor': (replaceSimpleSetter, 'rollOffFactor'), # KX_SoundActuator
+ 'setScene': (replaceSimpleSetter, 'scene'), # KX_SceneActuator
+ 'setScript': (replaceSimpleSetter, 'script'), # SCA_PythonController
+ 'setSeed': (replaceSimpleSetter, 'seed'), # SCA_RandomActuator
+ 'setStart': (replaceSimpleSetter, 'frameStart'), # BL_ShapeActionActuator, KX_IpoActuator, BL_ActionActuator
+ 'setState': (replaceSimpleSetter, 'state'), # KX_GameObject
+ 'setSubject': (replaceSimpleSetter, 'subject'), # KX_NetworkMessageActuator
+ 'setSubjectFilterText': (replaceSimpleSetter, 'subject'), # KX_NetworkMessageSensor
+ 'setThreshold': (replaceSimpleSetter, 'threshold'), # SCA_JoystickSensor
+ 'setTime': (replaceSimpleSetter, 'time'), # KX_SCA_AddObjectActuator, KX_TrackToActuator
+ 'setToPropName': (replaceSimpleSetter, 'propName'), # KX_NetworkMessageActuator
+ 'setType': (replaceSimpleSetter, 'mode'), # SCA_PropertySensor
+ 'setUse3D': (replaceSimpleSetter, 'use3D'), # KX_TrackToActuator
+ 'setUseNegPulseMode': (replaceSimpleSetter, 'useNegPulseMode'), # SCA_ISensor
+ 'setUsePosPulseMode': (replaceSimpleSetter, 'usePosPulseMode'), # SCA_ISensor
+ 'setUseRestart': (replaceSimpleSetter, 'useRestart'), # KX_SceneActuator
+ 'setValue': (replaceSimpleSetter, 'value'), # SCA_PropertySensor, SCA_PropertyActuator
+ 'setXY': (replaceSimpleSetter, 'useXY'), # KX_CameraActuator
+
+ # Unimplemented!
+ 'getLinearVelocity': (notImplemented, ['KX_SCA_AddObjectActuator', 'KX_GameObject']),
+ 'setLinearVelocity': (notImplemented, ['KX_SCA_AddObjectActuator', 'KX_GameObject']),
+ 'getAngularVelocity': (notImplemented, ['KX_SCA_AddObjectActuator', 'KX_GameObject']),
+ 'setAngularVelocity': (notImplemented, ['KX_SCA_AddObjectActuator', 'KX_GameObject']),
+ 'setAction': (notImplemented, ['BL_ShapeActionActuator', 'BL_ActionActuator']),
+ 'set': (notImplemented, ['KX_VisibilityActuator', 'KX_IpoActuator']),
+ 'getIndex': (notImplemented, ['SCA_JoystickSensor']),
+ 'getMesh': (notImplemented, ['KX_SCA_ReplaceMeshActuator']),
+ 'getObject': (notImplemented, ['KX_SCA_AddObjectActuator', 'KX_CameraActuator', 'KX_TrackToActuator', 'KX_ParentActuator']),
+ 'setIndex': (notImplemented, ['SCA_JoystickSensor']),
+ 'setObject': (notImplemented, ['KX_SCA_AddObjectActuator', 'KX_CameraActuator', 'KX_TrackToActuator', 'KX_ParentActuator']),
+ 'setOperation': (notImplemented, ['KX_SCA_DynamicActuator', 'KX_StateActuator']),
+ 'position': (notImplemented, ['KX_GameObject', 'KX_SoundActuator']),
+ 'orientation': (notImplemented, ['KX_GameObject', 'KX_SoundActuator']),
+ 'getDRot': (notImplemented, ['KX_ObjectActuator']),
+ 'setDRot': (notImplemented, ['KX_ObjectActuator']),
+ 'getDLoc': (notImplemented, ['KX_ObjectActuator']),
+ 'setDLoc': (notImplemented, ['KX_ObjectActuator']),
+ 'getTorque': (notImplemented, ['KX_ObjectActuator']),
+ 'getTorque': (notImplemented, ['KX_ObjectActuator']),
+ 'getForce': (notImplemented, ['KX_ObjectActuator']),
+ 'setForce': (notImplemented, ['KX_ObjectActuator']),
+}
+
+def convert248to249(lines, log = True, logErrors = True, fileName = None):
+ # Regular expression for finding attributes. For the string 'a.b', this
+ # returns three groups: ['a.b', 'a.', 'b']. The last is the attribute name.
+ attrRegex = re.compile(r'\.\s*' # Dot
+ r'([a-zA-Z_]\w*)') # Identifier
+
+ fileIdStr = ""
+ if fileName:
+ fileIdStr = fileName + ": "
+ row = 0
+ col = 0
+ nconverted = 0
+ nerrors = 0
+ while row < len(lines):
+ originalLine = lines[row]
+ changed = False
+ while col < len(lines[row]):
+ # Don't search past comment. We have to check each iteration
+ # because the line contents may have changed.
+ commentStart = lines[row].find('#', col)
+ if commentStart < 0:
+ commentStart = len(lines[row])
+
+ # Search for an attribute identifier.
+ match = attrRegex.search(lines[row], col, commentStart)
+ if not match:
+ break
+
+ attrName = match.group(1)
+ if attributeRenameDict.has_key(attrName):
+ # name is deprecated.
+ func, closure = attributeRenameDict[attrName]
+ try:
+ # Convert!
+ func(lines, row, match.start(1), match.end(1), closure)
+ except ConversionError as e:
+ # Insert a comment saying the conversion failed.
+ print "ERROR: %sline %d, %s: %s\n" % (
+ fileIdStr, row + 1, attrName, e)
+ if logErrors:
+ lines.insert(row,
+ "##248## ERROR: %s: %s\n" %
+ (attrName, e))
+ row = row + 1
+ nerrors = nerrors + 1
+ else:
+ changed = True
+ nconverted = nconverted + 1
+ # Search the rest of this line.
+ col = match.start(1)
+
+ if changed and log:
+ # Insert a comment to showing difference in lines.
+ if originalLine[-1] != '\n':
+ originalLine = originalLine + '\n'
+ lines.insert(row, "##248##%s" % originalLine)
+ row = row + 1
+
+ row = row + 1
+ col = 0
+ return nconverted, nerrors
+
+def usage():
+ print "Usage: blender248to249.py [options] <infile> [outfile]"
+ print "Options:"
+ print "\t--nolog Don't include old lines as comments."
+ print "\t--quieterrors Don't insert errors as comments."
+
+def runAsConsoleScript():
+ '''Called when being run as a console script.'''
+ try:
+ opts, args = getopt.getopt(sys.argv[1:], "", ["nolog", "quieterrors"])
+ except getopt.GetoptError, err:
+ # print help information and exit:
+ print str(err)
+ usage()
+ sys.exit(2)
+
+ log = True
+ logErrors = True
+ for o, a in opts:
+ if o == "--nolog":
+ log = False
+ elif o == "--quieterrors":
+ logErrors = False
+
+ try:
+ inpath = args.pop(0)
+ except IndexError:
+ usage()
+ sys.exit(2)
+ try:
+ outpath = args.pop(0)
+ except IndexError:
+ outpath = inpath
+
+ infile = io.FileIO(inpath, 'r')
+ # arbitrary file size of around 100kB
+ lines = infile.readlines(100000)
+ infile.close()
+
+ nconverted, nerrors = convert248to249(lines, log, logErrors)
+
+ outfile = io.FileIO(outpath, 'w')
+ outfile.writelines(lines)
+ outfile.close()
+ print "Conversion finished. Modified %d attributes." % nconverted
+ print "There were %d errors." % nerrors
+ print "Please review all the changes."
+
+def runAsTextPlugin():
+ '''Called when run as a text plugin.'''
+
+ import Blender
+ from Blender import Window, sys, Draw
+ import BPyTextPlugin, bpy
+
+ message = ("Convert Game Engine script from 4.48 API to 2.49 API%t|"
+ "Run on active script only%x1|"
+ "Run on ALL text buffers%x2")
+ convertAllBuffers = Draw.PupMenu(message) == 2
+
+ Window.WaitCursor(1)
+ try:
+ nconverted = 0
+ nerrors = 0
+
+ if convertAllBuffers:
+ texts = bpy.data.texts
+ else:
+ if not bpy.data.texts.active:
+ Draw.PupMenu("No active buffer.")
+ return
+ texts = [bpy.data.texts.active]
+
+ Blender.SaveUndoState('Convert BGE 2.49')
+
+ for txt in texts:
+ bufName = txt.name
+ if txt.lib:
+ bufName = txt.lib + '/' + bufName
+ lines = txt.asLines()
+ for i in range(0, len(lines)):
+ if not lines[i].endswith('\n'):
+ lines[i] = lines[i] + '\n'
+
+ nc, ne = convert248to249(lines, fileName = bufName)
+ nconverted = nconverted + nc
+ nerrors = nerrors + ne
+ txt.clear()
+ for line in lines:
+ txt.write(line)
+
+ finally:
+ Window.WaitCursor(0)
+
+ message = "Converted %d attributes." % nconverted
+ if nerrors == 1:
+ message = message + " There was 1 error (see console)."
+ if nerrors > 1:
+ message = message + " There were %d errors (see console)." % nerrors
+ message = message + "|Please review all the changes."
+ Draw.PupMenu(message)
+
+def main():
+ try:
+ import Blender
+ except ImportError:
+ runAsConsoleScript()
+ else:
+ runAsTextPlugin()
+
+# This lets you import the script without running it
+if __name__ == "__main__":
+ import sys
+ import getopt
+ import io
+ main()