~siretart/ubuntu/utopic/blender/libav10

« back to all changes in this revision

Viewing changes to source/blender/src/editconstraint.c

Tags: upstream-2.40
ImportĀ upstreamĀ versionĀ 2.40

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/**
2
 
 * $Id: editconstraint.c,v 1.20 2004/09/05 21:20:03 theeth Exp $
 
2
 * $Id: editconstraint.c,v 1.33 2005/12/18 18:05:10 broken Exp $
3
3
 *
4
4
 * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
5
5
 *
36
36
#include "MEM_guardedalloc.h"
37
37
 
38
38
#include "BLI_blenlib.h"
 
39
#include "BLI_arithb.h"
39
40
 
40
41
#include "DNA_action_types.h"
41
42
#include "DNA_armature_types.h"
 
43
#include "DNA_constraint_types.h"
 
44
#include "DNA_curve_types.h"
42
45
#include "DNA_object_types.h"
43
46
#include "DNA_scene_types.h"
44
47
#include "DNA_screen_types.h"
45
 
#include "DNA_constraint_types.h"
46
 
#include "DNA_curve_types.h"
 
48
#include "DNA_view3d_types.h"
47
49
 
48
 
#include "BKE_utildefines.h"
49
50
#include "BKE_action.h"
50
51
#include "BKE_armature.h"
51
 
#include "BKE_object.h"
 
52
#include "BKE_constraint.h"
 
53
#include "BKE_depsgraph.h"
52
54
#include "BKE_global.h"
53
 
#include "BKE_constraint.h"
54
55
#include "BKE_ipo.h"
 
56
#include "BKE_object.h"
 
57
#include "BKE_utildefines.h"
55
58
 
 
59
#include "BIF_editaction.h"
56
60
#include "BIF_editarmature.h"
57
61
#include "BIF_editconstraint.h"
 
62
#include "BIF_poseobject.h"
58
63
#include "BIF_interface.h"
59
64
#include "BIF_screen.h"
 
65
#include "BIF_space.h"
60
66
#include "BIF_toolbox.h"
61
67
 
62
 
#include "BSE_editaction.h"
63
 
 
64
68
#include "blendef.h"
65
69
#include "nla.h"
66
 
 
67
 
#ifdef HAVE_CONFIG_H
68
 
#include <config.h>
69
 
#endif
70
 
 
71
 
static short add_constraint_element (Object *owner, const char *substring, Object *parent, const char *parentstring);
72
 
static short detect_constraint_loop (Object *owner, const char* substring, int disable, char type);
73
 
static void test_bonelist_constraints (Object *owner, ListBase *list);
74
 
static void clear_object_constraint_loop_flags(Object *ob);
75
 
//static int is_child_of(struct Object *owner, struct Object *parent);
76
 
//static int is_bonechild_of(struct Bone *bone, struct Bone *parent);
77
 
static int is_child_of_ex(Object *owner, const char *ownersubstr, Object *parent, const char *parsubstr);
78
 
 
79
 
ListBase g_conBase;
80
 
const char *g_conString;
81
 
Object *g_conObj;
82
 
 
83
 
 
84
 
static int is_child_of_ex(Object *owner, const char *ownersubstr, Object *parent, const char *parsubstr)
85
 
{
86
 
        Object *curob;
87
 
        Bone *bone = NULL;
88
 
        Bone *parbone= NULL;
89
 
 
90
 
        curob=owner;
91
 
 
92
 
        /* If this is a bone */
93
 
        if (strlen(ownersubstr))
94
 
                bone = get_named_bone(get_armature(owner->parent), ownersubstr);
95
 
        
96
 
        if (strlen(parsubstr))
97
 
                parbone = get_named_bone(get_armature(parent), parsubstr);
98
 
 
99
 
 
100
 
        /* Traverse the scene graph */
101
 
        while (curob && !bone){
102
 
                switch (curob->partype){
103
 
                case PARBONE:
104
 
                        if (strlen(parsubstr)){
105
 
                                bone = get_named_bone(get_armature(curob->parent), curob->parsubstr);
106
 
                                break;
107
 
                        }
108
 
                        /* The break is supposed to be missing */
109
 
                default:
110
 
                        if (curob==parent){
111
 
                                if (parbone)
112
 
                                        return 0;
113
 
                                else
114
 
                                        return 1;
115
 
                        }
116
 
                }
117
 
                curob=curob->parent;
118
 
        }
119
 
 
120
 
 
121
 
        /* Descend into the armature scene graph */
122
 
        while (bone){
123
 
                if (bone==parbone)
124
 
                        return 1;
125
 
                bone=bone->parent;
126
 
        }
127
 
        
128
 
        return 0;
129
 
}
130
 
/*
131
 
static int is_child_of(Object *owner, Object *parent)
132
 
{
133
 
        Object *curpar;
134
 
 
135
 
        for (curpar = owner->parent; curpar; curpar=curpar->parent){
136
 
                if (curpar==parent)
137
 
                        return 1;
138
 
        }
139
 
 
140
 
        return 0;
141
 
}
142
 
 
143
 
 
144
 
static int is_bonechild_of(Bone *bone, Bone *parent)
145
 
{
146
 
        Bone *curpar;
147
 
 
148
 
        if (!bone)
149
 
                return 0;
150
 
 
151
 
        for (curpar = bone->parent; curpar; curpar=curpar->parent){
152
 
                if (curpar==parent)
153
 
                        return 1;
154
 
        }
155
 
        return 0;
156
 
}
157
 
*/
158
 
static short add_constraint_element (Object *owner, const char *substring, Object *parent, const char *parentstring)
159
 
{
160
 
        
161
 
        if (!owner)
162
 
                return 0;
163
 
 
164
 
        /* See if this is the original object */
165
 
        if (parent == owner){
166
 
                if (!strcmp (parentstring, substring))
167
 
                                return 1;
168
 
        }
169
 
 
170
 
        if (owner == g_conObj){
171
 
                if (!strcmp (g_conString, substring))
172
 
                        return 1;
173
 
        }
174
 
 
175
 
        /* See if this is a child of the adding object */
176
 
        if (parent){
177
 
//              if (is_child_of (owner, parent))
178
 
                if (is_child_of_ex (owner, substring, parent, parentstring))
179
 
                        return 1;
180
 
                /* Parent is a bone */
181
 
/*              if ((owner==parent) && (owner->type == OB_ARMATURE)){
182
 
                        if (strlen (substring) && strlen(parentstring)){
183
 
                                if (is_bonechild_of(get_named_bone(owner->data, substring), get_named_bone(parent->data, parentstring)))
184
 
                                        return 1;
185
 
                        }
186
 
                }
187
 
                */
188
 
        }
189
 
        return 0;
190
 
}
191
 
 
192
 
static void test_bonelist_constraints (Object *owner, ListBase *list)
193
 
{
194
 
        Bone *bone;
195
 
        Base    *base1;
196
 
 
197
 
 
198
 
        for (bone = list->first; bone; bone=bone->next){
199
 
                for (base1 = G.scene->base.first; base1; base1=base1->next){
200
 
                        clear_object_constraint_loop_flags(base1->object);
201
 
                }
202
 
                test_constraints(owner, bone->name, 1);
203
 
                test_bonelist_constraints (owner, &bone->childbase);
204
 
        }
205
 
}
206
 
 
207
 
 
208
 
static void clear_object_constraint_loop_flags(Object *ob)
209
 
