Okay, so you need python to run this and it does the following:
Transforming object coordinates is required when porting and resizing maps.
Here's the code:
- Code: Select all
# Quick and dirty hacky script for transforming the coordinates of decals,
# props, markers and units.
# Absolute values are used, because the input format is fixed anyway.
# This script can be destructive, if handled incorrectly. Never operate
# on original map files!
# Also note, that importing decals and props will ADD props at the new
# positions. Old props and decals will persit until deleted manually.
# To transform marker unit positions, pass in the <map>_save.lua
# To transform prop positions, pass in the props file (export from editor)
# To transform decals positions, pass in the decals file (export from editor)
# version: 1, author: Lionhardt, date: 25.07.2015
from sys import argv
import sys
from math import sin
from math import cos
from math import radians
########################################################################
# translation sub-functions and objects
########################################################################
# function object for translation
class Translation:
def __init__(self, x_index, y_index, x_offset, y_offset):
self.x_index = x_index
self.y_index = y_index
self.x_offset = x_offset
self.y_offset = y_offset
########################################################################
def _trans(coord, offset):
return str(float(coord)+offset)
########################################################################
def _translate(string, offset):
if string[-1] == ",":
return _trans(_isolate(string), offset)+","
else:
return _trans(string, offset)
########################################################################
# projection sub-functions and objects
########################################################################
# function object for projection
class Projection:
def __init__(self, x_index, y_index, scale_factor):
self.x_index = x_index
self.y_index = y_index
self.factor = scale_factor
########################################################################
def _proj(coord, factor):
return str(float(coord)*factor)
########################################################################
def _project(string, factor):
if string[-1] == ",":
return _proj(_isolate(string), factor)+","
else:
return _proj(string, factor)
########################################################################
# resizing sub-functions and objects
########################################################################
# function object for resizing
class Resizing:
def __init__(self, x_index, y_index, center_coordinate, scale_factor):
self.x_index = x_index
self.y_index = y_index
self.factor = scale_factor
self.center = center_coordinate
########################################################################
def _res(coord, c_coord, factor):
# get direction vector (point to translate) - (center)
# multiply direction vector by scale factor
# add scaled direction vector to center to get traslated point
return str(c_coord+((float(coord) - c_coord)*factor))
########################################################################
def _resize(string, center, factor):
if string[-1] == ",":
return _res(_isolate(string), center[0], factor)+","
else:
return _res(string, center[1], factor)
########################################################################
# symmetrization sub-functions and objects
########################################################################
# function object for symmetrization
class uSymmetrization:
def __init__(self, x_index, y_index, center_coordinate, rot_angle, uID):
self.x_index = x_index
self.y_index = y_index
self.angle = rot_angle
self.center = center_coordinate
self.ID = uID
def new_ID(self):
self.ID[0]+=1
return self.ID[0]
########################################################################
# function object for symmetrization
class mSymmetrization:
def __init__(self, x_index, y_index, center_coordinate, rot_angle, mIDs):
self.x_index = x_index
self.y_index = y_index
self.angle = rot_angle
self.center = center_coordinate
self.IDs = mIDs
def new_ID(self, m):
self.IDs[m]+=1
return self.IDs[m]
########################################################################
def _duplicate(lines, begin, end, FO, marker, option):
ret = str()
times = 360/int(FO.angle)
for t in range(1,times):
ret += make_head(lines[begin], FO, marker, option)
for l in lines[begin+1:end-2]:
ret+=l
if option == "marker":
ret+=lines[end-2]
posLine = lines[end-1].split(" ")
elif option == "unit":
posLine = lines[end-2].split(" ")
new_point_coords = _symmetrize(posLine[FO.x_index],
posLine[FO.y_index], FO, t)
posLine[FO.x_index] = str(new_point_coords[0])+","
posLine[FO.y_index] = str(new_point_coords[1])
ret+=(" ".join(posLine))
if option == "unit":
ret+=_rotate((lines[end-1]), FO, t)
ret+=(lines[end])
return ret
########################################################################
def _rotate(line, FO, factor):
line = line.split(" ")
orientation = float(_isolate(line[-3]))
line[-3] = str(radians(-1*factor*FO.angle)+orientation)+","
return " ".join(line)
########################################################################
def make_head(headline, FO, marker, option):
if option == "unit":
nID = FO.new_ID()
if nID < 10:
nID = "0"+str(nID)
else:
nID = str(nID)
head = headline.split("_") #[ "['UNIT", "3']" ]
head = head[0]+ "_"+str(nID)+"'] = {\r\n"
return head
elif option == "marker":
nID = FO.new_ID(marker)
if nID < 10:
nID = "0"+str(nID)
else:
nID = str(nID)
head = headline.split(" ")
head[-3] = nID+"']"
return " ".join(head)
########################################################################
def exists_marker(line, markers):
for m, c in markers.iteritems():
if (m in line) and ("{\r\n" in line):
return m
return False
########################################################################
def exists_unit(line):
if ("UNIT" in line) and ("{\r\n" in line):
return True
return False
########################################################################
def find_end_of_block(i, lines):
j = i
for line in lines[i:]:
if "},\r\n" in line and line[line.index("},\r\n")-2] == " ":
return j
j+=1
########################################################################
def _sym(x, y, FO, f):
a = FO.angle
x = x-FO.center[0]
y = y-FO.center[1]
sin_a = sin(f*radians(a))
cos_a = cos(f*radians(a))
x1 = cos_a*x + (-1*sin_a*y)
y1 = sin_a*x + cos_a*y
x = x1+FO.center[0]
y = y1+FO.center[1]
return (x, y)
########################################################################
def _symmetrize(string_x, string_y, FO, factor):
x = float(_isolate(string_x))
y = float(string_y)
return _sym(x, y, FO, factor)
########################################################################
# general sub-functions
########################################################################
def _isolate(string):
return string.split(",")[0]
########################################################################
def _alter(line, FO, mode):
if mode == "-t":
line[FO.x_index] = _translate(line[FO.x_index], FO.x_offset)
line[FO.y_index] = _translate(line[FO.y_index], FO.y_offset)
elif mode == "-p":
line[FO.x_index] = _project(line[FO.x_index], FO.factor)
line[FO.y_index] = _project(line[FO.y_index], FO.factor)
elif mode == "-r":
line[FO.x_index] = _resize(line[FO.x_index], FO.center, FO.factor)
line[FO.y_index] = _resize(line[FO.y_index], FO.center, FO.factor)
return line
########################################################################
def find_unit(line, max_id):
if "UNIT" in line:
line = line.split("_")
# get unit ID
u_id = int(line[1].split("'")[0])
# update max unit id if necessary
if u_id > max_id[0]:
return [u_id]
return max_id
########################################################################
def find_marker(line, max_ids):
# get the marker name that might be n line
markers = [m for m in max_ids if m in line]
line = line.split(" ")
if (len(markers) > 0) and ("{\r\n" in line):
m = markers[0]
# isolate the marker ID
m_id = int(line[-3].split("'")[0])
# compare if larger than largest ID for marker type
if m_id > max_ids[m]:
max_ids[m] = m_id
return max_ids
########################################################################
# driver functions
########################################################################
# translates coordinates
def translate(option, x_offset, y_offset, iFile, oFile):
with open(iFile, "r") as I:
with open(oFile, "w") as O:
# replace decal or prop coords
if option in ["-p", "-d"]:
for line in I:
line = line.split(" ")
if line[0] == "position":
line = _alter(line, Translation(3, 5, x_offset, y_offset),
argv[1])
line = " ".join(line)
O.write(line)
# replace unit and marker coords
if option == "-mu":
for line in I:
line = line.split(" ")
if "['position']" in line:
line = _alter(line, Translation(23, 25, x_offset, y_offset),
argv[1])
if "Position" in line:
line = _alter(line, Translation(35, 37, x_offset, y_offset),
argv[1])
line = " ".join(line)
O.write(line)
########################################################################
# projects coordinates
def project(option, factor, iFile, oFile):
with open(iFile, "r") as I:
with open(oFile, "w") as O:
# replace decal or prop coords
if option in ["-p", "-d"]:
for line in I:
line = line.split(" ")
if line[0] == "position":
line = _alter(line, Projection(3, 5, factor), argv[1])
line = " ".join(line)
O.write(line)
# replace unit and marker coords
if option == "-mu":
for line in I:
line = line.split(" ")
if "['position']" in line:
line = _alter(line, Projection(23, 25, factor), argv[1])
if "Position" in line:
line = _alter(line, Projection(35, 37, factor), argv[1])
line = " ".join(line)
O.write(line)
########################################################################
# scales coordinates
def resize(option, center_x, center_y, factor, iFile, oFile):
center = tuple((center_x, center_y))
with open(iFile, "r") as I:
with open(oFile, "w") as O:
# replace decal or prop coords
if option in ["-p", "-d"]:
for line in I:
line = line.split(" ")
if line[0] == "position":
line = _alter(line, Resizing(3, 5, center, factor), argv[1])
line = " ".join(line)
O.write(line)
# replace unit and marker coords
if option == "-mu":
for line in I:
line = line.split(" ")
if "['position']" in line:
line = _alter(line, Resizing(23, 25, center, factor), argv[1])
if "Position" in line:
line = _alter(line, Resizing(35, 37, center, factor), argv[1])
line = " ".join(line)
O.write(line)
########################################################################
def symmetrize(option, center_x, center_y, angle, iFile, oFile):
center = tuple((center_x, center_y))
# first get the highest Marker and Unit IDs
m_max = {"Blank":-1, "Camera":-1, "Combat":-1, "Defensive":-1,
"Expansion":-1, "Hydrocarbon":-1, "Island":-1, "Mass":-1,
"Naval":-1, "Experimental":-1, "Rally":-1, "Definition":-1,
"Generator":-1}
u_max = [0]
with open(iFile, "r") as I:
for line in I:
m_max = find_marker(line, m_max)
u_max = find_unit(line, u_max)
with open(iFile, "r") as I:
with open(oFile, "w") as O:
lines = I.readlines()
i = 0
j = None
for line in lines:
O.write(line)
marker = exists_marker(line, m_max)
unit = exists_unit(line)
if marker:
j = find_end_of_block(i, lines)
ms = mSymmetrization(23, 25, center, angle, m_max)
new_entries = _duplicate(lines, i, j, ms, marker, "marker")
m_max = ms.IDs
elif unit:
j = find_end_of_block(i, lines)
us = uSymmetrization(35, 37, center, angle, u_max)
new_entries = _duplicate(lines, i, j, us, marker, "unit")
if i == j:
j = None
O.write(new_entries)
i+=1
########################################################################
#
########################################################################
if __name__ == "__main__":
if len(argv) == 1:
print ("-h for usage")
elif len(argv) == 2 and argv[1] == "-h":
print (
"\nLionhardt's coordinate transformation script\n\n"
"-t -- translate\t(wirte t for more info)\n"
"-p -- project\t(write p for more info)\n"
"-r -- resize\t(write r for more info)\n"
"-s -- rotate\t(write ro for more info)\n"
)
o = raw_input()
while o not in ["t", "p", "r", "s"]:
print "invalid option"
o = raw_input()
if o == "t":
print (
"\nTRANSLATE\n---------\n"
"Moves objects without altering their relative distances to"
" each other.\n"
"usage: python transform -r [-d, -p, -mu] <x-offset> <y-offset>"
" <input file> <output file>\n"
"choose -d for decals, -p for props and -mu for markers and"
" units"
)
elif o == "p":
print (
"\nPROJECT\n-------\n"
"Projects objects onto a different map size, preserving"
" relative distances.\n"
"usage: python transform -p [-d, -p, -mu] <scale factor>"
" <input file> <output file>\n"
"choose -d for decals, -p for props and -mu for markers and"
" units"
)
elif o == "r":
print (
"\nRESIZE\n------\n"
"Alters distances between objects through a center projection\n"
"usage: python transform -r [-d, -p, -mu] <center x-coordinate>"
" <center y-coordinate> <scale factor> <input file> <output file>\n"
"choose -d for decals, -p for props and -mu for markers and"
" units\n"
)
elif o == "s":
print (
"\SYMMETRIZE\n----------\n"
"Rotates objects around center point and copies them <360/angle>"
" times, rounding down.\n"
"usage: python transform -ro [-mu] <center x-coordinate>"
" <center y-coordinate> <angle> <input file> <output file>\n"
"choose -d for decals, -p for props and -mu for markers and"
" units\n"
)
else:
if argv[-2] == argv[-1]:
sys.stderr.write(
"Error: input file must be different from output file\n"
)
elif (argv[1] == "-t") and (len(argv) == 7):
translate(argv[2], float(argv[3]), float(argv[4]), argv[5], argv[6])
elif (argv[1] == "-p") and (len(argv) == 6):
project(argv[2], float(argv[3]), argv[4], argv[5])
elif (argv[1] == "-r") and (len(argv) == 8):
resize(argv[2], float(argv[3]), float(argv[4]), float(argv[5]),
argv[6], argv[7])
elif (argv[1] == "-s") and (len(argv) == 8):
symmetrize(argv[2], float(argv[3]), float(argv[4]), float(argv[5]),
argv[6], argv[7])
# example call:
# py transform.py -t -mu -200 -200 MyMap_save.lua MyMap_save.lua.trans