SHARE
TWEET

merge_city.py

rPoXoTauJIo Sep 27th, 2019 102 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  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()
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top