{
210
 
        bConstraint *con;
211
 
 
212
 
        if (!ob)
213
 
                return;
214
 
 
215
 
        /* Test object constraints */
216
 
        for (con = ob->constraints.first; con; con=con->next){
217
 
                con->flag &= ~CONSTRAINT_LOOPTESTED;
218
 
        }
219
 
 
220
 
        switch (ob->type){
221
 
        case OB_ARMATURE:
222
 
                if (ob->pose){
223
 
                        bPoseChannel *pchan;
224
 
                        for (pchan = ob->pose->chanbase.first; pchan; pchan=pchan->next){
225
 
                                for (con = pchan->constraints.first; con; con=con->next){
226
 
                                        con->flag &= ~CONSTRAINT_LOOPTESTED;
227
 
                                }
228
 
                        }
229
 
                }
230
 
                break;
231
 
        default:
232
 
                break;
233
 
        }
234
 
}
235
 
void test_scene_constraints (void)
236
 
{
237
 
        Base *base, *base1;
238
 
 
239
 
/*      Clear the "done" flags of all constraints */
240
 
 
241
 
        for (base = G.scene->base.first; base; base=base->next){
242
 
                clear_object_constraint_loop_flags(base->object);
243
 
        }
244
 
 
245
 
        /*      Test all constraints */
246
 
        for (base = G.scene->base.first; base; base=base->next){
247
 
                /* Test the object */
248
 
                
249
 
                for (base1 = G.scene->base.first; base1; base1=base1->next)
250
 
                        clear_object_constraint_loop_flags(base1->object);
251
 
                
252
 
 
253
 
                test_constraints (base->object, "", 1);
254
 
 
255
 
        
256
 
                /* Test the subobject constraints */
257
 
                switch (base->object->type){
258
 
                case OB_ARMATURE:
259
 
                        {
260
 
                                bArmature *arm;
261
 
                                arm = get_armature(base->object);
262
 
                                if (arm)
263
 
                                        test_bonelist_constraints (base->object, &arm->bonebase);
264
 
                        }
265
 
                        break;
266
 
                default:
267
 
                        break;
268
 
                }
269
 
 
270
 
 
271
 
        }
272
 
}
273
 
 
274
 
int test_constraints (Object *owner, const char *substring, int disable)
275
 
{
276
 
/*      init_constraint_elements();*/
277
 
        g_conObj = owner;
278
 
        g_conString = substring;
279
 
 
280
 
        if (detect_constraint_loop (owner, substring, disable, 0))
281
 
                return 1;
282
 
        else
283
 
                return 0;
284
 
 
285
 
/*      free_constraint_elements();     */
286
 
}
287
 
 
288
 
static short detect_constraint_loop (Object *owner, const char* substring, int disable, char typefrom)
289
 
