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.

172 lines
5.5KB

  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 has(self, rtype, src):
  65. return (self._getResourceDict(rtype, src) is not None)
  66. def store(self, rtype, src):
  67. global _RESOURCES
  68. if type not in _RESOURCES:
  69. raise ResourceError("Unknown resource type '{}'.".format(rtype))
  70. if self._getResourceDict(rtype, src) == None:
  71. _RESOURCES[rtype]["r"].append({"src":src, "instance":None, "locked":False})
  72. return self
  73. def remove(self, rtype, src):
  74. global _RESOURCES
  75. d = self._getResourceDict(rtype, src)
  76. if d is None:
  77. raise ResourceError("No '{}' resource '{}' stored.".format(rtype, src))
  78. _RESOURCES[rtype]["r"].remove(d)
  79. return self
  80. def clear(self, rtype, src, ignore_lock):
  81. d = self._getResourceDict(rtype, src)
  82. if d is None:
  83. raise ResourceError("No '{}' resource '{}' stored.".format(rtype, src))
  84. if d["locked"] == False or ignore_lock == True:
  85. d["instance"] = None
  86. return self
  87. def get(self, rtype, src):
  88. global _RESOURCES
  89. if rtype not in _RESOURCES:
  90. raise ResourceError("Unknown resource type '{}'.".format(rtype))
  91. d = self._getResourceDict(rtype, src)
  92. if d is None:
  93. raise ResourceError("No '{}' resource '{}' stored.".format(rtype, src))
  94. if d["instance"] is None:
  95. loader = _RESOURCES[rtype]["loader"]
  96. filename = join_path(self.data_path, src)
  97. try:
  98. d["instance"] = loader(filename)
  99. except Exception as e:
  100. _l.error(e.message)
  101. return None
  102. return weakref.ref(d["instance"])
  103. def lock(self, rtype, src, lock=True):
  104. d = self._getResourceDict(rtype, src)
  105. if d is None:
  106. raise ResourceError("No '{}' resource '{}' stored.".format(rtype, src))
  107. d["locked"]=lock
  108. return self
  109. def is_locked(self, rtype, src):
  110. d = self._getResourceDict(rtype, src)
  111. if d is not None and d["src"] == src:
  112. return d["locked"]
  113. return False
  114. def clear_resource_type(self, rtype, ignore_lock=False):
  115. global _RESOURCES
  116. if rtype in _RESOURCES:
  117. for r in _RESOURCES[rtype]["r"]:
  118. if r["locked"] == False or ignore_lock == True:
  119. r["instance"] = None
  120. return self
  121. def clear_resources(self, ignore_lock=False):
  122. global _RESOURCES
  123. for key in _RESOURCES:
  124. self.clear_resource_type(key, ignore_lock)
  125. return self
  126. def remove_resource_type(self, rtype):
  127. global _RESOURCES
  128. if rtype not in _RESOURCES:
  129. raise ResourceError("Unknown resource type '{}'.".format(rtype))
  130. _RESOURCES[rtype]["r"] = []
  131. return self
  132. def remove_resources(self):
  133. global _RESOURCES
  134. for key in _RESOURCES:
  135. _RESOURCES[key]["r"] = []
  136. return self
  137. # ---------------------------------------------------------------
  138. # Defining the built-in loaders located in resourceLoaders.py
  139. # ---------------------------------------------------------------
  140. define_resource_type("graphic", "graphics/", load_image)
  141. define_resource_type("audio", "audio/", load_audio)
  142. define_resource_type("json", "data/json/", load_JSON)