Huge commit: VERSE
authorJiri Hnidek <jiri.hnidek@tul.cz>
Sun, 20 Aug 2006 15:22:56 +0000 (15:22 +0000)
committerJiri Hnidek <jiri.hnidek@tul.cz>
Sun, 20 Aug 2006 15:22:56 +0000 (15:22 +0000)
 - 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

56 files changed:
extern/Makefile
source/Makefile
source/blender/blenkernel/BKE_global.h
source/blender/blenkernel/BKE_verse.h [new file with mode: 0644]
source/blender/blenkernel/intern/DerivedMesh.c
source/blender/blenkernel/intern/Makefile
source/blender/blenkernel/intern/mesh.c
source/blender/blenkernel/intern/object.c
source/blender/blenkernel/intern/verse_bitmap_node.c [new file with mode: 0644]
source/blender/blenkernel/intern/verse_geometry_node.c [new file with mode: 0644]
source/blender/blenkernel/intern/verse_node.c [new file with mode: 0644]
source/blender/blenkernel/intern/verse_object_node.c [new file with mode: 0644]
source/blender/blenkernel/intern/verse_session.c [new file with mode: 0644]
source/blender/blenlib/BLI_blenlib.h
source/blender/blenlib/BLI_dynamiclist.h [new file with mode: 0644]
source/blender/blenlib/BLI_editVert.h
source/blender/blenlib/intern/util.c
source/blender/blenloader/intern/Makefile
source/blender/blenloader/intern/writefile.c
source/blender/include/BIF_outliner.h
source/blender/include/BIF_verse.h [new file with mode: 0644]
source/blender/include/blendef.h
source/blender/include/transform.h
source/blender/makesdna/DNA_ID.h
source/blender/makesdna/DNA_image_types.h
source/blender/makesdna/DNA_mesh_types.h
source/blender/makesdna/DNA_object_types.h
source/blender/src/Makefile
source/blender/src/buttons_editing.c
source/blender/src/drawobject.c
source/blender/src/drawview.c
source/blender/src/edit.c
source/blender/src/editmesh.c
source/blender/src/editmesh_add.c
source/blender/src/editmesh_lib.c
source/blender/src/editmesh_loop.c
source/blender/src/editmesh_mods.c
source/blender/src/editmesh_tools.c
source/blender/src/editobject.c
source/blender/src/editscreen.c
source/blender/src/header_info.c
source/blender/src/header_view3d.c
source/blender/src/meshtools.c
source/blender/src/outliner.c
source/blender/src/space.c
source/blender/src/transform_conversions.c
source/blender/src/transform_generics.c
source/blender/src/usiblender.c
source/blender/src/verse_common.c [new file with mode: 0644]
source/blender/src/verse_image.c [new file with mode: 0644]
source/blender/src/verse_mesh.c [new file with mode: 0644]
source/blender/src/verse_object.c [new file with mode: 0644]
source/creator/creator.c
source/nan_compile.mk
source/nan_definitions.mk
source/nan_link.mk

index 766f7f34d923484da061de3194a3c2fc1a7bd688..fb5570eff4b1b5736d19c5d68e68d00f69a5a8d7 100644 (file)
@@ -48,6 +48,10 @@ ifeq ($(NAN_FFMPEG), $(LCGDIR)/gcc/ffmpeg)
 endif
 endif
 
+ifeq ($(WITH_VERSE), true)
+   DIRS += verse
+endif
+
 ifneq ($(NAN_NO_KETSJI), true)
     DIRS += bullet
 endif
index ec78763506aee09382f91832fd5e8fbd30b079f2..5e4359c5d105d3802c33874a6a49ebe6d05826a7 100644 (file)
@@ -209,6 +209,18 @@ ifeq ($(INTERNATIONAL), true)
     endif
 endif
 
+ifeq ($(WITH_VERSE), true)
+   ifeq ($(OS), windows)
+       ifeq ($(FREE_WINDOWS), true)
+           COMLIB += $(NAN_VERSE)/lib/libverse.a
+       else
+           COMLIB += $(NAN_VERSE)/lib/verse.lib
+       endif
+   else
+       COMLIB += $(NAN_VERSE)/lib/libverse.a
+   endif
+endif
+
 ifeq ($(OS), irix)
     COMLIB += $(NAN_SDL)/lib/libSDL.a
 endif
index e239d4de3c03d400a47f21a1b6ae6f28410cd9e6..8f6aa8c3f54b38226994888338ea84b5f7b7c2a5 100644 (file)
@@ -184,6 +184,11 @@ typedef struct Global {
 
 #define G_RECORDKEYS   (1 << 25)
 
+/*#ifdef WITH_VERSE*/
+#define G_VERSE_CONNECTED  (1 << 26)
+#define G_DRAW_VERSE_DEBUG (1 << 27)
+/*#endif*/
+
 /* G.fileflags */
 
 #define G_AUTOPACK               (1 << 0)
diff --git a/source/blender/blenkernel/BKE_verse.h b/source/blender/blenkernel/BKE_verse.h
new file mode 100644 (file)
index 0000000..00a6bdd
--- /dev/null
@@ -0,0 +1,503 @@
+/**
+ * $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 *****
+ */
+
+/* #define WITH_VERSE */
+
+#ifndef BKE_VERSE_H
+#define BKE_VERSE_H
+
+#include "DNA_listBase.h"
+#include "BLI_dynamiclist.h"
+
+#include "verse.h"
+
+struct VNode;
+
+/*
+ * virtual data type (used only for retype)
+ */
+typedef struct verse_parent {
+       struct verse_parent *next, *prev;
+       VLayerID layer_id;
+       uint32 id;
+} verse_parent;
+
+/*
+ * verse data: 4 float value
+ */
+typedef struct quat_real32_item {
+       struct quat_real32_item *next, *prev;
+       VLayerID layer_id;
+       void *parent;
+       real32 value[4];
+} quat_real32_item;
+
+/*
+ * verse data: 4 uint32 values
+ */
+typedef struct quat_uint32_item {
+       struct quat_uint32_item *next, *prev;
+       VLayerID layer_id;
+       void *parent;
+       uint32 value[4];
+} quat_uint32_item;
+
+/*
+ * verse data: 3 float values
+ */
+typedef struct vec_real32_item {
+       struct vec_real32_item *next, *prev;
+       VLayerID layer_id;
+       void *parent;
+       real32 value[3];
+} vec_real32_item;
+
+/*
+ * verse data: float value (weight)
+ */
+typedef struct real32_item {
+       struct real32_item *next, *prev;
+       VLayerID layer_id;
+       void *parent;
+       real32 value;
+} real32_item;
+
+/*
+ * verse data: uint32 value
+ */
+typedef struct uint32_item {
+       struct uint32_item *next, *prev;
+       VLayerID layer_id;
+       void *parent;
+       uint32 value;
+} uint32_item;
+
+/*
+ * verse data: uint8 value
+ */
+typedef struct uint8_item {
+       struct uint8_item *next, *prev;
+       VLayerID layer_id;
+       void *parent;
+       uint8 value;
+} uint8_item;
+
+/*
+ * verse data: vertex
+ */
+typedef struct VerseVert {
+       struct VerseVert *next, *prev;
+       /* verse data */
+       struct VLayer *vlayer;          /* pointer at VerseLayer */
+       uint32 id;                      /* id of vertex */
+       real32 co[3];                   /* x,y,z-coordinates of vertex */
+       real32 no[3];                   /* normal of vertex */
+       /* blender internals */
+       short flag;                     /* flags: VERT_DELETED, VERT_RECEIVED */
+       void *vertex;                   /* pointer at EditVert or MVert */
+       int counter;                    /* counter of VerseFaces using this VerseVert */
+       union {
+               unsigned int index;     /* counter need during transformation to mesh */
+               struct VerseVert *vvert;
+       } tmp;                          /* pointer at new created verse vert, it is
+                                        * used during duplicating geometry node */     
+       float *cos;                     /* modified coordinates of vertex */
+} VerseVert;
+
+/*
+ * verse data: polygon
+ */
+typedef struct VerseFace {
+       struct VerseFace *next, *prev;
+       /* verse data */
+       struct VLayer *vlayer;          /* pointer at VerseLayer */
+       uint32 id;                      /* id of face */
+       struct VerseVert *vvert0;       /* pointer at 1st VerseVert */
+       struct VerseVert *vvert1;       /* pointer at 2nd VerseVert */
+       struct VerseVert *vvert2;       /* pointer at 3th VerseVert */
+       struct VerseVert *vvert3;       /* pointer at 4th VerseVert */
+       unsigned int v0, v1, v2, v3;    /* indexes of VerseVerts ... needed during receiving */
+       /* blender internals */
+       char flag;                      /* flags: FACE_SEND_READY, FACE_SENT, FACE_RECEIVED, FACE_CHANGED*/
+       short counter;                  /* counter of missed VerseVertexes */
+       void *face;                     /* pointer at EditFace */
+       float no[3];                    /* normal vector */
+} VerseFace;
+
+/*
+ * verse data: layer
+ */
+typedef struct VLayer {
+       struct VLayer *next, *prev;
+       /* verse data*/
+       struct VNode *vnode;            /* pointer at VerseNode */
+       uint16 id;                      /* id of layer */
+       char *name;                     /* name of layer */
+       VNGLayerType type;              /* type of layer (VN_G_LAYER_VERTEX_XYZ, VN_G_LAYER_POLYGON_CORNER_UINT32) */
+       uint32 def_int;                 /* default integer value */
+       real64 def_real;                /* default float value */
+       /* blender internals */
+       char flag;                      /* flags: LAYER_SENT, LAYER_RECEIVED, LAYER_DELETED, LAYER_OBSOLETE */
+       short content;                  /* type of content (VERTEX_LAYER, POLYGON_LAYER) */
+       struct DynamicList dl;          /* vertexes, polygons, etc. */
+       struct ListBase queue;          /* queue of vertexes, polygons, etc. waiting for sending to verse server */
+       struct ListBase orphans;        /* list of versedata (polygons, etc.), that can be added to the DynamicList
+                                        * due to not received VerseVerts */
+       unsigned int counter;           /* counter of sent items */
+       /* client dependent methods */
+       void (*post_layer_create)(struct VLayer *vlayer);
+       void (*post_layer_destroy)(struct VLayer *vlayer);
+} VLayer;
+
+/*
+ * verse data: link
+ */
+typedef struct VLink{
+       struct VLink *next, *prev;
+       /* verse data */
+       struct VerseSession *session;   /* session pointer */
+       struct VNode *source;           /* object VerseNode "pointing" at some other VerseNode */
+       struct VNode *target;           /* VerseNode linked with some object node */
+       unsigned int id;                /* id of VerseLink */
+       unsigned int target_id;         /* some unknow id */
+       char *label;                    /* name/label of VerseLink */
+       /* blender internals */
+       char flag;                      /* flags: LINK_SEND_READY */
+       /* client dependent methods */
+       void (*post_link_set)(struct VLink *vlink);
+       void (*post_link_destroy)(struct VLink *vlink);
+} VLink;
+
+/*
+ * bitmap layer 
+ */
+typedef struct VBitmapLayer {
+       struct VBitmapLayer *next, *prev;
+       /* verse data */
+       struct VNode *vnode;            /* pointer at Verse Node */
+       VLayerID id;                    /* id of layer */
+       char *name;                     /* name of layer */
+       VNBLayerType type;              /* type of layer (bits per channel) 1, 8, 16, 32, 64 */
+       void *data;                     /* dynamic allocated data */
+       /* blender internals */
+       char flag;
+} VBitmapLayer;
+
+/*
+ * data of bitmap node
+ */
+typedef struct VBitmapData {
+       struct DynamicList layers;      /* dynamic list with access array of bitmap layers */
+       struct ListBase queue;          /* queue of layers waiting for receiving from verse server */
+       uint16 width;                   /* width of all verse layers */
+       uint16 height;                  /* height of all verse layers */
+       uint16 depth;                   /* depth of bitmap 1 is 2D bitmap, >1 is 3D bitmap */
+       /* blender internals */
+       uint16 t_width;                 /* = (width/VN_B_TILE_SIZE + 1)*VN_B_TILE_SIZE */
+       uint16 t_height;                /* = (height/VN_B_TILE_SIZE + 1)*VN_B_TILE_SIZE */
+       void *image;                    /* pointer at image */
+       /* client dependent methods */
+       void (*post_bitmap_dimension_set)(struct VNode *vnode);
+       void (*post_bitmap_layer_create)(struct VBitmapLayer *vblayer);
+       void (*post_bitmap_layer_destroy)(struct VBitmapLayer *vblayer);
+       void (*post_bitmap_tile_set)(struct VBitmapLayer *vblayer, unsigned int xs, unsigned int ys);
+}VBitmapData;
+
+/* 
+ * data of geometry node
+ */
+typedef struct VGeomData {
+       struct DynamicList layers;      /* dynamic list with access array of Layers */
+       struct VLink *vlink;            /* pointer at VerseLink connecting object node and geom node */
+       struct ListBase queue;          /* queue of our layers waiting for receiving from verse server */
+       void *mesh;                     /* pointer at Mesh (object node) */
+       void *editmesh;                 /* pointer at EditMesh (edit mode) */
+       /* client dependent methods */
+       void (*post_vertex_create)(struct VerseVert *vvert);
+       void (*post_vertex_set_xyz)(struct VerseVert *vvert);
+       void (*post_vertex_delete)(struct VerseVert *vvert);
+       void (*post_vertex_free_constraint)(struct VerseVert *vvert);
+       void (*post_polygon_create)(struct VerseFace *vface);
+       void (*post_polygon_set_corner)(struct VerseFace *vface);
+       void (*post_polygon_delete)(struct VerseFace *vface);
+       void (*post_polygon_free_constraint)(struct VerseFace *vface);
+       void (*post_geometry_free_constraint)(struct VNode *vnode);
+       void (*post_polygon_set_uint8)(struct VerseFace *vface);
+} VGeomData;
+
+/*
+ * data of object node
+ */
+typedef struct VObjectData {
+       struct DynamicList links;       /* dynamic list with access array of links between other nodes */
+       struct ListBase queue;          /* queue of links waiting for sending and receiving from verse server */
+       float pos[3];                   /* position of object VerseNode */
+       float rot[4];                   /* rotation of object VerseNode stored in quat */
+       float scale[3];                 /* scale of object VerseNode */
+       void *object;                   /* pointer at object */
+       short flag;                     /* flag: POS_RECEIVE_READY, ROT_RECEIVE_READY. SCALE_RECEIVE_READY */
+       /* client dependent methods */
+       void (*post_transform)(struct VNode *vnode);
+       void (*post_object_free_constraint)(struct VNode *vnode);
+} VObjectData;
+
+/*
+ * Verse Tag
+ */
+typedef struct VTag {
+       struct VTag *next, *prev;
+       /* verse data*/
+       struct VTagGroup *vtaggroup;    /* pointer at Verse Tag Group */
+       uint16 id;                      /* id of this tag */
+       char *name;                     /* name of this tag*/
+       VNTagType type;                 /* type: VN_TAG_BOOLEAN, VN_TAG_UINT32, VN_TAG_REAL64, VN_TAG_REAL64_VEC3,
+                                          VN_TAG_LINK, VN_TAG_ANIMATION, VN_TAG_BLOB */
+       VNTag *tag;                     /* pointer at value (enum: vboolean, vuint32, vreal64, vstring,
+                                          vreal64_vec3, vlink, vanimation, vblob)*/
+       /* blender internals */
+       void *value;                    /* pointer at blender value */
+} VTag;
+
+/*
+ * Verse Tag Group (verse tags are grouped in tag groups)
+ */
+typedef struct VTagGroup {
+       struct VTagGroup *next, *prev;
+       /* verse data*/
+       struct VNode *vnode;            /* pointer at Verse Node */
+       uint16 id;                      /* id of this tag group */
+       char *name;                     /* name of this tag group */
+       /* blender internals */
+       struct DynamicList tags;        /* dynamic list with access array containing tags */
+       struct ListBase queue;          /* list of tags waiting for receiving from verse server */
+       /* client dependent methods */
+       void (*post_tag_change)(struct VTag *vatg);
+       void (*post_taggroup_create)(struct VTagGroup *vtaggroup);
+} VTagGroup;
+
+/*
+ * Verse Node
+ */
+typedef struct VNode {
+       struct VNode *next, *prev;
+       /* verse data*/
+       struct VerseSession *session;   /* session pointer */
+       VNodeID id;                     /* node id */
+       VNodeID owner_id;               /* owner's id of this node */
+       char *name;                     /* name of this node */
+       uint32 type;                    /* type of node (V_NT_OBJECT, V_NT_GEOMETRY, V_NT_BITMAP) */
+       /* blender internals */
+       char flag;                      /* flags: NODE_SENT, NODE_RECEIVED, NODE_DELTED, NODE_OBSOLETE */
+       struct DynamicList taggroups;   /* dynamic list with access array of taggroups */
+       struct ListBase queue;          /* list of taggroups waiting for receiving from verse server */
+       void *data;                     /* generic pointer at some data (VObjectData, VGeomData, ...) */
+       int counter;                    /* counter of verse link pointing at this vnode (vlink->target) */
+       /* client dependent methods */
+       void (*post_node_create)(struct VNode *vnode);  
+       void (*post_node_destroy)(struct VNode *vnode);
+       void (*post_node_name_set)(struct VNode *vnode);
+} VNode;
+
+/*
+ * Verse Session: verse client can be connected to several verse servers
+ * it is neccessary to store some information about each session
+ */
+typedef struct VerseSession {
+       struct VerseSession *next, *prev;
+       /* verse data */
+       VSession *vsession;             /* pointer at VSeesion (verse.h) */
+       uint32 avatar;                  /* id of avatar */
+       char *address;                  /* string containg IP/domain name of verse server and number of port */
+       void *connection;               /* no clue */
+       uint8 *host_id;                 /* no clue */
+       /* blender internals */
+       short flag;                     /* flag: VERSE_CONNECTING, VERSE_CONNECTED */
+       DynamicList nodes;              /* list of verse nodes */
+       ListBase queue;                 /* list of nodes waiting for sending to verse server */
+       unsigned int counter;           /* count of events, when connection wasn't accepted */
+       /* client dependent methods */
+       void (*post_connect_accept)(struct VerseSession *session);
+       void (*post_connect_terminated)(struct VerseSession *session);
+       void (*post_connect_update)(struct VerseSession *session);
+} VerseSession;
+
+/*
+ * list of post callback functions
+ */
+typedef struct PostCallbackFunction {
+       void (*function)(void *arg);
+       void *param;
+} PostCallbackFunction;
+
+/* VerseSession->flag */
+#define VERSE_CONNECTING       1
+#define VERSE_CONNECTED                2
+#define VERSE_AUTOSUBSCRIBE    4
+
+/* max VerseSession->counter value */
+#define MAX_UNCONNECTED_EVENTS 100
+
+/* VNode flags */
+#define NODE_SENT              1
+#define NODE_RECEIVED          2
+#define NODE_DELTED            4
+#define NODE_OBSOLETE          8
+
+/* VLayer flags */
+#define LAYER_SENT             1
+#define LAYER_RECEIVED         2
+#define LAYER_DELETED          4
+#define LAYER_OBSOLETE         8
+
+/* VLink->flag */
+#define LINK_SEND_READY                1
+
+/* VObjectData->flag */
+#define POS_RECEIVE_READY      1
+#define ROT_RECEIVE_READY      2
+#define SCALE_RECEIVE_READY    4
+#define POS_SEND_READY         8
+#define ROT_SEND_READY         16
+#define SCALE_SEND_READY       32
+
+/* VLayer->content */
+#define VERTEX_LAYER           0
+#define POLYGON_LAYER          1
+
+/* VerseVert->flag */
+#define VERT_DELETED           1       /* vertex delete command was received from verse server */
+#define VERT_RECEIVED          2       /* VerseVert was received from verse server (is not in sending queue) */
+#define VERT_LOCKED            4       /* VerseVert is ready to send local position to verse server */
+#define VERT_POS_OBSOLETE      8       /* position of vertex was changed during sending to verse server */
+#define VERT_OBSOLETE          16      /* vertex delete command was sent to verse server; it means, that
+                                        * no information related to this vertex shoudln't be sent to verse
+                                        * until verse vertex is completely deleted ... then this vertex id
+                                        * can be reused again for new vertex */
+
+/* VerseFace->flag */
+#define FACE_SEND_READY                1       /* VerseFace is ready for sending to verse server */
+#define FACE_RECEIVED          2       /* VerseFace was received from verse server */
+#define FACE_SENT              4       /* VerseFace was sent to verse server and we expect receiving from verse server */
+#define FACE_DELETED           8       /* delete command was sent to verse server */
+#define FACE_CHANGED           16      /* VerseFace was only changed not created */
+#define FACE_OBSOLETE          32      /* VerseFace was changed during sending to verse server */
+
+/* Queue type */
+#define VERSE_NODE             1
+#define VERSE_LINK             2
+#define VERSE_LAYER            3
+#define VERSE_VERT             4
+#define VERSE_FACE             5
+
+#define VERSE_TAG              6
+#define VERSE_TAG_GROUP                7
+
+#define VERSE_VERT_UINT32      8
+#define VERSE_VERT_REAL32      9
+#define VERSE_VERT_VEC_REAL32  10
+
+#define VERSE_FACE_UINT8       11
+#define VERSE_FACE_UINT32      12
+#define VERSE_FACE_REAL32      13
+#define VERSE_FACE_QUAT_UINT32 14
+#define VERSE_FACE_QUAT_REAL32 15
+
+/* Verse Bitmap Layer flags */
+#define VBLAYER_SUBSCRIBED     1
+
+/* function prototypes */
+
+/* functions from verse_session.c */
+void set_verse_session_callbacks(void);
+struct VerseSession *versesession_from_vsession(VSession *vsession);
+struct VerseSession *current_verse_session(void);
+struct VerseSession *create_verse_session(const char *name, const char *pass, const char *address, uint8 *expected_key);
+void free_verse_session(struct VerseSession *session);
+void b_verse_update(void);
+void b_verse_connect(char *address);
+void end_verse_session(struct VerseSession *session, char free);
+void end_all_verse_sessions(void);
+
+/* functions from verse_node.c */
+void send_verse_tag(struct VTag *vtag);
+void send_verse_taggroup(struct VTagGroup *vtaggroup);
+void send_verse_node(struct VNode *vnode);
+void free_verse_node_data(struct VNode *vnode);
+void free_verse_node(struct VNode *vnode);
+struct VNode* create_verse_node(VerseSession *session, VNodeID node_id, uint8 type, VNodeID owner_id);
+void set_node_callbacks(void);
+
+/* functions from verse_object_node.c */
+struct VLink *find_unsent_parent_vlink(struct VerseSession *session, struct VNode *vnode);
+struct VLink *find_unsent_child_vlink(struct VerseSession *session, struct VNode *vnode);
+struct VLink *create_verse_link(VerseSession *session, struct VNode *source, struct VNode *target, uint16 link_id, uint32 target_id, const char *label);
+void send_verse_object_position(struct VNode *vnode);
+void send_verse_object_rotation(struct VNode *vnode);
+void send_verse_object_scale(struct VNode *vnode);
+void send_verse_link(struct VLink *vlink);
+
+void free_object_data(struct VNode *vnode);
+void set_object_callbacks(void);
+struct VObjectData *create_object_data(void);
+
+/* functions from verse_geometry_node.c */
+struct VerseFace* create_verse_face(struct VLayer *vlayer, uint32 polygon_id, uint32 v0, uint32 v1, uint32 v2, uint32 v3);
+struct VerseVert* create_verse_vertex(struct VLayer *vlayer, uint32 vertex_id, real32 x, real32 y, real32 z);
+struct VLayer *create_verse_layer(struct VNode *vnode, VLayerID layer_id, const char *name, VNGLayerType type, uint32 def_integer, real64 def_real);
+struct VGeomData *create_geometry_data(void);
+
+void send_verse_layer(struct VLayer *vlayer);
+
+void send_verse_face_corner_quat_real32(struct quat_real32_item *item, short type);
+void send_verse_face_corner_quat_uint32(struct quat_uint32_item *item, short type);
+void send_verse_face_real32(struct real32_item *item, short type);
+void send_verse_face_uint32(struct uint32_item *item, short type);
+void send_verse_face_uint8(struct uint8_item *item, short type);
+
+void send_verse_vert_vec_real32(struct vec_real32_item *item, short type);
+void send_verse_vert_real32(struct real32_item *item, short type);
+void send_verse_vert_uint32(struct uint32_item *item, short type);
+
+void send_verse_vertex_delete(struct VerseVert *vvert);
+void send_verse_vertex(struct VerseVert *vvert);
+void send_verse_face_delete(struct VerseFace *vface);
+
+void destroy_geometry(struct VNode *vnode);
+
+struct VLayer* find_verse_layer_type(struct VGeomData *geom, short content);
+void add_item_to_send_queue(struct ListBase *lb, void *item, short type);
+void free_geom_data(struct VNode *vnode);
+void set_geometry_callbacks(void);
+
+/* functions prototypes from verse_bitmap.c */
+void set_bitmap_callbacks(void);
+void free_bitmap_layer_data(struct VBitmapLayer *vblayer);
+struct VBitmapLayer *create_bitmap_layer(struct VNode *vnode, VLayerID layer_id, const char *name, VNBLayerType type);
+void free_bitmap_node_data(struct VNode *vnode);
+struct VBitmapData *create_bitmap_data(void);
+
+#endif
index 063185f456a8927f56219cf0b4818ffafd746b58..f0c1ef7f890009fa38fb99aa53a9bc1e18696591 100644 (file)
 #include "BKE_modifier.h"
 #include "BKE_key.h"
 
+#ifdef WITH_VERSE
+#include "BKE_verse.h"
+#endif
+
 #include "BIF_gl.h"
 #include "BIF_glutil.h"
 
@@ -1490,6 +1494,454 @@ DerivedMesh *derivedmesh_from_displistmesh(DispListMesh *dlm, float (*vertexCos)
        return (DerivedMesh*) ssdm;
 }
 
+#ifdef WITH_VERSE
+
+/* verse derived mesh */
+typedef struct {
+       struct DerivedMesh dm;
+       struct VNode *vnode;
+       struct VLayer *vertex_layer;
+       struct VLayer *polygon_layer;
+       float (*verts)[3];
+} VDerivedMesh;
+
+/* this function set up border points of verse mesh bounding box */
+static void vDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3])
+{
+       VDerivedMesh *vdm = (VDerivedMesh*)dm;
+       struct VerseVert *vvert;
+
+       if(!vdm->vertex_layer) return;
+
+       vvert = (VerseVert*)vdm->vertex_layer->dl.lb.first;
+
+       if(vdm->vertex_layer->dl.da.count > 0) {
+               while(vvert) {
+                       DO_MINMAX(vdm->verts ? vvert->cos : vvert->co, min_r, max_r);
+                       vvert = vvert->next;
+               }
+       }
+       else {
+               min_r[0] = min_r[1] = min_r[2] = max_r[0] = max_r[1] = max_r[2] = 0.0;
+       }
+}
+
+/* this function return number of vertexes in vertex layer */
+static int vDM_getNumVerts(DerivedMesh *dm)
+{
+       VDerivedMesh *vdm = (VDerivedMesh*)dm;
+
+       if(!vdm->vertex_layer) return 0;
+       else return vdm->vertex_layer->dl.da.count;
+}
+
+/* this function returns number of polygons in polygon layer */
+static int vDM_getNumFaces(DerivedMesh *dm)
+{
+       VDerivedMesh *vdm = (VDerivedMesh*)dm;
+
+       if(!vdm->polygon_layer) return 0;
+       else return vdm->polygon_layer->dl.da.count;
+}
+
+/* create diplist mesh from verse mesh */
+static DispListMesh* vDM_convertToDispListMesh(DerivedMesh *dm, int allowShared)
+{
+       VDerivedMesh *vdm = (VDerivedMesh*)dm;
+       DispListMesh *dlm = MEM_callocN(sizeof(*dlm), "dlm");
+       struct VerseVert *vvert;
+       struct VerseFace *vface;
+       struct MVert *mvert=NULL;
+       struct MFace *mface=NULL;
+       float *norms;
+       unsigned int i;
+
+       if(!vdm->vertex_layer || !vdm->polygon_layer) {
+               dlm->totvert = 0;
+               dlm->totedge = 0;
+               dlm->totface = 0;
+               dlm->dontFreeVerts = dlm->dontFreeOther = dlm->dontFreeNors = 0;
+
+               return dlm;
+       };
+       
+       /* number of vertexes, edges and faces */
+       dlm->totvert = vdm->vertex_layer->dl.da.count;
+       dlm->totedge = 0;
+       dlm->totface = vdm->polygon_layer->dl.da.count;
+
+       /* create dynamic array of mverts */
+       mvert = (MVert*)MEM_mallocN(sizeof(MVert)*dlm->totvert, "dlm verts");
+       dlm->mvert = mvert;
+       vvert = (VerseVert*)vdm->vertex_layer->dl.lb.first;
+       i = 0;
+       while(vvert) {
+               VECCOPY(mvert->co, vdm->verts ? vvert->cos : vvert->co);
+               VECCOPY(mvert->no, vvert->no);
+               mvert->mat_nr = 0;
+               mvert->flag = 0;
+
+               vvert->tmp.index = i++;
+               mvert++;
+               vvert = vvert->next;
+       }
+
+       /* verse doesn't support edges */
+       dlm->medge = NULL;
+
+       /* create dynamic array of faces */
+       mface = (MFace*)MEM_mallocN(sizeof(MFace)*dlm->totface, "dlm faces");
+       dlm->mface = mface;
+       vface = (VerseFace*)vdm->polygon_layer->dl.lb.first;
+       i = 0;
+       while(vface) {
+               mface->v1 = vface->vvert0->tmp.index;
+               mface->v2 = vface->vvert1->tmp.index;
+               mface->v3 = vface->vvert2->tmp.index;
+               if(vface->vvert3) mface->v4 = vface->vvert3->tmp.index;
+               else mface->v4 = 0;
+
+               mface->pad = 0;
+               mface->mat_nr = 0;
+               mface->flag = 0;
+               mface->edcode = 0;
+
+               test_index_face(mface, NULL, NULL, vface->vvert3?4:3);
+
+               mface++;
+               vface = vface->next;
+       }
+
+       /* textures and verex colors aren't supported yet */
+       dlm->tface = NULL;
+       dlm->mcol = NULL;
+
+       /* faces normals */
+       norms = (float*)MEM_mallocN(sizeof(float)*3*dlm->totface, "dlm norms");
+       dlm->nors = norms;
+
+       vface = (VerseFace*)vdm->polygon_layer->dl.lb.first;
+       while(vface){
+               VECCOPY(norms, vface->no);
+               norms += 3;
+               vface = vface->next;
+       }
+
+       /* free everything, nothing is shared */
+       dlm->dontFreeVerts = dlm->dontFreeOther = dlm->dontFreeNors = 0;
+
+       return dlm;
+}
+
+/* return coordination of vertex with index ... I suppose, that it will
+ * be very hard to do, becuase there can be holes in access array */
+static void vDM_getVertCo(DerivedMesh *dm, int index, float co_r[3])
+{
+       VDerivedMesh *vdm = (VDerivedMesh*)dm;
+       struct VerseVert *vvert = NULL;
+
+       if(!vdm->vertex_layer) return;
+
+       vvert = BLI_dlist_find_link(&(vdm->vertex_layer->dl), index);
+       if(vvert) {
+               VECCOPY(co_r, vdm->verts ? vvert->cos : vvert->co);
+       }
+       else {
+               co_r[0] = co_r[1] = co_r[2] = 0.0;
+       }
+}
+
+/* return array of vertex coordiantions */
+static void vDM_getVertCos(DerivedMesh *dm, float (*cos_r)[3])
+{
+       VDerivedMesh *vdm = (VDerivedMesh*)dm;
+       struct VerseVert *vvert;
+       int i = 0;
+
+       if(!vdm->vertex_layer) return;
+
+       vvert = vdm->vertex_layer->dl.lb.first;
+       while(vvert) {
+               VECCOPY(cos_r[i], vdm->verts ? vvert->cos : vvert->co);
+               i++;
+               vvert = vvert->next;
+       }
+}
+
+/* return normal of vertex with index ... again, it will be hard to
+ * implemente, because access array */
+static void vDM_getVertNo(DerivedMesh *dm, int index, float no_r[3])
+{
+       VDerivedMesh *vdm = (VDerivedMesh*)dm;
+       struct VerseVert *vvert = NULL;
+
+       if(!vdm->vertex_layer) return;
+
+       vvert = BLI_dlist_find_link(&(vdm->vertex_layer->dl), index);
+       if(vvert) {
+               VECCOPY(no_r, vvert->no);
+       }
+       else {
+               no_r[0] = no_r[1] = no_r[2] = 0.0;
+       }
+}
+
+/* draw all VerseVertexes */
+static void vDM_drawVerts(DerivedMesh *dm)
+{
+       VDerivedMesh *vdm = (VDerivedMesh*)dm;
+       struct VerseVert *vvert;
+
+       if(!vdm->vertex_layer) return;
+
+       vvert = vdm->vertex_layer->dl.lb.first;
+
+       bglBegin(GL_POINTS);
+       while(vvert) {
+               bglVertex3fv(vdm->verts ? vvert->cos : vvert->co);
+               vvert = vvert->next;
+       }
+       bglEnd();
+}
+
+/* draw all edges of VerseFaces ... it isn't optimal, because verse
+ * specification doesn't support edges :-( ... bother eskil ;-)
+ * ... some edges (most of edges) are drawn twice */
+static void vDM_drawEdges(DerivedMesh *dm, int drawLooseEdges)
+{
+       VDerivedMesh *vdm = (VDerivedMesh*)dm;
+       struct VerseFace *vface;
+
+       if(!vdm->polygon_layer) return;
+
+       vface = vdm->polygon_layer->dl.lb.first;
+
+       while(vface) {
+               glBegin(GL_LINE_LOOP);
+               glVertex3fv(vdm->verts ? vface->vvert0->cos : vface->vvert0->co);
+               glVertex3fv(vdm->verts ? vface->vvert1->cos : vface->vvert1->co);
+               glVertex3fv(vdm->verts ? vface->vvert2->cos : vface->vvert2->co);
+               if(vface->vvert3) glVertex3fv(vdm->verts ? vface->vvert3->cos : vface->vvert3->co);
+               glEnd();
+
+               vface = vface->next;
+       }
+}
+
+/* verse spec doesn't support edges ... loose edges can't exist */
+void vDM_drawLooseEdges(DerivedMesh *dm)
+{
+}
+
+/* draw uv edges, not supported yet */
+static void vDM_drawUVEdges(DerivedMesh *dm)
+{
+}
+
+/* draw all VerseFaces */
+static void vDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int))
+{
+       VDerivedMesh *vdm = (VDerivedMesh*)dm;
+       struct VerseFace *vface;
+
+       if(!vdm->polygon_layer) return;
+
+       vface = vdm->polygon_layer->dl.lb.first;
+
+       while(vface) {
+/*             if((vface->smooth) && (vface->smooth->value)){
+                       glShadeModel(GL_SMOOTH);
+                       glBegin(vface->vvert3?GL_QUADS:GL_TRIANGLES);
+                       glNormal3fv(vface->vvert0->no);
+                       glVertex3fv(vdm->verts ? vface->vvert0->cos : vface->vvert0->co);
+                       glNormal3fv(vface->vvert1->no);
+                       glVertex3fv(vdm->verts ? vface->vvert1->cos : vface->vvert1->co);
+                       glNormal3fv(vface->vvert2->no);
+                       glVertex3fv(vdm->verts ? vface->vvert2->cos : vface->vvert2->co);
+                       if(vface->vvert3){
+                               glNormal3fv(vface->vvert3->no);
+                               glVertex3fv(vdm->verts ? vface->vvert3->cos : vface->vvert3->co);
+                       }
+                       glEnd();
+               }
+               else { */
+                       glShadeModel(GL_FLAT);
+                       glBegin(vface->vvert3?GL_QUADS:GL_TRIANGLES);
+                       glNormal3fv(vface->no);
+                       glVertex3fv(vdm->verts ? vface->vvert0->cos : vface->vvert0->co);
+                       glVertex3fv(vdm->verts ? vface->vvert1->cos : vface->vvert1->co);
+                       glVertex3fv(vdm->verts ? vface->vvert2->cos : vface->vvert2->co);
+                       if(vface->vvert3)
+                               glVertex3fv(vdm->verts ? vface->vvert3->cos : vface->vvert3->co);
+                       glEnd();
+/*             } */
+
+               vface = vface->next;
+       }
+       glShadeModel(GL_FLAT);
+}
+
+/* this function should draw mesh with colored faces (weight paint, vertex
+ * colors, etc.), but it isn't supported yet */
+static void vDM_drawFacesColored(DerivedMesh *dm, int useTwoSided, unsigned char *col1, unsigned char *col2)
+{
+       VDerivedMesh *vdm = (VDerivedMesh*)dm;
+       struct VerseFace *vface;
+
+       if(!vdm->polygon_layer) return;
+
+       vface = vdm->polygon_layer->dl.lb.first;
+
+       while(vface) {
+               glBegin(vface->vvert3?GL_QUADS:GL_TRIANGLES);
+               glVertex3fv(vdm->verts ? vface->vvert0->cos : vface->vvert0->co);
+               glVertex3fv(vdm->verts ? vface->vvert1->cos : vface->vvert1->co);
+               glVertex3fv(vdm->verts ? vface->vvert2->cos : vface->vvert2->co);
+               if(vface->vvert3)
+                       glVertex3fv(vdm->verts ? vface->vvert3->cos : vface->vvert3->co);
+               glEnd();
+
+               vface = vface->next;
+       }
+}
+
+/**/
+static void vDM_foreachMappedVert(
+               DerivedMesh *dm,
+               void (*func)(void *userData, int index, float *co, float *no_f, short *no_s),
+               void *userData)
+{
+}
+
+/**/
+static void vDM_foreachMappedEdge(
+               DerivedMesh *dm,
+               void (*func)(void *userData, int index, float *v0co, float *v1co),
+               void *userData)
+{
+}
+
+/**/
+static void vDM_foreachMappedFaceCenter(
+               DerivedMesh *dm,
+               void (*func)(void *userData, int index, float *cent, float *no),
+               void *userData)
+{
+}
+
+/**/
+static void vDM_drawMappedFacesTex(
+               DerivedMesh *dm,
+               int (*setDrawOptions)(void *userData, int index, int matnr),
+               void *userData)
+{
+}
+
+/**/
+static void vDM_drawMappedFaces(
+               DerivedMesh *dm,
+               int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r),
+               void *userData,
+               int useColors)
+{
+}
+
+/**/
+static void vDM_drawMappedEdges(
+               DerivedMesh *dm,
+               int (*setDrawOptions)(void *userData, int index),
+               void *userData)
+{
+}
+
+/**/
+static void vDM_drawMappedEdgesInterp(
+               DerivedMesh *dm, 
+               int (*setDrawOptions)(void *userData, int index), 
+               void (*setDrawInterpOptions)(void *userData, int index, float t),
+               void *userData)
+{
+}
+
+/* free all DerivedMesh data */
+static void vDM_release(DerivedMesh *dm)
+{
+       VDerivedMesh *vdm = (VDerivedMesh*)dm;
+
+       if(vdm->verts) MEM_freeN(vdm->verts);
+       MEM_freeN(vdm);
+}
+
+/* create derived mesh from verse mesh ... it is used in object mode, when some other client can
+ * change shared data and want to see this changes in real time too */
+DerivedMesh *derivedmesh_from_versemesh(VNode *vnode, float (*vertexCos)[3])
+{
+       VDerivedMesh *vdm = MEM_callocN(sizeof(*vdm), "vdm");
+       struct VerseVert *vvert;
+
+       vdm->vnode = vnode;
+       vdm->vertex_layer = find_verse_layer_type((VGeomData*)vnode->data, VERTEX_LAYER);
+       vdm->polygon_layer = find_verse_layer_type((VGeomData*)vnode->data, POLYGON_LAYER);
+
+       vdm->dm.getMinMax = vDM_getMinMax;
+
+       vdm->dm.getNumVerts = vDM_getNumVerts;
+       vdm->dm.getNumFaces = vDM_getNumFaces;
+
+       vdm->dm.foreachMappedVert = vDM_foreachMappedVert;
+       vdm->dm.foreachMappedEdge = vDM_foreachMappedEdge;
+       vdm->dm.foreachMappedFaceCenter = vDM_foreachMappedFaceCenter;
+
+       vdm->dm.convertToDispListMesh = vDM_convertToDispListMesh;
+
+       vdm->dm.getVertCos = vDM_getVertCos;
+       vdm->dm.getVertCo = vDM_getVertCo;
+       vdm->dm.getVertNo = vDM_getVertNo;
+
+       vdm->dm.drawVerts = vDM_drawVerts;
+
+       vdm->dm.drawEdges = vDM_drawEdges;
+       vdm->dm.drawLooseEdges = vDM_drawLooseEdges;
+       vdm->dm.drawUVEdges = vDM_drawUVEdges;
+
+       vdm->dm.drawFacesSolid = vDM_drawFacesSolid;
+       vdm->dm.drawFacesColored = vDM_drawFacesColored;
+
+       vdm->dm.drawMappedFacesTex = vDM_drawMappedFacesTex;
+       vdm->dm.drawMappedFaces = vDM_drawMappedFaces;
+       vdm->dm.drawMappedEdges = vDM_drawMappedEdges;
+       vdm->dm.drawMappedEdgesInterp = vDM_drawMappedEdgesInterp;
+
+       vdm->dm.release = vDM_release;
+
+       if(vdm->vertex_layer) {
+               if(vertexCos) {
+                       int i;
+
+                       vdm->verts = MEM_mallocN(sizeof(float)*3*vdm->vertex_layer->dl.da.count, "verse mod vertexes");
+                       vvert = vdm->vertex_layer->dl.lb.first;
+
+                       for(i=0; i<vdm->vertex_layer->dl.da.count && vvert; i++, vvert = vvert->next) {
+                               VECCOPY(vdm->verts[i], vertexCos[i]);
+                               vvert->cos = vdm->verts[i];
+                       }
+               }
+               else {
+                       vdm->verts = NULL;
+                       vvert = vdm->vertex_layer->dl.lb.first;
+
+                       while(vvert) {
+                               vvert->cos = NULL;
+                               vvert = vvert->next;
+                       }
+               }
+       }
+
+       return (DerivedMesh*) vdm;
+}
+
+#endif
+
 /***/
 
 DerivedMesh *mesh_create_derived_for_modifier(Object *ob, ModifierData *md)