{
290
 
 
291
 
        bConstraint *curcon;
292
 
        ListBase *conlist;
293
 
        int             type;
294
 
        int             result = 0;
295
 
 
296
 
        if (!owner)
297
 
                return result;
298
 
 
299
 
        /* Check parents */
300
 
        /* Get the constraint list for this object */
301
 
 
302
 
        if (strlen (substring)){
303
 
                switch (owner->type){
304
 
                case OB_ARMATURE:
305
 
                        type = TARGET_BONE;
306
 
                        break;
307
 
                default:
308
 
                        type = TARGET_OBJECT;
309
 
                        break;
310
 
                }
311
 
        }
312
 
        else
313
 
                type = TARGET_OBJECT;
314
 
 
315
 
 
316
 
        switch (type){
317
 
        case TARGET_OBJECT:
318
 
                conlist = &owner->constraints;
319
 
                /* Check parents */
320
 
#if 0
321
 
                if (owner->parent && (ELEM (owner->partype, PAROBJECT, PARBONE))){
322
 
                        if (add_constraint_element (owner->parent, "", NULL, NULL)){
323
 
                                return 1;
324
 
                        }
325
 
                /*      if (detect_constraint_loop (owner->parent, "", disable)){
326
 
                                return 1;
327
 
                        }
328
 
                */
329
 
                }
330
 
                /* Check tracking */
331
 
                if (owner->track && (ELEM (owner->partype, PAROBJECT, PARBONE))){
332
 
                        if (add_constraint_element (owner->track, "", NULL, NULL)){
333
 
                                return 1;
334
 
                        }
335
 
                /*      if (detect_constraint_loop (owner->track, "", disable)){
336
 
                                return 1;
337
 
                        }
338
 
                */
339
 
                }
340
 
#else
341
 
                if (owner->parent && (owner->partype==PAROBJECT))
342
 
                        if (add_constraint_element (owner->parent, "", NULL, NULL))
343
 
                                return 1;
344
 
 
345
 
                if (owner->parent && (owner->partype==PARBONE))
346
 
                        if (add_constraint_element (owner->parent, owner->parsubstr, NULL, NULL))
347
 
                                return 1;
348
 
 
349
 
                /* Check tracking */
350
 
                if (owner->track)
351
 
                        if (add_constraint_element (owner->track, "", NULL, NULL))
352
 
                                return 1;
353
 
#endif
354
 
 
355
 
                break;
356
 
        case TARGET_BONE:
357
 
                {
358
 
                        Bone *bone;
359
 
                        bPoseChannel *chan;
360
 
 
361
 
                        bone = get_named_bone(((bArmature*)owner->data), substring);
362
 
                        chan = get_pose_channel (owner->pose, substring);
363
 
                        if (bone){
364
 
                                conlist = &chan->constraints;
365
 
                                if (bone->parent){
366
 
                                        if (add_constraint_element (owner, bone->parent->name, NULL, NULL))
367
 
                                                return 1;
368
 
                                        if (detect_constraint_loop (owner, bone->parent->name, disable, 0))
369
 
                                                return 1;
370
 
                                }
371
 
                                else{
372
 
                                        if (add_constraint_element (owner, "", NULL, NULL))
373
 
                                                return 1;
374
 
                                        if (detect_constraint_loop (owner, "", disable, 0))
375
 
                                                return 1;
376
 
                                }
377
 
                        }
378
 
                        else
379
 
                                conlist = NULL;
380
 
                }
381
 
                break;
382
 
        default:
383
 
                conlist = NULL;
384
 
                break;
385
 
        }
386
 
        
387
 
        /* Cycle constraints */
388
 
        if (conlist){
389
 
                for (curcon = conlist->first; curcon; curcon=curcon->next){
390
 
                        
391
 
                        /* Clear the disable flag */
392
 
                        
393
 
                        if (curcon->flag & CONSTRAINT_LOOPTESTED){
394
 
                                return 0;
395
 
                        }
396
 
                        else {
397
 
                                curcon->flag &= ~CONSTRAINT_DISABLE;
398
 
                                curcon->flag |= CONSTRAINT_LOOPTESTED;
399
 
                                switch (curcon->type){
400
 
                                case CONSTRAINT_TYPE_ACTION:
401
 
                                        {
402
 
                                                bActionConstraint *data = curcon->data;
403
 
 
404
 
                                                if (!exist_object(data->tar)){
405
 
                                                        data->tar = NULL;
406
 
                                                        break;
407
 
                                                }
408
 
                                                
409
 
                                                if ( (data->tar == owner) &&
410
 
                                                         (!get_named_bone(get_armature(owner), 
411
 
                                                                                          data->subtarget))) {
412
 
                                                        curcon->flag |= CONSTRAINT_DISABLE;
413
 
                                                        result = 1;
414
 
                                                        break;
415
 
                                                }
416
 
                                                if (add_constraint_element (data->tar, data->subtarget, owner, substring)){
417
 
                                                        curcon->flag |= CONSTRAINT_DISABLE;
418
 
                                                        result = 1;
419
 
                                                        break;
420
 
                                                        //              return 1;
421
 
                                                }
422
 
                                                if (detect_constraint_loop (data->tar, data->subtarget, disable, CONSTRAINT_TYPE_ACTION)){
423
 
                                                        curcon->flag |= CONSTRAINT_DISABLE;
424
 
                                                        result = 1;
425
 
                                                        break;
426
 
                                                        //              return 1;
427
 
                                                }
428
 
                                        }
429
 
                                        break;
430
 
                                case CONSTRAINT_TYPE_LOCLIKE:
431
 
                                        {
432
 
                                                bLocateLikeConstraint *data = curcon->data;
433
 
                                        
434
 
                                                if (!exist_object(data->tar)){
435
 
                                                        data->tar = NULL;
436
 
                                                        break;
437
 
                                                }
438
 
                                                
439
 
                                                if ( (data->tar == owner) &&
440
 
                                                         (!get_named_bone(get_armature(owner), 
441
 
                                                                                          data->subtarget))) {
442
 
                                                        curcon->flag |= CONSTRAINT_DISABLE;
443
 
                                                        result = 1;
444
 
                                                        break;
445
 
                                                }
446
 
                                                if (add_constraint_element (data->tar, data->subtarget, owner, substring)){
447
 
                                                        curcon->flag |= CONSTRAINT_DISABLE;
448
 
                                                        result = 1;
449
 
                                                        break;
450
 
                                                        //              return 1;
451
 
                                                }
452
 
                                                if (detect_constraint_loop (data->tar, data->subtarget, disable, CONSTRAINT_TYPE_LOCLIKE)){
453
 
                                                        curcon->flag |= CONSTRAINT_DISABLE;
454
 
                                                        result = 1;
455
 
                                                        break;
456
 
                                                        //              return 1;
457
 
                                                }
458
 
                                        }
459
 
                                        break;
460
 
                                case CONSTRAINT_TYPE_ROTLIKE:
461
 
                                        {
462
 
                                                bRotateLikeConstraint *data = curcon->data;
463
 
                                        
464
 
                                                if (!exist_object(data->tar)){
465
 
                                                        data->tar = NULL;
466
 
                                                        break;
467
 
                                                }
468
 
                                                
469
 
                                                if ( (data->tar == owner) &&
470
 
                                                         (!get_named_bone(get_armature(owner), 
471
 
                                                                                          data->subtarget))) {
472
 
                                                        curcon->flag |= CONSTRAINT_DISABLE;
473
 
                                                        result = 1;
474
 
                                                        break;
475
 
                                                }
476
 
                                                if (add_constraint_element (data->tar, data->subtarget, owner, substring)){
477
 
                                                        curcon->flag |= CONSTRAINT_DISABLE;
478
 
                                                        result = 1;
479
 
                                                        break;
480
 
                                                        //              return 1;
481
 
                                                }
482
 
                                                if (detect_constraint_loop (data->tar, data->subtarget, disable, CONSTRAINT_TYPE_ROTLIKE)){
483
 
                                                        curcon->flag |= CONSTRAINT_DISABLE;
484
 
                                                        result = 1;
485
 
                                                        break;
486
 
                                                        //              return 1;
487
 
                                                }
488
 
                                        }
489
 
                                        break;
490
 
                                case CONSTRAINT_TYPE_KINEMATIC:
491
 
                                        {
492
 
                                                bKinematicConstraint *data = curcon->data;
493
 
                                                if (!exist_object(data->tar)){
494
 
                                                        data->tar = NULL;
495
 
                                                        break;
496
 
                                                }
497
 
 
498
 
                                                if ( (data->tar == owner) &&
499
 
                                                         (!get_named_bone(get_armature(owner), 
500
 
                                                                                          data->subtarget))) {
501
 
                                                        curcon->flag |= CONSTRAINT_DISABLE;
502
 
                                                        result = 1;
503
 
                                                        break;
504
 
                                                }
505
 
                                                if (add_constraint_element (data->tar, data->subtarget, owner, substring)){
506
 
                                                        curcon->flag |= CONSTRAINT_DISABLE;
507
 
                                                        result = 1;
508
 
                                                        break;
509
 
                                                        //      return 1;
510
 
                                                }
511
 
                                                if (detect_constraint_loop (data->tar, data->subtarget, disable, CONSTRAINT_TYPE_KINEMATIC)){
512
 
                                                        curcon->flag |= CONSTRAINT_DISABLE;
513
 
                                                        result = 1;
514
 
                                                        break;
515
 
                                                        //              return 1;
516
 
                                                }
517
 
                                        }
518
 
                                        break;
519
 
                                case CONSTRAINT_TYPE_TRACKTO:
520
 
                                        {
521
 
                                                bTrackToConstraint *data = curcon->data;
522
 
                                                if (!exist_object(data->tar)) {
523
 
                                                        data->tar = NULL;
524
 
                                                        break;
525
 
                                                }
526
 
                                                
527
 
                                                if ( (data->tar == owner) &&
528
 
                                                         (!get_named_bone(get_armature(owner), 
529
 
                                                                                          data->subtarget))) {
530
 
                                                        curcon->flag |= CONSTRAINT_DISABLE;
531
 
                                                        result = 1;
532
 
                                                        break;
533
 
                                                }
534
 
                                                if (typefrom != CONSTRAINT_TYPE_TRACKTO && typefrom != CONSTRAINT_TYPE_LOCKTRACK){
535
 
                                                        if (add_constraint_element (data->tar, data->subtarget, owner, substring)){
536
 
                                                                curcon->flag |= CONSTRAINT_DISABLE;
537
 
                                                                result = 1;
538
 
                                                                break;
539
 
                                                                //      return 1;
540
 
                                                        }
541
 
                                                }
542
 
                                                else {
543
 
                                                        curcon->flag |= CONSTRAINT_NOREFRESH;
544
 
                                                }
545
 
 
546
 
                                                if (detect_constraint_loop (data->tar, data->subtarget, disable, CONSTRAINT_TYPE_TRACKTO)){
547
 
                                                        curcon->flag |= CONSTRAINT_DISABLE;
548
 
                                                        result = 1;
549
 
                                                        break;
550
 
                                                        //              return 1;
551
 
                                                }
552
 
                                                if (data->reserved2==data->reserved1){
553
 
                                                        curcon->flag |= CONSTRAINT_DISABLE;
554
 
                                                        result = 1;
555
 
                                                        break;
556
 
                                                        //              return 1;
557
 
                                                }
558
 
                                                if (data->reserved2+3==data->reserved1){
559
 
                                                        curcon->flag |= CONSTRAINT_DISABLE;
560
 
                                                        result = 1;
561
 
                                                        break;
562
 
                                                        //              return 1;
563
 
                                                }
564
 
                                        }
565
 
                                        break;
566
 
                                case CONSTRAINT_TYPE_LOCKTRACK:
567
 
                                        {
568
 
                                                bLockTrackConstraint *data = curcon->data;
569
 
                                        
570
 
                                                if (!exist_object(data->tar)){
571
 
                                                        data->tar = NULL;
572
 
                                                        break;
573
 
                                                }
574
 
                                                
575
 
                                                if ( (data->tar == owner) &&
576
 
                                                         (!get_named_bone(get_armature(owner), 
577
 
                                                                                          data->subtarget))) {
578
 
                                                        curcon->flag |= CONSTRAINT_DISABLE;
579
 
                                                        result = 1;
580
 
                                                        break;
581
 
                                                }
582
 
                                                if (typefrom != CONSTRAINT_TYPE_TRACKTO && typefrom != CONSTRAINT_TYPE_LOCKTRACK){
583
 
                                                        if (add_constraint_element (data->tar, data->subtarget, owner, substring)){
584
 
                                                                curcon->flag |= CONSTRAINT_DISABLE;
585
 
                                                                result = 1;
586
 
                                                                break;
587
 
                                                                //              return 1;
588
 
                                                        }
589
 
                                                }
590
 
                                                else {
591
 
                                                        curcon->flag |= CONSTRAINT_NOREFRESH;
592
 
                                                }
593
 
 
594
 
                                                if (detect_constraint_loop (data->tar, data->subtarget, disable, CONSTRAINT_TYPE_LOCKTRACK)){
595
 
                                                        curcon->flag |= CONSTRAINT_DISABLE;
596
 
                                                        result = 1;
597
 
                                                        break;
598
 
                                                        //              return 1;
599
 
                                                }
600
 
                                                if (data->lockflag==data->trackflag){
601
 
                                                        curcon->flag |= CONSTRAINT_DISABLE;
602
 
                                                        result = 1;
603
 
                                                        break;
604
 
                                                        //              return 1;
605
 
                                                }
606
 
                                                if (data->lockflag+3==data->trackflag){
607
 
                                                        curcon->flag |= CONSTRAINT_DISABLE;
608
 
                                                        result = 1;
609
 
                                                        break;
610
 
                                                        //              return 1;
611
 
                                                }
612
 
                                        }
613
 
                                        break;
614
 
                                case CONSTRAINT_TYPE_STRETCHTO:
615
 
                                        {
616
 
                                                bStretchToConstraint *data = curcon->data;
617
 
                                        
618
 
                                                if (!exist_object(data->tar)){
619
 
                                                        data->tar = NULL;
620
 
                                                        break;
621
 
                                                }
622
 
 
623
 
                                                if ( (data->tar == owner) &&
624
 
                                                         (!get_named_bone(get_armature(owner), 
625
 
                                                                                          data->subtarget))) {
626
 
                                                        curcon->flag |= CONSTRAINT_DISABLE;
627
 
                                                        result = 1;
628
 
                                                        break;
629
 
                                                }
630
 
                                                if (detect_constraint_loop (data->tar, data->subtarget, disable, CONSTRAINT_TYPE_LOCKTRACK)){
631
 
                                                        curcon->flag |= CONSTRAINT_DISABLE;
632
 
                                                        result = 1;
633
 
                                                        break;
634
 
                                                        //              return 1;
635
 
                                                }
636
 
                                        }
637
 
                                        break;
638
 
                                case CONSTRAINT_TYPE_FOLLOWPATH:
639
 
                                        {
640
 
                                                bFollowPathConstraint *data = curcon->data;
641
 
                                        
642
 
                                                if (!exist_object(data->tar)){
643
 
                                                        data->tar = NULL;
644
 
                                                        break;
645
 
                                                }
646
 
                                                if (data->tar->type != OB_CURVE){
647
 
                                                        data->tar = NULL;
648
 
                                                        break;
649
 
                                                }
650
 
                                                if (add_constraint_element (data->tar, "", owner, substring)){
651
 
                                                        curcon->flag |= CONSTRAINT_DISABLE;
652
 
                                                        result = 1;
653
 
                                                        break;
654
 
                                                        //              return 1;
655
 
                                                }
656
 
                                                if (detect_constraint_loop (data->tar, "", disable, CONSTRAINT_TYPE_FOLLOWPATH)){
657
 
                                                        curcon->flag |= CONSTRAINT_DISABLE;
658
 
                                                        result = 1;
659
 
                                                        break;
660
 
                                                        //              return 1;
661
 
                                                }
662
 
                                                if (data->upflag==data->trackflag){
663
 
                                                        curcon->flag |= CONSTRAINT_DISABLE;
664
 
                                                        result = 1;
665
 
                                                        break;
666
 
                                                        //              return 1;
667
 
                                                }
668
 
                                                if (data->upflag+3==data->trackflag){
669
 
                                                        curcon->flag |= CONSTRAINT_DISABLE;
670
 
                                                        result = 1;
671
 
                                                        break;
672
 
                                                        //              return 1;
673
 
                                                }
674
 
                                        }
675
 
                                        break;
676
 
                                }
677
 
                        }
678
 
                }
679
 
        }
680
 
        
681
 
        return result;
682
 
}
683
 
 
684
 
