ResourceSetterNew.gd 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. class_name ResourceSetterNew
  2. extends Node
  3. @export var node_to_affect: Node = null
  4. @export var property_node: Node = null
  5. @export var property_name := ""
  6. @export var mode: ResourceMode = ResourceMode.SPRITE_FRAMES
  7. @export var resource_json: JSON = null:
  8. set(value):
  9. resource_json = value
  10. update_resource()
  11. enum ResourceMode {SPRITE_FRAMES, TEXTURE, AUDIO, RAW}
  12. @export var use_cache := true
  13. static var cache := {}
  14. static var property_cache := {}
  15. var current_json_path := ""
  16. static var state := [0, 0]
  17. static var pack_configs := {}
  18. var config_to_use := {}
  19. var is_random := false
  20. signal updated
  21. @export var force_properties := {}
  22. var update_on_spawn := true
  23. func _init() -> void:
  24. set_process_mode(Node.PROCESS_MODE_ALWAYS)
  25. func _ready() -> void:
  26. safety_check()
  27. if update_on_spawn:
  28. update_resource()
  29. Global.level_time_changed.connect(update_resource)
  30. Global.level_theme_changed.connect(update_resource)
  31. func safety_check() -> void:
  32. if Settings.file.visuals.resource_packs.has("BaseAssets") == false:
  33. Settings.file.visuals.resource_packs.append("BaseAssets")
  34. func update_resource() -> void:
  35. randomize()
  36. if is_inside_tree() == false or is_queued_for_deletion() or resource_json == null or node_to_affect == null:
  37. return
  38. if state != [Global.level_theme, Global.theme_time]:
  39. cache.clear()
  40. property_cache.clear()
  41. if node_to_affect != null:
  42. var resource = get_resource(resource_json)
  43. node_to_affect.set(property_name, resource)
  44. if node_to_affect is AnimatedSprite2D:
  45. node_to_affect.play()
  46. state = [Global.level_theme, Global.theme_time]
  47. updated.emit()
  48. func get_resource(json_file: JSON) -> Resource:
  49. if cache.has(json_file.resource_path) and use_cache and force_properties.is_empty():
  50. if property_cache.has(json_file.resource_path):
  51. apply_properties(property_cache[json_file.resource_path])
  52. return cache[json_file.resource_path]
  53. var resource: Resource = null
  54. var resource_path = json_file.resource_path
  55. config_to_use = {}
  56. for i in Settings.file.visuals.resource_packs:
  57. resource_path = get_resource_pack_path(resource_path, i)
  58. var source_json = JSON.parse_string(FileAccess.open(resource_path, FileAccess.READ).get_as_text())
  59. if source_json == null:
  60. Global.log_error("Error parsing " + resource_path + "!")
  61. return
  62. var json = source_json.duplicate()
  63. var source_resource_path = ""
  64. if json.has("variations"):
  65. json = get_variation_json(json.variations)
  66. if json.has("source"):
  67. if json.get("source") is String:
  68. source_resource_path = json_file.resource_path.replace(json_file.resource_path.get_file(), json.source)
  69. else:
  70. Global.log_error("Error getting variations! " + resource_path)
  71. return
  72. for i in Settings.file.visuals.resource_packs:
  73. source_resource_path = get_resource_pack_path(source_resource_path, i)
  74. if json.has("rect"):
  75. resource = load_image_from_path(source_resource_path)
  76. var atlas = AtlasTexture.new()
  77. atlas.atlas = resource
  78. atlas.region = Rect2(json.rect[0], json.rect[1], json.rect[2], json.rect[3])
  79. resource = atlas
  80. if json.has("properties"):
  81. apply_properties(json.get("properties"))
  82. if use_cache:
  83. property_cache[json_file.resource_path] = json.properties.duplicate()
  84. elif source_json.has("properties"):
  85. apply_properties(source_json.get("properties"))
  86. if use_cache:
  87. property_cache[json_file.resource_path] = source_json.properties.duplicate()
  88. match mode:
  89. ResourceMode.SPRITE_FRAMES:
  90. var animation_json = {}
  91. if json.has("animations"):
  92. animation_json = json.get("animations")
  93. elif source_json.has("animations"):
  94. animation_json = source_json.get("animations")
  95. if animation_json != {}:
  96. resource = load_image_from_path(source_resource_path)
  97. if json.has("rect"):
  98. var atlas = AtlasTexture.new()
  99. atlas.atlas = resource
  100. atlas.region = Rect2(json.rect[0], json.rect[1], json.rect[2], json.rect[3])
  101. resource = atlas
  102. resource = create_sprite_frames_from_image(resource, animation_json)
  103. else:
  104. resource = load_image_from_path(source_resource_path)
  105. if json.has("rect"):
  106. var atlas = AtlasTexture.new()
  107. atlas.atlas = resource
  108. atlas.region = Rect2(json.rect[0], json.rect[1], json.rect[2], json.rect[3])
  109. resource = atlas
  110. var sprite_frames = SpriteFrames.new()
  111. sprite_frames.add_frame("default", resource)
  112. resource = sprite_frames
  113. ResourceMode.TEXTURE:
  114. if json.get("source") is Array:
  115. resource = AnimatedTexture.new()
  116. resource.frames = json.get("source").size()
  117. var idx := 0
  118. for i in json.get("source"):
  119. var frame_path = ResourceSetter.get_pure_resource_path(json_file.resource_path.replace(json_file.resource_path.get_file(), i))
  120. print(frame_path)
  121. resource.set_frame_texture(idx, load_image_from_path(frame_path))
  122. idx += 1
  123. else:
  124. resource = load_image_from_path(source_resource_path)
  125. if json.has("rect"):
  126. var rect = json.rect
  127. var atlas = AtlasTexture.new()
  128. atlas.atlas = resource
  129. atlas.region = Rect2(rect[0], rect[1], rect[2], rect[3])
  130. resource = atlas
  131. ResourceMode.AUDIO:
  132. resource = load_audio_from_path(source_resource_path)
  133. ResourceMode.RAW:
  134. pass
  135. if cache.has(json_file.resource_path) == false and use_cache and not is_random:
  136. cache[json_file.resource_path] = resource
  137. return resource
  138. func apply_properties(properties := {}) -> void:
  139. if property_node == null:
  140. return
  141. for i in properties.keys():
  142. property_node.set(i, properties[i])
  143. func get_variation_json(json := {}) -> Dictionary:
  144. var level_theme = Global.level_theme
  145. if force_properties.has("Theme"):
  146. level_theme = force_properties.Theme
  147. for i in json.keys().filter(func(key): return key.contains("config:")):
  148. if config_to_use != {}:
  149. var option_name = i.get_slice(":", 1)
  150. if config_to_use.options.has(option_name):
  151. json = get_variation_json(json[i][config_to_use.options[option_name]])
  152. break
  153. if json.has(level_theme) == false:
  154. level_theme = "default"
  155. if json.has(level_theme):
  156. if json.get(level_theme).has("link"):
  157. json = get_variation_json(json[json.get(level_theme).get("link")])
  158. else:
  159. json = get_variation_json(json[level_theme])
  160. var level_time = Global.theme_time
  161. if force_properties.has("Time"):
  162. level_time = force_properties.Time
  163. if json.has(level_time):
  164. json = get_variation_json(json[level_time])
  165. var campaign = Global.current_campaign
  166. if force_properties.has("Campaign"):
  167. is_random = true
  168. campaign = force_properties.Campaign
  169. if json.has(campaign) == false:
  170. campaign = "SMB1"
  171. if json.has(campaign):
  172. if json.get(campaign).has("link"):
  173. json = get_variation_json(json[json.get(campaign).get("link")])
  174. else:
  175. json = get_variation_json(json[campaign])
  176. if json.has("choices"):
  177. is_random = true
  178. json = get_variation_json(json.choices.pick_random())
  179. var world = "World" + str(Global.world_num)
  180. if force_properties.has("World"):
  181. is_random = true
  182. world = "World" + str(force_properties.World)
  183. print(world)
  184. if json.has(world) == false:
  185. world = "World1"
  186. if json.has(world):
  187. if json.get(world).has("link"):
  188. json = get_variation_json(json[json.get(world).get("link")])
  189. else:
  190. json = get_variation_json(json[world])
  191. var level_string = "Level" + str(Global.level_num)
  192. if json.has(level_string) == false:
  193. level_string = "Level1"
  194. if json.has(level_string):
  195. if json.get(level_string).has("link"):
  196. json = get_variation_json(json[json.get(level_string).get("link")])
  197. else:
  198. json = get_variation_json(json[level_string])
  199. var game_mode = "GameMode:" + Global.game_mode_strings[Global.current_game_mode]
  200. if json.has(game_mode) == false:
  201. game_mode = "GameMode:" + Global.game_mode_strings[0]
  202. if json.has(game_mode):
  203. if json.get(game_mode).has("link"):
  204. json = get_variation_json(json[json.get(game_mode).get("link")])
  205. else:
  206. json = get_variation_json(json[game_mode])
  207. var chara = "Character:" + Player.CHARACTERS[int(Global.player_characters[0])]
  208. if json.has(chara) == false:
  209. chara = "Character:Mario"
  210. if json.has(chara):
  211. if json.get(chara).has("link"):
  212. json = get_variation_json(json[json.get(chara).get("link")])
  213. else:
  214. json = get_variation_json(json[chara])
  215. var boo = "RaceBoo:" + str(BooRaceHandler.boo_colour)
  216. if json.has(boo) == false:
  217. boo = "RaceBoo:0"
  218. if force_properties.has("RaceBoo"):
  219. boo = "RaceBoo:" + str(force_properties["RaceBoo"])
  220. if json.has(boo):
  221. if json.get(boo).has("link"):
  222. json = get_variation_json(json[json.get(boo).get("link")])
  223. else:
  224. json = get_variation_json(json[boo])
  225. return json
  226. func get_resource_pack_path(res_path := "", resource_pack := "") -> String:
  227. var user_path := res_path.replace("res://Assets", "user://resource_packs/" + resource_pack)
  228. user_path = user_path.replace("user://custom_characters/", "user://resource_packs/" + resource_pack + "/Sprites/Players/CustomCharacters/")
  229. if FileAccess.file_exists(user_path):
  230. if FileAccess.file_exists("user://resource_packs/" + resource_pack + "/config.json"):
  231. config_to_use = JSON.parse_string(FileAccess.open("user://resource_packs/" + resource_pack + "/config.json", FileAccess.READ).get_as_text())
  232. if config_to_use == null:
  233. Global.log_error("Error parsing Config File! (" + resource_pack + ")")
  234. config_to_use = {}
  235. return user_path
  236. else:
  237. return res_path
  238. func create_sprite_frames_from_image(image: Resource, animation_json := {}) -> SpriteFrames:
  239. var sprite_frames = SpriteFrames.new()
  240. sprite_frames.remove_animation("default")
  241. for anim_name in animation_json.keys():
  242. sprite_frames.add_animation(anim_name)
  243. for frame in animation_json[anim_name].frames:
  244. var frame_texture = AtlasTexture.new()
  245. frame_texture.atlas = image
  246. frame_texture.region = Rect2(frame[0], frame[1], frame[2], frame[3])
  247. frame_texture.filter_clip = true
  248. sprite_frames.add_frame(anim_name, frame_texture)
  249. sprite_frames.set_animation_loop(anim_name, animation_json[anim_name].loop)
  250. sprite_frames.set_animation_speed(anim_name, animation_json[anim_name].speed)
  251. return sprite_frames
  252. func clear_cache() -> void:
  253. for i in cache.keys():
  254. if cache[i] == null:
  255. cache.erase(i)
  256. cache.clear()
  257. property_cache.clear()
  258. func load_image_from_path(path := "") -> ImageTexture:
  259. if path.contains("res://"):
  260. if path.contains("NULL"):
  261. return null
  262. return load(path)
  263. var image = Image.new()
  264. if path == "":
  265. print([path, owner.name])
  266. image.load(path)
  267. return ImageTexture.create_from_image(image)
  268. func load_audio_from_path(path := "") -> AudioStream:
  269. var stream = null
  270. if path.contains("res://"):
  271. return load(path)
  272. if path.contains(".wav"):
  273. stream = AudioStreamWAV.load_from_file(path)
  274. elif path.contains(".mp3"):
  275. stream = AudioStreamMP3.load_from_file(path)
  276. return stream