Legend of the Gold Box... A game written for the LOWREZJAM 2018 game jam
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

177 lines
5.7KB

  1. import os, sys
  2. import logging
  3. import json
  4. import weakref
  5. import pygame
  6. from .resourceLoaders import *
  7. class ResourceError(Exception):
  8. pass
  9. _GAME_PATH=calculate_real_path(os.path.dirname(sys.argv[0]))
  10. def _BuildLogger():
  11. logger = logging.getLogger(__name__)
  12. logger.setLevel(logging.DEBUG)
  13. log_format = logging.Formatter("[%(levelname)s : %(asctime)s] %(message)s")
  14. log_handler = logging.FileHandler(join_path(_GAME_PATH, "logs/gbe.log"))
  15. log_handler.setFormatter(log_format)
  16. logger.addHandler(log_handler)
  17. return logger
  18. _l = _BuildLogger()
  19. _RESOURCES={}
  20. def define_resource_type(rtype, sub_path, loader_fn):
  21. global _RESOURCES, _GAME_PATH, join_path
  22. if rtype in _RESOURCES:
  23. _l.error("Resource '{}' already defined.".format(rtype))
  24. return
  25. fullpath = join_path(_GAME_PATH, sub_path)
  26. if not os.path.isdir(fullpath):
  27. _l.warning("'{}' is not a valid directory.".format(sub_path))
  28. if not callable(loader_fn):
  29. raise ResourceError("Expected a callable as the resource loader.")
  30. _RESOURCES[rtype]={"r":[], "loader":loader_fn, "path":fullpath}
  31. _l.info("Added resource type '{}' with search path '{}'.".format(rtype, sub_path))
  32. def configure(conf):
  33. global _RESOURCES, join_path
  34. if not isinstance(conf, dict):
  35. raise TypeError("Expected a dictionary.")
  36. for key in conf:
  37. if key in _RESOURCES:
  38. fullpath = join_path(_GAME_PATH, conf[key])
  39. if not os.path.isdir(fullpath):
  40. _l.warning("'{}' is not a valid directory.".format(conf[key]))
  41. _RESOURCES[key]["path"] = fullpath
  42. _RESOURCES[key]["r"] = [] # Completely drop old list.
  43. class ResourceManager:
  44. def __init__(self):
  45. pass
  46. @property
  47. def game_path(self):
  48. global _GAME_PATH
  49. return _GAME_PATH
  50. @property
  51. def resource_types(self):
  52. global _RESOURCES
  53. rtypes = []
  54. for key in _RESOURCES:
  55. rtypes.append(key)
  56. return rtypes
  57. def _getResourceDict(self, rtype, src):
  58. global _RESOURCES
  59. if rtype in _RESOURCES:
  60. for r in _RESOURCES[rtype]["r"]:
  61. if r["src"] == src:
  62. return r
  63. return None
  64. def is_valid(self, rtype, src):
  65. global _RESOURCES
  66. if rtype in _RESOURCES:
  67. return file_exists(join_path(_RESOURCES[rtype]["path"], src))
  68. return false
  69. def has(self, rtype, src):
  70. return (self._getResourceDict(rtype, src) is not None)
  71. def store(self, rtype, src):
  72. global _RESOURCES
  73. if rtype not in _RESOURCES:
  74. raise ResourceError("Unknown resource type '{}'.".format(rtype))
  75. if self._getResourceDict(rtype, src) == None:
  76. _RESOURCES[rtype]["r"].append({"src":src, "instance":None, "locked":False})
  77. return self
  78. def remove(self, rtype, src):
  79. global _RESOURCES
  80. d = self._getResourceDict(rtype, src)
  81. if d is None:
  82. raise ResourceError("No '{}' resource '{}' stored.".format(rtype, src))
  83. _RESOURCES[rtype]["r"].remove(d)
  84. return self
  85. def clear(self, rtype, src, ignore_lock=False):
  86. d = self._getResourceDict(rtype, src)
  87. if d is None:
  88. raise ResourceError("No '{}' resource '{}' stored.".format(rtype, src))
  89. if d["locked"] == False or ignore_lock == True:
  90. d["instance"] = None
  91. return self
  92. def get(self, rtype, src, params={}):
  93. global _RESOURCES
  94. if rtype not in _RESOURCES:
  95. raise ResourceError("Unknown resource type '{}'.".format(rtype))
  96. d = self._getResourceDict(rtype, src)
  97. if d is None:
  98. raise ResourceError("No '{}' resource '{}' stored.".format(rtype, src))
  99. if d["instance"] is None:
  100. loader = _RESOURCES[rtype]["loader"]
  101. filename = join_path(_RESOURCES[rtype]["path"], src)
  102. try:
  103. d["instance"] = loader(filename, params)
  104. except Exception as e:
  105. _l.error("{}".format(e))
  106. return None
  107. return weakref.ref(d["instance"])
  108. def lock(self, rtype, src, lock=True):
  109. d = self._getResourceDict(rtype, src)
  110. if d is None:
  111. raise ResourceError("No '{}' resource '{}' stored.".format(rtype, src))
  112. d["locked"]=lock
  113. return self
  114. def is_locked(self, rtype, src):
  115. d = self._getResourceDict(rtype, src)
  116. if d is not None and d["src"] == src:
  117. return d["locked"]
  118. return False
  119. def clear_resource_type(self, rtype, ignore_lock=False):
  120. global _RESOURCES
  121. if rtype in _RESOURCES:
  122. for r in _RESOURCES[rtype]["r"]:
  123. if r["locked"] == False or ignore_lock == True:
  124. r["instance"] = None
  125. return self
  126. def clear_resources(self, ignore_lock=False):
  127. global _RESOURCES
  128. for key in _RESOURCES:
  129. self.clear_resource_type(key, ignore_lock)
  130. return self
  131. def remove_resource_type(self, rtype):
  132. global _RESOURCES
  133. if rtype not in _RESOURCES:
  134. raise ResourceError("Unknown resource type '{}'.".format(rtype))
  135. _RESOURCES[rtype]["r"] = []
  136. return self
  137. def remove_resources(self):
  138. global _RESOURCES
  139. for key in _RESOURCES:
  140. _RESOURCES[key]["r"] = []
  141. return self
  142. # ---------------------------------------------------------------
  143. # Defining the built-in loaders located in resourceLoaders.py
  144. # ---------------------------------------------------------------
  145. define_resource_type("graphic", "graphics/", load_image)
  146. define_resource_type("audio", "audio/", load_audio)
  147. define_resource_type("json", "data/json/", load_JSON)
  148. define_resource_type("font", "fonts/", load_font)