ListBase *get_constraint_client_channels (int forcevalid)
685
 
{
686
 
 
687
 
        Object *ob;
 
70
#include "mydevice.h"
 
71
 
 
72
 
 
73
ListBase *get_active_constraint_channels (Object *ob, int forcevalid)
 
74
{
688
75
        char ipstr[64];
689
 
 
690
 
        ob=OBACT;
691
76
        
692
77
        if (!ob)
693
78
                return NULL;
694
79
        
695
80
        /* See if we are a bone constraint */
696
 
        if (G.obpose){
697
 
                switch (G.obpose->type){
698
 
                case OB_ARMATURE:
699
 
                        {
700
 
                                bActionChannel *achan;
701
 
                                Bone *bone;
702
 
 
703
 
                                bone = get_first_selected_bone();
704
 
                                if (!bone) break;
705
 
                                
706
 
                                /* Make sure we have an action */
707
 
                                if (!G.obpose->action){
708
 
                                        if (!forcevalid)
709
 
                                                return NULL;
710
 
                                        
711
 
                                        G.obpose->action=add_empty_action();
712
 
                                }
713
 
                                
714
 
                                /* Make sure we have an actionchannel */
715
 
                                achan = get_named_actionchannel(G.obpose->action, bone->name);
716
 
                                if (!achan){
717
 
                                        if (!forcevalid)
718
 
                                                return NULL;
719
 
                                        
720
 
                                        achan = MEM_callocN (sizeof(bActionChannel), "actionChannel");
721
 
 
722
 
                                        strcpy (achan->name, bone->name);
723
 
                                        sprintf (ipstr, "%s.%s", G.obpose->action->id.name+2, achan->name);
724
 
                                        ipstr[23]=0;
725
 
                                        achan->ipo=     add_ipo(ipstr, ID_AC);  
726
 
                                        
727
 
                                        BLI_addtail (&G.obpose->action->chanbase, achan);
728
 
                                }
729
 
                                
 
81
        if (ob->flag & OB_POSEMODE) {
 
82
                bActionChannel *achan;
 
83
                bPoseChannel *pchan;
 
84
 
 
85
                pchan = get_active_posechannel(ob);
 
86
                if (pchan) {
 
87
                        
 
88
                        /* Make sure we have an action */
 
89
                        if (!ob->action){
 
90
                                if (!forcevalid)
 
91
                                        return NULL;
 
92
                                
 
93
                                ob->action=add_empty_action(ID_PO);
 
94
                        }
 
95
                        
 
96
                        /* Make sure we have an actionchannel */
 
97
                        achan = get_action_channel(ob->action, pchan->name);
 
98
                        if (!achan){
 
99
                                if (!forcevalid)
 
100
                                        return NULL;
 
101
                                
 
102
                                achan = MEM_callocN (sizeof(bActionChannel), "actionChannel");
 
103
 
 
104
                                strcpy (achan->name, pchan->name);
 
105
                                sprintf (ipstr, "%s.%s", ob->action->id.name+2, achan->name);
 
106
                                ipstr[23]=0;
 
107
                                achan->ipo=     add_ipo(ipstr, ID_AC);  
 
108
                                
 
109
                                BLI_addtail (&ob->action->chanbase, achan);
 
110
                        }
 
111
                        
 
112
                        return &achan->constraintChannels;
 
113
                }
 
114
                else return NULL;
 
115
        }
 
116
        /* else we return object constraints */
 
117
        else {
 
118
                if(ob->ipoflag & OB_ACTION_OB) {
 
119
                        bActionChannel *achan = get_action_channel(ob->action, "Object");
 
120
                        if(achan)
730
121
                                return &achan->constraintChannels;
731
 
                        }
 
122
                        else 
 
123
                                return NULL;
732
124
                }
 
125
                
 
126
                return &ob->constraintChannels;
733
127
        }
734
 
        
735
 
        return &ob->constraintChannels;
736
128
}
737
129
 
738
 
ListBase *get_constraint_client(char *name, short *clientType, void **clientdata)
 
130
 
 
131
/* if object in posemode, active bone constraints, else object constraints */
 
132
ListBase *get_active_constraints(Object *ob)
739
133
{
740
 
        Object *ob;
741
 
        ListBase *list;
742
 
 
743
 
        ob=OBACT;
744
 
        if (clientType)
745
 
                *clientType = -1;
746
 
 
747
134
        if (!ob)
748
135
                return NULL;
749
136
 
750
 
        list = &ob->constraints;
751
 
 
752
 
        /* Prep the object's constraint channels */
753
 
        if (clientType)
754
 
                *clientType = TARGET_OBJECT;
755
 
        
756
 
        if (name)
757
 
                strcpy (name, ob->id.name+2);
758
 
 
759
 
        if (G.obpose){
760
 
                switch (G.obpose->type){
761
 
                case OB_ARMATURE:
762
 
                        {
763
 
                                Bone *bone;
764
 
 
765
 
                                bone = get_first_selected_bone();
766
 
                                if (!bone) break;
767
 
 
768
 
                                {
769
 
                                        bPoseChannel    *chan;
770
 
                                        
771
 
                                        /* Is the bone the client? */
772
 
                                        if (clientType)
773
 
                                                *clientType = TARGET_BONE;
774
 
                                        if (clientdata)
775
 
                                                *clientdata = bone;
776
 
                                        if (name)
777
 
                                                sprintf (name, "%s>>%s", name, bone->name);
778
 
                                        chan = verify_pose_channel(G.obpose->pose, bone->name);
779
 
                                        list = &chan->constraints;
780
 
 
781
 
                                }                       
782
 
                        }
783
 
                        break;
784
 
                }
785
 
        }
786
 
 
787
 
        return list;
788
 
}
789
 
 
790
 
bConstraint * add_new_constraint(char type)
 
137
        if (ob->flag & OB_POSEMODE) {
 
138
                bPoseChannel *pchan;
 
139
 
 
140
                pchan = get_active_posechannel(ob);
 
141
                if (pchan)
 
142
                        return &pchan->constraints;
 
143
        }
 
144
        else 
 
145
                return &ob->constraints;
 
146
 
 
147
        return NULL;
 
148
}
 
149
 
 
150
/* single constraint */
 
151
bConstraint *get_active_constraint(Object *ob)
 
152
{
 
153
        ListBase *lb= get_active_constraints(ob);
 
154
 
 
155
        if(lb) {
 
156
                bConstraint *con;
 
157
                for(con= lb->first; con; con=con->next)
 
158
                        if(con->flag & CONSTRAINT_ACTIVE)
 
159
                                return con;
 
160
        }
 
161
        return NULL;
 
162
}
 
163
 
 
164
/* single channel, for ipo */
 
165
bConstraintChannel *get_active_constraint_channel(Object *ob)
 
166
{
 
167
        bConstraint *con;
 
168
        bConstraintChannel *chan;
 
169
        
 
170
        if (ob->flag & OB_POSEMODE) {
 
171
                if(ob->action) {
 
172
                        bPoseChannel *pchan;
 
173
                        
 
174
                        pchan = get_active_posechannel(ob);
 
175
                        if(pchan) {
 
176
                                for(con= pchan->constraints.first; con; con= con->next)
 
177
                                        if(con->flag & CONSTRAINT_ACTIVE)
 
178
                                                break;
 
179
                                if(con) {
 
180
                                        bActionChannel *achan = get_action_channel(ob->action, pchan->name);
 
181
                                        if(achan) {
 
182
                                                for(chan= achan->constraintChannels.first; chan; chan= chan->next)
 
183
                                                        if(!strcmp(chan->name, con->name))
 
184
                                                                break;
 
185
                                                return chan;
 
186
                                        }
 
187
                                }
 
188
                        }
 
189
                }
 
190
        }
 
191
        else {
 
192
                for(con= ob->constraints.first; con; con= con->next)
 
193
                        if(con->flag & CONSTRAINT_ACTIVE)
 
194
                                break;
 
195
                if(con) {
 
196
                        ListBase *lb= get_active_constraint_channels(ob, 0);
 
197
 
 
198
                        if(lb) {
 
199
                                for(chan= lb->first; chan; chan= chan->next)
 
200
                                        if(!strcmp(chan->name, con->name))
 
201
                                                break;
 
202
                                return chan;
 
203
                        }
 
204
                }
 
205
        }
 
206
        
 
207
        return NULL;
 
208
}
 
209
 
 
210
 
 
211
bConstraint *add_new_constraint(short type)
791
212
{
792
213
        bConstraint *con;
793
214
 
807
228
{
808
229
        ListBase *list;
809
230
        list = &ob->constraints;
810
 
        if (list)
811
 
        {
812
 
                unique_constraint_name(con, list);
813
 
                BLI_addtail(list, con);
814
 
        }
815
 
}
816
 
 
817
 
void add_constraint_to_client(bConstraint *con)
818
 
{
819
 
        ListBase *list;
820
 
        short type;
821
 
        list = get_constraint_client(NULL, &type, NULL);
822
 
        if (list)
823
 
        {
824
 
                unique_constraint_name(con, list);
825
 
                BLI_addtail(list, con);
826
 
        }
827
 
}
828
 
 
829
 
bConstraintChannel *add_new_constraint_channel(const char* name)
830
 
{
831
 
        bConstraintChannel *chan = NULL;
832
 
 
833
 
        chan = MEM_callocN(sizeof(bConstraintChannel), "constraintChannel");
834
 
        strcpy(chan->name, name);
835
231
        
836
 
        return chan;
837
 
}
838
 
 
839
 
void add_influence_key_to_constraint (bConstraint *con){
840
 
        printf("doesn't do anything yet\n");
841
 
}
842
 
 
843
 
char *get_con_subtarget_name(bConstraint *constraint, Object *target)
 
232
        if (list) {
 
233
                unique_constraint_name(con, list);
 
234
                BLI_addtail(list, con);
 
235
                
 
236
                con->flag |= CONSTRAINT_ACTIVE;
 
237
                for(con= con->prev; con; con= con->prev)
 
238
                        con->flag &= ~CONSTRAINT_ACTIVE;
 
239
        }
 
240
}
 
241
 
 
242
 
 
243
char *get_con_subtarget_name(bConstraint *con, Object *target)
844
244
{
845
245
        /*
846
246
         * If the target for this constraint is target, return a pointer 
847
247
         * to the name for this constraints subtarget ... NULL otherwise
848
248
         */
849
 
        switch (constraint->type) {
 
249
        switch (con->type) {
850
250
 
851
251
                case CONSTRAINT_TYPE_ACTION:
852
252
                {
853
 
                        bActionConstraint *data = constraint->data;
 
253
                        bActionConstraint *data = con->data;
854
254
                        if (data->tar==target) return data->subtarget;
855
255
                }
856
256
                break;
857
257
                case CONSTRAINT_TYPE_LOCLIKE:
858
258
                {
859
 
                        bLocateLikeConstraint *data = constraint->data;
 
259
                        bLocateLikeConstraint *data = con->data;
860
260
                        if (data->tar==target) return data->subtarget;
861
261
                }
862
262
                break;
863
263
                case CONSTRAINT_TYPE_ROTLIKE:
864
264
                {
865
 
                        bRotateLikeConstraint *data = constraint->data;
 
265
                        bRotateLikeConstraint *data = con->data;
866
266
                        if (data->tar==target) return data->subtarget;
867
267
                }
868
268
                break;
869
269
                case CONSTRAINT_TYPE_KINEMATIC:
870
270
                {
871
 
                        bKinematicConstraint *data = constraint->data;
 
271
                        bKinematicConstraint *data = con->data;
872
272
                        if (data->tar==target) return data->subtarget;
873
273
                }
874
274
                break;
875
275
                case CONSTRAINT_TYPE_TRACKTO:
876
276
                {
877
 
                        bTrackToConstraint *data = constraint->data;
 
277
                        bTrackToConstraint *data = con->data;
 
278
                        if (data->tar==target) return data->subtarget;
 
279
                }
 
280
                break;
 
281
                case CONSTRAINT_TYPE_MINMAX:
 
282
                {
 
283
                        bMinMaxConstraint *data = con->data;
878
284
                        if (data->tar==target) return data->subtarget;
879
285
                }
880
286
                break;
881
287
                case CONSTRAINT_TYPE_LOCKTRACK:
882
288
                {
883
 
                        bLockTrackConstraint *data = constraint->data;
 
289
                        bLockTrackConstraint *data = con->data;
884
290
                        if (data->tar==target) return data->subtarget;
885
291
                }
886
292
                break;
887
293
                case CONSTRAINT_TYPE_STRETCHTO:
888
294
                {
889
 
                        bStretchToConstraint *data = constraint->data;
 
295
                        bStretchToConstraint *data = con->data;
890
296
                        if (data->tar==target) return data->subtarget;
891
297
                }
892
298
                break;
896
302
                         */
897
303
                {
898
304
                        /*
899
 
                         * bFollowPathConstraint *data = constraint->data;
 
305
                         * bFollowPathConstraint *data = con->data;
900
306
                         */
901
307
                        return NULL;
902
308
                }
906
312
        return NULL;  
907
313
}
908
314
 
 
315
/* checks validity of object pointers, and NULLs,
 
316
   if Bone doesnt exist it sets the CONSTRAINT_DISABLE flag */
 
317
static void test_constraints (Object *owner, const char* substring)
 
318
{
 
319
        
 
320
        bConstraint *curcon;
 
321
        ListBase *conlist= NULL;
 
322
        int type;
 
323
        
 
324
        if (owner==NULL) return;
 
325
        
 
326
        /* Check parents */
 
327
        /* Get the constraint list for this object */
 
328
        
 
329
        if (strlen (substring)){
 
330
                switch (owner->type){
 
331
                        case OB_ARMATURE:
 
332
                                type = TARGET_BONE;
 
333
                                break;
 
334
                        default:
 
335
                                type = TARGET_OBJECT;
 
336
                                break;
 
337
                }
 
338
        }
 
339
        else
 
340
                type = TARGET_OBJECT;
 
341
        
 
342
        
 
343
        switch (type){
 
344
                case TARGET_OBJECT:
 
345
                        conlist = &owner->constraints;
 
346
                        break;
 
347
                case TARGET_BONE:
 
348
                        {
 
349
                                Bone *bone;
 
350
                                bPoseChannel *chan;
 
351
                                
 
352
                                bone = get_named_bone(((bArmature*)owner->data), substring);
 
353
                                chan = get_pose_channel (owner->pose, substring);
 
354
                                if (bone && chan){
 
355
                                        conlist = &chan->constraints;
 
356
                                }
 
357
                        }
 
358
                        break;
 
359
        }
 
360
        
 
361
        /* Cycle constraints */
 
362
        if (conlist){
 
363
                for (curcon = conlist->first; curcon; curcon=curcon->next){
 
364
                        curcon->flag &= ~CONSTRAINT_DISABLE;
 
365
                        
 
366
                        switch (curcon->type){
 
367
                                case CONSTRAINT_TYPE_ACTION:
 
368
                                {
 
369
                                        bActionConstraint *data = curcon->data;
 
370
                                        
 
371
                                        if (!exist_object(data->tar)){
 
372
                                                data->tar = NULL;
 
373
                                                curcon->flag |= CONSTRAINT_DISABLE;
 
374
                                                break;
 
375
                                        }
 
376
                                        
 
377
                                        if ( (data->tar == owner) &&
 
378
                                                 (!get_named_bone(get_armature(owner), 
 
379
                                                                                  data->subtarget))) {
 
380
                                                curcon->flag |= CONSTRAINT_DISABLE;
 
381
                                                break;
 
382
                                        }
 
383
                                }
 
384
                                        break;
 
385
                                case CONSTRAINT_TYPE_LOCLIKE:
 
386
                                {
 
387
                                        bLocateLikeConstraint *data = curcon->data;
 
388
                                        
 
389
                                        if (!exist_object(data->tar)){
 
390
                                                data->tar = NULL;
 
391
                                                curcon->flag |= CONSTRAINT_DISABLE;
 
392
                                                break;
 
393
                                        }
 
394
                                        
 
395
                                        if ( (data->tar == owner) &&
 
396
                                                 (!get_named_bone(get_armature(owner), 
 
397
                                                                                  data->subtarget))) {
 
398
                                                curcon->flag |= CONSTRAINT_DISABLE;
 
399
                                                break;
 
400
                                        }
 
401
                                }
 
402
                                        break;
 
403
                                case CONSTRAINT_TYPE_MINMAX:
 
404
                                {
 
405
                                        bMinMaxConstraint *data = curcon->data;
 
406
                                        
 
407
                                        if (!exist_object(data->tar)){
 
408
                                                data->tar = NULL;
 
409
                                                curcon->flag |= CONSTRAINT_DISABLE;
 
410
                                                break;
 
411
                                        }
 
412
                                        
 
413
                                        if ( (data->tar == owner) &&
 
414
                                                 (!get_named_bone(get_armature(owner), 
 
415
                                                                                  data->subtarget))) {
 
416
                                                curcon->flag |= CONSTRAINT_DISABLE;
 
417
                                                break;
 
418
                                        }
 
419
                                }
 
420
                                        break;
 
421
                                case CONSTRAINT_TYPE_ROTLIKE:
 
422
                                {
 
423
                                        bRotateLikeConstraint *data = curcon->data;
 
424
                                        
 
425
                                        if (!exist_object(data->tar)){
 
426
                                                data->tar = NULL;
 
427
                                                curcon->flag |= CONSTRAINT_DISABLE;
 
428
                                                break;
 
429
                                        }
 
430
                                        
 
431
                                        if ( (data->tar == owner) &&
 
432
                                                 (!get_named_bone(get_armature(owner), 
 
433
                                                                                  data->subtarget))) {
 
434
                                                curcon->flag |= CONSTRAINT_DISABLE;
 
435
                                                break;
 
436
                                        }
 
437
                                }
 
438
                                        break;
 
439
                                case CONSTRAINT_TYPE_KINEMATIC:
 
440
                                {
 
441
                                        bKinematicConstraint *data = curcon->data;
 
442
                                        if (!exist_object(data->tar)){
 
443
                                                data->tar = NULL;
 
444
                                                curcon->flag |= CONSTRAINT_DISABLE;
 
445
                                                break;
 
446
                                        }
 
447
                                        
 
448
                                        if ( (data->tar == owner) &&
 
449
                                                 (!get_named_bone(get_armature(owner), 
 
450
                                                                                  data->subtarget))) {
 
451
                                                curcon->flag |= CONSTRAINT_DISABLE;
 
452
                                                break;
 
453
                                        }
 
454
                                }
 
455
                                        break;
 
456
                                case CONSTRAINT_TYPE_TRACKTO:
 
457
                                {
 
458
                                        bTrackToConstraint *data = curcon->data;
 
459
                                        if (!exist_object(data->tar)) {
 
460
                                                data->tar = NULL;
 
461
                                                curcon->flag |= CONSTRAINT_DISABLE;
 
462
                                                break;
 
463
                                        }
 
464
                                        
 
465
                                        if ( (data->tar == owner) &&
 
466
                                                 (!get_named_bone(get_armature(owner), 
 
467
                                                                                  data->subtarget))) {
 
468
                                                curcon->flag |= CONSTRAINT_DISABLE;
 
469
                                                break;
 
470
                                        }
 
471
                                        if (data->reserved2==data->reserved1){
 
472
                                                curcon->flag |= CONSTRAINT_DISABLE;
 
473
                                                break;
 
474
                                        }
 
475
                                        if (data->reserved2+3==data->reserved1){
 
476
                                                curcon->flag |= CONSTRAINT_DISABLE;
 
477
                                                break;
 
478
                                        }
 
479
                                }
 
480
                                        break;
 
481
                                case CONSTRAINT_TYPE_LOCKTRACK:
 
482
                                {
 
483
                                        bLockTrackConstraint *data = curcon->data;
 
484
                                        
 
485
                                        if (!exist_object(data->tar)){
 
486
                                                data->tar = NULL;
 
487
                                                curcon->flag |= CONSTRAINT_DISABLE;
 
488
                                                break;
 
489
                                        }
 
490
                                        
 
491
                                        if ( (data->tar == owner) &&
 
492
                                                 (!get_named_bone(get_armature(owner), 
 
493
                                                                                  data->subtarget))) {
 
494
                                                curcon->flag |= CONSTRAINT_DISABLE;
 
495
                                                break;
 
496
                                        }
 
497
 
 
498
                                        if (data->lockflag==data->trackflag){
 
499
                                                curcon->flag |= CONSTRAINT_DISABLE;
 
500
                                                break;
 
501
                                        }
 
502
                                        if (data->lockflag+3==data->trackflag){
 
503
                                                curcon->flag |= CONSTRAINT_DISABLE;
 
504
                                                break;
 
505
                                        }
 
506
                                }
 
507
                                        break;
 
508
                                case CONSTRAINT_TYPE_STRETCHTO:
 
509
                                {
 
510
                                        bStretchToConstraint *data = curcon->data;
 
511
                                        
 
512
                                        if (!exist_object(data->tar)){
 
513
                                                data->tar = NULL;
 
514
                                                curcon->flag |= CONSTRAINT_DISABLE;
 
515
                                                break;
 
516
                                        }
 
517
                                        
 
518
                                        if ( (data->tar == owner) &&
 
519
                                                 (!get_named_bone(get_armature(owner), 
 
520
                                                                                  data->subtarget))) {
 
521
                                                curcon->flag |= CONSTRAINT_DISABLE;
 
522
                                                break;
 
523
                                        }
 
524
                                }
 
525
                                        break;
 
526
                                case CONSTRAINT_TYPE_FOLLOWPATH:
 
527
                                {
 
528
                                        bFollowPathConstraint *data = curcon->data;
 
529
                                        
 
530
                                        if (!exist_object(data->tar)){
 
531
                                                data->tar = NULL;
 
532
                                                curcon->flag |= CONSTRAINT_DISABLE;
 
533
                                                break;
 
534
                                        }
 
535
                                        if (data->tar->type != OB_CURVE){
 
536
                                                data->tar = NULL;
 
537
                                                curcon->flag |= CONSTRAINT_DISABLE;
 
538
                                                break;
 
539
                                        }
 
540
                                        if (data->upflag==data->trackflag){
 
541
                                                curcon->flag |= CONSTRAINT_DISABLE;
 
542
                                                break;
 
543
                                        }
 
544
                                        if (data->upflag+3==data->trackflag){
 
545
                                                curcon->flag |= CONSTRAINT_DISABLE;
 
546
                                                break;
 
547
                                        }
 
548
                                }
 
549
                                        break;
 
550
                        }
 
551
                }
 
552
        }
 
553
}
 
554
 
 
555
static void test_bonelist_constraints (Object *owner, ListBase *list)
 
556
{
 
557
        Bone *bone;
 
558
 
 
559
        for (bone = list->first; bone; bone=bone->next) {
 
560
                
 
561
                test_constraints(owner, bone->name);
 
562
                test_bonelist_constraints (owner, &bone->childbase);
 
563
        }
 
564
}
 
565
 
 
566
void object_test_constraints (Object *owner)
 
567
{
 
568
        test_constraints(owner, "");
 
569
 
 
570
        if(owner->type==OB_ARMATURE) {
 
571
                bArmature *arm;
 
572
                arm = get_armature(owner);
 
573
                if (arm)
 
574
                        test_bonelist_constraints (owner, &arm->bonebase);
 
575
        }
 
576
 
 
577
}
 
578
 
 
579
/* context: active object in posemode, active channel, optional selected channel */
 
580
void add_constraint(int only_IK)
 
581
{
 
582
        Object *ob= OBACT, *obsel=NULL;
 
583
        bPoseChannel *pchanact=NULL, *pchansel=NULL;
 
584
        bConstraint *con=NULL;
 
585
        Base *base;
 
586
        short nr;
 
587
        
 
588
        /* paranoia checks */
 
589
        if(ob==NULL || ob==G.obedit) return;
 
590
        
 
591
        if(ob->pose && (ob->flag & OB_POSEMODE)) {
 
592
        
 
593
                /* find active channel */
 
594
                for(pchanact= ob->pose->chanbase.first; pchanact; pchanact= pchanact->next)
 
595
                        if(pchanact->bone->flag & BONE_ACTIVE) break;
 
596
                if(pchanact==NULL) return;
 
597
        
 
598
                /* find selected bone */
 
599
                for(pchansel= ob->pose->chanbase.first; pchansel; pchansel= pchansel->next) {
 
600
                        if(pchansel!=pchanact)
 
601
                                if(pchansel->bone->flag & BONE_SELECTED) break;
 
602
                }
 
603
        }
 
604
        
 
605
        /* find selected object */
 
606
        for(base= FIRSTBASE; base; base= base->next)
 
607
                if( TESTBASE(base) && base->object!=ob ) 
 
608
                        obsel= base->object;
 
609
        
 
610
        /* the only_IK caller has checked for posemode! */
 
611
        if(only_IK) {
 
612
                for(con= pchanact->constraints.first; con; con= con->next) {
 
613
                        if(con->type==CONSTRAINT_TYPE_KINEMATIC) break;
 
614
                }
 
615
                if(con) {
 
616
                        error("Pose Channel already has IK");
 
617
                        return;
 
618
                }
 
619
                
 
620
                if(pchansel)
 
621
                        nr= pupmenu("Add IK Constraint%t|To Active Bone%x10");
 
622
                else if(obsel)
 
623
                        nr= pupmenu("Add IK Constraint%t|To Active Object%x10");
 
624
                else 
 
625
                        nr= pupmenu("Add IK Constraint%t|To New Empty Object%x10|Without Target%x11");
 
626
        }
 
627
        else {
 
628
                if(pchanact) {
 
629
                        if(pchansel)
 
630
                                nr= pupmenu("Add Constraint to Active Bone%t|Copy Location%x1|Copy Rotation%x2|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7");
 
631
                        else if(obsel && obsel->type==OB_CURVE)
 
632
                                nr= pupmenu("Add Constraint to Active Object%t|Copy Location%x1|Copy Rotation%x2|Track To%x3|Floor%x4|Locked Track%x5|Follow Path%x6|Stretch To%x7");
 
633
                        else if(obsel)
 
634
                                nr= pupmenu("Add Constraint to Active Object%t|Copy Location%x1|Copy Rotation%x2|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7");
 
635
                        else
 
636
                                nr= pupmenu("Add Constraint to New Empty Object%t|Copy Location%x1|Copy Rotation%x2|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7");
 
637
                }
 
638
                else {
 
639
                        if(obsel && obsel->type==OB_CURVE)
 
640
                                nr= pupmenu("Add Constraint to Active Object%t|Copy Location%x1|Copy Rotation%x2|Track To%x3|Floor%x4|Locked Track%x5|Follow Path%x6");
 
641
                        else if(obsel)
 
642
                                nr= pupmenu("Add Constraint to Active Object%t|Copy Location%x1|Copy Rotation%x2|Track To%x3|Floor%x4|Locked Track%x5");
 
643
                        else
 
644
                                nr= pupmenu("Add Constraint to New Empty Object%t|Copy Location%x1|Copy Rotation%x2|Track To%x3|Floor%x4|Locked Track%x5");
 
645
                }
 
646
        }
 
647
        
 
648
        if(nr<1) return;
 
649
        
 
650
        /* handle IK separate */
 
651
        if(nr==10 || nr==11) {
 
652
                
 
653
                /* prevent weird chains... */
 
654
                if(pchansel) {
 
655
                        bPoseChannel *pchan= pchanact;
 
656
                        while(pchan) {
 
657
                                if(pchan==pchansel) break;
 
658
                                pchan= pchan->parent;
 
659
                        }
 
660
                        if(pchan) {
 
661
                                error("IK root cannot be linked to IK tip");
 
662
                                return;
 
663
                        }
 
664
                        pchan= pchansel;
 
665
                        while(pchan) {
 
666
                                if(pchan==pchanact) break;
 
667
                                pchan= pchan->parent;
 
668
                        }
 
669
                        if(pchan) {
 
670
                                error("IK tip cannot be linked to IK root");
 
671
                                return;
 
672
                        }               
 
673
                }
 
674
                
 
675
                con = add_new_constraint(CONSTRAINT_TYPE_KINEMATIC);
 
676
                BLI_addtail(&pchanact->constraints, con);
 
677
                pchanact->constflag |= PCHAN_HAS_IK;    // for draw, but also for detecting while pose solving
 
678
                if(nr==11) pchanact->constflag |= PCHAN_HAS_TARGET;
 
679
        }
 
680
        else {
 
681
                
 
682
                if(nr==1) con = add_new_constraint(CONSTRAINT_TYPE_LOCLIKE);
 
683
                else if(nr==2) con = add_new_constraint(CONSTRAINT_TYPE_ROTLIKE);
 
684
                else if(nr==3) con = add_new_constraint(CONSTRAINT_TYPE_TRACKTO);
 
685
                else if(nr==4) con = add_new_constraint(CONSTRAINT_TYPE_MINMAX);
 
686
                else if(nr==5) con = add_new_constraint(CONSTRAINT_TYPE_LOCKTRACK);
 
687
                else if(nr==6) con = add_new_constraint(CONSTRAINT_TYPE_FOLLOWPATH);
 
688
                else if(nr==7) con = add_new_constraint(CONSTRAINT_TYPE_STRETCHTO);
 
689
                
 
690
                if(con==NULL) return;   /* paranoia */
 
691
                
 
692
                if(pchanact) {
 
693
                        BLI_addtail(&pchanact->constraints, con);
 
694
                        pchanact->constflag |= PCHAN_HAS_CONST; /* for draw */
 
695
                }
 
696
                else {
 
697
                        BLI_addtail(&ob->constraints, con);
 
698
                }
 
699
        }
 
700
        
 
701
        /* set the target */
 
702
        if(pchansel) {
 
703
                set_constraint_target(con, ob, pchansel->name);
 
704
        }
 
705
        else if(obsel) {
 
706
                set_constraint_target(con, obsel, NULL);
 
707
        }
 
708
        else if(nr!=11) {       /* add new empty as target */
 
709
                Base *base= BASACT, *newbase;
 
710
                Object *obt;
 
711
                
 
712
                obt= add_object(OB_EMPTY);
 
713
                /* set layers OK */
 
714
                newbase= BASACT;
 
715
                newbase->lay= base->lay;
 
716
                obt->lay= newbase->lay;
 
717
                
 
718
                /* transform cent to global coords for loc */
 
719
                if(pchanact) {
 
720
                        if(only_IK)
 
721
                                VecMat4MulVecfl(obt->loc, ob->obmat, pchanact->pose_tail);
 
722
                        else
 
723
                                VecMat4MulVecfl(obt->loc, ob->obmat, pchanact->pose_head);
 
724
                }
 
725
                else
 
726
                        VECCOPY(obt->loc, ob->obmat[3]);
 
727
                
 
728
                set_constraint_target(con, obt, NULL);
 
729
                
 
730
                /* restore, add_object sets active */
 
731
                BASACT= base;
 
732
                base->flag |= SELECT;
 
733
        }
 
734
 
 
735
 
 
736
        /* active flag */
 
737
        con->flag |= CONSTRAINT_ACTIVE;
 
738
        for(con= con->prev; con; con= con->prev)
 
739
                con->flag &= ~CONSTRAINT_ACTIVE;
 
740
 
 
741
        DAG_scene_sort(G.scene);                // sort order of objects
 
742
        
 
743
        if(pchanact) {
 
744
                ob->pose->flag |= POSE_RECALC;  // sort pose channels
 
745
                DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);   // and all its relations
 
746
        }
 
747
        else
 
748
                DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);     // and all its relations
 
749
 
 
750
        allqueue (REDRAWVIEW3D, 0);
 
751
        allqueue (REDRAWBUTSOBJECT, 0);
 
752
        allqueue (REDRAWOOPS, 0);
 
753
        
 
754
        if(only_IK)
 
755
                BIF_undo_push("Add IK Constraint");
 
756
        else
 
757
                BIF_undo_push("Add Constraint");
 
758
 
 
759
}
 
760
 
 
761
void ob_clear_constraints(void)
 
762
{
 
763
        Object *ob= OBACT;
 
764
        
 
765
        /* paranoia checks */
 
766
        if(!ob) return;
 
767
        if(ob==G.obedit || (ob->flag & OB_POSEMODE)) return;
 
768
        
 
769
        if(okee("Clear Constraints")==0) return;
 
770
        
 
771
        free_constraints(&ob->constraints);
 
772
        
 
773
        DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);
 
774
        
 
775
        allqueue (REDRAWVIEW3D, 0);
 
776
        allqueue (REDRAWBUTSOBJECT, 0);
 
777
        allqueue (REDRAWOOPS, 0);
 
778
        
 
779
        BIF_undo_push("Clear Constraint(s)");
 
780
        
 
781
}
 
 
b'\\ No newline at end of file'