@@ -1506,8 +1958,13 @@ DerivedMesh *mesh_create_derived_for_modifier(Object *ob, ModifierData *md)
                float (*deformedVerts)[3] = mesh_getVertexCos(me, &numVerts);
 
                mti->deformVerts(md, ob, NULL, deformedVerts, numVerts);
-               
+#ifdef WITH_VERSE
+               if(me->vnode) dm = derivedmesh_from_versemesh(me->vnode, deformedVerts);
+               else dm = getMeshDerivedMesh(me, ob, deformedVerts);
+#else
                dm = getMeshDerivedMesh(me, ob, deformedVerts);
+#endif
+
                MEM_freeN(deformedVerts);
        } else {
                dm = mti->applyModifier(md, ob, NULL, NULL, 0, 0);
@@ -1566,7 +2023,13 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3], DerivedM
                         * places that wish to use the original mesh but with deformed
                         * coordinates (vpaint, etc.)
                         */
-               if (deform_r) *deform_r = getMeshDerivedMesh(me, ob, deformedVerts);
+               if (deform_r)
+#ifdef WITH_VERSE
+                       if(me->vnode) *deform_r = derivedmesh_from_versemesh(me->vnode, deformedVerts);
+                       else *deform_r = getMeshDerivedMesh(me, ob, deformedVerts);
+#else
+                       *deform_r = getMeshDerivedMesh(me, ob, deformedVerts);
+#endif
        } else {
                if(!fluidsimMeshUsed) {
                        // default behaviour for meshes
@@ -1651,7 +2114,12 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3], DerivedM
        } else if (dm) {
                *final_r = dm;
        } else {
+#ifdef WITH_VERSE
+               if(me->vnode) *final_r = derivedmesh_from_versemesh(me->vnode, deformedVerts);
+               else *final_r = getMeshDerivedMesh(me, ob, deformedVerts);
+#else
                *final_r = getMeshDerivedMesh(me, ob, deformedVerts);
+#endif
        }
 
        if (deformedVerts && deformedVerts!=inputVertexCos) {
index fdfcef53954b627d087c0f703004fbb67587eea2..28d4151154c94aa3e14672b55601930ff51ce348 100644 (file)
@@ -84,6 +84,11 @@ ifeq ($(WITH_FREETYPE2), true)
     CPPFLAGS += -I$(NAN_FREETYPE)/include/freetype2
 endif
 
+ifeq ($(WITH_VERSE), true)
+    CPPFLAGS += -DWITH_VERSE
+    CPPFLAGS += -I$(NAN_VERSE)/include
+endif
+
 ifeq ($(WITH_FFMPEG),true)
     CPPFLAGS += -DWITH_FFMPEG
     CPPFLAGS += $(NAN_FFMPEGCFLAGS)
index 098f6adb33c5000e6f4de0702ddf12f07d2ef507..2b0c936edd94557e34a3cfb620cce3e69bc3c0a2 100644 (file)
 #include "BKE_utildefines.h"
 #include "BKE_bad_level_calls.h"
 
+#ifdef WITH_VERSE
+#include "BKE_verse.h"
+#endif
+
 #include "BLI_blenlib.h"
 #include "BLI_editVert.h"
 #include "BLI_arithb.h"
@@ -199,7 +203,11 @@ Mesh *add_mesh()
        me->texflag= AUTOSPACE;
        me->flag= ME_TWOSIDED;
        me->bb= unit_boundbox();
-       
+
+#ifdef WITH_VERSE
+       me->vnode = NULL;
+#endif
+
        return me;
 }
 
@@ -234,7 +242,11 @@ Mesh *copy_mesh(Mesh *me)
        
        men->key= copy_key(me->key);
        if(men->key) men->key->from= (ID *)men;
-       
+
+#ifdef WITH_VERSE
+       men->vnode = NULL;
+#endif 
+
        return men;
 }
 
@@ -1073,15 +1085,39 @@ void mesh_calc_normals(MVert *mverts, int numVerts, MFace *mfaces, int numFaces,
 
 float (*mesh_getVertexCos(Mesh *me, int *numVerts_r))[3]
 {
-       int i, numVerts = me->totvert;
-       float (*cos)[3] = MEM_mallocN(sizeof(*cos)*numVerts, "vertexcos1");
+#ifdef WITH_VERSE
+       if(me->vnode) {
+               struct VLayer *vlayer;
+               struct VerseVert *vvert;
+               unsigned int i, numVerts;
+               float (*cos)[3];
 
-       if (numVerts_r) *numVerts_r = numVerts;
-       for (i=0; i<numVerts; i++) {
-               VECCOPY(cos[i], me->mvert[i].co);
-       }
+               vlayer = find_verse_layer_type((VGeomData*)((VNode*)me->vnode)->data, VERTEX_LAYER);
+
+               vvert = vlayer->dl.lb.first;
+               numVerts = vlayer->dl.da.count;
+               cos = MEM_mallocN(sizeof(*cos)*numVerts, "verse_vertexcos");
 
-       return cos;
+               for(i=0; i<numVerts && vvert; vvert = vvert->next, i++) {
+                       VECCOPY(cos[i], vvert->co);
+               }
+
+               return cos;
+       }
+       else {
+#endif
+               int i, numVerts = me->totvert;
+               float (*cos)[3] = MEM_mallocN(sizeof(*cos)*numVerts, "vertexcos1");
+        
+               if (numVerts_r) *numVerts_r = numVerts;
+               for (i=0; i<numVerts; i++) {
+                       VECCOPY(cos[i], me->mvert[i].co);
+               }
+        
+               return cos;
+#ifdef WITH_VERSE
+       }
+#endif
 }
 
 /* UvVertMap */
index 1a96b41d9bb45a683e778cf042da2500fcec9338..5ce83c19033285ef484d0a7714ae18286a8a5173 100644 (file)
@@ -910,6 +910,11 @@ Object *copy_object(Object *ob)
        obn->derivedDeform = NULL;
        obn->derivedFinal = NULL;
 
+#ifdef WITH_VERSE
+       obn->vnode = NULL;
+#endif
+
+
        return obn;
 }
 
