Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJiri Hnidek <jiri.hnidek@tul.cz>2006-08-20 19:22:56 +0400
committerJiri Hnidek <jiri.hnidek@tul.cz>2006-08-20 19:22:56 +0400
commit2ee42ac01e6f4b154ac68976024af0615f7acb26 (patch)
tree9a2400a99bf7880a2f146c7a89bd2d8c0108374c /source/blender/src/verse_object.c
parentffe630b452f4abb28c105fca2b8eb9fdb6e72370 (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/src/verse_object.c')
-rw-r--r--source/blender/src/verse_object.c587
1 files changed, 587 insertions, 0 deletions
diff --git a/source/blender/src/verse_object.c b/source/blender/src/verse_object.c
new file mode 100644
index 00000000000..3327ac4e5de
--- /dev/null
+++ b/source/blender/src/verse_object.c
@@ -0,0 +1,587 @@
+/**
+ * $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 "mydevice.h"
+
+#include "DNA_object_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_image_types.h"
+#include "DNA_listBase.h"
+
+#include "BLI_dynamiclist.h"
+#include "BLI_blenlib.h"
+#include "BLI_editVert.h"
+#include "BLI_arithb.h"
+
+#include "BIF_verse.h"
+#include "BIF_space.h"
+#include "BIF_editmesh.h"
+#include "BIF_drawimage.h"
+#include "BIF_editmode_undo.h"
+#include "BIF_toolbox.h"
+
+#include "BKE_verse.h"
+#include "BKE_global.h"
+#include "BKE_object.h"
+#include "BKE_utildefines.h"
+#include "BKE_depsgraph.h"
+#include "BKE_image.h"
+#include "BKE_library.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_mesh.h"
+#include "BKE_displist.h"
+
+#include "BDR_editobject.h"
+
+#include "verse.h"
+
+/* button callback function, it test object name and send new name to verse server */
+void test_and_send_idbutton_cb(void *obj, void *ob_name)
+{
+ struct Object *ob = (Object*)obj;
+ char *name= (char*)ob_name;
+
+ test_idbutton(name+2);
+
+ if(ob->vnode) verse_send_node_name_set(((VNode*)ob->vnode)->id, name+2);
+}
+
+/*
+ * duplicate verse object nodes
+ */
+void b_verse_duplicate_object(VerseSession *session, Object *ob, Object *n_ob)
+{
+ struct VNode *obj_vnode;
+
+ if(!session) return;
+
+ if(!(session->flag & VERSE_CONNECTED)) return;
+
+ /* create "my" new object VerseNode */
+ obj_vnode= create_verse_node(session, -1 , V_NT_OBJECT, VN_OWNER_MINE);
+ /* create object data */
+ obj_vnode->data = create_object_data();
+
+ /* set up name of VerseNode */
+ obj_vnode->name = (char*)MEM_mallocN(sizeof(char*)*(strlen(n_ob->id.name)-1), "object node name");
+ obj_vnode->name[0] = '\0';
+ strcat(obj_vnode->name, n_ob->id.name+2);
+
+ /* set up object node transformation */
+ VECCOPY(((VObjectData*)obj_vnode->data)->pos, n_ob->loc);
+ EulToQuat(n_ob->rot, ((VObjectData*)obj_vnode->data)->rot);
+ VECCOPY(((VObjectData*)obj_vnode->data)->scale, n_ob->size);
+
+ /* set up pointers between Object and VerseNode */
+ ((VObjectData*)obj_vnode->data)->object = (void*)n_ob;
+ n_ob->vnode = (void*)obj_vnode;
+
+ /* add node to sending queue */
+ add_item_to_send_queue(&(session->queue), obj_vnode, VERSE_NODE);
+
+ if(ob->type==OB_MESH) {
+ struct Mesh *me;
+ struct VNode *geom_vnode;
+ struct VLink *vlink;
+
+ /* when current mesh already shared at verse server, then only set up link
+ * between object node and geometry node */
+ if(ob->data == n_ob->data) {
+ geom_vnode = (VNode*)((Mesh*)ob->data)->vnode;
+ }
+ else {
+ geom_vnode = create_geom_vnode_from_geom_vnode((VNode*)((Mesh*)ob->data)->vnode);
+ me = (Mesh*)n_ob->data;
+ me->vnode = (void*)geom_vnode;
+ ((VGeomData*)geom_vnode->data)->mesh = (void*)me;
+
+ }
+ /* create new link between VereseNodes */
+ vlink = create_verse_link(session, obj_vnode, geom_vnode, -1, -1, "geometry");
+ /* "send" link to verse server */
+ add_item_to_send_queue(&(((VObjectData*)obj_vnode->data)->queue), vlink, VERSE_LINK);
+ }
+}
+
+/*
+ * temp hack: this function push mesh objects (edit mode only) to verse server
+ */
+void b_verse_push_object(VerseSession *session, Object *ob)
+{
+ struct VNode *obj_vnode;
+
+ if(!session) return;
+
+ if(!(session->flag & VERSE_CONNECTED)) return;
+
+ /* create "my" new object VerseNode */
+ obj_vnode= create_verse_node(session, -1 , V_NT_OBJECT, VN_OWNER_MINE);
+ /* create object data */
+ obj_vnode->data = create_object_data();
+
+ /* set up name of VerseNode */
+ obj_vnode->name = (char*)MEM_mallocN(sizeof(char*)*(strlen(ob->id.name)-1), "object node name");
+ obj_vnode->name[0] = '\0';
+ strcat(obj_vnode->name, ob->id.name+2);
+
+ /* set up object node transformation */
+ VECCOPY(((VObjectData*)obj_vnode->data)->pos, ob->loc);
+ EulToQuat(ob->rot, ((VObjectData*)obj_vnode->data)->rot);
+ VECCOPY(((VObjectData*)obj_vnode->data)->scale, ob->size);
+
+ /* set up pointers between Object and VerseNode */
+ ((VObjectData*)obj_vnode->data)->object = (void*)ob;
+ ob->vnode = (void*)obj_vnode;
+
+ /* add node to sending queue */
+ add_item_to_send_queue(&(session->queue), obj_vnode, VERSE_NODE);
+
+ if(ob->type==OB_MESH) {
+ struct VNode *geom_vnode;
+ struct VLink *vlink;
+
+ if(G.obedit)
+ geom_vnode = create_geom_vnode_data_from_editmesh(session, G.editMesh);
+ else
+ geom_vnode = create_geom_vnode_data_from_mesh(session, get_mesh(ob));
+
+ if(geom_vnode) {
+ /* create new link between VereseNodes */
+ vlink = create_verse_link(session, obj_vnode, geom_vnode, -1, -1, "geometry");
+ /* send link to verse server */
+ add_item_to_send_queue(&(((VObjectData*)obj_vnode->data)->queue), vlink, VERSE_LINK);
+ }
+ }
+}
+
+/*
+ * creates blender object from verse object node and it
+ * will create links between them
+ */
+Object *create_object_from_verse_node(VNode *vnode)
+{
+ struct Object *ob;
+
+ if(vnode->type != V_NT_OBJECT) return NULL;
+
+ /* create new object*/
+ ob = add_object(OB_MESH);
+ /* set up bindings between verse node and blender object */
+ ob->vnode = (void*)vnode;
+ ((VObjectData*)vnode->data)->object = (void*)ob;
+ /* set up flags */
+ ((VObjectData*)vnode->data)->flag |= POS_RECEIVE_READY;
+ ((VObjectData*)vnode->data)->flag |= ROT_RECEIVE_READY;
+ ((VObjectData*)vnode->data)->flag |= SCALE_RECEIVE_READY;
+ /* copy name from verse node to object */
+ if(vnode->name) {
+ char *str;
+ str = (char*)MEM_mallocN(sizeof(char)*(strlen(vnode->name)+3), "temp object name");
+ str[0] = '\0';
+ strcat(str, "OB");
+ strcat(str, vnode->name);
+ strncpy(ob->id.name, str, 23);
+ MEM_freeN(str);
+ }
+ /* subscribe for object transformation */
+ verse_send_o_transform_subscribe(vnode->id, 0);
+
+ return ob;
+}
+
+/*
+ * Create blender object-mesh from verse object node, verse geometry node,
+ */
+void b_verse_pop_node(VNode *vnode)
+{
+ if((!vnode) || (!(vnode->data))) return;
+
+ if(vnode->type==V_NT_OBJECT) {
+ struct VNode *geom_node=NULL;
+ struct VLink *vlink;
+ struct VLayer *vlayer;
+ struct Object *ob;
+ struct Mesh *me;
+
+ if(((VObjectData*)vnode->data)->object) {
+ printf("\tError: already subscribed to object node.\n");
+ return;
+ }
+
+ vlink = ((VObjectData*)vnode->data)->links.lb.first;
+
+ /* try to find geometry node */
+ while(vlink) {
+ if(vlink->target && vlink->target->type==V_NT_GEOMETRY){
+ geom_node = vlink->target;
+ break;
+ }
+ vlink = vlink->next;
+ }
+
+ /* we are not interested now in avatars node, etc. (vnodes without
+ * links at geometry node) */
+ if(!geom_node) return;
+
+ /* subscribe to all verse geometry layer */
+ vlayer = ((VGeomData*)geom_node->data)->layers.lb.first;
+ while(vlayer) {
+ verse_send_g_layer_subscribe(geom_node->id, vlayer->id, 0);
+ vlayer = vlayer->next;
+ }
+
+ ob = create_object_from_verse_node(vnode);
+
+ me = create_mesh_from_geom_node(geom_node);
+
+ /* set up bindings between object and mesh */
+ if(ob && me) ob->data = me;
+ }
+ else if(vnode->type==V_NT_BITMAP) {
+ struct VBitmapData *vbitmap;
+ struct VBitmapLayer *vblayer;
+
+ vbitmap = (VBitmapData*)vnode->data;
+
+ vblayer = vbitmap->layers.lb.first;
+
+ while(vblayer) {
+ if(!(vblayer->flag & VBLAYER_SUBSCRIBED)) {
+ /* 0 means level of subscription (full resolution) */
+ verse_send_b_layer_subscribe(vnode->id, vblayer->id, 0);
+ vblayer->flag |= VBLAYER_SUBSCRIBED;
+ }
+ vblayer = vblayer->next;
+ }
+
+ if(vbitmap->image) {
+ printf("\tError: already subscribed to image node.\n");
+ return;
+ }
+
+ vbitmap->image = (void*)new_image(
+ vbitmap->width,
+ vbitmap->height,
+ vnode->name,
+ 0);
+ ((Image*)vbitmap->image)->vnode = (void*)vnode;
+ sync_blender_image_with_verse_bitmap_node(vnode);
+
+ allqueue(REDRAWIMAGE, 0);
+ allqueue(REDRAWVIEW3D, 0);
+ }
+}
+
+/*
+ * this function will unsubscribe object node from transformation, but it will
+ * keep all tags and links at other nodes ... user could subscribe to this node
+ * again in future
+ */
+void unsubscribe_from_obj_node(VNode *vnode)
+{
+ struct VerseSession *session = vnode->session;
+ struct VLink *vlink;
+
+ if(vnode->type != V_NT_OBJECT) return;
+
+ /* unsubscribe from receiving changes of transformation matrix */
+ if(session->flag & VERSE_CONNECTED)
+ verse_send_o_transform_unsubscribe(vnode->id, 0);
+
+ /* we have to reinitialize object node transformation */
+ ((VObjectData*)vnode->data)->pos[0] = 0.0f;
+ ((VObjectData*)vnode->data)->pos[1] = 0.0f;
+ ((VObjectData*)vnode->data)->pos[2] = 0.0f;
+
+ ((VObjectData*)vnode->data)->rot[0] = 0.0f;
+ ((VObjectData*)vnode->data)->rot[1] = 0.0f;
+ ((VObjectData*)vnode->data)->rot[2] = 0.0f;
+ ((VObjectData*)vnode->data)->rot[3] = 0.0f;
+
+ ((VObjectData*)vnode->data)->scale[0] = 0.0f;
+ ((VObjectData*)vnode->data)->scale[1] = 0.0f;
+ ((VObjectData*)vnode->data)->scale[2] = 0.0f;
+
+ /* clear bindings between object and object node */
+ if(((VObjectData*)vnode->data)->object) {
+ ((Object*)((VObjectData*)vnode->data)->object)->vnode = NULL;
+ ((VObjectData*)vnode->data)->object = NULL;
+ }
+
+ /* unsubscribe from all supported verse nodes */
+ vlink = ((VObjectData*)vnode->data)->links.lb.first;
+ while(vlink) {
+ if(vlink->target->counter==1) {
+ switch(vlink->target->type) {
+ case V_NT_OBJECT:
+ unsubscribe_from_obj_node(vlink->target);
+ break;
+ case V_NT_GEOMETRY:
+ unsubscribe_from_geom_node(vlink->target);
+ break;
+ case V_NT_BITMAP:
+ unsubscribe_from_bitmap_node(vlink->target);
+ break;
+ default:
+ break;
+ }
+ }
+ vlink = vlink->next;
+ }
+}
+
+/*
+ * when blender Object is deleted, then we have to unsubscribe and free all
+ * VerseNode dependent on this object
+ */
+void b_verse_delete_object(Object *object)
+{
+ struct VNode *vnode;
+
+ vnode = (VNode*)object->vnode;
+
+ if(vnode) unsubscribe_from_obj_node(vnode);
+}
+
+/*
+ * "fake" unsubscribing from object node and all child nodes
+ */
+void b_verse_unsubscribe(VNode *vnode)
+{
+ struct VLink *vlink = ((VObjectData*)vnode->data)->links.lb.first;
+ struct Object *ob = (Object*)((VObjectData*)vnode->data)->object;
+
+ if(vnode->type != V_NT_OBJECT) return;
+
+ if(G.obedit && G.obedit->vnode == (void*)vnode)
+ exit_editmode(2);
+
+ /* create mesh data */
+ while(vlink){
+ if(vlink->target->type == V_NT_GEOMETRY) {
+ struct Mesh *me;
+ me = ((VGeomData*)vnode->data)->mesh;
+ create_meshdata_from_geom_node(me, vnode);
+ break;
+ }
+ vlink = vlink->next;
+ }
+
+ /* unsubscribe from object transformation and clear bindings between
+ * verse object node and object */
+ unsubscribe_from_obj_node(vnode);
+
+ /* when geometry node was shared with more object nodes, then make
+ * data single user */
+ if(ob->type == OB_MESH) {
+ struct ID *id = ob->data;
+ if(id && id->us>1 && id->lib==0) {
+ ob->recalc= OB_RECALC_DATA;
+ ob->data = copy_mesh(ob->data);
+ id->us--;
+ id->newid= ob->data;
+ }
+ }
+
+ /* reinitialize object derived mesh */
+ makeDispListMesh(ob);
+
+ DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
+ allqueue(REDRAWVIEW3D, 1);
+
+}
+
+/*
+ * whe VerseLink is created between two nodes, the Object start to point at
+ * coresponding data
+ */
+void post_link_set(VLink *vlink)
+{
+ struct VNode *target, *source;
+ struct Object *ob=NULL;
+ struct Mesh *me=NULL;
+
+ source = vlink->source;
+ target = vlink->target;
+
+ if(source->type==V_NT_OBJECT && target->type==V_NT_GEOMETRY){
+ if(((VObjectData*)source->data)->object)
+ ob = (Object*)((VObjectData*)source->data)->object;
+ if(((VGeomData*)target->data)->mesh)
+ me = (Mesh*)((VGeomData*)target->data)->mesh;
+ if(ob && me && ob->data!=me) {
+ ob->data = me;
+ makeDispListMesh(ob);
+ }
+ }
+
+ allqueue(REDRAWALL, 1);
+}
+
+/*
+ * when VerseLink is deleted, then bindings between Object and data should be removed
+ */
+void post_link_destroy(VLink *vlink)
+{
+ struct VNode *source, *target;
+ struct Object *ob;
+
+ source = vlink->source;
+ target = vlink->target;
+
+ if(source->type==V_NT_OBJECT && target->type==V_NT_GEOMETRY) {
+ if(((VObjectData*)source->data)->object) {
+ ob = (Object*)((VObjectData*)source->data)->object;
+ ob->data=NULL;
+ }
+ }
+
+ allqueue(REDRAWALL, 1);
+}
+
+/*
+ * recalculate transformation matrix of object
+ */
+void post_transform(VNode *vnode)
+{
+ struct VObjectData *obj_data = (VObjectData*)vnode->data;
+ struct Object *ob = (Object*)obj_data->object;
+ float mat_s[4][4];
+ float mat_r[4][4];
+ float mat_p[4][4];
+ float mat[4][4];
+
+ if(!obj_data->object) return;
+
+ Mat4One(mat_s);
+ Mat4One(mat_r);
+ Mat4One(mat_p);
+
+ /* scale */
+ mat_s[0][0] = ob->size[0] = obj_data->scale[0];
+ mat_s[1][1] = ob->size[1] = obj_data->scale[1];
+ mat_s[2][2] = ob->size[2] = obj_data->scale[2];
+
+ /* rotate */
+ QuatToEul(obj_data->rot, ob->rot);
+ QuatToMat4(obj_data->rot, mat_r);
+
+ /* position */
+ mat_p[3][0] = ob->loc[0] = obj_data->pos[0];
+ mat_p[3][1] = ob->loc[1] = obj_data->pos[1];
+ mat_p[3][2] = ob->loc[2] = obj_data->pos[2];
+
+ /* matrix multiplication */
+ Mat4MulMat4(mat, mat_r, mat_p);
+ Mat4MulMat4(ob->obmat, mat_s, mat);
+
+ DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);
+
+ allqueue(REDRAWVIEW3D, 1);
+}
+
+/*
+ * send transformation of Object to verse server
+ */
+void b_verse_send_transformation(Object *ob)
+{
+ struct VNode *vnode= ob->vnode;
+ float quat[4];
+
+ if(!vnode) return;
+
+ /* if last sent position wasn't received yet, then next change of position
+ * can't be send until last send change is received */
+ if( ((VObjectData*)vnode->data)->flag & POS_SEND_READY ) {
+ if((((VObjectData*)vnode->data)->pos[0]!=ob->loc[0]) ||
+ (((VObjectData*)vnode->data)->pos[1]!=ob->loc[1]) ||
+ (((VObjectData*)vnode->data)->pos[2]!=ob->loc[2])) {
+ VECCOPY(((VObjectData*)vnode->data)->pos, ob->loc);
+ send_verse_object_position(vnode);
+ }
+ }
+
+ /* if last sent rotation wasn't received yet, then next change of rotation
+ * can't be send until last send change is received */
+ if( ((VObjectData*)vnode->data)->flag & ROT_SEND_READY ) {
+ EulToQuat(ob->rot, quat);
+
+ if((((VObjectData*)vnode->data)->rot[0] != quat[0]) ||
+ (((VObjectData*)vnode->data)->rot[1] != quat[1]) ||
+ (((VObjectData*)vnode->data)->rot[2] != quat[2]) ||
+ (((VObjectData*)vnode->data)->rot[3] != quat[3])) {
+ QUATCOPY(((VObjectData*)vnode->data)->rot, quat);
+ send_verse_object_rotation(vnode);
+ }
+ }
+
+ /* if last sent object size wasn't received yet, then next change of object size
+ * can't be send until last send change is received */
+ if( ((VObjectData*)vnode->data)->flag & SCALE_SEND_READY ) {
+ if((((VObjectData*)vnode->data)->scale[0]!=ob->size[0]) ||
+ (((VObjectData*)vnode->data)->scale[1]!=ob->size[1]) ||
+ (((VObjectData*)vnode->data)->scale[2]!=ob->size[2])) {
+ VECCOPY(((VObjectData*)vnode->data)->scale, ob->size);
+ send_verse_object_scale(vnode);
+ }
+ }
+
+ verse_callback_update(0);
+}
+
+/*
+ * free constraint between object VerseNode and blender Object
+ */
+void post_object_free_constraint(VNode *vnode)
+{
+ if(((VObjectData*)vnode->data)->object) {
+ /* free pointer at verse derived mesh */
+ struct Object *ob = (Object*)((VObjectData*)vnode->data)->object;
+ if(ob) {
+ if(ob->derivedFinal) {
+ ((DerivedMesh*)ob->derivedFinal)->release((DerivedMesh*)ob->derivedFinal);
+ ob->derivedFinal = NULL;
+ }
+ if(ob->derivedDeform) {
+ ((DerivedMesh*)ob->derivedDeform)->release((DerivedMesh*)ob->derivedDeform);
+ ob->derivedDeform = NULL;
+ }
+ }
+ /* free constraint */
+ ((Object*)((VObjectData*)vnode->data)->object)->vnode = NULL;
+ ((VObjectData*)vnode->data)->object = NULL;
+ }
+}
+
+#endif
+