middleware.py 5.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. # coding: utf-8
  2. import os
  3. import tempfile
  4. import typing
  5. from xml.etree import ElementTree
  6. from xml.etree.ElementTree import Element
  7. from synergine2.config import Config
  8. from synergine2.log import get_logger
  9. from synergine2_cocos2d.util import get_map_file_path_from_dir
  10. if typing.TYPE_CHECKING:
  11. import cocos
  12. from cocos.tiles import Resource
  13. class MapLoader(object):
  14. def load(self, map_file_path: str) -> 'Resource':
  15. # import cocos here for prevent test crash when no X server is
  16. # present
  17. import cocos
  18. tree = ElementTree.parse(map_file_path)
  19. map_element = tree.getroot()
  20. final_map_content = self.get_sanitized_map_content(map_element, map_file_path)
  21. new_file = tempfile.NamedTemporaryFile(mode='w+', suffix='.tmx', delete=False)
  22. new_file.write(final_map_content)
  23. new_file.seek(0)
  24. # return the map
  25. return cocos.tiles.load(new_file.name)
  26. def get_sanitized_map_content(
  27. self,
  28. map_element: Element,
  29. map_file_path: str,
  30. ) -> str:
  31. # Parse tileset to modify path if required
  32. for tileset_tag in map_element.findall('tileset'):
  33. if 'source' in tileset_tag.attrib:
  34. tileset_path = tileset_tag.attrib['source']
  35. if not os.path.exists(tileset_path):
  36. # try with map file relative path
  37. map_dir = os.path.dirname(map_file_path)
  38. new_path = os.path.join(map_dir, tileset_path)
  39. if os.path.exists(new_path):
  40. # It is the correct path, update it
  41. tileset_new_content = self.get_sanitized_tileset_content(
  42. new_path,
  43. )
  44. new_file = tempfile.NamedTemporaryFile(
  45. mode='w+',
  46. suffix='.tsx',
  47. delete=False,
  48. )
  49. new_file.write(tileset_new_content)
  50. new_file.seek(0)
  51. tileset_tag.attrib['source'] = new_file.name
  52. # Write new file in temporary dir
  53. map_xml_str = ElementTree.tostring(
  54. map_element,
  55. encoding='utf8',
  56. method='xml',
  57. )
  58. return map_xml_str.decode('utf-8')
  59. def get_sanitized_tileset_content(
  60. self,
  61. tileset_path: str,
  62. ) -> str:
  63. tileset_dir = os.path.dirname(tileset_path)
  64. tree = ElementTree.parse(tileset_path)
  65. tileset_element = tree.getroot()
  66. image_node = tileset_element.find('image')
  67. image_path = image_node.attrib['source']
  68. final_image_path = os.path.join(tileset_dir, image_path)
  69. image_node.attrib['source'] = final_image_path
  70. tileset_xml_str = ElementTree.tostring(
  71. tileset_element,
  72. encoding='utf8',
  73. method='xml',
  74. )
  75. return tileset_xml_str.decode('utf-8')
  76. class MapMiddleware(object):
  77. def __init__(
  78. self,
  79. config: Config,
  80. map_dir_path: str,
  81. ) -> None:
  82. self.config = config
  83. self.logger = get_logger(self.__class__.__name__, config)
  84. self.map_dir_path = map_dir_path
  85. self.tmx = None
  86. def get_map_file_path(self) -> str:
  87. return get_map_file_path_from_dir(self.map_dir_path)
  88. def init(self) -> None:
  89. # import cocos here for prevent test crash when no X server is
  90. # present
  91. import cocos
  92. map_file_path = self.get_map_file_path()
  93. loader = MapLoader()
  94. self.tmx = loader.load(map_file_path)
  95. def get_background_sprite(self) -> 'cocos.sprite.Sprite':
  96. raise NotImplementedError()
  97. def get_ground_layer(self) -> 'cocos.tiles.RectMapLayer':
  98. raise NotImplementedError()
  99. def get_top_layer(self) -> 'cocos.tiles.RectMapLayer':
  100. raise NotImplementedError()
  101. def get_world_height(self) -> int:
  102. raise NotImplementedError()
  103. def get_world_width(self) -> int:
  104. raise NotImplementedError()
  105. def get_cell_height(self) -> int:
  106. raise NotImplementedError()
  107. def get_cell_width(self) -> int:
  108. raise NotImplementedError()
  109. class TMXMiddleware(MapMiddleware):
  110. def get_background_sprite(self) -> 'cocos.sprite.Sprite':
  111. # TODO: Extract it from tmx
  112. import cocos
  113. return cocos.sprite.Sprite(os.path.join(
  114. self.map_dir_path,
  115. 'background.png',
  116. ))
  117. def get_interior_sprite(self) -> 'cocos.sprite.Sprite':
  118. # TODO: Extract it from tmx
  119. import cocos
  120. return cocos.sprite.Sprite(os.path.join(
  121. self.map_dir_path,
  122. 'background_interiors.png',
  123. ))
  124. def get_ground_layer(self) -> 'cocos.tiles.RectMapLayer':
  125. assert self.tmx
  126. return self.tmx['ground']
  127. def get_top_layer(self) -> 'cocos.tiles.RectMapLayer':
  128. assert self.tmx
  129. return self.tmx['top']
  130. def get_world_height(self) -> int:
  131. return len(self.tmx['ground'].cells[0])
  132. def get_world_width(self) -> int:
  133. return len(self.tmx['ground'].cells)
  134. def get_cell_height(self) -> int:
  135. return self.tmx['ground'].cells[0][0].size[1]
  136. def get_cell_width(self) -> int:
  137. return self.tmx['ground'].cells[0][0].size[0]