diff --git a/source/blender/blenkernel/intern/verse_bitmap_node.c b/source/blender/blenkernel/intern/verse_bitmap_node.c
new file mode 100644 (file)
index 0000000..f9b18c3
--- /dev/null
@@ -0,0 +1,449 @@
+/**
+ * $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 */
+static void cb_b_dimension_set(void *user_data, VNodeID node_id, uint16 width, uint16 height, uint16 depth);
+static void cb_b_layer_create(void *user_data, VNodeID node_id, VLayerID layer_id, const char *name, VNBLayerType type);
+static void cb_b_layer_destroy(void *user_data, VNodeID node_id, VLayerID layer_id);
+static void cb_b_tile_set(void *user_data, VNodeID node_id, VLayerID layer_id, uint16 tile_x, uint16 tile_y, uint16 z,         VNBLayerType type, const VNBTile *tile);
+
+static void change_layer_dimension(
+               VBitmapLayer *vblayer,
+               unsigned int old_width,
+               unsigned int old_height,
+               unsigned int t_old_width,
+               unsigned int t_old_height);
+static void *alloc_verse_bitmap_layer_data(struct VBitmapLayer *vblayer);
+
+/*
+ * resize/crop verse bitmap layer
+ */
+static void change_layer_dimension(
+               VBitmapLayer *vblayer,
+               unsigned int old_width,
+               unsigned int old_height,
+               unsigned int t_old_width,
+               unsigned int t_old_height)
+{
+       struct VNode *vnode = vblayer->vnode;
+       unsigned int t_width = ((VBitmapData*)(vnode->data))->t_width;
+       unsigned int t_height = ((VBitmapData*)(vnode->data))->t_height;
+       unsigned int width = ((VBitmapData*)(vnode->data))->width;
+       unsigned int height = ((VBitmapData*)(vnode->data))->height;
+       unsigned int x, y, i, j;
+       
+       i = j = 0;
+
+       /* "copy" old data to new data */
+       if(vblayer->type==VN_B_LAYER_UINT8) {
+               unsigned char *data = (unsigned char*)vblayer->data;
+               /* allocate new verse bitmap layer data */
+               unsigned char *new_data = (unsigned char*)alloc_verse_bitmap_layer_data(vblayer);
+               for(y=0; y<old_height && y<height; y++, i=y*t_width, j=y*t_old_width) {
+                       for(x=0; x<old_width && y<width; x++, i++, j++) {
+                               new_data[i] = data[j];
+                       }
+               }
+               MEM_freeN(vblayer->data);
+               vblayer->data = new_data;
+       }
+}
+
+/*
+ * free data stored in verse bitmap layer
+ */
+void free_bitmap_layer_data(VBitmapLayer *vblayer)
+{
+       struct VerseSession *session = vblayer->vnode->session;
+
+       /* free name of bitmap layer */
+       MEM_freeN(vblayer->name);
+
+       /* unsubscribe from verse bitmap layer */
+       if(session->flag & VERSE_CONNECTED)
+               verse_send_b_layer_unsubscribe(vblayer->vnode->id, vblayer->id);
+
+       /* free image data of bitmap layer */
+       if(vblayer->data) MEM_freeN(vblayer->data);
+}
+
+/*
+ * allocate data of verse bitmap layer
+ */
+static void *alloc_verse_bitmap_layer_data(VBitmapLayer *vblayer)
+{
+       struct VNode *vnode = vblayer->vnode;
+       unsigned int t_width = ((VBitmapData*)(vnode->data))->t_width;
+       unsigned int t_height = ((VBitmapData*)(vnode->data))->t_height;
+       unsigned int size;
+       void *data;
+
+       size = t_width*t_height;
+
+       /* allocation of own data stored in verse bitmap layer */
+       switch (vblayer->type) {
+               case VN_B_LAYER_UINT1:
+                       data = (void*)MEM_mallocN(sizeof(unsigned char)*size, "VBLayer data uint1");
+                       break;
+               case VN_B_LAYER_UINT8:
+                       data = (void*)MEM_mallocN(sizeof(unsigned char)*size, "VBLayer data uint8");
+                       break;
+               case VN_B_LAYER_UINT16:
+                       data = (void*)MEM_mallocN(sizeof(unsigned int)*size, "VBLayer data uint16");
+                       break;
+               case VN_B_LAYER_REAL32:
+                       data = (void*)MEM_mallocN(sizeof(float)*size, "VBLayer data float16");
+                       break;
+               case VN_B_LAYER_REAL64:
+                       data = (void*)MEM_mallocN(sizeof(double)*size, "VBLayer data float32");
+                       break;
+       }
+
+       return data;
+}
+
+/*
+ * create verse bitmap layer
+ */
+VBitmapLayer *create_bitmap_layer(
+               VNode *vnode,
+               VLayerID layer_id,
+               const char *name,
+               VNBLayerType type)
+{
+       struct VBitmapLayer *vblayer;
+       unsigned int width = ((VBitmapData*)(vnode->data))->width;
+       unsigned int height = ((VBitmapData*)(vnode->data))->height;
+
+       /* allocate memory for own verse bitmap layer */
+       vblayer = (VBitmapLayer*)MEM_mallocN(sizeof(VBitmapLayer), "Verse Bitmap Layer");
+
+       /* verse bitmap layer will include pointer at parent verse node and own id */
+       vblayer->vnode = vnode;
+       vblayer->id = layer_id;
+
+       /* name of verse layer */
+       vblayer->name = (char*)MEM_mallocN(sizeof(char)*(strlen(name)+1), "Verse Bitmap Layer name");
+       vblayer->name[0] = '\0';
+       strcpy(vblayer->name, name);
+
+       /* type of data stored in verse bitmap layer */
+       vblayer->type = type;
+
+       /* we can allocate memory for layer data, when we know dimmension of layers; when
+        * we don't know it, then we will allocate this data when we will receive dimmension */
+       if(width==0 || height==0)
+               vblayer->data = NULL;
+       else
+               vblayer->data = alloc_verse_bitmap_layer_data(vblayer);
+
+       vblayer->flag = 0;
+
+       return vblayer;
+}
+
+/*
+ * free data of bitmap node
+ */
+void free_bitmap_node_data(VNode *vnode)
+{
+       if(vnode->data) {
+               struct VBitmapLayer *vblayer = (VBitmapLayer*)((VBitmapData*)(vnode->data))->layers.lb.first;
+
+               /* free all VerseLayer data */
+               while(vblayer) {
+                       free_bitmap_layer_data(vblayer);
+                       vblayer = vblayer->next;
+               }
+
+               /* free all VerseLayers */
+               BLI_dlist_destroy(&(((VGeomData*)vnode->data)->layers));
+       }
+}
+
+/*
+ * create data of bitmap node
+ */
+VBitmapData *create_bitmap_data()
+{
+       struct VBitmapData *vbitmap;
+
+       vbitmap = (VBitmapData*)MEM_mallocN(sizeof(VBitmapData), "Verse Bitmap Data");
+
+       BLI_dlist_init(&(vbitmap->layers));
+       vbitmap->queue.first = vbitmap->queue.last = NULL;
+
+       vbitmap->width = 0;
+       vbitmap->height = 0;
+       vbitmap->depth = 0;
+
+       vbitmap->image = NULL;
+
+       vbitmap->post_bitmap_dimension_set = post_bitmap_dimension_set;
+       vbitmap->post_bitmap_layer_create = post_bitmap_layer_create;
+       vbitmap->post_bitmap_layer_destroy = post_bitmap_layer_destroy;
+       vbitmap->post_bitmap_tile_set = post_bitmap_tile_set;
+
+       return vbitmap;
+}
+
+/*
+ * callback function, dimension of image was changed, it is neccessary to
+ * crop all layers
+ */
+static void cb_b_dimension_set(
+               void *user_data,
+               VNodeID node_id,
+               uint16 width,
+               uint16 height,
+               uint16 depth)
+{
+       struct VerseSession *session = (VerseSession*)current_verse_session();
+       struct VNode *vnode;
+       struct VBitmapLayer *vblayer;
+       unsigned int old_width, old_height, t_old_width, t_old_height;
+       
+       if(!session) return;
+
+       vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
+       if(!vnode) return;
+
+#ifdef VERSE_DEBUG_PRINT
+       printf("\t cb_b_dimension_set()\n");
+#endif
+
+       /* backup old width and height */
+       old_width = ((VBitmapData*)(vnode->data))->width;
+       old_height = ((VBitmapData*)(vnode->data))->height;
+       t_old_width = ((VBitmapData*)(vnode->data))->t_width;
+       t_old_height = ((VBitmapData*)(vnode->data))->t_height;
+
+       /* set up new dimension of layers */
+       ((VBitmapData*)(vnode->data))->width = width;
+       ((VBitmapData*)(vnode->data))->height = height;
+       ((VBitmapData*)(vnode->data))->depth = depth;
+
+       /* we cache t_width because tiles aren't one pixel width */
+       if((width % VN_B_TILE_SIZE)!=0)
+               ((VBitmapData*)(vnode->data))->t_width = (width/VN_B_TILE_SIZE + 1)*VN_B_TILE_SIZE;
+       else
+               ((VBitmapData*)(vnode->data))->t_width = width;
+
+       /* we cache t_height because tiles aren't one pixel height */
+       if((height % VN_B_TILE_SIZE)!=0)
+               ((VBitmapData*)(vnode->data))->t_height = (height/VN_B_TILE_SIZE + 1)*VN_B_TILE_SIZE;
+       else
+               ((VBitmapData*)(vnode->data))->t_height = height;
+
+       /* crop resize all layers */
+       vblayer = ((VBitmapData*)vnode->data)->layers.lb.first;
+
+       while(vblayer) {
+               /* when this callback function received after cb_b_layer_create,
+                * then we have to allocate memory for verse bitmap layer data */
+               if(!vblayer->data) vblayer->data = alloc_verse_bitmap_layer_data(vblayer);
+               /* crop/resize all verse bitmap layers */
+               else change_layer_dimension(vblayer, old_width, old_height, t_old_width, t_old_height);
+
+               vblayer = vblayer->next;
+       }
+       
+       /* post callback function */
+       ((VBitmapData*)(vnode->data))->post_bitmap_dimension_set(vnode);
+}
+
+/*
+ * callback function, new layer channel of image was created
+ */
+static void cb_b_layer_create(
+               void *user_data,
+               VNodeID node_id,
+               VLayerID layer_id,
+               const char *name,
+               VNBLayerType type)
+{
+       struct VerseSession *session = (VerseSession*)current_verse_session();
+       struct VNode *vnode;
+       struct VBitmapLayer *vblayer;
+       
+       if(!session) return;
+
+       vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
+       if(!vnode) return;
+       
+#ifdef VERSE_DEBUG_PRINT
+       printf("\t cb_b_layer_create()\n");
+#endif
+
+       /* when no layer exists, then new layer will be created */
+       vblayer = create_bitmap_layer(vnode, layer_id, name, type);
+
+       /* add verse bitmap layer to list of layers */
+       BLI_dlist_add_item_index(&((VBitmapData*)vnode->data)->layers, vblayer, layer_id);
+
+       /* post callback function */
+       ((VBitmapData*)(vnode->data))->post_bitmap_layer_create(vblayer);
+
+}
+
+/*
+ * callback function, existing layer of image was destroyed
+ */
+static void cb_b_layer_destroy(
+               void *user_data,
+               VNodeID node_id,
+               VLayerID layer_id)
+{
+       struct VerseSession *session = (VerseSession*)current_verse_session();
+       struct VNode *vnode;
+       struct VBitmapLayer *vblayer;
+       
+       if(!session) return;
+
+       /* find node of this layer*/
+       vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
+       if(!vnode) return;
+
+       vblayer = (VBitmapLayer*)BLI_dlist_find_link(&(((VBitmapData*)vnode->data)->layers), layer_id);
+       if(!vblayer) return;
+
+#ifdef VERSE_DEBUG_PRINT
+       printf("\t cb_b_layer_destroy()\n");
+#endif
+
+       /* remove verse bitmap layer from list of layers */
+       BLI_dlist_rem_item(&(((VBitmapData*)vnode->data)->layers), layer_id);
+
+       /* post callback function */
+       ((VBitmapData*)(vnode->data))->post_bitmap_layer_destroy(vblayer);
+
+       /* free data of verse bitmap layer */
+       free_bitmap_layer_data(vblayer);
+
+       /* free verse bitmap layer */
+       MEM_freeN(vblayer);
+}
+
+/*
+ * callback function, small part (8x8 pixels) was changed
+ */
+static void cb_b_tile_set(
+               void *user_data,
+               VNodeID node_id,
+               VLayerID layer_id,
+               uint16 tile_x,
+               uint16 tile_y,
+               uint16 z,
+               VNBLayerType type,
+               const VNBTile *tile)
+{
+       struct VerseSession *session = (VerseSession*)current_verse_session();
+       struct VNode *vnode;
+       struct VBitmapLayer *vblayer;
+       unsigned int x, y, xs, ys, width, height, t_height, t_width, i, j;
+       
+       if(!session) return;
+
+       /* try to find verse node in dynamic list nodes */
+       vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
+       if(!vnode) return;
+
+       /* try to find verse bitmap layer in list of layers */
+       vblayer = (VBitmapLayer*)BLI_dlist_find_link(&(((VBitmapData*)vnode->data)->layers), layer_id);
+       if(!vblayer) return;
+
+       /* we have to have allocated memory for bitmap layer */
+       if(!vblayer->data) return;
+
+       width = ((VBitmapData*)vnode->data)->width;
+       height = ((VBitmapData*)vnode->data)->height;
+
+       /* width of verse image including all tiles */
+       t_height = ((VBitmapData*)vnode->data)->t_height;
+       /* height of verse image including all tiles */
+       t_width = ((VBitmapData*)vnode->data)->t_width;
+
+#ifdef VERSE_DEBUG_PRINT
+       printf("\t cb_b_tile_set()\n");
+#endif
+
+       xs = tile_x*VN_B_TILE_SIZE;
+       ys = tile_y*VN_B_TILE_SIZE;
+
+       /* initial position in one dimension vblayer->data (y_start*width + x_start) */
+       i = ys*t_width + xs;
+       /* intial position in one dimension tile array */
+       j = 0;
+
+       if(type==VN_B_LAYER_UINT8) {
+               unsigned char *data = (unsigned char*)vblayer->data;
+               for(y=ys; y<ys+VN_B_TILE_SIZE && y<height; y++, i=y*t_width+xs)
+                       for(x=xs; x<xs+VN_B_TILE_SIZE && x<width; x++, i++, j++)
+                               data[i] = (unsigned char)tile->vuint8[j];
+       }
+
+       /* post callback function */
+       ((VBitmapData*)(vnode->data))->post_bitmap_tile_set(vblayer, xs, ys);
+}
+
+/*
+ * set up all callbacks functions for image nodes
+ */
+void set_bitmap_callbacks(void)
+{
+       /* dimension (size) of bitmap was set up or changes (image will be croped) */
+       verse_callback_set(verse_send_b_dimensions_set, cb_b_dimension_set, NULL);
+
+       /* new layer (chanell) of image was added or created */
+       verse_callback_set(verse_send_b_layer_create, cb_b_layer_create, NULL);
+
+       /* existing layer was destroyed */
+       verse_callback_set(verse_send_b_layer_destroy, cb_b_layer_destroy, NULL);
+
+       /* some tile (small part 8x8 pixels of image was changed) */
+       verse_callback_set(verse_send_b_tile_set, cb_b_tile_set, NULL);
+}
+
+#endif
+
diff --git a/source/blender/blenkernel/intern/verse_geometry_node.c b/source/blender/blenkernel/intern/verse_geometry_node.c
new file mode 100644 (file)
index 0000000..bb3234d
--- /dev/null
@@ -0,0 +1,1665 @@
+/**
+ * $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 "BLI_arithb.h"
+
+#include "BKE_verse.h"
+#include "BKE_utildefines.h"
+
+#include "BIF_verse.h"
+
+#include "verse.h"
+
+/* function prototypes of static functions */
+
+/* test functions for callback functions */
+static char test_polygon_set_corner_uint32(uint32 v0, uint32 v1, uint32 v2, uint32 v3);
+
+/* callback functions */
+static void cb_g_layer_create(void *user_data, VNodeID node_id, VLayerID layer_id, const char *name, VNGLayerType type, uint32 def_integer, real64 def_real);
+static void cb_g_layer_destroy(void *user_data, VNodeID node_id, VLayerID layer_id);
+static void cb_g_vertex_set_xyz_real32(void *user_data, VNodeID node_id, VLayerID layer_id, uint32 vertex_id, real32 x,        real32 y, real32 z);
+static void cb_g_polygon_set_corner_uint32(void *user_data, VNodeID node_id, VLayerID layer_id, uint32 polygon_id, uint32 v0, uint32 v1, uint32 v2, uint32 v3);
+static void cb_g_vertex_delete_real32(void *user_data, VNodeID node_id, uint32 vertex_id);
+static void cb_g_polygon_delete(void *user_data, VNodeID node_id, uint32 polygon_id);
+static void cb_g_crease_set_edge(void *user_data, VNodeID node_id, const char *layer, uint32 def_crease);
+static void cb_g_crease_set_vertex(void *user_data, VNodeID node_id, const char *layer, uint32 def_crease);
+
+/* other static functions */
+
+static void free_unneeded_verseverts_of_verseface(struct VNode *vnode, struct VerseFace *vface);
+static void free_verse_vertex(struct VLayer *vlayer, struct VerseVert *vvert);
+static void free_verse_face(struct VLayer *vlayer, struct VerseFace *vface);
+static void free_verse_layer_data(struct VNode *vnode, struct VLayer *vlayer);
+
+static void send_verse_face(struct VerseFace *vface);
+
+static VerseVert* find_verse_vert_in_queue(struct VLayer *vlayer, VNodeID node_id, uint32 vertex_id, real32 x, real32 y, real32 z);
+static VerseFace* find_verse_face_in_queue(struct VLayer *vlayer, VNodeID node_id, uint32 polygon_id, uint32 v0, uint32 v1, uint32 v2, uint32 v3);
+
+static unsigned short test_incoming_verseface(struct VGeomData *geom, struct VerseFace *vface);
+static void find_unsent_faces(struct VNode *vnode, struct VerseVert *vvert);
+static void find_vlayer_orphans(struct VNode *vnode, struct VerseVert *vvert);
+static void move_face_orphan_to_dlist(struct VNode *vnode, struct VLayer *vlayer, struct VerseFace *vface);
+static void increase_verse_verts_references(struct VerseFace *vface);
+static void recalculate_verseface_normals(struct VNode *vnode);
+
+/*
+ * recalcute normals of all VerseFaces
+ */
+static void recalculate_verseface_normals(VNode *vnode)
+{
+       struct VLayer *vert_layer, *face_layer;
+       struct VerseFace *vface;
+       struct VerseVert *vvert;
+
+       if(vnode->type != V_NT_GEOMETRY) return;
+
+       vert_layer = find_verse_layer_type((VGeomData*)vnode->data, VERTEX_LAYER);
+       face_layer = find_verse_layer_type((VGeomData*)vnode->data, POLYGON_LAYER);
+
+       vvert = vert_layer->dl.lb.first;
+       while(vvert) {
+               vvert->no[0] = vvert->no[1] = vvert->no[2] = 0.0;
+               vvert = vvert->next;
+       }
+
+       vface = face_layer->dl.lb.first;
+       while(vface) {
+               /* calculate face normals */
+               if(vface->vvert3) {
+                       CalcNormFloat4(vface->vvert0->co, vface->vvert1->co,
+                                       vface->vvert2->co, vface->vvert3->co, vface->no);
+                       VecAddf(vface->vvert3->no, vface->vvert3->no, vface->no);
+               }
+               else
+                       CalcNormFloat(vface->vvert0->co, vface->vvert1->co,
+                                       vface->vvert2->co, vface->no);
+
+               /* calculate vertex normals ... it is averadge of all face normals using the vertex */
+               VecAddf(vface->vvert0->no, vface->vvert0->no, vface->no);
+               VecAddf(vface->vvert1->no, vface->vvert1->no, vface->no);
+               VecAddf(vface->vvert2->no, vface->vvert2->no, vface->no);
+
+               vface = vface->next;
+       }
+
+       /* we have to normalise all vertex normals */
+       vvert = vert_layer->dl.lb.first;
+       while(vvert) {
+               Normalise(vvert->no);
+               vvert = vvert->next;
+       }
+}
+
+/*
+ * add created item to the queue and send it if possible
+ */
+void add_item_to_send_queue(ListBase *lb, void *item, short type)
+{
+       /* this prevent from adding duplicated faces */
+       if(type==VERSE_FACE) {
+               struct Link *link = (Link*)lb->first;
+               while(link) {
+                       if(link==item) {
+                               if(((VerseFace*)item)->flag & FACE_SENT) {
+/*                                     printf("\tverse face %d marked as OBSOLETE\n", ((VerseFace*)item)->id);*/
+                                       ((VerseFace*)item)->flag |= FACE_OBSOLETE;
+                               }
+                               return;
+                       }
+                       link = link->next;
+               }
+       }
+
+       /* add item to sending queue (two way dynamic list) */
+       BLI_addtail(lb, item);
+
+       /* send item, when it is possible */
+       switch (type) {
+               case VERSE_NODE:        /* only first node in queue can be sent */
+                       if(lb->first==lb->last) 
+                               send_verse_node((VNode*)item);
+                       break;
+               case VERSE_LINK:        /* both object between have to exist */
+                       if(((VLink*)item)->flag & LINK_SEND_READY)
+                               send_verse_link((VLink*)item);
+                       break;
+               case VERSE_LAYER:
+                       if(((VLayer*)item)->vnode->flag & NODE_RECEIVED)
+                               send_verse_layer((VLayer*)item);
+                       break;
+               case VERSE_VERT:
+                       if(((VerseVert*)item)->vlayer->flag & LAYER_RECEIVED)
+                               send_verse_vertex((VerseVert*)item);
+                       break;
+               case VERSE_FACE:        /* all vertexes of face have to be received */
+                       if(((VerseFace*)item)->flag & FACE_SEND_READY)
+                               send_verse_face((VerseFace*)item);
+                       break;
+               case VERSE_TAG:
+                       send_verse_tag((VTag*)item);
+                       break;
+               case VERSE_TAG_GROUP:
+                       send_verse_taggroup((VTagGroup*)item);
+                       break;
+               case VERSE_VERT_UINT32: /* parent item has to exist */
+                       if( ((verse_parent*)((uint32_item*)item)->parent)->id != -1)
+                               send_verse_vert_uint32((uint32_item*)item, type);
+                       break;
+               case VERSE_VERT_REAL32: /* parent item has to exist */
+                       if( ((verse_parent*)((real32_item*)item)->parent)->id != -1)
+                               send_verse_vert_real32((real32_item*)item, type);
+                       break;
+               case VERSE_VERT_VEC_REAL32:     /* parent item has to exist */
+                       if( ((verse_parent*)((vec_real32_item*)item)->parent)->id != -1)
+                               send_verse_vert_vec_real32((vec_real32_item*)item, type);
+                       break;
+               case VERSE_FACE_UINT8:  /* parent item has to exist */
+                       if( ((verse_parent*)((uint8_item*)item)->parent)->id != -1)
+                               send_verse_face_uint8((uint8_item*)item, type);
+                       break;
+               case VERSE_FACE_UINT32: /* parent item has to exist */
+                       if( ((verse_parent*)((uint32_item*)item)->parent)->id != -1)
+                               send_verse_face_uint32((uint32_item*)item, type);
+                       break;
+               case VERSE_FACE_REAL32: /* parent item has to exist */
+                       if( ((verse_parent*)((real32_item*)item)->parent)->id != -1)
+                               send_verse_face_real32((real32_item*)item, type);
+                       break;
+               case VERSE_FACE_QUAT_UINT32:    /* parent item has to exist */
+                       if( ((verse_parent*)((quat_uint32_item*)item)->parent)->id != -1)
+                               send_verse_face_corner_quat_uint32((quat_uint32_item*)item, type);
+                       break;
+               case VERSE_FACE_QUAT_REAL32:    /* parent item has to exist */
+                       if( ((verse_parent*)((quat_real32_item*)item)->parent)->id != -1)
+                               send_verse_face_corner_quat_real32((quat_real32_item*)item, type);
+                       break;
+       }
+}
+
+/*
+ * return VerseLayer with certain content (vertexes, polygons, in the
+ * future: weight, red color, etc.)
+ */
+VLayer* find_verse_layer_type(VGeomData *geom, short content)
+{
+       struct VLayer *vlayer = NULL;
+       
+       switch(content) {
+               case VERTEX_LAYER:
+                       /* VERTEX_LAYER equals 0 and vertex layer is
+                        * always in 1st layer */
+                       vlayer = geom->layers.da.items[VERTEX_LAYER];
+                       break;
+               case POLYGON_LAYER:
+                       /* POLYGON_LAYER equals 1 and vertex layer is
+                        * always in 2nd layer */
+                       vlayer = geom->layers.da.items[POLYGON_LAYER];
+                       break;
+       }
+
+       return vlayer;
+}
+
+/*
+ * increase references of VerseVerts of new VerseFace
+ */
+static void increase_verse_verts_references(VerseFace *vface)
+{
+       if(vface->vvert0) vface->vvert0->counter++;
+       if(vface->vvert1) vface->vvert1->counter++;
+       if(vface->vvert2) vface->vvert2->counter++;
+       if(vface->vvert3) vface->vvert3->counter++;
+}
+
+/*
+ * move VerseFace from list of orphans to dlist of VerseFaces (if VerseFace was only changed
+ * then this VerseFace is only removed from list of orphans)
+ */
+static void move_face_orphan_to_dlist(VNode *vnode, VLayer *vlayer, VerseFace *vface)
+{
+       /* remove vface from list of orphans */
+       BLI_remlink(&(vlayer->orphans), vface);
+       /* increase references of all vertexes beying part of this face*/
+       increase_verse_verts_references(vface);
+
+       if(vface->flag & FACE_RECEIVED) {
+               /* set up vface flag */
+               vface->flag &= ~FACE_RECEIVED;
+               /* move vface to dynamic list of faces */
+               BLI_dlist_add_item_index(&(vlayer->dl), (void*)vface, vface->id);
+               /* recalculate all vertex and faces normals */
+               recalculate_verseface_normals(vnode);
+               /* post create action (change local data) */
+               ((VGeomData*)vnode->data)->post_polygon_create(vface);
+       }
+       else if(vface->flag & FACE_CHANGED) {
+               /* set up vface flag */
+               vface->flag &= ~FACE_CHANGED;
+               /* move vface to dynamic list of faces */
+               BLI_dlist_add_item_index(&(vlayer->dl), (void*)vface, vface->id);
+               /* recalculate all vertex and faces normals */
+               recalculate_verseface_normals(vnode);
+               /* post create action (change local data) */
+               ((VGeomData*)vnode->data)->post_polygon_set_corner(vface);
+       }
+}
+
+/*
+ * find all VerseFaces waiting in queue, which needs id of new VerseVert
+ */
+static void find_unsent_faces(VNode *vnode, VerseVert *vvert)
+{
+       VLayer *vlayer;
+       VerseFace *vface, *next_vface;
+
+       vlayer = find_verse_layer_type((VGeomData*)vnode->data, POLYGON_LAYER);
+
+       if(vlayer) {
+               vface = vlayer->queue.first;
+               while(vface) {
+                       next_vface = vface->next;
+                       if(vface->vvert0==vvert) {
+                               vface->v0 = vvert->id;
+                               vface->counter--;
+                       }
+                       else if(vface->vvert1==vvert) {
+                               vface->v1 = vvert->id;
+                               vface->counter--;
+                       }
+                       else if(vface->vvert2==vvert) {
+                               vface->v2 = vvert->id;
+                               vface->counter--;
+                       }
+                       else if(vface->vvert3==vvert){
+                               vface->v3 = vvert->id;
+                               vface->counter--;
+                       }
+
+                       if(vface->counter<1 && !(vface->flag & FACE_SENT))
+                               send_verse_face(vface);
+
+                       vface = next_vface;
+               }
+       }
+}
+
+/*
+ * find all VerseFace orphans, which needs incoming VerseVert
+ */
+static void find_vlayer_orphans(VNode *vnode, VerseVert *vvert)
+{
+       VLayer *vlayer;
+       VerseFace *vface, *next_vface;
+       unsigned int vertex_id = vvert->id;
+
+       vlayer = find_verse_layer_type((VGeomData*)vnode->data, POLYGON_LAYER);
+
+       if(vlayer) {
+               vface = vlayer->orphans.first;
+               while(vface){
+                       next_vface = vface->next;
+                       if(vface->v0 == vertex_id) {
+                               vface->vvert0 = vvert;
+                               vface->counter--;
+                       }
+                       else if(vface->v1 == vertex_id) {
+                               vface->vvert1 = vvert;
+                               vface->counter--;
+                       }
+                       else if(vface->v2 == vertex_id) {
+                               vface->vvert2 = vvert;
+                               vface->counter--;
+                       }
+                       else if(vface->v3 == vertex_id) {
+                               vface->vvert3 = vvert;
+                               vface->counter--;
+                       }
+                       if(vface->counter<1) {
+                               /* moving VerseFace orphan to dlist */
+                               move_face_orphan_to_dlist(vnode, vlayer, vface);
+                       }
+                       vface = next_vface;
+               }
+       }
+}
+
+/*
+ * return number of VerseVerts missing to incoming VerseFace, set up pointers
+ * at VerseVerts
+ */
+static unsigned short test_incoming_verseface(VGeomData *geom, VerseFace *vface)
+{
+       struct VLayer *vert_layer;
+       struct VerseVert *vvert; 
+       int counter=0;
+
+       vert_layer = find_verse_layer_type(geom, VERTEX_LAYER);
+
+       if(vface->v0 != -1){
+               vvert = BLI_dlist_find_link(&(vert_layer->dl), vface->v0);
+               if(vvert==NULL) counter++;
+               else vface->vvert0 = vvert;
+       }
+       if(vface->v1 != -1){
+               vvert = BLI_dlist_find_link(&(vert_layer->dl), vface->v1);
+               if(vvert==NULL) counter++;
+               else vface->vvert1 = vvert;
+       }
+       if(vface->v2 != -1){
+               vvert = BLI_dlist_find_link(&(vert_layer->dl), vface->v2);
+               if(vvert==NULL) counter++;
+               else vface->vvert2 = vvert;
+       }
+       if(vface->v3 != -1){
+               vvert = BLI_dlist_find_link(&(vert_layer->dl), vface->v3);
+               if(vvert==NULL) counter++;
+               else vface->vvert3 = vvert;
+       }
+       
+       return counter;
+}
+
+/*
+ * try to find changed VerseFace in sending queue
+ */
+static VerseFace* find_changed_verse_face_in_queue(VLayer *vlayer, uint32 polygon_id)
+{
+       struct VerseFace *vface = vlayer->queue.first;
+
+       while(vface){
+               if(vface->id == polygon_id && vface->flag & FACE_CHANGED) {
+                       return vface;
+               }
+               vface = vface->next;
+       }
+       return NULL;
+}
+
+/*
+ * try to find VerseFace in queue
+ */
+static VerseFace* find_verse_face_in_queue(
+               VLayer *vlayer,
+               VNodeID node_id,
+               uint32 polygon_id,
+               uint32 v0,
+               uint32 v1,
+               uint32 v2,
+               uint32 v3)
+{
+       struct VerseFace *vface = vlayer->queue.first;
+
+       while(vface){
+               if((vface->v0==v0) && (vface->v1==v1) && (vface->v2==v2) && (vface->v3==v3)){
+                       vface->id = polygon_id;
+                       vface->vlayer = vlayer;
+                       return vface;
+               }
+               vface = vface->next;
+       }
+       return NULL;
+}
+
+/*
+ * try to find VerseVert in queue
+ */
+static VerseVert* find_verse_vert_in_queue(
+               VLayer *vlayer,
+               VNodeID node_id,
+               uint32 vertex_id,
+               real32 x,
+               real32 y,
+               real32 z)
+{
+       struct VerseVert *vvert = vlayer->queue.first;
+
+       while(vvert){
+               if((vvert->vlayer->vnode->id == node_id) && (vvert->co[0] == x) && (vvert->co[1] == y) && (vvert->co[2] == z))
+               {
+                       vvert->id = vertex_id;
+                       vvert->vlayer = vlayer;
+
+                       return vvert;
+               }
+               vvert = vvert->next;
+       }
+
+       return NULL;
+}
+
+
+/*
+ * send quat of float values to verse server (4x32 bits)
+ */
+void send_verse_face_corner_quat_real32(quat_real32_item *item, short type)
+{
+       struct VerseFace *vface = (VerseFace*)item->parent;
+
+       verse_send_g_polygon_set_corner_real32(
+                       vface->vlayer->vnode->id,
+                       item->layer_id,
+                       vface->id,
+                       item->value[0],
+                       item->value[1],
+                       item->value[2],
+                       item->value[3]);
+}
+
+/*
+ * send quat of unsigned int values to verse server (4x32 bits)
+ */
+void send_verse_face_corner_quat_uint32(quat_uint32_item *item, short type)
+{
+       struct VerseFace *vface = (VerseFace*)item->parent;
+
+       verse_send_g_polygon_set_corner_uint32(
+                       vface->vlayer->vnode->id,
+                       item->layer_id,
+                       vface->id,
+                       item->value[0],
+                       item->value[1],
+                       item->value[2],
+                       item->value[3]);
+}
+
+/*
+ * send float value (32 bits) to verse server
+ */
+void send_verse_face_real32(real32_item *item, short type)
+{
+       struct VerseFace *vface = (VerseFace*)item->parent;
+
+       verse_send_g_polygon_set_face_real32(
+                       vface->vlayer->vnode->id,
+                       item->layer_id,
+                       vface->id,
+                       item->value);
+}
+
+/*
+ * send unsigned integer (32 bits) to verse server
+ */
+void send_verse_face_uint32(uint32_item *item, short type)
+{
+       struct VerseFace *vface = (VerseFace*)item->parent;
+
+       verse_send_g_polygon_set_face_uint32(
+                       vface->vlayer->vnode->id,
+                       item->layer_id,
+                       vface->id,
+                       item->value);
+}
+
+/*
+ * send unsigned char (8 bits) to verse server
+ */
+void send_verse_face_uint8(uint8_item *item, short type)
+{
+       struct VerseFace *vface = (VerseFace*)item->parent;
+
+       verse_send_g_polygon_set_face_uint8(
+                       vface->vlayer->vnode->id,
+                       item->layer_id,
+                       vface->id,
+                       item->value);
+}
+
+/*
+ * send vector of float values to verse server (3x32 bits)
+ */
+void send_verse_vert_vec_real32(vec_real32_item *item, short type)
+{
+       struct VerseVert *vvert = (VerseVert*)item->parent;
+
+       verse_send_g_vertex_set_xyz_real32(
+                       vvert->vlayer->vnode->id,
+                       item->layer_id,
+                       vvert->id,
+                       item->value[0],
+                       item->value[1],
+                       item->value[2]);
+}
+
+/*
+ * send float value (32 bits) to verse server
+ */
+void send_verse_vert_real32(real32_item *item, short type)
+{
+       struct VerseVert *vvert = (VerseVert*)item->parent;
+
+       verse_send_g_vertex_set_real32(
+                       vvert->vlayer->vnode->id,
+                       item->layer_id,
+                       vvert->id,
+                       item->value);
+}
+
+/*
+ * send unsigned integer (32 bits) to verse server
+ */
+void send_verse_vert_uint32(uint32_item *item, short type)
+{
+       struct VerseVert *vvert = (VerseVert*)item->parent;
+
+       verse_send_g_vertex_set_uint32(
+                       vvert->vlayer->vnode->id,
+                       item->layer_id,
+                       vvert->id,
+                       item->value);
+}
+
+/*
+ * send delete command to verse server
+ */
+void send_verse_vertex_delete(VerseVert *vvert)
+{
+       verse_session_set(vvert->vlayer->vnode->session->vsession);
+
+       vvert->flag |= VERT_OBSOLETE;
+       
+       verse_send_g_vertex_delete_real32(vvert->vlayer->vnode->id, vvert->id);
+}
+
+/*
+ * send VerseLayer to verse server
+ */
+void send_verse_layer(VLayer *vlayer)
+{
+       verse_session_set(vlayer->vnode->session->vsession);
+
+       verse_send_g_layer_create(
+                       vlayer->vnode->id,
+                       vlayer->id,
+                       vlayer->name,
+                       vlayer->type,
+                       vlayer->def_int,
+                       vlayer->def_real);
+}
+
+/* 
+ * send VerseVert to verse server
+ */
+void send_verse_vertex(VerseVert *vvert)
+{
+       /* new vertex position will not be sent, when vertex was deleted */
+       if(vvert->flag & VERT_OBSOLETE) return;
+       
+       verse_session_set(vvert->vlayer->vnode->session->vsession);
+
+       verse_send_g_vertex_set_xyz_real32(
+                       vvert->vlayer->vnode->id,
+                       vvert->vlayer->id,
+                       vvert->id,
+                       vvert->co[0],
+                       -vvert->co[2],
+                       vvert->co[1]);
+}
+
+/*
+ * send delete command to verse server
+ */
+void send_verse_face_delete(VerseFace *vface)
+{
+       verse_session_set(vface->vlayer->vnode->session->vsession);
+
+       vface->flag |= FACE_DELETED;
+
+       verse_send_g_polygon_delete(vface->vlayer->vnode->id, vface->id);
+}
+
+/*
+ * send VerseFace to verse server
+ */
+static void send_verse_face(VerseFace *vface)
+{
+       verse_session_set(vface->vlayer->vnode->session->vsession);
+
+       vface->flag |= FACE_SENT;
+
+       if(vface->v3 != -1) {
+/*             printf("\tSEND: VerseFace: %d, %d, %d, %d, %d\n", vface->id, vface->v0, vface->v3, vface->v2, vface->v1);*/
+               verse_send_g_polygon_set_corner_uint32(
+                               vface->vlayer->vnode->id,
+                               vface->vlayer->id,
+                               vface->id,
+                               vface->v0,
+                               vface->v3,      /* verse use clock-wise winding */
+                               vface->v2,
+                               vface->v1);     /* verse use clock-wise winding */
+       }
+       else {
+/*             printf("\tSEND: VerseFace: %d, %d, %d, %d, %d\n", vface->id, vface->v0, vface->v2, vface->v1, vface->v3);*/
+               verse_send_g_polygon_set_corner_uint32(
+                               vface->vlayer->vnode->id,
+                               vface->vlayer->id,
+                               vface->id,
+                               vface->v0,
+                               vface->v2,      /* verse use clock-wise winding */
+                               vface->v1,      /* verse use clock-wise winding */
+                               vface->v3);
+       }
+}
+
+/*
+ * free VerseVert
+ */
+static void free_verse_vertex(VLayer *vlayer, VerseVert *vvert)
+{
+       /* free VerseVert */
+       BLI_freelinkN(&(vlayer->orphans), vvert);
+}
+
+/*
+ * free VerseFace (and blender face)
+ */
+static void free_verse_face(VLayer *vlayer, VerseFace *vface)
+{
+       /* free VerseFace */
+       BLI_dlist_free_item(&(vlayer->dl), (unsigned int)vface->id);
+}
+
+/*
+ * free VerseLayer data
+ */
+static void free_verse_layer_data(VNode *vnode, VLayer *vlayer)
+{
+       struct VerseFace *vface;
+       struct VerseVert *vvert;
+
+       /* set up EditVert->vvert and EditFace->vface pointers to NULL */
+       switch(vlayer->content) {
+               case VERTEX_LAYER:
+                       vvert = (VerseVert*)vlayer->dl.lb.first;
+                       while(vvert) {
+                               ((VGeomData*)vnode->data)->post_vertex_free_constraint(vvert);
+                               vvert = vvert->next;
+                       }
+                       break;
+               case POLYGON_LAYER:
+                       vface = (VerseFace*)vlayer->dl.lb.first;
+                       while(vface) {
+                               ((VGeomData*)vnode->data)->post_polygon_free_constraint(vface);
+                               vface = vface->next;
+                       }
+                       break;
+               default:
+                       break;
+       }
+       /* free Verse Layer name */
+       MEM_freeN(vlayer->name);
+       /* destroy VerseLayer data (vertexes, polygons, etc.) */
+       BLI_dlist_destroy(&(vlayer->dl));
+       /* free unsent data */
+       BLI_freelistN(&(vlayer->queue));
+       /* free orphans */
+       BLI_freelistN(&(vlayer->orphans));
+}
+
+/*
+ * free all unneeded VerseVerts waiting for deleting
+ */
+static void free_unneeded_verseverts_of_verseface(VNode *vnode, VerseFace *vface)
+{
+       struct VLayer *vert_vlayer;
+
+       /* find layer containing vertexes */
+       vert_vlayer = find_verse_layer_type((VGeomData*)vnode->data, VERTEX_LAYER);
+
+       /* free all "deleted" VerseVert waiting for deleting this VerseFace */
+       
+       if((vface->vvert0->counter < 1) && (vface->vvert0->flag & VERT_DELETED)) {
+               ((VGeomData*)vnode->data)->post_vertex_delete(vface->vvert0);
+               free_verse_vertex(vert_vlayer, vface->vvert0);
+               vface->vvert0 = NULL;
+       }
+       if((vface->vvert1->counter < 1) && (vface->vvert1->flag & VERT_DELETED)) {
+               ((VGeomData*)vnode->data)->post_vertex_delete(vface->vvert1);
+               free_verse_vertex(vert_vlayer, vface->vvert1);
+               vface->vvert1 = NULL;
+       }
+       if((vface->vvert2->counter < 1) && (vface->vvert2->flag & VERT_DELETED)) {
+               ((VGeomData*)vnode->data)->post_vertex_delete(vface->vvert2);
+               free_verse_vertex(vert_vlayer, vface->vvert2);
+               vface->vvert2 = NULL;
+       }
+       if((vface->vvert3) && (vface->vvert3->counter < 1) && (vface->vvert3->flag & VERT_DELETED)) {
+               ((VGeomData*)vnode->data)->post_vertex_delete(vface->vvert3);
+               free_verse_vertex(vert_vlayer, vface->vvert3);
+               vface->vvert3 = NULL;
+       }
+}
+
+/*
+ * This function create VerseVert and returns pointer on this vertex
+ */
+VerseVert* create_verse_vertex(
+               VLayer *vlayer,
+               uint32 vertex_id,
+               real32 x,
+               real32 y,
+               real32 z)
+{
+       struct VerseVert *vvert;
+
+       vvert = (VerseVert*)MEM_mallocN(sizeof(VerseVert), "VerseVert");
+       
+       /* set up pointer on parent node */
+       vvert->vlayer = vlayer;
+       vvert->id = vertex_id;
+       /* position */
+       vvert->co[0] = x;
+       vvert->co[1] = y;
+       vvert->co[2] = z;
+       /* normal */
+       vvert->no[0] = vvert->no[1] = vvert->no[2] = 0.0;
+       /* blender internals */
+       vvert->flag = 0;
+       vvert->counter = 0;
+       vvert->vertex = NULL;
+
+       /* increase layer counter of vertexes */
+       vlayer->counter++;
+
+       return vvert;
+}
+
+/*
+ * this function will create new VerseFace and will return pointer on such Face
+ */
+VerseFace* create_verse_face(
+               VLayer *vlayer,
+               uint32 polygon_id,
+               uint32 v0,
+               uint32 v1,
+               uint32 v2,
+               uint32 v3)
+{
+       struct VerseFace *vface;
+
+       vface = (VerseFace*)MEM_mallocN(sizeof(VerseFace), "VerseFace");
+
+       /* verse data */
+       vface->vlayer = vlayer;
+       vface->id = polygon_id;
+
+       vface->vvert0 = NULL;
+       vface->vvert1 = NULL;
+       vface->vvert2 = NULL;
+       vface->vvert3 = NULL;
+
+       vface->v0 = v0;
+       vface->v1 = v1;
+       vface->v2 = v2;
+       vface->v3 = v3;
+
+       /* blender data */
+       vface->face = NULL;
+       vface->flag = 0;
+       vface->counter = 4;
+
+       /* increase layer counter of faces */
+       vlayer->counter++;
+       
+       return vface;
+}
+
+/*
+ * create and return VerseLayer
+ */
+VLayer *create_verse_layer(
+               VNode *vnode,
+               VLayerID layer_id,
+               const char *name,
+               VNGLayerType type,
+               uint32 def_integer,
+               real64 def_real)
+{
+       struct VLayer *vlayer;
+
+       /* add layer to the DynamicList */
+       vlayer = (VLayer*)MEM_mallocN(sizeof(VLayer), "VerseLayer");
+
+       /* store all relevant info to the vlayer and set up vlayer */
+       vlayer->vnode = vnode;
+       vlayer->id = layer_id;
+       vlayer->name = (char*)MEM_mallocN(sizeof(char)*(sizeof(name)+1),"Verse Layer name");
+       strcpy(vlayer->name, name);
+       vlayer->type = type;
+       vlayer->def_int = def_integer;
+       vlayer->def_real = def_real;
+
+       if((type == VN_G_LAYER_VERTEX_XYZ) && (layer_id == 0))
+               vlayer->content = VERTEX_LAYER;
+       else if((type == VN_G_LAYER_POLYGON_CORNER_UINT32) && (layer_id == 1))
+               vlayer->content = POLYGON_LAYER;
+       else
+               vlayer->content = -1;
+
+       /* initialize DynamicList in the vlayer (vertexes, polygons, etc.)*/
+       BLI_dlist_init(&(vlayer->dl));
+       /* initialization of queue of layer */
+       vlayer->queue.first = vlayer->queue.last = NULL;
+       /* initialization of list of orphans */
+       vlayer->orphans.first = vlayer->orphans.last = NULL;
+       /* initialize number of sent items (vertexes, faces, etc) */
+       vlayer->counter = 0;
+       /* initialize flag */
+       vlayer->flag = 0;
+
+       /* set up methods */
+       vlayer->post_layer_create = post_layer_create;
+       vlayer->post_layer_destroy = post_layer_destroy;
+
+       return vlayer;
+}
+
+/*
+ * create geometry data
+ */
+VGeomData *create_geometry_data(void)
+{
+       struct VGeomData *geom;
+
+       geom = (VGeomData*)MEM_mallocN(sizeof(VGeomData), "VerseGeometryData");
+       BLI_dlist_init(&(geom->layers));
+       geom->vlink = NULL;
+       geom->queue.first = geom->queue.last = NULL;
+       geom->mesh = NULL;
+       geom->editmesh = NULL;
+
+       /* set up methods */
+       geom->post_vertex_create = post_vertex_create;
+       geom->post_vertex_set_xyz = post_vertex_set_xyz;
+       geom->post_vertex_delete = post_vertex_delete;
+       geom->post_vertex_free_constraint = post_vertex_free_constraint;
+       geom->post_polygon_create = post_polygon_create;
+       geom->post_polygon_set_corner = post_polygon_set_corner;
+       geom->post_polygon_delete = post_polygon_delete;
+       geom->post_polygon_free_constraint = post_polygon_free_constraint;
+       geom->post_geometry_free_constraint = post_geometry_free_constraint;
+       geom->post_polygon_set_uint8 = post_polygon_set_uint8;
+
+       return geom;
+}
+
+/*
+ * callback function: vertex crease was set
+ */
+static void cb_g_crease_set_vertex(
+               void *user_data,
+               VNodeID node_id,
+               const char *layer,
+               uint32 def_crease)
+{
+/*     struct VerseSession *session = (VerseSession*)current_verse_session();
+       struct VNode *vnode;*/
+}
+
+/*
+ * callback function: edge crease was set
+ */
+static void cb_g_crease_set_edge(
+               void *user_data,
+               VNodeID node_id,
+               const char *layer,
+               uint32 def_crease)
+{
+/*     struct VerseSession *session = (VerseSession*)current_verse_session();
+       struct VNode *vnode;*/
+}
+
+/*
+ * callback function: float value for polygon was set up
+ */
+static void cb_g_polygon_set_face_real32(
+               void *user_def,
+               VNodeID node_id,
+               VLayerID layer_id,
+               uint32 polygon_id,
+               real32 value)
+{
+/*     struct VerseSession *session = (VerseSession*)current_verse_session();
+       struct VNode *vnode;*/
+}
+
+/*
+ * callback function: int values for polygon was set up
+ */
+static void cb_g_polygon_set_face_uint32(
+               void *user_def,
+               VNodeID node_id,
+               VLayerID layer_id,
+               uint32 polygon_id,
+               uint32 value)
+{
+/*     struct VerseSession *session = (VerseSession*)current_verse_session();
+       struct VNode *vnode;*/
+}
+
+static uint8_item *create_uint8_item(void)
+{
+       struct uint8_item *item;
+
+       item = (uint8_item*)MEM_mallocN(sizeof(uint8_item), "uint8_item");
+       item->value = 0;
+
+       return item;
+}
+
+/*
+ * callback function: uint8 value for polygon was set up
+ */
+static void cb_g_polygon_set_face_uint8(
+               void *user_def,
+               VNodeID node_id,
+               VLayerID layer_id,
+               uint32 polygon_id,
+               uint8 value)
+{
+       struct VerseSession *session = (VerseSession*)current_verse_session();
+       struct VNode *vnode;
+       struct VLayer *vlayer;
+       struct uint8_item *item;
+
+       if(!session) return;
+
+       /* find needed node (we can be sure, that it is geometry node) */
+       vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
+
+       /* find layer containing uint_8 data */
+       vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), (unsigned int)layer_id);
+
+       /* try to find item*/
+       item = BLI_dlist_find_link(&(vlayer->dl), polygon_id);
+
+       if(item) {
+               item->value = value;
+       }
+       else {
+               item = create_uint8_item();
+               BLI_dlist_add_item_index(&(vlayer->dl), item, polygon_id);
+               item->value = value;
+       }
+}
+
+/*
+ * callback function: float value for polygon corner was set up
+ */
+static void cb_g_polygon_set_corner_real32(
+               void *user_def,
+               VNodeID node_id,
+               VLayerID layer_id,
+               uint32 polygon_id,
+               real32 v0,
+               real32 v1,
+               real32 v2,
+               real32 v3)
+{
+}
+
+/*
+ * callback function: polygon is deleted
+ */
+static void cb_g_polygon_delete(
+               void *user_data,
+               VNodeID node_id,
+               uint32 polygon_id)
+{
+       struct VerseSession *session = (VerseSession*)current_verse_session();
+       VNode *vnode;
+       VLayer *vlayer;
+       VerseFace *vface;
+
+       if(!session) return;
+
+       /* find needed node (we can be sure, that it is geometry node) */
+       vnode = BLI_dlist_find_link(&(session->nodes), node_id);
+
+       /* find layer containing faces */
+       vlayer = find_verse_layer_type((VGeomData*)vnode->data, POLYGON_LAYER);
+
+       /* find wanted VerseFace */
+       vface = BLI_dlist_find_link(&(vlayer->dl), polygon_id);
+
+       if(!vface) return;
+       
+       ((VGeomData*)vnode->data)->post_polygon_delete(vface);
+
+       /* decrease references at coresponding VerseVertexes */
+       vface->vvert0->counter--;
+       vface->vvert1->counter--;
+       vface->vvert2->counter--;
+       if(vface->vvert3) vface->vvert3->counter--;
+
+       /* delete unneeded VerseVertexes */
+       free_unneeded_verseverts_of_verseface(vnode, vface);
+       
+       free_verse_face(vlayer, vface);
+}
+
+/*
+ * we have to test corretness of incoming data from verse server
+ * no two vertexes can have the same index
+ */
+static char test_polygon_set_corner_uint32(
+               uint32 v0,
+               uint32 v1,
+               uint32 v2,
+               uint32 v3)
+{
+       if((v0==v1) || (v0==v2) || (v0==v3) || (v1==v2) || (v1==v3) || (v2==v3))
+               return 0;
+       else
+               return 1;
+}
+
+/*
+ * try to find verse layer in sending queue of verse geometry node
+ */
+static VLayer *find_vlayer_in_sending_queue(VNode *vnode, VLayerID layer_id)
+{
+       struct VLayer *vlayer;
+       
+       /* try to find verse layyer in sending queue */
+       vlayer = ((VGeomData*)vnode->data)->queue.first;
+       while(vlayer) {
+               if(vlayer->id==layer_id) return vlayer;
+               vlayer = vlayer->next;
+       }
+
+       return NULL;
+}
+
+/*
+ * callback function: new polygon (face) created or existing polygon was changed
+ */
+static void cb_g_polygon_set_corner_uint32(
+               void *user_data,
+               VNodeID node_id,
+               VLayerID layer_id,
+               uint32 polygon_id,
+               uint32 v0,
+               uint32 v1,
+               uint32 v2,
+               uint32 v3)
+{
+       struct VerseSession *session = (VerseSession*)current_verse_session();
+       struct VNode *vnode;
+       struct VLayer *vlayer;
+       struct VerseFace *vface=NULL;
+
+       if(!session) return;
+
+       /* try to find VerseNode */
+       vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
+       if(!vnode) return;
+
+       /* try to find VerseLayer */
+       vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), (unsigned int)layer_id);
+       if(!vlayer) return;
+
+       /* we have to test coretness of incoming data */
+       if(!test_polygon_set_corner_uint32(v0, v1, v2, v3)) return;
+       
+/*     printf("\tRECEIVE VerseFace: %d, %d, %d, %d, %d\n", polygon_id, v0, v1, v2, v3);*/
+
+       /* Blender uses different order of vertexes */
+       if(v3!=-1) { /* quat swap */
+               unsigned int v; v = v1; v1 = v3; v3 = v;
+       }
+       else { /* triangle swap */
+               unsigned int v; v = v1; v1 = v2; v2 = v;
+       }
+
+       /* try to find VerseFace */
+       vface = (VerseFace*)BLI_dlist_find_link(&(vlayer->dl), (unsigned int)polygon_id);
+
+       /* try to find modified VerseFace */
+       if(!vface) {
+               vface = find_changed_verse_face_in_queue(vlayer, polygon_id);
+               if(vface) {
+                       BLI_remlink(&(vlayer->queue), (void*)vface);
+                       BLI_dlist_add_item_index(&(vlayer->dl), (void*)vface, (unsigned int)polygon_id);
+/*                     printf("\treceived changed face (changed by this app)\n");*/
+               }
+       }
+
+       if(!vface) {
+/*             printf("\tno vface\n");*/
+               /* try to find VerseFace in list of VerseVaces created by me and set up polygon and
+                * layer ids */
+               vface = find_verse_face_in_queue(vlayer, node_id, polygon_id, v0, v1, v2, v3);
+               
+               if(vface){
+/*                     printf("\tremove from vface queue\n");*/
+                       /* I creeated this face ... remove VerseFace from queue */
+                       BLI_remlink(&(vlayer->queue), (void*)vface);
+               }
+               else {
+/*                     printf("\tcreate vface\n");*/
+                       /* some other client created this face*/
+                       vface = create_verse_face(vlayer, polygon_id, v0, v1, v2, v3);
+               }
+
+               vface->flag &= ~FACE_SENT;
+
+               /* return number of missing verse vertexes */
+               vface->counter = test_incoming_verseface((VGeomData*)vnode->data, vface);
+
+               if(vface->counter < 1) {
+                       /* when VerseFace received all needed VerseFaces, then it is moved
+                        * to list of VerseFaces */
+                       BLI_dlist_add_item_index(&(vlayer->dl), (void*)vface, (unsigned int)polygon_id);
+                       increase_verse_verts_references(vface);
+                       recalculate_verseface_normals(vnode);
+                       ((VGeomData*)vnode->data)->post_polygon_create(vface);
+               }
+               else {
+/*                     printf("\torphan vface\n");*/
+                       /* when all needed VerseVertexes weren't received, then VerseFace is moved to
+                        * the list of orphans waiting on needed vertexes */
+                       vface->flag |= FACE_RECEIVED;
+                       BLI_addtail(&(vlayer->orphans), (void*)vface);
+               }
+       }
+       else {
+               VLayer *vert_vlayer = find_verse_layer_type((VGeomData*)vnode->data, VERTEX_LAYER);
+/*             printf("\tvface changed\n");*/
+               /* VerseVertexes of existing VerseFace were changed (VerseFace will use some different
+                * VerseVertexes or it will use them in different order) */
+
+               /* initialize count of unreceived vertexes needed for this face */
+               vface->counter = 4;
+
+               /* 1st corner */
+               if(vface->vvert0->id != v0) {
+                       /* decrease references of obsolete vertexes*/
+                       vface->vvert0->counter--;
+                       /* delete this vertex, when it isn't used by any face and it was marked as deleted */
+                       if((vface->vvert0->counter < 1) && (vface->vvert0->flag & VERT_DELETED)) {
+                               ((VGeomData*)vnode->data)->post_vertex_delete(vface->vvert0);
+                               free_verse_vertex(vert_vlayer, vface->vvert0);
+                       }
+                       /* try to set up new pointer at verse vertex */
+                       vface->v0 = v0;
+                       vface->vvert0 = BLI_dlist_find_link(&(vert_vlayer->dl), vface->v0);
+                       if(vface->vvert0) {
+                               /* increase references at new vertex */
+                               vface->vvert0->counter++;
+                               /* decrease count of needed vertex to receive */
+                               vface->counter--;
+                       }
+                       
+               }
+               else
+                       /* this corner wasn't changed */
+                       vface->counter--;
+
+               /* 2nd corner */
+               if(vface->vvert1->id != v1) {
+                       vface->vvert1->counter--;
+                       if((vface->vvert1->counter < 1) && (vface->vvert1->flag & VERT_DELETED)) {
+                               ((VGeomData*)vnode->data)->post_vertex_delete(vface->vvert1);
+                               free_verse_vertex(vert_vlayer, vface->vvert1);
+                       }
+                       vface->v1 = v1;
+                       vface->vvert1 = BLI_dlist_find_link(&(vert_vlayer->dl), vface->v1);
+                       if(vface->vvert1) {
+                               vface->vvert1->counter++;
+                               vface->counter--;
+                       }
+               }
+               else
+                       vface->counter--;
+
+               /* 3rd corner */
+               if(vface->vvert2->id != v2) {
+                       vface->vvert2->counter--;
+                       if((vface->vvert2->counter < 1) && (vface->vvert2->flag & VERT_DELETED)) {
+                               ((VGeomData*)vnode->data)->post_vertex_delete(vface->vvert2);
+                               free_verse_vertex(vert_vlayer, vface->vvert2);
+                       }
+                       vface->v2 = v2;
+                       vface->vvert2 = BLI_dlist_find_link(&(vert_vlayer->dl), vface->v2);
+                       if(vface->vvert2) {
+                               vface->vvert2->counter++;
+                               vface->counter--;
+                       }
+               }
+               else
+                       vface->counter--;
+       
+               /* 4th corner */        
+               if(vface->vvert3) {
+                       if(vface->vvert3->id != v3) {
+                               vface->vvert3->counter--;
+                               if((vface->vvert3->counter < 1) && (vface->vvert3->flag & VERT_DELETED)) {
+                                       ((VGeomData*)vnode->data)->post_vertex_delete(vface->vvert3);
+                                       free_verse_vertex(vert_vlayer, vface->vvert3);
+                               }
+                               vface->v3 = v3;
+                               if(v3 != -1) {
+                                       vface->vvert3 = BLI_dlist_find_link(&(vert_vlayer->dl), vface->v3);
+                                       if(vface->vvert3) {
+                                               vface->vvert3->counter++;
+                                               vface->counter--;
+                                       }
+                               }
+                               else {
+                                       /* this is some special case, this face hase now only 3 corners
+                                        * quat -> triangle */
+                                       vface->vvert3 = NULL;
+                                       vface->counter--;
+                               }
+                       }
+               }
+               else if(v3 != -1)
+                       /* this is some special case, 4th corner of this polygon was created
+                        * triangle -> quat */
+                       vface->v3 = v3;
+                       vface->vvert3 = BLI_dlist_find_link(&(vert_vlayer->dl), vface->v3);
+                       if(vface->vvert3) {
+                               vface->vvert3->counter++;
+                               vface->counter--;
+                       }
+               else {
+                       vface->v3 = -1;
+                       vface->counter--;
+               }
+               
+               vface->flag &= ~FACE_SENT;
+               vface->flag |= FACE_CHANGED;
+
+               if(vface->counter<1) {
+                       vface->flag &= ~FACE_CHANGED;
+                       recalculate_verseface_normals(vnode);
+                       ((VGeomData*)vnode->data)->post_polygon_set_corner(vface);
+               }
+               else {
+                       /* when all needed VerseVertexes weren't received, then VerseFace is added to
+                        * the list of orphans waiting on needed vertexes */
+                       BLI_dlist_rem_item(&(vlayer->dl), vface->id);
+                       BLI_addtail(&(vlayer->orphans), (void*)vface);
+               }
+       }
+}
+
+/*
+ * callback function: float value was set up for VerseVert with vertex_id
+ */
+static void cb_g_vertex_set_real32(
+               void *user_def,
+               VNodeID node_id,
+               VLayerID layer_id,
+               uint32 vertex_id,
+               real32 value)
+{
+/*     struct VerseSession *session = (VerseSession*)current_verse_session();
+       struct VNode *vnode;*/
+}
+
+/*
+ * callback function: int value was set up for VerseVert with vertex_id
+ */
+static void cb_g_vertex_set_uint32(
+               void *user_def,
+               VNodeID node_id,
+               VLayerID layer_id,
+               uint32 vertex_id,
+               uint32 value)
+{
+/*     struct VerseSession *session = (VerseSession*)current_verse_session();
+       struct VNode *vnode;*/
+}
+
+/*
+ * callback function: polygon was deleted
+ */
+static void cb_g_vertex_delete_real32(
+               void *user_data,
+               VNodeID node_id,
+               uint32 vertex_id)
+{
+       struct VerseSession *session = (VerseSession*)current_verse_session();
+       VNode *vnode=NULL;
+       VLayer *vert_vlayer=NULL;
+       VerseVert *vvert=NULL;
+
+       if(!session) return;
+
+       vnode = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
+
+       vert_vlayer = find_verse_layer_type((VGeomData*)vnode->data, VERTEX_LAYER);
+
+       vvert = BLI_dlist_find_link(&(vert_vlayer->dl), (unsigned int)vertex_id);
+
+       if(!vvert) return;
+
+       if(vvert->counter < 1) {
+               ((VGeomData*)vnode->data)->post_vertex_delete(vvert);
+               BLI_dlist_free_item(&(vert_vlayer->dl), (unsigned int)vertex_id);
+       }
+       else {
+               /* some VerseFace(s) still need VerseVert, remove verse vert from
+                * list verse vertexes and put it to list of orphans */
+               vvert->flag |= VERT_DELETED;
+               BLI_dlist_rem_item(&(vert_vlayer->dl), (unsigned int)vertex_id);
+               BLI_addtail(&(vert_vlayer->orphans), vvert);
+       }
+}
+
+/*
+ * callback function: position of one vertex was changed or new vertex was created
+ */
+static void cb_g_vertex_set_xyz_real32(
+               void *user_data,
+               VNodeID node_id,
+               VLayerID layer_id,
+               uint32 vertex_id,
+               real32 x,
+               real32 y,
+               real32 z)
+{
+       struct VerseSession *session = (VerseSession*)current_verse_session();
+       struct VNode *vnode = NULL;
+       struct VLayer *vlayer = NULL;
+       struct VerseVert *vvert = NULL;
+       real32 tmp;
+
+       if(!session) return;
+
+       vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
+       if(!vnode)return;
+
+       vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), (unsigned int)layer_id);
+       if(!vlayer) return;
+
+       /* switch axis orientation */
+       tmp = -y;
+       y = z;
+       z = tmp;
+       
+       if(vlayer->id == 0) {
+               /* try to pick up verse vert from DynamicList */
+               vvert = (VerseVert*)BLI_dlist_find_link(&(vlayer->dl), (unsigned int)vertex_id);
+
+               if(vvert) {
+                       if(vvert->flag & VERT_OBSOLETE) return;
+
+                       if (vvert->flag & VERT_LOCKED) {
+                               if((vvert->co[0]==x) && (vvert->co[1]==y) && (vvert->co[2]==z)) {
+                                       if (!(vvert->flag & VERT_POS_OBSOLETE))
+                                               vvert->flag &= ~VERT_LOCKED;
+                                       recalculate_verseface_normals(vnode);
+                                       ((VGeomData*)vnode->data)->post_vertex_set_xyz(vvert);
+                               }
+                       }
+                       else {
+                               if((vvert->co[0]!=x) || (vvert->co[1]!=y) || (vvert->co[2]!=z)) {
+                                       vvert->co[0] = x;
+                                       vvert->co[1] = y;
+                                       vvert->co[2] = z;
+
+                                       recalculate_verseface_normals(vnode);
+                                       ((VGeomData*)vnode->data)->post_vertex_set_xyz(vvert);
+                               }
+                       }
+               }
+               else {
+                       /* create new verse vert */
+
+                       /* test if we are authors of this vertex :-) */
+                       vvert = find_verse_vert_in_queue(vlayer, node_id, vertex_id, x, y, z);
+
+                       if(vvert) {
+                               /* remove vert from queue */
+                               BLI_remlink(&(vlayer->queue), (void*)vvert);
+                               /* add vvert to the dynamic list */
+                               BLI_dlist_add_item_index(&(vlayer->dl), (void*)vvert, (unsigned int)vertex_id);
+                               /* set VerseVert flags */
+                               vvert->flag |= VERT_RECEIVED;
+                               if(!(vvert->flag & VERT_POS_OBSOLETE))
+                                       vvert->flag &= ~VERT_LOCKED;
+                               /* find VerseFaces orphans */
+                               find_vlayer_orphans(vnode, vvert);
+                               /* find unsent VerseFaces */
+                               find_unsent_faces(vnode, vvert);
+                       }
+                       else {
+                               /* create new VerseVert */
+                               vvert = create_verse_vertex(vlayer, vertex_id, x, y, z);
+                               /* add VerseVert to list of VerseVerts */
+                               BLI_dlist_add_item_index(&(vlayer->dl), (void*)vvert, (unsigned int)vertex_id);
+                               /* set VerseVert flags */
+                               vvert->flag |= VERT_RECEIVED;
+                               /* find VerseFaces orphans */
+                               find_vlayer_orphans(vnode, vvert);
+                       }
+
+                       ((VGeomData*)vnode->data)->post_vertex_create(vvert);
+               }
+       }
+}
+
+/*
+ * callback function for destroyng of verse layer
+ */
+static void cb_g_layer_destroy(
+               void *user_data,
+               VNodeID node_id,
+               VLayerID layer_id)
+{
+       struct VerseSession *session = (VerseSession*)current_verse_session();
+       struct VNode *vnode;
+       struct VLayer *vlayer;
+
+       if(!session) return;
+
+       vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), node_id);
+       if(!vnode) return;
+
+       vlayer = (VLayer*) BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), layer_id);
+
+       if(vlayer){
+               /* free VerseLayer data */
+               free_verse_layer_data(vnode, vlayer);
+               /* remove VerseLayer from list of verse layers */
+               BLI_dlist_rem_item(&(((VGeomData*)vnode->data)->layers), layer_id);
+               /* do client dependent actions */
+               vlayer->post_layer_destroy(vlayer);
+               /* free vlayer itself */
+               MEM_freeN(vlayer);
+       }
+
+}
+
+/*
+ * callback function: new layer was created
+ */
+static void cb_g_layer_create(
+               void *user_data,
+               VNodeID node_id,
+               VLayerID layer_id,
+               const char *name,
+               VNGLayerType type,
+               uint32 def_integer,
+               real64 def_real)
+{
+       struct VerseSession *session = (VerseSession*)current_verse_session();
+       struct VNode *vnode=NULL;
+       struct VLayer *vlayer=NULL;
+
+       if(!session) return;
+
+       /* find node of this layer*/
+       vnode = BLI_dlist_find_link(&(session->nodes), node_id);
+       if(!vnode) return;
+
+       /* when we created this layer, then subscribe to this layer */
+       if(vnode->owner_id == VN_OWNER_MINE || session->flag & VERSE_AUTOSUBSCRIBE)
+               verse_send_g_layer_subscribe(node_id, layer_id, 0);
+
+       /* try to find */
+       if(vnode->owner_id == VN_OWNER_MINE)
+               vlayer = find_vlayer_in_sending_queue(vnode, layer_id);
+
+       if(vlayer) {
+               /* remove vlayer form sending queue add verse layer to list of verse layers */
+               BLI_remlink(&((VGeomData*)vnode->data)->queue, vlayer);
+               BLI_dlist_add_item_index(&((VGeomData*)vnode->data)->layers, (void*)vlayer, (unsigned int)vlayer->id);
+               /* send all not sent vertexes to verse server
+                * other items waiting in sending queue will be automaticaly sent to verse server,
+                * when verse vertexes will be received from verse server */
+               if((vlayer->type == VN_G_LAYER_VERTEX_XYZ) && (layer_id==0)) {
+                       struct VerseVert *vvert = (VerseVert*)vlayer->queue.first;
+                       while(vvert) {
+                               send_verse_vertex(vvert);
+                               vvert = vvert->next;
+                       }
+               }
+       }
+       else {
+               /* create new VerseLayer */
+               vlayer = create_verse_layer(vnode, layer_id, name, type, def_integer, def_real);
+               /* add layer to the list of VerseLayers */
+               BLI_dlist_add_item_index(&(((VGeomData*)vnode->data)->layers), (void*)vlayer, (unsigned int)layer_id);
+       }
+
+       vlayer->flag |= LAYER_RECEIVED;
+
+       /* post callback function */
+       vlayer->post_layer_create(vlayer);
+}
+
+/*
+ * this function will send destroy commands for all VerseVertexes and
+ * VerseFaces to verse server, but it will not send destroy commands
+ * for VerseLayers or geometry node, it can be used in other functions
+ * (undo, destroy geom node, some edit mesh commands, ... ), parameter of
+ * this function has to be geometry verse node
+ */
+void destroy_geometry(VNode *vnode)
+{
+       struct VLayer *vert_vlayer, *face_vlayer;
+       struct VerseFace *vface;
+       struct VerseVert *vvert;
+
+       if(vnode->type != V_NT_GEOMETRY) return;
+
+       face_vlayer = find_verse_layer_type((VGeomData*)vnode->data, POLYGON_LAYER);
+       vface = face_vlayer->dl.lb.first;
+
+       while(vface) {
+               send_verse_face_delete(vface);
+               vface = vface->next;
+       }
+
+       vert_vlayer = find_verse_layer_type((VGeomData*)vnode->data, VERTEX_LAYER);
+       vvert = vert_vlayer->dl.lb.first;
+
+       while(vvert) {
+               send_verse_vertex_delete(vvert);
+               vvert = vvert->next;
+       }
+
+       /* own destruction of local verse date will be executed, when client will
+        * receive apropriate callback commands from verse server */
+}
+
+/*
+ * free VGeomData
+ */
+void free_geom_data(VNode *vnode)
+{
+       struct VerseSession *session = vnode->session;
+       struct VLayer *vlayer;
+
+       if(vnode->data){
+               vlayer = (VLayer*)((VGeomData*)vnode->data)->layers.lb.first;
+               while(vlayer){
+                       /* unsubscribe from layer */
+                       if(session->flag & VERSE_CONNECTED)
+                               verse_send_g_layer_unsubscribe(vnode->id, vlayer->id);
+                       /* free VerseLayer data */
+                       free_verse_layer_data(vnode, vlayer);
+                       /* next layer */
+                       vlayer = vlayer->next;
+               }
+               /* free constraint between vnode and mesh */
+               ((VGeomData*)vnode->data)->post_geometry_free_constraint(vnode);
+               /* free all VerseLayers */
+               BLI_dlist_destroy(&(((VGeomData*)vnode->data)->layers));
+       }
+}
+
+void set_geometry_callbacks(void)
+{
+       /* new layer created */
+       verse_callback_set(verse_send_g_layer_create, cb_g_layer_create, NULL);
+       /* layer was destroyed */
+       verse_callback_set(verse_send_g_layer_destroy, cb_g_layer_destroy, NULL);
+
+       /* position of vertex was changed */
+       verse_callback_set(verse_send_g_vertex_set_xyz_real32, cb_g_vertex_set_xyz_real32, NULL);
+       /* vertex was deleted */
+       verse_callback_set(verse_send_g_vertex_delete_real32, cb_g_vertex_delete_real32, NULL);
+
+       /* callback functions for values being associated with vertexes */
+       verse_callback_set(verse_send_g_vertex_set_uint32, cb_g_vertex_set_uint32, NULL);
+       verse_callback_set(verse_send_g_vertex_set_real32, cb_g_vertex_set_real32, NULL);
+
+       /* new polygon was created / vertex(es) of polygon was set */
+       verse_callback_set(verse_send_g_polygon_set_corner_uint32, cb_g_polygon_set_corner_uint32, NULL);
+       /* polygon was deleted */
+       verse_callback_set(verse_send_g_polygon_delete, cb_g_polygon_delete, NULL);
+
+       /* callback functions for values being associated with polygon corners */
+       verse_callback_set(verse_send_g_polygon_set_corner_real32, cb_g_polygon_set_corner_real32, NULL);
+       /* callback functions for values being associated with faces */
+       verse_callback_set(verse_send_g_polygon_set_face_uint8, cb_g_polygon_set_face_uint8, NULL);
+       verse_callback_set(verse_send_g_polygon_set_face_uint32, cb_g_polygon_set_face_uint32, NULL);
+       verse_callback_set(verse_send_g_polygon_set_face_real32, cb_g_polygon_set_face_real32, NULL);
+
+       /* crease of vertex was set */
+       verse_callback_set(verse_send_g_crease_set_vertex, cb_g_crease_set_vertex, NULL);
+       /* crease of edge was set */
+       verse_callback_set(verse_send_g_crease_set_edge, cb_g_crease_set_edge, NULL);
+}
+
+#endif
diff --git a/source/blender/blenkernel/intern/verse_node.c b/source/blender/blenkernel/intern/verse_node.c
new file mode 100644 (file)
index 0000000..570d3a2
--- /dev/null
@@ -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
diff --git a/source/blender/blenkernel/intern/verse_object_node.c b/source/blender/blenkernel/intern/verse_object_node.c
new file mode 100644 (file)
index 0000000..9e6de92
--- /dev/null
@@ -0,0 +1,605 @@
+/**
+ * $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 "BLI_arithb.h"
+
+#include "BIF_verse.h"
+
+#include "BKE_verse.h"
+
+#include "verse.h"
+
+/* function prototypes of static functions */
+
+/* callback functions */
+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);
+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);
+static void cb_o_transform_scale_real32(void *user_data, VNodeID node_id, real32 scale_x, real32 scale_y, real32 scale_z);
+static void cb_o_link_set(void *user_data, VNodeID node_id, uint16 link_id, VNodeID link, const char *label, uint32 target_id);
+static void cb_o_link_destroy(void *user_data, VNodeID node_id,uint16 link_id);
+
+/* other functions */
+static void set_target_node_link_pointer(struct VNode *vnode, struct VLink *vlink);
+static void free_verse_link_data(struct VLink *vlink);
+
+/*
+ * find noy sent VerseLink in queue
+ */
+VLink *find_unsent_child_vlink(VerseSession *session, VNode *vnode)
+{
+       struct VLink *vlink;
+
+       if(vnode->type!=V_NT_OBJECT) return NULL;
+
+       vlink = ((VObjectData*)vnode->data)->queue.first;
+       while(vlink) {
+               if(vlink->target->id != -1) {
+                       printf("\t vlink found, vnode target id %d\n", vlink->target->id);
+                       return vlink;
+               }
+               vlink = vlink->next;
+       }
+       return NULL;
+}
+
+/*
+ * find unsent VerseLink "pointing at this VerseNode"
+ */
+VLink *find_unsent_parent_vlink(VerseSession *session, VNode *vnode)
+{
+       struct VNode *tmp;
+       struct VLink *vlink;
+
+       tmp = session->nodes.lb.first;
+
+       while(tmp) {
+               if(tmp->type==V_NT_OBJECT) {
+                       vlink = ((VObjectData*)tmp->data)->queue.first;
+                       while(vlink) {
+                               if(vlink->target == vnode)
+                                       return vlink;
+                               vlink = vlink->next;
+                       }
+               }
+               tmp = tmp->next;
+       }
+       return NULL;
+}
+
+/*
+ * send object position to verse server
+ */
+void send_verse_object_position(VNode *vnode)
+{
+       float tmp;
+       
+       ((VObjectData*)vnode->data)->flag &= ~POS_SEND_READY;
+
+       tmp = -((VObjectData*)vnode->data)->pos[1];
+       ((VObjectData*)vnode->data)->pos[1] = ((VObjectData*)vnode->data)->pos[2];
+       ((VObjectData*)vnode->data)->pos[2] = tmp;
+
+       verse_send_o_transform_pos_real32(
+                       vnode->id,      /* node id */
+                       0,              /* time_s ... no interpolation */
+                       0,              /* time_f ... no interpolation */
+                       ((VObjectData*)vnode->data)->pos,
+                       NULL,           /* speed ... no interpolation */
+                       NULL,           /* accelerate  ... no interpolation */
+                       NULL,           /* drag normal ... no interpolation */
+                       0.0);           /* drag ... no interpolation */
+}
+
+/*
+ * send object rotation to verse server
+ */
+void send_verse_object_rotation(VNode *vnode)
+{
+       float quat[4];
+/*     float bvec[3], vvec[3];*/
+       VNQuat32 rot;
+
+       rot.x = ((VObjectData*)vnode->data)->rot[0];
+       rot.y = ((VObjectData*)vnode->data)->rot[1];
+       rot.z = ((VObjectData*)vnode->data)->rot[2];
+       rot.w = ((VObjectData*)vnode->data)->rot[3];
+
+/*     
+       quat[0] = ((VObjectData*)vnode->data)->rot[0];
+       quat[1] = ((VObjectData*)vnode->data)->rot[1];
+       quat[2] = ((VObjectData*)vnode->data)->rot[2];
+       quat[3] = ((VObjectData*)vnode->data)->rot[3];
+       
+       QuatToEul(quat, bvec);
+       vvec[0] = bvec[0];
+       vvec[1] = bvec[1];
+       vvec[2] = bvec[2];
+       EulToQuat(vvec, quat);
+
+       rot.x = quat[0];
+       rot.y = quat[1];
+       rot.z = quat[2];
+       rot.w = quat[3];
+*/
+       
+       ((VObjectData*)vnode->data)->flag &= ~ROT_SEND_READY;
+
+       verse_send_o_transform_rot_real32(
+                       vnode->id,      /* node id */
+                       0,              /* time_s ... no interpolation */
+                       0,              /* time_f ... no interpolation */
+                       &rot,
+                       NULL,           /* speed ... no interpolation */
+                       NULL,           /* accelerate  ... no interpolation */
+                       NULL,           /* drag normal ... no interpolation */
+                       0.0);           /* drag ... no interpolation */
+}
+
+/*
+ * send object rotation to verse server 
+ */
+void send_verse_object_scale(VNode *vnode)
+{
+       ((VObjectData*)vnode->data)->flag &= ~SCALE_SEND_READY;
+
+       verse_send_o_transform_scale_real32(
+                       vnode->id,
+                       ((VObjectData*)vnode->data)->scale[0],
+                       ((VObjectData*)vnode->data)->scale[2],
+                       ((VObjectData*)vnode->data)->scale[1]);
+}
+
+/*
+ * send VerseLink to verse server
+ */
+void send_verse_link(VLink *vlink)
+{
+       verse_session_set(vlink->session->vsession);
+
+       verse_send_o_link_set(
+                       vlink->source->id,
+                       vlink->id,
+                       vlink->target->id,
+                       vlink->label,
+                       vlink->target_id);
+}
+
+/*
+ * set up pointer at VerseLink of target node (geometry node, material node, etc.)
+ */
+static void set_target_node_link_pointer(VNode *vnode, VLink *vlink)
+{
+       switch (vnode->type) {
+               case V_NT_GEOMETRY:
+                       ((VGeomData*)vnode->data)->vlink = vlink;
+                       break;
+               default:
+                       break;
+       }
+}
+
+/*
+ * free VerseLink and it's label
+ */
+static void free_verse_link_data(VLink *vlink)
+{
+       MEM_freeN(vlink->label);
+}
+
+/*
+ * create new VerseLink
+ */
+VLink *create_verse_link(
+               VerseSession *session,
+               VNode *source,
+               VNode *target,
+               uint16 link_id,
+               uint32 target_id,
+               const char *label)
+{
+       struct VLink *vlink;
+
+       vlink = (VLink*)MEM_mallocN(sizeof(VLink), "VerseLink");
+       vlink->session = session;
+       vlink->source = source;
+       vlink->target = target;
+       vlink->id = link_id;
+       vlink->target_id = target_id;
+
+       set_target_node_link_pointer(target, vlink);
+
+       vlink->label = (char*)MEM_mallocN(sizeof(char)*(strlen(label)+1), "VerseLink label");
+       vlink->label[0] = '\0';
+       strcat(vlink->label, label);
+
+       vlink->flag = 0;
+
+       vlink->post_link_set = post_link_set;
+       vlink->post_link_destroy = post_link_destroy;
+
+       return vlink;
+}
+
+/*
+ * free ObjectData (links, links in queue and lables of links)
+ */
+void free_object_data(VNode *vnode)
+{
+       struct VerseSession *session = vnode->session;
+       struct VObjectData *obj = (VObjectData*)vnode->data;
+       struct VLink *vlink;
+
+       if(!obj) return;
+
+       /* free all labels of links in dlist */
+       vlink = obj->links.lb.first;
+       while(vlink){
+               free_verse_link_data(vlink);
+               vlink = vlink->next;
+       }
+
+       /* free all labels of links waiting in queue */
+       vlink = obj->queue.first;
+       while(vlink){
+               free_verse_link_data(vlink);
+               vlink = vlink->next;
+       }
+       /* free dynamic list and sendig queue of links */
+       BLI_dlist_destroy(&(obj->links));
+       BLI_freelistN(&(obj->queue));
+
+       /* free constraint between VerseNode and Object */
+       obj->post_object_free_constraint(vnode);
+
+       /* unsubscribe from receiving changes of transformation matrix */
+       if(session->flag & VERSE_CONNECTED)
+               verse_send_o_transform_unsubscribe(vnode->id, 0);
+}
+
+/*
+ * create new object data
+ */
+VObjectData *create_object_data(void)
+{
+       VObjectData *obj;
+
+       obj = (VObjectData*)MEM_mallocN(sizeof(VObjectData), "VerseObjectData");
+       obj->object = NULL;
+       BLI_dlist_init(&(obj->links));
+       obj->queue.first = obj->queue.last = NULL;
+       obj->flag = 0;
+
+       /* transformation matrix */
+       obj->pos[0] = obj->pos[1] = obj->pos[2] = 0.0;
+       obj->rot[0] = obj->rot[1] = obj->rot[2] = 0.0; obj->rot[3] = 1;
+       obj->scale[0] = obj->scale[1] = obj->scale[2] = 1.0;
+
+       /* transformation flags */
+       obj->flag |= POS_SEND_READY;
+       obj->flag |= ROT_SEND_READY;
+       obj->flag |= SCALE_SEND_READY;
+
+       /* set up pointers at post callback functions */
+       obj->post_transform = post_transform;
+       obj->post_object_free_constraint = post_object_free_constraint;
+
+       return obj;
+}
+
+/*
+ * callback function: 
+ */
+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)
+{
+       struct VerseSession *session = (VerseSession*)current_verse_session();
+       struct VNode *vnode;
+       float vec[3], dt, tmp;
+
+       if(!session) return;
+
+       vnode = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
+
+       ((VObjectData*)vnode->data)->flag |= POS_SEND_READY;
+
+       /* verse server sends automaticaly some stupid default values ...
+        * we have to ignore these values, when we created this object node */
+       if( (vnode->owner_id==VN_OWNER_MINE) && !(((VObjectData*)vnode->data)->flag & POS_RECEIVE_READY) ) {
+               ((VObjectData*)vnode->data)->flag |= POS_RECEIVE_READY;
+               return;
+       }
+
+       dt = time_s + time_f/(0xffff);
+
+       /* we have to flip z and y coordinates, because verse and blender use different axis
+        * orientation */
+       if(pos) {
+               vec[0] = pos[0];
+               vec[1] = pos[1];
+               vec[2] = pos[2];
+       }
+
+       if(speed) {
+               vec[0] += speed[0]*dt;
+               vec[1] += speed[1]*dt;
+               vec[2] += speed[2]*dt;
+       }
+
+       if(accelerate) {
+               vec[0] += accelerate[0]*dt*dt/2;
+               vec[1] += accelerate[1]*dt*dt/2;
+               vec[2] += accelerate[2]*dt*dt/2;
+       }
+
+       /* flip axis (due to verse spec) */
+       tmp = vec[1];
+       vec[1] = -vec[2];
+       vec[2] = tmp;
+
+       if( (((VObjectData*)vnode->data)->pos[0] != vec[0]) ||
+                       (((VObjectData*)vnode->data)->pos[1] != vec[1]) ||
+                       (((VObjectData*)vnode->data)->pos[2] != vec[2]))
+       {
+               ((VObjectData*)vnode->data)->pos[0] = vec[0];
+               ((VObjectData*)vnode->data)->pos[1] = vec[1];
+               ((VObjectData*)vnode->data)->pos[2] = vec[2];
+
+               ((VObjectData*)vnode->data)->post_transform(vnode);
+       }
+}
+
+/*
+ * callback function:
+ */
+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)
+{
+       struct VerseSession *session = (VerseSession*)current_verse_session();
+       struct VNode *vnode;
+       float quat[4]={0, 0, 0, 0}, dt;
+/*     float vvec[3], bvec[3];*/
+
+       if(!session) return;
+
+       vnode = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
+
+       ((VObjectData*)vnode->data)->flag |= ROT_SEND_READY;
+       
+       /* verse server sends automaticaly some stupid default values ...
+        * we have to ignore these values, when we created this object node */
+       if( (vnode->owner_id==VN_OWNER_MINE) && !(((VObjectData*)vnode->data)->flag & ROT_RECEIVE_READY) ) {
+               ((VObjectData*)vnode->data)->flag |= ROT_RECEIVE_READY;
+               return;
+       }
+
+       dt = time_s + time_f/(0xffff);
+
+       if(rot) {
+               quat[0] = rot->x;
+               quat[1] = rot->y;
+               quat[2] = rot->z;
+               quat[3] = rot->w;
+       }
+
+       if(speed) {
+               quat[0] += speed->x*dt;
+               quat[1] += speed->y*dt;
+               quat[2] += speed->z*dt;
+               quat[3] += speed->w*dt;
+       }
+
+       if(accelerate) {
+               quat[0] += accelerate->x*dt*dt/2;
+               quat[1] += accelerate->y*dt*dt/2;
+               quat[2] += accelerate->z*dt*dt/2;
+               quat[3] += accelerate->w*dt*dt/2;
+       }
+
+/*     QuatToEul(quat, vvec);
+       bvec[0] = vvec[0];
+       bvec[1] = vvec[1];
+       bvec[2] = vvec[2];
+       EulToQuat(bvec, 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]))
+       {
+               ((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];
+
+               ((VObjectData*)vnode->data)->post_transform(vnode);
+       }
+}
+
+/*
+ * callback function:
+ */
+static void cb_o_transform_scale_real32(
+               void *user_data,
+               VNodeID node_id,
+               real32 scale_x,
+               real32 scale_y,
+               real32 scale_z)
+{
+       struct VerseSession *session = (VerseSession*)current_verse_session();
+       struct VNode *vnode;
+       real32 tmp;
+
+       if(!session) return;
+
+       vnode = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
+
+       ((VObjectData*)vnode->data)->flag |= SCALE_SEND_READY;
+       
+       /* verse server sends automaticaly some stupid default values ...
+        * we have to ignore these values, when we created this object node */
+       if( (vnode->owner_id==VN_OWNER_MINE) && !(((VObjectData*)vnode->data)->flag & SCALE_RECEIVE_READY) ) {
+               ((VObjectData*)vnode->data)->flag |= SCALE_RECEIVE_READY;
+               return;
+       }
+
+       /* flip axis (verse spec) */
+       tmp = scale_y;
+       scale_y = scale_z;
+       scale_z = tmp;
+
+       /* z and y axis are flipped here too */
+       if( (((VObjectData*)vnode->data)->scale[0] != scale_x) ||
+                       (((VObjectData*)vnode->data)->scale[1] != scale_y) ||
+                       (((VObjectData*)vnode->data)->scale[2] != scale_z))
+       {
+               ((VObjectData*)vnode->data)->scale[0] = scale_x;
+               ((VObjectData*)vnode->data)->scale[1] = scale_y;
+               ((VObjectData*)vnode->data)->scale[2] = scale_z;
+
+               ((VObjectData*)vnode->data)->post_transform(vnode);
+       }
+}
+
+/*
+ * callback function: link between object node and some other node was created
+ */
+static void cb_o_link_set(
+               void *user_data,
+               VNodeID node_id,
+               uint16 link_id,
+               VNodeID link,
+               const char *label,
+               uint32 target_id)
+{
+       struct VLink *vlink;
+       struct VNode *source;
+       struct VNode *target;
+
+       struct VerseSession *session = (VerseSession*)current_verse_session();
+
+       if(!session) return;
+
+       source = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
+       target = BLI_dlist_find_link(&(session->nodes), (unsigned int)link);
+
+       if(!(source && target)) return;
+
+       vlink = ((VObjectData*)source->data)->queue.first;
+
+       if(vlink && (vlink->source==source) && (vlink->target==target)) {
+               /* remove VerseLink from sending queue */
+               BLI_remlink(&(((VObjectData*)source->data)->queue), vlink);
+               /* add VerseLink to dynamic list of VerseLinks */
+               BLI_dlist_add_item_index(&(((VObjectData*)source->data)->links), vlink, (unsigned int)link_id);
+               /* send next link from sending queue */
+               if(((VObjectData*)source->data)->queue.first)
+                       send_verse_link(((VObjectData*)source->data)->queue.first);
+               /* set up VerseLink variables */
+               vlink->flag = 0;
+               vlink->id = link_id;
+               vlink->target_id = target_id;
+       }
+       else {
+               /* create new VerseLink */
+               vlink = create_verse_link(session, source, target, link_id, target_id, label);
+               /* add VerseLink to dynamic list of VerseLinks */
+               BLI_dlist_add_item_index(&(((VObjectData*)source->data)->links), vlink, (unsigned int)link_id);
+       }
+
+       target->counter++;
+
+       vlink->post_link_set(vlink);
+}
+
+/*
+ * callback function: destroy link between two VerseNodes
+ */
+static void cb_o_link_destroy(
+               void *user_data,
+               VNodeID node_id,
+               uint16 link_id)
+{
+       struct VerseSession *session = (VerseSession*)current_verse_session();
+       struct VNode *vnode;
+       struct VLink *vlink;
+
+       if(!session) return;
+
+       vnode = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
+
+       vlink = BLI_dlist_find_link(&(((VObjectData*)vnode->data)->links), link_id);
+
+       if(vlink) {
+               vlink->target->counter--;
+               free_verse_link_data(vlink);
+               BLI_dlist_free_item(&(((VObjectData*)vnode->data)->links), link_id);
+       }
+
+       vlink->post_link_destroy(vlink);
+}
+
+void set_object_callbacks(void)
+{
+       /* position of object was changed */
+       verse_callback_set(verse_send_o_transform_pos_real32, cb_o_transform_pos_real32, NULL);
+       /* rotation of object was changed */
+       verse_callback_set(verse_send_o_transform_rot_real32, cb_o_transform_rot_real32, NULL);
+       /* size of object was changed  */
+       verse_callback_set(verse_send_o_transform_scale_real32, cb_o_transform_scale_real32, NULL);
+       /* new link between nodes was created */
+       verse_callback_set(verse_send_o_link_set, cb_o_link_set, NULL);
+       /* link between nodes was destroyed */
+       verse_callback_set(verse_send_o_link_destroy, cb_o_link_destroy, NULL);
+}
+
+#endif
diff --git a/source/blender/blenkernel/intern/verse_session.c b/source/blender/blenkernel/intern/verse_session.c
new file mode 100644 (file)
index 0000000..e6f16a9
--- /dev/null
@@ -0,0 +1,345 @@
+/**
+ * $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_mesh_types.h"    /* temp */
+#include "DNA_listBase.h"
+#include "DNA_screen_types.h"
+
+#include "BLI_dynamiclist.h"
+#include "BLI_blenlib.h"
+
+#include "BIF_verse.h"
+
+#include "BKE_global.h"        
+#include "BKE_verse.h"
+
+#include "verse.h"
+
+struct ListBase session_list={NULL, NULL};
+
+/* list of static function prototypes */
+static void cb_connect_terminate(const char *address, const char *bye);
+static void cb_connect_accept(void *user_data, uint32 avatar, void *address, void *connection, const uint8 *host_id);
+static void set_all_callbacks(void);
+static void free_verse_session_data(struct VerseSession *session);
+
+/*
+ * callback function for connection terminated
+ */
+static void cb_connect_terminate(const char *address, const char *bye)
+{
+       VerseSession *session = (VerseSession*)current_verse_session();
+
+       if(!session) return;
+
+       /* remove session from list of session */
+       BLI_remlink(&session_list, session);
+       /* do post connect operations */
+       session->post_connect_terminated(session);
+       /* free session data */
+       free_verse_session_data(session);
+       /* free session */
+       MEM_freeN(session);
+}
+
+/*
+ * callback function for accepted connection to verse server
+ */
+static void cb_connect_accept(
+               void *user_data,
+               uint32 avatar,
+               void *address,
+               void *connection,
+               const uint8 *host_id)
+{
+       struct VerseSession *session = (VerseSession*)current_verse_session();
+       uint32 i, mask=0;
+
+       if(!session) return;
+
+       session->flag |= VERSE_CONNECTED;
+       session->flag &= ~VERSE_CONNECTING;
+
+       printf("\tBlender was connected to verse server: %s\n", (char*)address);
+       printf("\tVerseSession->counter: %d\n", session->counter);
+
+       session->avatar = avatar;
+
+       session->post_connect_accept(session);
+
+       for(i = 0; i < V_NT_NUM_TYPES; i++)
+               mask = mask | (1 << i);
+       verse_send_node_index_subscribe(mask);
+}
+
+/*
+ * set up all callbacks for sessions
+ */
+void set_verse_session_callbacks(void)
+{
+       /* connection */
+       verse_callback_set(verse_send_connect_accept, cb_connect_accept, NULL);
+       /* connection was terminated */
+       verse_callback_set(verse_send_connect_terminate, cb_connect_terminate, NULL);
+}
+
+/*
+ * set all callbacks used in Blender
+ */
+static void set_all_callbacks(void)
+{
+       /* set up all callbacks for sessions */
+       set_verse_session_callbacks();
+
+       /* set up callbacks for nodes */
+       set_node_callbacks();
+
+       /* set up all callbacks for object nodes */
+       set_object_callbacks();
+
+       /* set up all callbacks for geometry nodes */
+       set_geometry_callbacks();
+
+       /* set up all callbacks for bitmap nodes */
+       set_bitmap_callbacks();
+}
+
+/*
+ * this function sends and receive all packets for all sessions
+ */
+void b_verse_update(void)
+{
+       VerseSession *session, *next_session;
+
+       session = session_list.first;
+       while(session){
+               next_session = session->next;
+               verse_session_set(session->vsession);
+               if((session->flag & VERSE_CONNECTED) || (session->flag & VERSE_CONNECTING)) {
+                       verse_callback_update(10);
+                       session->post_connect_update(session);
+               }
+               session = next_session;
+       }
+}
+
+/*
+ * returns VerseSession coresponding to vsession pointer
+ */
+VerseSession *versesession_from_vsession(VSession *vsession)
+{
+       struct VerseSession *session;
+
+       session = session_list.first;
+
+       while(session) {
+               if(session->vsession==vsession) return session;
+               session = session->next;
+       }
+       
+       return session;
+}
+
+/*
+ * returns pointer at current VerseSession
+ */
+VerseSession *current_verse_session(void)
+{
+       struct VerseSession *session;
+       VSession vsession = verse_session_get();
+
+       session = session_list.first;
+
+       while(session){
+               if(session->vsession == vsession)
+                       return session;
+               session = session->next;
+       }
+
+       printf("error: non-existing SESSION occured!\n");
+       return NULL;
+}
+
+/*
+ * free VerseSession
+ */
+static void free_verse_session_data(VerseSession *session)
+{
+       struct VNode *vnode;
+
+       /* free data of all nodes */
+       vnode = session->nodes.lb.first;
+       while(vnode){
+               free_verse_node_data(vnode);
+               vnode = vnode->next;
+       }
+
+       /* free data of nodes waiting in queue */
+       vnode = session->queue.first;
+       while(vnode){
+               free_verse_node_data(vnode);
+               vnode = vnode->next;
+       }
+
+       /* free all VerseNodes */
+       BLI_dlist_destroy(&(session->nodes));
+       /* free all VerseNodes waiting in queque */
+       BLI_freelistN(&(session->queue));
+
+       /* free name of verse host for this session */
+       MEM_freeN(session->address);
+}
+
+/*
+ * free VerseSession
+ */
+void free_verse_session(VerseSession *session)
+{
+       /* remove session from session list*/
+       BLI_remlink(&session_list, session);
+       /* do post terminated operations */
+       session->post_connect_terminated(session);
+       /* free session data (nodes, layers) */
+       free_verse_session_data(session);
+       /* free session */
+       MEM_freeN(session);
+}
+
+/*
+ * create new verse session and return coresponding data structure
+ */
+VerseSession *create_verse_session(
+               const char *name,
+               const char *pass,
+               const char *address,
+               uint8 *expected_key)
+{
+       struct VerseSession *session;
+       VSession *vsession;
+       
+       vsession = verse_send_connect(name, pass, address, expected_key);
+
+       if(!vsession) return NULL;
+
+       session = (VerseSession*)MEM_mallocN(sizeof(VerseSession), "VerseSession");
+
+       session->flag = VERSE_CONNECTING;
+
+       session->vsession = vsession;
+       session->avatar = -1;
+
+       session->address = (char*)MEM_mallocN(sizeof(char)*(strlen(address)+1),"session adress name");
+       strcpy(session->address, address);
+
+       session->connection = NULL;
+       session->host_id = NULL;
+       session->counter = 0;
+
+       /* initialize dynamic list of nodes and node queue */
+       BLI_dlist_init(&(session->nodes));
+       session->queue.first = session->queue.last = NULL;
+
+       /* set up all client dependent functions */
+       session->post_connect_accept = post_connect_accept;
+       session->post_connect_terminated = post_connect_terminated;
+       session->post_connect_update = post_connect_update;
+
+       return session;
+}
+
+/*
+ * end verse session and free all session data
+ */
+void end_verse_session(VerseSession *session, char free)
+{
+       /* send terminate command to verse server */
+       verse_send_connect_terminate(session->address, "blender: bye bye");
+       /* update callbacks */
+       verse_callback_update(1000);
+       /* send destroy session command to verse server */
+       verse_session_destroy(session->vsession);
+       /* set up flag of verse session */
+       session->flag &= ~VERSE_CONNECTED;
+       /* do post connect operations */
+       session->post_connect_terminated(session);
+       /* free session data */
+       free_verse_session_data(session);
+       /* free structure of verse session */
+       if(free) free_verse_session(session);
+}
+
+/*
+ * end connection to all verse hosts (servers) ... free all VerseSessions
+ */
+void end_all_verse_sessions(void)
+{
+       VerseSession *session;
+
+       session = session_list.first;
+
+       while(session) {
+               end_verse_session(session, 0);
+               /* end next session */
+               session = session->next;
+       }
+
+       BLI_freelistN(&session_list);
+}
+
+/*
+ * connect to verse host, set up all callbacks, create session
+ */
+void b_verse_connect(char *address)
+{
+       VerseSession *session;
+
+       /* if no session was created before, then set up all callbacks */
+       if((session_list.first==NULL) && (session_list.last==NULL))
+               set_all_callbacks();
+
+       /* create new session */
+       if(address)
+               session = create_verse_session("Blender", "pass", address, NULL);
+
+       if(session) {
+               /* add new session to the list of sessions */
+               BLI_addtail(&session_list, session);
+
+               /* add verse handler if this is first session */
+               if(session_list.first == session_list.last)
+                       add_screenhandler(G.curscreen, SCREEN_HANDLER_VERSE, 1);
+
+       }
+}
+
+#endif
index d26afbc350c238e4da31790668776344a503ade3..564b250da81bdba0d39a845bc3c5a78fd9f16d2b 100644 (file)
@@ -84,6 +84,7 @@ struct rcti;
 struct EditVert;
 struct PackedFile;
 struct LinkNode;
+struct DynamicList;
 
 #ifdef __cplusplus
 extern "C" {
@@ -112,6 +113,17 @@ int BLI_countlist(struct ListBase *listbase);
 void BLI_freelinkN(ListBase *listbase, void *vlink);
 void BLI_splitdirstring(char *di,char *fi);
 
+struct DynamicList *BLI_dlist_from_listbase(struct ListBase *lb);
+struct ListBase *BLI_listbase_from_dlist(struct DynamicList *dlist, struct ListBase *lb);
+void * BLI_dlist_find_link(struct DynamicList *dlist, unsigned int index);
+unsigned int BLI_count_items(struct DynamicList *dlist);
+void BLI_dlist_free_item(struct DynamicList *dlist, unsigned int index);
+void BLI_dlist_rem_item(struct DynamicList *dlist, unsigned int index);
+void * BLI_dlist_add_item_index(struct DynamicList *dlist, void *item, unsigned int index);
+void BLI_dlist_destroy(struct DynamicList *dlist);
+void BLI_dlist_init(struct DynamicList *dlist);
+void BLI_dlist_reinit(struct DynamicList *dlist);
+
        /**
         * dir can be any input, like from buttons, and this function
         * converts it to a regular full path.
diff --git a/source/blender/blenlib/BLI_dynamiclist.h b/source/blender/blenlib/BLI_dynamiclist.h
new file mode 100644 (file)
index 0000000..89e2774
--- /dev/null
@@ -0,0 +1,58 @@
+/**
+ * $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.
+ *
+ * Documentation of Two way dynamic list with access array can be found at:
+ *
+ * http://wiki.blender.org/bin/view.pl/Blenderwiki/DynamicListWithAccessArray
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef B_DYNAMIC_LIST_H
+#define B_DYNAMIC_LIST_H
+
+#define PAGE_SIZE 4
+
+struct ListBase;
+
+/*
+ * Access array using realloc 
+ */
+typedef struct DynamicArray{
+       unsigned int count;             /* count of items in list */
+       unsigned int max_item_index;    /* max available index */
+       unsigned int last_item_index;   /* max used index */
+       void **items;                   /* dynamicaly allocated array of pointers
+                                          pointing at items in list */
+} DynamicArray;
+
+/*
+ * Two way dynamic list with access array
+ */
+typedef struct DynamicList {
+       struct DynamicArray da;         /* access array */
+       struct ListBase lb;             /* two way linked dynamic list */
+} DynamicList;
+
+#endif
index 3dc6ebadb71df0c112158196d5c3447971d64b7f..2c8df6efd4364851fc981d1445f8a79ddb0cf1d6 100644 (file)
@@ -68,6 +68,9 @@ typedef struct EditVert
        int hash;
        struct MDeformWeight *dw;       /* __NLA a pointer to an array of defirm weights */
        int keyindex; /* original index #, for restoring  key information */
+/*#ifdef WITH_VERSE*/
+       void *vvert;
+/*#endif*/
 } EditVert;
 
 struct EditEdge;
@@ -124,6 +127,9 @@ typedef struct EditFace
        unsigned char f, f1, h;
        unsigned char fast;                     /* only 0 or 1, for editmesh_fastmalloc */
        unsigned char fgonf;            /* flag for fgon options */
+/*#ifdef WITH_VERSE*/
+       void *vface;
+/*#endif*/
 } EditFace;
 
 
