slot_layer.ts 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810
  1. type slot_layer_t = {
  2. id?: i32;
  3. name?: string;
  4. ext?: string;
  5. visible?: bool;
  6. parent?: slot_layer_t; // Group (for layers) or layer (for masks)
  7. texpaint?: image_t; // Base or mask
  8. ///if is_paint
  9. texpaint_nor?: image_t;
  10. texpaint_pack?: image_t;
  11. texpaint_preview?: image_t; // Layer preview
  12. ///end
  13. mask_opacity?: f32; // Opacity mask
  14. fill_layer?: slot_material_t;
  15. show_panel?: bool;
  16. blending?: blend_type_t;
  17. object_mask?: i32;
  18. scale?: f32;
  19. angle?: f32;
  20. uv_type?: uv_type_t;
  21. paint_base?: bool;
  22. paint_opac?: bool;
  23. paint_occ?: bool;
  24. paint_rough?: bool;
  25. paint_met?: bool;
  26. paint_nor?: bool;
  27. paint_nor_blend?: bool;
  28. paint_height?: bool;
  29. paint_height_blend?: bool;
  30. paint_emis?: bool;
  31. paint_subs?: bool;
  32. decal_mat?: mat4_t; // Decal layer
  33. };
  34. function slot_layer_create(ext: string = "", type: layer_slot_type_t = layer_slot_type_t.LAYER, parent: slot_layer_t = null): slot_layer_t {
  35. let raw: slot_layer_t = {};
  36. raw.id = 0;
  37. raw.ext = "";
  38. raw.visible = true;
  39. raw.mask_opacity = 1.0; // Opacity mask
  40. raw.show_panel = true;
  41. raw.blending = blend_type_t.MIX;
  42. raw.object_mask = 0;
  43. raw.scale = 1.0;
  44. raw.angle = 0.0;
  45. raw.uv_type = uv_type_t.UVMAP;
  46. raw.paint_base = true;
  47. raw.paint_opac = true;
  48. raw.paint_occ = true;
  49. raw.paint_rough = true;
  50. raw.paint_met = true;
  51. raw.paint_nor = true;
  52. raw.paint_nor_blend = true;
  53. raw.paint_height = true;
  54. raw.paint_height_blend = true;
  55. raw.paint_emis = true;
  56. raw.paint_subs = true;
  57. raw.decal_mat = mat4_identity(); // Decal layer
  58. if (ext == "") {
  59. raw.id = 0;
  60. for (let i: i32 = 0; i < project_layers.length; ++i) {
  61. let l: slot_layer_t = project_layers[i];
  62. if (l.id >= raw.id) {
  63. raw.id = l.id + 1;
  64. }
  65. }
  66. ext = raw.id + "";
  67. }
  68. raw.ext = ext;
  69. raw.parent = parent;
  70. if (type == layer_slot_type_t.GROUP) {
  71. raw.name = "Group " + (raw.id + 1);
  72. }
  73. else if (type == layer_slot_type_t.LAYER) {
  74. raw.name = "Layer " + (raw.id + 1);
  75. ///if is_paint
  76. let format: string = base_bits_handle.position == texture_bits_t.BITS8 ? "RGBA32" :
  77. base_bits_handle.position == texture_bits_t.BITS16 ? "RGBA64" :
  78. "RGBA128";
  79. ///end
  80. ///if is_sculpt
  81. let format: string = "RGBA128";
  82. ///end
  83. {
  84. let t: render_target_t = render_target_create();
  85. t.name = "texpaint" + ext;
  86. t.width = config_get_texture_res_x();
  87. t.height = config_get_texture_res_y();
  88. t.format = format;
  89. raw.texpaint = render_path_create_render_target(t)._image;
  90. }
  91. ///if is_paint
  92. {
  93. let t: render_target_t = render_target_create();
  94. t.name = "texpaint_nor" + ext;
  95. t.width = config_get_texture_res_x();
  96. t.height = config_get_texture_res_y();
  97. t.format = format;
  98. raw.texpaint_nor = render_path_create_render_target(t)._image;
  99. }
  100. {
  101. let t: render_target_t = render_target_create();
  102. t.name = "texpaint_pack" + ext;
  103. t.width = config_get_texture_res_x();
  104. t.height = config_get_texture_res_y();
  105. t.format = format;
  106. raw.texpaint_pack = render_path_create_render_target(t)._image;
  107. }
  108. raw.texpaint_preview = image_create_render_target(util_render_layer_preview_size, util_render_layer_preview_size, tex_format_t.RGBA32);
  109. ///end
  110. }
  111. ///if is_paint
  112. else { // Mask
  113. raw.name = "Mask " + (raw.id + 1);
  114. let format: string = "RGBA32"; // Full bits for undo support, R8 is used
  115. raw.blending = blend_type_t.ADD;
  116. {
  117. let t: render_target_t = render_target_create();
  118. t.name = "texpaint" + ext;
  119. t.width = config_get_texture_res_x();
  120. t.height = config_get_texture_res_y();
  121. t.format = format;
  122. raw.texpaint = render_path_create_render_target(t)._image;
  123. }
  124. raw.texpaint_preview = image_create_render_target(util_render_layer_preview_size, util_render_layer_preview_size, tex_format_t.RGBA32);
  125. }
  126. ///end
  127. return raw;
  128. }
  129. function slot_layer_delete(raw: slot_layer_t) {
  130. slot_layer_unload(raw);
  131. if (slot_layer_is_layer(raw)) {
  132. let masks: slot_layer_t[] = slot_layer_get_masks(raw, false); // Prevents deleting group masks
  133. if (masks != null) {
  134. for (let i: i32 = 0; i < masks.length; ++i) {
  135. let m: slot_layer_t = masks[i];
  136. slot_layer_delete(m);
  137. }
  138. }
  139. }
  140. else if (slot_layer_is_group(raw)) {
  141. let children: slot_layer_t[] = slot_layer_get_children(raw);
  142. if (children != null) {
  143. for (let i: i32 = 0; i < children.length; ++i) {
  144. let c: slot_layer_t = children[i];
  145. slot_layer_delete(c);
  146. }
  147. }
  148. let masks: slot_layer_t[] = slot_layer_get_masks(raw);
  149. if (masks != null) {
  150. for (let i: i32 = 0; i < masks.length; ++i) {
  151. let m: slot_layer_t = masks[i];
  152. slot_layer_delete(m);
  153. }
  154. }
  155. }
  156. let lpos: i32 = array_index_of(project_layers, raw);
  157. array_remove(project_layers, raw);
  158. // Undo can remove base layer and then restore it from undo layers
  159. if (project_layers.length > 0) {
  160. context_set_layer(project_layers[lpos > 0 ? lpos - 1 : 0]);
  161. }
  162. // Do not remove empty groups if the last layer is deleted as this prevents redo from working properly
  163. }
  164. function slot_layer_unload(raw: slot_layer_t) {
  165. if (slot_layer_is_group(raw)) {
  166. return;
  167. }
  168. let _texpaint: image_t = raw.texpaint;
  169. ///if is_paint
  170. let _texpaint_nor: image_t = raw.texpaint_nor;
  171. let _texpaint_pack: image_t = raw.texpaint_pack;
  172. let _texpaint_preview: image_t = raw.texpaint_preview;
  173. ///end
  174. app_notify_on_next_frame(function (_texpaint: image_t) {
  175. image_unload(_texpaint);
  176. }, _texpaint);
  177. ///if is_paint
  178. if (_texpaint_nor != null) {
  179. app_notify_on_next_frame(function (_texpaint_nor: image_t) {
  180. image_unload(_texpaint_nor);
  181. }, _texpaint_nor);
  182. }
  183. if (_texpaint_pack != null) {
  184. app_notify_on_next_frame(function (_texpaint_pack: image_t) {
  185. image_unload(_texpaint_pack);
  186. }, _texpaint_pack);
  187. }
  188. image_unload(_texpaint_preview);
  189. ///end
  190. map_delete(render_path_render_targets, "texpaint" + raw.ext);
  191. ///if is_paint
  192. if (slot_layer_is_layer(raw)) {
  193. map_delete(render_path_render_targets, "texpaint_nor" + raw.ext);
  194. map_delete(render_path_render_targets, "texpaint_pack" + raw.ext);
  195. }
  196. ///end
  197. }
  198. function slot_layer_swap(raw: slot_layer_t, other: slot_layer_t) {
  199. if ((slot_layer_is_layer(raw) || slot_layer_is_mask(raw)) && (slot_layer_is_layer(other) || slot_layer_is_mask(other))) {
  200. map_get(render_path_render_targets, "texpaint" + raw.ext)._image = other.texpaint;
  201. map_get(render_path_render_targets, "texpaint" + other.ext)._image = raw.texpaint;
  202. let _texpaint: image_t = raw.texpaint;
  203. raw.texpaint = other.texpaint;
  204. other.texpaint = _texpaint;
  205. ///if is_paint
  206. let _texpaint_preview: image_t = raw.texpaint_preview;
  207. raw.texpaint_preview = other.texpaint_preview;
  208. other.texpaint_preview = _texpaint_preview;
  209. ///end
  210. }
  211. ///if is_paint
  212. if (slot_layer_is_layer(raw) && slot_layer_is_layer(other)) {
  213. map_get(render_path_render_targets, "texpaint_nor" + raw.ext)._image = other.texpaint_nor;
  214. map_get(render_path_render_targets, "texpaint_pack" + raw.ext)._image = other.texpaint_pack;
  215. map_get(render_path_render_targets, "texpaint_nor" + other.ext)._image = raw.texpaint_nor;
  216. map_get(render_path_render_targets, "texpaint_pack" + other.ext)._image = raw.texpaint_pack;
  217. let _texpaint_nor: image_t = raw.texpaint_nor;
  218. let _texpaint_pack: image_t = raw.texpaint_pack;
  219. raw.texpaint_nor = other.texpaint_nor;
  220. raw.texpaint_pack = other.texpaint_pack;
  221. other.texpaint_nor = _texpaint_nor;
  222. other.texpaint_pack = _texpaint_pack;
  223. }
  224. ///end
  225. }
  226. function slot_layer_clear(raw: slot_layer_t, base_color: i32 = 0x00000000, base_image: image_t = null, occlusion: f32 = 1.0, roughness: f32 = base_default_rough, metallic: f32 = 0.0) {
  227. g4_begin(raw.texpaint);
  228. g4_clear(base_color); // Base
  229. g4_end();
  230. if (base_image != null) {
  231. g2_begin(raw.texpaint);
  232. g2_draw_scaled_image(base_image, 0, 0, raw.texpaint.width, raw.texpaint.height);
  233. g2_end();
  234. }
  235. ///if is_paint
  236. if (slot_layer_is_layer(raw)) {
  237. g4_begin(raw.texpaint_nor);
  238. g4_clear(color_from_floats(0.5, 0.5, 1.0, 0.0)); // Nor
  239. g4_end();
  240. g4_begin(raw.texpaint_pack);
  241. g4_clear(color_from_floats(occlusion, roughness, metallic, 0.0)); // Occ, rough, met
  242. g4_end();
  243. }
  244. ///end
  245. context_raw.layer_preview_dirty = true;
  246. context_raw.ddirty = 3;
  247. }
  248. function slot_layer_invert_mask(raw: slot_layer_t) {
  249. if (base_pipe_invert8 == null) {
  250. base_make_pipe();
  251. }
  252. let inverted: image_t = image_create_render_target(raw.texpaint.width, raw.texpaint.height, tex_format_t.RGBA32);
  253. g2_begin(inverted);
  254. g2_set_pipeline(base_pipe_invert8);
  255. g2_draw_image(raw.texpaint, 0, 0);
  256. g2_set_pipeline(null);
  257. g2_end();
  258. let _texpaint: image_t = raw.texpaint;
  259. app_notify_on_next_frame(function (_texpaint: image_t) {
  260. image_unload(_texpaint);
  261. }, _texpaint);
  262. raw.texpaint = map_get(render_path_render_targets, "texpaint" + raw.id)._image = inverted;
  263. context_raw.layer_preview_dirty = true;
  264. context_raw.ddirty = 3;
  265. }
  266. function slot_layer_apply_mask(raw: slot_layer_t) {
  267. if (raw.parent.fill_layer != null) {
  268. slot_layer_to_paint_layer(raw.parent);
  269. }
  270. if (slot_layer_is_group(raw.parent)) {
  271. for (let i: i32 = 0; i < slot_layer_get_children(raw.parent).length; ++i) {
  272. let c: slot_layer_t = slot_layer_get_children(raw.parent)[i];
  273. base_apply_mask(c, raw);
  274. }
  275. }
  276. else {
  277. base_apply_mask(raw.parent, raw);
  278. }
  279. slot_layer_delete(raw);
  280. }
  281. function slot_layer_duplicate(raw: slot_layer_t): slot_layer_t {
  282. let layers: slot_layer_t[] = project_layers;
  283. let i: i32 = array_index_of(layers, raw) + 1;
  284. let l: slot_layer_t = slot_layer_create("", slot_layer_is_layer(raw) ? layer_slot_type_t.LAYER : slot_layer_is_mask(raw) ? layer_slot_type_t.MASK : layer_slot_type_t.GROUP, raw.parent);
  285. array_insert(layers, i, l);
  286. if (base_pipe_merge == null) {
  287. base_make_pipe();
  288. }
  289. if (slot_layer_is_layer(raw)) {
  290. g2_begin(l.texpaint);
  291. g2_set_pipeline(base_pipe_copy);
  292. g2_draw_image(raw.texpaint, 0, 0);
  293. g2_set_pipeline(null);
  294. g2_end();
  295. ///if is_paint
  296. g2_begin(l.texpaint_nor);
  297. g2_set_pipeline(base_pipe_copy);
  298. g2_draw_image(raw.texpaint_nor, 0, 0);
  299. g2_set_pipeline(null);
  300. g2_end();
  301. g2_begin(l.texpaint_pack);
  302. g2_set_pipeline(base_pipe_copy);
  303. g2_draw_image(raw.texpaint_pack, 0, 0);
  304. g2_set_pipeline(null);
  305. g2_end();
  306. ///end
  307. }
  308. else if (slot_layer_is_mask(raw)) {
  309. g2_begin(l.texpaint);
  310. g2_set_pipeline(base_pipe_copy8);
  311. g2_draw_image(raw.texpaint, 0, 0);
  312. g2_set_pipeline(null);
  313. g2_end();
  314. }
  315. ///if is_paint
  316. g2_begin(l.texpaint_preview);
  317. g2_clear(0x00000000);
  318. g2_set_pipeline(base_pipe_copy);
  319. g2_draw_scaled_image(raw.texpaint_preview, 0, 0, raw.texpaint_preview.width, raw.texpaint_preview.height);
  320. g2_set_pipeline(null);
  321. g2_end();
  322. ///end
  323. l.visible = raw.visible;
  324. l.mask_opacity = raw.mask_opacity;
  325. l.fill_layer = raw.fill_layer;
  326. l.object_mask = raw.object_mask;
  327. l.blending = raw.blending;
  328. l.uv_type = raw.uv_type;
  329. l.scale = raw.scale;
  330. l.angle = raw.angle;
  331. l.paint_base = raw.paint_base;
  332. l.paint_opac = raw.paint_opac;
  333. l.paint_occ = raw.paint_occ;
  334. l.paint_rough = raw.paint_rough;
  335. l.paint_met = raw.paint_met;
  336. l.paint_nor = raw.paint_nor;
  337. l.paint_nor_blend = raw.paint_nor_blend;
  338. l.paint_height = raw.paint_height;
  339. l.paint_height_blend = raw.paint_height_blend;
  340. l.paint_emis = raw.paint_emis;
  341. l.paint_subs = raw.paint_subs;
  342. return l;
  343. }
  344. function slot_layer_resize_and_set_bits(raw: slot_layer_t) {
  345. let res_x: i32 = config_get_texture_res_x();
  346. let res_y: i32 = config_get_texture_res_y();
  347. let rts: map_t<string, render_target_t> = render_path_render_targets;
  348. if (base_pipe_merge == null) {
  349. base_make_pipe();
  350. }
  351. if (slot_layer_is_layer(raw)) {
  352. ///if is_paint
  353. let format: tex_format_t = base_bits_handle.position == texture_bits_t.BITS8 ? tex_format_t.RGBA32 :
  354. base_bits_handle.position == texture_bits_t.BITS16 ? tex_format_t.RGBA64 :
  355. tex_format_t.RGBA128;
  356. ///end
  357. ///if is_sculpt
  358. let format: tex_format_t = tex_format_t.RGBA128;
  359. ///end
  360. let _texpaint: image_t = raw.texpaint;
  361. raw.texpaint = image_create_render_target(res_x, res_y, format);
  362. g2_begin(raw.texpaint);
  363. g2_set_pipeline(base_pipe_copy);
  364. g2_draw_scaled_image(_texpaint, 0, 0, res_x, res_y);
  365. g2_set_pipeline(null);
  366. g2_end();
  367. ///if is_paint
  368. let _texpaint_nor: image_t = raw.texpaint_nor;
  369. let _texpaint_pack: image_t = raw.texpaint_pack;
  370. raw.texpaint_nor = image_create_render_target(res_x, res_y, format);
  371. raw.texpaint_pack = image_create_render_target(res_x, res_y, format);
  372. g2_begin(raw.texpaint_nor);
  373. g2_set_pipeline(base_pipe_copy);
  374. g2_draw_scaled_image(_texpaint_nor, 0, 0, res_x, res_y);
  375. g2_set_pipeline(null);
  376. g2_end();
  377. g2_begin(raw.texpaint_pack);
  378. g2_set_pipeline(base_pipe_copy);
  379. g2_draw_scaled_image(_texpaint_pack, 0, 0, res_x, res_y);
  380. g2_set_pipeline(null);
  381. g2_end();
  382. ///end
  383. app_notify_on_next_frame(function (_texpaint: image_t) {
  384. image_unload(_texpaint);
  385. }, _texpaint);
  386. ///if is_paint
  387. app_notify_on_next_frame(function (_texpaint_nor: image_t) {
  388. image_unload(_texpaint_nor);
  389. }, _texpaint_nor);
  390. app_notify_on_next_frame(function (_texpaint_pack: image_t) {
  391. image_unload(_texpaint_pack);
  392. }, _texpaint_pack);
  393. ///end
  394. map_get(rts, "texpaint" + raw.ext)._image = raw.texpaint;
  395. ///if is_paint
  396. map_get(rts, "texpaint_nor" + raw.ext)._image = raw.texpaint_nor;
  397. map_get(rts, "texpaint_pack" + raw.ext)._image = raw.texpaint_pack;
  398. ///end
  399. }
  400. else if (slot_layer_is_mask(raw)) {
  401. let _texpaint: image_t = raw.texpaint;
  402. raw.texpaint = image_create_render_target(res_x, res_y, tex_format_t.RGBA32);
  403. g2_begin(raw.texpaint);
  404. g2_set_pipeline(base_pipe_copy8);
  405. g2_draw_scaled_image(_texpaint, 0, 0, res_x, res_y);
  406. g2_set_pipeline(null);
  407. g2_end();
  408. app_notify_on_next_frame(function (_texpaint: image_t) {
  409. image_unload(_texpaint);
  410. }, _texpaint);
  411. map_get(rts, "texpaint" + raw.ext)._image = raw.texpaint;
  412. }
  413. }
  414. function slot_layer_to_fill_layer(raw: slot_layer_t) {
  415. context_set_layer(raw);
  416. raw.fill_layer = context_raw.material;
  417. base_update_fill_layer();
  418. app_notify_on_next_frame(function () {
  419. make_material_parse_paint_material();
  420. context_raw.layer_preview_dirty = true;
  421. ui_base_hwnds[tab_area_t.SIDEBAR0].redraws = 2;
  422. });
  423. }
  424. function slot_layer_to_paint_layer(raw: slot_layer_t) {
  425. context_set_layer(raw);
  426. raw.fill_layer = null;
  427. make_material_parse_paint_material();
  428. context_raw.layer_preview_dirty = true;
  429. ui_base_hwnds[tab_area_t.SIDEBAR0].redraws = 2;
  430. }
  431. function slot_layer_is_visible(raw: slot_layer_t): bool {
  432. return raw.visible && (raw.parent == null || raw.parent.visible);
  433. }
  434. function slot_layer_get_children(raw: slot_layer_t): slot_layer_t[] {
  435. let children: slot_layer_t[] = null; // Child layers of a group
  436. for (let i: i32 = 0; i < project_layers.length; ++i) {
  437. let l: slot_layer_t = project_layers[i];
  438. if (l.parent == raw && slot_layer_is_layer(l)) {
  439. if (children == null) {
  440. children = [];
  441. }
  442. array_push(children, l);
  443. }
  444. }
  445. return children;
  446. }
  447. function slot_layer_get_recursive_children(raw: slot_layer_t): slot_layer_t[] {
  448. let children: slot_layer_t[] = null;
  449. for (let i: i32 = 0; i < project_layers.length; ++i) {
  450. let l: slot_layer_t = project_layers[i];
  451. if (l.parent == raw) { // Child layers and group masks
  452. if (children == null) {
  453. children = [];
  454. }
  455. array_push(children, l);
  456. }
  457. if (l.parent != null && l.parent.parent == raw) { // Layer masks
  458. if (children == null) {
  459. children = [];
  460. }
  461. array_push(children, l);
  462. }
  463. }
  464. return children;
  465. }
  466. function slot_layer_get_masks(raw: slot_layer_t, includeGroupMasks = true): slot_layer_t[] {
  467. if (slot_layer_is_mask(raw)) {
  468. return null;
  469. }
  470. let children: slot_layer_t[] = null;
  471. // Child masks of a layer
  472. for (let i: i32 = 0; i < project_layers.length; ++i) {
  473. let l: slot_layer_t = project_layers[i];
  474. if (l.parent == raw && slot_layer_is_mask(l)) {
  475. if (children == null) {
  476. children = [];
  477. }
  478. array_push(children, l);
  479. }
  480. }
  481. // Child masks of a parent group
  482. if (includeGroupMasks) {
  483. if (raw.parent != null && slot_layer_is_group(raw.parent)) {
  484. for (let i: i32 = 0; i < project_layers.length; ++i) {
  485. let l: slot_layer_t = project_layers[i];
  486. if (l.parent == raw.parent && slot_layer_is_mask(l)) {
  487. if (children == null) {
  488. children = [];
  489. }
  490. array_push(children, l);
  491. }
  492. }
  493. }
  494. }
  495. return children;
  496. }
  497. function slot_layer_has_masks(raw: slot_layer_t, includeGroupMasks = true): bool {
  498. // Layer mask
  499. for (let i: i32 = 0; i < project_layers.length; ++i) {
  500. let l: slot_layer_t = project_layers[i];
  501. if (l.parent == raw && slot_layer_is_mask(l)) {
  502. return true;
  503. }
  504. }
  505. // Group mask
  506. if (includeGroupMasks && raw.parent != null && slot_layer_is_group(raw.parent)) {
  507. for (let i: i32 = 0; i < project_layers.length; ++i) {
  508. let l: slot_layer_t = project_layers[i];
  509. if (l.parent == raw.parent && slot_layer_is_mask(l)) {
  510. return true;
  511. }
  512. }
  513. }
  514. return false;
  515. }
  516. function slot_layer_get_opacity(raw: slot_layer_t): f32 {
  517. let f: f32 = raw.mask_opacity;
  518. if (slot_layer_is_layer(raw) && raw.parent != null) {
  519. f *= raw.parent.mask_opacity;
  520. }
  521. return f;
  522. }
  523. function slot_layer_get_object_mask(raw: slot_layer_t): i32 {
  524. return slot_layer_is_mask(raw) ? raw.parent.object_mask : raw.object_mask;
  525. }
  526. function slot_layer_is_layer(raw: slot_layer_t): bool {
  527. ///if is_paint
  528. return raw.texpaint != null && raw.texpaint_nor != null;
  529. ///end
  530. ///if is_sculpt
  531. return raw.texpaint != null;
  532. ///end
  533. }
  534. function slot_layer_is_group(raw: slot_layer_t): bool {
  535. return raw.texpaint == null;
  536. }
  537. function slot_layer_get_containing_group(raw: slot_layer_t): slot_layer_t {
  538. if (raw.parent != null && slot_layer_is_group(raw.parent)) {
  539. return raw.parent;
  540. }
  541. else if (raw.parent != null && raw.parent.parent != null && slot_layer_is_group(raw.parent.parent)) {
  542. return raw.parent.parent;
  543. }
  544. else {
  545. return null;
  546. }
  547. }
  548. function slot_layer_is_mask(raw: slot_layer_t): bool {
  549. ///if is_paint
  550. return raw.texpaint != null && raw.texpaint_nor == null;
  551. ///end
  552. ///if is_sculpt
  553. return false;
  554. ///end
  555. }
  556. function slot_layer_is_group_mask(raw: slot_layer_t): bool {
  557. ///if is_paint
  558. return raw.texpaint != null && raw.texpaint_nor == null && slot_layer_is_group(raw.parent);
  559. ///end
  560. ///if is_sculpt
  561. return false;
  562. ///end
  563. }
  564. function slot_layer_is_layer_mask(raw: slot_layer_t): bool {
  565. ///if is_paint
  566. return raw.texpaint != null && raw.texpaint_nor == null && slot_layer_is_layer(raw.parent);
  567. ///end
  568. ///if is_sculpt
  569. return false;
  570. ///end
  571. }
  572. function slot_layer_is_in_group(raw: slot_layer_t): bool {
  573. return raw.parent != null && (slot_layer_is_group(raw.parent) || (raw.parent.parent != null && slot_layer_is_group(raw.parent.parent)));
  574. }
  575. function slot_layer_can_move(raw: slot_layer_t, to: i32): bool {
  576. let old_index: i32 = array_index_of(project_layers, raw);
  577. let delta: i32 = to - old_index; // If delta > 0 the layer is moved up, otherwise down
  578. if (to < 0 || to > project_layers.length - 1 || delta == 0) {
  579. return false;
  580. }
  581. // If the layer is moved up, all layers between the old position and the new one move one down
  582. // The layers above the new position stay where they are
  583. // If the new position is on top or on bottom no upper resp. lower layer exists
  584. let new_upper_layer: slot_layer_t = delta > 0 ? (to < project_layers.length - 1 ? project_layers[to + 1] : null) : project_layers[to];
  585. // Group or layer is collapsed so we check below and update the upper layer
  586. if (new_upper_layer != null && !new_upper_layer.show_panel) {
  587. let children: slot_layer_t[] = slot_layer_get_recursive_children(new_upper_layer);
  588. to -= children != null ? children.length : 0;
  589. delta = to - old_index;
  590. new_upper_layer = delta > 0 ? (to < project_layers.length - 1 ? project_layers[to + 1] : null) : project_layers[to];
  591. }
  592. let new_lower_layer: slot_layer_t = delta > 0 ? project_layers[to] : (to > 0 ? project_layers[to - 1] : null);
  593. if (slot_layer_is_mask(raw)) {
  594. // Masks can not be on top
  595. if (new_upper_layer == null) {
  596. return false;
  597. }
  598. // Masks should not be placed below a collapsed group - this condition can be savely removed
  599. if (slot_layer_is_in_group(new_upper_layer) && !slot_layer_get_containing_group(new_upper_layer).show_panel) {
  600. return false;
  601. }
  602. // Masks should not be placed below a collapsed layer - this condition can be savely removed
  603. if (slot_layer_is_mask(new_upper_layer) && !new_upper_layer.parent.show_panel) {
  604. return false;
  605. }
  606. }
  607. if (slot_layer_is_layer(raw)) {
  608. // Layers can not be moved directly below its own mask(s)
  609. if (new_upper_layer != null && slot_layer_is_mask(new_upper_layer) && new_upper_layer.parent == raw) {
  610. return false;
  611. }
  612. // Layers can not be placed above a mask as the mask would be reparented
  613. if (new_lower_layer != null && slot_layer_is_mask(new_lower_layer)) {
  614. return false;
  615. }
  616. }
  617. // Currently groups can not be nested - thus valid positions for groups are:
  618. if (slot_layer_is_group(raw)) {
  619. // At the top
  620. if (new_upper_layer == null) {
  621. return true;
  622. }
  623. // NOT below its own children
  624. if (slot_layer_get_containing_group(new_upper_layer) == raw) {
  625. return false;
  626. }
  627. // At the bottom
  628. if (new_lower_layer == null) {
  629. return true;
  630. }
  631. // Above a group
  632. if (slot_layer_is_group(new_lower_layer)) {
  633. return true;
  634. }
  635. // Above a non-grouped layer
  636. if (slot_layer_is_layer(new_lower_layer) && !slot_layer_is_in_group(new_lower_layer)) {
  637. return true;
  638. }
  639. else {
  640. return false;
  641. }
  642. }
  643. return true;
  644. }
  645. function slot_layer_move(raw: slot_layer_t, to: i32) {
  646. if (!slot_layer_can_move(raw, to)) {
  647. return;
  648. }
  649. let pointers: map_t<slot_layer_t, i32> = tab_layers_init_layer_map();
  650. let old_index: i32 = array_index_of(project_layers, raw);
  651. let delta: i32 = to - old_index;
  652. let new_upper_layer: slot_layer_t = delta > 0 ? (to < project_layers.length - 1 ? project_layers[to + 1] : null) : project_layers[to];
  653. // Group or layer is collapsed so we check below and update the upper layer
  654. if (new_upper_layer != null && !new_upper_layer.show_panel) {
  655. let children: slot_layer_t[] = slot_layer_get_recursive_children(new_upper_layer);
  656. to -= children != null ? children.length : 0;
  657. delta = to - old_index;
  658. new_upper_layer = delta > 0 ? (to < project_layers.length - 1 ? project_layers[to + 1] : null) : project_layers[to];
  659. }
  660. context_set_layer(raw);
  661. history_order_layers(to);
  662. ui_base_hwnds[tab_area_t.SIDEBAR0].redraws = 2;
  663. array_remove(project_layers, raw);
  664. array_insert(project_layers, to, raw);
  665. if (slot_layer_is_layer(raw)) {
  666. let old_parent: slot_layer_t = raw.parent;
  667. if (new_upper_layer == null) {
  668. raw.parent = null; // Placed on top
  669. }
  670. else if (slot_layer_is_in_group(new_upper_layer) && !slot_layer_get_containing_group(new_upper_layer).show_panel) {
  671. raw.parent = null; // Placed below a collapsed group
  672. }
  673. else if (slot_layer_is_layer(new_upper_layer)) {
  674. raw.parent = new_upper_layer.parent; // Placed below a layer, use the same parent
  675. }
  676. else if (slot_layer_is_group(new_upper_layer)) {
  677. raw.parent = new_upper_layer; // Placed as top layer in a group
  678. }
  679. else if (slot_layer_is_group_mask(new_upper_layer)) {
  680. raw.parent = new_upper_layer.parent; // Placed in a group below the lowest group mask
  681. }
  682. else if (slot_layer_is_layer_mask(new_upper_layer)) {
  683. raw.parent = slot_layer_get_containing_group(new_upper_layer); // Either the group the mask belongs to or null
  684. }
  685. // Layers can have masks as children
  686. // These have to be moved, too
  687. let layer_masks: slot_layer_t[] = slot_layer_get_masks(raw, false);
  688. if (layer_masks != null) {
  689. for (let idx: i32 = 0; idx < layer_masks.length; ++idx) {
  690. let mask: slot_layer_t = layer_masks[idx];
  691. array_remove(project_layers, mask);
  692. // If the masks are moved down each step increases the index below the layer by one.
  693. array_insert(project_layers, delta > 0 ? old_index + delta - 1 : old_index + delta + idx, mask);
  694. }
  695. }
  696. // The layer is the last layer in the group, remove it
  697. // Notice that this might remove group masks
  698. if (old_parent != null && slot_layer_get_children(old_parent) == null) {
  699. slot_layer_delete(old_parent);
  700. }
  701. }
  702. else if (slot_layer_is_mask(raw)) {
  703. // Precondition new_upper_layer != null, ensured in can_move
  704. if (slot_layer_is_layer(new_upper_layer) || slot_layer_is_group(new_upper_layer)) {
  705. raw.parent = new_upper_layer;
  706. }
  707. else if (slot_layer_is_mask(new_upper_layer)) { // Group mask or layer mask
  708. raw.parent = new_upper_layer.parent;
  709. }
  710. }
  711. else if (slot_layer_is_group(raw)) {
  712. let children: slot_layer_t[] = slot_layer_get_recursive_children(raw);
  713. if (children != null) {
  714. for (let idx: i32 = 0; idx < children.length; ++idx) {
  715. let child: slot_layer_t = children[idx];
  716. array_remove(project_layers, child);
  717. // If the children are moved down each step increases the index below the layer by one
  718. array_insert(project_layers, delta > 0 ? old_index + delta - 1 : old_index + delta + idx, child);
  719. }
  720. }
  721. }
  722. for (let i: i32 = 0; i < project_materials.length; ++i) {
  723. let m: slot_material_t = project_materials[i];
  724. tab_layers_remap_layer_pointers(m.canvas.nodes, tab_layers_fill_layer_map(pointers));
  725. }
  726. }