stk-code_catmod/tools/create_kart_properties.py

229 lines
8.5 KiB
Python
Raw Normal View History

#!/usr/bin/env python3
#
# SuperTuxKart - a fun racing game with go-kart
# Copyright (C) 2006-2015 SuperTuxKart-Team
#
# 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, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
# This script creates code for the characteristics.
2015-04-16 11:50:17 -04:00
# It takes an argument that specifies what the output of the script should be.
2015-04-18 18:11:39 -04:00
# The output options can be seen by running this script without arguments.
2015-04-16 11:50:17 -04:00
import sys
# Input data
characteristics = """Suspension: stiffness, rest, travel, expSpringResponse(bool), maxForce
2015-04-16 11:50:17 -04:00
Stability: rollInfluence, chassisLinearDamping, chassisAngularDamping, downwardImpulseFactor, trackConnectionAccel, smoothFlyingImpulse
Turn: radius(InterpolationArray), timeResetSteer, timeFullSteer(InterpolationArray)
Engine: power, maxSpeed, brakeFactor, brakeTimeIncrease, maxSpeedReverseRatio
Gear: switchRatio(std::vector<float>/floatVector), powerIncrease(std::vector<float>/floatVector)
Mass
Wheels: dampingRelaxation, dampingCompression
2015-04-16 11:50:17 -04:00
Camera: distance, forwardUpAngle, backwardUpAngle
Jump: animationTime
Lean: max, speed
Anvil: duration, weight, speedFactor
2015-07-11 19:29:17 -04:00
Parachute: friction, duration, durationOther, lboundFraction, uboundFraction, maxSpeed
2015-04-16 11:50:17 -04:00
Bubblegum: duration, speedFraction, torque, fadeInTime, shieldDuration
Zipper: duration, force, speedGain, maxSpeedIncrease, fadeOutTime
2015-04-16 11:50:17 -04:00
Swatter: duration, distance, squashDuration, squashSlowdown
Plunger: bandMaxLength, bandForce, bandDuration, bandSpeedIncrease, bandFadeOutTime, inFaceTime
2015-04-16 11:50:17 -04:00
Startup: time(std::vector<float>/floatVector), boost(std::vector<float>/floatVector)
Rescue: duration, vertOffset, height
Explosion: duration, radius, invulnerabilityTime
Nitro: duration, engineForce, consumption, smallContainer, bigContainer, maxSpeedIncrease, fadeOutTime, max
Slipstream: duration, length, width, collectTime, useTime, addPower, minSpeed, maxSpeedIncrease, fadeOutTime"""
2015-04-15 03:01:23 -04:00
class GroupMember:
def __init__(self, name, typeC, typeStr):
self.name = name
if name == "value":
self.getName = ""
else:
self.getName = name
2015-04-15 03:01:23 -04:00
self.typeC = typeC
self.typeStr = typeStr
""" E.g. power(std::vector<float>/floatVector)
or speed(InterpolationArray)
The default type is float
The name 'value' is special: Only the group name will be used to access
the member but in the xml file it will be still value (because we
need a name). """
2015-04-15 03:01:23 -04:00
def parse(content):
typeC = "float"
typeStr = typeC
name = content.strip()
pos = content.find("(")
end = content.find(")", pos)
if pos != -1 and end != -1:
name = content[:pos].strip()
pos2 = content.find("/", pos, end)
if pos2 != -1:
typeC = content[pos + 1:pos2].strip()
typeStr = content[pos2 + 1:end].strip()
else:
typeC = content[pos + 1:end].strip()
typeStr = typeC
return GroupMember(name, typeC, typeStr)
class Group:
def __init__(self, baseName):
self.baseName = baseName
2015-04-15 03:01:23 -04:00
self.members = []
def addMember(self, content):
self.members.append(GroupMember.parse(content))
2015-04-16 11:50:17 -04:00
def getBaseName(self):
return self.baseName
""" E.g. engine: power, gears(std::vector<Gear>/Gears)
or mass(float) or only mass """
2015-04-15 03:01:23 -04:00
def parse(content):
pos = content.find(":")
if pos == -1:
group = Group(content)
group.addMember("value")
2015-04-15 03:01:23 -04:00
return group
else:
group = Group(content[:pos].strip())
for m in content[pos + 1:].split(","):
group.addMember(m)
return group
""" Creates a list of words from a titlecase string """
def toList(name):
result = []
cur = ""
for c in name:
if c.isupper() and len(cur) != 0:
result.append(cur)
cur = ""
cur += c.lower()
if len(cur) != 0:
result.append(cur)
return result
""" titleCase: true = result is titlecase
false = result has underscores """
2015-04-15 03:01:23 -04:00
def joinSubName(group, member, titleCase):
words = toList(group.baseName) + toList(member.getName)
first = True
if titleCase:
2015-04-16 11:50:17 -04:00
words = [w.title() for w in words]
return "".join(words)
else:
return "_".join(words)
def main():
2015-04-16 11:50:17 -04:00
# Find out what to do
if len(sys.argv) == 1:
print("""Usage: ./create_kart_properties.py <operation>
Operations:
enum List the enum values for all characteristics in abstract_characteristic.hpp
defs Create the headers in abstract_characteristic.hpp
getter The getter implementations in abstract_characteristic.cpp
getProp1 Creates the getType function in abstract_characteristic.cpp
getProp2 Creates the getName funciton in abstract_characteristic.cpp
getXml Used to load the characteristics from an xml file in xml_characteristic.cpp""")
2015-04-16 11:50:17 -04:00
return
task = sys.argv[1]
groups = [Group.parse(line) for line in characteristics.split("\n")]
# Find longest name to align the function bodies
2015-04-18 18:11:39 -04:00
nameLengthTitle = 0
nameLengthUnderscore = 0
for g in groups:
for m in g.members:
l = len(joinSubName(g, m, True))
if l > nameLengthTitle:
nameLengthTitle = l
l = len(joinSubName(g, m, False))
if l > nameLengthUnderscore:
nameLengthUnderscore = l
# Print the results
2015-04-16 11:50:17 -04:00
if task == "enum":
for g in groups:
print()
print(" // {0}".format(g.getBaseName().title()))
for m in g.members:
print(" {0},".format(joinSubName(g, m, False).upper()))
elif task == "defs":
for g in groups:
print()
for m in g.members:
nameTitle = joinSubName(g, m, True)
nameUnderscore = joinSubName(g, m, False)
typeC = m.typeC
2015-04-16 11:50:17 -04:00
print(" {0} get{1}() const;".
format(typeC, nameTitle, nameUnderscore))
elif task == "getter":
for g in groups:
for m in g.members:
nameTitle = joinSubName(g, m, True)
nameUnderscore = joinSubName(g, m, False)
typeC = m.typeC
result = "result"
2015-04-16 11:50:17 -04:00
print("""// ----------------------------------------------------------------------------
{3} AbstractCharacteristic::get{1}() const
2015-04-16 11:50:17 -04:00
{{
{0} result;
2015-04-18 20:56:15 -04:00
bool is_set = false;
process({2}, &result, &is_set);
if (!is_set)
Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
getName({2}).c_str());
2015-04-16 11:50:17 -04:00
return {4};
}} // get{1}
2015-04-16 11:50:17 -04:00
""".format(m.typeC, nameTitle, nameUnderscore.upper(), typeC, result))
elif task == "getProp1":
2015-04-16 11:50:17 -04:00
for g in groups:
for m in g.members:
nameTitle = joinSubName(g, m, True)
nameUnderscore = joinSubName(g, m, False)
2015-04-18 19:44:54 -04:00
print(" case {0}:\n return TYPE_{1};".
2015-04-16 11:50:17 -04:00
format(nameUnderscore.upper(), "_".join(toList(m.typeStr)).upper()))
elif task == "getProp2":
2015-04-18 19:44:54 -04:00
for g in groups:
for m in g.members:
nameTitle = joinSubName(g, m, True)
nameUnderscore = joinSubName(g, m, False).upper()
print(" case {0}:\n return \"{0}\";".
format(nameUnderscore))
2015-04-18 18:11:39 -04:00
elif task == "getXml":
for g in groups:
print(" if (const XMLNode *sub_node = node->getNode(\"{0}\"))\n {{".
2015-07-11 09:38:52 -04:00
format(g.baseName.lower()))
2015-04-18 18:11:39 -04:00
for m in g.members:
nameUnderscore = joinSubName(g, m, False)
nameMinus = "-".join(toList(m.name))
print(""" sub_node->get(\"{0}\",
&m_values[{1}]);""".
2015-04-18 18:11:39 -04:00
format(nameMinus, nameUnderscore.upper()))
print(" }\n")
2015-04-16 11:50:17 -04:00
else:
print("Unknown task")
2015-04-13 05:10:18 -04:00
if __name__ == '__main__':
main()
2015-04-16 11:50:17 -04:00