Advertisement
rPoXoTauJIo

merge_city.py

Sep 27th, 2019
350
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 12.34 KB | None | 0 0
  1. import os
  2. import sys
  3. import logging
  4. import re
  5. import shutil
  6. import datetime
  7.  
  8. import bf2
  9.  
  10. G_OBJECTS_CORE = {
  11.         'housingblock_1_groundfloor_v2' : 'staticobjects/pr/citybuildings/housingblock_1_groundfloor_v2',
  12.         'housingblock_1_midfloor_v1'    : 'staticobjects/pr/citybuildings/housingblock_1_midfloor_v1',
  13.         'housingblock_1_topfloor'       : 'staticobjects/pr/citybuildings/housingblock_1_topfloor',
  14.     }
  15.  
  16. # placeholder func
  17. def getStaticObjects(fname_staticobjects):
  18.     from vec3 import Vec3
  19.  
  20.     pattern_bf2_float3 = r'[-]{0,1}\d+.\d+\/[-]{0,1}\d+.\d+\/[-]{0,1}\d+.\d+'
  21.  
  22.     pattern = r'^rem \*\*\* \S+ \*\*\*$\n'
  23.     pattern += r'^object.create (?P<name>\S+)$\n'
  24.     pattern += r'^object.absolutePosition (?P<position>' + pattern_bf2_float3 + ')$\n'
  25.     pattern += r'^object.rotation (?P<rotation>' + pattern_bf2_float3 + ')$\n'
  26.     pattern += r'^object.layer 1$\n'
  27.     pattern += r'^\n'
  28.  
  29.     flags = re.MULTILINE | re.IGNORECASE
  30.  
  31.     staticobjects = []
  32.     with open(fname_staticobjects) as fo:
  33.         matches = re.findall(pattern, fo.read(), flags)
  34.         for match in matches:
  35.             templateName = match[0]
  36.             position = Vec3(*match[1].split('/'))
  37.             rotation = match[2].split('/')
  38.             staticobjects.append(bf2.StaticObject(templateName, position, rotation))
  39.    
  40.     return staticobjects
  41.  
  42. def writeStaticObjects(fname_staticobjects, staticobjects):
  43.     with open(fname_staticobjects, 'w') as fo:
  44.         for staticobjects in staticobjects:
  45.             createScript = ''
  46.             createScript += '\nrem *** %s ***' % staticobjects.name
  47.             createScript += '\nObject.create %s' % staticobjects.name
  48.             createScript += '\nObject.absolutePosition %s/%s/%s' % (staticobjects.position.x, staticobjects.position.y, staticobjects.position.z)
  49.             createScript += '\nObject.rotation %s/%s/%s' % (float(staticobjects.rotation[0]), float(staticobjects.rotation[1]), float(staticobjects.rotation[2]))
  50.             createScript += '\nObject.layer 1'
  51.             createScript += '\n'
  52.             fo.write(createScript)
  53.  
  54. def rename_objects(path, templateName, suffix, filter=None):
  55.     for dirname, dirnames, filenames in os.walk(path):
  56.         for filename in filenames:
  57.             fname, ext = os.path.splitext(filename)
  58.             fname_path = os.path.join(dirname, filename)
  59.             if ext in ['.con', '.tweak']:
  60.                 fin = open(fname_path, 'r').readlines()
  61.                 with open(fname_path, 'w') as fout:
  62.                     for line in fin:
  63.                         if filter:
  64.                             line = filter(line)
  65.                         fout.write(line.replace(templateName, templateName + suffix))
  66.             filename_new = filename.replace(templateName, templateName + suffix)
  67.             fname_path_new = os.path.join(dirname, filename_new)
  68.             logging.debug('os.rename(%s, %s)' % (fname_path, fname_path_new))
  69.             os.rename(fname_path, fname_path_new)
  70.  
  71. def remove_geom_visible(line):
  72.     if line.lower().startswith('objecttemplate.geometry'): return ''
  73.     if line.lower().startswith('geometrytemplate.create staticmesh'): return ''
  74.     return line
  75.  
  76. def remove_geom_cols(line):
  77.     if line.lower().startswith('ObjectTemplate.collisionMesh'.lower()): return ''
  78.     if line.lower().startswith('ObjectTemplate.setCollisionMesh '.lower()): return ''
  79.     if line.lower().startswith('ObjectTemplate.hasCollisionPhysics'.lower()): return ''
  80.     if line.lower().startswith('CollisionManager.createTemplate'.lower()): return ''
  81.     return line
  82.  
  83. def copy_object_as_custom(game, templateName, suffix=None, filter=None):
  84.     logging.debug('cloning %s as custom to %s' % (templateName, game.level.name))
  85.     src = os.path.join(game.root, game.modPath, 'objects', G_OBJECTS_CORE[templateName])
  86.     dst = os.path.join(game.root, game.modPath, 'levels', game.level.name, 'objects', G_OBJECTS_CORE[templateName])
  87.     if suffix: dst += suffix
  88.     logging.debug('shutil.copytree(%s, %s)' % (src, dst))
  89.     if os.path.exists(dst):
  90.         shutil.rmtree(dst)
  91.     shutil.copytree(src, dst)
  92.  
  93.     if suffix: rename_objects(dst, templateName, suffix, filter)
  94.  
  95. def merge_objects(game, staticobjects, templateName, suffix):
  96.     # stop
  97.     # you violated the law
  98.     from bf2mesh.visiblemesh import VisibleMesh
  99.  
  100.     staticobject_main = staticobjects[0]
  101.     mergedNum = 0
  102.     with VisibleMesh(os.path.join(game.root, game.modPath, 'objects', G_OBJECTS_CORE[templateName], 'meshes', templateName + '.staticMesh')) as staticobject_main_mesh:
  103.         for staticobject_secondary in staticobjects[1:]:
  104.             offset = staticobject_secondary.position - staticobject_main.position
  105.             with VisibleMesh(os.path.join(game.root, game.modPath, 'objects', G_OBJECTS_CORE[templateName], 'meshes', templateName + '.staticMesh')) as staticobject_secondary_mesh:
  106.                 logging.info('translating(%s) %s' % (offset, staticobject_secondary_mesh.filename))
  107.                 staticobject_secondary_mesh.translate(offset, False)
  108.                 try:
  109.                     logging.info('merging #%d %s to %s' % (mergedNum, templateName, staticobject_main_mesh.filename))
  110.                     staticobject_main_mesh.merge(staticobject_secondary_mesh, False)
  111.                 except OverflowError as err:
  112.                     logging.error(err.__repr__)
  113.                     raise err
  114.                 mergedNum += 1
  115.         export_path = os.path.join(game.root,
  116.                                     game.mod.modPath,
  117.                                     'levels',
  118.                                     game.level.name,
  119.                                     'objects',
  120.                                     G_OBJECTS_CORE[templateName] + suffix,
  121.                                     'Meshes',
  122.                                     '%s.staticmesh' % (templateName + suffix))
  123.         logging.info('updating bounds %s' % (staticobject_main_mesh.filename))
  124.         staticobject_main_mesh.update_boundaries()
  125.         staticobject_main_mesh.export(export_path)
  126.         logging.info('exported %d merged %s to %s' % (mergedNum, templateName, export_path))
  127.    
  128.         staticobject_main.name += suffix
  129.         return staticobject_main
  130.  
  131. def main2():
  132.     logging.debug('logging level is DEBUG')
  133.  
  134.     root = 'D:\\Games\\Project Reality'
  135.     modPath = 'mods/pr_repo'
  136.     levelName = 'test_airfield'
  137.     game = bf2.Game(root)
  138.     game.loadMod(modPath)
  139.     game.loadLevel(levelName)
  140.  
  141.     fname_for_merge = 'staticobjects_testing.con'
  142.     fname_visible = 'staticobjects_visible.con'
  143.     fname_cols = 'staticobjects_cols.con'
  144.  
  145.     staticobjects_city = getStaticObjects(os.path.join(root, modPath, 'levels', levelName, fname_for_merge))
  146.     #staticobjects_city = game.level.getStaticObjects(os.path.join(game.level.path, fname_for_merge))
  147.  
  148.     objects2merge = {}
  149.     for staticobject in staticobjects_city:
  150.         if staticobject.name not in objects2merge: objects2merge[staticobject.name] = []
  151.         objects2merge[staticobject.name].append(staticobject)
  152.  
  153.     # cleanup first
  154.     shutil.rmtree(os.path.join(game.root, game.modPath, 'levels', game.level.name, 'objects', 'staticobjects'), ignore_errors=True)
  155.  
  156.     # clone first&remove geometry
  157.     suffix_cols = '_cols'
  158.     for templateName in objects2merge:
  159.         copy_object_as_custom(game, templateName, suffix_cols, remove_geom_visible)
  160.     staticobjects_city_cols = []
  161.     for staticobject in staticobjects_city:
  162.         staticobject_cols = bf2.StaticObject(
  163.                                 staticobject.name+suffix_cols,
  164.                                 staticobject.position,
  165.                                 staticobject.rotation)
  166.         staticobjects_city_cols.append(staticobject_cols)
  167.     writeStaticObjects(os.path.join(root, modPath, 'levels', levelName, fname_cols), staticobjects_city_cols)
  168.  
  169.     # clone visible meshes now
  170.     # then merge
  171.     staticobjects_city_visible_merged = []
  172.     # 1. merge groundfloor
  173.     templateName = 'housingblock_1_groundfloor_v2'
  174.     suffix_merged = '_merged'
  175.     copy_object_as_custom(game, templateName, suffix_merged, remove_geom_cols)
  176.     staticobjects_groundfloors = [staticobject for staticobject in staticobjects_city if staticobject.name == templateName]
  177.     staticobject_merged = merge_objects(game, staticobjects_groundfloors, templateName, suffix_merged)
  178.     staticobjects_city_visible_merged.append(staticobject_merged)
  179.  
  180.     # 2. merge middle floors, grouped
  181.     templateName = 'housingblock_1_midfloor_v1'
  182.     suffix_merged = '_merged'
  183.     copy_object_as_custom(game, templateName, suffix_merged, remove_geom_cols)
  184.     staticobjects_middlefloors = {}
  185.     for staticobject in staticobjects_city:
  186.         if staticobject.name != templateName: continue
  187.         positionXZ = '%s%s' % (staticobject.position.x, staticobject.position.z)
  188.         if positionXZ not in staticobjects_middlefloors.keys(): staticobjects_middlefloors[positionXZ] = []
  189.         staticobjects_middlefloors[positionXZ].append(staticobject)
  190.     midfloors_merged = False
  191.     for positionXZ in staticobjects_middlefloors:
  192.         staticobject = staticobjects_middlefloors[positionXZ][0]
  193.         staticobject_middlefloors_base = bf2.StaticObject(
  194.                                 staticobject.name+suffix_merged,
  195.                                 staticobject.position,
  196.                                 staticobject.rotation)
  197.         staticobjects_city_visible_merged.append(staticobject_middlefloors_base)
  198.         if not midfloors_merged: merge_objects(game, staticobjects_middlefloors[positionXZ], templateName, suffix_merged)
  199.         midfloors_merged = True
  200.    
  201.     # 3. merge topfloor
  202.     templateName = 'housingblock_1_topfloor'
  203.     suffix_merged = '_merged'
  204.     copy_object_as_custom(game, templateName, suffix_merged, remove_geom_cols)
  205.     staticobjects_topfloors = [staticobject for staticobject in staticobjects_city if staticobject.name == templateName]
  206.     staticobject_merged = merge_objects(game, staticobjects_topfloors, templateName, suffix_merged)
  207.     staticobjects_city_visible_merged.append(staticobject_merged)
  208.  
  209.     # MERGED ALL
  210.     writeStaticObjects(os.path.join(root, modPath, 'levels', levelName, fname_visible), staticobjects_city_visible_merged)
  211.  
  212. def main():
  213.     logging.debug('logging level is DEBUG')
  214.  
  215.     root = 'D:\\Games\\Project Reality'
  216.     modPath = 'mods/pr_repo'
  217.     levelName = 'test_airfield'
  218.     game = bf2.Game(root)
  219.     game.loadMod(modPath)
  220.     game.loadLevel(levelName)
  221.  
  222.     fname_for_merge = 'staticobjects_testing.con'
  223.     fname_visible = 'staticobjects_visible.con'
  224.     fname_cols = 'staticobjects_cols.con'
  225.  
  226.     #staticobjects_city = getStaticObjects(os.path.join(root, modPath, 'levels', levelName, fname_for_merge))
  227.     staticobjects_city = game.level.getStaticObjects(os.path.join(game.level.path, fname_for_merge))
  228.  
  229.     objects2merge = {}
  230.     for staticobject in staticobjects_city:
  231.         if staticobject.name not in objects2merge: objects2merge[staticobject.name] = []
  232.         objects2merge[staticobject.name].append(staticobject)
  233.  
  234.     staticobjects_merged = []
  235.     for templateName in objects2merge:
  236.         staticobject_main = objects2merge[templateName][0]
  237.         for staticobject_secondary in objects2merge[templateName][1:]:
  238.             offset = staticobject_secondary.position - staticobject_main.position
  239.             staticobject_secondary.objectTemplate(game).geometry.mesh.translate(offset)
  240.             staticobject_main.objectTemplate(game).geometry.mesh.merge(staticobject_secondary.objectTemplate(game).geometry.mesh)
  241.         templateName_merged = '%s_merged' % templateName
  242.         export_path = os.path.join(game.root, game.mod.modPath, 'levels', game.level, 'objects', 'staticobjects', 'merged', templateName_merged, 'Meshes', '%s.staticmesh' % templateName_merged)
  243.         logging.info('exporting merged %s to %s' % (templateName, export_path))
  244.         #vmesh_main.export()
  245.         raise NotImplementedError
  246.         staticobject_main.name = templateName_merged
  247.         staticobjects_merged.append(staticobject_main)
  248.  
  249. if __name__ == '__main__':
  250.     loglevel=logging.INFO
  251.     FORMAT = '%(levelname)s:%(module)s:%(funcName)s:%(message)s'
  252.     logging.basicConfig(filename='merge.log',filemode='a',level=loglevel, format=FORMAT)
  253.     logging.getLogger().addHandler(logging.StreamHandler(sys.stdout))
  254.     #logging.basicConfig(level=loglevel, format=FORMAT)
  255.     #main()
  256.     main2()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement