1 /* BurrTools
2 *
3 * BurrTools is the legal property of its developers, whose
4 * names are listed in the COPYRIGHT file, which is included
5 * within the source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21 #include "disasmtomoves.h"
22
23 #include "disassembly.h"
24 #include "disassemblernode.h"
25
disasmToMoves_c(const separation_c * tr,unsigned int sz,unsigned int max)26 disasmToMoves_c::disasmToMoves_c(const separation_c * tr, unsigned int sz, unsigned int max) : size(sz), maxPieceName(max) {
27
28 tree = new separation_c(tr);
29
30 moves = new float[maxPieceName*4];
31 mv = new bool[maxPieceName];
32 }
33
~disasmToMoves_c()34 disasmToMoves_c::~disasmToMoves_c() {
35 delete [] moves;
36 delete [] mv;
37 delete tree;
38 }
39
setStep(float step,bool fadeOut,bool center_active)40 void disasmToMoves_c::setStep(float step, bool fadeOut, bool center_active) {
41
42 int s = int(step);
43 float frac = step - s;
44
45 // a temporary array, used to save the 2nd placement for the interpolation */
46 float * moves2 = new float[maxPieceName*4];
47
48 for (unsigned int i = 0; i < 4 * maxPieceName; i++) {
49 moves[i] = moves2[i] = 0;
50 }
51
52 /* what we do is go twice through the tree and linearly interpolate between
53 * the 2 states that we have in in the two nodes that we are currently in between
54 *
55 * this is done with the weight value (1-frac and frac)
56 */
57 if (tree) {
58
59 /* get the 2 possible positions between we have to interpolate */
60 doRecursive(tree, s , moves, center_active, 0, 0, 0);
61 doRecursive(tree, s+1, moves2, center_active, 0, 0, 0);
62
63 // interpolate and check, which piece moves right now
64 for (unsigned int i = 0; i < maxPieceName; i++) {
65 mv[i] = ((moves[4*i+0] != moves2[4*i+0]) || (moves[4*i+1] != moves2[4*i+1]) || (moves[4*i+2] != moves2[4*i+2]));
66 moves[4*i+0] = (1-frac)*moves[4*i+0] + frac*moves2[4*i+0];
67 moves[4*i+1] = (1-frac)*moves[4*i+1] + frac*moves2[4*i+1];
68 moves[4*i+2] = (1-frac)*moves[4*i+2] + frac*moves2[4*i+2];
69 moves[4*i+3] = (1-frac)*moves[4*i+3] + frac*moves2[4*i+3];
70 }
71
72 if (!fadeOut)
73 for (unsigned int i = 0; i < maxPieceName; i++)
74 if (moves[4*i+3] > 0) moves[4*i+3] = 1;
75
76 }
77
78 delete [] moves2;
79 }
80
getX(unsigned int piece)81 float disasmToMoves_c::getX(unsigned int piece) {
82 bt_assert(piece < maxPieceName);
83 return moves[4*piece+0];
84 }
getY(unsigned int piece)85 float disasmToMoves_c::getY(unsigned int piece) {
86 bt_assert(piece < maxPieceName);
87 return moves[4*piece+1];
88 }
getZ(unsigned int piece)89 float disasmToMoves_c::getZ(unsigned int piece) {
90 bt_assert(piece < maxPieceName);
91 return moves[4*piece+2];
92 }
getA(unsigned int piece)93 float disasmToMoves_c::getA(unsigned int piece) {
94 bt_assert(piece < maxPieceName);
95 return moves[4*piece+3];
96 }
moving(unsigned int piece)97 bool disasmToMoves_c::moving(unsigned int piece) {
98 bt_assert(piece < maxPieceName);
99 return mv[piece];
100 }
101
mabs(int a)102 static int mabs(int a) {
103 if (a > 0)
104 return a;
105 else
106 return -a;
107 }
108
mmax(int a,int b)109 static int mmax(int a, int b) {
110 if (a>b)
111 return a;
112 else
113 return b;
114 }
115
116 /* this is the core function that walks through the tree, let's see if I can
117 * describe what's going on in here
118 *
119 * let's start with the parameters:
120 * tree is the current subtree to walk through
121 * step is the step to show inside this tree, if step is negative or bigger than
122 * the steps required for this tree we are somewhere outside the tree
123 * weight is used for the linear interpolation it is a value between 0 and 1 including
124 * values are multiplied by this value and then the 2 end points are added
125 * cx, cy, cz are the centre to display the current tree
126 */
doRecursive(const separation_c * tree,int step,float * array,bool center_active,int cx,int cy,int cz)127 int disasmToMoves_c::doRecursive(const separation_c * tree, int step, float * array, bool center_active, int cx, int cy, int cz) {
128
129 bt_assert(tree);
130
131 /* first check, if we are inside this tree node, this is the case when
132 * the number of steps is between 0 and the number of steps in this node
133 *
134 * we do need to include "=" here because the last move will be the separation and
135 * we don't want to display that move as said in the state but rather a bit
136 * more adequate for the screen
137 *
138 * in the state the removed part would be removed by 10000 units
139 */
140 if ((step >= 0) && ((unsigned int)step >= tree->getMoves())) {
141
142 /* so, this is the path for after the current node, the first thing
143 * is to find out in which directions the pieces that are removed
144 * are removed, then define the new centre for the removed
145 * part and call the subtrees
146 *
147 * we can be sure that we have disassembled the current subpuzzle,
148 * so we need to display both subparts separated. It is possible that
149 * one or both subparts are only one piece. In this case the tree
150 * doesn't contain the subtrees
151 *
152 * take the last state, in this state the removed pieces have a
153 * distance grater 1000
154 */
155 const state_c * s = tree->getState(tree->getMoves());
156
157 /* find one of the removed pieces and one of the left pieces */
158 unsigned int pc, pc2;
159
160 for (pc = 0; pc < tree->getPieceNumber(); pc++)
161 if (s->pieceRemoved(pc))
162 break;
163
164 for (pc2 = 0; pc2 < tree->getPieceNumber(); pc2++)
165 if (!s->pieceRemoved(pc2))
166 break;
167
168 /* find out the direction the piece is removed */
169 int dx, dy, dz;
170
171 dx = dy = dz = 0;
172
173 if (s->getX(pc) > 10000) dx = size;
174 if (s->getX(pc) < -10000) dx = - size;
175 if (s->getY(pc) > 10000) dy = size;
176 if (s->getY(pc) < -10000) dy = - size;
177 if (s->getZ(pc) > 10000) dz = size;
178 if (s->getZ(pc) < -10000) dz = - size;
179
180 int steps, steps2;
181
182 /* place the removed pieces with the new centre */
183 if (tree->getRemoved()) {
184
185 /* if we use the center_active option we need to keep the removed part stationary
186 * and place the pieces where they belong,
187 *
188 * otherwise we place the removed part somewhere out of the way
189 */
190 if (center_active)
191 steps = doRecursive(tree->getRemoved(), step - (int)tree->getMoves(), array, center_active,
192 tree->getState(tree->getMoves()-1)->getX(pc) + cx - tree->getRemoved()->getState(0)->getX(0),
193 tree->getState(tree->getMoves()-1)->getY(pc) + cy - tree->getRemoved()->getState(0)->getY(0),
194 tree->getState(tree->getMoves()-1)->getZ(pc) + cz - tree->getRemoved()->getState(0)->getZ(0));
195 else
196 steps = doRecursive(tree->getRemoved(), step - (int)tree->getMoves(), array, center_active, cx+dx, cy+dy, cz+dz);
197
198 } else {
199
200 const state_c * s2 = tree->getState(tree->getMoves()-1);
201
202 /* if there is no removed tree, the pieces need to vanish */
203 if (array)
204 for (unsigned int p = 0; p < tree->getPieceNumber(); p++)
205 if (s->pieceRemoved(p)) {
206 array[4*tree->getPieceName(p)+0] += dx+cx+((mabs(s->getX(p))<10000)?(s->getX(p)):(s2->getX(p)));
207 array[4*tree->getPieceName(p)+1] += dy+cy+((mabs(s->getY(p))<10000)?(s->getY(p)):(s2->getY(p)));
208 array[4*tree->getPieceName(p)+2] += dz+cz+((mabs(s->getZ(p))<10000)?(s->getZ(p)):(s2->getZ(p)));
209 array[4*tree->getPieceName(p)+3] += 0;
210 }
211
212 steps = 0;
213 }
214
215 /* place the left over pieces in the old centre */
216 if (tree->getLeft()) {
217
218 /* if we use center_active switch, we first display the removed part and need to move the left
219 * over part out of the way, this is done via the d. values in the negative direction of the
220 * removal of the pieces
221 *
222 * if we don't use the center_active option, the left over part stays in the middle
223 */
224 if (center_active && (step - (int)tree->getMoves() < steps) && (tree->getRemoved()))
225 steps2 = doRecursive(tree->getLeft(), step - (int)tree->getMoves() - steps, array, center_active, cx-dx, cy-dy, cz-dz);
226 else
227 steps2 = doRecursive(tree->getLeft(), step - (int)tree->getMoves() - steps, array, center_active, cx, cy, cz);
228
229 /* if the steps tell us that we are currenlty animating the removed part
230 * and there actually _is_ a removed animation, we hide all
231 * pieces that are not removed
232 */
233 if (array && center_active && (step - (int)tree->getMoves() < steps) && (tree->getRemoved())) {
234 for (unsigned int p = 0; p < tree->getPieceNumber(); p++)
235 if (!s->pieceRemoved(p)) {
236 array[4*tree->getPieceName(p)+3] = 0;
237 }
238 }
239
240 } else {
241
242 if (array)
243 for (unsigned int p = 0; p < tree->getPieceNumber(); p++)
244 if (!s->pieceRemoved(p)) {
245 array[4*tree->getPieceName(p)+0] += cx+s->getX(p);
246 array[4*tree->getPieceName(p)+1] += cy+s->getY(p);
247 array[4*tree->getPieceName(p)+2] += cz+s->getZ(p);
248 array[4*tree->getPieceName(p)+3] += 0;
249 }
250
251 steps2 = 0;
252 }
253
254 return tree->getMoves() + steps + steps2;
255 }
256
257 /* all right the number of steps shows us that we have the task to disassemble
258 * this node, so get the state and place the pieces at the right position
259 *
260 * we also have to place the pieces at their initial position, when we are
261 * before the current node
262 */
263 const state_c * s = tree->getState(mmax(step, 0));
264
265 if (array)
266 for (unsigned int i = 0; i < tree->getPieceNumber(); i++) {
267 array[4*tree->getPieceName(i)+0] += cx+s->getX(i);
268 array[4*tree->getPieceName(i)+1] += cy+s->getY(i);
269 array[4*tree->getPieceName(i)+2] += cz+s->getZ(i);
270 array[4*tree->getPieceName(i)+3] += 1;
271 }
272
273 int steps = tree->getRemoved() ? doRecursive(tree->getRemoved(), step - tree->getMoves() , 0, center_active, 0, 0, 0) : 0;
274 int steps2 = tree->getLeft() ? doRecursive(tree->getLeft() , step - tree->getMoves() - steps, 0, center_active, 0, 0, 0) : 0;
275
276 return tree->getMoves() + steps + steps2;
277 }
278
279
280
281
282
283
284
fixedPositions_c(const disassemblerNode_c * nd,const std::vector<unsigned int> & pc,unsigned int pcs)285 fixedPositions_c::fixedPositions_c(const disassemblerNode_c * nd, const std::vector<unsigned int> & pc, unsigned int pcs) {
286
287 pieces = pcs;
288 x = new int[pieces];
289 y = new int[pieces];
290 z = new int[pieces];
291 visible = new bool[pieces];
292
293 for (unsigned int p = 0; p < pieces; p++) {
294 visible[p] = false;
295 x[p] = y[p] = z[p] = 0;
296 }
297
298 for (unsigned int p = 0; p < pc.size(); p++) {
299
300 unsigned int pi = pc[p];
301
302 bt_assert(pi < pieces);
303
304 x[pi] = (int)nd->getX(p);
305 y[pi] = (int)nd->getY(p);
306 z[pi] = (int)nd->getZ(p);
307
308 visible[pi] = true;
309 }
310 }
311
fixedPositions_c(const fixedPositions_c * nd)312 fixedPositions_c::fixedPositions_c(const fixedPositions_c * nd) {
313
314 pieces = nd->pieces;
315 x = new int[pieces];
316 y = new int[pieces];
317 z = new int[pieces];
318 visible = new bool[pieces];
319
320 for (unsigned int p = 0; p < pieces; p++) {
321 x[p] = nd->x[p];
322 y[p] = nd->y[p];
323 z[p] = nd->z[p];
324 visible[p] = nd->visible[p];
325 }
326 }
327
~fixedPositions_c(void)328 fixedPositions_c::~fixedPositions_c(void) {
329 delete [] x;
330 delete [] y;
331 delete [] z;
332 delete [] visible;
333 }
334
getX(unsigned int piece)335 float fixedPositions_c::getX(unsigned int piece) { bt_assert(piece < pieces); return x[piece]; }
getY(unsigned int piece)336 float fixedPositions_c::getY(unsigned int piece) { bt_assert(piece < pieces); return y[piece]; }
getZ(unsigned int piece)337 float fixedPositions_c::getZ(unsigned int piece) { bt_assert(piece < pieces); return z[piece]; }
getA(unsigned int piece)338 float fixedPositions_c::getA(unsigned int piece) { return visible[piece] ? 1 : 0; }
moving(unsigned int)339 bool fixedPositions_c::moving(unsigned int /*piece*/) { return false; }
340
341