Depsgraph: Comb code to a better state all over
[blender.git] / source / blender / depsgraph / intern / builder / deg_builder_pchanmap.cc
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2015 Blender Foundation.
19  * All rights reserved.
20  *
21  * Original Author: Sergey Sharybin
22  * Contributor(s): Joshua Leung
23  *
24  * ***** END GPL LICENSE BLOCK *****
25  */
26
27 /** \file blender/depsgraph/intern/builder/deg_builder_pchanmap.cc
28  *  \ingroup depsgraph
29  */
30
31 #include "intern/builder/deg_builder_pchanmap.h"
32
33 #include <stdio.h>
34 #include <string.h>
35
36 #include "BLI_utildefines.h"
37 #include "BLI_ghash.h"
38
39 namespace DEG {
40
41 static void free_rootpchanmap_valueset(void *val)
42 {
43         /* Just need to free the set itself - the names stored are all references. */
44         GSet *values = (GSet *)val;
45         BLI_gset_free(values, NULL);
46 }
47
48 RootPChanMap::RootPChanMap()
49 {
50         /* Just create empty map. */
51         map_ = BLI_ghash_str_new("RootPChanMap");
52 }
53
54 RootPChanMap::~RootPChanMap()
55 {
56         /* Free the map, and all the value sets. */
57         BLI_ghash_free(map_, NULL, free_rootpchanmap_valueset);
58 }
59
60 /* Debug contents of map */
61 void RootPChanMap::print_debug()
62 {
63         GHashIterator it1;
64         GSetIterator it2;
65
66         printf("Root PChan Map:\n");
67         GHASH_ITER(it1, map_) {
68                 const char *item = (const char *)BLI_ghashIterator_getKey(&it1);
69                 GSet *values = (GSet *)BLI_ghashIterator_getValue(&it1);
70
71                 printf("  %s : { ", item);
72                 GSET_ITER(it2, values) {
73                         const char *val = (const char *)BLI_gsetIterator_getKey(&it2);
74                         printf("%s, ", val);
75                 }
76                 printf("}\n");
77         }
78 }
79
80 /* Add a mapping. */
81 void RootPChanMap::add_bone(const char *bone, const char *root)
82 {
83         if (BLI_ghash_haskey(map_, bone)) {
84                 /* Add new entry, but only add the root if it doesn't already
85                  * exist in there. */
86                 GSet *values = (GSet *)BLI_ghash_lookup(map_, bone);
87                 BLI_gset_add(values, (void *)root);
88         }
89         else {
90                 /* Create new set and mapping. */
91                 GSet *values = BLI_gset_new(BLI_ghashutil_strhash_p,
92                                             BLI_ghashutil_strcmp,
93                                             "RootPChanMap Value Set");
94                 BLI_ghash_insert(map_, (void *)bone, (void *)values);
95
96                 /* Add new entry now. */
97                 BLI_gset_insert(values, (void *)root);
98         }
99 }
100
101 /* Check if there's a common root bone between two bones. */
102 bool RootPChanMap::has_common_root(const char *bone1, const char *bone2)
103 {
104         /* Ensure that both are in the map... */
105         if (BLI_ghash_haskey(map_, bone1) == false) {
106                 //fprintf("RootPChanMap: bone1 '%s' not found (%s => %s)\n", bone1, bone1, bone2);
107                 //print_debug();
108                 return false;
109         }
110
111         if (BLI_ghash_haskey(map_, bone2) == false) {
112                 //fprintf("RootPChanMap: bone2 '%s' not found (%s => %s)\n", bone2, bone1, bone2);
113                 //print_debug();
114                 return false;
115         }
116
117         GSet *bone1_roots = (GSet *)BLI_ghash_lookup(map_, (void *)bone1);
118         GSet *bone2_roots = (GSet *)BLI_ghash_lookup(map_, (void *)bone2);
119
120         GSetIterator it1, it2;
121         GSET_ITER(it1, bone1_roots) {
122                 GSET_ITER(it2, bone2_roots) {
123                         const char *v1 = (const char *)BLI_gsetIterator_getKey(&it1);
124                         const char *v2 = (const char *)BLI_gsetIterator_getKey(&it2);
125
126                         if (strcmp(v1, v2) == 0) {
127                                 //fprintf("RootPchanMap: %s in common for %s => %s\n", v1, bone1, bone2);
128                                 return true;
129                         }
130                 }
131         }
132
133         //fprintf("RootPChanMap: No common root found (%s => %s)\n", bone1, bone2);
134         return false;
135 }
136
137 }  // namespace DEG