export_arm.ts 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483
  1. function export_arm_run_mesh(path: string, paint_objects: mesh_object_t[]) {
  2. let mesh_datas: mesh_data_t[] = [];
  3. for (let i: i32 = 0; i < paint_objects.length; ++i) {
  4. let p: mesh_object_t = paint_objects[i];
  5. array_push(mesh_datas, p.data);
  6. }
  7. let raw: scene_t = {mesh_datas : mesh_datas};
  8. let b: buffer_t = util_encode_scene(raw);
  9. if (!ends_with(path, ".arm")) {
  10. path += ".arm";
  11. }
  12. iron_file_save_bytes(path, b, b.length + 1);
  13. }
  14. function export_arm_run_project() {
  15. let mnodes: ui_node_canvas_t[] = [];
  16. for (let i: i32 = 0; i < project_materials.length; ++i) {
  17. let m: slot_material_t = project_materials[i];
  18. let c: ui_node_canvas_t = util_clone_canvas(m.canvas);
  19. for (let i: i32 = 0; i < c.nodes.length; ++i) {
  20. let n: ui_node_t = c.nodes[i];
  21. export_arm_export_node(n);
  22. }
  23. array_push(mnodes, c);
  24. }
  25. let bnodes: ui_node_canvas_t[] = [];
  26. for (let i: i32 = 0; i < project_brushes.length; ++i) {
  27. let b: slot_brush_t = project_brushes[i];
  28. let c: ui_node_canvas_t = util_clone_canvas(b.canvas);
  29. for (let i: i32 = 0; i < c.nodes.length; ++i) {
  30. let n: ui_node_t = c.nodes[i];
  31. export_arm_export_node(n);
  32. }
  33. array_push(bnodes, c);
  34. }
  35. let mgroups: ui_node_canvas_t[] = null;
  36. if (project_material_groups.length > 0) {
  37. mgroups = [];
  38. for (let i: i32 = 0; i < project_material_groups.length; ++i) {
  39. let g: node_group_t = project_material_groups[i];
  40. let c: ui_node_canvas_t = util_clone_canvas(g.canvas);
  41. for (let i: i32 = 0; i < c.nodes.length; ++i) {
  42. let n: ui_node_t = c.nodes[i];
  43. export_arm_export_node(n);
  44. }
  45. array_push(mgroups, c);
  46. }
  47. }
  48. let md: mesh_data_t[] = [];
  49. for (let i: i32 = 0; i < project_paint_objects.length; ++i) {
  50. let p: mesh_object_t = project_paint_objects[i];
  51. array_push(md, p.data);
  52. }
  53. let texture_files: string[] = export_arm_assets_to_files(project_filepath, project_assets);
  54. let font_files: string[] = export_arm_fonts_to_files(project_filepath, project_fonts);
  55. let mesh_files: string[] = export_arm_meshes_to_files(project_filepath);
  56. let bits_pos: i32 = base_bits_handle.i;
  57. let bpp: i32 = bits_pos == texture_bits_t.BITS8 ? 8 : bits_pos == texture_bits_t.BITS16 ? 16 : 32;
  58. let ld: layer_data_t[] = [];
  59. for (let i: i32 = 0; i < project_layers.length; ++i) {
  60. let l: slot_layer_t = project_layers[i];
  61. let d: layer_data_t = {
  62. name : l.name,
  63. res : l.texpaint != null ? l.texpaint.width : project_layers[0].texpaint.width,
  64. bpp : bpp,
  65. texpaint : l.texpaint != null ? lz4_encode(gpu_get_texture_pixels(l.texpaint)) : null,
  66. uv_scale : l.scale,
  67. uv_rot : l.angle,
  68. uv_type : l.uv_type,
  69. uv_map : l.uv_map,
  70. decal_mat : l.uv_type == uv_type_t.PROJECT ? mat4_to_f32_array(l.decal_mat) : null,
  71. opacity_mask : l.mask_opacity,
  72. fill_layer : l.fill_layer != null ? array_index_of(project_materials, l.fill_layer) : -1,
  73. object_mask : l.object_mask,
  74. blending : l.blending,
  75. parent : l.parent != null ? array_index_of(project_layers, l.parent) : -1,
  76. visible : l.visible,
  77. texpaint_nor : l.texpaint_nor != null ? lz4_encode(gpu_get_texture_pixels(l.texpaint_nor)) : null,
  78. texpaint_pack : l.texpaint_pack != null ? lz4_encode(gpu_get_texture_pixels(l.texpaint_pack)) : null,
  79. paint_base : l.paint_base,
  80. paint_opac : l.paint_opac,
  81. paint_occ : l.paint_occ,
  82. paint_rough : l.paint_rough,
  83. paint_met : l.paint_met,
  84. paint_nor : l.paint_nor,
  85. paint_nor_blend : l.paint_nor_blend,
  86. paint_height : l.paint_height,
  87. paint_height_blend : l.paint_height_blend,
  88. paint_emis : l.paint_emis,
  89. paint_subs : l.paint_subs
  90. };
  91. array_push(ld, d);
  92. }
  93. let packed_assets: packed_asset_t[] = (project_raw.packed_assets == null || project_raw.packed_assets.length == 0) ? null : project_raw.packed_assets;
  94. /// if arm_ios
  95. let same_drive: bool = false;
  96. /// else
  97. let same_drive: bool = project_raw.envmap != null ? char_at(project_filepath, 0) == char_at(project_raw.envmap, 0) : true;
  98. /// end
  99. project_raw.version = manifest_version_project;
  100. project_raw.material_groups = mgroups;
  101. project_raw.assets = texture_files;
  102. project_raw.packed_assets = packed_assets;
  103. project_raw.swatches = project_raw.swatches;
  104. project_raw.envmap = project_raw.envmap != null ? (same_drive ? path_to_relative(project_filepath, project_raw.envmap) : project_raw.envmap) : null;
  105. project_raw.envmap_strength = scene_world.strength;
  106. project_raw.envmap_angle = context_raw.envmap_angle;
  107. project_raw.envmap_blur = context_raw.show_envmap_blur;
  108. project_raw.camera_world = mat4_to_f32_array(scene_camera.base.transform.local);
  109. project_raw.camera_origin = export_arm_vec3f32(camera_origins[0].v);
  110. project_raw.camera_fov = scene_camera.data.fov;
  111. // project_raw.mesh_datas = md; // TODO: fix GC ref
  112. if (project_raw.mesh_datas == null) {
  113. project_raw.mesh_datas = md;
  114. }
  115. else {
  116. project_raw.mesh_datas.length = 0;
  117. for (let i: i32 = 0; i < md.length; ++i) {
  118. array_push(project_raw.mesh_datas, md[i]);
  119. }
  120. }
  121. project_raw.material_nodes = mnodes;
  122. project_raw.brush_nodes = bnodes;
  123. project_raw.layer_datas = ld;
  124. project_raw.font_assets = font_files;
  125. project_raw.mesh_assets = mesh_files;
  126. project_raw.atlas_objects = project_atlas_objects;
  127. project_raw.atlas_names = project_atlas_names;
  128. /// if IRON_BGRA
  129. project_raw.is_bgra = true;
  130. /// else
  131. project_raw.is_bgra = false;
  132. /// end
  133. /// if (arm_android || arm_ios)
  134. let rt: render_target_t = map_get(render_path_render_targets, "buf");
  135. let tex: gpu_texture_t = rt._image;
  136. let mesh_icon: gpu_texture_t = gpu_create_render_target(256, 256);
  137. let r: f32 = sys_w() / sys_h();
  138. draw_begin(mesh_icon);
  139. draw_scaled_image(tex, -(256 * r - 256) / 2, 0, 256 * r, 256);
  140. draw_end();
  141. let mesh_icon_pixels: buffer_t = gpu_get_texture_pixels(mesh_icon);
  142. let u8a: u8_array_t = mesh_icon_pixels;
  143. for (let i: i32 = 0; i < 256 * 256 * 4; ++i) {
  144. u8a[i] = math_floor(math_pow(u8a[i] / 255, 1.0 / 2.2) * 255);
  145. }
  146. iron_write_png(substring(project_filepath, 0, project_filepath.length - 4) + "_icon.png", mesh_icon_pixels, 256, 256, 0);
  147. gpu_delete_texture(mesh_icon);
  148. /// end
  149. let is_packed: bool = ends_with(project_filepath, "_packed_.arm");
  150. if (is_packed) { // Pack textures
  151. export_arm_pack_assets(project_raw, project_assets);
  152. }
  153. let buffer: buffer_t = util_encode_project(project_raw);
  154. iron_file_save_bytes(project_filepath, buffer, buffer.length + 1);
  155. // Save to recent
  156. /// if arm_ios
  157. let recent_path: string = substring(project_filepath, string_last_index_of(project_filepath, "/") + 1, project_filepath.length);
  158. /// else
  159. let recent_path: string = project_filepath;
  160. /// end
  161. /// if arm_windows
  162. recent_path = string_replace_all(recent_path, "\\", "/");
  163. /// end
  164. let recent: string[] = config_raw.recent_projects;
  165. array_remove(recent, recent_path);
  166. array_insert(recent, 0, recent_path);
  167. config_save();
  168. console_info(tr("Project saved"));
  169. }
  170. function export_arm_export_node(n: ui_node_t, assets: asset_t[] = null) {
  171. if (n.type == "TEX_IMAGE") {
  172. let index: i32 = n.buttons[0].default_value[0];
  173. if (index > 9000) { // 9999 - Texture deleted
  174. n.buttons[0].data = u8_array_create_from_string("");
  175. }
  176. else {
  177. n.buttons[0].data = u8_array_create_from_string(base_enum_texts(n.type)[index]);
  178. }
  179. if (assets != null) {
  180. let asset: asset_t = project_assets[index];
  181. if (array_index_of(assets, asset) == -1) {
  182. array_push(assets, asset);
  183. }
  184. }
  185. }
  186. }
  187. function export_arm_run_material(path: string) {
  188. if (!ends_with(path, ".arm")) {
  189. path += ".arm";
  190. }
  191. let mnodes: ui_node_canvas_t[] = [];
  192. let mgroups: ui_node_canvas_t[] = null;
  193. let m: slot_material_t = context_raw.material;
  194. let c: ui_node_canvas_t = util_clone_canvas(m.canvas);
  195. let assets: asset_t[] = [];
  196. if (ui_nodes_has_group(c)) {
  197. mgroups = [];
  198. ui_nodes_traverse_group(mgroups, c);
  199. for (let i: i32 = 0; i < mgroups.length; ++i) {
  200. let gc: ui_node_canvas_t = mgroups[i];
  201. for (let i: i32 = 0; i < gc.nodes.length; ++i) {
  202. let n: ui_node_t = gc.nodes[i];
  203. export_arm_export_node(n, assets);
  204. }
  205. }
  206. }
  207. for (let i: i32 = 0; i < c.nodes.length; ++i) {
  208. let n: ui_node_t = c.nodes[i];
  209. export_arm_export_node(n, assets);
  210. }
  211. array_push(mnodes, c);
  212. let texture_files: string[] = export_arm_assets_to_files(path, assets);
  213. let is_cloud: bool = ends_with(path, "_cloud_.arm");
  214. if (is_cloud) {
  215. path = string_replace_all(path, "_cloud_", "");
  216. }
  217. let packed_assets: packed_asset_t[] = null;
  218. if (!context_raw.pack_assets_on_export) {
  219. packed_assets = export_arm_get_packed_assets(path, texture_files);
  220. }
  221. let micons: buffer_t[] = null;
  222. if (!is_cloud) {
  223. /// if IRON_BGRA
  224. let buf: buffer_t = lz4_encode(export_arm_bgra64_swap(gpu_get_texture_pixels(m.image)));
  225. /// else
  226. let buf: buffer_t = lz4_encode(gpu_get_texture_pixels(m.image));
  227. /// end
  228. micons = [ buf ];
  229. }
  230. let raw: project_format_t = {
  231. version : manifest_version_project,
  232. material_nodes : mnodes,
  233. material_groups : mgroups,
  234. material_icons : micons,
  235. assets : texture_files,
  236. packed_assets : packed_assets
  237. };
  238. if (context_raw.write_icon_on_export) { // Separate icon files
  239. iron_write_png(substring(path, 0, path.length - 4) + "_icon.png", gpu_get_texture_pixels(m.image), m.image.width, m.image.height, 0);
  240. if (is_cloud) {
  241. iron_write_jpg(substring(path, 0, path.length - 4) + "_icon.jpg", gpu_get_texture_pixels(m.image), m.image.width, m.image.height, 0, 50);
  242. }
  243. }
  244. if (context_raw.pack_assets_on_export) { // Pack textures
  245. export_arm_pack_assets(raw, assets);
  246. }
  247. let buffer: buffer_t = util_encode_project(raw);
  248. iron_file_save_bytes(path, buffer, buffer.length + 1);
  249. }
  250. function export_arm_bgra_swap(buffer: buffer_t): buffer_t {
  251. for (let i: i32 = 0; i < math_floor((buffer.length) / 4); ++i) {
  252. let r: i32 = buffer[i * 4];
  253. buffer[i * 4] = buffer[i * 4 + 2];
  254. buffer[i * 4 + 2] = r;
  255. }
  256. return buffer;
  257. }
  258. function export_arm_bgra64_swap(buffer: buffer_t): buffer_t {
  259. for (let i: i32 = 0; i < math_floor((buffer.length) / 8); ++i) {
  260. let r_low: i32 = buffer[i * 8 + 4];
  261. let r_high: i32 = buffer[i * 8 + 5];
  262. buffer[i * 8 + 4] = buffer[i * 8 + 0];
  263. buffer[i * 8 + 5] = buffer[i * 8 + 1];
  264. buffer[i * 8] = r_low;
  265. buffer[i * 8 + 1] = r_high;
  266. }
  267. return buffer;
  268. }
  269. function export_arm_run_brush(path: string) {
  270. if (!ends_with(path, ".arm")) {
  271. path += ".arm";
  272. }
  273. let bnodes: ui_node_canvas_t[] = [];
  274. let b: slot_brush_t = context_raw.brush;
  275. let c: ui_node_canvas_t = util_clone_canvas(b.canvas);
  276. let assets: asset_t[] = [];
  277. for (let i: i32 = 0; i < c.nodes.length; ++i) {
  278. let n: ui_node_t = c.nodes[i];
  279. export_arm_export_node(n, assets);
  280. }
  281. array_push(bnodes, c);
  282. let texture_files: string[] = export_arm_assets_to_files(path, assets);
  283. let is_cloud: bool = ends_with(path, "_cloud_.arm");
  284. if (is_cloud) {
  285. path = string_replace_all(path, "_cloud_", "");
  286. }
  287. let packed_assets: packed_asset_t[] = null;
  288. if (!context_raw.pack_assets_on_export) {
  289. packed_assets = export_arm_get_packed_assets(path, texture_files);
  290. }
  291. let bicons: buffer_t[] = null;
  292. if (!is_cloud) {
  293. /// if IRON_BGRA
  294. let buf: buffer_t = lz4_encode(export_arm_bgra_swap(gpu_get_texture_pixels(b.image)));
  295. /// else
  296. let buf: buffer_t = lz4_encode(gpu_get_texture_pixels(b.image));
  297. /// end
  298. bicons = [ buf ];
  299. }
  300. let raw: project_format_t =
  301. {version : manifest_version_project, brush_nodes : bnodes, brush_icons : bicons, assets : texture_files, packed_assets : packed_assets};
  302. if (context_raw.write_icon_on_export) { // Separate icon file
  303. iron_write_png(substring(path, 0, path.length - 4) + "_icon.png", gpu_get_texture_pixels(b.image), b.image.width, b.image.height, 0);
  304. }
  305. if (context_raw.pack_assets_on_export) { // Pack textures
  306. export_arm_pack_assets(raw, assets);
  307. }
  308. let buffer: buffer_t = util_encode_project(raw);
  309. iron_file_save_bytes(path, buffer, buffer.length + 1);
  310. }
  311. function export_arm_assets_to_files(project_path: string, assets: asset_t[]): string[] {
  312. let texture_files: string[] = [];
  313. for (let i: i32 = 0; i < assets.length; ++i) {
  314. let a: asset_t = assets[i];
  315. /// if arm_ios
  316. let same_drive: bool = false;
  317. /// else
  318. let same_drive: bool = char_at(project_path, 0) == char_at(a.file, 0);
  319. /// end
  320. // Convert image path from absolute to relative
  321. if (same_drive) {
  322. array_push(texture_files, path_to_relative(project_path, a.file));
  323. }
  324. else {
  325. array_push(texture_files, a.file);
  326. }
  327. }
  328. return texture_files;
  329. }
  330. function export_arm_meshes_to_files(project_path: string): string[] {
  331. let mesh_files: string[] = [];
  332. for (let i: i32 = 0; i < project_mesh_assets.length; ++i) {
  333. let file: string = project_mesh_assets[i];
  334. /// if arm_ios
  335. let same_drive: bool = false;
  336. /// else
  337. let same_drive: bool = char_at(project_path, 0) == char_at(file, 0);
  338. /// end
  339. // Convert mesh path from absolute to relative
  340. if (same_drive) {
  341. array_push(mesh_files, path_to_relative(project_path, file));
  342. }
  343. else {
  344. array_push(mesh_files, file);
  345. }
  346. }
  347. return mesh_files;
  348. }
  349. function export_arm_fonts_to_files(project_path: string, fonts: slot_font_t[]): string[] {
  350. let font_files: string[] = [];
  351. for (let i: i32 = 1; i < fonts.length; ++i) {
  352. let f: slot_font_t = fonts[i];
  353. /// if arm_ios
  354. let same_drive: bool = false;
  355. /// else
  356. let same_drive: bool = char_at(project_path, 0) == char_at(f.file, 0);
  357. /// end
  358. // Convert font path from absolute to relative
  359. if (same_drive) {
  360. array_push(font_files, path_to_relative(project_path, f.file));
  361. }
  362. else {
  363. array_push(font_files, f.file);
  364. }
  365. }
  366. return font_files;
  367. }
  368. function export_arm_get_packed_assets(project_path: string, texture_files: string[]): packed_asset_t[] {
  369. let packed_assets: packed_asset_t[] = null;
  370. if (project_raw.packed_assets != null) {
  371. for (let i: i32 = 0; i < project_raw.packed_assets.length; ++i) {
  372. let pa: packed_asset_t = project_raw.packed_assets[i];
  373. /// if arm_ios
  374. let same_drive: bool = false;
  375. /// else
  376. let same_drive: bool = char_at(project_path, 0) == char_at(pa.name, 0);
  377. /// end
  378. // Convert path from absolute to relative
  379. pa.name = same_drive ? path_to_relative(project_path, pa.name) : pa.name;
  380. for (let i: i32 = 0; i < texture_files.length; ++i) {
  381. let tf: string = texture_files[i];
  382. if (pa.name == tf) {
  383. if (packed_assets == null) {
  384. packed_assets = [];
  385. }
  386. array_push(packed_assets, pa);
  387. break;
  388. }
  389. }
  390. }
  391. }
  392. return packed_assets;
  393. }
  394. function export_arm_pack_assets(raw: project_format_t, assets: asset_t[]) {
  395. if (raw.packed_assets == null) {
  396. raw.packed_assets = [];
  397. }
  398. let temp_images: gpu_texture_t[] = [];
  399. for (let i: i32 = 0; i < assets.length; ++i) {
  400. if (!project_packed_asset_exists(raw.packed_assets, assets[i].file)) {
  401. let image: gpu_texture_t = project_get_image(assets[i]);
  402. let temp: gpu_texture_t = gpu_create_render_target(image.width, image.height);
  403. draw_begin(temp);
  404. draw_image(image, 0, 0);
  405. draw_end();
  406. array_push(temp_images, temp);
  407. let pa: packed_asset_t = {
  408. name : assets[i].file,
  409. bytes : ends_with(assets[i].file, ".jpg") ? iron_encode_jpg(gpu_get_texture_pixels(temp), temp.width, temp.height, 0, 80)
  410. : iron_encode_png(gpu_get_texture_pixels(temp), temp.width, temp.height, 0)
  411. };
  412. array_push(raw.packed_assets, pa);
  413. }
  414. }
  415. for (let i: i32 = 0; i < temp_images.length; ++i) {
  416. let image: gpu_texture_t = temp_images[i];
  417. gpu_delete_texture(image);
  418. }
  419. }
  420. function export_arm_run_swatches(path: string) {
  421. if (!ends_with(path, ".arm")) {
  422. path += ".arm";
  423. }
  424. let raw: project_format_t = {version : manifest_version_project, swatches : project_raw.swatches};
  425. let buffer: buffer_t = util_encode_project(raw);
  426. iron_file_save_bytes(path, buffer, buffer.length + 1);
  427. }
  428. function export_arm_vec3f32(v: vec4_t): f32_array_t {
  429. let res: f32_array_t = f32_array_create(3);
  430. res[0] = v.x;
  431. res[1] = v.y;
  432. res[2] = v.z;
  433. return res;
  434. }