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:
authorCampbell Barton <ideasman42@gmail.com>2009-05-21 03:31:58 +0400
committerCampbell Barton <ideasman42@gmail.com>2009-05-21 03:31:58 +0400
commit3daa8bd4ef5a52c40b01827b55df3807a1917eea (patch)
tree83f466e54e5d9f093c95ca01765cbe84ba953920 /release
parentfcdb34f593735f977589e925c4c66883603d2bbc (diff)
fix for [#18772] c3d_import script crashes
Patch from Roger Wickes update to 2.48 sFrame, eFrame, fps. [#18794] GE API conversion script: 2.48 -> 2.49 patch from Alex Fraser (z0r), will test further in the next few days. --- This is text plug in and standalone script that updates Blender 2.48 Game Engine scripts to be compatible with the 2.49 API. The script contains a mapping of attribute names to functions that do the conversion. Most of the mappings were extracted from the documentation in GameTypes.py. Where the conversion is ambiguous, the script will not change the source except to insert a warning as a comment. This means that the script does not completely automate the conversion process, but will do a lot of the work. The script still needs a fair bit of testing. Many of the mappings have not been tested and could result in broken scripts. I'm submitting this patch now to start the review process early. I think I might need help if it is to be included in 2.49.
Diffstat (limited to 'release')
-rw-r--r--release/scripts/c3d_import.py7
-rw-r--r--release/scripts/textplugin_convert_ge.py677
2 files changed, 681 insertions, 3 deletions
diff --git a/release/scripts/c3d_import.py b/release/scripts/c3d_import.py
index bfe691c394c..98f643cbab9 100644
--- a/release/scripts/c3d_import.py
+++ b/release/scripts/c3d_import.py
@@ -527,9 +527,10 @@ def setupAnim(StartFrame, EndFrame, VideoFrameRate):
if VideoFrameRate>120: VideoFrameRate=120
# set up anim panel for them
context=scn.getRenderingContext()
- context.startFrame(StartFrame)
- context.endFrame(EndFrame)
- context.framesPerSec(int(VideoFrameRate))
+ context.sFrame=StartFrame
+ context.eFrame=EndFrame
+ context.fps=int(VideoFrameRate)
+
Blender.Set("curframe",StartFrame)
Blender.Redraw()
return
diff --git a/release/scripts/textplugin_convert_ge.py b/release/scripts/textplugin_convert_ge.py
new file mode 100644
index 00000000000..4a472247dcc
--- /dev/null
+++ b/release/scripts/textplugin_convert_ge.py
@@ -0,0 +1,677 @@
+#!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/>.
+#
+
+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 a 4-tuple 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 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()
+
+ 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):
+ 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.
+
+ 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)."
+
+#
+# Deprecated attribute information. The format is:
+# deprecatedAttributeName: {(conversionFunction, closure): classList}
+# Usually the closure will be the name of the superceding attribute.
+#
+# If an attribute maps to more than one function/attribute pair, the conversion
+# is ambiguous and can't be performed.
+#
+attributeRenameDict = {
+ # Special cases
+ 'addActiveActuator': {(replaceAddActiveActuator, None): []},
+ 'getActuator': {(replaceGetActuator, None): ['SCA_IController', 'SCA_ActuatorSensor']},
+ 'getXPosition': {(replaceGetXYPosition, '0'): ['SCA_MouseSensor']},
+ 'getYPosition': {(replaceGetXYPosition, '1'): ['SCA_MouseSensor']},
+
+ # Unimplemented! There are probably more of these below that would cause errors.
+ #'getLinearVelocity': {(replaceSimpleGetter, 'linearVelocity'): ['KX_SCA_AddObjectActuator']},
+ #'setLinearVelocity': {(replaceSimpleSetter, 'linearVelocity'): ['KX_SCA_AddObjectActuator']},
+ #'getAngularVelocity': {(replaceSimpleGetter, 'angularVelocity'): ['KX_SCA_AddObjectActuator']},
+ #'setAngularVelocity': {(replaceSimpleSetter, 'angularVelocity'): ['KX_SCA_AddObjectActuator']},
+
+ # Generic converters
+ 'enableViewport': {(replaceSimpleSetter, 'useViewport'): ['KX_Camera']},
+ 'getAction': {(replaceSimpleGetter, 'action'): ['BL_ShapeActionActuator', 'BL_ActionActuator']},
+ 'getActuators': {(replaceKeyedGetter, 'actuators'): ['SCA_IController']},
+ 'getAxis': {(replaceSimpleGetter, 'axis'): ['SCA_JoystickSensor']},
+ 'getAxisValue': {(replaceSimpleGetter, 'axisSingle'): ['SCA_JoystickSensor']},
+ 'getBlendin': {(replaceSimpleGetter, 'blendIn'): ['BL_ShapeActionActuator',
+ 'BL_ActionActuator']},
+ 'getBodies': {(replaceSimpleGetter, 'bodies'): ['KX_NetworkMessageSensor']},
+ 'getButton': {(replaceSimpleGetter, 'button'): ['SCA_JoystickSensor']},
+ 'getButtonValue': {(replaceRename, 'getButtonActiveList'): ['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']},
+ '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']},
+ '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']},
+ 'getIndex': {(replaceSimpleGetter, 'index'): ['SCA_JoystickSensor']},
+ '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']},
+ 'getMesh': {(replaceSimpleGetter, 'mesh'): ['KX_SCA_ReplaceMeshActuator']},
+ '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']},
+ 'getObject': {(replaceSimpleGetter, 'object'): ['KX_SCA_AddObjectActuator',
+ 'KX_CameraActuator',
+ 'KX_TrackToActuator',
+ 'KX_ParentActuator']},
+ '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']},
+ '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']},
+ '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']},
+ 'getSensor': {(replaceKeyedGetter, 'sensors'): ['SCA_IController']},
+ 'getSensors': {(replaceKeyedGetter, 'sensors'): ['SCA_IController']},
+ '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']},
+ 'set': {(replaceSimpleSetter, 'visibility'): ['KX_VisibilityActuator']},
+ 'setAction': {(replaceSimpleSetter, 'action'): ['BL_ShapeActionActuator', 'BL_ActionActuator']},
+ 'setActuator': {(replaceSimpleSetter, 'actuator'): ['SCA_ActuatorSensor']},
+ 'setAxis': {(replaceSimpleSetter, 'axis'): ['SCA_JoystickSensor']},
+ 'setBlendin': {(replaceSimpleSetter, 'blendIn'): ['BL_ShapeActionActuator',
+ 'BL_ActionActuator']},
+ 'setBlendtime': {(replaceSimpleSetter, 'blendTime'): ['BL_ShapeActionActuator',
+ 'BL_ActionActuator']},
+ 'setBodyType': {(replaceSimpleSetter, 'usePropBody'): ['KX_NetworkMessageActuator']},
+ 'setButton': {(replaceSimpleSetter, 'button'): ['SCA_JoystickSensor']},
+ 'setCamera': {(replaceSimpleSetter, 'camera'): ['KX_SceneActuator']},
+ 'setContinue': {(replaceSimpleSetter, 'useContinue'): ['BL_ActionActuator']},
+ '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']},
+ 'setHat': {(replaceSimpleSetter, 'hat'): ['SCA_JoystickSensor']},
+ 'setHeight': {(replaceSimpleSetter, 'height'): ['KX_CameraActuator']},
+ 'setHold1': {(replaceSimpleSetter, 'hold1'): ['SCA_KeyboardSensor']},
+ 'setHold2': {(replaceSimpleSetter, 'hold2'): ['SCA_KeyboardSensor']},
+ 'setIndex': {(replaceSimpleSetter, 'index'): ['SCA_JoystickSensor']},
+ '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']},
+ 'setObject': {(replaceSimpleSetter, 'object'): ['KX_SCA_AddObjectActuator',
+ 'KX_CameraActuator',
+ 'KX_TrackToActuator',
+ 'KX_ParentActuator']},
+ 'setOperation': {(replaceSimpleSetter, 'mode'): ['KX_SCA_DynamicActuator'],
+ (replaceSimpleSetter, 'operation'): ['KX_StateActuator']},
+ 'setOrientation': {(replaceSimpleSetter, 'localOrientation'): ['KX_GameObject'],
+ (replaceSimpleSetter, 'orientation'): ['KX_SoundActuator']},
+ 'setPitch': {(replaceSimpleSetter, 'pitch'): ['KX_SoundActuator']},
+ 'setPosition': {(replaceSimpleSetter, 'localPosition'): ['KX_GameObject'],
+ (replaceSimpleSetter, 'position'): ['KX_SoundActuator']},
+ 'setPriority': {(replaceSimpleSetter, 'priority'): ['BL_ShapeActionActuator',
+ 'BL_ActionActuator']},
+ 'setProjectionMatrix': {(replaceSimpleSetter, 'projection_matrix'): ['KX_Camera']},
+ 'setProperty': {(replaceSimpleSetter, 'propName'): ['KX_IpoActuator',
+ 'SCA_PropertySensor',
+ 'SCA_RandomActuator']},
+ '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']},
+ 'setVelocity': {(replaceSimpleSetter, 'velocity'): ['KX_SoundActuator']},
+ 'setXY': {(replaceSimpleSetter, 'useXY'): ['KX_CameraActuator']}
+}
+
+def convert248to249(lines, log = True, logErrors = True):
+ # 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
+
+ row = 0
+ sourceRow = 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.
+ conversionDict = attributeRenameDict[attrName]
+
+ if len(conversionDict.keys()) > 1:
+ # Ambiguous! Can't convert.
+ print "ERROR: source line %d, ambiguous conversion:" % sourceRow
+ if logErrors:
+ lines.insert(row, "##248## ERROR: ambiguous conversion.\n")
+ row = row + 1
+ for conversion in conversionDict.keys():
+ _, newAttrName = conversion
+ classes = conversionDict[conversion]
+ print "\t%s -> %s (classes %s)" % (attrName, newAttrName, classes)
+ if logErrors:
+ lines.insert(row, "##248##%s -> %s (classes %s)\n" %
+ (attrName, newAttrName, classes))
+ row = row + 1
+ nerrors = nerrors + 1
+
+ else:
+ # Conversion is well-defined. Execute.
+ func, newAttrName = conversionDict.keys()[0]
+ try:
+ func(lines, row, match.start(1), match.end(1), newAttrName)
+ except ConversionError as e:
+ # Insert a comment saying the conversion failed.
+ print "ERROR: source line %d, %s: %s\n" % (
+ sourceRow, 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:
+ if originalLine[-1] != '\n':
+ originalLine = originalLine + '\n'
+ lines.insert(row, "##248##%s" % originalLine)
+ row = row + 1
+ row = row + 1
+ sourceRow = sourceRow + 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
+
+ # Gets the active text object, there can be many in one blend file.
+ txt = bpy.data.texts.active
+
+ # Silently return if the script has been run with no active text
+ if not txt:
+ return
+
+ Window.WaitCursor(1)
+ try:
+ lines = txt.asLines()
+ for i in range(0, len(lines)):
+ if not lines[i].endswith('\n'):
+ lines[i] = lines[i] + '\n'
+
+ nconverted, nerrors = convert248to249(lines)
+
+ Blender.SaveUndoState('Convert GE 249')
+ txt.clear()
+ for line in lines:
+ txt.write(line)
+
+ 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)
+
+ finally:
+ Window.WaitCursor(0)
+
+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()