import_blend_material.ts 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. ///if (is_paint || is_sculpt)
  2. function import_blend_material_run(path: string) {
  3. let b: buffer_t = data_get_blob(path);
  4. let bl: blend_t = parser_blend_init(b);
  5. if (bl.dna == null) {
  6. console_error(strings_error3());
  7. return;
  8. }
  9. let mats: bl_handle_t[] = parser_blend_get(bl, "Material");
  10. if (mats.length == 0) {
  11. console_error("Error: No materials found");
  12. return;
  13. }
  14. let imported: slot_material_t[] = [];
  15. for (let i: i32 = 0; i < mats.length; ++i) {
  16. let mat: bl_handle_t = mats[i];
  17. // Material slot
  18. context_raw.material = slot_material_create(project_materials[0].data);
  19. array_push(project_materials, context_raw.material);
  20. array_push(imported, context_raw.material);
  21. let nodes: zui_nodes_t = context_raw.material.nodes;
  22. let canvas: zui_node_canvas_t = context_raw.material.canvas;
  23. canvas.name = bl_handle_get(bl_handle_get(mat, "id"), "name"); // MAWood
  24. canvas.name = substring(canvas.name, 2, canvas.name.length);
  25. let nout: zui_node_t = null;
  26. for (let i: i32 = 0; i < canvas.nodes.length; ++i) {
  27. let n: zui_node_t = canvas.nodes[i];
  28. if (n.type == "OUTPUT_MATERIAL_PBR") {
  29. nout = n;
  30. break;
  31. }
  32. }
  33. for (let i: i32 = 0; i < canvas.nodes.length; ++i) {
  34. let n: zui_node_t = canvas.nodes[i];
  35. if (n.name == "RGB") {
  36. zui_remove_node(n, canvas);
  37. break;
  38. }
  39. }
  40. // Parse nodetree
  41. let nodetree: any = bl_handle_get(mat, "nodetree"); // bNodeTree
  42. let blnodes: any = bl_handle_get(nodetree, "nodes"); // ListBase
  43. let bllinks: any = bl_handle_get(nodetree, "links"); // bNodeLink
  44. // Look for Principled BSDF node
  45. let node: any = bl_handle_get(blnodes, "first", 0, "bNode");
  46. let last: any = bl_handle_get(blnodes, "last", 0, "bNode");
  47. while (true) {
  48. if (bl_handle_get(node, "idname") == "ShaderNodeBsdfPrincipled") {
  49. break;
  50. }
  51. if (bl_handle_get(node, "name") == bl_handle_get(last, "name")) {
  52. break;
  53. }
  54. node = bl_handle_get(node, "next");
  55. }
  56. if (bl_handle_get(node, "idname") != "ShaderNodeBsdfPrincipled") {
  57. console_error("Error: No Principled BSDF node found");
  58. continue;
  59. }
  60. // Use Principled BSDF as material output
  61. nout.name = bl_handle_get(node, "name");
  62. nout.x = bl_handle_get(node, "locx") + 400;
  63. nout.y = -bl_handle_get(node, "locy") + 400;
  64. // Place nodes
  65. node = bl_handle_get(blnodes, "first", 0, "bNode");
  66. while (true) {
  67. // Search for node in list
  68. let search: string = bl_handle_get(node, "idname");
  69. search = to_lower_case(substring(search, 10, search.length));
  70. let base: zui_node_t = null;
  71. for (let i: i32 = 0; i < nodes_material_list.length; ++i) {
  72. let list: zui_node_t[] = nodes_material_list[i];
  73. let found: bool = false;
  74. for (let i: i32 = 0; i < list.length; ++i) {
  75. let n: zui_node_t = list[i];
  76. let s: string = to_lower_case(string_replace_all(n.type, "_", ""));
  77. if (search == s) {
  78. base = n;
  79. found = true;
  80. break;
  81. }
  82. }
  83. if (found) {
  84. break;
  85. }
  86. }
  87. if (base != null) {
  88. let n: zui_node_t = ui_nodes_make_node(base, nodes, canvas);
  89. n.x = bl_handle_get(node, "locx") + 400;
  90. n.y = -bl_handle_get(node, "locy") + 400;
  91. n.name = bl_handle_get(node, "name");
  92. // Fill input socket values
  93. let inputs: any = bl_handle_get(node, "inputs");
  94. let sock: any = bl_handle_get(inputs, "first", 0, "bNodeSocket");
  95. let pos: i32 = 0;
  96. while (true) {
  97. if (pos >= n.inputs.length) {
  98. break;
  99. }
  100. n.inputs[pos].default_value = import_blend_material_read_blend_socket(sock);
  101. let last: any = sock;
  102. sock = bl_handle_get(sock, "next");
  103. if (last.block == sock.block) {
  104. break;
  105. }
  106. pos++;
  107. }
  108. // Fill button values
  109. if (search == "teximage") {
  110. let img: any = bl_handle_get(node, "id", 0, "Image");
  111. let file: string = bl_handle_get(img, "name"); // "//desktop\logo.png"
  112. file = substring(file, 2, file.length);
  113. file = path_base_dir(path) + file;
  114. import_texture_run(file);
  115. let ar: string[] = string_split(file, path_sep);
  116. let filename: string = ar[ar.length - 1];
  117. n.buttons[0].default_value = f32_array_create_x(base_get_asset_index(filename));
  118. }
  119. else if (search == "valtorgb") {
  120. // let ramp: any = bl_handle_get(node, "storage", 0, "ColorBand");
  121. // n.buttons[0].data = bl_handle_get(ramp, "ipotype") == 0 ? 0 : 1; // Linear / Constant
  122. // let elems: f32[][] = n.buttons[0].default_value;
  123. // for (let i: i32 = 0; i < bl_handle_get(ramp, "tot"); ++i) {
  124. // if (i >= elems.length) {
  125. // array_push(elems, [1.0, 1.0, 1.0, 1.0, 0.0]);
  126. // }
  127. // let cbdata: any = bl_handle_get(ramp, "data", i, "CBData");
  128. // elems[i][0] = math_floor(bl_handle_get(cbdata, "r") * 100) / 100;
  129. // elems[i][1] = math_floor(bl_handle_get(cbdata, "g") * 100) / 100;
  130. // elems[i][2] = math_floor(bl_handle_get(cbdata, "b") * 100) / 100;
  131. // elems[i][3] = math_floor(bl_handle_get(cbdata, "a") * 100) / 100;
  132. // elems[i][4] = math_floor(bl_handle_get(cbdata, "pos") * 100) / 100;
  133. // }
  134. }
  135. else if (search == "mixrgb" || search == "math") {
  136. n.buttons[0].default_value = f32_array_create_x(bl_handle_get(node, "custom1"));
  137. n.buttons[1].default_value = f32_array_create_x(bl_handle_get(node, "custom2") & 2);
  138. }
  139. else if (search == "mapping") {
  140. let storage: any = bl_handle_get(node, "storage", 0, "TexMapping");
  141. n.buttons[0].default_value = bl_handle_get(storage, "loc");
  142. n.buttons[1].default_value = bl_handle_get(storage, "rot");
  143. n.buttons[2].default_value = bl_handle_get(storage, "size");
  144. // let mat: any = get(storage, "mat"); float[4][4]
  145. // storage.flag & 1 // use_min
  146. // storage.flag & 2 // use_max
  147. // storage.min[0]
  148. // storage.min[1]
  149. // storage.min[2]
  150. // storage.max[0]
  151. // storage.max[1]
  152. // storage.max[2]
  153. }
  154. // Fill output socket values
  155. let outputs: any = bl_handle_get(node, "outputs");
  156. sock = bl_handle_get(outputs, "first", 0, "bNodeSocket");
  157. pos = 0;
  158. while (true) {
  159. if (pos >= n.outputs.length) {
  160. break;
  161. }
  162. n.outputs[pos].default_value = import_blend_material_read_blend_socket(sock);
  163. let last: any = sock;
  164. sock = bl_handle_get(sock, "next");
  165. if (last.block == sock.block) {
  166. break;
  167. }
  168. pos++;
  169. }
  170. array_push(canvas.nodes, n);
  171. }
  172. if (bl_handle_get(node, "name") == bl_handle_get(last, "name")) {
  173. break;
  174. }
  175. node = bl_handle_get(node, "next");
  176. }
  177. // Place links
  178. let link: any = bl_handle_get(bllinks, "first", 0, "bNodeLink");
  179. while (true) {
  180. let fromnode: any = bl_handle_get(bl_handle_get(link, "fromnode"), "name");
  181. let tonode: any = bl_handle_get(bl_handle_get(link, "tonode"), "name");
  182. let fromsock: any = bl_handle_get(link, "fromsock");
  183. let tosock: any = bl_handle_get(link, "tosock");
  184. let from_id: i32 = -1;
  185. let to_id: i32 = -1;
  186. for (let i: i32 = 0; i < canvas.nodes.length; ++i) {
  187. let n: zui_node_t = canvas.nodes[i];
  188. if (n.name == fromnode) {
  189. from_id = n.id;
  190. break;
  191. }
  192. }
  193. for (let i: i32 = 0; i < canvas.nodes.length; ++i) {
  194. let n: zui_node_t = canvas.nodes[i];
  195. if (n.name == tonode) {
  196. to_id = n.id;
  197. break;
  198. }
  199. }
  200. if (from_id >= 0 && to_id >= 0) {
  201. let from_socket: i32 = 0;
  202. let sock: any = fromsock;
  203. while (true) {
  204. let last: any = sock;
  205. sock = bl_handle_get(sock, "prev");
  206. if (last.block == sock.block) {
  207. break;
  208. }
  209. from_socket++;
  210. }
  211. let to_socket: i32 = 0;
  212. sock = tosock;
  213. while (true) {
  214. let last: any = sock;
  215. sock = bl_handle_get(sock, "prev");
  216. if (last.block == sock.block) {
  217. break;
  218. }
  219. to_socket++;
  220. }
  221. let valid: bool = true;
  222. // Remap principled
  223. if (tonode == nout.name) {
  224. if (to_socket == 0) {
  225. to_socket = 0; // Base
  226. }
  227. else if (to_socket == 18) {
  228. to_socket = 1; // Opac
  229. }
  230. else if (to_socket == 7) {
  231. to_socket = 3; // Rough
  232. }
  233. else if (to_socket == 4) {
  234. to_socket = 4; // Met
  235. }
  236. else if (to_socket == 19) {
  237. to_socket = 5; // TODO: auto-remove normal_map node
  238. }
  239. else if (to_socket == 17) {
  240. to_socket = 6; // Emis
  241. }
  242. else if (to_socket == 1) {
  243. to_socket = 8; // Subs
  244. }
  245. else {
  246. valid = false;
  247. }
  248. }
  249. if (valid) {
  250. let raw: zui_node_link_t = {
  251. id: zui_get_link_id(canvas.links),
  252. from_id: from_id,
  253. from_socket: from_socket,
  254. to_id: to_id,
  255. to_socket: to_socket
  256. };
  257. array_push(canvas.links, raw);
  258. }
  259. }
  260. let last: any = link;
  261. link = bl_handle_get(link, "next");
  262. if (last.block == link.block) {
  263. break;
  264. }
  265. }
  266. history_new_material();
  267. }
  268. app_notify_on_init(function (imported: slot_material_t[]) {
  269. for (let i: i32 = 0; i < imported.length; ++i) {
  270. let m: slot_material_t = imported[i];
  271. context_set_material(m);
  272. make_material_parse_paint_material();
  273. util_render_make_material_preview();
  274. }
  275. }, imported);
  276. ui_base_hwnds[tab_area_t.SIDEBAR1].redraws = 2;
  277. data_delete_blob(path);
  278. }
  279. function import_blend_material_read_blend_socket(sock: any): any {
  280. let idname: any = bl_handle_get(sock, "idname");
  281. if (starts_with(idname, "NodeSocketVector")) {
  282. let v: any = bl_handle_get(bl_handle_get(sock, "default_value", 0, "bNodeSocketValueVector"), "value");
  283. v[0] = math_floor(v[0] * 100) / 100;
  284. v[1] = math_floor(v[1] * 100) / 100;
  285. v[2] = math_floor(v[2] * 100) / 100;
  286. return v;
  287. }
  288. else if (starts_with(idname, "NodeSocketColor")) {
  289. let v: any = bl_handle_get(bl_handle_get(sock, "default_value", 0, "bNodeSocketValueRGBA"), "value");
  290. v[0] = math_floor(v[0] * 100) / 100;
  291. v[1] = math_floor(v[1] * 100) / 100;
  292. v[2] = math_floor(v[2] * 100) / 100;
  293. v[3] = math_floor(v[3] * 100) / 100;
  294. return v;
  295. }
  296. else if (starts_with(idname, "NodeSocketFloat")) {
  297. let v: any = bl_handle_get(bl_handle_get(sock, "default_value", 0, "bNodeSocketValueFloat"), "value");
  298. v = math_floor(v * 100) / 100;
  299. return v;
  300. }
  301. else if (starts_with(idname, "NodeSocketInt")) {
  302. return bl_handle_get(bl_handle_get(sock, "default_value", 0, "bNodeSocketValueInt"), "value");
  303. }
  304. else if (starts_with(idname, "NodeSocketBoolean")) {
  305. return bl_handle_get(bl_handle_get(sock, "default_value", 0, "bNodeSocketValueBoolean"), "value");
  306. }
  307. else if (starts_with(idname, "NodeSocketString")) {
  308. return bl_handle_get(bl_handle_get(sock, "default_value", 0, "bNodeSocketValueString"), "value");
  309. }
  310. return null;
  311. }
  312. ///end