package_resource.cpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. /*
  2. * Copyright (c) 2012-2022 Daniele Bartolini et al.
  3. * License: https://github.com/crownengine/crown/blob/master/LICENSE
  4. */
  5. #include "config.h"
  6. #include "core/containers/array.inl"
  7. #include "core/containers/hash_map.inl"
  8. #include "core/containers/hash_set.inl"
  9. #include "core/filesystem/file.h"
  10. #include "core/filesystem/filesystem.h"
  11. #include "core/filesystem/reader_writer.inl"
  12. #include "core/json/json_object.inl"
  13. #include "core/json/sjson.h"
  14. #include "core/memory/temp_allocator.inl"
  15. #include "core/strings/dynamic_string.inl"
  16. #include "core/strings/string_id.inl"
  17. #include "resource/compile_options.inl"
  18. #include "resource/data_compiler.h"
  19. #include "resource/package_resource.h"
  20. #include "resource/resource_id.inl"
  21. namespace crown
  22. {
  23. template<>
  24. struct hash<PackageResource::Resource>
  25. {
  26. u32 operator()(const PackageResource::Resource &val) const
  27. {
  28. return (u32)resource_id(val.type, val.name)._id;
  29. }
  30. };
  31. PackageResource::Resource::Resource()
  32. {
  33. }
  34. PackageResource::Resource::Resource(StringId64 t, StringId64 n)
  35. : type(t)
  36. , name(n)
  37. {
  38. }
  39. bool operator<(const PackageResource::Resource &a, const PackageResource::Resource &b)
  40. {
  41. return a.type < b.type;
  42. }
  43. bool operator==(const PackageResource::Resource &a, const PackageResource::Resource &b)
  44. {
  45. return a.type == b.type
  46. && a.name == b.name
  47. ;
  48. }
  49. PackageResource::PackageResource(Allocator &a)
  50. : resources(a)
  51. {
  52. }
  53. namespace package_resource_internal
  54. {
  55. void *load(File &file, Allocator &a)
  56. {
  57. BinaryReader br(file);
  58. u32 version;
  59. br.read(version);
  60. CE_ASSERT(version == RESOURCE_HEADER(RESOURCE_VERSION_PACKAGE), "Wrong version");
  61. u32 num_resources;
  62. br.read(num_resources);
  63. PackageResource *pr = CE_NEW(a, PackageResource)(a);
  64. array::resize(pr->resources, num_resources);
  65. br.read(array::begin(pr->resources), sizeof(PackageResource::Resource)*num_resources);
  66. return pr;
  67. }
  68. void unload(Allocator &a, void *resource)
  69. {
  70. CE_DELETE(a, (PackageResource *)resource);
  71. }
  72. } // namespace package_resource_internal
  73. #if CROWN_CAN_COMPILE
  74. namespace package_resource_internal
  75. {
  76. s32 bring_in_requirements(HashSet<PackageResource::Resource> &output, CompileOptions &opts, ResourceId res_id)
  77. {
  78. const HashMap<DynamicString, u32> reqs_deffault(default_allocator());
  79. const HashMap<DynamicString, u32> &reqs = hash_map::get(opts._data_compiler._data_requirements, res_id, reqs_deffault);
  80. auto cur = hash_map::begin(reqs);
  81. auto end = hash_map::end(reqs);
  82. for (; cur != end; ++cur) {
  83. HASH_MAP_SKIP_HOLE(reqs, cur);
  84. const char *req_filename = cur->first.c_str();
  85. const char *req_type = resource_type(req_filename);
  86. const u32 req_name_len = resource_name_length(req_type, req_filename);
  87. const StringId64 req_type_hash(req_type);
  88. const StringId64 req_name_hash(req_filename, req_name_len);
  89. hash_set::insert(output, PackageResource::Resource(req_type_hash, req_name_hash));
  90. bring_in_requirements(output, opts, resource_id(req_type_hash, req_name_hash));
  91. }
  92. return 0;
  93. }
  94. s32 compile_resources(HashSet<PackageResource::Resource> &output, CompileOptions &opts, const char *type, const JsonArray &names)
  95. {
  96. const StringId64 type_hash = StringId64(type);
  97. for (u32 i = 0; i < array::size(names); ++i) {
  98. TempAllocator256 ta;
  99. DynamicString name(ta);
  100. sjson::parse_string(name, names[i]);
  101. DATA_COMPILER_ASSERT_RESOURCE_EXISTS(type, name.c_str(), opts);
  102. name += ".";
  103. name += type;
  104. opts.fake_read(name.c_str());
  105. const StringId64 name_hash = sjson::parse_resource_name(names[i]);
  106. hash_set::insert(output, PackageResource::Resource(type_hash, name_hash));
  107. // Bring in requirements
  108. bring_in_requirements(output, opts, resource_id(type_hash, name_hash));
  109. }
  110. return 0;
  111. }
  112. s32 compile(CompileOptions &opts)
  113. {
  114. TempAllocator4096 ta;
  115. JsonObject obj(ta);
  116. JsonArray texture(ta);
  117. JsonArray script(ta);
  118. JsonArray sound(ta);
  119. JsonArray mesh(ta);
  120. JsonArray unit(ta);
  121. JsonArray sprite(ta);
  122. JsonArray material(ta);
  123. JsonArray font(ta);
  124. JsonArray level(ta);
  125. JsonArray phyconf(ta);
  126. JsonArray shader(ta);
  127. JsonArray sprite_animation(ta);
  128. Array<PackageResource::Resource> resources(default_allocator());
  129. HashSet<PackageResource::Resource> resources_set(default_allocator());
  130. Buffer buf = opts.read();
  131. sjson::parse(obj, buf);
  132. if (json_object::has(obj, "texture"))
  133. sjson::parse_array(texture, obj["texture"]);
  134. if (json_object::has(obj, "lua"))
  135. sjson::parse_array(script, obj["lua"]);
  136. if (json_object::has(obj, "sound"))
  137. sjson::parse_array(sound, obj["sound"]);
  138. if (json_object::has(obj, "mesh"))
  139. sjson::parse_array(mesh, obj["mesh"]);
  140. if (json_object::has(obj, "unit"))
  141. sjson::parse_array(unit, obj["unit"]);
  142. if (json_object::has(obj, "sprite"))
  143. sjson::parse_array(sprite, obj["sprite"]);
  144. if (json_object::has(obj, "material"))
  145. sjson::parse_array(material, obj["material"]);
  146. if (json_object::has(obj, "font"))
  147. sjson::parse_array(font, obj["font"]);
  148. if (json_object::has(obj, "level"))
  149. sjson::parse_array(level, obj["level"]);
  150. if (json_object::has(obj, "physics_config"))
  151. sjson::parse_array(phyconf, obj["physics_config"]);
  152. if (json_object::has(obj, "shader"))
  153. sjson::parse_array(shader, obj["shader"]);
  154. if (json_object::has(obj, "sprite_animation"))
  155. sjson::parse_array(sprite_animation, obj["sprite_animation"]);
  156. s32 err = 0;
  157. err = compile_resources(resources_set, opts, "texture", texture);
  158. DATA_COMPILER_ENSURE(err == 0, opts);
  159. err = compile_resources(resources_set, opts, "lua", script);
  160. DATA_COMPILER_ENSURE(err == 0, opts);
  161. err = compile_resources(resources_set, opts, "sound", sound);
  162. DATA_COMPILER_ENSURE(err == 0, opts);
  163. err = compile_resources(resources_set, opts, "mesh", mesh);
  164. DATA_COMPILER_ENSURE(err == 0, opts);
  165. err = compile_resources(resources_set, opts, "unit", unit);
  166. DATA_COMPILER_ENSURE(err == 0, opts);
  167. err = compile_resources(resources_set, opts, "sprite", sprite);
  168. DATA_COMPILER_ENSURE(err == 0, opts);
  169. err = compile_resources(resources_set, opts, "material", material);
  170. DATA_COMPILER_ENSURE(err == 0, opts);
  171. err = compile_resources(resources_set, opts, "font", font);
  172. DATA_COMPILER_ENSURE(err == 0, opts);
  173. err = compile_resources(resources_set, opts, "level", level);
  174. DATA_COMPILER_ENSURE(err == 0, opts);
  175. err = compile_resources(resources_set, opts, "physics_config", phyconf);
  176. DATA_COMPILER_ENSURE(err == 0, opts);
  177. err = compile_resources(resources_set, opts, "shader", shader);
  178. DATA_COMPILER_ENSURE(err == 0, opts);
  179. err = compile_resources(resources_set, opts, "sprite_animation", sprite_animation);
  180. DATA_COMPILER_ENSURE(err == 0, opts);
  181. // Generate resource list
  182. auto cur = hash_set::begin(resources_set);
  183. auto end = hash_set::end(resources_set);
  184. for (; cur != end; ++cur) {
  185. HASH_SET_SKIP_HOLE(resources_set, cur);
  186. array::push_back(resources, *cur);
  187. }
  188. // Write
  189. opts.write(RESOURCE_HEADER(RESOURCE_VERSION_PACKAGE));
  190. opts.write(array::size(resources));
  191. for (u32 i = 0; i < array::size(resources); ++i) {
  192. opts.write(resources[i].type);
  193. opts.write(resources[i].name);
  194. }
  195. return 0;
  196. }
  197. } // namespace package_resource_internal
  198. #endif // if CROWN_CAN_COMPILE
  199. } // namespace crown