Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenkernel/intern/mball.c
| Show First 20 Lines • Show All 341 Lines • ▼ Show 20 Lines | while (a--) { | ||||
| data += 3; | data += 3; | ||||
| orco += 3; | orco += 3; | ||||
| } | } | ||||
| return orcodata; | return orcodata; | ||||
| } | } | ||||
| bool BKE_mball_is_basis(Object *ob) | bool BKE_mball_is_basis(const Object *ob) | ||||
| { | { | ||||
| /* Meta-Ball Basis Notes from Blender-2.5x | /* Meta-Ball Basis Notes from Blender-2.5x | ||||
| * ======================================= | * ======================================= | ||||
| * | * | ||||
| * NOTE(@campbellbarton): This is a can of worms. | * NOTE(@campbellbarton): This is a can of worms. | ||||
| * | * | ||||
| * This really needs a rewrite/refactor its totally broken in anything other than basic cases | * This really needs a rewrite/refactor its totally broken in anything other than basic cases | ||||
| * Multiple Scenes + Set Scenes & mixing meta-ball basis _should_ work but fails to update the | * Multiple Scenes + Set Scenes & mixing meta-ball basis _should_ work but fails to update the | ||||
| * depsgraph on rename and linking into scenes or removal of basis meta-ball. | * depsgraph on rename and linking into scenes or removal of basis meta-ball. | ||||
| * So take care when changing this code. | * So take care when changing this code. | ||||
| * | * | ||||
| * Main idiot thing here is that the system returns #BKE_mball_basis_find() | * Main idiot thing here is that the system returns #BKE_mball_basis_find() | ||||
| * objects which fail a #BKE_mball_is_basis() test. | * objects which fail a #BKE_mball_is_basis() test. | ||||
| * | * | ||||
| * Not only that but the depsgraph and their areas depend on this behavior, | * Not only that but the depsgraph and their areas depend on this behavior, | ||||
| * so making small fixes here isn't worth it. */ | * so making small fixes here isn't worth it. */ | ||||
| /* Just a quick test. */ | /* Just a quick test. */ | ||||
| const int len = strlen(ob->id.name); | const int len = strlen(ob->id.name); | ||||
| return (!isdigit(ob->id.name[len - 1])); | return (!isdigit(ob->id.name[len - 1])); | ||||
| } | } | ||||
| bool BKE_mball_is_basis_for(Object *ob1, Object *ob2) | bool BKE_mball_is_same_group(const Object *ob1, const Object *ob2) | ||||
| { | { | ||||
| int basis1nr, basis2nr; | int basis1nr, basis2nr; | ||||
| char basis1name[MAX_ID_NAME], basis2name[MAX_ID_NAME]; | char basis1name[MAX_ID_NAME], basis2name[MAX_ID_NAME]; | ||||
| if (ob1->id.name[2] != ob2->id.name[2]) { | if (ob1->id.name[2] != ob2->id.name[2]) { | ||||
| /* Quick return in case first char of both ID's names is not the same... */ | /* Quick return in case first char of both ID's names is not the same... */ | ||||
| return false; | return false; | ||||
| } | } | ||||
| BLI_split_name_num(basis1name, &basis1nr, ob1->id.name + 2, '.'); | BLI_split_name_num(basis1name, &basis1nr, ob1->id.name + 2, '.'); | ||||
| BLI_split_name_num(basis2name, &basis2nr, ob2->id.name + 2, '.'); | BLI_split_name_num(basis2name, &basis2nr, ob2->id.name + 2, '.'); | ||||
| if (STREQ(basis1name, basis2name)) { | return STREQ(basis1name, basis2name); | ||||
| return BKE_mball_is_basis(ob1); | |||||
| } | } | ||||
| return false; | bool BKE_mball_is_basis_for(const Object *ob1, const Object *ob2) | ||||
| { | |||||
| return BKE_mball_is_same_group(ob1, ob2) && BKE_mball_is_basis(ob1); | |||||
| } | } | ||||
| bool BKE_mball_is_any_selected(const MetaBall *mb) | bool BKE_mball_is_any_selected(const MetaBall *mb) | ||||
| { | { | ||||
| for (const MetaElem *ml = mb->editelems->first; ml != NULL; ml = ml->next) { | for (const MetaElem *ml = mb->editelems->first; ml != NULL; ml = ml->next) { | ||||
| if (ml->flag & SELECT) { | if (ml->flag & SELECT) { | ||||
| return true; | return true; | ||||
| } | } | ||||
| Show All 18 Lines | bool BKE_mball_is_any_unselected(const MetaBall *mb) | ||||
| for (const MetaElem *ml = mb->editelems->first; ml != NULL; ml = ml->next) { | for (const MetaElem *ml = mb->editelems->first; ml != NULL; ml = ml->next) { | ||||
| if ((ml->flag & SELECT) == 0) { | if ((ml->flag & SELECT) == 0) { | ||||
| return true; | return true; | ||||
| } | } | ||||
| } | } | ||||
| return false; | return false; | ||||
| } | } | ||||
| void BKE_mball_properties_copy(Scene *scene, Object *active_object) | static void mball_data_properties_copy(MetaBall *mb_dst, MetaBall *mb_src) | ||||
| { | { | ||||
| Scene *sce_iter = scene; | mb_dst->wiresize = mb_src->wiresize; | ||||
| Base *base; | mb_dst->rendersize = mb_src->rendersize; | ||||
| Object *ob; | mb_dst->thresh = mb_src->thresh; | ||||
| MetaBall *active_mball = (MetaBall *)active_object->data; | mb_dst->flag = mb_src->flag; | ||||
| int basisnr, obnr; | DEG_id_tag_update(&mb_dst->id, 0); | ||||
| char basisname[MAX_ID_NAME], obname[MAX_ID_NAME]; | } | ||||
| SceneBaseIter iter; | |||||
| void BKE_mball_properties_copy(Main *bmain, MetaBall *metaball_src) | |||||
| { | |||||
| /* WARNING: This code does not cover all potential corner-cases. E.g. if: | |||||
| * | Object | ObData | | |||||
| * | ---------- | ---------- | | |||||
| * | Meta_A | Meta_A | | |||||
| * | Meta_A.001 | Meta_A.001 | | |||||
| * | Meta_B | Meta_A | | |||||
| * | Meta_B.001 | Meta_B.001 | | |||||
| * | |||||
| * Calling this function with `metaball_src` being `Meta_A.001` will update `Meta_A`, but NOT | |||||
| * `Meta_B.001`. So in the 'Meta_B' family, the two metaballs will have unmatching settings now. | |||||
| * | |||||
| * Solving this case would drastically increase the complexity of this code though, so don't | |||||
| * think it would be worth it. | |||||
| */ | |||||
| for (Object *ob_src = bmain->objects.first; ob_src != NULL && !ID_IS_LINKED(ob_src);) { | |||||
| if (ob_src->data != metaball_src) { | |||||
| ob_src = ob_src->id.next; | |||||
| continue; | |||||
| } | |||||
| BLI_split_name_num(basisname, &basisnr, active_object->id.name + 2, '.'); | /* In this code we take advantage of two facts: | ||||
| * - MetaBalls of a same family have the same basis name, | |||||
sergey: Think here and later it should be `the family`. | |||||
| * - IDs are sorted by name in their Main listbase. | |||||
| * So, all MetaBall objects of a same family are contiguous in bmain list (potentially mixed | |||||
| * with non-meta-ball objects with same basis names). | |||||
| * | |||||
| * Using this, it is possible to process the whole set of meta-balls with a single loop on the | |||||
| * whole list of Objects, though additionally going backward on part of the list in some cases. | |||||
| */ | |||||
| Object *ob_iter = NULL; | |||||
| int obactive_nr, ob_nr; | |||||
| char obactive_name[MAX_ID_NAME], ob_name[MAX_ID_NAME]; | |||||
| BLI_split_name_num(obactive_name, &obactive_nr, ob_src->id.name + 2, '.'); | |||||
| /* Pass depsgraph as NULL, which means we will not expand into | for (ob_iter = ob_src->id.prev; ob_iter != NULL; ob_iter = ob_iter->id.prev) { | ||||
| * duplis unlike when we generate the meta-ball. Expanding duplis | if (ob_iter->id.name[2] != obactive_name[0]) { | ||||
| * would not be compatible when editing multiple view layers. */ | break; | ||||
| BKE_scene_base_iter_next(NULL, &iter, &sce_iter, 0, NULL, NULL); | } | ||||
| while (BKE_scene_base_iter_next(NULL, &iter, &sce_iter, 1, &base, &ob)) { | if (ob_iter->type != OB_MBALL || ob_iter->data == metaball_src) { | ||||
| if (ob->type == OB_MBALL) { | continue; | ||||
| if (ob != active_object) { | } | ||||
| BLI_split_name_num(obname, &obnr, ob->id.name + 2, '.'); | BLI_split_name_num(ob_name, &ob_nr, ob_iter->id.name + 2, '.'); | ||||
| if (!STREQ(obactive_name, ob_name)) { | |||||
| break; | |||||
| } | |||||
| /* Object ob has to be in same "group" ... it means, that it has to have | mball_data_properties_copy(ob_iter->data, metaball_src); | ||||
| * same base of its name */ | } | ||||
| if (STREQ(obname, basisname)) { | |||||
| MetaBall *mb = ob->data; | |||||
| /* Copy properties from selected/edited metaball */ | for (ob_iter = ob_src->id.next; ob_iter != NULL; ob_iter = ob_iter->id.next) { | ||||
| mb->wiresize = active_mball->wiresize; | if (ob_iter->id.name[2] != obactive_name[0] || ID_IS_LINKED(ob_iter)) { | ||||
| mb->rendersize = active_mball->rendersize; | break; | ||||
| mb->thresh = active_mball->thresh; | |||||
| mb->flag = active_mball->flag; | |||||
| DEG_id_tag_update(&mb->id, 0); | |||||
| } | } | ||||
| if (ob_iter->type != OB_MBALL || ob_iter->data == metaball_src) { | |||||
| continue; | |||||
| } | } | ||||
| BLI_split_name_num(ob_name, &ob_nr, ob_iter->id.name + 2, '.'); | |||||
| if (!STREQ(obactive_name, ob_name)) { | |||||
| break; | |||||
| } | } | ||||
| mball_data_properties_copy(ob_iter->data, metaball_src); | |||||
| } | |||||
| ob_src = ob_iter; | |||||
| } | } | ||||
| } | } | ||||
| Object *BKE_mball_basis_find(Scene *scene, Object *object) | Object *BKE_mball_basis_find(Scene *scene, Object *object) | ||||
| { | { | ||||
| Object *bob = object; | Object *bob = object; | ||||
| int basisnr, obnr; | int basisnr, obnr; | ||||
| char basisname[MAX_ID_NAME], obname[MAX_ID_NAME]; | char basisname[MAX_ID_NAME], obname[MAX_ID_NAME]; | ||||
| ▲ Show 20 Lines • Show All 242 Lines • Show Last 20 Lines | |||||
Think here and later it should be the family.