package_resource.cpp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. /*
  2. * Copyright (c) 2012-2021 Daniele Bartolini et al.
  3. * License: https://github.com/dbartolini/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. HashMap<DynamicString, u32> reqs_deffault(default_allocator());
  79. 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. {
  84. HASH_MAP_SKIP_HOLE(reqs, cur);
  85. const char* req_filename = cur->first.c_str();
  86. const char* req_type = resource_type(req_filename);
  87. const u32 req_name_len = resource_name_length(req_type, req_filename);
  88. const StringId64 req_type_hash(req_type);
  89. const StringId64 req_name_hash(req_filename, req_name_len);
  90. hash_set::insert(output, PackageResource::Resource(req_type_hash, req_name_hash));
  91. bring_in_requirements(output, opts, resource_id(req_type_hash, req_name_hash));
  92. }
  93. return 0;
  94. }
  95. s32 compile_resources(HashSet<PackageResource::Resource>& output, CompileOptions& opts, const char* type, const JsonArray& names)
  96. {
  97. const StringId64 type_hash = StringId64(type);
  98. for (u32 i = 0; i < array::size(names); ++i)
  99. {
  100. TempAllocator256 ta;
  101. DynamicString name(ta);
  102. sjson::parse_string(name, names[i]);
  103. DATA_COMPILER_ASSERT_RESOURCE_EXISTS(type, name.c_str(), opts);
  104. name += ".";
  105. name += type;
  106. opts.fake_read(name.c_str());
  107. const StringId64 name_hash = sjson::parse_resource_name(names[i]);
  108. hash_set::insert(output, PackageResource::Resource(type_hash, name_hash));
  109. // Bring in requirements
  110. bring_in_requirements(output, opts, resource_id(type_hash, name_hash));
  111. }
  112. return 0;
  113. }
  114. s32 compile(CompileOptions& opts)
  115. {
  116. TempAllocator4096 ta;
  117. JsonObject obj(ta);
  118. JsonArray texture(ta);
  119. JsonArray script(ta);
  120. JsonArray sound(ta);
  121. JsonArray mesh(ta);
  122. JsonArray unit(ta);
  123. JsonArray sprite(ta);
  124. JsonArray material(ta);
  125. JsonArray font(ta);
  126. JsonArray level(ta);
  127. JsonArray phyconf(ta);
  128. JsonArray shader(ta);
  129. JsonArray sprite_animation(ta);
  130. Array<PackageResource::Resource> resources(default_allocator());
  131. HashSet<PackageResource::Resource> resources_set(default_allocator());
  132. Buffer buf = opts.read();
  133. sjson::parse(obj, buf);
  134. if (json_object::has(obj, "texture")) sjson::parse_array(texture, obj["texture"]);
  135. if (json_object::has(obj, "lua")) sjson::parse_array(script, obj["lua"]);
  136. if (json_object::has(obj, "sound")) sjson::parse_array(sound, obj["sound"]);
  137. if (json_object::has(obj, "mesh")) sjson::parse_array(mesh, obj["mesh"]);
  138. if (json_object::has(obj, "unit")) sjson::parse_array(unit, obj["unit"]);
  139. if (json_object::has(obj, "sprite")) sjson::parse_array(sprite, obj["sprite"]);
  140. if (json_object::has(obj, "material")) sjson::parse_array(material, obj["material"]);
  141. if (json_object::has(obj, "font")) sjson::parse_array(font, obj["font"]);
  142. if (json_object::has(obj, "level")) sjson::parse_array(level, obj["level"]);
  143. if (json_object::has(obj, "physics_config")) sjson::parse_array(phyconf, obj["physics_config"]);
  144. if (json_object::has(obj, "shader")) sjson::parse_array(shader, obj["shader"]);
  145. if (json_object::has(obj, "sprite_animation")) sjson::parse_array(sprite_animation, obj["sprite_animation"]);
  146. s32 err = 0;
  147. err = compile_resources(resources_set, opts, "texture", texture);
  148. DATA_COMPILER_ENSURE(err == 0, opts);
  149. err = compile_resources(resources_set, opts, "lua", script);
  150. DATA_COMPILER_ENSURE(err == 0, opts);
  151. err = compile_resources(resources_set, opts, "sound", sound);
  152. DATA_COMPILER_ENSURE(err == 0, opts);
  153. err = compile_resources(resources_set, opts, "mesh", mesh);
  154. DATA_COMPILER_ENSURE(err == 0, opts);
  155. err = compile_resources(resources_set, opts, "unit", unit);
  156. DATA_COMPILER_ENSURE(err == 0, opts);
  157. err = compile_resources(resources_set, opts, "sprite", sprite);
  158. DATA_COMPILER_ENSURE(err == 0, opts);
  159. err = compile_resources(resources_set, opts, "material", material);
  160. DATA_COMPILER_ENSURE(err == 0, opts);
  161. err = compile_resources(resources_set, opts, "font", font);
  162. DATA_COMPILER_ENSURE(err == 0, opts);
  163. err = compile_resources(resources_set, opts, "level", level);
  164. DATA_COMPILER_ENSURE(err == 0, opts);
  165. err = compile_resources(resources_set, opts, "physics_config", phyconf);
  166. DATA_COMPILER_ENSURE(err == 0, opts);
  167. err = compile_resources(resources_set, opts, "shader", shader);
  168. DATA_COMPILER_ENSURE(err == 0, opts);
  169. err = compile_resources(resources_set, opts, "sprite_animation", sprite_animation);
  170. DATA_COMPILER_ENSURE(err == 0, opts);
  171. // Generate resource list
  172. auto cur = hash_set::begin(resources_set);
  173. auto end = hash_set::end(resources_set);
  174. for (; cur != end; ++cur)
  175. {
  176. HASH_SET_SKIP_HOLE(resources_set, cur);
  177. array::push_back(resources, *cur);
  178. }
  179. // Write
  180. opts.write(RESOURCE_HEADER(RESOURCE_VERSION_PACKAGE));
  181. opts.write(array::size(resources));
  182. for (u32 i = 0; i < array::size(resources); ++i)
  183. {
  184. opts.write(resources[i].type);
  185. opts.write(resources[i].name);
  186. }
  187. return 0;
  188. }
  189. } // namespace package_resource_internal
  190. #endif // CROWN_CAN_COMPILE
  191. } // namespace crown