diff options
author | Jiri Hnidek <jiri.hnidek@tul.cz> | 2006-08-20 19:22:56 +0400 |
---|---|---|
committer | Jiri Hnidek <jiri.hnidek@tul.cz> | 2006-08-20 19:22:56 +0400 |
commit | 2ee42ac01e6f4b154ac68976024af0615f7acb26 (patch) | |
tree | 9a2400a99bf7880a2f146c7a89bd2d8c0108374c /source/blender/blenkernel/intern/verse_node.c | |
parent | ffe630b452f4abb28c105fca2b8eb9fdb6e72370 (diff) |
Huge commit: VERSE
- All code is in #ifdef ... #endif
- Only make build system is supported and you have to add:
export WITH_VERSE=true
to user-def.mk file
- Blender can share only mesh objects and bitmaps now
- More informations can be found at wiki:
http://mediawiki.blender.org/index.php/BlenderDev/VerseIntegrationToBlender
http://mediawiki.blender.org/index.php/BlenderDev/VerseIntegrationToBlenderUserDoc
I hope, that I didn't forget at anything
Diffstat (limited to 'source/blender/blenkernel/intern/verse_node.c')
-rw-r--r-- | source/blender/blenkernel/intern/verse_node.c | 735 |
1 files changed, 735 insertions, 0 deletions
diff --git a/source/blender/blenkernel/intern/verse_node.c b/source/blender/blenkernel/intern/verse_node.c new file mode 100644 index 00000000000..570d3a2df5c --- /dev/null +++ b/source/blender/blenkernel/intern/verse_node.c @@ -0,0 +1,735 @@ +/** + * $Id$ + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Contributor(s): Jiri Hnidek. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifdef WITH_VERSE + +#include <string.h> + +#include "MEM_guardedalloc.h" + +#include "DNA_listBase.h" + +#include "BLI_dynamiclist.h" +#include "BLI_blenlib.h" + +#include "BIF_verse.h" + +#include "BKE_verse.h" + +#include "verse.h" + +/* function prototypes of static functions */ + /* for tags */ +static void free_verse_tag_data(struct VTag *vtag); +static struct VTag *find_tag_in_queue(struct VTagGroup *vtaggroup, const char *name); +static struct VTag *create_verse_tag(struct VTagGroup *vtaggroup, uint16 tag_id, const char *name, VNTagType type, const VNTag *tag); + /* for verse tag groups */ +static void free_verse_taggroup_data(struct VTagGroup *taggroup); +static struct VTagGroup *find_taggroup_in_queue(struct VNode *vnode, const char *name); +static struct VTagGroup *create_verse_taggroup(VNode *vnode, uint16 group_id, const char *name); + /* for verse nodes */ +static void move_verse_node_to_dlist(struct VerseSession *session, VNodeID vnode_id); + /* function prototypes of node callback functions */ +static void cb_tag_destroy(void *user_data, VNodeID node_id, uint16 group_id, uint16 tag_id); +static void cb_tag_create(void *user_data, VNodeID node_id, uint16 group_id, uint16 tag_id, const char *name, VNTagType type, const VNTag *tag); +static void cb_tag_group_destroy(void *user_data, VNodeID node_id, uint16 group_id); +static void cb_tag_group_create(void *user_data, VNodeID node_id, uint16 group_id, const char *name); +static void cb_node_name_set(void *user_data, VNodeID node_id, const char *name); +static void cb_node_destroy(void *user_data, VNodeID node_id); +static void cb_node_create(void *user_data, VNodeID node_id, uint8 type, VNodeID owner_id); + +/* + * send new tag to verse server + */ +void send_verse_tag(VTag *vtag) +{ + verse_send_tag_create(vtag->vtaggroup->vnode->id, + vtag->vtaggroup->id, + vtag->id, + vtag->name, + vtag->type, + vtag->tag); +} + +/* + * free tag data + */ +static void free_verse_tag_data(VTag *vtag) +{ + /* free name of verse tag */ + MEM_freeN(vtag->name); + /* free value of tag */ + MEM_freeN(vtag->tag); +} + +/* + * try to find tag in sending queue ... if tag will be found, then + * this function will removed tag from queue and will return pointer + * at this tag + */ +static VTag *find_tag_in_queue(VTagGroup *vtaggroup, const char *name) +{ + struct VTag *vtag; + + vtag = vtaggroup->queue.first; + + while(vtag) { + if(strcmp(vtag->name, name)==0) { + BLI_remlink(&(vtaggroup->queue), vtag); + break; + } + vtag = vtag->next; + } + + return vtag; +} + +/* + * create new verse tag + */ +static VTag *create_verse_tag( + VTagGroup *vtaggroup, + uint16 tag_id, + const char *name, + VNTagType type, + const VNTag *tag) +{ + struct VTag *vtag; + + vtag = (VTag*)MEM_mallocN(sizeof(VTag), "VTag"); + + vtag->vtaggroup = vtaggroup; + vtag->id = tag_id; + vtag->name = (char*)MEM_mallocN(sizeof(char)*(strlen(name)+1), "VTag name"); + strcpy(vtag->name, name); + vtag->type = type; + + vtag->tag = (VNTag*)MEM_mallocN(sizeof(VNTag), "VNTag"); + *vtag->tag = *tag; + + vtag->value = NULL; + + return vtag; +} + +/* + * send taggroup to verse server + */ +void send_verse_taggroup(VTagGroup *vtaggroup) +{ + verse_send_tag_group_create( + vtaggroup->vnode->id, + vtaggroup->id, + vtaggroup->name); +} + +/* + * free taggroup data + */ +static void free_verse_taggroup_data(VTagGroup *taggroup) +{ + struct VerseSession *session = taggroup->vnode->session; + struct VTag *vtag; + + vtag = taggroup->tags.lb.first; + + while(vtag) { + free_verse_tag_data(vtag); + vtag = vtag->next; + } + + /* unsubscribe from taggroup */ + if(session->flag & VERSE_CONNECTED) + verse_send_tag_group_unsubscribe(taggroup->vnode->id, taggroup->id); + + BLI_dlist_destroy(&(taggroup->tags)); + MEM_freeN(taggroup->name); +} + +/* + * move taggroup from queue to dynamic list with access array, + * set up taggroup id and return pointer at this taggroup + */ +static VTagGroup *find_taggroup_in_queue(VNode *vnode, const char *name) +{ + struct VTagGroup *vtaggroup; + + vtaggroup = vnode->queue.first; + + while(vtaggroup) { + if(strcmp(vtaggroup->name, name)==0) { + BLI_remlink(&(vnode->queue), vtaggroup); + break; + } + vtaggroup = vtaggroup->next; + } + + return vtaggroup; +} + +/* + * create new verse group of tags + */ +static VTagGroup *create_verse_taggroup(VNode *vnode, uint16 group_id, const char *name) +{ + struct VTagGroup *taggroup; + + taggroup = (VTagGroup*)MEM_mallocN(sizeof(VTagGroup), "VTagGroup"); + + taggroup->vnode = vnode; + taggroup->id = group_id; + taggroup->name = (char*)MEM_mallocN(sizeof(char)*(strlen(name)+1), "VTagGroup name"); + strcpy(taggroup->name, name); + + BLI_dlist_init(&(taggroup->tags)); + taggroup->queue.first = taggroup->queue.last = NULL; + + taggroup->post_tag_change = post_tag_change; + taggroup->post_taggroup_create = post_taggroup_create; + + return taggroup; +} + +/* + * move first VerseNode waiting in sending queue to dynamic list of VerseNodes + * (it usually happens, when "our" VerseNode was received from verse server) + */ +static void move_verse_node_to_dlist(VerseSession *session, VNodeID vnode_id) +{ + VNode *vnode; + + vnode = session->queue.first; + + if(vnode) { + BLI_remlink(&(session->queue), vnode); + BLI_dlist_add_item_index(&(session->nodes), (void*)vnode, vnode_id); + } +} + +/* + * send VerseNode to verse server + */ +void send_verse_node(VNode *vnode) +{ + verse_send_node_create( + vnode->id, + vnode->type, + vnode->session->avatar); +} + +/* + * free Verse Node data + */ +void free_verse_node_data(VNode *vnode) +{ + struct VerseSession *session = vnode->session; + struct VTagGroup *vtaggroup; + + /* free node data (object, geometry, etc.) */ + switch(vnode->type){ + case V_NT_OBJECT: + free_object_data(vnode); + break; + case V_NT_GEOMETRY: + free_geom_data(vnode); + break; + case V_NT_BITMAP: + free_bitmap_node_data(vnode); + break; + default: + break; + } + + /* free all tag groups in dynamic list with access array */ + vtaggroup = vnode->taggroups.lb.first; + while(vtaggroup) { + free_verse_taggroup_data(vtaggroup); + vtaggroup = vtaggroup->next; + } + BLI_dlist_destroy(&(vnode->taggroups)); + + /* free all tag groups still waiting in queue */ + vtaggroup = vnode->queue.first; + while(vtaggroup) { + free_verse_taggroup_data(vtaggroup); + vtaggroup = vtaggroup->next; + } + BLI_freelistN(&(vnode->queue)); + + /* unsubscribe from node */ + if(session->flag & VERSE_CONNECTED) + verse_send_node_unsubscribe(vnode->id); + + /* free node name */ + MEM_freeN(vnode->name); + vnode->name = NULL; + + /* free node data */ + MEM_freeN(vnode->data); + vnode->data = NULL; + +} + +/* + * free VerseNode + */ +void free_verse_node(VNode *vnode) +{ + free_verse_node_data(vnode); + + BLI_dlist_free_item(&(vnode->session->nodes), vnode->id); +} + +/* + * create new Verse Node + */ +VNode* create_verse_node(VerseSession *session, VNodeID node_id, uint8 type, VNodeID owner_id) +{ + struct VNode *vnode; + + vnode = (VNode*)MEM_mallocN(sizeof(VNode), "VerseNode"); + + vnode->session = session; + vnode->id = node_id; + vnode->owner_id = owner_id; + vnode->name = NULL; + vnode->type = type; + + BLI_dlist_init(&(vnode->taggroups)); + vnode->queue.first = vnode->queue.last = NULL; + + vnode->data = NULL; + + vnode->counter = 0; + + vnode->flag = 0; + + vnode->post_node_create = post_node_create; + vnode->post_node_destroy = post_node_destroy; + vnode->post_node_name_set = post_node_name_set; + + return vnode; +} + +/* + * callback function: tag was destroyed + */ +static void cb_tag_destroy( + void *user_data, + VNodeID node_id, + uint16 group_id, + uint16 tag_id) +{ + struct VerseSession *session = (VerseSession*)current_verse_session(); + struct VNode *vnode; + struct VTagGroup *vtaggroup; + struct VTag *vtag; + + if(!session) return; + + vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); + if(!vnode) return; + + /* try to find tag group in list of tag groups */ + vtaggroup = BLI_dlist_find_link(&(vnode->taggroups), group_id); + + if(!vtaggroup) return; + + /* try to find verse tag in dynamic list of tags in tag group */ + vtag = (VTag*)BLI_dlist_find_link(&(vtaggroup->tags), tag_id); + + if(vtag) { + free_verse_tag_data(vtag); + BLI_dlist_free_item(&(vtaggroup->tags), vtag->id); + } +} + +/* + * callback function: new tag was created + */ +static void cb_tag_create( + void *user_data, + VNodeID node_id, + uint16 group_id, + uint16 tag_id, + const char *name, + VNTagType type, + const VNTag *tag) +{ + struct VerseSession *session = (VerseSession*)current_verse_session(); + struct VNode *vnode; + struct VTagGroup *vtaggroup; + struct VTag *vtag; + + if(!session) return; + + vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); + if(!vnode) return; + + /* try to find tag group in list of tag groups */ + vtaggroup = BLI_dlist_find_link(&(vnode->taggroups), group_id); + + if(!vtaggroup) return; + + /* try to find verse tag in dynamic list of tags in tag group */ + vtag = (VTag*)BLI_dlist_find_link(&(vtaggroup->tags), tag_id); + + if(!vtag) { + /* we will try to find vtag in sending queue */ + vtag = find_tag_in_queue(vtaggroup, name); + + /* when we didn't create this tag, then we will have to create one */ + if(!vtag) vtag = create_verse_tag(vtaggroup, tag_id, name, type, tag); + else vtag->id = tag_id; + + /* add tag to the list of tags in tag group */ + BLI_dlist_add_item_index(&(vtaggroup->tags), vtag, tag_id); + + /* post change/create method */ + vtaggroup->post_tag_change(vtag); + } + else { + /* this tag exists, then we will propably change value of this tag */ + if((vtag->type != type) || (strcmp(vtag->name, name)!=0)) { + /* changes of type or name are not allowed and such + * stupid changes will be returned back */ + send_verse_tag(vtag); + } + else { + /* post change/create method */ + vtaggroup->post_tag_change(vtag); + } + } +} + +/* + * callback function: tag group was destroyed + */ +static void cb_tag_group_destroy( + void *user_data, + VNodeID node_id, + uint16 group_id) +{ + struct VerseSession *session = (VerseSession*)current_verse_session(); + struct VNode *vnode; + struct VTagGroup *vtaggroup; + + if(!session) return; + + vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); + if(!vnode) return; + + vtaggroup = BLI_dlist_find_link(&(vnode->taggroups), group_id); + + if(vtaggroup) { + free_verse_taggroup_data(vtaggroup); + BLI_dlist_free_item(&(vnode->taggroups), vtaggroup->id); + } +} + +/* + * callback function: new tag group was created + */ +static void cb_tag_group_create( + void *user_data, + VNodeID node_id, + uint16 group_id, + const char *name) +{ + struct VerseSession *session = (VerseSession*)current_verse_session(); + struct VNode *vnode; + struct VTagGroup *vtaggroup; + + if(!session) return; + + vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); + if(!vnode) return; + + /* name of taggroup has to begin with string "blender:" */ + if(strncmp("blender:", name, 8)) return; + + /* try to find tag group in list of tag groups */ + vtaggroup = BLI_dlist_find_link(&(vnode->taggroups), group_id); + + if(!vtaggroup) { + /* subscribe to tag group (when new tag will be created, then blender will + * receive command about it) */ + verse_send_tag_group_subscribe(vnode->id, group_id); + verse_callback_update(0); + + /* try to find taggroup in waiting queue */ + vtaggroup = find_taggroup_in_queue(vnode, name); + + /* if no taggroup exist, then new has to be created */ + if(!vtaggroup) vtaggroup = create_verse_taggroup(vnode, group_id, name); + else vtaggroup->id = group_id; + + /* add tag group to dynamic list with access array */ + BLI_dlist_add_item_index(&(vnode->taggroups), (void*)vtaggroup, (unsigned int)group_id); + + /* post create method */ + vtaggroup->post_taggroup_create(vtaggroup); + } + else { + /* this taggroup exist and somebody try to change its name */ + if(strcmp(vtaggroup->name, name)!=0) { + /* blender doesn't allow such stupid and dangerous things */ + send_verse_taggroup(vtaggroup); + } + } +} + +/* + * callback function: change name of node + */ +static void cb_node_name_set( + void *user_data, + VNodeID node_id, + const char *name) +{ + struct VerseSession *session = (VerseSession*)current_verse_session(); + struct VNode *vnode; + + if(!session) return; + + vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); + if(vnode && name) { + if(!vnode->name) { + vnode->name = (char*)MEM_mallocN(sizeof(char)*(strlen(name)+1), "VerseNode name"); + } + else if(strlen(name) > strlen(vnode->name)) { + MEM_freeN(vnode->name); + vnode->name = (char*)MEM_mallocN(sizeof(char)*(strlen(name)+1), "VerseNode name"); + } + strcpy(vnode->name, name); + + vnode->post_node_name_set(vnode); + } +} + +/* + * callback function for deleting node + */ +static void cb_node_destroy( + void *user_data, + VNodeID node_id) +{ + struct VerseSession *session = (VerseSession*)current_verse_session(); + struct VNode *vnode; + + if(!session) return; + + vnode = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); + + if(vnode) { + /* remove VerseNode from dynamic list */ + BLI_dlist_rem_item(&(session->nodes), (unsigned int)node_id); + /* do post destroy operations */ + vnode->post_node_destroy(vnode); + /* free verse data */ + free_verse_node_data(vnode); + /* free VerseNode */ + MEM_freeN(vnode); + }; +} + + +/* + * callback function for new created node + */ +static void cb_node_create( + void *user_data, + VNodeID node_id, + uint8 type, + VNodeID owner_id) +{ + struct VerseSession *session = (VerseSession*)current_verse_session(); + struct VNode *vnode; + + if(!session) return; + + /* subscribe to node */ + if((type==V_NT_OBJECT) || (type==V_NT_GEOMETRY) || (type==V_NT_BITMAP)) + verse_send_node_subscribe(node_id); + else + return; + + switch(type){ + case V_NT_OBJECT : + if(owner_id==VN_OWNER_MINE) { + struct VLink *vlink; + /* collect VerseNode from VerseNode queue */ + move_verse_node_to_dlist(session, node_id); + /* send next VerseNode waiting in queue */ + if(session->queue.first) send_verse_node(session->queue.first); + /* get received VerseNode from list of VerseNodes */ + vnode = BLI_dlist_find_link(&(session->nodes), node_id); + /* set up ID */ + vnode->id = node_id; + /* set up flags */ + vnode->flag |= NODE_RECEIVED; + /* find unsent link pointing at this VerseNode */ + vlink = find_unsent_child_vlink(session, vnode); + /* send VerseLink */ + if(vlink) send_verse_link(vlink); + /* send name of object node */ + verse_send_node_name_set(node_id, vnode->name); + /* subscribe to changes of object node transformations */ + verse_send_o_transform_subscribe(node_id, 0); + /* send object transformation matrix */ + send_verse_object_position(vnode); + send_verse_object_rotation(vnode); + send_verse_object_scale(vnode); + } + else { + /* create new VerseNode */ + vnode = create_verse_node(session, node_id, type, owner_id); + /* add VerseNode to list of nodes */ + BLI_dlist_add_item_index(&(session->nodes), (void*)vnode, (unsigned int)node_id); + /* set up flags */ + vnode->flag |= NODE_RECEIVED; + /* create object data */ + vnode->data = create_object_data(); + /* set up avatar's name */ + if(node_id == session->avatar) { + char *client_name; + client_name = verse_client_name(); + verse_send_node_name_set(node_id, client_name); + MEM_freeN(client_name); + } + else if(session->flag & VERSE_AUTOSUBSCRIBE) { + /* subscribe to changes of object node transformations */ + verse_send_o_transform_subscribe(node_id, 0); + } + } + break; + case V_NT_GEOMETRY : + if(owner_id==VN_OWNER_MINE){ + struct VLink *vlink; + struct VLayer *vlayer; + /* collect VerseNode from VerseNode queue */ + move_verse_node_to_dlist(session, node_id); + /* send next VerseNode waiting in queue */ + if(session->queue.first) send_verse_node(session->queue.first); + /* get received VerseNode from list of VerseNodes */ + vnode = BLI_dlist_find_link(&(session->nodes), node_id); + /* set up ID */ + vnode->id = node_id; + /* set up flags */ + vnode->flag |= NODE_RECEIVED; + /* find unsent link pointing at this VerseNode */ + vlink = find_unsent_parent_vlink(session, vnode); + /* send VerseLink */ + if(vlink) send_verse_link(vlink); + /* send name of geometry node */ + verse_send_node_name_set(node_id, vnode->name); + /* send all not sent layer to verse server */ + vlayer = (VLayer*)((VGeomData*)vnode->data)->queue.first; + if(vlayer) { + while(vlayer) { + send_verse_layer(vlayer); + vlayer = vlayer->next; + } + } + else { + /* send two verse layers to verse server */ +/* verse_send_g_layer_create(node_id, 0, "vertex", VN_G_LAYER_VERTEX_XYZ, 0, 0); + verse_send_g_layer_create(node_id, 1, "polygon", VN_G_LAYER_POLYGON_CORNER_UINT32, 0, 0);*/ + } + } + else { + /* create new VerseNode*/ + vnode = create_verse_node(session, node_id, type, owner_id); + /* add VerseNode to dlist of nodes */ + BLI_dlist_add_item_index(&(session->nodes), (void*)vnode, (unsigned int)node_id); + /* set up flags */ + vnode->flag |= NODE_RECEIVED; + /* create geometry data */ + vnode->data = (void*)create_geometry_data(); + } + break; + case V_NT_BITMAP : + if(owner_id==VN_OWNER_MINE) { + /* collect VerseNode from VerseNode queue */ + move_verse_node_to_dlist(session, node_id); + /* send next VerseNode waiting in queue */ + if(session->queue.first) send_verse_node(session->queue.first); + /* get received VerseNode from list of VerseNodes */ + vnode = BLI_dlist_find_link(&(session->nodes), node_id); + /* set up ID */ + vnode->id = node_id; + /* set up flags */ + vnode->flag |= NODE_RECEIVED; + /* send name of object node */ + verse_send_node_name_set(node_id, vnode->name); + /* send dimension of image to verse server */ + verse_send_b_dimensions_set(node_id, + ((VBitmapData*)vnode->data)->width, + ((VBitmapData*)vnode->data)->height, + ((VBitmapData*)vnode->data)->depth); + } + else { + /* create new VerseNode*/ + vnode = create_verse_node(session, node_id, type, owner_id); + /* add VerseNode to dlist of nodes */ + BLI_dlist_add_item_index(&(session->nodes), (void*)vnode, (unsigned int)node_id); + /* set up flags */ + vnode->flag |= NODE_RECEIVED; + /* create bitmap data */ + vnode->data = (void*)create_bitmap_data(); + } + default: + break; + } + + vnode->post_node_create(vnode); +} + +/* + * set up all callbacks for verse nodes + */ +void set_node_callbacks(void) +{ + /* new node created */ + verse_callback_set(verse_send_node_create, cb_node_create, NULL); + /* node was deleted */ + verse_callback_set(verse_send_node_destroy, cb_node_destroy, NULL); + /* name of node was set */ + verse_callback_set(verse_send_node_name_set, cb_node_name_set, NULL); + + /* new tag group was created */ + verse_callback_set(verse_send_tag_group_create, cb_tag_group_create, NULL); + /* tag group was destroy */ + verse_callback_set(verse_send_tag_group_destroy, cb_tag_group_destroy, NULL); + + /* new tag was created */ + verse_callback_set(verse_send_tag_create, cb_tag_create, NULL); + /* tag was destroy */ + verse_callback_set(verse_send_tag_destroy, cb_tag_destroy, NULL); +} + +#endif |