The-Powder-Toy/generator.py

237 lines
5.1 KiB
Python

import re, os, shutil, string, sys
def generateElements(elementFiles, outputCpp, outputH):
elementClasses = {}
baseClasses = {}
elementHeader = """// This file is automatically generated by generator.py
#ifndef ELEMENTCLASSES_H
#define ELEMENTCLASSES_H
#include <vector>
#include "simulation/SimulationData.h"
#include "simulation/elements/Element.h"
"""
directives = []
for elementFile in elementFiles:
try:
f = open(elementFile, "r")
except:
f = open("src/simulation/elements/"+elementFile, "r")
fileData = f.read()
f.close()
directiveMatcher = '//#TPT-Directive\s+([^\r\n]+)'
matcher = re.compile(directiveMatcher)
directiveMatches = matcher.findall(fileData)
for match in directiveMatches:
directives.append(match.split(" "))
classDirectives = []
usedIDs = []
for d in directives:
if d[0] == "ElementClass":
d[3] = int(d[3])
classDirectives.append(d)
if d[3] in usedIDs:
print("WARNING: duplicate element ID {} ({})".format(d[3],d[2]))
usedIDs.append(d[3])
elementIDs = sorted(classDirectives, key=lambda directive: directive[3])
for d in elementIDs:
tmpClass = d[1]
newClass = ""
baseClass = "Element"
if ':' in tmpClass:
classBits = tmpClass.split(':')
newClass = classBits[0]
baseClass = classBits[1]
else:
newClass = tmpClass
elementClasses[newClass] = []
baseClasses[newClass] = baseClass
elementHeader += "#define %s %s\n" % (d[2], d[3])
for d in directives:
if d[0] == "ElementHeader":
tmpClass = d[1]
newClass = ""
baseClass = "Element"
if ':' in tmpClass:
classBits = tmpClass.split(':')
newClass = classBits[0]
baseClass = classBits[1]
else:
newClass = tmpClass
elementClasses[newClass].append(" ".join(d[2:])+";")
#for className, classMembers in elementClasses.items():
for d in elementIDs:
tmpClass = d[1]
newClass = ""
baseClass = "Element"
if ':' in tmpClass:
classBits = tmpClass.split(':')
newClass = classBits[0]
baseClass = classBits[1]
else:
newClass = tmpClass
className = newClass
classMembers = elementClasses[newClass]
elementBase = baseClass
elementHeader += """
class {0}: public {1}
{{
public:
{0}();
virtual ~{0}();
{2}
}};
""".format(className, elementBase, str.join("\n\t", classMembers))
elementHeader += """
std::vector<Element> GetElements();
#endif
"""
elementContent = """#include "simulation/ElementDefs.h"
#include "ElementClasses.h"
std::vector<Element> GetElements()
{
std::vector<Element> elements;
""";
for d in elementIDs:
tmpClass = d[1]
newClass = ""
baseClass = "Element"
if ':' in tmpClass:
classBits = tmpClass.split(':')
newClass = classBits[0]
baseClass = classBits[1]
else:
newClass = tmpClass
elementContent += """elements.push_back(%s());
""" % (newClass)
elementContent += """return elements;
}
""";
outputPath, outputFile = os.path.split(outputH)
if not os.path.exists(outputPath):
os.makedirs(outputPath)
f = open(outputH, "w")
f.write(elementHeader)
f.close()
f = open(outputCpp, "w")
f.write(elementContent)
f.close()
def generateTools(toolFiles, outputCpp, outputH):
toolClasses = {}
toolHeader = """#ifndef TOOLCLASSES_H
#define TOOLCLASSES_H
#include <vector>
#include "simulation/simtools/SimTool.h"
"""
directives = []
for toolFile in toolFiles:
try:
f = open(toolFile, "r")
except:
f = open("src/simulation/simtools/"+toolFile, "r")
fileData = f.read()
f.close()
directiveMatcher = '//#TPT-Directive\s+([^\r\n]+)'
matcher = re.compile(directiveMatcher)
directiveMatches = matcher.findall(fileData)
for match in directiveMatches:
directives.append(match.split(" "))
classDirectives = []
usedIDs = []
for d in directives:
if d[0] == "ToolClass":
toolClasses[d[1]] = []
toolHeader += "#define %s %s\n" % (d[2], d[3])
d[3] = int(d[3])
classDirectives.append(d)
if d[3] in usedIDs:
print("WARNING: duplicate tool ID {} ({})".format(d[3],d[2]))
usedIDs.append(d[3])
for d in directives:
if d[0] == "ToolHeader":
toolClasses[d[1]].append(" ".join(d[2:])+";")
for className, classMembers in list(toolClasses.items()):
toolHeader += """
class {0}: public SimTool
{{
public:
{0}();
virtual ~{0}();
int Perform(Simulation * sim, Particle * cpart, int x, int y, int brushX, int brushY, float strength) override;
}};
""".format(className, str.join("\n", classMembers))
toolHeader += """
std::vector<SimTool*> GetTools();
#endif
"""
toolContent = """#include "ToolClasses.h"
std::vector<SimTool*> GetTools()
{
std::vector<SimTool*> tools;
""";
toolIDs = sorted(classDirectives, key=lambda directive: directive[3])
for d in toolIDs:
toolContent += """ tools.push_back(new %s());
""" % (d[1])
toolContent += """ return tools;
}
""";
outputPath, outputFile = os.path.split(outputH)
if not os.path.exists(outputPath):
os.makedirs(outputPath)
f = open(outputH, "w")
f.write(toolHeader)
f.close()
f = open(outputCpp, "w")
f.write(toolContent)
f.close()
generateElements(os.listdir("src/simulation/elements"), "generated/ElementClasses.cpp", "generated/ElementClasses.h")
generateTools(os.listdir("src/simulation/simtools"), "generated/ToolClasses.cpp", "generated/ToolClasses.h")