@@ -154,6 +160,10 @@ typedef struct EditMesh
                 * to derived final, care should be taken on release.
                 */
        struct DerivedMesh *derivedCage, *derivedFinal;
+
+#ifdef WITH_VERSE
+       void *vnode;
+#endif
 } EditMesh;
 
 #endif
index c559761fb3229a6648d33c702149274559df6ffe..1ef9c5c8cdab03e64d866028fdfcb474ea584c76 100644 (file)
@@ -47,6 +47,7 @@
 #include "DNA_listBase.h"
 #include "BLI_storage.h"
 #include "BLI_storage_types.h"
+#include "BLI_dynamiclist.h"
 
 #include "BLI_util.h"
 
@@ -403,6 +404,228 @@ void * BLI_findlink(ListBase *listbase, int number)
        return (link);
 }
 
+/*=====================================================================================*/
+/* Methods for access array (realloc) */
+/*=====================================================================================*/
+
+/* remove item with index */
+static void rem_array_item(struct DynamicArray *da, unsigned int index)
+{
+       da->items[index]=NULL;
+       da->count--;
+       if(index==da->last_item_index){
+               while((!da->items[da->last_item_index]) && (da->last_item_index>0)){
+                       da->last_item_index--;
+               }
+       }
+}
+
+/* add array (if needed, then realloc) */
+static void add_array_item(struct DynamicArray *da, void *item, unsigned int index)
+{
+       /* realloc of access array */
+       if(da->max_item_index < index){
+               unsigned int i, max = da->max_item_index;
+               void **nitems;
+
+               do {
+                       da->max_item_index += PAGE_SIZE;        /* OS can allocate only PAGE_SIZE Bytes */
+               } while(da->max_item_index<=index);
+
+               nitems = (void**)MEM_mallocN(sizeof(void*)*(da->max_item_index+1), "dlist access array");
+               for(i=0;i<=max;i++)
+                       nitems[i] = da->items[i];
+
+               /* set rest pointers to the NULL */
+               for(i=max+1; i<=da->max_item_index; i++)
+                       nitems[i]=NULL;
+
+               MEM_freeN(da->items);           /* free old access array */
+               da->items = nitems;
+       }
+
+       da->items[index] = item;
+       da->count++;
+       if(index > da->last_item_index) da->last_item_index = index;
+}
+
+/* free access array */
+static void destroy_array(DynamicArray *da)
+{
+       da->count=0;
+       da->last_item_index=0;
+       da->max_item_index=0;
+       MEM_freeN(da->items);
+       da->items = NULL;
+}
+
+/* initialize dynamic array */
+static void init_array(DynamicArray *da)
+{
+       unsigned int i;
+
+       da->count=0;
+       da->last_item_index=0;
+       da->max_item_index = PAGE_SIZE-1;
+       da->items = (void*)MEM_mallocN(sizeof(void*)*(da->max_item_index+1), "dlist access array");
+       for(i=0; i<=da->max_item_index; i++) da->items[i]=NULL;
+}
+
+/* reinitialize dynamic array */
+static void reinit_array(DynamicArray *da)
+{
+       destroy_array(da);
+       init_array(da);
+}
+
+/*=====================================================================================*/
+/* Methods for two way dynamic list with access array */
+/*=====================================================================================*/
+
+/* create new two way dynamic list with access array from two way dynamic list
+ * it doesn't copy any items to new array or something like this It is strongly
+ * recomended to use BLI_dlist_ methods for adding/removing items from dynamic list
+ * unless you can end with inconsistence system !!! */
+DynamicList *BLI_dlist_from_listbase(ListBase *lb)
+{
+       DynamicList *dlist;
+       Link *item;
+       int i=0, count;
+       
+       if(!lb) return NULL;
+       
+       count = BLI_countlist(lb);
+
+       dlist = MEM_mallocN(sizeof(DynamicList), "temp dynamic list");
+       /* ListBase stuff */
+       dlist->lb.first = lb->first;
+       dlist->lb.last = lb->last;
+       /* access array stuff */
+       dlist->da.count=count;
+       dlist->da.max_item_index = count-1;
+       dlist->da.last_item_index = count -1;
+       dlist->da.items = (void*)MEM_mallocN(sizeof(void*)*count, "temp dlist access array");
+
+       item = (Link*)lb->first;
+       while(item){
+               dlist->da.items[i] = (void*)item;
+               item = item->next;
+               i++;
+       }
+
+       /* to prevent you of using original ListBase :-) */
+       lb->first = lb->last = NULL;
+
+       return dlist;
+}
+
+/* take out ListBase from DynamicList and destroy all temporary structures of DynamicList */
+ListBase *BLI_listbase_from_dlist(DynamicList *dlist, ListBase *lb)
+{
+       if(!dlist) return NULL;
+
+       if(!lb) lb = (ListBase*)MEM_mallocN(sizeof(ListBase), "ListBase");
+       
+       lb->first = dlist->lb.first;
+       lb->last = dlist->lb.last;
+
+       /* free all items of access array */
+       MEM_freeN(dlist->da.items);
+       /* free DynamicList*/
+       MEM_freeN(dlist);
+
+       return lb;
+}
+
+/* return pointer at item from th dynamic list with access array */
+void *BLI_dlist_find_link(DynamicList *dlist, unsigned int index)
+{
+       if(!dlist || !dlist->da.items) return NULL;
+
+       if((index <= dlist->da.last_item_index) && (index >= 0) && (dlist->da.count>0)){
+               return dlist->da.items[index];
+       }
+       else {
+               return NULL;
+       }
+}
+
+/* return count of items in the dynamic list with access array */
+unsigned int BLI_count_items(DynamicList *dlist)
+{
+       if(!dlist) return 0;
+
+       return dlist->da.count;
+}
+
+/* free item from the dynamic list with access array */
+void BLI_dlist_free_item(DynamicList *dlist, unsigned int index)
+{
+       if(!dlist || !dlist->da.items) return;
+       
+       if((index <= dlist->da.last_item_index) && (dlist->da.items[index])){
+               BLI_freelinkN(&(dlist->lb), dlist->da.items[index]);
+               rem_array_item(&(dlist->da), index);
+       }
+}
+
+/* remove item from the dynamic list with access array */
+void BLI_dlist_rem_item(DynamicList *dlist, unsigned int index)
+{
+       if(!dlist || !dlist->da.items) return;
+       
+       if((index <= dlist->da.last_item_index) && (dlist->da.items[index])){
+               BLI_remlink(&(dlist->lb), dlist->da.items[index]);
+               rem_array_item(&(dlist->da), index);
+       }
+}
+
+/* add item to the dynamic list with access array (index) */
+void* BLI_dlist_add_item_index(DynamicList *dlist, void *item, unsigned int index)
+{
+       if(!dlist || !dlist->da.items) return NULL;
+
+       if((index <= dlist->da.max_item_index) && (dlist->da.items[index])) {
+               /* you can't place item at used index */
+               return NULL;
+       }
+       else {
+               add_array_item(&(dlist->da), item, index);
+               BLI_addtail(&(dlist->lb), item);
+               return item;
+       }
+}
+
+/* destroy dynamic list with access array */
+void BLI_dlist_destroy(DynamicList *dlist)
+{
+       if(!dlist) return;
+
+       BLI_freelistN(&(dlist->lb));
+       destroy_array(&(dlist->da));
+}
+
+/* initialize dynamic list with access array */
+void BLI_dlist_init(DynamicList *dlist)
+{
+       if(!dlist) return;
+
+       dlist->lb.first = NULL;
+       dlist->lb.last = NULL;
+
+       init_array(&(dlist->da));
+}
+
+/* reinitialize dynamic list with acces array */
+void BLI_dlist_reinit(DynamicList *dlist)
+{
+       if(!dlist) return;
+       
+       BLI_freelistN(&(dlist->lb));
+       reinit_array(&(dlist->da));
+}
+
+/*=====================================================================================*/
 
 char *BLI_strdupn(char *str, int len) {
        char *n= MEM_mallocN(len+1, "strdup");
index 9faeb42879fb7ca8a7b2594aa87ade6a8970d817..86ccd607d63e024d446fff668531645e2777252b 100644 (file)
@@ -51,6 +51,11 @@ ifeq ($(OS),$(findstring $(OS), "solaris windows"))
     CPPFLAGS += -I$(NAN_ZLIB)/include
 endif
 
+ifeq ($(WITH_VERSE), true)
+    CPPFLAGS += -DWITH_VERSE
+    CPPFLAGS += -I$(NAN_VERSE)/include
+endif
+
 # streaming write function
 CPPFLAGS += -I../../writestreamglue
 CPPFLAGS += -I../../readstreamglue
index 557c553d0fd0b14af3b9f3c99fa49bc56a56d375..7156b6ffcabf2eb3e953fa0f6a70c9ed866d7a53 100644 (file)
@@ -164,6 +164,10 @@ Important to know is that 'streaming' has been added to files, for Blender Publi
 #include "BKE_sound.h" /* ... and for samples */
 #include "BKE_utildefines.h" // for defines
 #include "BKE_modifier.h"
+#ifdef WITH_VERSE
+#include "BKE_verse.h"
+#include "BIF_verse.h"
+#endif
 
 #include "GEN_messaging.h"
 
@@ -745,7 +749,15 @@ static void write_objects(WriteData *wd, ListBase *idbase)
        while(ob) {
                if(ob->id.us>0 || wd->current) {
                        /* write LibData */
+#ifdef WITH_VERSE
+                       /* pointer at vnode stored in file have to be NULL */
+                       struct VNode *vnode = (VNode*)ob->vnode;
+                       if(vnode) ob->vnode = NULL;
+#endif
                        writestruct(wd, ID_OB, "Object", 1, ob);
+#ifdef WITH_VERSE
+                       if(vnode) ob->vnode = (void*)vnode;
+#endif
 
                        /* direct data */
                        writedata(wd, DATA, sizeof(void *)*ob->totcol, ob->mat);
@@ -987,7 +999,19 @@ static void write_meshs(WriteData *wd, ListBase *idbase)
        while(mesh) {
                if(mesh->id.us>0 || wd->current) {
                        /* write LibData */
+#ifdef WITH_VERSE
+                       struct VNode *vnode = (VNode*)mesh->vnode;
+                       if(vnode) {
+                               /* mesh has to be created from verse geometry node*/
+                               create_meshdata_from_geom_node(mesh, vnode);
+                               /* pointer at verse node can't be stored in file */
+                               mesh->vnode = NULL;
+                       }
+#endif
                        writestruct(wd, ID_ME, "Mesh", 1, mesh);
+#ifdef WITH_VERSE
+                       if(vnode) mesh->vnode = (void*)vnode;
+#endif
 
                        /* direct data */
                        writedata(wd, DATA, sizeof(void *)*mesh->totcol, mesh->mat);
index 442247864b535585935dad2e00a463793d91503b..539ee055dba4b099830f63229645b9eadb1f2c1b 100644 (file)
@@ -66,6 +66,11 @@ typedef struct TreeElement {
 #define TSE_SCRIPT_BASE                12
 #define TSE_POSE_BASE          13
 #define TSE_POSE_CHANNEL       14
+/*#ifdef WITH_VERSE*/
+#define TSE_VERSE_SESSION      15
+#define TSE_VERSE_OBJ_NODE     16
+#define TSE_VERSE_GEOM_NODE    17
+/*#endif*/
 
 /* button events */
 #define OL_NAMEBUTTON          1
diff --git a/source/blender/include/BIF_verse.h b/source/blender/include/BIF_verse.h
new file mode 100644 (file)
index 0000000..7dada3f
--- /dev/null
@@ -0,0 +1,134 @@
+/**
+ * $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
+
+#ifndef BIF_VERSE_H
+#define BIF_VERSE_H
+
+#include "BKE_verse.h"
+#include "DNA_meshdata_types.h"
+
+struct Object;
+
+struct EditVert;
+struct EditFace;
+struct MVert;
+struct Mface;
+
+/* verse_object.c */
+void unsubscribe_from_obj_node(struct VNode *vnode);
+void unsubscribe_from_geom_node(struct VNode *vnode);
+void unsubscribe_from_bitmap_node(struct VNode *vnode);
+
+void test_and_send_idbutton_cb(void *obj, void *ob_name);
+
+struct Object *create_object_from_verse_node(struct VNode *vnode);
+
+void b_verse_pop_node(struct VNode *vnode);
+void b_verse_unsubscribe(VNode *vnode);
+void b_verse_push_object(struct VerseSession *session, struct Object *ob);
+void b_verse_delete_object(struct Object *ob);
+
+void post_transform(struct VNode *vnode);
+void post_link_set(struct VLink *vlink);
+void post_link_destroy(struct VLink *vlink);
+void post_object_free_constraint(struct VNode *vnode);
+
+void b_verse_send_transformation(struct Object *ob);
+
+/* verse_mesh.c */
+void b_verse_send_vertex_delete(struct EditVert *eve);
+void send_versevert_pos(struct VerseVert *vvert);
+
+void b_verse_send_face_delete(struct EditFace *efa);
+
+void sync_all_versefaces_with_editfaces(struct VNode *vnode);
+void sync_all_verseverts_with_editverts(struct VNode *vnode);
+
+void createVerseVert(struct EditVert *ev);
+void createVerseFace(struct EditFace *efa);
+
+void b_verse_duplicate_object(struct VerseSession *session, struct Object *ob, struct Object *n_ob);
+struct VNode *create_geom_vnode_from_geom_vnode(struct VNode *vnode);
+struct VNode *create_geom_vnode_data_from_editmesh(struct VerseSession *session, struct EditMesh *em);
+struct VNode *create_geom_vnode_data_from_mesh(struct VerseSession *session, struct Mesh *me);
+
+void destroy_unused_geometry(struct VNode *vnode);
+void destroy_binding_between_versemesh_and_editmesh(struct VNode *vnode);
+
+void destroy_verse_mesh(struct VNode *vnode);
+
+void unsubscribe_from_geom_node(struct VNode *vnode);
+
+void create_edit_mesh_from_geom_node(struct VNode *vnode);
+struct Mesh *create_mesh_from_geom_node(struct VNode *vnode);
+void create_meshdata_from_geom_node(struct Mesh *me, struct VNode *vnode);
+
+/* geometry post callback functions */
+void post_layer_create(struct VLayer *vlayer);
+void post_layer_destroy(struct VLayer *vlayer);
+
+void post_vertex_create(struct VerseVert *vvert);
+void post_vertex_set_xyz(struct VerseVert *vvert);
+void post_vertex_delete(struct VerseVert *vvert);
+void post_vertex_free_constraint(struct VerseVert *vvert);
+
+void post_polygon_set_uint8(struct VerseFace *vface);
+void post_polygon_create(struct VerseFace *vface);
+void post_polygon_set_corner(struct VerseFace *vface);
+void post_polygon_delete(struct VerseFace *vface);
+void post_polygon_free_constraint(struct VerseFace *vface);
+
+void post_geometry_free_constraint(struct VNode *vnode);
+
+/* verse_common.c */
+struct VerseSession *session_menu(void);
+char *verse_client_name(void);
+
+void post_tag_change(struct VTag *vtag);
+void post_taggroup_create(struct VTagGroup *vtaggroup);
+
+void post_node_create(struct VNode *vnode);
+void post_node_destroy(struct VNode *vnode);
+void post_node_name_set(struct VNode *vnode);
+
+void post_connect_accept(struct VerseSession *session);
+void post_connect_terminated(struct VerseSession *session);
+void post_connect_update(struct VerseSession *session);
+
+/* verse_image.c */
+
+void sync_blender_image_with_verse_bitmap_node(struct VNode *vnode);
+void post_bitmap_dimension_set(struct VNode *vnode);
+void post_bitmap_layer_create(struct VBitmapLayer *vblayer);
+void post_bitmap_layer_destroy(struct VBitmapLayer *vblayer);
+void post_bitmap_tile_set(struct VBitmapLayer *vblayer, unsigned int xs, unsigned int ys);
+
+#endif
+
+#endif
index c7cc268de19e54898c6395acd5aa0272bfe47638..ddbbfbd802f4e39152f329e152109eea28b6f02b 100644 (file)
@@ -89,6 +89,9 @@
 
 #define SELECT                 1
 #define ACTIVE                 2
+/*#ifdef WITH_VERSE*/
+#define VERSE                  3
+/*#endif*/
 #define DESELECT               0
 #define NOT_YET                        0
 
index c17d920693f917552eb872309c4fcbd79dbd071b..ec55b768381c14315ba04d8d91f2387d1721a599 100755 (executable)
@@ -128,6 +128,9 @@ typedef struct TransData {
        void *tdmir;             /* mirrored element pointer, in editmode mesh to EditVert */
     short  flag;         /* Various flags */
        short  protectflag;      /* If set, copy of Object or PoseChannel protection */
+/*#ifdef WITH_VERSE*/
+       void *verse;                    /* pointer at verse data struct (VerseVert, etc.) */
+/*#endif*/
 } TransData;
 
 typedef struct TransInfo {
@@ -232,6 +235,10 @@ typedef struct TransInfo {
 #define        TD_USEQUAT                      4
 #define TD_NOTCONNECTED                8
 #define TD_SINGLESIZE          16      /* used for scaling of MetaElem->rad */
+#ifdef WITH_VERSE
+#define TD_VERSE_OBJECT                32
+#define TD_VERSE_VERT          64
+#endif
 
 void checkFirstTime(void);
 
index f9a824eec2731ecabbc472ed7b4b1eaca4c84e0f..847f71231501d09ba7ae137352c702c3a8ed1001 100644 (file)
@@ -140,6 +140,11 @@ typedef struct Library {
                        /* used in outliner... */
 #define ID_NLA         MAKE_ID2('N', 'L')
 
+/*#ifdef WITH_VERSE*/
+#define ID_VS          MAKE_ID2('V', 'S')      /* fake id for VerseSession, needed for outliner */
+#define ID_VN          MAKE_ID2('V', 'N')      /* fake id for VerseNode, needed for outliner */
+/*#endif*/
+
 
 /* id->flag: set frist 8 bits always at zero while reading */
 #define LIB_LOCAL              0
index da8787d05abc609326acfe693340c3582ce8286a..ad8b3daf6576afbdcc9ea3735374dcbc22a9fcc8 100644 (file)
@@ -73,6 +73,9 @@ typedef struct Image {
        short animspeed;
        short reserved1;
        int   reserved2;
+/*#ifdef WITH_VERSE*/
+       void *vnode;            /* pointer at verse bitmap node */
+/*#endif*/
 } Image;
 
 /*  in Image struct */
index 6f477e963c67bdbe8e0e3f2f07f5fe9ee7047332..a57791be06d3ad51e53fc40bf27157f55eff9d46 100644 (file)
@@ -99,6 +99,10 @@ typedef struct Mesh {
        short totcol;
        short subsurftype; 
 
+/*ifdef WITH_VERSE*/
+       /* not written in file, pointer at geometry VerseNode */
+       void *vnode;
+/*#endif*/
 } Mesh;
 
 
index e8573f3da4a6e45a2e5beb14acee06b5aefaffee..9cdb505449323cc8d13c754d991901703f1d63b0 100644 (file)
@@ -201,6 +201,10 @@ typedef struct Object {
        struct FluidsimSettings *fluidsimSettings; /* if fluidsim enabled, store additional settings */
   
        struct DerivedMesh *derivedDeform, *derivedFinal;
+
+/*#ifdef WITH_VERSE*/
+       void *vnode;                    /* pointer at object VerseNode */
+/*#endif*/
 } Object;
 
 typedef struct ObHook {
index 3bfb17dc5866ada426dfd3b9f8d61ca7dabb3df6..fd92c412736a0186edc194659dad8444023f20e3 100644 (file)
@@ -123,6 +123,15 @@ ifeq ($(INTERNATIONAL), true)
     CPPFLAGS += -DINTERNATIONAL
 endif
 
+ifeq ($(WITH_VERSE), true)
+   CPPFLAGS += -DWITH_VERSE
+   CPPFLAGS += -I$(NAN_VERSE)/include
+   # print some other debug information
+   ifeq ($(VERSE_DEBUG_PRINT), true)
+       CPPFLAGS += -DVERSE_DEBUG_PRINT
+   endif
+endif
+
 ifeq ($(NAN_TWEAK_MODE), true)
     CPPFLAGS += -DTWEAK_MODE
 endif
index 36280938da9c47071c63f39e0afcaac54d416570..baa3d27be90f553013dc8cb3ecc888ad5ac42a6a 100644 (file)
 #include "BIF_previewrender.h"
 #include "BIF_butspace.h"
 
+#ifdef WITH_VERSE
+#include "BIF_verse.h"
+#endif
+
 #include "mydevice.h"
 #include "blendef.h"
 
@@ -3499,6 +3503,10 @@ static void editing_panel_mesh_tools1(Object *ob, Mesh *me)
        
        /* Measurement drawing options */
        uiBlockBeginAlign(block);
+#ifdef WITH_VERSE
+       if(G.editMesh->vnode)
+               uiDefButBitI(block, TOG, G_DRAW_VERSE_DEBUG, REDRAWVIEW3D, "Draw VDebug",1125,132,150,19, &G.f, 0, 0, 0, 0, "Displays verse debug information");
+#endif
        uiDefButBitI(block, TOG, G_DRAW_VNORMALS, REDRAWVIEW3D, "Draw VNormals",1125,110,150,19, &G.f, 0, 0, 0, 0, "Displays vertex normals as lines");
        uiDefButBitI(block, TOG, G_DRAW_EDGELEN, REDRAWVIEW3D, "Edge Length",   1125,88,150,19, &G.f, 0, 0, 0, 0, "Displays selected edge lengths");
        uiDefButBitI(block, TOG, G_DRAW_EDGEANG, REDRAWVIEW3D, "Edge Angles",   1125,66,150,19,  &G.f, 0, 0, 0, 0, "Displays the angles in the selected edges in degrees");
@@ -3608,7 +3616,13 @@ static void editing_panel_links(Object *ob)
        }
        if(ob) {
                but = uiDefBut(block, TEX, B_IDNAME, "OB:",     xco, 180, 454-xco, YIC, ob->id.name+2, 0.0, 19.0, 0, 0, "Displays Active Object name. Click to change.");
+#ifdef WITH_VERSE
+               if(ob->vnode) uiButSetFunc(but, test_and_send_idbutton_cb, ob, ob->id.name);
+               else uiButSetFunc(but, test_idbutton_cb, ob->id.name, NULL);
+#else
                uiButSetFunc(but, test_idbutton_cb, ob->id.name, NULL);
+#endif
+
        }
 
 
index c4f11a577c00ffe161cd5bbb47a0745d8dd17db7..6bb70a42b96906c55bd3a28a9e8909c235924b94 100644 (file)
@@ -92,6 +92,9 @@
 #include "BKE_mball.h"
 #include "BKE_object.h"
 #include "BKE_anim.h"                  //for the where_on_path function
+#ifdef WITH_VERSE
+#include "BKE_verse.h"
+#endif
 
 #include "BIF_gl.h"
 #include "BIF_glutil.h"
@@ -325,7 +328,13 @@ static void drawcentercircle(float *vec, int selstate, int special_color)
        glEnable(GL_BLEND);
        
        if(special_color) {
+#ifdef WITH_VERSE
+               if (selstate==VERSE) glColor4ub(0x00, 0xFF, 0x00, 155);
+               else if (selstate==ACTIVE || selstate==SELECT) glColor4ub(0x88, 0xFF, 0xFF, 155);
+#else
                if (selstate==ACTIVE || selstate==SELECT) glColor4ub(0x88, 0xFF, 0xFF, 155);
+#endif
+
                else glColor4ub(0x55, 0xCC, 0xCC, 155);
        }
        else {
@@ -1506,6 +1515,71 @@ static void draw_em_fancy_edges(DerivedMesh *cageDM)
        }
 }      
 
+#ifdef WITH_VERSE
+/*
+ * draw some debug info about verse mesh (vertex indexes,
+ * face indexes, status of )
+ */
+static draw_verse_debug(Object *ob, EditMesh *em)
+{
+       struct EditVert *eve=NULL;
+       struct EditFace *efa=NULL;
+       float v1[3], v2[3], v3[3], v4[3], fvec[3], col[3];
+       char val[32];
+       
+       if(G.vd->zbuf && (G.vd->flag & V3D_ZBUF_SELECT)==0)
+               glDisable(GL_DEPTH_TEST);
+
+       if(G.vd->zbuf) bglPolygonOffset(5.0);
+
+       BIF_GetThemeColor3fv(TH_TEXT, col);
+       /* make color a bit more red */
+       if(col[0]> 0.5) {col[1]*=0.7; col[2]*= 0.7;}
+       else col[0]= col[0]*0.7 + 0.3;
+       glColor3fv(col);
+
+       /* draw IDs of verse vertexes */
+       for(eve = em->verts.first; eve; eve = eve->next) {
+               if(eve->vvert) {
+                       VecLerpf(fvec, ob->loc, eve->co, 1.1);
+                       glRasterPos3f(fvec[0], fvec[1], fvec[2]);
+
+                       sprintf(val, "%d", ((VerseVert*)eve->vvert)->id);
+                       BMF_DrawString(G.fonts, val);
+               }
+       }
+
+       /* draw IDs of verse faces */
+       for(efa = em->faces.first; efa; efa = efa->next) {
+               if(efa->vface) {
+                       VECCOPY(v1, efa->v1->co);
+                       VECCOPY(v2, efa->v2->co);
+                       VECCOPY(v3, efa->v3->co);
+                       if(efa->v4) {
+                               VECCOPY(v4, efa->v4->co);
+                               glRasterPos3f(0.25*(v1[0]+v2[0]+v3[0]+v4[0]),
+                                               0.25*(v1[1]+v2[1]+v3[1]+v4[1]),
+                                               0.25*(v1[2]+v2[2]+v3[2]+v4[2]));
+                       }
+                       else {
+                               glRasterPos3f((v1[0]+v2[0]+v3[0])/3,
+                                               (v1[1]+v2[1]+v3[1])/3,
+                                               (v1[2]+v2[2]+v3[2])/3);
+                       }
+                       
+                       sprintf(val, "%d", ((VerseFace*)efa->vface)->id);
+                       BMF_DrawString(G.fonts, val);
+                       
+               }
+       }
+       
+       if(G.vd->zbuf) {
+               glEnable(GL_DEPTH_TEST);
+               bglPolygonOffset(0.0);
+       }
+}
+#endif
+
 static void draw_em_measure_stats(Object *ob, EditMesh *em)
 {
        EditEdge *eed;
@@ -1760,6 +1834,10 @@ static void draw_em_fancy(Object *ob, EditMesh *em, DerivedMesh *cageDM, Derived
 
                if(G.f & (G_DRAW_EDGELEN|G_DRAW_FACEAREA|G_DRAW_EDGEANG))
                        draw_em_measure_stats(ob, em);
+#ifdef WITH_VERSE
+               if(em->vnode && (G.f & G_DRAW_VERSE_DEBUG))
+                       draw_verse_debug(ob, em);
+#endif
        }
 
        if(dt>OB_WIRE) {
@@ -1808,8 +1886,31 @@ static void draw_mesh_fancy(Base *base, DerivedMesh *baseDM, DerivedMesh *dm, in
        Material *ma= give_current_material(ob, 1);
        int hasHaloMat = (ma && (ma->mode&MA_HALO));
        int draw_wire = ob->dtx&OB_DRAWWIRE;
+       int totvert, totedge, totface;
        DispList *dl;
 
+#ifdef WITH_VERSE
+       if(me->vnode) {
+               struct VNode *vnode = (VNode*)me->vnode;
+               struct VLayer *vert_vlayer = find_verse_layer_type((VGeomData*)vnode->data, VERTEX_LAYER);
+               struct VLayer *face_vlayer = find_verse_layer_type((VGeomData*)vnode->data, POLYGON_LAYER);
+
+               if(vert_vlayer) totvert = vert_vlayer->dl.da.count;
+               else totvert = 0;
+               totedge = 0;    /* total count of edge needn't to be zero, but verse doesn't know edges */
+               if(face_vlayer) totface = face_vlayer->dl.da.count;
+               else totface = 0;
+       }
+       else {
+               totvert = me->totvert;
+               totedge = me->totedge;
+               totface = me->totface;
+       }
+#else
+       totvert = me->totvert;
+       totedge = me->totedge;
+       totface = me->totface;
+#endif
        glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
 
                // Unwanted combination.
@@ -1818,12 +1919,12 @@ static void draw_mesh_fancy(Base *base, DerivedMesh *baseDM, DerivedMesh *dm, in
        if(dt==OB_BOUNDBOX) {
                draw_bounding_volume(ob);
        }
-       else if(hasHaloMat || (me->totface==0 && me->totedge==0)) {
+       else if(hasHaloMat || (totface==0 && totedge==0)) {
                glPointSize(1.5);
                dm->drawVerts(dm);
                glPointSize(1.0);
        }
-       else if(dt==OB_WIRE || me->totface==0) {
+       else if(dt==OB_WIRE || totface==0) {
                draw_wire = 1;
        }
        else if( (ob==OBACT && (G.f & G_FACESELECT)) || (G.vd->drawtype==OB_TEXTURE && dt>OB_SOLID)) {
@@ -1946,7 +2047,7 @@ static void draw_mesh_fancy(Base *base, DerivedMesh *baseDM, DerivedMesh *dm, in
 //             if (G.f & (G_VERTEXPAINT|G_WEIGHTPAINT|G_TEXTUREPAINT)) {
 //                     baseDM->drawEdges(baseDM, dt==OB_WIRE);
 //             } else {
-                       dm->drawEdges(dm, (dt==OB_WIRE || me->totface==0));
+                       dm->drawEdges(dm, (dt==OB_WIRE || totface==0));
 //             }
 
                if (dt!=OB_WIRE) {
@@ -3999,7 +4100,12 @@ void draw_object(Base *base, int flag)
                        } 
                        else if((flag & DRAW_CONSTCOLOR)==0) {
                                /* we don't draw centers for duplicators and sets */
-                               drawcentercircle(ob->obmat[3], do_draw_center, ob->id.lib || ob->id.us>1);
+#ifdef WITH_VERSE
+                               if(ob->vnode)
+                                       drawcentercircle(ob->obmat[3], VERSE, 1);
+                               else
+#endif
+                                       drawcentercircle(ob->obmat[3], do_draw_center, ob->id.lib || ob->id.us>1);
                        }
                }
        }
index 8368d69d30ee16ff126a622afced2ecc9a494e71..773ad3cfb8f0d77b38961bc4f71985c87ceabbb4 100644 (file)
 #include "BIF_screen.h"
 #include "BIF_space.h"
 
+#ifdef WITH_VERSE
+#include "BIF_verse.h"
+#endif
+
 #include "BDR_drawmesh.h"
 #include "BDR_drawobject.h"
 #include "BDR_editobject.h"
@@ -2228,7 +2232,13 @@ static void view3d_panel_object(short cntrl)     // VIEW3D_HANDLER_OBJECT
        }
        else {
                bt= uiDefBut(block, TEX, B_IDNAME, "OB: ",      10,180,140,20, ob->id.name+2, 0.0, 19.0, 0, 0, "");
+#ifdef WITH_VERSE
+               if(ob->vnode) uiButSetFunc(bt, test_and_send_idbutton_cb, ob, ob->id.name);
+               else uiButSetFunc(bt, test_idbutton_cb, ob->id.name, NULL);
+#else
                uiButSetFunc(bt, test_idbutton_cb, ob->id.name, NULL);
+#endif
+
 
                uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_OBJECTPANELPARENT, "Par:", 160, 180, 140, 20, &ob->parent, "Parent Object"); 
        }
index bad89da633f618c355b3986ec4a6f3da8b0cd6bc..914ddffb528dd45bffe4974187a718cfd2cded54 100644 (file)
 #include "BKE_object.h"
 #include "BKE_utildefines.h"
 
+#ifdef WITH_VERSE
+#include "BKE_verse.h"
+#endif
+
 #include "BIF_editmesh.h"
 #include "BIF_editview.h"
 #include "BIF_editarmature.h"
 #include "BIF_screen.h"
 #include "BIF_toolbox.h"
 
+#ifdef WITH_VERSE
+#include "BIF_verse.h"
+#endif
+
 #include "BSE_edit.h"
 #include "BSE_drawipo.h"
 #include "BSE_drawview.h"
@@ -759,6 +767,10 @@ static void special_transvert_update(void)
                DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
                
                if(G.obedit->type==OB_MESH) {
+#ifdef WITH_VERSE
+                       if(G.editMesh->vnode)
+                               sync_all_verseverts_with_editverts((VNode*)G.editMesh->vnode);
+#endif
                        recalc_editnormals();   // does face centers too
                }
                else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) {
@@ -1114,6 +1126,9 @@ void snap_sel_to_grid()
                                        ob->loc[1]+= vec[1];
                                        ob->loc[2]+= vec[2];
                                }
+#ifdef WITH_VERSE
+                               if(ob->vnode) b_verse_send_transformation(ob);
+#endif
                        }
                }
 
@@ -1212,6 +1227,9 @@ void snap_sel_to_curs()
                                        ob->loc[1]+= vec[1];
                                        ob->loc[2]+= vec[2];
                                }
+#ifdef WITH_VERSE
+                               if(ob->vnode) b_verse_send_transformation(ob);
+#endif
                        }
                }
 
@@ -1519,6 +1537,9 @@ void snap_to_center()
                                        ob->loc[1]+= vec[1];
                                        ob->loc[2]+= vec[2];
                                }
+#ifdef WITH_VERSE
+                               if(ob->vnode) b_verse_send_transformation(ob);
+#endif
                        }
                }
 
index 3bba88003d1f83e8456458e14487c60ea45691f1..6c351a09dc4ba34d9f9b79f4d6fa7e8f5e021500 100644 (file)
 #include "BKE_texture.h"
 #include "BKE_utildefines.h"
 
+#ifdef WITH_VERSE
+#include "BKE_verse.h"
+#endif
+
 #include "BIF_editkey.h"
 #include "BIF_editmesh.h"
 #include "BIF_editmode_undo.h"
 #include "BIF_screen.h"
 #include "BIF_toolbox.h"
 
+#ifdef WITH_VERSE
+#include "BIF_verse.h"
+#endif
+
 #include "BSE_view.h"
 #include "BSE_edit.h"
 #include "BSE_trans_types.h"
@@ -141,11 +149,27 @@ EditVert *addvertlist(float *vec)
         * have a pre-editmode vertex order
         */
        eve->keyindex = -1;
+
+#ifdef WITH_VERSE
+       createVerseVert(eve);
+#endif
+
        return eve;
 }
 
 void free_editvert (EditVert *eve)
 {
+#ifdef WITH_VERSE
+       if(eve->vvert) {
+               /* it prevents from removing all verse vertexes
+                * during entering edit mode ... messy solution */
+               if(G.editMesh->vnode)
+                       b_verse_send_vertex_delete(eve);
+               else
+                       ((VerseVert*)eve->vvert)->vertex = NULL;
+       }
+#endif
+
        if(eve->dw) MEM_freeN(eve->dw);
        EM_remove_selection(eve, EDITVERT);
        if(eve->fast==0){ 
@@ -288,6 +312,16 @@ void free_editedge(EditEdge *eed)
 
 void free_editface(EditFace *efa)
 {
+#ifdef WITH_VERSE
+       if(efa->vface) {
+               /* it prevents from removing all verse faces
+                * during entering edit mode ... messy solution */
+               if(G.editMesh->vnode)
+                       b_verse_send_face_delete(efa);
+               else
+                       ((VerseFace*)efa->vface)->face = NULL;
+       }
+#endif
        EM_remove_selection(efa, EDITFACE);
        if(efa->fast==0){ 
                free(efa);
@@ -397,6 +431,10 @@ EditFace *addfacelist(EditVert *v1, EditVert *v2, EditVert *v3, EditVert *v4, Ed
                CalcCent3f(efa->cent, efa->v1->co, efa->v2->co, efa->v3->co);
        }
 
+#ifdef WITH_VERSE
+       createVerseFace(efa);
+#endif
+
        return efa;
 }
 
@@ -500,8 +538,18 @@ static void end_editmesh_fastmalloc(void)
 
 void free_editMesh(EditMesh *em)
 {
+#ifdef WITH_VERSE
+       struct VNode *vnode=NULL;
+#endif
        if(em==NULL) return;
-       
+
+#ifdef WITH_VERSE
+       if(em->vnode) {
+               vnode = (VNode*)em->vnode;
+               em->vnode = NULL;
+       }
+#endif
+
        if(em->verts.first) free_vertlist(&em->verts);
        if(em->edges.first) free_edgelist(&em->edges);
        if(em->faces.first) free_facelist(&em->faces);
@@ -517,6 +565,12 @@ void free_editMesh(EditMesh *em)
                em->derivedCage= NULL;
        }
 
+#ifdef WITH_VERSE
+       if(vnode) {
+               em->vnode = (void*)vnode;
+       }
+#endif
+
        /* DEBUG: hashtabs are slowest part of enter/exit editmode. here a testprint */
 #if 0
        if(em->hashedgetab) {
@@ -727,6 +781,13 @@ void make_editMesh()
        EditSelection *ese;
        int tot, a, eekadoodle= 0;
 
+#ifdef WITH_VERSE
+       if(me->vnode){
+               create_edit_mesh_from_geom_node(me->vnode);
+               return;
+       }
+#endif
+
        /* because of reload */
        free_editMesh(G.editMesh);
        
@@ -907,6 +968,15 @@ void load_editMesh(void)
        MDeformVert *dvert;
 
        waitcursor(1);
+
+#ifdef WITH_VERSE
+       if(em->vnode) {
+               struct VNode *vnode = (VNode*)em->vnode;
+               ((VGeomData*)vnode->data)->editmesh = NULL;
+               em->vnode = NULL;
+       }
+#endif
+
        countall();
 
        /* this one also tests of edges are not in faces: */
@@ -989,7 +1059,13 @@ void load_editMesh(void)
                if(eve->f1==1) mvert->flag |= ME_SPHERETEST;
                mvert->flag |= (eve->f & SELECT);
                if (eve->h) mvert->flag |= ME_HIDE;                     
-                       
+
+#ifdef WITH_VERSE
+               if(eve->vvert) {
+                       ((VerseVert*)eve->vvert)->vertex = NULL;
+                       eve->vvert = NULL;
+               }
+#endif                 
                eve= eve->next;
                mvert++;
                if(dvert) dvert++;
@@ -1069,7 +1145,13 @@ void load_editMesh(void)
 
                /* no index '0' at location 3 or 4 */
                test_index_face(mface, NULL, &efa->tf, efa->v4?4:3);
-               
+
+#ifdef WITH_VERSE
+               if(efa->vface) {
+                       ((VerseFace*)efa->vface)->face = NULL;
+                       efa->vface = NULL;
+               }
+#endif         
                efa->tmp.l = a++;
                i++;
                efa= efa->next;
@@ -1326,6 +1408,9 @@ void separate_mesh(void)
        Mesh *me, *men;
        Base *base, *oldbase;
        ListBase edve, eded, edvl;
+#ifdef WITH_VERSE
+       struct VNode *vnode = NULL;
+#endif
        
        TEST_EDITMESH   
 
@@ -1359,9 +1444,21 @@ void separate_mesh(void)
                base= base->next;
        }
        
+#ifdef WITH_VERSE
+       if(G.editMesh->vnode) {
+               vnode = G.editMesh->vnode;
+               G.editMesh->vnode = NULL;
+       }
+#endif
        /* no test for split, split doesn't split when a loose part is selected */
        /* SPLIT: first make duplicate */
        adduplicateflag(SELECT);
+
+#ifdef WITH_VERSE
+       if(vnode) {
+               G.editMesh->vnode = vnode;
+       }
+#endif
        /* SPLIT: old faces have 3x flag 128 set, delete these ones */
        delfaceflag(128);
        
@@ -1376,7 +1473,14 @@ void separate_mesh(void)
                if((eve->f & SELECT)==0) {
                        BLI_remlink(&em->verts, eve);
                        BLI_addtail(&edve, eve);
+#ifdef WITH_VERSE
+                       if(eve->vvert) {
+                               ((VerseVert*)eve->vvert)->vertex = NULL;
+                               eve->vvert = NULL;
+                       }
+#endif
                }
+               
                eve= v1;
        }
        eed= em->edges.first;
@@ -1394,6 +1498,12 @@ void separate_mesh(void)
                if((efa->f & SELECT)==0) {
                        BLI_remlink(&em->faces, efa);
                        BLI_addtail(&edvl, efa);
+#ifdef WITH_VERSE
+                       if(efa->vface) {
+                               ((VerseFace*)efa->vface)->face = NULL;
+                               efa->vface = NULL;
+                       }
+#endif
                }
                efa= vl1;
        }
@@ -1401,7 +1511,18 @@ void separate_mesh(void)
        oldob= G.obedit;
        oldbase= BASACT;
        
+#ifdef WITH_VERSE
+       if(G.obedit->vnode) {
+               vnode = G.obedit->vnode;
+               G.obedit->vnode = NULL;
+       }
+#endif
        adduplicate(1, 0); /* notrans and a linked duplicate*/
+#ifdef WITH_VERSE
+       if(vnode) {
+               G.obedit->vnode = vnode;
+       }
+#endif
        
        G.obedit= BASACT->object;       /* basact was set in adduplicate()  */
 
@@ -1428,7 +1549,7 @@ void separate_mesh(void)
        
        /* hashedges are freed now, make new! */
        editMesh_set_hash();
-       
+
        DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);     
        G.obedit= oldob;
        BASACT= oldbase;
@@ -1449,13 +1570,28 @@ void separate_mesh_loose(void)
        EditVert *eve, *v1;
        EditEdge *eed, *e1;
        EditFace *efa, *vl1;
-       Object *oldob;
+       Object *oldob=NULL;
        Mesh *me, *men;
        Base *base, *oldbase;
        ListBase edve, eded, edvl;
        int vertsep=0;  
        short done=0, check=1;
-               
+#ifdef WITH_VERSE
+       struct VNode *vnode = NULL;
+#endif
+                       
+       me= get_mesh(G.obedit);
+#ifdef WITH_VERSE
+       if(me->vnode) {
+               error("Can't separate a mesh shared at verse server");
+               return;
+       }
+#endif
+       if(me->key) {
+               error("Can't separate a mesh with vertex keys");
+               return;
+       }
+       
        TEST_EDITMESH
        waitcursor(1);  
        
@@ -1467,19 +1603,11 @@ void separate_mesh_loose(void)
         * 5. freelist and get back old verts, edges, facs
         */
                        
-       
-                       
        while(!done){           
                vertsep=check=1;
                
                countall();
                
-               me= get_mesh(G.obedit);
-               if(me->key) {
-                       error("Can't separate a mesh with vertex keys");
-                       return;
-               }               
-               
                /* make only obedit selected */
                base= FIRSTBASE;
                while(base) {
@@ -1541,6 +1669,11 @@ void separate_mesh_loose(void)
                                if((eve->f & SELECT)==0) {
                                        BLI_remlink(&em->verts, eve);
                                        BLI_addtail(&edve, eve);
+#ifdef WITH_VERSE
+                                       if(eve->vvert) {
+                                               b_verse_send_vertex_delete(eve);
+                                       }
+#endif
                                }
                                eve= v1;
                        }
@@ -1559,6 +1692,11 @@ void separate_mesh_loose(void)
                                if( (efa->f & SELECT)==0 ) {
                                        BLI_remlink(&em->faces, efa);
                                        BLI_addtail(&edvl, efa);
+#ifdef WITH_VERSE
+                                       if(efa->vface) {
+                                               b_verse_send_face_delete(efa);
+                                       }
+#endif
                                }
                                efa= vl1;
                        }
@@ -1566,10 +1704,21 @@ void separate_mesh_loose(void)
                        oldob= G.obedit;
                        oldbase= BASACT;
                        
-                       adduplicate(1, 0); /* notrans and 0 for linked duplicate */
+#ifdef WITH_VERSE
+                       if(G.obedit->vnode) {
+                               vnode = G.obedit->vnode;
+                               G.obedit->vnode = NULL;
+                       }
+#endif
+                       adduplicate(1, 0); /* notrans and a linked duplicate*/
+#ifdef WITH_VERSE
+                       if(vnode) {
+                               G.obedit->vnode = vnode;
+                       }
+#endif
                        
                        G.obedit= BASACT->object;       /* basact was set in adduplicate()  */
-               
+
                        men= copy_mesh(me);
                        set_mesh(G.obedit, men);
                        /* because new mesh is a copy: reduce user count */
@@ -1627,7 +1776,7 @@ typedef struct EditVertC
        unsigned char f, h;
        short totweight;
        struct MDeformWeight *dw;
-       int keyindex; 
+       int keyindex;
 } EditVertC;
 
 typedef struct EditEdgeC
@@ -1791,18 +1940,28 @@ static void undoMesh_to_editMesh(void *umv)
        EditSelectionC *esec;
        TFace *tface;
        int a=0;
-       
+
+#ifdef WITH_VERSE
+       struct VNode *vnode = G.editMesh->vnode;
+       if(vnode) {
+               /* send delete command to all verse vertexes and verse face ...
+                * verse mesh will be recreated from new edit mesh */
+               destroy_versemesh(vnode);
+       }
+#endif 
        G.scene->selectmode = um->selectmode;
        
        free_editMesh(G.editMesh);
        
        /* malloc blocks */
        memset(em, 0, sizeof(EditMesh));
-
-       
                
        init_editmesh_fastmalloc(em, um->totvert, um->totedge, um->totface);
 
+#ifdef WITH_VERSE
+       G.editMesh->vnode = vnode;
+#endif
+
        /* now copy vertices */
        if(um->totvert) evar= MEM_mallocN(um->totvert*sizeof(EditVert *), "vertex ar");
        for(a=0, evec= um->verts; a<um->totvert; a++, evec++) {
@@ -1867,6 +2026,7 @@ static void undoMesh_to_editMesh(void *umv)
                }
                EM_free_index_arrays();
        }
