2015-04-10 20:44:38 -04:00
|
|
|
#!/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.
|
|
|
|
|
2015-04-16 11:50:17 -04:00
|
|
|
# This script creates the output for the AbstractCharacteristics
|
|
|
|
# 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
|
2015-07-08 16:07:46 -04:00
|
|
|
#FIXME is wheelPosition needed?
|
2015-04-16 11:50:17 -04:00
|
|
|
characteristics = """Suspension: stiffness, rest, travelCm, expSpringResponse, maxForce
|
|
|
|
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, radius, position(std::vector<float>/floatVector)
|
|
|
|
Camera: distance, forwardUpAngle, backwardUpAngle
|
|
|
|
Jump: animationTime
|
|
|
|
Lean: max, speed
|
|
|
|
Anvil: duration, weight, speedFactor
|
|
|
|
Parachute: friction, duration, durationOther, lboundFranction, uboundFranction, maxSpeed
|
|
|
|
Bubblegum: duration, speedFraction, torque, fadeInTime, shieldDuration
|
|
|
|
Zipper: duration, force, speedGain, speedIncrease, fadeOutTime
|
|
|
|
Swatter: duration, distance, squashDuration, squashSlowdown
|
|
|
|
Plunger: maxLength, force, duration, speedIncrease, fadeOutTime, inFaceTime
|
|
|
|
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-10 20:44:38 -04:00
|
|
|
|
2015-04-15 03:01:23 -04:00
|
|
|
class GroupMember:
|
|
|
|
def __init__(self, name, typeC, typeStr):
|
|
|
|
self.name = name
|
|
|
|
self.typeC = typeC
|
|
|
|
self.typeStr = typeStr
|
|
|
|
|
|
|
|
"""E.g. power(std::vector<float>/floatVector)
|
|
|
|
or speed(InterpolationArray)
|
|
|
|
The default type is float"""
|
|
|
|
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)
|
|
|
|
|
2015-04-10 20:44:38 -04:00
|
|
|
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):
|
|
|
|
if len(self.baseName) == 0 and len(self.members) > 0:
|
|
|
|
return self.members[0].name
|
|
|
|
return self.baseName
|
|
|
|
|
2015-04-15 03:01:23 -04:00
|
|
|
"""E.g. engine: power, gears(std::vector<Gear>/Gears)
|
|
|
|
or mass(float) or only mass"""
|
|
|
|
def parse(content):
|
|
|
|
pos = content.find(":")
|
|
|
|
if pos == -1:
|
|
|
|
group = Group("")
|
|
|
|
group.addMember(content)
|
|
|
|
return group
|
|
|
|
else:
|
|
|
|
group = Group(content[:pos].strip())
|
|
|
|
for m in content[pos + 1:].split(","):
|
|
|
|
group.addMember(m)
|
|
|
|
return group
|
2015-04-10 20:44:38 -04:00
|
|
|
|
|
|
|
"""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.name)
|
2015-04-10 20:44:38 -04:00
|
|
|
first = True
|
|
|
|
if titleCase:
|
2015-04-16 11:50:17 -04:00
|
|
|
words = [w.title() for w in words]
|
2015-04-10 20:44:38 -04:00
|
|
|
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:
|
2015-04-18 19:44:54 -04:00
|
|
|
print("Please specify what you want to know [enum/defs/getter/getProp/getXml]")
|
2015-04-16 11:50:17 -04:00
|
|
|
return
|
|
|
|
task = sys.argv[1]
|
|
|
|
|
|
|
|
groups = [Group.parse(line) for line in characteristics.split("\n")]
|
2015-04-10 20:44:38 -04:00
|
|
|
|
|
|
|
# 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
|
2015-04-10 20:44:38 -04:00
|
|
|
|
|
|
|
# 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)
|
2015-07-08 16:07:46 -04:00
|
|
|
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)
|
2015-07-08 16:07:46 -04:00
|
|
|
typeC = m.typeC
|
|
|
|
result = "result"
|
2015-04-16 11:50:17 -04:00
|
|
|
|
2015-07-09 18:36:50 -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)
|
2015-07-09 18:36:50 -04:00
|
|
|
Log::fatal("AbstractCharacteristic", "Can't get characteristic %s", getName({2}).c_str());
|
2015-04-16 11:50:17 -04:00
|
|
|
return {4};
|
|
|
|
}}
|
|
|
|
""".format(m.typeC, nameTitle, nameUnderscore.upper(), typeC, result))
|
2015-04-18 19:44:54 -04:00
|
|
|
elif task == "getProp":
|
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()))
|
2015-04-18 19:44:54 -04:00
|
|
|
print("\n\n-------------------- END --------------------\n")
|
|
|
|
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}]);".
|
|
|
|
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
|
|
|
|
2015-04-18 18:57:55 -04:00
|
|
|
#print("Constructor ****************************************")
|
|
|
|
#lineLength = 4;
|
|
|
|
#line = " "
|
|
|
|
#for g in groups:
|
|
|
|
# for n in g.subNames:
|
|
|
|
# name = "m_{0} = ".format(joinSubName(g, n, False))
|
|
|
|
# l = len(name)
|
|
|
|
# if lineLength + l > 80 and lineLength > 4:
|
|
|
|
# print(line)
|
|
|
|
# line = " " + name
|
|
|
|
# lineLength = l + 4
|
|
|
|
# else:
|
|
|
|
# line += name
|
|
|
|
# lineLength += l
|
|
|
|
#if lineLength > 4:
|
|
|
|
# line += "1;"
|
|
|
|
# print(line)
|
2015-04-10 20:44:38 -04:00
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
main()
|
2015-04-16 11:50:17 -04:00
|
|
|
|