Fixed all gcc 4 warnings in blenkernel. Found 2 potentially harmful
[blender.git] / source / blender / blenkernel / intern / verse_object_node.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * Contributor(s): Jiri Hnidek.
24  *
25  * ***** END GPL/BL DUAL LICENSE BLOCK *****
26  */
27
28 #ifdef WITH_VERSE
29
30 #include <string.h>
31
32 #include "MEM_guardedalloc.h"
33
34 #include "DNA_listBase.h"
35
36 #include "BLI_dynamiclist.h"
37 #include "BLI_blenlib.h"
38 #include "BLI_arithb.h"
39
40 #include "BIF_verse.h"
41
42 #include "BKE_verse.h"
43
44 #include "verse.h"
45
46 /* function prototypes of static functions */
47
48 /* callback functions */
49 static void cb_o_transform_pos_real32(void *user_data, VNodeID node_id, uint32 time_s, uint32 time_f, const real32 *pos, const real32 *speed, const real32 *accelerate, const real32 *drag_normal, real32 drag);
50 static void cb_o_transform_rot_real32(void *user_data, VNodeID node_id, uint32 time_s, uint32 time_f, const VNQuat32 *rot, const VNQuat32 *speed, const VNQuat32 *accelerate, const VNQuat32 *drag_normal, real32 drag);
51 static void cb_o_transform_scale_real32(void *user_data, VNodeID node_id, real32 scale_x, real32 scale_y, real32 scale_z);
52 static void cb_o_link_set(void *user_data, VNodeID node_id, uint16 link_id, VNodeID link, const char *label, uint32 target_id);
53 static void cb_o_link_destroy(void *user_data, VNodeID node_id,uint16 link_id);
54
55 /* other functions */
56 static void set_target_node_link_pointer(struct VNode *vnode, struct VLink *vlink);
57 static void free_verse_link_data(struct VLink *vlink);
58
59 /*
60  * find noy sent VerseLink in queue
61  */
62 VLink *find_unsent_child_vlink(VerseSession *session, VNode *vnode)
63 {
64         struct VLink *vlink;
65
66         if(vnode->type!=V_NT_OBJECT) return NULL;
67
68         vlink = ((VObjectData*)vnode->data)->queue.first;
69         while(vlink) {
70                 if(vlink->target->id != -1) {
71                         printf("\t vlink found, vnode target id %d\n", vlink->target->id);
72                         return vlink;
73                 }
74                 vlink = vlink->next;
75         }
76         return NULL;
77 }
78
79 /*
80  * find unsent VerseLink "pointing at this VerseNode"
81  */
82 VLink *find_unsent_parent_vlink(VerseSession *session, VNode *vnode)
83 {
84         struct VNode *tmp;
85         struct VLink *vlink;
86
87         tmp = session->nodes.lb.first;
88
89         while(tmp) {
90                 if(tmp->type==V_NT_OBJECT) {
91                         vlink = ((VObjectData*)tmp->data)->queue.first;
92                         while(vlink) {
93                                 if(vlink->target == vnode)
94                                         return vlink;
95                                 vlink = vlink->next;
96                         }
97                 }
98                 tmp = tmp->next;
99         }
100         return NULL;
101 }
102
103 /*
104  * send object position to verse server
105  */
106 void send_verse_object_position(VNode *vnode)
107 {
108         float tmp;
109         
110         ((VObjectData*)vnode->data)->flag &= ~POS_SEND_READY;
111
112         tmp = -((VObjectData*)vnode->data)->pos[1];
113         ((VObjectData*)vnode->data)->pos[1] = ((VObjectData*)vnode->data)->pos[2];
114         ((VObjectData*)vnode->data)->pos[2] = tmp;
115
116         verse_send_o_transform_pos_real32(
117                         vnode->id,      /* node id */
118                         0,              /* time_s ... no interpolation */
119                         0,              /* time_f ... no interpolation */
120                         ((VObjectData*)vnode->data)->pos,
121                         NULL,           /* speed ... no interpolation */
122                         NULL,           /* accelerate  ... no interpolation */
123                         NULL,           /* drag normal ... no interpolation */
124                         0.0);           /* drag ... no interpolation */
125 }
126
127 /*
128  * send object rotation to verse server
129  */
130 void send_verse_object_rotation(VNode *vnode)
131 {
132 /*      float quat[4];
133         float bvec[3], vvec[3];*/
134         VNQuat32 rot;
135
136         rot.x = ((VObjectData*)vnode->data)->rot[0];
137         rot.y = ((VObjectData*)vnode->data)->rot[1];
138         rot.z = ((VObjectData*)vnode->data)->rot[2];
139         rot.w = ((VObjectData*)vnode->data)->rot[3];
140
141 /*      
142         quat[0] = ((VObjectData*)vnode->data)->rot[0];
143         quat[1] = ((VObjectData*)vnode->data)->rot[1];
144         quat[2] = ((VObjectData*)vnode->data)->rot[2];
145         quat[3] = ((VObjectData*)vnode->data)->rot[3];
146         
147         QuatToEul(quat, bvec);
148         vvec[0] = bvec[0];
149         vvec[1] = bvec[1];
150         vvec[2] = bvec[2];
151         EulToQuat(vvec, quat);
152
153         rot.x = quat[0];
154         rot.y = quat[1];
155         rot.z = quat[2];
156         rot.w = quat[3];
157 */
158         
159         ((VObjectData*)vnode->data)->flag &= ~ROT_SEND_READY;
160
161         verse_send_o_transform_rot_real32(
162                         vnode->id,      /* node id */
163                         0,              /* time_s ... no interpolation */
164                         0,              /* time_f ... no interpolation */
165                         &rot,
166                         NULL,           /* speed ... no interpolation */
167                         NULL,           /* accelerate  ... no interpolation */
168                         NULL,           /* drag normal ... no interpolation */
169                         0.0);           /* drag ... no interpolation */
170 }
171
172 /*
173  * send object rotation to verse server 
174  */
175 void send_verse_object_scale(VNode *vnode)
176 {
177         ((VObjectData*)vnode->data)->flag &= ~SCALE_SEND_READY;
178
179         verse_send_o_transform_scale_real32(
180                         vnode->id,
181                         ((VObjectData*)vnode->data)->scale[0],
182                         ((VObjectData*)vnode->data)->scale[2],
183                         ((VObjectData*)vnode->data)->scale[1]);
184 }
185
186 /*
187  * send VerseLink to verse server
188  */
189 void send_verse_link(VLink *vlink)
190 {
191         verse_session_set(vlink->session->vsession);
192
193         verse_send_o_link_set(
194                         vlink->source->id,
195                         vlink->id,
196                         vlink->target->id,
197                         vlink->label,
198                         vlink->target_id);
199 }
200
201 /*
202  * set up pointer at VerseLink of target node (geometry node, material node, etc.)
203  */
204 static void set_target_node_link_pointer(VNode *vnode, VLink *vlink)
205 {
206         switch (vnode->type) {
207                 case V_NT_GEOMETRY:
208                         ((VGeomData*)vnode->data)->vlink = vlink;
209                         break;
210                 default:
211                         break;
212         }
213 }
214
215 /*
216  * free VerseLink and it's label
217  */
218 static void free_verse_link_data(VLink *vlink)
219 {
220         MEM_freeN(vlink->label);
221 }
222
223 /*
224  * create new VerseLink
225  */
226 VLink *create_verse_link(
227                 VerseSession *session,
228                 VNode *source,
229                 VNode *target,
230                 uint16 link_id,
231                 uint32 target_id,
232                 const char *label)
233 {
234         struct VLink *vlink;
235
236         vlink = (VLink*)MEM_mallocN(sizeof(VLink), "VerseLink");
237         vlink->session = session;
238         vlink->source = source;
239         vlink->target = target;
240         vlink->id = link_id;
241         vlink->target_id = target_id;
242
243         set_target_node_link_pointer(target, vlink);
244
245         vlink->label = (char*)MEM_mallocN(sizeof(char)*(strlen(label)+1), "VerseLink label");
246         vlink->label[0] = '\0';
247         strcat(vlink->label, label);
248
249         vlink->flag = 0;
250
251         vlink->post_link_set = post_link_set;
252         vlink->post_link_destroy = post_link_destroy;
253
254         return vlink;
255 }
256
257 /*
258  * free ObjectData (links, links in queue and lables of links)
259  */
260 void free_object_data(VNode *vnode)
261 {
262         struct VerseSession *session = vnode->session;
263         struct VObjectData *obj = (VObjectData*)vnode->data;
264         struct VLink *vlink;
265
266         if(!obj) return;
267
268         /* free all labels of links in dlist */
269         vlink = obj->links.lb.first;
270         while(vlink){
271                 free_verse_link_data(vlink);
272                 vlink = vlink->next;
273         }
274
275         /* free all labels of links waiting in queue */
276         vlink = obj->queue.first;
277         while(vlink){
278                 free_verse_link_data(vlink);
279                 vlink = vlink->next;
280         }
281         /* free dynamic list and sendig queue of links */
282         BLI_dlist_destroy(&(obj->links));
283         BLI_freelistN(&(obj->queue));
284
285         /* free constraint between VerseNode and Object */
286         obj->post_object_free_constraint(vnode);
287
288         /* unsubscribe from receiving changes of transformation matrix */
289         if(session->flag & VERSE_CONNECTED)
290                 verse_send_o_transform_unsubscribe(vnode->id, 0);
291 }
292
293 /*
294  * create new object data
295  */
296 VObjectData *create_object_data(void)
297 {
298         VObjectData *obj;
299
300         obj = (VObjectData*)MEM_mallocN(sizeof(VObjectData), "VerseObjectData");
301         obj->object = NULL;
302         BLI_dlist_init(&(obj->links));
303         obj->queue.first = obj->queue.last = NULL;
304         obj->flag = 0;
305
306         /* transformation matrix */
307         obj->pos[0] = obj->pos[1] = obj->pos[2] = 0.0;
308         obj->rot[0] = obj->rot[1] = obj->rot[2] = 0.0; obj->rot[3] = 1;
309         obj->scale[0] = obj->scale[1] = obj->scale[2] = 1.0;
310
311         /* transformation flags */
312         obj->flag |= POS_SEND_READY;
313         obj->flag |= ROT_SEND_READY;
314         obj->flag |= SCALE_SEND_READY;
315
316         /* set up pointers at post callback functions */
317         obj->post_transform = post_transform;
318         obj->post_object_free_constraint = post_object_free_constraint;
319
320         return obj;
321 }
322
323 /*
324  * callback function: 
325  */
326 static void cb_o_transform_pos_real32(
327                 void *user_data,
328                 VNodeID node_id,
329                 uint32 time_s,
330                 uint32 time_f,
331                 const real32 *pos,
332                 const real32 *speed,
333                 const real32 *accelerate,
334                 const real32 *drag_normal,
335                 real32 drag)
336 {
337         struct VerseSession *session = (VerseSession*)current_verse_session();
338         struct VNode *vnode;
339         float vec[3], dt, tmp;
340
341         if(!session) return;
342
343         vnode = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
344
345         ((VObjectData*)vnode->data)->flag |= POS_SEND_READY;
346
347         /* verse server sends automaticaly some stupid default values ...
348          * we have to ignore these values, when we created this object node */
349         if( (vnode->owner_id==VN_OWNER_MINE) && !(((VObjectData*)vnode->data)->flag & POS_RECEIVE_READY) ) {
350                 ((VObjectData*)vnode->data)->flag |= POS_RECEIVE_READY;
351                 return;
352         }
353
354         dt = time_s + time_f/(0xffff);
355
356         /* we have to flip z and y coordinates, because verse and blender use different axis
357          * orientation */
358         if(pos) {
359                 vec[0] = pos[0];
360                 vec[1] = pos[1];
361                 vec[2] = pos[2];
362         }
363         else {
364                 vec[0] = 0.0f;
365                 vec[1] = 0.0f;
366                 vec[2] = 0.0f;
367         }
368
369         if(speed) {
370                 vec[0] += speed[0]*dt;
371                 vec[1] += speed[1]*dt;
372                 vec[2] += speed[2]*dt;
373         }
374
375         if(accelerate) {
376                 vec[0] += accelerate[0]*dt*dt/2;
377                 vec[1] += accelerate[1]*dt*dt/2;
378                 vec[2] += accelerate[2]*dt*dt/2;
379         }
380
381         /* flip axis (due to verse spec) */
382         tmp = vec[1];
383         vec[1] = -vec[2];
384         vec[2] = tmp;
385
386         if( (((VObjectData*)vnode->data)->pos[0] != vec[0]) ||
387                         (((VObjectData*)vnode->data)->pos[1] != vec[1]) ||
388                         (((VObjectData*)vnode->data)->pos[2] != vec[2]))
389         {
390                 ((VObjectData*)vnode->data)->pos[0] = vec[0];
391                 ((VObjectData*)vnode->data)->pos[1] = vec[1];
392                 ((VObjectData*)vnode->data)->pos[2] = vec[2];
393
394                 ((VObjectData*)vnode->data)->post_transform(vnode);
395         }
396 }
397
398 /*
399  * callback function:
400  */
401 static void cb_o_transform_rot_real32(
402                 void *user_data,
403                 VNodeID node_id,
404                 uint32 time_s,
405                 uint32 time_f,
406                 const VNQuat32 *rot,
407                 const VNQuat32 *speed,
408                 const VNQuat32 *accelerate,
409                 const VNQuat32 *drag_normal,
410                 real32 drag)
411 {
412         struct VerseSession *session = (VerseSession*)current_verse_session();
413         struct VNode *vnode;
414         float quat[4]={0, 0, 0, 0}, dt;
415 /*      float vvec[3], bvec[3];*/
416
417         if(!session) return;
418
419         vnode = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
420
421         ((VObjectData*)vnode->data)->flag |= ROT_SEND_READY;
422         
423         /* verse server sends automaticaly some stupid default values ...
424          * we have to ignore these values, when we created this object node */
425         if( (vnode->owner_id==VN_OWNER_MINE) && !(((VObjectData*)vnode->data)->flag & ROT_RECEIVE_READY) ) {
426                 ((VObjectData*)vnode->data)->flag |= ROT_RECEIVE_READY;
427                 return;
428         }
429
430         dt = time_s + time_f/(0xffff);
431
432         if(rot) {
433                 quat[0] = rot->x;
434                 quat[1] = rot->y;
435                 quat[2] = rot->z;
436                 quat[3] = rot->w;
437         }
438
439         if(speed) {
440                 quat[0] += speed->x*dt;
441                 quat[1] += speed->y*dt;
442                 quat[2] += speed->z*dt;
443                 quat[3] += speed->w*dt;
444         }
445
446         if(accelerate) {
447                 quat[0] += accelerate->x*dt*dt/2;
448                 quat[1] += accelerate->y*dt*dt/2;
449                 quat[2] += accelerate->z*dt*dt/2;
450                 quat[3] += accelerate->w*dt*dt/2;
451         }
452
453 /*      QuatToEul(quat, vvec);
454         bvec[0] = vvec[0];
455         bvec[1] = vvec[1];
456         bvec[2] = vvec[2];
457         EulToQuat(bvec, quat);*/
458         
459         if( (((VObjectData*)vnode->data)->rot[0] != quat[0]) ||
460                         (((VObjectData*)vnode->data)->rot[1] != quat[1]) ||
461                         (((VObjectData*)vnode->data)->rot[2] != quat[2]) ||
462                         (((VObjectData*)vnode->data)->rot[3] != quat[3]))
463         {
464                 ((VObjectData*)vnode->data)->rot[0] = quat[0];
465                 ((VObjectData*)vnode->data)->rot[1] = quat[1];
466                 ((VObjectData*)vnode->data)->rot[2] = quat[2];
467                 ((VObjectData*)vnode->data)->rot[3] = quat[3];
468
469                 ((VObjectData*)vnode->data)->post_transform(vnode);
470         }
471 }
472
473 /*
474  * callback function:
475  */
476 static void cb_o_transform_scale_real32(
477                 void *user_data,
478                 VNodeID node_id,
479                 real32 scale_x,
480                 real32 scale_y,
481                 real32 scale_z)
482 {
483         struct VerseSession *session = (VerseSession*)current_verse_session();
484         struct VNode *vnode;
485         real32 tmp;
486
487         if(!session) return;
488
489         vnode = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
490
491         ((VObjectData*)vnode->data)->flag |= SCALE_SEND_READY;
492         
493         /* verse server sends automaticaly some stupid default values ...
494          * we have to ignore these values, when we created this object node */
495         if( (vnode->owner_id==VN_OWNER_MINE) && !(((VObjectData*)vnode->data)->flag & SCALE_RECEIVE_READY) ) {
496                 ((VObjectData*)vnode->data)->flag |= SCALE_RECEIVE_READY;
497                 return;
498         }
499
500         /* flip axis (verse spec) */
501         tmp = scale_y;
502         scale_y = scale_z;
503         scale_z = tmp;
504
505         /* z and y axis are flipped here too */
506         if( (((VObjectData*)vnode->data)->scale[0] != scale_x) ||
507                         (((VObjectData*)vnode->data)->scale[1] != scale_y) ||
508                         (((VObjectData*)vnode->data)->scale[2] != scale_z))
509         {
510                 ((VObjectData*)vnode->data)->scale[0] = scale_x;
511                 ((VObjectData*)vnode->data)->scale[1] = scale_y;
512                 ((VObjectData*)vnode->data)->scale[2] = scale_z;
513
514                 ((VObjectData*)vnode->data)->post_transform(vnode);
515         }
516 }
517
518 /*
519  * callback function: link between object node and some other node was created
520  */
521 static void cb_o_link_set(
522                 void *user_data,
523                 VNodeID node_id,
524                 uint16 link_id,
525                 VNodeID link,
526                 const char *label,
527                 uint32 target_id)
528 {
529         struct VLink *vlink;
530         struct VNode *source;
531         struct VNode *target;
532
533         struct VerseSession *session = (VerseSession*)current_verse_session();
534
535         if(!session) return;
536
537         source = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
538         target = BLI_dlist_find_link(&(session->nodes), (unsigned int)link);
539
540         if(!(source && target)) return;
541
542         vlink = ((VObjectData*)source->data)->queue.first;
543
544         if(vlink && (vlink->source==source) && (vlink->target==target)) {
545                 /* remove VerseLink from sending queue */
546                 BLI_remlink(&(((VObjectData*)source->data)->queue), vlink);
547                 /* add VerseLink to dynamic list of VerseLinks */
548                 BLI_dlist_add_item_index(&(((VObjectData*)source->data)->links), vlink, (unsigned int)link_id);
549                 /* send next link from sending queue */
550                 if(((VObjectData*)source->data)->queue.first)
551                         send_verse_link(((VObjectData*)source->data)->queue.first);
552                 /* set up VerseLink variables */
553                 vlink->flag = 0;
554                 vlink->id = link_id;
555                 vlink->target_id = target_id;
556         }
557         else {
558                 /* create new VerseLink */
559                 vlink = create_verse_link(session, source, target, link_id, target_id, label);
560                 /* add VerseLink to dynamic list of VerseLinks */
561                 BLI_dlist_add_item_index(&(((VObjectData*)source->data)->links), vlink, (unsigned int)link_id);
562         }
563
564         target->counter++;
565
566         vlink->post_link_set(vlink);
567 }
568
569 /*
570  * callback function: destroy link between two VerseNodes
571  */
572 static void cb_o_link_destroy(
573                 void *user_data,
574                 VNodeID node_id,
575                 uint16 link_id)
576 {
577         struct VerseSession *session = (VerseSession*)current_verse_session();
578         struct VNode *vnode;
579         struct VLink *vlink;
580
581         if(!session) return;
582
583         vnode = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
584
585         vlink = BLI_dlist_find_link(&(((VObjectData*)vnode->data)->links), link_id);
586
587         if(vlink) {
588                 vlink->target->counter--;
589                 free_verse_link_data(vlink);
590                 BLI_dlist_free_item(&(((VObjectData*)vnode->data)->links), link_id);
591         }
592
593         vlink->post_link_destroy(vlink);
594 }
595
596 void set_object_callbacks(void)
597 {
598         /* position of object was changed */
599         verse_callback_set(verse_send_o_transform_pos_real32, cb_o_transform_pos_real32, NULL);
600         /* rotation of object was changed */
601         verse_callback_set(verse_send_o_transform_rot_real32, cb_o_transform_rot_real32, NULL);
602         /* size of object was changed  */
603         verse_callback_set(verse_send_o_transform_scale_real32, cb_o_transform_scale_real32, NULL);
604         /* new link between nodes was created */
605         verse_callback_set(verse_send_o_link_set, cb_o_link_set, NULL);
606         /* link between nodes was destroyed */
607         verse_callback_set(verse_send_o_link_destroy, cb_o_link_destroy, NULL);
608 }
609
610 #endif