Blender V4.3
blenkernel/intern/material.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include <cmath>
10#include <cstddef>
11#include <cstring>
12#include <optional>
13
14#include "CLG_log.h"
15
16#include "MEM_guardedalloc.h"
17
18/* Allow using deprecated functionality for .blend file I/O. */
19#define DNA_DEPRECATED_ALLOW
20
21#include "DNA_ID.h"
22#include "DNA_anim_types.h"
24#include "DNA_curve_types.h"
25#include "DNA_curves_types.h"
27#include "DNA_defaults.h"
30#include "DNA_material_types.h"
31#include "DNA_meta_types.h"
32#include "DNA_node_types.h"
33#include "DNA_object_types.h"
34#include "DNA_particle_types.h"
36#include "DNA_scene_types.h"
37#include "DNA_volume_types.h"
38
39#include "BLI_array_utils.h"
40#include "BLI_listbase.h"
41#include "BLI_math_color.h"
42#include "BLI_math_vector.h"
43#include "BLI_string.h"
44#include "BLI_utildefines.h"
45
46#include "BLT_translation.hh"
47
48#include "BKE_anim_data.hh"
49#include "BKE_attribute.hh"
50#include "BKE_brush.hh"
51#include "BKE_curve.hh"
52#include "BKE_displist.h"
53#include "BKE_editmesh.hh"
54#include "BKE_gpencil_legacy.h"
55#include "BKE_grease_pencil.hh"
56#include "BKE_icons.h"
57#include "BKE_idtype.hh"
58#include "BKE_image.hh"
59#include "BKE_lib_id.hh"
60#include "BKE_lib_query.hh"
61#include "BKE_main.hh"
62#include "BKE_material.h"
63#include "BKE_mesh.hh"
64#include "BKE_node.hh"
65#include "BKE_node_runtime.hh"
66#include "BKE_object.hh"
67#include "BKE_object_types.hh"
68#include "BKE_preview_image.hh"
69#include "BKE_scene.hh"
70#include "BKE_vfont.hh"
71
72#include "DEG_depsgraph.hh"
75
76#include "GPU_material.hh"
77
78#include "NOD_shader.h"
79
80#include "BLO_read_write.hh"
81
82static CLG_LogRef LOG = {"bke.material"};
83
84static void material_init_data(ID *id)
85{
86 Material *material = (Material *)id;
87
89
91
92 *((short *)id->name) = ID_MA;
93}
94
95static void material_copy_data(Main *bmain,
96 std::optional<Library *> owner_library,
97 ID *id_dst,
98 const ID *id_src,
99 const int flag)
100{
101 Material *material_dst = (Material *)id_dst;
102 const Material *material_src = (const Material *)id_src;
103
104 const bool is_localized = (flag & LIB_ID_CREATE_LOCAL) != 0;
105 /* Never handle user-count here for own sub-data. */
106 const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT;
107 /* Always need allocation of the embedded ID data. */
108 const int flag_embedded_id_data = flag_subdata & ~LIB_ID_CREATE_NO_ALLOCATE;
109
110 if (material_src->nodetree != nullptr) {
111 if (is_localized) {
112 material_dst->nodetree = blender::bke::node_tree_localize(material_src->nodetree,
113 &material_dst->id);
114 }
115 else {
116 BKE_id_copy_in_lib(bmain,
117 owner_library,
118 &material_src->nodetree->id,
119 &material_dst->id,
120 reinterpret_cast<ID **>(&material_dst->nodetree),
121 flag_embedded_id_data);
122 }
123 }
124
125 if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0) {
126 BKE_previewimg_id_copy(&material_dst->id, &material_src->id);
127 }
128 else {
129 material_dst->preview = nullptr;
130 }
131
132 if (material_src->texpaintslot != nullptr) {
133 /* TODO: Think we can also skip copying this data in the more generic `NO_MAIN` case? */
134 material_dst->texpaintslot = is_localized ? nullptr :
135 static_cast<TexPaintSlot *>(
136 MEM_dupallocN(material_src->texpaintslot));
137 }
138
139 if (material_src->gp_style != nullptr) {
140 material_dst->gp_style = static_cast<MaterialGPencilStyle *>(
141 MEM_dupallocN(material_src->gp_style));
142 }
143
144 BLI_listbase_clear(&material_dst->gpumaterial);
145
146 /* TODO: Duplicate Engine Settings and set runtime to nullptr. */
147}
148
149static void material_free_data(ID *id)
150{
151 Material *material = (Material *)id;
152
153 /* Free gpu material before the ntree */
154 GPU_material_free(&material->gpumaterial);
155
156 /* is no lib link block, but material extension */
157 if (material->nodetree) {
159 MEM_freeN(material->nodetree);
160 material->nodetree = nullptr;
161 }
162
163 MEM_SAFE_FREE(material->texpaintslot);
164
165 MEM_SAFE_FREE(material->gp_style);
166
167 BKE_previewimg_free(&material->preview);
168
169 BKE_icon_id_delete((ID *)material);
170}
171
173{
174 Material *material = reinterpret_cast<Material *>(id);
176
177 /* Node-trees **are owned by IDs**, treat them as mere sub-data and not real ID! */
179 data, BKE_library_foreach_ID_embedded(data, (ID **)&material->nodetree));
180 if (material->texpaintslot != nullptr) {
181 BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, material->texpaintslot->ima, IDWALK_CB_NOP);
182 }
183 if (material->gp_style != nullptr) {
184 BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, material->gp_style->sima, IDWALK_CB_USER);
185 BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, material->gp_style->ima, IDWALK_CB_USER);
186 }
187
190 }
191}
192
193static void material_blend_write(BlendWriter *writer, ID *id, const void *id_address)
194{
195 Material *ma = (Material *)id;
196
197 /* Clean up, important in undo case to reduce false detection of changed datablocks. */
198 ma->texpaintslot = nullptr;
200
201 /* write LibData */
202 BLO_write_id_struct(writer, Material, id_address, &ma->id);
203 BKE_id_blend_write(writer, &ma->id);
204
205 /* nodetree is integral part of material, no libdata */
206 if (ma->nodetree) {
207 BLO_Write_IDBuffer *temp_embedded_id_buffer = BLO_write_allocate_id_buffer();
209 temp_embedded_id_buffer, &ma->nodetree->id, BLO_write_is_undo(writer));
211 writer, bNodeTree, ma->nodetree, BLO_write_get_id_buffer_temp_id(temp_embedded_id_buffer));
213 writer,
214 reinterpret_cast<bNodeTree *>(BLO_write_get_id_buffer_temp_id(temp_embedded_id_buffer)));
215 BLO_write_destroy_id_buffer(&temp_embedded_id_buffer);
216 }
217
219
220 /* grease pencil settings */
221 if (ma->gp_style) {
223 }
224}
225
227{
228 Material *ma = (Material *)id;
229
230 ma->texpaintslot = nullptr;
231
232 BLO_read_struct(reader, PreviewImage, &ma->preview);
234
236
238}
239
241 /*id_code*/ ID_MA,
242 /*id_filter*/ FILTER_ID_MA,
243 /*dependencies_id_types*/ FILTER_ID_TE | FILTER_ID_GR,
244 /*main_listbase_index*/ INDEX_ID_MA,
245 /*struct_size*/ sizeof(Material),
246 /*name*/ "Material",
247 /*name_plural*/ N_("materials"),
248 /*translation_context*/ BLT_I18NCONTEXT_ID_MATERIAL,
250 /*asset_type_info*/ nullptr,
251
252 /*init_data*/ material_init_data,
253 /*copy_data*/ material_copy_data,
254 /*free_data*/ material_free_data,
255 /*make_local*/ nullptr,
256 /*foreach_id*/ material_foreach_id,
257 /*foreach_cache*/ nullptr,
258 /*foreach_path*/ nullptr,
259 /*owner_pointer_get*/ nullptr,
260
261 /*blend_write*/ material_blend_write,
262 /*blend_read_data*/ material_blend_read_data,
263 /*blend_read_after_liblink*/ nullptr,
264
265 /*blend_read_undo_preserve*/ nullptr,
266
267 /*lib_override_apply_post*/ nullptr,
268};
269
271{
272 if ((ma) && (ma->gp_style == nullptr)) {
273 ma->gp_style = static_cast<MaterialGPencilStyle *>(
274 MEM_callocN(sizeof(MaterialGPencilStyle), "Grease Pencil Material Settings"));
275
276 MaterialGPencilStyle *gp_style = ma->gp_style;
277 /* set basic settings */
278 gp_style->stroke_rgba[3] = 1.0f;
279 gp_style->fill_rgba[3] = 1.0f;
280 ARRAY_SET_ITEMS(gp_style->mix_rgba, 1.0f, 1.0f, 1.0f, 1.0f);
281 ARRAY_SET_ITEMS(gp_style->texture_scale, 1.0f, 1.0f);
282 gp_style->texture_offset[0] = -0.5f;
283 gp_style->texture_pixsize = 100.0f;
284 gp_style->mix_factor = 0.5f;
285
286 gp_style->flag |= GP_MATERIAL_STROKE_SHOW;
287 }
288}
289
291{
292 if (tree == nullptr) {
293 return;
294 }
295 tree->runtime->previews_refresh_state++;
296 for (bNode *node : tree->all_nodes()) {
297 if (node->type == NODE_GROUP) {
298 bNodeTree *nested_tree = reinterpret_cast<bNodeTree *>(node->id);
300 }
301 }
302}
303
310
311Material *BKE_material_add(Main *bmain, const char *name)
312{
313 Material *ma;
314
315 ma = static_cast<Material *>(BKE_id_new(bmain, ID_MA, name));
316
317 return ma;
318}
319
320Material *BKE_gpencil_material_add(Main *bmain, const char *name)
321{
322 Material *ma;
323
324 ma = BKE_material_add(bmain, name);
325
326 /* grease pencil settings */
327 if (ma != nullptr) {
329 }
330 return ma;
331}
332
334{
335 if (ob->type == OB_MESH) {
336 Mesh *mesh = static_cast<Mesh *>(ob->data);
337 return &(mesh->mat);
338 }
340 Curve *cu = static_cast<Curve *>(ob->data);
341 return &(cu->mat);
342 }
343 if (ob->type == OB_MBALL) {
344 MetaBall *mb = static_cast<MetaBall *>(ob->data);
345 return &(mb->mat);
346 }
347 if (ob->type == OB_GPENCIL_LEGACY) {
348 bGPdata *gpd = static_cast<bGPdata *>(ob->data);
349 return &(gpd->mat);
350 }
351 if (ob->type == OB_CURVES) {
352 Curves *curves = static_cast<Curves *>(ob->data);
353 return &(curves->mat);
354 }
355 if (ob->type == OB_POINTCLOUD) {
356 PointCloud *pointcloud = static_cast<PointCloud *>(ob->data);
357 return &(pointcloud->mat);
358 }
359 if (ob->type == OB_VOLUME) {
360 Volume *volume = static_cast<Volume *>(ob->data);
361 return &(volume->mat);
362 }
363 if (ob->type == OB_GREASE_PENCIL) {
364 GreasePencil *grease_pencil = static_cast<GreasePencil *>(ob->data);
365 return &(grease_pencil->material_array);
366 }
367 return nullptr;
368}
369
371{
372 if (ob->type == OB_MESH) {
373 Mesh *mesh = static_cast<Mesh *>(ob->data);
374 return &(mesh->totcol);
375 }
377 Curve *cu = static_cast<Curve *>(ob->data);
378 return &(cu->totcol);
379 }
380 if (ob->type == OB_MBALL) {
381 MetaBall *mb = static_cast<MetaBall *>(ob->data);
382 return &(mb->totcol);
383 }
384 if (ob->type == OB_GPENCIL_LEGACY) {
385 bGPdata *gpd = static_cast<bGPdata *>(ob->data);
386 return &(gpd->totcol);
387 }
388 if (ob->type == OB_CURVES) {
389 Curves *curves = static_cast<Curves *>(ob->data);
390 return &(curves->totcol);
391 }
392 if (ob->type == OB_POINTCLOUD) {
393 PointCloud *pointcloud = static_cast<PointCloud *>(ob->data);
394 return &(pointcloud->totcol);
395 }
396 if (ob->type == OB_VOLUME) {
397 Volume *volume = static_cast<Volume *>(ob->data);
398 return &(volume->totcol);
399 }
400 if (ob->type == OB_GREASE_PENCIL) {
401 GreasePencil *grease_pencil = static_cast<GreasePencil *>(ob->data);
402 return &(grease_pencil->material_array_num);
403 }
404 return nullptr;
405}
406
408{
409 /* ensure we don't try get materials from non-obdata */
410 BLI_assert(OB_DATA_SUPPORT_ID(GS(id->name)));
411
412 switch (GS(id->name)) {
413 case ID_ME:
414 return &(((Mesh *)id)->mat);
415 case ID_CU_LEGACY:
416 return &(((Curve *)id)->mat);
417 case ID_MB:
418 return &(((MetaBall *)id)->mat);
419 case ID_GD_LEGACY:
420 return &(((bGPdata *)id)->mat);
421 case ID_CV:
422 return &(((Curves *)id)->mat);
423 case ID_PT:
424 return &(((PointCloud *)id)->mat);
425 case ID_VO:
426 return &(((Volume *)id)->mat);
427 case ID_GP:
428 return &(((GreasePencil *)id)->material_array);
429 default:
430 break;
431 }
432 return nullptr;
433}
434
436{
437 /* ensure we don't try get materials from non-obdata */
438 BLI_assert(OB_DATA_SUPPORT_ID(GS(id->name)));
439
440 switch (GS(id->name)) {
441 case ID_ME:
442 return &(((Mesh *)id)->totcol);
443 case ID_CU_LEGACY:
444 return &(((Curve *)id)->totcol);
445 case ID_MB:
446 return &(((MetaBall *)id)->totcol);
447 case ID_GD_LEGACY:
448 return &(((bGPdata *)id)->totcol);
449 case ID_CV:
450 return &(((Curves *)id)->totcol);
451 case ID_PT:
452 return &(((PointCloud *)id)->totcol);
453 case ID_VO:
454 return &(((Volume *)id)->totcol);
455 case ID_GP:
456 return &(((GreasePencil *)id)->material_array_num);
457 default:
458 break;
459 }
460 return nullptr;
461}
462
463static void material_data_index_remove_id(ID *id, short index)
464{
465 /* ensure we don't try get materials from non-obdata */
466 BLI_assert(OB_DATA_SUPPORT_ID(GS(id->name)));
467
468 switch (GS(id->name)) {
469 case ID_ME:
471 break;
472 case ID_CU_LEGACY:
474 break;
475 case ID_GP:
476 BKE_grease_pencil_material_index_remove(reinterpret_cast<GreasePencil *>(id), index);
477 break;
478 case ID_MB:
479 case ID_CV:
480 case ID_PT:
481 case ID_VO:
482 /* No material indices for these object data types. */
483 break;
484 default:
485 break;
486 }
487}
488
489bool BKE_object_material_slot_used(Object *object, short actcol)
490{
492 return false;
493 }
494
495 LISTBASE_FOREACH (ParticleSystem *, psys, &object->particlesystem) {
496 if (psys->part->omat == actcol) {
497 return true;
498 }
499 }
500
501 ID *ob_data = static_cast<ID *>(object->data);
502 if (ob_data == nullptr || !OB_DATA_SUPPORT_ID(GS(ob_data->name))) {
503 return false;
504 }
505
506 switch (GS(ob_data->name)) {
507 case ID_ME:
508 return BKE_mesh_material_index_used((Mesh *)ob_data, actcol - 1);
509 case ID_CU_LEGACY:
510 return BKE_curve_material_index_used((Curve *)ob_data, actcol - 1);
511 case ID_MB:
512 /* Meta-elements don't support materials at the moment. */
513 return false;
514 case ID_GP:
515 return BKE_grease_pencil_material_index_used(reinterpret_cast<GreasePencil *>(ob_data),
516 actcol - 1);
517 default:
518 return false;
519 }
520}
521
523{
524 /* ensure we don't try get materials from non-obdata */
525 BLI_assert(OB_DATA_SUPPORT_ID(GS(id->name)));
526
527 switch (GS(id->name)) {
528 case ID_ME:
530 break;
531 case ID_CU_LEGACY:
533 break;
534 case ID_MB:
535 case ID_CV:
536 case ID_PT:
537 case ID_VO:
538 /* No material indices for these object data types. */
539 break;
540 default:
541 break;
542 }
543}
544
545void BKE_id_materials_copy(Main *bmain, ID *id_src, ID *id_dst)
546{
547 Material ***matar_src = BKE_id_material_array_p(id_src);
548 const short *materials_len_p_src = BKE_id_material_len_p(id_src);
549
550 Material ***matar_dst = BKE_id_material_array_p(id_dst);
551 short *materials_len_p_dst = BKE_id_material_len_p(id_dst);
552
553 *materials_len_p_dst = *materials_len_p_src;
554 if (*materials_len_p_src != 0) {
555 (*matar_dst) = static_cast<Material **>(MEM_dupallocN(*matar_src));
556
557 for (int a = 0; a < *materials_len_p_src; a++) {
558 id_us_plus((ID *)(*matar_dst)[a]);
559 }
560
563 }
564}
565
566void BKE_id_material_resize(Main *bmain, ID *id, short totcol, bool do_id_user)
567{
568 Material ***matar = BKE_id_material_array_p(id);
569 short *totcolp = BKE_id_material_len_p(id);
570
571 if (matar == nullptr) {
572 return;
573 }
574
575 if (do_id_user && totcol < (*totcolp)) {
576 short i;
577 for (i = totcol; i < (*totcolp); i++) {
578 id_us_min((ID *)(*matar)[i]);
579 }
580 }
581
582 if (totcol == 0) {
583 if (*totcolp) {
584 MEM_freeN(*matar);
585 *matar = nullptr;
586 }
587 }
588 else {
589 *matar = static_cast<Material **>(MEM_recallocN(*matar, sizeof(void *) * totcol));
590 }
591 *totcolp = totcol;
592
595}
596
598{
599 Material ***matar;
600 if ((matar = BKE_id_material_array_p(id))) {
601 short *totcol = BKE_id_material_len_p(id);
602 Material **mat = MEM_cnew_array<Material *>((*totcol) + 1, "newmatar");
603 if (*totcol) {
604 memcpy(mat, *matar, sizeof(void *) * (*totcol));
605 }
606 if (*matar) {
607 MEM_freeN(*matar);
608 }
609
610 *matar = mat;
611 (*matar)[(*totcol)++] = ma;
612
613 id_us_plus((ID *)ma);
615
618 }
619}
620
621Material *BKE_id_material_pop(Main *bmain, ID *id, int index_i)
622{
623 short index = short(index_i);
624 Material *ret = nullptr;
625 Material ***matar;
626 if ((matar = BKE_id_material_array_p(id))) {
627 short *totcol = BKE_id_material_len_p(id);
628 if (index >= 0 && index < (*totcol)) {
629 ret = (*matar)[index];
630 id_us_min((ID *)ret);
631
632 if (*totcol <= 1) {
633 *totcol = 0;
634 MEM_freeN(*matar);
635 *matar = nullptr;
636 }
637 else {
638 if (index + 1 != (*totcol)) {
639 memmove((*matar) + index,
640 (*matar) + (index + 1),
641 sizeof(void *) * ((*totcol) - (index + 1)));
642 }
643
644 (*totcol)--;
645 *matar = static_cast<Material **>(MEM_reallocN(*matar, sizeof(void *) * (*totcol)));
647 }
648
650
653 }
654 }
655
656 return ret;
657}
658
660{
661 Material ***matar;
662 if ((matar = BKE_id_material_array_p(id))) {
663 short *totcol = BKE_id_material_len_p(id);
664
665 while ((*totcol)--) {
666 id_us_min((ID *)((*matar)[*totcol]));
667 }
668 *totcol = 0;
669 if (*matar) {
670 MEM_freeN(*matar);
671 *matar = nullptr;
672 }
673
676
679 }
680}
681
683{
684 Material ***matarar, **ma_p;
685 const short *totcolp;
686
687 if (ob == nullptr) {
688 return nullptr;
689 }
690
691 /* if object cannot have material, (totcolp == nullptr) */
692 totcolp = BKE_object_material_len_p(ob);
693 if (totcolp == nullptr || *totcolp == 0) {
694 return nullptr;
695 }
696
697 /* Clamp to number of slots if index is out of range, same convention as used for rendering. */
698 const int slot_index = clamp_i(act - 1, 0, *totcolp - 1);
699
700 /* Fix inconsistency which may happen when library linked data reduces the number of
701 * slots but object was not updated. Ideally should be fixed elsewhere. */
702 if (*totcolp < ob->totcol) {
703 ob->totcol = *totcolp;
704 }
705
706 if (slot_index < ob->totcol && ob->matbits && ob->matbits[slot_index]) {
707 /* Use object material slot. */
708 ma_p = &ob->mat[slot_index];
709 }
710 else {
711 /* Use data material slot. */
712 matarar = BKE_object_material_array_p(ob);
713
714 if (matarar && *matarar) {
715 ma_p = &(*matarar)[slot_index];
716 }
717 else {
718 ma_p = nullptr;
719 }
720 }
721
722 return ma_p;
723}
724
726{
727 Material **ma_p = BKE_object_material_get_p(ob, act);
728 /* Grease Pencil objects currently make the assumption that the returned material has Grease
729 * Pencil settings. Ensure that this is the case otherwise return `nullptr`. */
730 if (ob->type == OB_GREASE_PENCIL && ma_p != nullptr) {
731 Material *ma = *ma_p;
732 if (ma != nullptr) {
733 return ma->gp_style != nullptr ? ma : nullptr;
734 }
735 }
736 return ma_p ? *ma_p : nullptr;
737}
738
740{
741 const ID *data = static_cast<ID *>(ob->data);
742 /* Meshes in edit mode need special handling. */
743 if (ob->type == OB_MESH && ob->mode == OB_MODE_EDIT) {
744 const Mesh *mesh = static_cast<const Mesh *>(ob->data);
745 const Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(ob);
746 if (mesh->runtime->edit_mesh && editmesh_eval_final) {
747 data = &editmesh_eval_final->id;
748 }
749 }
750 return data;
751}
752
754{
756
758 const short *tot_slots_data_ptr = BKE_id_material_len_p(const_cast<ID *>(data));
759 const int tot_slots_data = tot_slots_data_ptr ? *tot_slots_data_ptr : 0;
760
761 if (tot_slots_data == 0) {
762 return nullptr;
763 }
764
765 /* Clamp to number of slots if index is out of range, same convention as used for rendering. */
766 const int slot_index = clamp_i(act - 1, 0, tot_slots_data - 1);
767 const int tot_slots_object = ob->totcol;
768
769 Material ***materials_data_ptr = BKE_id_material_array_p(const_cast<ID *>(data));
770 Material **materials_data = materials_data_ptr ? *materials_data_ptr : nullptr;
771 Material **materials_object = ob->mat;
772
773 /* Check if slot is overwritten by object. */
774 if (slot_index < tot_slots_object) {
775 if (ob->matbits) {
776 if (ob->matbits[slot_index]) {
777 Material *material = materials_object[slot_index];
778 if (material != nullptr) {
779 return material;
780 }
781 }
782 }
783 }
784 /* Otherwise use data from object-data. */
785 if (slot_index < tot_slots_data) {
786 Material *material = materials_data[slot_index];
787 return material;
788 }
789 return nullptr;
790}
791
793{
795 if (ob->type == OB_EMPTY) {
796 return 0;
797 }
798 BLI_assert(ob->data != nullptr);
799 const ID *id = get_evaluated_object_data_with_materials(const_cast<Object *>(ob));
800 const short *len_p = BKE_id_material_len_p(const_cast<ID *>(id));
801 return len_p ? *len_p : 0;
802}
803
804void BKE_id_material_eval_assign(ID *id, int slot, Material *material)
805{
806 BLI_assert(slot >= 1);
807 Material ***materials_ptr = BKE_id_material_array_p(id);
808 short *len_ptr = BKE_id_material_len_p(id);
809 if (ELEM(nullptr, materials_ptr, len_ptr)) {
811 return;
812 }
813
814 const int slot_index = slot - 1;
815 const int old_length = *len_ptr;
816
817 if (slot_index >= old_length) {
818 /* Need to grow slots array. */
819 const int new_length = slot_index + 1;
820 *materials_ptr = static_cast<Material **>(
821 MEM_reallocN(*materials_ptr, sizeof(void *) * new_length));
822 *len_ptr = new_length;
823 for (int i = old_length; i < new_length; i++) {
824 (*materials_ptr)[i] = nullptr;
825 }
826 }
827
828 (*materials_ptr)[slot_index] = material;
829}
830
832{
833 short *len_ptr = BKE_id_material_len_p(id);
834 if (len_ptr == nullptr) {
835 return;
836 }
837 if (*len_ptr == 0) {
838 BKE_id_material_eval_assign(id, 1, nullptr);
839 }
840}
841
843{
844 short *totcol = BKE_object_material_len_p(ob);
845 Material *read_ma = nullptr;
846 for (short i = 0; i < *totcol; i++) {
847 read_ma = BKE_object_material_get(ob, i + 1);
848 if (ma == read_ma) {
849 return i;
850 }
851 }
852 return -1;
853}
854
855int BKE_object_material_index_get_with_hint(Object *ob, const Material *ma, const int hint_index)
856{
857 short *totcol = BKE_object_material_len_p(ob);
858 if ((hint_index >= 0) && (hint_index < *totcol)) {
859 if (ma == BKE_object_material_get(ob, hint_index + 1)) {
860 return hint_index;
861 }
862 }
863 return BKE_object_material_index_get(ob, ma);
864}
865
867{
868 if (!material) {
869 return -1;
870 }
871 int index = BKE_object_material_index_get(ob, material);
872 if (index < 0) {
875 return ob->totcol - 1;
876 }
877 return index;
878}
879
881{
882 Material *ma = BKE_object_material_get(ob, act);
883 if (ma != nullptr) {
884 return ma;
885 }
886
888}
889
891{
892 Material *ma = BKE_object_material_get(ob, act);
893 if (ma != nullptr) {
894 if (ma->gp_style == nullptr) {
896 }
897
898 return ma->gp_style;
899 }
900
902}
903
904void BKE_object_material_resize(Main *bmain, Object *ob, const short totcol, bool do_id_user)
905{
906 Material **newmatar;
907 char *newmatbits;
908
909 if (do_id_user && totcol < ob->totcol) {
910 for (int i = totcol; i < ob->totcol; i++) {
911 id_us_min((ID *)ob->mat[i]);
912 }
913 }
914
915 if (totcol == 0) {
916 if (ob->totcol) {
917 MEM_freeN(ob->mat);
918 MEM_freeN(ob->matbits);
919 ob->mat = nullptr;
920 ob->matbits = nullptr;
921 }
922 }
923 else if (ob->totcol < totcol) {
924 newmatar = MEM_cnew_array<Material *>(totcol, "newmatar");
925 newmatbits = MEM_cnew_array<char>(totcol, "newmatbits");
926 if (ob->totcol) {
927 memcpy(newmatar, ob->mat, sizeof(void *) * ob->totcol);
928 memcpy(newmatbits, ob->matbits, sizeof(char) * ob->totcol);
929 MEM_freeN(ob->mat);
930 MEM_freeN(ob->matbits);
931 }
932 ob->mat = newmatar;
933 ob->matbits = newmatbits;
934 }
935 /* XXX(@ideasman42): why not realloc on shrink? */
936
937 ob->totcol = totcol;
938 if (ob->totcol && ob->actcol == 0) {
939 ob->actcol = 1;
940 }
941 if (ob->actcol > ob->totcol) {
942 ob->actcol = ob->totcol;
943 }
944
947}
948
950{
951 /* make the ob mat-array same size as 'ob->data' mat-array */
952 const short *totcol;
953
954 if (id == nullptr || (totcol = BKE_id_material_len_p(id)) == nullptr) {
955 return;
956 }
957
958 if ((ob->id.tag & ID_TAG_MISSING) == 0 && (id->tag & ID_TAG_MISSING) != 0) {
959 /* Exception: In case the object is a valid data, but its obdata is an empty place-holder,
960 * use object's material slots amount as reference.
961 * This avoids losing materials in a local object when its linked obdata goes missing.
962 * See #92780. */
963 BKE_id_material_resize(bmain, id, short(ob->totcol), false);
964 }
965 else {
966 /* Normal case: the use the obdata amount of materials slots to update the object's one. */
967 BKE_object_material_resize(bmain, ob, *totcol, false);
968 }
969}
970
972{
973 /* make the ob mat-array same size as 'ob->data' mat-array */
974 Object *ob;
975 const short *totcol;
976
977 if (id == nullptr || (totcol = BKE_id_material_len_p(id)) == nullptr) {
978 return;
979 }
980
981 BKE_main_lock(bmain);
982 int processed_objects = 0;
983 for (ob = static_cast<Object *>(bmain->objects.first); ob;
984 ob = static_cast<Object *>(ob->id.next))
985 {
986 if (ob->data == id) {
987 BKE_object_material_resize(bmain, ob, *totcol, false);
988 processed_objects++;
989 BLI_assert(processed_objects <= id->us && processed_objects > 0);
990 if (processed_objects == id->us) {
991 break;
992 }
993 }
994 }
995 BKE_main_unlock(bmain);
996}
997
998void BKE_id_material_assign(Main *bmain, ID *id, Material *ma, short act)
999{
1000 Material *mao, **matar, ***matarar;
1001 short *totcolp;
1002
1003 if (act > MAXMAT) {
1004 return;
1005 }
1006 if (act < 1) {
1007 act = 1;
1008 }
1009
1010 /* test arraylens */
1011
1012 totcolp = BKE_id_material_len_p(id);
1013 matarar = BKE_id_material_array_p(id);
1014
1015 if (totcolp == nullptr || matarar == nullptr) {
1016 return;
1017 }
1018
1019 if (act > *totcolp) {
1020 matar = MEM_cnew_array<Material *>(act, "matarray1");
1021
1022 if (*totcolp) {
1023 memcpy(matar, *matarar, sizeof(void *) * (*totcolp));
1024 MEM_freeN(*matarar);
1025 }
1026
1027 *matarar = matar;
1028 *totcolp = act;
1029 }
1030
1031 /* in data */
1032 mao = (*matarar)[act - 1];
1033 if (mao) {
1034 id_us_min(&mao->id);
1035 }
1036 (*matarar)[act - 1] = ma;
1037
1038 if (ma) {
1039 id_us_plus(&ma->id);
1040 }
1041
1043}
1044
1046 Main *bmain, Object *ob, Material *ma, short act, int assign_type, bool do_test_all)
1047{
1048 Material *mao, **matar, ***matarar;
1049 short *totcolp;
1050 char bit = 0;
1051
1052 if (act > MAXMAT) {
1053 return;
1054 }
1055 if (act < 1) {
1056 act = 1;
1057 }
1058
1059 /* test arraylens */
1060
1061 totcolp = BKE_object_material_len_p(ob);
1062 matarar = BKE_object_material_array_p(ob);
1063
1064 if (totcolp == nullptr || matarar == nullptr) {
1065 return;
1066 }
1067
1068 if (act > *totcolp) {
1069 matar = MEM_cnew_array<Material *>(act, "matarray1");
1070
1071 if (*totcolp) {
1072 memcpy(matar, *matarar, sizeof(void *) * (*totcolp));
1073 MEM_freeN(*matarar);
1074 }
1075
1076 *matarar = matar;
1077 *totcolp = act;
1078 }
1079
1080 if (act > ob->totcol) {
1081 /* Need more space in the material arrays */
1082 ob->mat = static_cast<Material **>(
1083 MEM_recallocN_id(ob->mat, sizeof(void *) * act, "matarray2"));
1084 ob->matbits = static_cast<char *>(
1085 MEM_recallocN_id(ob->matbits, sizeof(char) * act, "matbits1"));
1086 ob->totcol = act;
1087 }
1088
1089 /* Determine the object/mesh linking */
1090 if (assign_type == BKE_MAT_ASSIGN_EXISTING) {
1091 /* keep existing option (avoid confusion in scripts),
1092 * intentionally ignore userpref (default to obdata). */
1093 bit = ob->matbits[act - 1];
1094 }
1095 else if (assign_type == BKE_MAT_ASSIGN_USERPREF && ob->totcol && ob->actcol) {
1096 /* copy from previous material */
1097 bit = ob->matbits[ob->actcol - 1];
1098 }
1099 else {
1100 switch (assign_type) {
1102 bit = 0;
1103 break;
1105 bit = 1;
1106 break;
1108 default:
1109 bit = (U.flag & USER_MAT_ON_OB) ? 1 : 0;
1110 break;
1111 }
1112 }
1113
1114 /* do it */
1115
1116 ob->matbits[act - 1] = bit;
1117 if (bit == 1) { /* in object */
1118 mao = ob->mat[act - 1];
1119 if (mao) {
1120 id_us_min(&mao->id);
1121 }
1122 ob->mat[act - 1] = ma;
1123 BKE_object_materials_test(bmain, ob, static_cast<ID *>(ob->data));
1124 }
1125 else { /* in data */
1126 mao = (*matarar)[act - 1];
1127 if (mao) {
1128 id_us_min(&mao->id);
1129 }
1130 (*matarar)[act - 1] = ma;
1131 /* Data may be used by several objects. */
1132 if (do_test_all) {
1133 BKE_objects_materials_test_all(bmain, static_cast<ID *>(ob->data));
1134 }
1135 }
1136
1137 if (ma) {
1138 id_us_plus(&ma->id);
1139 }
1140}
1141
1142void BKE_object_material_assign(Main *bmain, Object *ob, Material *ma, short act, int assign_type)
1143{
1144 object_material_assign(bmain, ob, ma, act, assign_type, true);
1145}
1146
1148{
1149 object_material_assign(bmain, ob, ma, act, BKE_MAT_ASSIGN_OBDATA, false);
1150}
1151
1153{
1155 const short *totcol_p = BKE_object_material_len_p(ob);
1156
1157 BLI_array_permute(ob->mat, ob->totcol, remap);
1158
1159 if (ob->matbits) {
1160 BLI_array_permute(ob->matbits, ob->totcol, remap);
1161 }
1162
1163 if (matar) {
1164 BLI_array_permute(*matar, *totcol_p, remap);
1165 }
1166
1167 if (ob->type == OB_MESH) {
1168 BKE_mesh_material_remap(static_cast<Mesh *>(ob->data), remap, ob->totcol);
1169 }
1170 else if (ELEM(ob->type, OB_CURVES_LEGACY, OB_SURF, OB_FONT)) {
1171 BKE_curve_material_remap(static_cast<Curve *>(ob->data), remap, ob->totcol);
1172 }
1173 else if (ob->type == OB_GREASE_PENCIL) {
1174 BKE_grease_pencil_material_remap(static_cast<GreasePencil *>(ob->data), remap, ob->totcol);
1175 }
1176 else {
1177 /* add support for this object data! */
1178 BLI_assert(matar == nullptr);
1179 }
1180}
1181
1182void BKE_object_material_remap_calc(Object *ob_dst, Object *ob_src, short *remap_src_to_dst)
1183{
1184 if (ob_src->totcol == 0) {
1185 return;
1186 }
1187
1188 GHash *gh_mat_map = BLI_ghash_ptr_new_ex(__func__, ob_src->totcol);
1189
1190 for (int i = 0; i < ob_dst->totcol; i++) {
1191 Material *ma_src = BKE_object_material_get(ob_dst, i + 1);
1192 BLI_ghash_reinsert(gh_mat_map, ma_src, POINTER_FROM_INT(i), nullptr, nullptr);
1193 }
1194
1195 /* setup default mapping (when materials don't match) */
1196 {
1197 int i = 0;
1198 if (ob_dst->totcol >= ob_src->totcol) {
1199 for (; i < ob_src->totcol; i++) {
1200 remap_src_to_dst[i] = i;
1201 }
1202 }
1203 else {
1204 for (; i < ob_dst->totcol; i++) {
1205 remap_src_to_dst[i] = i;
1206 }
1207 for (; i < ob_src->totcol; i++) {
1208 remap_src_to_dst[i] = 0;
1209 }
1210 }
1211 }
1212
1213 for (int i = 0; i < ob_src->totcol; i++) {
1214 Material *ma_src = BKE_object_material_get(ob_src, i + 1);
1215
1216 if ((i < ob_dst->totcol) && (ma_src == BKE_object_material_get(ob_dst, i + 1))) {
1217 /* when objects have exact matching materials - keep existing index */
1218 }
1219 else {
1220 void **index_src_p = BLI_ghash_lookup_p(gh_mat_map, ma_src);
1221 if (index_src_p) {
1222 remap_src_to_dst[i] = POINTER_AS_INT(*index_src_p);
1223 }
1224 }
1225 }
1226
1227 BLI_ghash_free(gh_mat_map, nullptr, nullptr);
1228}
1229
1230void BKE_object_material_from_eval_data(Main *bmain, Object *ob_orig, const ID *data_eval)
1231{
1232 ID *data_orig = static_cast<ID *>(ob_orig->data);
1233
1234 short *orig_totcol = BKE_id_material_len_p(data_orig);
1235 Material ***orig_mat = BKE_id_material_array_p(data_orig);
1236
1237 /* Can cast away const, because the data is not changed. */
1238 const short *eval_totcol = BKE_id_material_len_p((ID *)data_eval);
1239 Material ***eval_mat = BKE_id_material_array_p((ID *)data_eval);
1240
1241 if (ELEM(nullptr, orig_totcol, orig_mat, eval_totcol, eval_mat)) {
1242 return;
1243 }
1244
1245 /* Remove old materials from original geometry. */
1246 for (int i = 0; i < *orig_totcol; i++) {
1247 id_us_min(&(*orig_mat)[i]->id);
1248 }
1249 MEM_SAFE_FREE(*orig_mat);
1250
1251 /* Create new material slots based on materials on evaluated geometry. */
1252 *orig_totcol = *eval_totcol;
1253 *orig_mat = *eval_totcol > 0 ? MEM_cnew_array<Material *>(*eval_totcol, __func__) : nullptr;
1254 for (int i = 0; i < *eval_totcol; i++) {
1255 Material *material_eval = (*eval_mat)[i];
1256 if (material_eval != nullptr) {
1257 Material *material_orig = (Material *)DEG_get_original_id(&material_eval->id);
1258 (*orig_mat)[i] = material_orig;
1259 id_us_plus(&material_orig->id);
1260 }
1261 }
1262 BKE_object_materials_test(bmain, ob_orig, data_orig);
1263}
1264
1266 Main *bmain, Object *ob, Material ***matar, int totcol, const bool to_object_only)
1267{
1268 int actcol_orig = ob->actcol;
1269
1270 while ((ob->totcol > totcol) && BKE_object_material_slot_remove(bmain, ob)) {
1271 /* pass */
1272 }
1273
1274 /* now we have the right number of slots */
1275 for (int i = 0; i < totcol; i++) {
1276 if (to_object_only && ob->matbits && ob->matbits[i] == 0) {
1277 /* If we only assign to object, and that slot uses obdata material, do nothing. */
1278 continue;
1279 }
1281 ob,
1282 (*matar)[i],
1283 i + 1,
1285 }
1286
1287 if (actcol_orig > ob->totcol) {
1288 actcol_orig = ob->totcol;
1289 }
1290
1291 ob->actcol = actcol_orig;
1292}
1293
1295{
1296 Material ***matarar;
1297 short a, *totcolp;
1298
1299 if (ma == nullptr) {
1300 return 0;
1301 }
1302
1303 totcolp = BKE_object_material_len_p(ob);
1304 matarar = BKE_object_material_array_p(ob);
1305
1306 if (totcolp == nullptr || matarar == nullptr) {
1307 return 0;
1308 }
1309
1310 for (a = 0; a < *totcolp; a++) {
1311 if ((*matarar)[a] == ma) {
1312 break;
1313 }
1314 }
1315 if (a < *totcolp) {
1316 return a + 1;
1317 }
1318 return 0;
1319}
1320
1322{
1323 if (ob == nullptr) {
1324 return false;
1325 }
1326 if (ob->totcol >= MAXMAT) {
1327 return false;
1328 }
1329
1330 BKE_object_material_assign(bmain, ob, nullptr, ob->totcol + 1, BKE_MAT_ASSIGN_USERPREF);
1331 ob->actcol = ob->totcol;
1332 return true;
1333}
1334
1335/* ****************** */
1336
1338{
1339 Material *mao, ***matarar;
1340 short *totcolp;
1341
1342 if (ob == nullptr || ob->totcol == 0) {
1343 return false;
1344 }
1345
1346 /* this should never happen and used to crash */
1347 if (ob->actcol <= 0) {
1348 CLOG_ERROR(&LOG, "invalid material index %d, report a bug!", ob->actcol);
1349 return false;
1350 }
1351
1352 /* Take a mesh/curve/meta-ball as starting point, remove 1 index,
1353 * AND with all objects that share the `ob->data`.
1354 * After that check indices in mesh/curve/meta-ball! */
1355
1356 totcolp = BKE_object_material_len_p(ob);
1357 matarar = BKE_object_material_array_p(ob);
1358
1359 if (ELEM(nullptr, matarar, *matarar)) {
1360 return false;
1361 }
1362
1363 /* can happen on face selection in editmode */
1364 if (ob->actcol > ob->totcol) {
1365 ob->actcol = ob->totcol;
1366 }
1367
1368 /* we delete the actcol */
1369 mao = (*matarar)[ob->actcol - 1];
1370 if (mao) {
1371 id_us_min(&mao->id);
1372 }
1373
1374 for (int a = ob->actcol; a < ob->totcol; a++) {
1375 (*matarar)[a - 1] = (*matarar)[a];
1376 }
1377 (*totcolp)--;
1378
1379 if (*totcolp == 0) {
1380 MEM_freeN(*matarar);
1381 *matarar = nullptr;
1382 }
1383
1384 const int actcol = ob->actcol;
1385
1386 for (Object *obt = static_cast<Object *>(bmain->objects.first); obt;
1387 obt = static_cast<Object *>(obt->id.next))
1388 {
1389 if (obt->data == ob->data) {
1390 /* Can happen when object material lists are used, see: #52953 */
1391 if (actcol > obt->totcol) {
1392 continue;
1393 }
1394 /* WATCH IT: do not use actcol from ob or from obt (can become zero) */
1395 mao = obt->mat[actcol - 1];
1396 if (mao) {
1397 id_us_min(&mao->id);
1398 }
1399
1400 for (int a = actcol; a < obt->totcol; a++) {
1401 obt->mat[a - 1] = obt->mat[a];
1402 obt->matbits[a - 1] = obt->matbits[a];
1403 }
1404 obt->totcol--;
1405 if (obt->actcol > obt->totcol) {
1406 obt->actcol = obt->totcol;
1407 }
1408
1409 if (obt->totcol == 0) {
1410 MEM_freeN(obt->mat);
1411 MEM_freeN(obt->matbits);
1412 obt->mat = nullptr;
1413 obt->matbits = nullptr;
1414 }
1415 }
1416 }
1417
1418 /* check indices from mesh and grease pencil. */
1420 material_data_index_remove_id((ID *)ob->data, actcol - 1);
1421 if (ob->runtime->curve_cache) {
1422 BKE_displist_free(&ob->runtime->curve_cache->disp);
1423 }
1424 }
1425
1426 return true;
1427}
1428
1430{
1431 LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
1432 if (sock->link) {
1433 bNode *inode = sock->link->fromnode;
1434 if (inode->typeinfo->nclass == NODE_CLASS_INPUT && inode->typeinfo->type == SH_NODE_UVMAP) {
1435 return inode;
1436 }
1437
1438 return nodetree_uv_node_recursive(inode);
1439 }
1440 }
1441
1442 return nullptr;
1443}
1444
1451
1452using ForEachTexNodeCallback = bool (*)(bNode *node, void *userdata);
1455 void *userdata,
1456 ePaintSlotFilter slot_filter)
1457{
1458 const bool do_image_nodes = (slot_filter & PAINT_SLOT_IMAGE) != 0;
1459 const bool do_color_attributes = (slot_filter & PAINT_SLOT_COLOR_ATTRIBUTE) != 0;
1460 for (bNode *node : nodetree->all_nodes()) {
1461 if (do_image_nodes && node->typeinfo->nclass == NODE_CLASS_TEXTURE &&
1462 node->typeinfo->type == SH_NODE_TEX_IMAGE && node->id)
1463 {
1464 if (!callback(node, userdata)) {
1465 return false;
1466 }
1467 }
1468 if (do_color_attributes && node->typeinfo->type == SH_NODE_ATTRIBUTE) {
1469 if (!callback(node, userdata)) {
1470 return false;
1471 }
1472 }
1473 else if (ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP) && node->id) {
1474 /* recurse into the node group and see if it contains any textures */
1475 if (!ntree_foreach_texnode_recursive((bNodeTree *)node->id, callback, userdata, slot_filter))
1476 {
1477 return false;
1478 }
1479 }
1480 }
1481 return true;
1482}
1483
1484static bool count_texture_nodes_cb(bNode * /*node*/, void *userdata)
1485{
1486 (*((int *)userdata))++;
1487 return true;
1488}
1489
1491{
1492 int tex_nodes = 0;
1493 ntree_foreach_texnode_recursive(nodetree, count_texture_nodes_cb, &tex_nodes, slot_filter);
1494
1495 return tex_nodes;
1496}
1497
1505
1506static bool fill_texpaint_slots_cb(bNode *node, void *userdata)
1507{
1508 FillTexPaintSlotsData *fill_data = static_cast<FillTexPaintSlotsData *>(userdata);
1509
1510 Material *ma = fill_data->ma;
1511 int index = fill_data->index;
1512 fill_data->index++;
1513
1514 if (fill_data->active_node == node) {
1515 ma->paint_active_slot = index;
1516 }
1517
1518 switch (node->type) {
1519 case SH_NODE_TEX_IMAGE: {
1520 TexPaintSlot *slot = &ma->texpaintslot[index];
1521 slot->ima = (Image *)node->id;
1522 NodeTexImage *storage = (NodeTexImage *)node->storage;
1523 slot->interp = storage->interpolation;
1524 slot->image_user = &storage->iuser;
1525 /* For new renderer, we need to traverse the tree back in search of a UV node. */
1526 bNode *uvnode = nodetree_uv_node_recursive(node);
1527
1528 if (uvnode) {
1529 NodeShaderUVMap *uv_storage = (NodeShaderUVMap *)uvnode->storage;
1530 slot->uvname = uv_storage->uv_map;
1531 /* set a value to index so UI knows that we have a valid pointer for the mesh */
1532 slot->valid = true;
1533 }
1534 else {
1535 /* just invalidate the index here so UV map does not get displayed on the UI */
1536 slot->valid = false;
1537 }
1538 break;
1539 }
1540
1541 case SH_NODE_ATTRIBUTE: {
1542 TexPaintSlot *slot = &ma->texpaintslot[index];
1543 NodeShaderAttribute *storage = static_cast<NodeShaderAttribute *>(node->storage);
1544 slot->attribute_name = storage->name;
1545 if (storage->type == SHD_ATTRIBUTE_GEOMETRY) {
1546 const Mesh *mesh = (const Mesh *)fill_data->ob->data;
1547 const CustomDataLayer *layer = BKE_id_attributes_color_find(&mesh->id, storage->name);
1548 slot->valid = layer != nullptr;
1549 }
1550
1551 /* Do not show unsupported attributes. */
1552 if (!slot->valid) {
1553 slot->attribute_name = nullptr;
1554 fill_data->index--;
1555 }
1556
1557 break;
1558 }
1559 }
1560
1561 return fill_data->index != fill_data->slot_len;
1562}
1563
1565 bNode *active_node,
1566 const Object *ob,
1567 Material *ma,
1568 int slot_len,
1569 ePaintSlotFilter slot_filter)
1570{
1571 FillTexPaintSlotsData fill_data = {active_node, ob, ma, 0, slot_len};
1572 ntree_foreach_texnode_recursive(nodetree, fill_texpaint_slots_cb, &fill_data, slot_filter);
1573}
1574
1577{
1578 ePaintSlotFilter slot_filter = PAINT_SLOT_IMAGE;
1579 if (ob->mode == OB_MODE_SCULPT && U.experimental.use_sculpt_texture_paint) {
1580 slot_filter |= PAINT_SLOT_COLOR_ATTRIBUTE;
1581 }
1582 return slot_filter;
1583}
1584
1586{
1587 if (!ma) {
1588 return;
1589 }
1590
1591 const ePaintSlotFilter slot_filter = material_paint_slot_filter(ob);
1592
1593 const TexPaintSlot *prev_texpaintslot = ma->texpaintslot;
1594 const int prev_paint_active_slot = ma->paint_active_slot;
1595 const int prev_paint_clone_slot = ma->paint_clone_slot;
1596 const int prev_tot_slots = ma->tot_slots;
1597
1598 ma->texpaintslot = nullptr;
1599 ma->tot_slots = 0;
1600
1601 if (scene->toolsettings->imapaint.mode == IMAGEPAINT_MODE_IMAGE) {
1602 ma->paint_active_slot = 0;
1603 ma->paint_clone_slot = 0;
1604 }
1605 else if (!(ma->nodetree)) {
1606 ma->paint_active_slot = 0;
1607 ma->paint_clone_slot = 0;
1608 }
1609 else {
1610 int count = count_texture_nodes_recursive(ma->nodetree, slot_filter);
1611
1612 if (count == 0) {
1613 ma->paint_active_slot = 0;
1614 ma->paint_clone_slot = 0;
1615 }
1616 else {
1617 ma->texpaintslot = static_cast<TexPaintSlot *>(
1618 MEM_callocN(sizeof(TexPaintSlot) * count, "texpaint_slots"));
1619
1621
1622 fill_texpaint_slots_recursive(ma->nodetree, active_node, ob, ma, count, slot_filter);
1623
1624 ma->tot_slots = count;
1625
1626 if (ma->paint_active_slot >= count) {
1627 ma->paint_active_slot = count - 1;
1628 }
1629
1630 if (ma->paint_clone_slot >= count) {
1631 ma->paint_clone_slot = count - 1;
1632 }
1633 }
1634 }
1635
1636 /* Copy-on-eval needed when adding texture slot on an object with no materials.
1637 * But do it only when slots actually change to avoid continuous depsgraph updates. */
1638 if (ma->tot_slots != prev_tot_slots || ma->paint_active_slot != prev_paint_active_slot ||
1639 ma->paint_clone_slot != prev_paint_clone_slot ||
1640 (ma->texpaintslot && prev_texpaintslot &&
1641 memcmp(ma->texpaintslot, prev_texpaintslot, sizeof(*ma->texpaintslot) * ma->tot_slots) !=
1642 0))
1643 {
1645 }
1646
1647 MEM_SAFE_FREE(prev_texpaintslot);
1648}
1649
1651{
1652 for (int i = 1; i < ob->totcol + 1; i++) {
1653 Material *ma = BKE_object_material_get(ob, i);
1654 BKE_texpaint_slot_refresh_cache(scene, ma, ob);
1655 }
1656}
1657
1662
1663static bool texpaint_slot_node_find_cb(bNode *node, void *userdata)
1664{
1665 FindTexPaintNodeData *find_data = static_cast<FindTexPaintNodeData *>(userdata);
1666 if (find_data->slot->ima && node->type == SH_NODE_TEX_IMAGE) {
1667 Image *node_ima = (Image *)node->id;
1668 if (find_data->slot->ima == node_ima) {
1669 find_data->r_node = node;
1670 return false;
1671 }
1672 }
1673
1674 if (find_data->slot->attribute_name && node->type == SH_NODE_ATTRIBUTE) {
1675 NodeShaderAttribute *storage = static_cast<NodeShaderAttribute *>(node->storage);
1676 if (STREQLEN(find_data->slot->attribute_name, storage->name, sizeof(storage->name))) {
1677 find_data->r_node = node;
1678 return false;
1679 }
1680 }
1681
1682 return true;
1683}
1684
1686{
1687 if (ma->texpaintslot == nullptr) {
1688 return nullptr;
1689 }
1690
1691 if (texpaint_slot >= ma->tot_slots) {
1692 return nullptr;
1693 }
1694
1695 TexPaintSlot *slot = &ma->texpaintslot[texpaint_slot];
1696 FindTexPaintNodeData find_data = {slot, nullptr};
1699 &find_data,
1701
1702 return find_data.r_node;
1703}
1704
1705void ramp_blend(int type, float r_col[3], const float fac, const float col[3])
1706{
1707 float tmp, facm = 1.0f - fac;
1708
1709 switch (type) {
1710 case MA_RAMP_BLEND:
1711 r_col[0] = facm * (r_col[0]) + fac * col[0];
1712 r_col[1] = facm * (r_col[1]) + fac * col[1];
1713 r_col[2] = facm * (r_col[2]) + fac * col[2];
1714 break;
1715 case MA_RAMP_ADD:
1716 r_col[0] += fac * col[0];
1717 r_col[1] += fac * col[1];
1718 r_col[2] += fac * col[2];
1719 break;
1720 case MA_RAMP_MULT:
1721 r_col[0] *= (facm + fac * col[0]);
1722 r_col[1] *= (facm + fac * col[1]);
1723 r_col[2] *= (facm + fac * col[2]);
1724 break;
1725 case MA_RAMP_SCREEN:
1726 r_col[0] = 1.0f - (facm + fac * (1.0f - col[0])) * (1.0f - r_col[0]);
1727 r_col[1] = 1.0f - (facm + fac * (1.0f - col[1])) * (1.0f - r_col[1]);
1728 r_col[2] = 1.0f - (facm + fac * (1.0f - col[2])) * (1.0f - r_col[2]);
1729 break;
1730 case MA_RAMP_OVERLAY:
1731 if (r_col[0] < 0.5f) {
1732 r_col[0] *= (facm + 2.0f * fac * col[0]);
1733 }
1734 else {
1735 r_col[0] = 1.0f - (facm + 2.0f * fac * (1.0f - col[0])) * (1.0f - r_col[0]);
1736 }
1737 if (r_col[1] < 0.5f) {
1738 r_col[1] *= (facm + 2.0f * fac * col[1]);
1739 }
1740 else {
1741 r_col[1] = 1.0f - (facm + 2.0f * fac * (1.0f - col[1])) * (1.0f - r_col[1]);
1742 }
1743 if (r_col[2] < 0.5f) {
1744 r_col[2] *= (facm + 2.0f * fac * col[2]);
1745 }
1746 else {
1747 r_col[2] = 1.0f - (facm + 2.0f * fac * (1.0f - col[2])) * (1.0f - r_col[2]);
1748 }
1749 break;
1750 case MA_RAMP_SUB:
1751 r_col[0] -= fac * col[0];
1752 r_col[1] -= fac * col[1];
1753 r_col[2] -= fac * col[2];
1754 break;
1755 case MA_RAMP_DIV:
1756 if (col[0] != 0.0f) {
1757 r_col[0] = facm * (r_col[0]) + fac * (r_col[0]) / col[0];
1758 }
1759 if (col[1] != 0.0f) {
1760 r_col[1] = facm * (r_col[1]) + fac * (r_col[1]) / col[1];
1761 }
1762 if (col[2] != 0.0f) {
1763 r_col[2] = facm * (r_col[2]) + fac * (r_col[2]) / col[2];
1764 }
1765 break;
1766 case MA_RAMP_DIFF:
1767 r_col[0] = facm * (r_col[0]) + fac * fabsf(r_col[0] - col[0]);
1768 r_col[1] = facm * (r_col[1]) + fac * fabsf(r_col[1] - col[1]);
1769 r_col[2] = facm * (r_col[2]) + fac * fabsf(r_col[2] - col[2]);
1770 break;
1771 case MA_RAMP_EXCLUSION:
1772 r_col[0] = max_ff(facm * (r_col[0]) + fac * (r_col[0] + col[0] - 2.0f * r_col[0] * col[0]),
1773 0.0f);
1774 r_col[1] = max_ff(facm * (r_col[1]) + fac * (r_col[1] + col[1] - 2.0f * r_col[1] * col[1]),
1775 0.0f);
1776 r_col[2] = max_ff(facm * (r_col[2]) + fac * (r_col[2] + col[2] - 2.0f * r_col[2] * col[2]),
1777 0.0f);
1778 break;
1779 case MA_RAMP_DARK:
1780 r_col[0] = min_ff(r_col[0], col[0]) * fac + r_col[0] * facm;
1781 r_col[1] = min_ff(r_col[1], col[1]) * fac + r_col[1] * facm;
1782 r_col[2] = min_ff(r_col[2], col[2]) * fac + r_col[2] * facm;
1783 break;
1784 case MA_RAMP_LIGHT:
1785 tmp = fac * col[0];
1786 if (tmp > r_col[0]) {
1787 r_col[0] = tmp;
1788 }
1789 tmp = fac * col[1];
1790 if (tmp > r_col[1]) {
1791 r_col[1] = tmp;
1792 }
1793 tmp = fac * col[2];
1794 if (tmp > r_col[2]) {
1795 r_col[2] = tmp;
1796 }
1797 break;
1798 case MA_RAMP_DODGE:
1799 if (r_col[0] != 0.0f) {
1800 tmp = 1.0f - fac * col[0];
1801 if (tmp <= 0.0f) {
1802 r_col[0] = 1.0f;
1803 }
1804 else if ((tmp = (r_col[0]) / tmp) > 1.0f) {
1805 r_col[0] = 1.0f;
1806 }
1807 else {
1808 r_col[0] = tmp;
1809 }
1810 }
1811 if (r_col[1] != 0.0f) {
1812 tmp = 1.0f - fac * col[1];
1813 if (tmp <= 0.0f) {
1814 r_col[1] = 1.0f;
1815 }
1816 else if ((tmp = (r_col[1]) / tmp) > 1.0f) {
1817 r_col[1] = 1.0f;
1818 }
1819 else {
1820 r_col[1] = tmp;
1821 }
1822 }
1823 if (r_col[2] != 0.0f) {
1824 tmp = 1.0f - fac * col[2];
1825 if (tmp <= 0.0f) {
1826 r_col[2] = 1.0f;
1827 }
1828 else if ((tmp = (r_col[2]) / tmp) > 1.0f) {
1829 r_col[2] = 1.0f;
1830 }
1831 else {
1832 r_col[2] = tmp;
1833 }
1834 }
1835 break;
1836 case MA_RAMP_BURN:
1837 tmp = facm + fac * col[0];
1838
1839 if (tmp <= 0.0f) {
1840 r_col[0] = 0.0f;
1841 }
1842 else if ((tmp = (1.0f - (1.0f - (r_col[0])) / tmp)) < 0.0f) {
1843 r_col[0] = 0.0f;
1844 }
1845 else if (tmp > 1.0f) {
1846 r_col[0] = 1.0f;
1847 }
1848 else {
1849 r_col[0] = tmp;
1850 }
1851
1852 tmp = facm + fac * col[1];
1853 if (tmp <= 0.0f) {
1854 r_col[1] = 0.0f;
1855 }
1856 else if ((tmp = (1.0f - (1.0f - (r_col[1])) / tmp)) < 0.0f) {
1857 r_col[1] = 0.0f;
1858 }
1859 else if (tmp > 1.0f) {
1860 r_col[1] = 1.0f;
1861 }
1862 else {
1863 r_col[1] = tmp;
1864 }
1865
1866 tmp = facm + fac * col[2];
1867 if (tmp <= 0.0f) {
1868 r_col[2] = 0.0f;
1869 }
1870 else if ((tmp = (1.0f - (1.0f - (r_col[2])) / tmp)) < 0.0f) {
1871 r_col[2] = 0.0f;
1872 }
1873 else if (tmp > 1.0f) {
1874 r_col[2] = 1.0f;
1875 }
1876 else {
1877 r_col[2] = tmp;
1878 }
1879 break;
1880 case MA_RAMP_HUE: {
1881 float rH, rS, rV;
1882 float colH, colS, colV;
1883 float tmpr, tmpg, tmpb;
1884 rgb_to_hsv(col[0], col[1], col[2], &colH, &colS, &colV);
1885 if (colS != 0) {
1886 rgb_to_hsv(r_col[0], r_col[1], r_col[2], &rH, &rS, &rV);
1887 hsv_to_rgb(colH, rS, rV, &tmpr, &tmpg, &tmpb);
1888 r_col[0] = facm * (r_col[0]) + fac * tmpr;
1889 r_col[1] = facm * (r_col[1]) + fac * tmpg;
1890 r_col[2] = facm * (r_col[2]) + fac * tmpb;
1891 }
1892 break;
1893 }
1894 case MA_RAMP_SAT: {
1895 float rH, rS, rV;
1896 float colH, colS, colV;
1897 rgb_to_hsv(r_col[0], r_col[1], r_col[2], &rH, &rS, &rV);
1898 if (rS != 0) {
1899 rgb_to_hsv(col[0], col[1], col[2], &colH, &colS, &colV);
1900 hsv_to_rgb(rH, (facm * rS + fac * colS), rV, r_col + 0, r_col + 1, r_col + 2);
1901 }
1902 break;
1903 }
1904 case MA_RAMP_VAL: {
1905 float rH, rS, rV;
1906 float colH, colS, colV;
1907 rgb_to_hsv(r_col[0], r_col[1], r_col[2], &rH, &rS, &rV);
1908 rgb_to_hsv(col[0], col[1], col[2], &colH, &colS, &colV);
1909 hsv_to_rgb(rH, rS, (facm * rV + fac * colV), r_col + 0, r_col + 1, r_col + 2);
1910 break;
1911 }
1912 case MA_RAMP_COLOR: {
1913 float rH, rS, rV;
1914 float colH, colS, colV;
1915 float tmpr, tmpg, tmpb;
1916 rgb_to_hsv(col[0], col[1], col[2], &colH, &colS, &colV);
1917 if (colS != 0) {
1918 rgb_to_hsv(r_col[0], r_col[1], r_col[2], &rH, &rS, &rV);
1919 hsv_to_rgb(colH, colS, rV, &tmpr, &tmpg, &tmpb);
1920 r_col[0] = facm * (r_col[0]) + fac * tmpr;
1921 r_col[1] = facm * (r_col[1]) + fac * tmpg;
1922 r_col[2] = facm * (r_col[2]) + fac * tmpb;
1923 }
1924 break;
1925 }
1926 case MA_RAMP_SOFT: {
1927 float scr, scg, scb;
1928
1929 /* first calculate non-fac based Screen mix */
1930 scr = 1.0f - (1.0f - col[0]) * (1.0f - r_col[0]);
1931 scg = 1.0f - (1.0f - col[1]) * (1.0f - r_col[1]);
1932 scb = 1.0f - (1.0f - col[2]) * (1.0f - r_col[2]);
1933
1934 r_col[0] = facm * (r_col[0]) +
1935 fac * (((1.0f - r_col[0]) * col[0] * (r_col[0])) + (r_col[0] * scr));
1936 r_col[1] = facm * (r_col[1]) +
1937 fac * (((1.0f - r_col[1]) * col[1] * (r_col[1])) + (r_col[1] * scg));
1938 r_col[2] = facm * (r_col[2]) +
1939 fac * (((1.0f - r_col[2]) * col[2] * (r_col[2])) + (r_col[2] * scb));
1940 break;
1941 }
1942 case MA_RAMP_LINEAR:
1943 if (col[0] > 0.5f) {
1944 r_col[0] = r_col[0] + fac * (2.0f * (col[0] - 0.5f));
1945 }
1946 else {
1947 r_col[0] = r_col[0] + fac * (2.0f * (col[0]) - 1.0f);
1948 }
1949 if (col[1] > 0.5f) {
1950 r_col[1] = r_col[1] + fac * (2.0f * (col[1] - 0.5f));
1951 }
1952 else {
1953 r_col[1] = r_col[1] + fac * (2.0f * (col[1]) - 1.0f);
1954 }
1955 if (col[2] > 0.5f) {
1956 r_col[2] = r_col[2] + fac * (2.0f * (col[2] - 0.5f));
1957 }
1958 else {
1959 r_col[2] = r_col[2] + fac * (2.0f * (col[2]) - 1.0f);
1960 }
1961 break;
1962 }
1963}
1964
1965void BKE_material_eval(Depsgraph *depsgraph, Material *material)
1966{
1967 DEG_debug_print_eval(depsgraph, __func__, material->id.name, material);
1968 GPU_material_free(&material->gpumaterial);
1969}
1970
1971/* Default Materials
1972 *
1973 * Used for rendering when objects have no materials assigned, and initializing
1974 * default shader nodes. */
1975
1981
1988
1990{
1991 BLI_strncpy(ma->id.name + 2, "Default GPencil", MAX_NAME);
1993 add_v3_fl(&ma->gp_style->stroke_rgba[0], 0.6f);
1994}
1995
1997{
1998 BLI_strncpy(ma->id.name + 2, "Default Surface", MAX_NAME);
1999
2001 nullptr, &ma->id, "Shader Nodetree", ntreeType_Shader->idname);
2002 ma->use_nodes = true;
2003
2004 bNode *principled = blender::bke::node_add_static_node(nullptr, ntree, SH_NODE_BSDF_PRINCIPLED);
2005 bNodeSocket *base_color = blender::bke::node_find_socket(principled, SOCK_IN, "Base Color");
2006 copy_v3_v3(((bNodeSocketValueRGBA *)base_color->default_value)->value, &ma->r);
2007
2009
2011 principled,
2012 blender::bke::node_find_socket(principled, SOCK_OUT, "BSDF"),
2013 output,
2014 blender::bke::node_find_socket(output, SOCK_IN, "Surface"));
2015
2016 principled->locx = 10.0f;
2017 principled->locy = 300.0f;
2018 output->locx = 300.0f;
2019 output->locy = 300.0f;
2020
2021 blender::bke::node_set_active(ntree, output);
2022}
2023
2025{
2026 BLI_strncpy(ma->id.name + 2, "Default Volume", MAX_NAME);
2027
2029 nullptr, &ma->id, "Shader Nodetree", ntreeType_Shader->idname);
2030 ma->use_nodes = true;
2031
2033 nullptr, ntree, SH_NODE_VOLUME_PRINCIPLED);
2035
2037 principled,
2038 blender::bke::node_find_socket(principled, SOCK_OUT, "Volume"),
2039 output,
2040 blender::bke::node_find_socket(output, SOCK_IN, "Volume"));
2041
2042 principled->locx = 10.0f;
2043 principled->locy = 300.0f;
2044 output->locx = 300.0f;
2045 output->locy = 300.0f;
2046
2047 blender::bke::node_set_active(ntree, output);
2048}
2049
2051{
2052 BLI_strncpy(ma->id.name + 2, "Default Holdout", MAX_NAME);
2053
2055 nullptr, &ma->id, "Shader Nodetree", ntreeType_Shader->idname);
2056 ma->use_nodes = true;
2057
2058 bNode *holdout = blender::bke::node_add_static_node(nullptr, ntree, SH_NODE_HOLDOUT);
2060
2062 holdout,
2063 blender::bke::node_find_socket(holdout, SOCK_OUT, "Holdout"),
2064 output,
2065 blender::bke::node_find_socket(output, SOCK_IN, "Surface"));
2066
2067 holdout->locx = 10.0f;
2068 holdout->locy = 300.0f;
2069 output->locx = 300.0f;
2070 output->locy = 300.0f;
2071
2072 blender::bke::node_set_active(ntree, output);
2073}
2074
2079
2084
2089
2094
2099
2101{
2102 for (int i = 0; default_materials[i]; i++) {
2103 Material *ma = default_materials[i];
2104 if (ma->gpumaterial.first) {
2106 }
2107 }
2108}
2109
2110/* Module functions called on startup and exit. */
2111
2123
2125{
2126 for (int i = 0; default_materials[i]; i++) {
2128 }
2129}
const struct CustomDataLayer * BKE_id_attributes_color_find(const struct ID *id, const char *name)
void BKE_curve_material_remap(Curve *cu, const unsigned int *remap, unsigned int remap_len)
Definition curve.cc:5385
void BKE_curve_material_index_remove(Curve *cu, int index)
Definition curve.cc:5291
bool BKE_curve_material_index_used(const Curve *cu, int index)
Definition curve.cc:5312
void BKE_curve_material_index_clear(Curve *cu)
Definition curve.cc:5335
display list (or rather multi purpose list) stuff.
void BKE_displist_free(struct ListBase *lb)
Definition displist.cc:64
Low-level operations for grease pencil.
void BKE_grease_pencil_material_remap(GreasePencil *grease_pencil, const uint *remap, int totcol)
void BKE_grease_pencil_material_index_remove(GreasePencil *grease_pencil, int index)
bool BKE_grease_pencil_material_index_used(GreasePencil *grease_pencil, int index)
void BKE_icon_id_delete(struct ID *id)
Definition icons.cc:451
@ IDTYPE_FLAGS_APPEND_IS_REUSABLE
Definition BKE_idtype.hh:39
@ LIB_ID_COPY_NO_PREVIEW
@ LIB_ID_CREATE_LOCAL
@ LIB_ID_CREATE_NO_USER_REFCOUNT
void id_us_plus(ID *id)
Definition lib_id.cc:351
struct ID * BKE_id_copy_in_lib(Main *bmain, std::optional< Library * > owner_library, const ID *id, const ID *new_owner_id, ID **new_id_p, int flag)
Definition lib_id.cc:656
void * BKE_id_new(Main *bmain, short type, const char *name)
Definition lib_id.cc:1482
void id_us_min(ID *id)
Definition lib_id.cc:359
void BKE_id_blend_write(BlendWriter *writer, ID *id)
Definition lib_id.cc:2560
#define BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(data_, func_call_)
#define BKE_LIB_FOREACHID_PROCESS_IDSUPER(data_, id_super_, cb_flag_)
void BKE_library_foreach_ID_embedded(LibraryForeachIDData *data, ID **id_pp)
Definition lib_query.cc:163
@ IDWALK_CB_USER
@ IDWALK_CB_NOP
int BKE_lib_query_foreachid_process_flags_get(const LibraryForeachIDData *data)
Definition lib_query.cc:120
@ IDWALK_DO_DEPRECATED_POINTERS
#define BKE_LIB_FOREACHID_PROCESS_ID_NOCHECK(data_, id_, cb_flag_)
void BKE_main_lock(Main *bmain)
Definition main.cc:479
void BKE_main_unlock(Main *bmain)
Definition main.cc:484
General operations, lookup, etc. for materials.
@ BKE_MAT_ASSIGN_OBDATA
@ BKE_MAT_ASSIGN_USERPREF
@ BKE_MAT_ASSIGN_OBJECT
@ BKE_MAT_ASSIGN_EXISTING
void BKE_mesh_material_remap(Mesh *mesh, const unsigned int *remap, unsigned int remap_len)
bool BKE_mesh_material_index_used(Mesh *mesh, short index)
void BKE_mesh_material_index_clear(Mesh *mesh)
void BKE_mesh_material_index_remove(Mesh *mesh, short index)
#define SH_NODE_UVMAP
Definition BKE_node.hh:970
#define SH_NODE_TEX_IMAGE
Definition BKE_node.hh:930
#define NODE_CUSTOM_GROUP
Definition BKE_node.hh:807
#define SH_NODE_OUTPUT_MATERIAL
Definition BKE_node.hh:913
#define NODE_GROUP
Definition BKE_node.hh:800
#define NODE_CLASS_INPUT
Definition BKE_node.hh:404
#define NODE_CLASS_TEXTURE
Definition BKE_node.hh:414
#define SH_NODE_ATTRIBUTE
Definition BKE_node.hh:918
General operations, lookup, etc. for blender objects.
bool BKE_object_supports_material_slots(Object *ob)
const Mesh * BKE_object_get_editmesh_eval_final(const Object *object)
void BKE_previewimg_blend_write(BlendWriter *writer, const PreviewImage *prv)
void BKE_previewimg_free(PreviewImage **prv)
void BKE_previewimg_blend_read(BlendDataReader *reader, PreviewImage *prv)
void BKE_previewimg_id_copy(ID *new_id, const ID *old_id)
Generic array manipulation API.
#define BLI_array_permute(arr, arr_len, order)
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
#define BLI_assert(a)
Definition BLI_assert.h:50
bool BLI_ghash_reinsert(GHash *gh, void *key, void *val, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition BLI_ghash.c:712
void ** BLI_ghash_lookup_p(GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.c:745
GHash * BLI_ghash_ptr_new_ex(const char *info, unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition BLI_ghash.c:860
#define LISTBASE_FOREACH(type, var, list)
BLI_INLINE void BLI_listbase_clear(struct ListBase *lb)
MINLINE float max_ff(float a, float b)
MINLINE float min_ff(float a, float b)
MINLINE int clamp_i(int value, int min, int max)
void rgb_to_hsv(float r, float g, float b, float *r_h, float *r_s, float *r_v)
void hsv_to_rgb(float h, float s, float v, float *r_r, float *r_g, float *r_b)
Definition math_color.cc:21
MINLINE void add_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
unsigned int uint
#define ARRAY_SET_ITEMS(...)
#define STREQLEN(a, b, n)
#define ENUM_OPERATORS(_type, _max)
#define POINTER_FROM_INT(i)
#define POINTER_AS_INT(i)
#define ELEM(...)
#define MEMCMP_STRUCT_AFTER_IS_ZERO(struct_var, member)
#define MEMCPY_STRUCT_AFTER(struct_dst, struct_src, member)
BLO_Write_IDBuffer * BLO_write_allocate_id_buffer()
#define BLO_write_id_struct(writer, struct_name, id_address, id)
#define BLO_write_struct(writer, struct_name, data_ptr)
void BLO_write_init_id_buffer_from_id(BLO_Write_IDBuffer *id_buffer, ID *id, const bool is_undo)
void BLO_write_destroy_id_buffer(BLO_Write_IDBuffer **id_buffer)
ID * BLO_write_get_id_buffer_temp_id(BLO_Write_IDBuffer *id_buffer)
#define BLO_read_struct(reader, struct_name, ptr_p)
bool BLO_write_is_undo(BlendWriter *writer)
#define BLO_write_struct_at_address(writer, struct_name, address, data_ptr)
#define BLT_I18NCONTEXT_ID_MATERIAL
#define CLOG_ERROR(clg_ref,...)
Definition CLG_log.h:182
void DEG_id_tag_update(ID *id, unsigned int flags)
void DEG_debug_print_eval(Depsgraph *depsgraph, const char *function_name, const char *object_name, const void *object_address)
void DEG_relations_tag_update(Main *bmain)
ID * DEG_get_original_id(ID *id)
bool DEG_is_evaluated_object(const Object *object)
ID and Library types, which are fundamental for SDNA.
@ ID_RECALC_SHADING
Definition DNA_ID.h:1061
@ ID_RECALC_SYNC_TO_EVAL
Definition DNA_ID.h:1085
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:1041
#define FILTER_ID_MA
Definition DNA_ID.h:1175
#define FILTER_ID_GR
Definition DNA_ID.h:1170
#define FILTER_ID_TE
Definition DNA_ID.h:1187
@ ID_TAG_MISSING
Definition DNA_ID.h:813
@ INDEX_ID_MA
Definition DNA_ID.h:1280
@ ID_VO
@ ID_CV
@ ID_MA
@ ID_CU_LEGACY
@ ID_GD_LEGACY
@ ID_ME
@ ID_MB
@ ID_GP
@ ID_PT
Object groups, one object can be in many groups at once.
#define DNA_struct_default_get(struct_name)
#define MAX_NAME
Definition DNA_defs.h:50
@ MA_RAMP_LIGHT
@ MA_RAMP_COLOR
@ MA_RAMP_SAT
@ MA_RAMP_HUE
@ MA_RAMP_LINEAR
@ MA_RAMP_DIV
@ MA_RAMP_EXCLUSION
@ MA_RAMP_ADD
@ MA_RAMP_DODGE
@ MA_RAMP_SUB
@ MA_RAMP_SCREEN
@ MA_RAMP_SOFT
@ MA_RAMP_DARK
@ MA_RAMP_BURN
@ MA_RAMP_BLEND
@ MA_RAMP_VAL
@ MA_RAMP_OVERLAY
@ MA_RAMP_MULT
@ MA_RAMP_DIFF
struct Material Material
@ GP_MATERIAL_STROKE_SHOW
#define MAXMAT
@ SHD_ATTRIBUTE_GEOMETRY
@ SOCK_OUT
@ SOCK_IN
@ OB_MODE_EDIT
@ OB_MODE_SCULPT
Object is a sort of wrapper for general info.
#define OB_DATA_SUPPORT_ID(_id_type)
@ OB_MBALL
@ OB_EMPTY
@ OB_SURF
@ OB_FONT
@ OB_GREASE_PENCIL
@ OB_MESH
@ OB_POINTCLOUD
@ OB_VOLUME
@ OB_CURVES_LEGACY
@ OB_GPENCIL_LEGACY
@ OB_CURVES
#define IMAGEPAINT_MODE_IMAGE
@ USER_MAT_ON_OB
void GPU_material_free(ListBase *gpumaterial)
Read Guarded memory(de)allocation.
#define MEM_recallocN(vmemh, len)
#define MEM_SAFE_FREE(v)
#define MEM_reallocN(vmemh, len)
struct blender::bke::bNodeTreeType * ntreeType_Shader
static void material_default_surface_init(Material *ma)
int BKE_object_material_index_get_with_hint(Object *ob, const Material *ma, const int hint_index)
void BKE_texpaint_slots_refresh_object(Scene *scene, Object *ob)
short * BKE_object_material_len_p(Object *ob)
static void material_copy_data(Main *bmain, std::optional< Library * > owner_library, ID *id_dst, const ID *id_src, const int flag)
static void material_default_holdout_init(Material *ma)
static void material_data_index_clear_id(ID *id)
static void nodetree_mark_previews_dirty_reccursive(bNodeTree *tree)
static void fill_texpaint_slots_recursive(bNodeTree *nodetree, bNode *active_node, const Object *ob, Material *ma, int slot_len, ePaintSlotFilter slot_filter)
int BKE_object_material_count_eval(const Object *ob)
void BKE_object_material_array_assign(Main *bmain, Object *ob, Material ***matar, int totcol, const bool to_object_only)
void BKE_id_material_eval_ensure_default_slot(ID *id)
MaterialGPencilStyle * BKE_gpencil_material_settings(Object *ob, short act)
void BKE_gpencil_material_attr_init(Material *ma)
void BKE_object_material_assign_single_obdata(Main *bmain, Object *ob, Material *ma, short act)
void BKE_id_material_clear(Main *bmain, ID *id)
Material ** BKE_object_material_get_p(Object *ob, short act)
void BKE_id_material_assign(Main *bmain, ID *id, Material *ma, short act)
short * BKE_id_material_len_p(ID *id)
static bool ntree_foreach_texnode_recursive(bNodeTree *nodetree, ForEachTexNodeCallback callback, void *userdata, ePaintSlotFilter slot_filter)
static Material default_material_gpencil
Material * BKE_material_default_surface()
static void material_foreach_id(ID *id, LibraryForeachIDData *data)
Material *** BKE_id_material_array_p(ID *id)
short BKE_object_material_slot_find_index(Object *ob, Material *ma)
Material * BKE_material_default_volume()
Material * BKE_gpencil_material(Object *ob, short act)
void BKE_material_eval(Depsgraph *depsgraph, Material *material)
void BKE_material_defaults_free_gpu()
void BKE_object_material_from_eval_data(Main *bmain, Object *ob_orig, const ID *data_eval)
Material * BKE_gpencil_material_add(Main *bmain, const char *name)
static void material_data_index_remove_id(ID *id, short index)
static Material default_material_surface
static void material_blend_write(BlendWriter *writer, ID *id, const void *id_address)
Material * BKE_id_material_pop(Main *bmain, ID *id, int index_i)
static bool texpaint_slot_node_find_cb(bNode *node, void *userdata)
static const ID * get_evaluated_object_data_with_materials(Object *ob)
static ePaintSlotFilter material_paint_slot_filter(const Object *ob)
bool(*)(bNode *node, void *userdata) ForEachTexNodeCallback
static Material default_material_empty
void BKE_id_materials_copy(Main *bmain, ID *id_src, ID *id_dst)
void BKE_object_material_remap(Object *ob, const uint *remap)
bool BKE_object_material_slot_add(Main *bmain, Object *ob)
Material * BKE_material_default_holdout()
IDTypeInfo IDType_ID_MA
static void material_free_data(ID *id)
void BKE_materials_init()
static Material * default_materials[]
void BKE_id_material_resize(Main *bmain, ID *id, short totcol, bool do_id_user)
void BKE_texpaint_slot_refresh_cache(Scene *scene, Material *ma, const Object *ob)
static Material default_material_holdout
static bNode * nodetree_uv_node_recursive(bNode *node)
Material * BKE_material_default_gpencil()
void BKE_id_material_eval_assign(ID *id, int slot, Material *material)
Material * BKE_material_add(Main *bmain, const char *name)
void BKE_object_materials_test(Main *bmain, Object *ob, ID *id)
void BKE_id_material_append(Main *bmain, ID *id, Material *ma)
bool BKE_object_material_slot_used(Object *object, short actcol)
int BKE_object_material_ensure(Main *bmain, Object *ob, Material *material)
static void object_material_assign(Main *bmain, Object *ob, Material *ma, short act, int assign_type, bool do_test_all)
Material * BKE_material_default_empty()
void BKE_object_material_resize(Main *bmain, Object *ob, const short totcol, bool do_id_user)
void BKE_objects_materials_test_all(Main *bmain, ID *id)
Material * BKE_object_material_get(Object *ob, short act)
void BKE_object_material_remap_calc(Object *ob_dst, Object *ob_src, short *remap_src_to_dst)
static void material_default_volume_init(Material *ma)
static void material_default_gpencil_init(Material *ma)
static void material_blend_read_data(BlendDataReader *reader, ID *id)
static bool count_texture_nodes_cb(bNode *, void *userdata)
static int count_texture_nodes_recursive(bNodeTree *nodetree, ePaintSlotFilter slot_filter)
static void material_init_data(ID *id)
Material * BKE_object_material_get_eval(Object *ob, short act)
static CLG_LogRef LOG
void BKE_object_material_assign(Main *bmain, Object *ob, Material *ma, short act, int assign_type)
void BKE_materials_exit()
bNode * BKE_texpaint_slot_material_find_node(Material *ma, short texpaint_slot)
static Material default_material_volume
static bool fill_texpaint_slots_cb(bNode *node, void *userdata)
int BKE_object_material_index_get(Object *ob, const Material *ma)
void BKE_material_make_node_previews_dirty(Material *ma)
Material *** BKE_object_material_array_p(Object *ob)
bool BKE_object_material_slot_remove(Main *bmain, Object *ob)
void ramp_blend(int type, float r_col[3], const float fac, const float col[3])
unsigned int U
Definition btGjkEpa3.h:78
OperationNode * node
Material material
const Depsgraph * depsgraph
DEGForeachIDComponentCallback callback
#define fabsf(x)
KDTree_3d * tree
uint col
int count
#define GS(x)
Definition iris.cc:202
void *(* MEM_recallocN_id)(void *vmemh, size_t len, const char *str)
Definition mallocn.cc:41
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void *(* MEM_callocN)(size_t len, const char *str)
Definition mallocn.cc:42
void *(* MEM_dupallocN)(const void *vmemh)
Definition mallocn.cc:39
void node_set_active(bNodeTree *ntree, bNode *node)
Definition node.cc:3896
bNodeTree * node_tree_localize(bNodeTree *ntree, ID *new_owner_id)
Definition node.cc:3750
void node_tree_blend_write(BlendWriter *writer, bNodeTree *ntree)
Definition node.cc:760
bNode * node_add_static_node(const bContext *C, bNodeTree *ntree, int type)
Definition node.cc:2642
bNode * node_get_active_paint_canvas(bNodeTree *ntree)
bNodeLink * node_add_link(bNodeTree *ntree, bNode *fromnode, bNodeSocket *fromsock, bNode *tonode, bNodeSocket *tosock)
Definition node.cc:2912
bNodeTree * node_tree_add_tree_embedded(Main *bmain, ID *owner_id, const char *name, const char *idname)
Definition node.cc:3239
bNodeSocket * node_find_socket(bNode *node, eNodeSocketInOut in_out, StringRef identifier)
Definition node.cc:1829
void node_tree_free_embedded_tree(bNodeTree *ntree)
Definition node.cc:3632
return ret
struct Material ** mat
short totcol
struct Material ** material_array
Definition DNA_ID.h:413
int tag
Definition DNA_ID.h:434
void * next
Definition DNA_ID.h:416
char name[66]
Definition DNA_ID.h:425
void * first
ListBase objects
Definition BKE_main.hh:212
struct bNodeTree * nodetree
short paint_active_slot
struct PreviewImage * preview
struct MaterialGPencilStyle * gp_style
ListBase gpumaterial
struct TexPaintSlot * texpaintslot
struct Material ** mat
ObjectRuntimeHandle * runtime
struct Material ** mat
char * matbits
struct Material ** mat
struct Image * ima
struct ImageUser * image_user
struct Material ** mat
void * default_value
bNodeTypeHandle * typeinfo
float locy
float locx
void * storage
#define N_(msgid)
uint8_t flag
Definition wm_window.cc:138
smooth(Type::VEC3, "normal_interp") .smooth(Type materials_data[]