+
 }
 
 
index b10d855d12e375015e9faeab488d04f06f5543a4..18f8fbd20dc3755280442ce8420252f6011f1b3a 100644 (file)
 #include "BKE_object.h"
 #include "BKE_utildefines.h"
 
+#ifdef WITH_VERSE
+#include "BKE_verse.h"
+#endif
+
+
 #include "BIF_editmesh.h"
 #include "BIF_graphics.h"
 #include "BIF_interface.h"
 #include "BIF_toolbox.h"
 #include "BIF_transform.h"
 
+#ifdef WITH_VERSE
+#include "BIF_verse.h"
+#endif
+
 #include "BDR_editobject.h" 
 
 #include "BSE_view.h"
@@ -233,6 +242,12 @@ void add_click_mesh(void)
        
        countall();
 
+#ifdef WITH_VERSE
+       if(G.editMesh->vnode) {
+               sync_all_verseverts_with_editverts((VNode*)G.editMesh->vnode);
+       }
+#endif
+
        BIF_undo_push("Add vertex/edge/face");
        allqueue(REDRAWVIEW3D, 0);
        DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);     
@@ -561,7 +576,18 @@ static void fix_new_face(EditFace *eface)
                eface->flag &= ~ME_SMOOTH;
 
        /* flip face, when too much "face normals" in neighbourhood is different */
-       if(count > 0) flipface(eface);
+       if(count > 0) {
+               flipface(eface);
+#ifdef WITH_VERSE
+               if(eface->vface) {
+                       struct VNode *vnode;
+                       struct VLayer *vlayer;
+                       vnode = (VNode*)((Mesh*)G.obedit->data)->vnode;
+                       vlayer = find_verse_layer_type((VGeomData*)vnode->data, POLYGON_LAYER);
+                       add_item_to_send_queue(&(vlayer->queue), (void*)eface->vface, VERSE_FACE);
+               }
+#endif
+       }
 }
 
 void addedgeface_mesh(void)
index fce6141e5a9b7e864b9ff9b61f146ccad8812ba1..2d729cf94d99591c6f1be95dcb429c19ade0fdaf 100644 (file)
@@ -63,6 +63,10 @@ editmesh_lib: generic (no UI, no menus) operations/evaluators for editmesh data
 
 #include "BIF_editmesh.h"
 
+#ifdef WITH_VERSE
+#include "BIF_verse.h"
+#endif
+
 #include "BSE_edit.h"
 
 #include "editmesh.h"
@@ -1711,6 +1715,10 @@ void flip_editnormals(void)
                }
                efa= efa->next;
        }
+#ifdef WITH_VERSE
+       if(G.editMesh->vnode)
+               sync_all_versefaces_with_editfaces((VNode*)G.editMesh->vnode);
+#endif
 }
 
 /* does face centers too */
index a5b41d8291e5208cc91dea8547536040814009b2..06da8711028eb1c1019a8b9db8dde3762915878f 100644 (file)
@@ -63,6 +63,10 @@ editmesh_loop: tools with own drawing subloops, select, knife, subdiv
 #include "BKE_object.h"
 #include "BKE_utildefines.h"
 
+#ifdef WITH_VERSE
+#include "BKE_verse.h"
+#endif
+
 #include "BIF_cursors.h"
 #include "BIF_editmesh.h"
 #include "BIF_gl.h"
@@ -74,6 +78,10 @@ editmesh_loop: tools with own drawing subloops, select, knife, subdiv
 #include "BIF_space.h"
 #include "BIF_toolbox.h"
 
+#ifdef WITH_VERSE
+#include "BIF_verse.h"
+#endif
+
 #include "BSE_view.h"
 #include "BSE_edit.h"
 #include "BSE_drawview.h"
@@ -402,8 +410,12 @@ void CutEdgeloop(int numcuts)
        }       
        
        DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+#ifdef WITH_VERSE
+       if(G.editMesh->vnode)
+               sync_all_verseverts_with_editverts((VNode*)G.editMesh->vnode);
+#endif
        scrarea_queue_headredraw(curarea);
-       scrarea_queue_winredraw(curarea);       
+       scrarea_queue_winredraw(curarea);
        return;
 }
 
@@ -754,6 +766,12 @@ void KnifeSubdivide(char mode)
        window_set_cursor(win, oldcursor);
        BLI_ghash_free(gh, NULL, (GHashValFreeFP)MEM_freeN);
        if (curve) MEM_freeN(curve);
+
+#ifdef WITH_VERSE
+       if(G.editMesh->vnode)
+               sync_all_versefaces_with_editfaces((VNode*)G.editMesh->vnode);
+#endif
+
        BIF_undo_push("Knife");
 }
 
index ab105a0cd4aa2df54fcf64e919d56c72720fa228..cf24bbd05a90dcb62d923a42f44a4753d0e7efff 100644 (file)
@@ -68,6 +68,10 @@ editmesh_mods.c, UI level access, no geometry changes
 #include "BKE_texture.h"
 #include "BKE_utildefines.h"
 
+#ifdef WITH_VERSE
+#include "BKE_verse.h"
+#endif
+
 #include "BIF_editmesh.h"
 #include "BIF_resources.h"
 #include "BIF_gl.h"
@@ -81,6 +85,10 @@ editmesh_mods.c, UI level access, no geometry changes
 #include "BIF_space.h"
 #include "BIF_toolbox.h"
 
+#ifdef WITH_VERSE
+#include "BIF_verse.h"
+#endif
+
 #include "BDR_drawobject.h"
 #include "BDR_editobject.h"
 
@@ -2792,6 +2800,11 @@ void righthandfaces(int select)  /* makes faces righthand turning */
        recalc_editnormals();
        
        DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+
+#ifdef WITH_VERSE
+       if(G.editMesh->vnode)
+               sync_all_versefaces_with_editfaces((VNode*)G.editMesh->vnode);
+#endif
        
        waitcursor(0);
 }
@@ -3081,6 +3094,11 @@ void vertexsmooth(void)
 
        allqueue(REDRAWVIEW3D, 0);
        DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+
+#ifdef WITH_VERSE
+       if(G.editMesh->vnode)
+               sync_all_verseverts_with_editverts(G.editMesh->vnode);
+#endif
        BIF_undo_push("Vertex Smooth");
 }
 
@@ -3128,6 +3146,10 @@ void vertexnoise(void)
        recalc_editnormals();
        allqueue(REDRAWVIEW3D, 0);
        DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+#ifdef WITH_VERSE
+       if(G.editMesh->vnode)
+               sync_all_verseverts_with_editverts(G.editMesh->vnode);
+#endif
        BIF_undo_push("Vertex Noise");
 }
 
@@ -3192,6 +3214,10 @@ void vertices_to_sphere(void)
        recalc_editnormals();
        allqueue(REDRAWVIEW3D, 0);
        DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+#ifdef WITH_VERSE
+       if(G.editMesh->vnode)
+               sync_all_verseverts_with_editverts(G.editMesh->vnode);
+#endif
        BIF_undo_push("To Sphere");
 }
 
index de8cc5b7a9bf45644f2bbc6d7e05685883f3b0f4..f1e5b555009afa3f5509388178fc2e63c84c9b50 100644 (file)
@@ -72,6 +72,10 @@ editmesh_tool.c: UI called tools for editmesh, geometry changes here, otherwise
 #include "BKE_object.h"
 #include "BKE_utildefines.h"
 
+#ifdef WITH_VERSE
+#include "BKE_verse.h"
+#endif
+
 #include "BIF_cursors.h"
 #include "BIF_editmesh.h"
 #include "BIF_gl.h"
@@ -85,6 +89,10 @@ editmesh_tool.c: UI called tools for editmesh, geometry changes here, otherwise
 #include "BIF_toolbox.h"
 #include "BIF_transform.h"
 
+#ifdef WITH_VERSE
+#include "BIF_verse.h"
+#endif
+
 #include "BDR_drawobject.h"
 #include "BDR_editobject.h"
 
@@ -200,6 +208,11 @@ void convert_to_triface(int direction)
        }
        
        EM_fgon_flags();        // redo flags and indices for fgons
+
+#ifdef WITH_VERSE
+       if(G.editMesh->vnode)
+               sync_all_versefaces_with_editfaces((VNode*)G.editMesh->vnode);
+#endif
        BIF_undo_push("Convert Quads to Triangles");
        
 }
@@ -509,6 +522,13 @@ int removedoublesflag(short flag, float limit)             /* return amount */
                eve= nextve;
        }
 
+#ifdef WITH_VERSE
+       if((a>0) && (G.editMesh->vnode)) {
+               sync_all_verseverts_with_editverts((VNode*)G.editMesh->vnode);
+               sync_all_versefaces_with_editfaces((VNode*)G.editMesh->vnode);
+       }
+#endif
+
        return a;       /* amount */
 }
 
@@ -549,6 +569,12 @@ void xsortvert_flag(int flag)
        addlisttolist(&em->verts, &tbase);
        
        MEM_freeN(sortblock);
+
+#ifdef WITH_VERSE
+       if(G.editMesh->vnode)
+               sync_all_versefaces_with_editfaces((VNode*)G.editMesh->vnode);
+#endif
+
        BIF_undo_push("Xsort");
        
 }
@@ -609,6 +635,10 @@ void hashvert_flag(int flag)
        addlisttolist(&em->verts, &tbase);
        
        MEM_freeN(sortblock);
+#ifdef WITH_VERSE
+       if(G.editMesh->vnode)
+               sync_all_versefaces_with_editfaces((VNode*)G.editMesh->vnode);
+#endif
        BIF_undo_push("Hash");
 
 }
@@ -710,6 +740,12 @@ void split_mesh(void)
        countall();
        allqueue(REDRAWVIEW3D, 0);
        DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+
+#ifdef WITH_VERSE
+       if(G.editMesh->vnode)
+               sync_all_versefaces_with_editfaces((VNode*)G.editMesh->vnode);
+#endif
+
        BIF_undo_push("Split");
 
 }
@@ -747,7 +783,7 @@ void extrude_repeat_mesh(int steps, float offs)
        
        allqueue(REDRAWVIEW3D, 0);
        DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
-       
+
        BIF_undo_push("Extrude Repeat");
 }
 
@@ -833,6 +869,7 @@ void spin_mesh(int steps, int degr, float *dvec, int mode)
        countall();
        allqueue(REDRAWVIEW3D, 0);
        DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+
        
        if(dvec==NULL) BIF_undo_push("Spin");
 }
@@ -1180,6 +1217,12 @@ void fill_mesh(void)
        countall();
        allqueue(REDRAWVIEW3D, 0);
        DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+
+#ifdef WITH_VERSE
+       if(G.editMesh->vnode)
+               sync_all_versefaces_with_editfaces((VNode*)G.editMesh->vnode);
+#endif
+
        BIF_undo_push("Fill");
 }
 /*GB*/
@@ -3310,6 +3353,10 @@ void beauty_fill(void)
        
        allqueue(REDRAWVIEW3D, 0);
        DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+#ifdef WITH_VERSE
+       if(G.editMesh->vnode)
+               sync_all_versefaces_with_editfaces((VNode*)G.editMesh->vnode);
+#endif
        BIF_undo_push("Beauty Fill");
 }
 
@@ -3404,6 +3451,10 @@ void join_triangles(void)
        
        allqueue(REDRAWVIEW3D, 0);
        DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+#ifdef WITH_VERSE
+       if(G.editMesh->vnode)
+               sync_all_versefaces_with_editfaces((VNode*)G.editMesh->vnode);
+#endif
        BIF_undo_push("Convert Triangles to Quads");
 }
 
@@ -3515,6 +3566,10 @@ void edge_flip(void)
        
        allqueue(REDRAWVIEW3D, 0);
        DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+#ifdef WITH_VERSE
+       if(G.editMesh->vnode)
+               sync_all_versefaces_with_editfaces((VNode*)G.editMesh->vnode);
+#endif
        BIF_undo_push("Flip Triangle Edges");
        
 }
@@ -3974,7 +4029,12 @@ void edge_rotate_selected(int dir)
        
        allqueue(REDRAWVIEW3D, 0);
        DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
-       
+
+#ifdef WITH_VERSE
+       if(G.editMesh->vnode)
+               sync_all_versefaces_with_editfaces((VNode*)G.editMesh->vnode);
+#endif
+
        BIF_undo_push("Rotate Edge");   
 }
 
@@ -5377,10 +5437,18 @@ int EdgeSlide(short immediate, float imperc)
        BLI_ghash_free(vertgh, NULL, (GHashValFreeFP)MEM_freeN);
        BLI_linklist_free(vertlist,NULL); 
        BLI_linklist_free(edgelist,NULL); 
-       
+
        if(cancel == 1) {
                return -1;
        }
+       else {
+#ifdef WITH_VERSE
+       if(G.editMesh->vnode) {
+               sync_all_verseverts_with_editverts((VNode*)G.editMesh->vnode);
+               sync_all_versefaces_with_editfaces((VNode*)G.editMesh->vnode);
+       }
+#endif
+       }
        return 1;
 }
 
@@ -5638,7 +5706,14 @@ void mesh_rip(void)
        }
        
        countall();     // apparently always needed when adding stuff, derived mesh
-       
+
+#ifdef WITH_VERSE
+       if(G.editMesh->vnode) {
+               sync_all_verseverts_with_editverts((VNode*)G.editMesh->vnode);
+               sync_all_versefaces_with_editfaces((VNode*)G.editMesh->vnode);
+       }
+#endif
+
        BIF_TransformSetUndo("Rip");
        initTransform(TFM_TRANSLATION, 0);
        Transform();
index 4ab9005e8756e8c924bdbac18a43345f1eda25e2..5dd7bab51760b3e973541328e3e29c1e5fa5ca25 100644 (file)
 #include "BIF_toolbox.h"
 #include "BIF_toets.h"
 
+#ifdef WITH_VERSE
+#include "BIF_verse.h"
+#endif
+
 #include "BSE_edit.h"
 #include "BSE_editipo.h"
 #include "BSE_filesel.h"       /* For activate_databrowse() */
@@ -255,7 +259,9 @@ void delete_obj(int ok)
                if TESTBASE(base) {
                        if(ok==0 &&  (ok=okee("Erase selected Object(s)"))==0) return;
                        if(base->object->type==OB_LAMP) islamp= 1;
-                       
+#ifdef WITH_VERSE
+                       if(base->object->vnode) b_verse_delete_object(base->object);
+#endif                 
                        free_and_unlink_base(base);
                }
                
@@ -961,16 +967,40 @@ void clear_object(char mode)
                                        memset(ob->drot, 0, 3*sizeof(float));
                                        QuatOne(ob->quat);
                                        QuatOne(ob->dquat);
+#ifdef WITH_VERSE
+                                       if(ob->vnode) {
+                                               struct VNode *vnode = (VNode*)ob->vnode;
+                                               ((VObjectData*)vnode->data)->flag |= ROT_SEND_READY;
+                                               b_verse_send_transformation(ob);
+                                       }
+#endif
+
                                }
                                else if(mode=='g') {
                                        memset(ob->loc, 0, 3*sizeof(float));
                                        memset(ob->dloc, 0, 3*sizeof(float));
+#ifdef WITH_VERSE
+                                       if(ob->vnode) {
+                                               struct VNode *vnode = (VNode*)ob->vnode;
+                                               ((VObjectData*)vnode->data)->flag |= POS_SEND_READY;
+                                               b_verse_send_transformation(ob);
+                                       }
+#endif
+
                                }
                                else if(mode=='s') {
                                        memset(ob->dsize, 0, 3*sizeof(float));
                                        ob->size[0]= 1.0;
                                        ob->size[1]= 1.0;
                                        ob->size[2]= 1.0;
+#ifdef WITH_VERSE
+                                       if(ob->vnode) {
+                                               struct VNode *vnode = (VNode*)ob->vnode;
+                                               ((VObjectData*)vnode->data)->flag |= SCALE_SEND_READY;
+                                               b_verse_send_transformation(ob);
+                                       }
+#endif
+
                                }
                                else if(mode=='o') {
                                        if(ob->parent) {
@@ -1661,7 +1691,6 @@ void docentre(int centremode)
                                                Mat4MulVecfl(base->object->imat, cent);
                                        } else {
                                                INIT_MINMAX(min, max);
-               
                                                mvert= me->mvert;
                                                for(a=0; a<me->totvert; a++, mvert++) {
                                                        DO_MINMAX(mvert->co, min, max);
@@ -1671,7 +1700,7 @@ void docentre(int centremode)
                                                cent[1]= (min[1]+max[1])/2.0f;
                                                cent[2]= (min[2]+max[2])/2.0f;
                                        }
-                                               
+
                                        mvert= me->mvert;
                                        for(a=0; a<me->totvert; a++, mvert++) {
                                                VecSubf(mvert->co, mvert->co, cent);
@@ -3770,7 +3799,19 @@ void single_obdata_users(int flag)
        Mesh *me;
        ID *id;
        int a;
-       
+
+#ifdef WITH_VERSE
+       base= FIRSTBASE;
+       while(base) {
+               ob= base->object;
+               if(ob->vnode) {
+                       error("Can't make data single user, when data are shared at verse server");
+                       return;
+               }
+               base = base->next;
+       }
+#endif
+
        base= FIRSTBASE;
        while(base) {
                ob= base->object;
@@ -4478,6 +4519,13 @@ void adduplicate(int mode, int dupflag)
                                                }
                                        }
                                }
+#ifdef WITH_VERSE
+                               /* send new created object to verse server,
+                                * when original object was linked with object node */
+                               if(ob->vnode) {
+                                       b_verse_duplicate_object(((VNode*)ob->vnode)->session, ob, obn);
+                               }
+#endif
                        }
                                                
                }
index 47476bd76f6e4b7cbdd0ccd76bf9036f974b77b3..4085cb353f5939fbfbb8d3d7b93f41660c185ba2 100644 (file)
 #include "BKE_blender.h"
 #include "BKE_screen.h"
 
+#ifdef WITH_VERSE
+#include "BKE_verse.h"
+#endif
+
 #include "BIF_cursors.h"
 #include "BIF_drawscene.h"
 #include "BIF_editsound.h"
@@ -1118,6 +1122,10 @@ int do_screenhandlers(bScreen *sc)
                                        done= 1;
                                        break;
                                case SCREEN_HANDLER_VERSE:
+#ifdef WITH_VERSE
+                                       b_verse_update();
+#endif
+
                                        done= 1;
                                        break;
                        }
index 55a4ad49d9313c0ce2b0232c78b9d10a47f067dc..bfbd9d1b265a51a76a20389f651202b6687185b7 100644 (file)
 #include "BIF_writeimage.h"
 #include "BIF_drawscene.h"
 
+#ifdef WITH_VERSE
+#include "BIF_verse.h"
+#endif
+
 #include "BKE_blender.h"
 #include "BKE_depsgraph.h"
 #include "BKE_exotic.h"
 #include "BKE_scene.h"
 #include "BKE_world.h"
 
+#ifdef WITH_VERSE
+#include "BKE_verse.h"
+#endif
+
 #include "BLI_arithb.h"
 #include "BLI_blenlib.h"
 #include "BLO_writefile.h"
@@ -720,6 +728,82 @@ static uiBlock *info_file_exportmenu(void *arg_unused)
        return block;
 }
 
+#ifdef WITH_VERSE
+
+extern ListBase session_list;
+
+static void do_verse_filemenu(void *arg, int event)
+{
+       char address[64];               /* lenght of domain name is 63 characters or less */
+       VerseSession *session = NULL;
+       ScrArea *sa;
+       
+       if(curarea->spacetype==SPACE_INFO) {
+               sa= closest_bigger_area();
+               areawinset(sa->win);
+       }
+
+       switch(event) {
+               case 0:
+                       waitcursor(1);
+                       printf("Connecting to localhost!\n");
+                       b_verse_connect("localhost");
+                       waitcursor(0);
+                       break;
+               case 1:
+                       address[0] = '\0';
+                       if(sbutton(address, 0, 63, "Server:")) {
+                               waitcursor(1);
+                               printf("Connecting to %s\n", address);
+                               b_verse_connect(address);
+                               waitcursor(0);
+                       }
+                       break;
+               case 2:
+                       session = session_menu();
+                       if(session) {
+                               printf("Disconnecting session: %s!\n", session->address);
+                               end_verse_session(session, 1);
+                       }
+                       break;
+               case 3:
+                       printf("Disconnecting all sessions!\n");
+                       end_all_verse_sessions();
+                       break;
+       }
+}
+
+static uiBlock *verse_filemenu(void *unusedargs)
+{
+       uiBlock *block;
+       short yco = 20, menuwidth = 120;
+
+       block= uiNewBlock(&curarea->uiblocks, "verse_filemenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
+       uiBlockSetButmFunc(block, do_verse_filemenu, NULL);
+               
+       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Connect to localhost", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, "");
+       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Connect ...", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+       if(session_list.first != NULL) {
+               if(session_list.first != session_list.last) {
+                       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Disconnect ...",
+                                       0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
+                       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Disconnect all",
+                                       0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
+               }
+               else {
+                       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Disconnect",
+                                       0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
+               }
+               
+       }
+
+       uiBlockSetDirection(block, UI_RIGHT);
+       uiTextBoundsBlock(block, 60);
+
+       return block;
+}
+#endif
+
 static void do_info_filemenu(void *arg, int event)
 {
        ScrArea *sa;
@@ -871,6 +955,9 @@ static uiBlock *info_filemenu(void *arg_unused)
        
        uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "New|Ctrl X",                             0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, "");
        uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Open...|F1",                             0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
+#ifdef WITH_VERSE
+       uiDefIconTextBlockBut(block, verse_filemenu, NULL, ICON_RIGHTARROW_THIN, "Verse", 0, yco-=20, menuwidth, 19, "");
+#endif
        uiDefIconTextBlockBut(block, info_openrecentmenu, NULL, ICON_RIGHTARROW_THIN, "Open Recent",0, yco-=20, 120, 19, "");
        uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Recover Last Session",                           0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 15, "");
 
index ade1b001efce7687380f0cd8c0047273c654c528..a0aa801b55af82cac6996e49e8cf6e11481ec6e6 100644 (file)
@@ -1,4 +1,4 @@
-/**
+/*
  * header_view3d.c oct-2003
  *
  * Functions to draw the "3D Viewport" window header
 #include "BKE_main.h"
 #include "BKE_mesh.h"
 
+#ifdef WITH_VERSE
+#include "BKE_verse.h"
+#endif
+
 #include "BLI_arithb.h"
 #include "BLI_blenlib.h"
 
 #include "BIF_toolbox.h"
 #include "BIF_transform.h"
 
+#ifdef WITH_VERSE
+#include "BIF_verse.h"
+#endif
+
 #include "BPY_extern.h"
 #include "BPY_menus.h"
 
@@ -2074,11 +2082,18 @@ static uiBlock *view3d_edit_object_scriptsmenu(void *arg_unused)
        return block;
 }
 
+#ifdef WITH_VERSE
+extern ListBase session_list;
+#endif
+
 static void do_view3d_edit_objectmenu(void *arg, int event)
 {
        /* needed to check for valid selected objects */
        Base *base=NULL;
        Object *ob=NULL;
+#ifdef WITH_VERSE
+       struct VerseSession *session=NULL;
+#endif
 
        base= BASACT;
        if (base) ob= base->object;
@@ -2118,6 +2133,13 @@ static void do_view3d_edit_objectmenu(void *arg, int event)
        case 15: /* Object Panel */
                add_blockhandler(curarea, VIEW3D_HANDLER_OBJECT, UI_PNL_UNSTOW);
                break;
+#ifdef WITH_VERSE
+       case 16: /* Share Object at Verse server */
+               if(session_list.first != session_list.last) session = session_menu();
+               else session = session_list.first;
+               if(session) b_verse_push_object(session, ob);
+               break;
+#endif
        }
        allqueue(REDRAWVIEW3D, 0);
 }
@@ -2130,6 +2152,19 @@ static uiBlock *view3d_edit_objectmenu(void *arg_unused)
        block= uiNewBlock(&curarea->uiblocks, "view3d_edit_objectmenu", UI_EMBOSSP, UI_HELV, curarea->headwin);
        uiBlockSetButmFunc(block, do_view3d_edit_objectmenu, NULL);
        
+#ifdef WITH_VERSE
+       if(session_list.first != NULL) {
+               Base *base = BASACT;
+               Object *ob = NULL;
+               if (base) ob= base->object;
+
+               if((ob->type == OB_MESH) && (!ob->vnode)) {
+                       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Share at Verse Server", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 16, "");
+                       uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+               }
+       }
+#endif
+
        uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL, "Transform Properties|N",             0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 15, "");
        uiDefIconTextBlockBut(block, view3d_transformmenu, NULL, ICON_RIGHTARROW_THIN, "Transform", 0, yco-=20, 120, 19, "");
        uiDefIconTextBlockBut(block, view3d_object_mirrormenu, NULL, ICON_RIGHTARROW_THIN, "Mirror", 0, yco-=20, menuwidth, 19, "");
@@ -2610,6 +2645,10 @@ static uiBlock *view3d_edit_mesh_scriptsmenu(void *arg_unused)
 
 static void do_view3d_edit_meshmenu(void *arg, int event)
 {
+#ifdef WITH_VERSE
+       struct VerseSession *session;
+#endif
+
        switch(event) {
        
        case 0: /* Undo Editing */
@@ -2652,6 +2691,13 @@ static void do_view3d_edit_meshmenu(void *arg, int event)
                if(G.scene->proportional) G.scene->proportional= 0;
                else G.scene->proportional= 1;
                break;
+#ifdef WITH_VERSE
+       case 13:
+               if(session_list.first != session_list.last) session = session_menu();
+               else session = session_list.first;
+               if(session) b_verse_push_object(session, G.obedit);
+               break;
+#endif
        }
        allqueue(REDRAWVIEW3D, 0);
 }
@@ -2664,7 +2710,15 @@ static uiBlock *view3d_edit_meshmenu(void *arg_unused)
                
        block= uiNewBlock(&curarea->uiblocks, "view3d_edit_meshmenu", UI_EMBOSSP, UI_HELV, curarea->headwin);
        uiBlockSetButmFunc(block, do_view3d_edit_meshmenu, NULL);
-               
+
+#ifdef WITH_VERSE
+       if((session_list.first != NULL) && (!G.obedit->vnode)) {
+               uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Share at Verse Server",
+                               0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 13, "");
+               uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+       }
+#endif
+
        uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Undo Editing|U",         0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, "");
        uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Redo Editing|Shift U",           0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
        uiDefIconTextBlockBut(block, editmode_undohistorymenu, NULL, ICON_RIGHTARROW_THIN, "Undo History", 0, yco-=20, 120, 19, "");
index 4dd3825c1344d653f1e0911cebe9e52d44dfa608..03771e3df933516435419ee28abcdf494a5d1ecc 100644 (file)
@@ -138,7 +138,28 @@ int join_mesh(void)
        
        ob= OBACT;
        if(!ob || ob->type!=OB_MESH) return 0;
-       
+
+#ifdef WITH_VERSE
+       /* it isn't allowed to join shared object at verse server
+        * this function will be implemented as soon as possible */
+       base= FIRSTBASE;
+       while(base) {
+               if TESTBASELIB(base) {
+                       if(base->object->type==OB_MESH) {
+                               if(base->object->vnode) {
+                                       haskey= 1;
+                                       break;
+                               }
+                       }
+               }
+               base= base->next;
+       }
+       if(haskey) {
+               error("Can't join meshes shared at verse server");
+               return 0;
+       }
+#endif
+
        /* count */
        base= FIRSTBASE;
        while(base) {
index d7d89f991d7599d62a39be6ffad2d69597e47b23..187106e79d6088100b84a185cae98de59a4d1d33 100644 (file)
 #include "BKE_scene.h"
 #include "BKE_utildefines.h"
 
+#ifdef WITH_VERSE
+#include "BKE_verse.h"
+#endif
+
 #include "BIF_butspace.h"
 #include "BIF_drawscene.h"
 #include "BIF_drawtext.h"
 #include "BIF_space.h"
 #include "BIF_toolbox.h"
 
+#ifdef WITH_VERSE
+#include "BIF_verse.h"
+#endif
+
 #ifdef INTERNATIONAL
 #include "FTF_Api.h"
 #endif
 
 #define TREESTORE(a) ((a)?soops->treestore->data+(a)->store_index:NULL)
 
+#ifdef WITH_VERSE
+extern ListBase session_list;
+#endif
+
 /* ******************** PERSISTANT DATA ***************** */
 
 static void outliner_storage_cleanup(SpaceOops *soops)
@@ -702,6 +714,34 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
                        break;
                }
        }
+#ifdef WITH_VERSE
+       else if(type==ID_VS) {
+               struct VerseSession *session = (VerseSession*)idv;
+               te->name = session->address;
+               te->directdata = (void*)session;
+               te->idcode = ID_VS;
+       }
+       else if(type==ID_VN) {
+               struct VNode *vnode = (VNode*)idv;
+               te->name = vnode->name;
+               te->idcode = ID_VN;
+               if(vnode->type==V_NT_OBJECT) {
+                       struct TreeElement *ten;
+                       struct VNode *child_node;
+                       struct VLink *vlink;
+                       
+                       vlink = ((VObjectData*)vnode->data)->links.lb.first;
+                       while(vlink) {
+                               child_node = vlink->target;
+                               if(child_node && child_node->type==V_NT_GEOMETRY) {
+                                       ten = outliner_add_element(soops, &te->subtree, child_node, te, ID_VN, 0);
+                                       ten->directdata = child_node;
+                               }
+                               vlink = vlink->next;
+                       }
+               }
+       }
+#endif
        return te;
 }
 
@@ -754,6 +794,9 @@ static void outliner_build_tree(SpaceOops *soops)
        TreeElement *te, *ten;
        TreeStoreElem *tselem;
        int show_opened= soops->treestore==NULL; /* on first view, we open scenes */
+#ifdef WITH_VERSE
+       struct VerseSession *session;
+#endif
 
        outliner_free_tree(&soops->tree);
        outliner_storage_cleanup(soops);
@@ -840,7 +883,28 @@ static void outliner_build_tree(SpaceOops *soops)
                ten= outliner_add_element(soops, &soops->tree, OBACT, NULL, 0, 0);
                if(ten) ten->directdata= BASACT;
        }
-       
+
+#ifdef WITH_VERSE
+       /* add all session to the "root" of hierarchy */
+       for(session=session_list.first; session; session = session->next) {
+               struct VNode *vnode;
+               if(session->flag & VERSE_CONNECTED) {
+                       te= outliner_add_element(soops, &soops->tree, session, NULL, ID_VS, 0);
+                       /* add all object nodes as childreen of session */
+                       for(vnode=session->nodes.lb.first; vnode; vnode=vnode->next) {
+                               if(vnode->type==V_NT_OBJECT) {
+                                       ten= outliner_add_element(soops, &te->subtree, vnode, te, ID_VN, 0);
+                                       ten->directdata= vnode;
+                               }
+                               else if(vnode->type==V_NT_BITMAP) {
+                                       ten= outliner_add_element(soops, &te->subtree, vnode, te, ID_VN, 0);
+                                       ten->directdata= vnode;
+                               }
+                       }
+               }
+       }
+#endif
+
        outliner_sort(soops, &soops->tree);
 }
 
@@ -1509,6 +1573,59 @@ static int do_outliner_mouse_event(SpaceOops *soops, TreeElement *te, short even
                                }
                        }
                        else {
+#ifdef WITH_VERSE
+                               if(event==RIGHTMOUSE) {
+                                       short event;
+                                       if(te->idcode==ID_VS) {
+                                               struct VerseSession *session = (VerseSession*)te->directdata;
+                                               struct VNode *vnode;
+                                               if(!(session->flag & VERSE_AUTOSUBSCRIBE)) {
+                                                       event = pupmenu("VerseSession %t| End Session %x1| Subscribe to All Nodes %x2| Start Autosubscribe %x3");
+                                               }
+                                               else {
+                                                       event = pupmenu("VerseSession %t| End Session %x1| Subscribe to All Nodes %x2| Stop Autosubscribe %x4");
+                                               }
+                                               switch(event) {
+                                                       case 1:
+                                                               end_verse_session(session, 1);
+                                                               break;
+                                                       case 2:
+                                                               vnode = session->nodes.lb.first;
+                                                               while(vnode) {
+                                                                       b_verse_pop_node(vnode);
+                                                                       vnode = vnode->next;
+                                                               }
+                                                               break;
+                                                       case 3:
+                                                               vnode = session->nodes.lb.first;
+                                                               while(vnode) {
+                                                                       b_verse_pop_node(vnode);
+                                                                       vnode = vnode->next;
+                                                               }
+                                                               session->flag |= VERSE_AUTOSUBSCRIBE;
+                                                               break;
+                                                       case 4:
+                                                               session->flag &= ~VERSE_AUTOSUBSCRIBE;
+                                                               break;
+                                               }
+                                       }
+                                       else if(te->idcode==ID_VN) {
+                                               struct VNode *vnode = (VNode*)te->directdata;
+                                               event = pupmenu("VerseNode %t| Subscribe %x1| Unsubscribe %x2");
+                                               switch(event) {
+                                                       case 1:
+                                                               b_verse_pop_node(vnode);
+                                                               break;
+                                                       case 2:
+                                                               /* Global */
+                                                               b_verse_unsubscribe(vnode);
+                                                               break;
+                                               }
+                                       }
+                               }
+                               else {
+#endif
+
                                /* always makes active object */
                                tree_element_active_object(soops, te);
                                
@@ -1533,6 +1650,9 @@ static int do_outliner_mouse_event(SpaceOops *soops, TreeElement *te, short even
                                        
                                }
                                else tree_element_type_active(soops, te, tselem, 1);
+#ifdef WITH_VERSE
+                               }
+#endif
                        }
                        return 1;
                }
@@ -1722,7 +1842,13 @@ static void set_operation_types(SpaceOops *soops, ListBase *lb)
                tselem= TREESTORE(te);
                if(tselem->flag & TSE_SELECTED) {
                        if(tselem->type) {
+#ifdef WITH_VERSE
+                               if(te->idcode==ID_VS) datalevel= TSE_VERSE_SESSION;
+                               else if(te->idcode==ID_VN) datalevel= TSE_VERSE_OBJ_NODE;
+                               else if(datalevel==0) datalevel= tselem->type;
+#else
                                if(datalevel==0) datalevel= tselem->type;
+#endif
                                else if(datalevel!=tselem->type) datalevel= -1;
                        }
                        else {
@@ -1973,6 +2099,17 @@ static void ebone_cb(int event, TreeElement *te, TreeStoreElem *tselem)
                ebone->flag &= ~BONE_HIDDEN_A;
 }
 
+#ifdef WITH_VERSE
+static void vsession_cb(int event, TreeElement *te, TreeStoreElem *tselem)
+{
+/*     struct VerseSession *vsession =(VerseSession*)te->directdata;*/
+
+       if(event==1) {
+               printf("\tending verse session\n");
+       }
+}
+#endif
+
 static void outliner_do_data_operation(SpaceOops *soops, int type, int event, ListBase *lb, 
                                                                                 void (*operation_cb)(int, TreeElement *, TreeStoreElem *))
 {
@@ -2095,6 +2232,14 @@ void outliner_operation_menu(ScrArea *sa)
                                        BIF_undo_push("EditBone operation");
                                }
                        }
+#ifdef WITH_VERSE
+                       else if(datalevel==TSE_VERSE_SESSION) {
+                               short event= pupmenu("VerseSession %t| End %x1");
+                               if(event>0) {
+                                       outliner_do_data_operation(soops, datalevel, event, &soops->tree, vsession_cb);
+                               }
+                       }
+#endif
                        
                        allqueue(REDRAWOOPS, 0);
                        allqueue(REDRAWBUTSALL, 0);
@@ -2163,6 +2308,12 @@ static void tselem_draw_icon(float x, float y, TreeStoreElem *tselem, TreeElemen
                                BIF_icon_draw(x, y, ICON_ARMATURE_DEHLT); break;
                        case TSE_POSE_CHANNEL:
                                BIF_icon_draw(x, y, ICON_WPAINT_DEHLT); break;
+#ifdef WITH_VERSE
+                       case ID_VS:
+                               BIF_icon_draw(x, y, ICON_VERSE); break;
+                       case ID_VN:
+                               BIF_icon_draw(x, y, ICON_VERSE); break;
+#endif
                        default:
                                BIF_icon_draw(x, y, ICON_DOT); break;
                }
@@ -2354,9 +2505,14 @@ static void outliner_draw_tree_element(SpaceOops *soops, TreeElement *te, int st
                else BIF_ThemeColor(TH_TEXT);
                glRasterPos2i(startx+offsx, *starty+5);
                BIF_RasterPos(startx+offsx, *starty+5);
-               BIF_DrawString(G.font, te->name, 0);
-               
-               offsx+= OL_X + BIF_GetStringWidth(G.font, te->name, 0);
+#ifdef WITH_VERSE
+               if(te->name) {
+#endif
+                       BIF_DrawString(G.font, te->name, 0);
+                       offsx+= OL_X + BIF_GetStringWidth(G.font, te->name, 0);
+#ifdef WITH_VERSE
+               }
+#endif
                
                /* closed item, we draw the icons, not when it's a scene though */
                if(tselem->flag & TSE_CLOSED) {
index 8ce07779d842cc57cb3ebc334705e57291b4c67f..6f05605cb30543d4b0d68684d3dfe949c3f8bb85 100644 (file)
@@ -4327,7 +4327,12 @@ static void winqreadoopsspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
                        view2dmove(event);      /* in drawipo.c */
                        break;
                case RIGHTMOUSE:
+#ifdef WITH_VERSE
+                       /* evil hack due to verse */
+                       outliner_mouse_event(sa, event);
+#else
                        outliner_operation_menu(sa);
+#endif
                        break;
                        
                case AKEY:
index 572bde118d531dc056867c3fa292c0576668b29f..30ab9fdb17e46be8be40f9a815e51bee91b1a78b 100755 (executable)
@@ -1428,6 +1428,15 @@ static void VertsToTransData(TransData *td, EditVert *eve)
        td->tdi = NULL;
        td->val = NULL;
        td->tdmir= NULL;
+
+#ifdef WITH_VERSE
+       if(eve->vvert) {
+               td->verse = (void*)eve->vvert;
+               td->flag |= TD_VERSE_VERT;
+       }
+       else
+               td->flag &= ~TD_VERSE_VERT;
+#endif
 }
 
 /* *********************** CrazySpace correction. Now without doing subsurf optimal ****************** */
@@ -2051,6 +2060,14 @@ static void ObjectToTransData(TransData *td, Object *ob)
                Mat3One(td->smtx);
                Mat3One(td->mtx);
        }
+#ifdef WITH_VERSE
+       if(ob->vnode) {
+               td->verse = (void*)ob;
+               td->flag |= TD_VERSE_OBJECT;
+       }
+       else
+               td->flag &= ~TD_VERSE_OBJECT;
+#endif
 }
 
 
index 52b2c823cc8c9c878f946e482ae72b4724e27219..71ce2ff7f8439460d03fefd9f7376bd6de82a851 100755 (executable)
 #include "BIF_editsima.h"
 #include "BIF_meshtools.h"
 
+#ifdef WITH_VERSE
+#include "BIF_verse.h"
+#endif
+
 #include "BKE_action.h"
 #include "BKE_anim.h"
 #include "BKE_armature.h"
 #include "BKE_object.h"
 #include "BKE_utildefines.h"
 
+#ifdef WITH_VERSE
+#include "BKE_verse.h"
+#endif
+
 #include "BSE_view.h"
 #include "BDR_unwrapper.h"
 
@@ -202,6 +210,9 @@ static void editmesh_apply_to_mirror(TransInfo *t)
 void recalcData(TransInfo *t)
 {
        Base *base;
+#ifdef WITH_VERSE
+       struct TransData *td;
+#endif
                
        if (G.obedit) {
                if (G.obedit->type == OB_MESH) {
@@ -334,6 +345,17 @@ void recalcData(TransInfo *t)
                        }
                } 
        }
+
+#ifdef WITH_VERSE
+       for (td = t->data; td < t->data + t->total; td++) {
+               if(td->flag & TD_VERSE_VERT) {
+                       if(td->verse)
+                               send_versevert_pos((VerseVert*)td->verse);
+               }
+               else if(td->flag & TD_VERSE_OBJECT)
+                       if(td->verse) b_verse_send_transformation((Object*)td->verse);
+       }
+#endif
        
        /* update shaded drawmode while transform */
        if(t->spacetype==SPACE_VIEW3D && G.vd->drawtype == OB_SHADED)
@@ -463,6 +485,25 @@ void initTrans (TransInfo *t)
 void postTrans (TransInfo *t) 
 {
        G.moving = 0; // Set moving flag off (display as usual)
+#ifdef WITH_VERSE
+       struct TransData *td;
+
+       for (td = t->data; td < t->data + t->total; td++) {
+               if(td->flag & TD_VERSE_VERT) {
+                       if(td->verse) send_versevert_pos((VerseVert*)td->verse);
+               }
+               else if(td->flag & TD_VERSE_OBJECT) {
+                       if(td->verse) {
+                               struct VNode *vnode;
+                               vnode = (VNode*)((Object*)td->verse)->vnode;
+                               ((VObjectData*)vnode->data)->flag |= POS_SEND_READY;
+                               ((VObjectData*)vnode->data)->flag |= ROT_SEND_READY;
+                               ((VObjectData*)vnode->data)->flag |= SCALE_SEND_READY;
+                               b_verse_send_transformation((Object*)td->verse);
+                       }
+               }
+       }
+#endif
 
        stopConstraint(t);
        
@@ -619,6 +660,25 @@ void restoreTransObjects(TransInfo *t)
        
        for (td = t->data; td < t->data + t->total; td++) {
                restoreElement(td);
+#ifdef WITH_VERSE
+               /* position of vertexes and object transformation matrix is sent
+                * extra, becuase blender uses synchronous sen