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.
This commit is contained in:
Campbell Barton 2009-05-20 23:31:58 +00:00
parent fcdb34f593
commit 3daa8bd4ef
3 changed files with 764 additions and 5 deletions

@ -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

@ -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()

@ -151,16 +151,22 @@ class SCA_ISensor(SCA_ILogicBrick):
def isPositive():
"""
True if this sensor brick is in a positive state.
@deprecated: use L{positive}
"""
def isTriggered():
"""
True if this sensor brick has triggered the current controller.
@deprecated: use L{triggered}
"""
def getUsePosPulseMode():
"""
True if the sensor is in positive pulse mode.
@deprecated: use L{usePosPulseMode}
"""
def setUsePosPulseMode(pulse):
"""
@ -168,6 +174,7 @@ class SCA_ISensor(SCA_ILogicBrick):
@type pulse: boolean
@param pulse: If True, will activate positive pulse mode for this sensor.
@deprecated: use L{usePosPulseMode}
"""
def getFrequency():
"""
@ -175,6 +182,7 @@ class SCA_ISensor(SCA_ILogicBrick):
@rtype: integer
@return: the pulse frequency in 1/50 sec.
@deprecated: use L{frequency}
"""
def setFrequency(freq):
"""
@ -182,10 +190,13 @@ class SCA_ISensor(SCA_ILogicBrick):
@type freq: integer
@return: the pulse frequency in 1/50 sec.
@deprecated: use L{frequency}
"""
def getUseNegPulseMode():
"""
True if the sensor is in negative pulse mode.
@deprecated: use L{useNegPulseMode}
"""
def setUseNegPulseMode(pulse):
"""
@ -193,10 +204,13 @@ class SCA_ISensor(SCA_ILogicBrick):
@type pulse: boolean
@param pulse: If True, will activate negative pulse mode for this sensor.
@deprecated: use L{useNegPulseMode}
"""
def getInvert():
"""
True if this sensor activates on negative events.
@deprecated: use L{invert}
"""
def setInvert(invert):
"""
@ -204,6 +218,7 @@ class SCA_ISensor(SCA_ILogicBrick):
@type invert: boolean
@param invert: true if activates on negative events; false if activates on positive events.
@deprecated: use L{invert}
"""
def getLevel():
"""
@ -215,6 +230,7 @@ class SCA_ISensor(SCA_ILogicBrick):
@rtype: boolean
@return: true if sensor is level sensitive, false if it is edge sensitive
@deprecated: use L{level}
"""
def setLevel(level):
"""
@ -222,6 +238,7 @@ class SCA_ISensor(SCA_ILogicBrick):
@param level: Detect level instead of edge? (KX_TRUE, KX_FALSE)
@type level: boolean
@deprecated: use L{level}
"""
#}
@ -315,7 +332,7 @@ class BL_ActionActuator(SCA_IActuator):
@ivar useContinue: The actions continue option, True or False.
When True, the action will always play from where last left off,
otherwise negative events to this actuator will reset it to its start frame.
@type: boolean
@type useContinue: boolean
@ivar framePropName: The name of the property that is set to the current frame number.
@type framePropName: string
"""
@ -2575,7 +2592,7 @@ class KX_NetworkMessageSensor(SCA_ISensor):
@type subject: string
@ivar frameMessageCount: The number of messages received since the last frame.
(Read-only)
@type framemessageCount: int
@type frameMessageCount: int
@ivar subjects: The list of message subjects received. (Read-only)
@type subjects: list of strings
@ivar bodies: The list of message bodies received. (Read-only)
@ -5614,3 +5631,67 @@ for name, val in locals().items():
for a in attrs:
print a
"""
# Util func to construct a mapping from deprecated attrs to new ones.
"""
import types
import re
import pprint
depAttrs = {}
for name, val in locals().items():
if name.startswith('__'):
continue
if type(val) == types.ClassType:
print "\t# %s" % name
# Inspect each attribute.
for attrName in dir(val):
if attrName.startswith('__'):
continue
attr = getattr(val, attrName)
# Check whether this attribute is deprecated by searching each line.
newAttrName = None
for line in attr.__doc__.split('\n'):
match = re.search(r'@deprecated.*L{(\w+)}', line)
if match:
newAttrName = match.group(1)
break
if not newAttrName:
continue
# Store the mappings to new attributes in a list (because there
# could be collisions).
if not depAttrs.has_key(attrName):
depAttrs[attrName] = {}
mapping = depAttrs[attrName]
for line in val.__doc__.split('\n'):
if ("@type %s:" % newAttrName) in line:
# The attribute is being replaced in this class (i.e. the
# deprecated attribute wasn't inherited from a parent). We
# have a winner!
funcType = None
if 'sequence' in line:
funcType = 'Keyed'
else:
funcType = 'Simple'
if attrName.startswith('get') or attrName.startswith('is'):
func = "replace%sGetter" % funcType
elif attrName.startswith('set') or attrName.startswith('enable'):
func = "replace%sSetter" % funcType
else:
func = 'UNKNOWN'
# Another mapping, from a conversion tuple to lists of class
# names.
conversion = (func, newAttrName)
if not mapping.has_key(conversion):
mapping[conversion] = []
mapping[conversion].append(name)
break
pprint.pprint(depAttrs, width = 100)
"""