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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJiri Hnidek <jiri.hnidek@tul.cz>2006-08-20 19:22:56 +0400
committerJiri Hnidek <jiri.hnidek@tul.cz>2006-08-20 19:22:56 +0400
commit2ee42ac01e6f4b154ac68976024af0615f7acb26 (patch)
tree9a2400a99bf7880a2f146c7a89bd2d8c0108374c
parentffe630b452f4abb28c105fca2b8eb9fdb6e72370 (diff)
Huge commit: VERSE
- All code is in #ifdef ... #endif - Only make build system is supported and you have to add: export WITH_VERSE=true to user-def.mk file - Blender can share only mesh objects and bitmaps now - More informations can be found at wiki: http://mediawiki.blender.org/index.php/BlenderDev/VerseIntegrationToBlender http://mediawiki.blender.org/index.php/BlenderDev/VerseIntegrationToBlenderUserDoc I hope, that I didn't forget at anything
-rw-r--r--extern/Makefile4
-rw-r--r--source/Makefile12
-rw-r--r--source/blender/blenkernel/BKE_global.h5
-rw-r--r--source/blender/blenkernel/BKE_verse.h503
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c472
-rw-r--r--source/blender/blenkernel/intern/Makefile5
-rw-r--r--source/blender/blenkernel/intern/mesh.c54
-rw-r--r--source/blender/blenkernel/intern/object.c5
-rw-r--r--source/blender/blenkernel/intern/verse_bitmap_node.c449
-rw-r--r--source/blender/blenkernel/intern/verse_geometry_node.c1665
-rw-r--r--source/blender/blenkernel/intern/verse_node.c735
-rw-r--r--source/blender/blenkernel/intern/verse_object_node.c605
-rw-r--r--source/blender/blenkernel/intern/verse_session.c345
-rw-r--r--source/blender/blenlib/BLI_blenlib.h12
-rw-r--r--source/blender/blenlib/BLI_dynamiclist.h58
-rw-r--r--source/blender/blenlib/BLI_editVert.h10
-rw-r--r--source/blender/blenlib/intern/util.c223
-rw-r--r--source/blender/blenloader/intern/Makefile5
-rw-r--r--source/blender/blenloader/intern/writefile.c24
-rw-r--r--source/blender/include/BIF_outliner.h5
-rw-r--r--source/blender/include/BIF_verse.h134
-rw-r--r--source/blender/include/blendef.h3
-rwxr-xr-xsource/blender/include/transform.h7
-rw-r--r--source/blender/makesdna/DNA_ID.h5
-rw-r--r--source/blender/makesdna/DNA_image_types.h3
-rw-r--r--source/blender/makesdna/DNA_mesh_types.h4
-rw-r--r--source/blender/makesdna/DNA_object_types.h4
-rw-r--r--source/blender/src/Makefile9
-rw-r--r--source/blender/src/buttons_editing.c14
-rw-r--r--source/blender/src/drawobject.c114
-rw-r--r--source/blender/src/drawview.c10
-rw-r--r--source/blender/src/edit.c21
-rw-r--r--source/blender/src/editmesh.c200
-rw-r--r--source/blender/src/editmesh_add.c28
-rw-r--r--source/blender/src/editmesh_lib.c8
-rw-r--r--source/blender/src/editmesh_loop.c20
-rw-r--r--source/blender/src/editmesh_mods.c26
-rw-r--r--source/blender/src/editmesh_tools.c83
-rw-r--r--source/blender/src/editobject.c56
-rw-r--r--source/blender/src/editscreen.c8
-rw-r--r--source/blender/src/header_info.c87
-rw-r--r--source/blender/src/header_view3d.c58
-rw-r--r--source/blender/src/meshtools.c23
-rw-r--r--source/blender/src/outliner.c164
-rw-r--r--source/blender/src/space.c5
-rwxr-xr-xsource/blender/src/transform_conversions.c17
-rwxr-xr-xsource/blender/src/transform_generics.c60
-rw-r--r--source/blender/src/usiblender.c45
-rw-r--r--source/blender/src/verse_common.c270
-rw-r--r--source/blender/src/verse_image.c345
-rw-r--r--source/blender/src/verse_mesh.c1611
-rw-r--r--source/blender/src/verse_object.c587
-rw-r--r--source/creator/creator.c1
-rw-r--r--source/nan_compile.mk4
-rw-r--r--source/nan_definitions.mk4
-rw-r--r--source/nan_link.mk3
56 files changed, 9178 insertions, 59 deletions
diff --git a/extern/Makefile b/extern/Makefile
index 766f7f34d92..fb5570eff4b 100644
--- a/extern/Makefile
+++ b/extern/Makefile
@@ -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
diff --git a/source/Makefile b/source/Makefile
index ec78763506a..5e4359c5d10 100644
--- a/source/Makefile
+++ b/source/Makefile
@@ -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
diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h
index e239d4de3c0..8f6aa8c3f54 100644
--- a/source/blender/blenkernel/BKE_global.h
+++ b/source/blender/blenkernel/BKE_global.h
@@ -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
index 00000000000..00a6bdd4e60
--- /dev/null
+++ b/source/blender/blenkernel/BKE_verse.h
@@ -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
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index 063185f456a..f0c1ef7f890 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -68,6 +68,10 @@
#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) {
diff --git a/source/blender/blenkernel/intern/Makefile b/source/blender/blenkernel/intern/Makefile
index fdfcef53954..28d4151154c 100644
--- a/source/blender/blenkernel/intern/Makefile
+++ b/source/blender/blenkernel/intern/Makefile
@@ -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)
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index 098f6adb33c..2b0c936edd9 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -71,6 +71,10 @@
#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 */
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 1a96b41d9bb..5ce83c19033 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -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
index 00000000000..f9b18c38dc8
--- /dev/null
+++ b/source/blender/blenkernel/intern/verse_bitmap_node.c
@@ -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
index 00000000000..bb3234d04fd
--- /dev/null
+++ b/source/blender/blenkernel/intern/verse_geometry_node.c
@@ -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
index 00000000000..570d3a2df5c
--- /dev/null
+++ b/source/blender/blenkernel/intern/verse_node.c
@@ -0,0 +1,735 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Contributor(s): Jiri Hnidek.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifdef WITH_VERSE
+
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_listBase.h"
+
+#include "BLI_dynamiclist.h"
+#include "BLI_blenlib.h"
+
+#include "BIF_verse.h"
+
+#include "BKE_verse.h"
+
+#include "verse.h"
+
+/* function prototypes of static functions */
+ /* for tags */
+static void free_verse_tag_data(struct VTag *vtag);
+static struct VTag *find_tag_in_queue(struct VTagGroup *vtaggroup, const char *name);
+static struct VTag *create_verse_tag(struct VTagGroup *vtaggroup, uint16 tag_id, const char *name, VNTagType type, const VNTag *tag);
+ /* for verse tag groups */
+static void free_verse_taggroup_data(struct VTagGroup *taggroup);
+static struct VTagGroup *find_taggroup_in_queue(struct VNode *vnode, const char *name);
+static struct VTagGroup *create_verse_taggroup(VNode *vnode, uint16 group_id, const char *name);
+ /* for verse nodes */
+static void move_verse_node_to_dlist(struct VerseSession *session, VNodeID vnode_id);
+ /* function prototypes of node callback functions */
+static void cb_tag_destroy(void *user_data, VNodeID node_id, uint16 group_id, uint16 tag_id);
+static void cb_tag_create(void *user_data, VNodeID node_id, uint16 group_id, uint16 tag_id, const char *name, VNTagType type, const VNTag *tag);
+static void cb_tag_group_destroy(void *user_data, VNodeID node_id, uint16 group_id);
+static void cb_tag_group_create(void *user_data, VNodeID node_id, uint16 group_id, const char *name);
+static void cb_node_name_set(void *user_data, VNodeID node_id, const char *name);
+static void cb_node_destroy(void *user_data, VNodeID node_id);
+static void cb_node_create(void *user_data, VNodeID node_id, uint8 type, VNodeID owner_id);
+
+/*
+ * send new tag to verse server
+ */
+void send_verse_tag(VTag *vtag)
+{
+ verse_send_tag_create(vtag->vtaggroup->vnode->id,
+ vtag->vtaggroup->id,
+ vtag->id,
+ vtag->name,
+ vtag->type,
+ vtag->tag);
+}
+
+/*
+ * free tag data
+ */
+static void free_verse_tag_data(VTag *vtag)
+{
+ /* free name of verse tag */
+ MEM_freeN(vtag->name);
+ /* free value of tag */
+ MEM_freeN(vtag->tag);
+}
+
+/*
+ * try to find tag in sending queue ... if tag will be found, then
+ * this function will removed tag from queue and will return pointer
+ * at this tag
+ */
+static VTag *find_tag_in_queue(VTagGroup *vtaggroup, const char *name)
+{
+ struct VTag *vtag;
+
+ vtag = vtaggroup->queue.first;
+
+ while(vtag) {
+ if(strcmp(vtag->name, name)==0) {
+ BLI_remlink(&(vtaggroup->queue), vtag);
+ break;
+ }
+ vtag = vtag->next;
+ }
+
+ return vtag;
+}
+
+/*
+ * create new verse tag
+ */
+static VTag *create_verse_tag(
+ VTagGroup *vtaggroup,
+ uint16 tag_id,
+ const char *name,
+ VNTagType type,
+ const VNTag *tag)
+{
+ struct VTag *vtag;
+
+ vtag = (VTag*)MEM_mallocN(sizeof(VTag), "VTag");
+
+ vtag->vtaggroup = vtaggroup;
+ vtag->id = tag_id;
+ vtag->name = (char*)MEM_mallocN(sizeof(char)*(strlen(name)+1), "VTag name");
+ strcpy(vtag->name, name);
+ vtag->type = type;
+
+ vtag->tag = (VNTag*)MEM_mallocN(sizeof(VNTag), "VNTag");
+ *vtag->tag = *tag;
+
+ vtag->value = NULL;
+
+ return vtag;
+}
+
+/*
+ * send taggroup to verse server
+ */
+void send_verse_taggroup(VTagGroup *vtaggroup)
+{
+ verse_send_tag_group_create(
+ vtaggroup->vnode->id,
+ vtaggroup->id,
+ vtaggroup->name);
+}
+
+/*
+ * free taggroup data
+ */
+static void free_verse_taggroup_data(VTagGroup *taggroup)
+{
+ struct VerseSession *session = taggroup->vnode->session;
+ struct VTag *vtag;
+
+ vtag = taggroup->tags.lb.first;
+
+ while(vtag) {
+ free_verse_tag_data(vtag);
+ vtag = vtag->next;
+ }
+
+ /* unsubscribe from taggroup */
+ if(session->flag & VERSE_CONNECTED)
+ verse_send_tag_group_unsubscribe(taggroup->vnode->id, taggroup->id);
+
+ BLI_dlist_destroy(&(taggroup->tags));
+ MEM_freeN(taggroup->name);
+}
+
+/*
+ * move taggroup from queue to dynamic list with access array,
+ * set up taggroup id and return pointer at this taggroup
+ */
+static VTagGroup *find_taggroup_in_queue(VNode *vnode, const char *name)
+{
+ struct VTagGroup *vtaggroup;
+
+ vtaggroup = vnode->queue.first;
+
+ while(vtaggroup) {
+ if(strcmp(vtaggroup->name, name)==0) {
+ BLI_remlink(&(vnode->queue), vtaggroup);
+ break;
+ }
+ vtaggroup = vtaggroup->next;
+ }
+
+ return vtaggroup;
+}
+
+/*
+ * create new verse group of tags
+ */
+static VTagGroup *create_verse_taggroup(VNode *vnode, uint16 group_id, const char *name)
+{
+ struct VTagGroup *taggroup;
+
+ taggroup = (VTagGroup*)MEM_mallocN(sizeof(VTagGroup), "VTagGroup");
+
+ taggroup->vnode = vnode;
+ taggroup->id = group_id;
+ taggroup->name = (char*)MEM_mallocN(sizeof(char)*(strlen(name)+1), "VTagGroup name");
+ strcpy(taggroup->name, name);
+
+ BLI_dlist_init(&(taggroup->tags));
+ taggroup->queue.first = taggroup->queue.last = NULL;
+
+ taggroup->post_tag_change = post_tag_change;
+ taggroup->post_taggroup_create = post_taggroup_create;
+
+ return taggroup;
+}
+
+/*
+ * move first VerseNode waiting in sending queue to dynamic list of VerseNodes
+ * (it usually happens, when "our" VerseNode was received from verse server)
+ */
+static void move_verse_node_to_dlist(VerseSession *session, VNodeID vnode_id)
+{
+ VNode *vnode;
+
+ vnode = session->queue.first;
+
+ if(vnode) {
+ BLI_remlink(&(session->queue), vnode);
+ BLI_dlist_add_item_index(&(session->nodes), (void*)vnode, vnode_id);
+ }
+}
+
+/*
+ * send VerseNode to verse server
+ */
+void send_verse_node(VNode *vnode)
+{
+ verse_send_node_create(
+ vnode->id,
+ vnode->type,
+ vnode->session->avatar);
+}
+
+/*
+ * free Verse Node data
+ */
+void free_verse_node_data(VNode *vnode)
+{
+ struct VerseSession *session = vnode->session;
+ struct VTagGroup *vtaggroup;
+
+ /* free node data (object, geometry, etc.) */
+ switch(vnode->type){
+ case V_NT_OBJECT:
+ free_object_data(vnode);
+ break;
+ case V_NT_GEOMETRY:
+ free_geom_data(vnode);
+ break;
+ case V_NT_BITMAP:
+ free_bitmap_node_data(vnode);
+ break;
+ default:
+ break;
+ }
+
+ /* free all tag groups in dynamic list with access array */
+ vtaggroup = vnode->taggroups.lb.first;
+ while(vtaggroup) {
+ free_verse_taggroup_data(vtaggroup);
+ vtaggroup = vtaggroup->next;
+ }
+ BLI_dlist_destroy(&(vnode->taggroups));
+
+ /* free all tag groups still waiting in queue */
+ vtaggroup = vnode->queue.first;
+ while(vtaggroup) {
+ free_verse_taggroup_data(vtaggroup);
+ vtaggroup = vtaggroup->next;
+ }
+ BLI_freelistN(&(vnode->queue));
+
+ /* unsubscribe from node */
+ if(session->flag & VERSE_CONNECTED)
+ verse_send_node_unsubscribe(vnode->id);
+
+ /* free node name */
+ MEM_freeN(vnode->name);
+ vnode->name = NULL;
+
+ /* free node data */
+ MEM_freeN(vnode->data);
+ vnode->data = NULL;
+
+}
+
+/*
+ * free VerseNode
+ */
+void free_verse_node(VNode *vnode)
+{
+ free_verse_node_data(vnode);
+
+ BLI_dlist_free_item(&(vnode->session->nodes), vnode->id);
+}
+
+/*
+ * create new Verse Node
+ */
+VNode* create_verse_node(VerseSession *session, VNodeID node_id, uint8 type, VNodeID owner_id)
+{
+ struct VNode *vnode;
+
+ vnode = (VNode*)MEM_mallocN(sizeof(VNode), "VerseNode");
+
+ vnode->session = session;
+ vnode->id = node_id;
+ vnode->owner_id = owner_id;
+ vnode->name = NULL;
+ vnode->type = type;
+
+ BLI_dlist_init(&(vnode->taggroups));
+ vnode->queue.first = vnode->queue.last = NULL;
+
+ vnode->data = NULL;
+
+ vnode->counter = 0;
+
+ vnode->flag = 0;
+
+ vnode->post_node_create = post_node_create;
+ vnode->post_node_destroy = post_node_destroy;
+ vnode->post_node_name_set = post_node_name_set;
+
+ return vnode;
+}
+
+/*
+ * callback function: tag was destroyed
+ */
+static void cb_tag_destroy(
+ void *user_data,
+ VNodeID node_id,
+ uint16 group_id,
+ uint16 tag_id)
+{
+ struct VerseSession *session = (VerseSession*)current_verse_session();
+ struct VNode *vnode;
+ struct VTagGroup *vtaggroup;
+ struct VTag *vtag;
+
+ if(!session) return;
+
+ vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
+ if(!vnode) return;
+
+ /* try to find tag group in list of tag groups */
+ vtaggroup = BLI_dlist_find_link(&(vnode->taggroups), group_id);
+
+ if(!vtaggroup) return;
+
+ /* try to find verse tag in dynamic list of tags in tag group */
+ vtag = (VTag*)BLI_dlist_find_link(&(vtaggroup->tags), tag_id);
+
+ if(vtag) {
+ free_verse_tag_data(vtag);
+ BLI_dlist_free_item(&(vtaggroup->tags), vtag->id);
+ }
+}
+
+/*
+ * callback function: new tag was created
+ */
+static void cb_tag_create(
+ void *user_data,
+ VNodeID node_id,
+ uint16 group_id,
+ uint16 tag_id,
+ const char *name,
+ VNTagType type,
+ const VNTag *tag)
+{
+ struct VerseSession *session = (VerseSession*)current_verse_session();
+ struct VNode *vnode;
+ struct VTagGroup *vtaggroup;
+ struct VTag *vtag;
+
+ if(!session) return;
+
+ vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
+ if(!vnode) return;
+
+ /* try to find tag group in list of tag groups */
+ vtaggroup = BLI_dlist_find_link(&(vnode->taggroups), group_id);
+
+ if(!vtaggroup) return;
+
+ /* try to find verse tag in dynamic list of tags in tag group */
+ vtag = (VTag*)BLI_dlist_find_link(&(vtaggroup->tags), tag_id);
+
+ if(!vtag) {
+ /* we will try to find vtag in sending queue */
+ vtag = find_tag_in_queue(vtaggroup, name);
+
+ /* when we didn't create this tag, then we will have to create one */
+ if(!vtag) vtag = create_verse_tag(vtaggroup, tag_id, name, type, tag);
+ else vtag->id = tag_id;
+
+ /* add tag to the list of tags in tag group */
+ BLI_dlist_add_item_index(&(vtaggroup->tags), vtag, tag_id);
+
+ /* post change/create method */
+ vtaggroup->post_tag_change(vtag);
+ }
+ else {
+ /* this tag exists, then we will propably change value of this tag */
+ if((vtag->type != type) || (strcmp(vtag->name, name)!=0)) {
+ /* changes of type or name are not allowed and such
+ * stupid changes will be returned back */
+ send_verse_tag(vtag);
+ }
+ else {
+ /* post change/create method */
+ vtaggroup->post_tag_change(vtag);
+ }
+ }
+}
+
+/*
+ * callback function: tag group was destroyed
+ */
+static void cb_tag_group_destroy(
+ void *user_data,
+ VNodeID node_id,
+ uint16 group_id)
+{
+ struct VerseSession *session = (VerseSession*)current_verse_session();
+ struct VNode *vnode;
+ struct VTagGroup *vtaggroup;
+
+ if(!session) return;
+
+ vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
+ if(!vnode) return;
+
+ vtaggroup = BLI_dlist_find_link(&(vnode->taggroups), group_id);
+
+ if(vtaggroup) {
+ free_verse_taggroup_data(vtaggroup);
+ BLI_dlist_free_item(&(vnode->taggroups), vtaggroup->id);
+ }
+}
+
+/*
+ * callback function: new tag group was created
+ */
+static void cb_tag_group_create(
+ void *user_data,
+ VNodeID node_id,
+ uint16 group_id,
+ const char *name)
+{
+ struct VerseSession *session = (VerseSession*)current_verse_session();
+ struct VNode *vnode;
+ struct VTagGroup *vtaggroup;
+
+ if(!session) return;
+
+ vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
+ if(!vnode) return;
+
+ /* name of taggroup has to begin with string "blender:" */
+ if(strncmp("blender:", name, 8)) return;
+
+ /* try to find tag group in list of tag groups */
+ vtaggroup = BLI_dlist_find_link(&(vnode->taggroups), group_id);
+
+ if(!vtaggroup) {
+ /* subscribe to tag group (when new tag will be created, then blender will
+ * receive command about it) */
+ verse_send_tag_group_subscribe(vnode->id, group_id);
+ verse_callback_update(0);
+
+ /* try to find taggroup in waiting queue */
+ vtaggroup = find_taggroup_in_queue(vnode, name);
+
+ /* if no taggroup exist, then new has to be created */
+ if(!vtaggroup) vtaggroup = create_verse_taggroup(vnode, group_id, name);
+ else vtaggroup->id = group_id;
+
+ /* add tag group to dynamic list with access array */
+ BLI_dlist_add_item_index(&(vnode->taggroups), (void*)vtaggroup, (unsigned int)group_id);
+
+ /* post create method */
+ vtaggroup->post_taggroup_create(vtaggroup);
+ }
+ else {
+ /* this taggroup exist and somebody try to change its name */
+ if(strcmp(vtaggroup->name, name)!=0) {
+ /* blender doesn't allow such stupid and dangerous things */
+ send_verse_taggroup(vtaggroup);
+ }
+ }
+}
+
+/*
+ * callback function: change name of node
+ */
+static void cb_node_name_set(
+ void *user_data,
+ VNodeID node_id,
+ const char *name)
+{
+ struct VerseSession *session = (VerseSession*)current_verse_session();
+ struct VNode *vnode;
+
+ if(!session) return;
+
+ vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
+ if(vnode && name) {
+ if(!vnode->name) {
+ vnode->name = (char*)MEM_mallocN(sizeof(char)*(strlen(name)+1), "VerseNode name");
+ }
+ else if(strlen(name) > strlen(vnode->name)) {
+ MEM_freeN(vnode->name);
+ vnode->name = (char*)MEM_mallocN(sizeof(char)*(strlen(name)+1), "VerseNode name");
+ }
+ strcpy(vnode->name, name);
+
+ vnode->post_node_name_set(vnode);
+ }
+}
+
+/*
+ * callback function for deleting node
+ */
+static void cb_node_destroy(
+ void *user_data,
+ VNodeID node_id)
+{
+ struct VerseSession *session = (VerseSession*)current_verse_session();
+ struct VNode *vnode;
+
+ if(!session) return;
+
+ vnode = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
+
+ if(vnode) {
+ /* remove VerseNode from dynamic list */
+ BLI_dlist_rem_item(&(session->nodes), (unsigned int)node_id);
+ /* do post destroy operations */
+ vnode->post_node_destroy(vnode);
+ /* free verse data */
+ free_verse_node_data(vnode);
+ /* free VerseNode */
+ MEM_freeN(vnode);
+ };
+}
+
+
+/*
+ * callback function for new created node
+ */
+static void cb_node_create(
+ void *user_data,
+ VNodeID node_id,
+ uint8 type,
+ VNodeID owner_id)
+{
+ struct VerseSession *session = (VerseSession*)current_verse_session();
+ struct VNode *vnode;
+
+ if(!session) return;
+
+ /* subscribe to node */
+ if((type==V_NT_OBJECT) || (type==V_NT_GEOMETRY) || (type==V_NT_BITMAP))
+ verse_send_node_subscribe(node_id);
+ else
+ return;
+
+ switch(type){
+ case V_NT_OBJECT :
+ if(owner_id==VN_OWNER_MINE) {
+ struct VLink *vlink;
+ /* collect VerseNode from VerseNode queue */
+ move_verse_node_to_dlist(session, node_id);
+ /* send next VerseNode waiting in queue */
+ if(session->queue.first) send_verse_node(session->queue.first);
+ /* get received VerseNode from list of VerseNodes */
+ vnode = BLI_dlist_find_link(&(session->nodes), node_id);
+ /* set up ID */
+ vnode->id = node_id;
+ /* set up flags */
+ vnode->flag |= NODE_RECEIVED;
+ /* find unsent link pointing at this VerseNode */
+ vlink = find_unsent_child_vlink(session, vnode);
+ /* send VerseLink */
+ if(vlink) send_verse_link(vlink);
+ /* send name of object node */
+ verse_send_node_name_set(node_id, vnode->name);
+ /* subscribe to changes of object node transformations */
+ verse_send_o_transform_subscribe(node_id, 0);
+ /* send object transformation matrix */
+ send_verse_object_position(vnode);
+ send_verse_object_rotation(vnode);
+ send_verse_object_scale(vnode);
+ }
+ else {
+ /* create new VerseNode */
+ vnode = create_verse_node(session, node_id, type, owner_id);
+ /* add VerseNode to list of nodes */
+ BLI_dlist_add_item_index(&(session->nodes), (void*)vnode, (unsigned int)node_id);
+ /* set up flags */
+ vnode->flag |= NODE_RECEIVED;
+ /* create object data */
+ vnode->data = create_object_data();
+ /* set up avatar's name */
+ if(node_id == session->avatar) {
+ char *client_name;
+ client_name = verse_client_name();
+ verse_send_node_name_set(node_id, client_name);
+ MEM_freeN(client_name);
+ }
+ else if(session->flag & VERSE_AUTOSUBSCRIBE) {
+ /* subscribe to changes of object node transformations */
+ verse_send_o_transform_subscribe(node_id, 0);
+ }
+ }
+ break;
+ case V_NT_GEOMETRY :
+ if(owner_id==VN_OWNER_MINE){
+ struct VLink *vlink;
+ struct VLayer *vlayer;
+ /* collect VerseNode from VerseNode queue */
+ move_verse_node_to_dlist(session, node_id);
+ /* send next VerseNode waiting in queue */
+ if(session->queue.first) send_verse_node(session->queue.first);
+ /* get received VerseNode from list of VerseNodes */
+ vnode = BLI_dlist_find_link(&(session->nodes), node_id);
+ /* set up ID */
+ vnode->id = node_id;
+ /* set up flags */
+ vnode->flag |= NODE_RECEIVED;
+ /* find unsent link pointing at this VerseNode */
+ vlink = find_unsent_parent_vlink(session, vnode);
+ /* send VerseLink */
+ if(vlink) send_verse_link(vlink);
+ /* send name of geometry node */
+ verse_send_node_name_set(node_id, vnode->name);
+ /* send all not sent layer to verse server */
+ vlayer = (VLayer*)((VGeomData*)vnode->data)->queue.first;
+ if(vlayer) {
+ while(vlayer) {
+ send_verse_layer(vlayer);
+ vlayer = vlayer->next;
+ }
+ }
+ else {
+ /* send two verse layers to verse server */
+/* verse_send_g_layer_create(node_id, 0, "vertex", VN_G_LAYER_VERTEX_XYZ, 0, 0);
+ verse_send_g_layer_create(node_id, 1, "polygon", VN_G_LAYER_POLYGON_CORNER_UINT32, 0, 0);*/
+ }
+ }
+ else {
+ /* create new VerseNode*/
+ vnode = create_verse_node(session, node_id, type, owner_id);
+ /* add VerseNode to dlist of nodes */
+ BLI_dlist_add_item_index(&(session->nodes), (void*)vnode, (unsigned int)node_id);
+ /* set up flags */
+ vnode->flag |= NODE_RECEIVED;
+ /* create geometry data */
+ vnode->data = (void*)create_geometry_data();
+ }
+ break;
+ case V_NT_BITMAP :
+ if(owner_id==VN_OWNER_MINE) {
+ /* collect VerseNode from VerseNode queue */
+ move_verse_node_to_dlist(session, node_id);
+ /* send next VerseNode waiting in queue */
+ if(session->queue.first) send_verse_node(session->queue.first);
+ /* get received VerseNode from list of VerseNodes */
+ vnode = BLI_dlist_find_link(&(session->nodes), node_id);
+ /* set up ID */
+ vnode->id = node_id;
+ /* set up flags */
+ vnode->flag |= NODE_RECEIVED;
+ /* send name of object node */
+ verse_send_node_name_set(node_id, vnode->name);
+ /* send dimension of image to verse server */
+ verse_send_b_dimensions_set(node_id,
+ ((VBitmapData*)vnode->data)->width,
+ ((VBitmapData*)vnode->data)->height,
+ ((VBitmapData*)vnode->data)->depth);
+ }
+ else {
+ /* create new VerseNode*/
+ vnode = create_verse_node(session, node_id, type, owner_id);
+ /* add VerseNode to dlist of nodes */
+ BLI_dlist_add_item_index(&(session->nodes), (void*)vnode, (unsigned int)node_id);
+ /* set up flags */
+ vnode->flag |= NODE_RECEIVED;
+ /* create bitmap data */
+ vnode->data = (void*)create_bitmap_data();
+ }
+ default:
+ break;
+ }
+
+ vnode->post_node_create(vnode);
+}
+
+/*
+ * set up all callbacks for verse nodes
+ */
+void set_node_callbacks(void)
+{
+ /* new node created */
+ verse_callback_set(verse_send_node_create, cb_node_create, NULL);
+ /* node was deleted */
+ verse_callback_set(verse_send_node_destroy, cb_node_destroy, NULL);
+ /* name of node was set */
+ verse_callback_set(verse_send_node_name_set, cb_node_name_set, NULL);
+
+ /* new tag group was created */
+ verse_callback_set(verse_send_tag_group_create, cb_tag_group_create, NULL);
+ /* tag group was destroy */
+ verse_callback_set(verse_send_tag_group_destroy, cb_tag_group_destroy, NULL);
+
+ /* new tag was created */
+ verse_callback_set(verse_send_tag_create, cb_tag_create, NULL);
+ /* tag was destroy */
+ verse_callback_set(verse_send_tag_destroy, cb_tag_destroy, NULL);
+}
+
+#endif
diff --git a/source/blender/blenkernel/intern/verse_object_node.c b/source/blender/blenkernel/intern/verse_object_node.c
new file mode 100644
index 00000000000..9e6de928ef0
--- /dev/null
+++ b/source/blender/blenkernel/intern/verse_object_node.c
@@ -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
index 00000000000..e6f16a93239
--- /dev/null
+++ b/source/blender/blenkernel/intern/verse_session.c
@@ -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
diff --git a/source/blender/blenlib/BLI_blenlib.h b/source/blender/blenlib/BLI_blenlib.h
index d26afbc350c..564b250da81 100644
--- a/source/blender/blenlib/BLI_blenlib.h
+++ b/source/blender/blenlib/BLI_blenlib.h
@@ -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
index 00000000000..89e27743054
--- /dev/null
+++ b/source/blender/blenlib/BLI_dynamiclist.h
@@ -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
diff --git a/source/blender/blenlib/BLI_editVert.h b/source/blender/blenlib/BLI_editVert.h
index 3dc6ebadb71..2c8df6efd43 100644
--- a/source/blender/blenlib/BLI_editVert.h
+++ b/source/blender/blenlib/BLI_editVert.h
@@ -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
diff --git a/source/blender/blenlib/intern/util.c b/source/blender/blenlib/intern/util.c
index c559761fb32..1ef9c5c8cda 100644
--- a/source/blender/blenlib/intern/util.c
+++ b/source/blender/blenlib/intern/util.c
@@ -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");
diff --git a/source/blender/blenloader/intern/Makefile b/source/blender/blenloader/intern/Makefile
index 9faeb42879f..86ccd607d63 100644
--- a/source/blender/blenloader/intern/Makefile
+++ b/source/blender/blenloader/intern/Makefile
@@ -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
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index 557c553d0fd..7156b6ffcab 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -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);
diff --git a/source/blender/include/BIF_outliner.h b/source/blender/include/BIF_outliner.h
index 442247864b5..539ee055dba 100644
--- a/source/blender/include/BIF_outliner.h
+++ b/source/blender/include/BIF_outliner.h
@@ -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
index 00000000000..7dada3f3986
--- /dev/null
+++ b/source/blender/include/BIF_verse.h
@@ -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
diff --git a/source/blender/include/blendef.h b/source/blender/include/blendef.h
index c7cc268de19..ddbbfbd802f 100644
--- a/source/blender/include/blendef.h
+++ b/source/blender/include/blendef.h
@@ -89,6 +89,9 @@
#define SELECT 1
#define ACTIVE 2
+/*#ifdef WITH_VERSE*/
+#define VERSE 3
+/*#endif*/
#define DESELECT 0
#define NOT_YET 0
diff --git a/source/blender/include/transform.h b/source/blender/include/transform.h
index c17d920693f..ec55b768381 100755
--- a/source/blender/include/transform.h
+++ b/source/blender/include/transform.h
@@ -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);
diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h
index f9a824eec27..847f7123150 100644
--- a/source/blender/makesdna/DNA_ID.h
+++ b/source/blender/makesdna/DNA_ID.h
@@ -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
diff --git a/source/blender/makesdna/DNA_image_types.h b/source/blender/makesdna/DNA_image_types.h
index da8787d05ab..ad8b3daf657 100644
--- a/source/blender/makesdna/DNA_image_types.h
+++ b/source/blender/makesdna/DNA_image_types.h
@@ -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 */
diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h
index 6f477e963c6..a57791be06d 100644
--- a/source/blender/makesdna/DNA_mesh_types.h
+++ b/source/blender/makesdna/DNA_mesh_types.h
@@ -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;
diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h
index e8573f3da4a..9cdb5054493 100644
--- a/source/blender/makesdna/DNA_object_types.h
+++ b/source/blender/makesdna/DNA_object_types.h
@@ -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 {
diff --git a/source/blender/src/Makefile b/source/blender/src/Makefile
index 3bfb17dc586..fd92c412736 100644
--- a/source/blender/src/Makefile
+++ b/source/blender/src/Makefile
@@ -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
diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c
index 36280938da9..baa3d27be90 100644
--- a/source/blender/src/buttons_editing.c
+++ b/source/blender/src/buttons_editing.c
@@ -117,6 +117,10 @@
#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
+
}
diff --git a/source/blender/src/drawobject.c b/source/blender/src/drawobject.c
index c4f11a577c0..6bb70a42b96 100644
--- a/source/blender/src/drawobject.c
+++ b/source/blender/src/drawobject.c
@@ -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);
}
}
}
diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c
index 8368d69d30e..773ad3cfb8f 100644
--- a/source/blender/src/drawview.c
+++ b/source/blender/src/drawview.c
@@ -112,6 +112,10 @@
#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");
}
diff --git a/source/blender/src/edit.c b/source/blender/src/edit.c
index bad89da633f..914ddffb528 100644
--- a/source/blender/src/edit.c
+++ b/source/blender/src/edit.c
@@ -82,6 +82,10 @@
#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"
@@ -94,6 +98,10 @@
#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
}
}
diff --git a/source/blender/src/editmesh.c b/source/blender/src/editmesh.c
index 3bba88003d1..6c351a09dc4 100644
--- a/source/blender/src/editmesh.c
+++ b/source/blender/src/editmesh.c
@@ -74,6 +74,10 @@
#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"
@@ -84,6 +88,10 @@
#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();
}
+
}
diff --git a/source/blender/src/editmesh_add.c b/source/blender/src/editmesh_add.c
index b10d855d12e..18f8fbd20dc 100644
--- a/source/blender/src/editmesh_add.c
+++ b/source/blender/src/editmesh_add.c
@@ -60,6 +60,11 @@
#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"
@@ -69,6 +74,10 @@
#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)
diff --git a/source/blender/src/editmesh_lib.c b/source/blender/src/editmesh_lib.c
index fce6141e5a9..2d729cf94d9 100644
--- a/source/blender/src/editmesh_lib.c
+++ b/source/blender/src/editmesh_lib.c
@@ -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 */
diff --git a/source/blender/src/editmesh_loop.c b/source/blender/src/editmesh_loop.c
index a5b41d8291e..06da8711028 100644
--- a/source/blender/src/editmesh_loop.c
+++ b/source/blender/src/editmesh_loop.c
@@ -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");
}
diff --git a/source/blender/src/editmesh_mods.c b/source/blender/src/editmesh_mods.c
index ab105a0cd4a..cf24bbd05a9 100644
--- a/source/blender/src/editmesh_mods.c
+++ b/source/blender/src/editmesh_mods.c
@@ -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");
}
diff --git a/source/blender/src/editmesh_tools.c b/source/blender/src/editmesh_tools.c
index de8cc5b7a9b..f1e5b555009 100644
--- a/source/blender/src/editmesh_tools.c
+++ b/source/blender/src/editmesh_tools.c
@@ -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();
diff --git a/source/blender/src/editobject.c b/source/blender/src/editobject.c
index 4ab9005e875..5dd7bab5176 100644
--- a/source/blender/src/editobject.c
+++ b/source/blender/src/editobject.c
@@ -143,6 +143,10 @@
#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
}
}
diff --git a/source/blender/src/editscreen.c b/source/blender/src/editscreen.c
index 47476bd76f6..4085cb353f5 100644
--- a/source/blender/src/editscreen.c
+++ b/source/blender/src/editscreen.c
@@ -76,6 +76,10 @@
#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;
}
diff --git a/source/blender/src/header_info.c b/source/blender/src/header_info.c
index 55a4ad49d93..bfbd9d1b265 100644
--- a/source/blender/src/header_info.c
+++ b/source/blender/src/header_info.c
@@ -79,6 +79,10 @@
#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"
@@ -91,6 +95,10 @@
#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, "");
diff --git a/source/blender/src/header_view3d.c b/source/blender/src/header_view3d.c
index ade1b001efc..a0aa801b55a 100644
--- a/source/blender/src/header_view3d.c
+++ b/source/blender/src/header_view3d.c
@@ -1,4 +1,4 @@
-/**
+/*
* header_view3d.c oct-2003
*
* Functions to draw the "3D Viewport" window header
@@ -69,6 +69,10 @@
#include "BKE_main.h"
#include "BKE_mesh.h"
+#ifdef WITH_VERSE
+#include "BKE_verse.h"
+#endif
+
#include "BLI_arithb.h"
#include "BLI_blenlib.h"
@@ -106,6 +110,10 @@
#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, "");
diff --git a/source/blender/src/meshtools.c b/source/blender/src/meshtools.c
index 4dd3825c134..03771e3df93 100644
--- a/source/blender/src/meshtools.c
+++ b/source/blender/src/meshtools.c
@@ -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) {
diff --git a/source/blender/src/outliner.c b/source/blender/src/outliner.c
index d7d89f991d7..187106e79d6 100644
--- a/source/blender/src/outliner.c
+++ b/source/blender/src/outliner.c
@@ -70,6 +70,10 @@
#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"
@@ -94,6 +98,10 @@
#include "BIF_space.h"
#include "BIF_toolbox.h"
+#ifdef WITH_VERSE
+#include "BIF_verse.h"
+#endif
+
#ifdef INTERNATIONAL
#include "FTF_Api.h"
#endif
@@ -114,6 +122,10 @@
#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) {
diff --git a/source/blender/src/space.c b/source/blender/src/space.c
index 8ce07779d84..6f05605cb30 100644
--- a/source/blender/src/space.c
+++ b/source/blender/src/space.c
@@ -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:
diff --git a/source/blender/src/transform_conversions.c b/source/blender/src/transform_conversions.c
index 572bde118d5..30ab9fdb17e 100755
--- a/source/blender/src/transform_conversions.c
+++ b/source/blender/src/transform_conversions.c
@@ -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
}
diff --git a/source/blender/src/transform_generics.c b/source/blender/src/transform_generics.c
index 52b2c823cc8..71ce2ff7f84 100755
--- a/source/blender/src/transform_generics.c
+++ b/source/blender/src/transform_generics.c
@@ -59,6 +59,10 @@
#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"
@@ -74,6 +78,10 @@
#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 sending of vertexes
+ * position as well object trans. matrix and it isn't possible to
+ * send it in recalcData sometimes */
+ if(td->flag & TD_VERSE_VERT) {
+ if(td->verse) {
+ ((VerseVert*)td->verse)->flag |= VERT_POS_OBSOLETE;
+ }
+ }
+ 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;
+ }
+#endif
}
recalcData(t);
}
diff --git a/source/blender/src/usiblender.c b/source/blender/src/usiblender.c
index 27f2248d985..10dd2a29024 100644
--- a/source/blender/src/usiblender.c
+++ b/source/blender/src/usiblender.c
@@ -82,6 +82,10 @@
#include "BKE_packedFile.h"
#include "BKE_utildefines.h"
+#ifdef WITH_VERSE
+#include "BKE_verse.h"
+#endif
+
#include "BLI_vfontdata.h"
#include "BIF_fsmenu.h"
@@ -104,6 +108,11 @@
#include "BIF_toolbox.h"
#include "BIF_cursors.h"
+#ifdef WITH_VERSE
+#include "BIF_verse.h"
+#endif
+
+
#include "BSE_drawview.h"
#include "BSE_edit.h"
#include "BSE_editipo.h"
@@ -344,13 +353,38 @@ static void init_userdef_file(void)
}
+#ifdef WITH_VERSE
+extern ListBase session_list;
+#endif
+
void BIF_read_file(char *name)
{
extern short winqueue_break; /* editscreen.c */
int retval;
-
- //NOT here!
- //sound_end_all_sounds();
+#ifdef WITH_VERSE
+ struct VerseSession *session;
+ struct VNode *vnode;
+
+ session = session_list.first;
+ while(session) {
+ vnode = session->nodes.lb.first;
+ while(vnode) {
+ switch(vnode->type) {
+ case V_NT_OBJECT:
+ unsubscribe_from_obj_node(vnode);
+ break;
+ case V_NT_GEOMETRY:
+ unsubscribe_from_geom_node(vnode);
+ break;
+ case V_NT_BITMAP:
+ unsubscribe_from_bitmap_node(vnode);
+ break;
+ }
+ vnode = vnode->next;
+ }
+ session = session->next;
+ }
+#endif
/* first try to read exotic file formats... */
/* it throws error box when file doesnt exist and returns -1 */
@@ -568,7 +602,6 @@ static void readBlog(void)
BLI_free_file_lines(lines);
}
-
static void writeBlog(void)
{
struct RecentFile *recent, *next_recent;
@@ -859,6 +892,10 @@ void exit_usiblender(void)
sound_exit_audio();
if(G.listener) MEM_freeN(G.listener);
+#ifdef WITH_VERSE
+ end_all_verse_sessions();
+#endif
+
libtiff_exit();
#ifdef WITH_QUICKTIME
diff --git a/source/blender/src/verse_common.c b/source/blender/src/verse_common.c
new file mode 100644
index 00000000000..ec1ee8cf024
--- /dev/null
+++ b/source/blender/src/verse_common.c
@@ -0,0 +1,270 @@
+/**
+ * $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 <stdlib.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "mydevice.h"
+
+#include "DNA_object_types.h"
+#include "DNA_mesh_types.h"
+
+#include "BKE_global.h"
+#include "BKE_blender.h"
+
+#include "BIF_verse.h"
+#include "BIF_space.h"
+#include "BIF_interface.h"
+
+extern ListBase session_list;
+
+/*
+ * this function creates popup menu with all active VerseSessions
+ * it return pointer at selected VerseSession, if no VerseSession
+ * is selected, then NULL is returned
+ */
+VerseSession *session_menu(void)
+{
+ struct VerseSession *session;
+ char session_number[10];
+ short i=1, num=1;
+ char session_address_list[1024]; /* pupmenu business */
+
+ session_number[0] = '\0';
+ session_address_list[0] = '\0';
+
+ strcat(session_address_list, "Session list %t");
+
+ session = session_list.first;
+
+ while(session){
+ strcat(session_address_list, "| ");
+ strcat(session_address_list, session->address);
+ strcat(session_address_list, " %x");
+ sprintf(session_number, "%d", num);
+ strcat(session_address_list, session_number);
+ num++;
+ session = session->next;
+ }
+
+ printf("session list: %s\n", session_address_list);
+ num = pupmenu(session_address_list);
+
+ if(num==-1) return NULL;
+
+ session = session_list.first;
+
+ while(session) {
+ if(i==num) return session;
+ i++;
+ session = session->next;
+ }
+
+ return NULL;
+}
+
+/*
+ * returns name of verse client (it is used as avatar's name)
+ */
+char *verse_client_name(void)
+{
+ char *client_name;
+ char blender_version[5];
+ short name_lenght = 14;
+
+#ifndef WIN32
+ char *hostname;
+ hostname = getenv("HOSTNAME");
+ if(hostname) name_lenght += strlen(hostname);
+#endif
+
+ client_name = (char*)MEM_mallocN(sizeof(char)*name_lenght, "verse client name");
+ client_name[0] = '\0';
+
+ strcat(client_name, "blender_");
+ blender_version[0] = '\0';
+ sprintf(blender_version, "%d", BLENDER_VERSION);
+ strcat(client_name, blender_version);
+
+#ifndef WIN32
+ /* add at the end of the client name hostname */
+ if(hostname) {
+ strcat(client_name, ":");
+ strcat(client_name, hostname);
+ }
+#endif
+
+ return client_name;
+}
+
+/*===========================================================
+ *
+ * functions executed after calling callback functions
+ *
+ ============================================================*/
+
+/*
+ * this function is called, when some tag was changed or new tag was created
+ */
+void post_tag_change(VTag *vtag)
+{
+ printf("\tnew tag %s was created or changed\n", vtag->name);
+}
+
+/*
+ * this function is called, when verse taggroup was created
+ */
+void post_taggroup_create(VTagGroup *vtaggroup)
+{
+ printf("\tnew taggroup %s was created\n", vtaggroup->name);
+}
+
+/*
+ * this function is called after creating of new VerseNode
+ */
+void post_node_create(VNode *vnode)
+{
+ struct VerseSession *session = vnode->session;
+
+ if((session->flag & VERSE_AUTOSUBSCRIBE) && (vnode->owner_id != VN_OWNER_MINE)) {
+ if(vnode->type == V_NT_OBJECT) {
+ create_object_from_verse_node(vnode);
+ }
+ else if(vnode->type == V_NT_GEOMETRY) {
+ create_mesh_from_geom_node(vnode);;
+ }
+ }
+
+ allqueue(REDRAWOOPS, 0);
+}
+
+/*
+ * this function is called after destroying of VerseNode
+ */
+void post_node_destroy(VNode *vnode)
+{
+ allqueue(REDRAWOOPS, 0);
+
+ /* TODO: destroy bindings between vnode and blender data structures */
+}
+
+/*
+ * this function is calles after renaming of VerseNode by verse_server
+ */
+void post_node_name_set(VNode *vnode)
+{
+ /* if VerseNode has coresponding blender data structure, then
+ * change ID name of data structure */
+ if(vnode->type==V_NT_OBJECT) {
+ struct Object *ob;
+ ob = (Object*)((VObjectData*)vnode->data)->object;
+ if(ob) {
+ char *str;
+ str = (char*)malloc(sizeof(char)*(strlen(vnode->name)+3));
+ str[0] = '\0';
+ strcat(str, "OB");
+ strcat(str, vnode->name);
+ strncpy(ob->id.name, str, 23);
+ printf("\tob->id.name: %s\n", ob->id.name);
+ free(str);
+ }
+ }
+ else if(vnode->type==V_NT_GEOMETRY) {
+ struct Mesh *me;
+
+ me = (Mesh*)((VGeomData*)vnode->data)->mesh;
+ if(me) {
+ char *str;
+ str = (char*)malloc(sizeof(char)*(strlen(vnode->name)+3));
+ str[0] = '\0';
+ strcat(str, "ME");
+ strcat(str, vnode->name);
+ strncpy(me->id.name, str, 23);
+ printf("\tme->id.name: %s\n", me->id.name);
+ free(str);
+ }
+ }
+
+ allqueue(REDRAWALL, 0);
+}
+
+/*
+ * this function is called after acception connection with verse server
+ */
+void post_connect_accept(VerseSession *session)
+{
+ G.f |= G_VERSE_CONNECTED;
+
+ session->counter = 0;
+
+ allqueue(REDRAWOOPS, 0);
+}
+
+/*
+ * this function is called, when connestion with verse server is ended/terminated/etc.
+ */
+void post_connect_terminated(VerseSession *session)
+{
+ /* if it is last session, then no other will exist ... set Global flag */
+ if((session->prev==NULL) && (session->next==NULL))
+ G.f &= ~G_VERSE_CONNECTED;
+
+ allqueue(REDRAWOOPS, 0);
+}
+
+/*
+ * if connection wasn't accepted, then free VerseSession
+ * and print warning message with popupmenu
+ */
+void post_connect_update(VerseSession *session)
+{
+ if(session->flag & VERSE_CONNECTING) {
+ session->counter++;
+ if(session->counter > MAX_UNCONNECTED_EVENTS) {
+ char *str;
+ /* popup menu*/
+ str = malloc(sizeof(char)*(strlen(session->address)+35));
+ str[0]='\0';
+ strcat(str, "Error%t|No response from server: ");
+ strcat(str, session->address);
+ pupmenu(str);
+ free(str);
+
+ session->flag = 0;
+ session->counter = 0;
+ session->post_connect_terminated(session);
+ free_verse_session(session);
+ }
+ }
+}
+
+#endif
+
diff --git a/source/blender/src/verse_image.c b/source/blender/src/verse_image.c
new file mode 100644
index 00000000000..78da14220e8
--- /dev/null
+++ b/source/blender/src/verse_image.c
@@ -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 "mydevice.h"
+
+#include "BKE_verse.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_image_types.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "BDR_drawmesh.h"
+
+#include "BIF_verse.h"
+#include "BIF_space.h"
+
+/*
+ * unsubscribe from verse bitmap
+ */
+void unsubscribe_from_bitmap_node(VNode *vnode)
+{
+ if(vnode->type != V_NT_BITMAP) return;
+
+ /* TODO */
+}
+
+/*
+ * upload image to verse server
+ */
+void push_image_to_verse_server(VerseSession *session, Image *image)
+{
+ struct VNode *vnode;
+
+ if(!session) return;
+
+ if(!(session->flag & VERSE_CONNECTED)) return;
+
+ /* create "my" new object VerseNode */
+ vnode= create_verse_node(session->vsession, -1 , V_NT_BITMAP, VN_OWNER_MINE);
+ /* create object data */
+ vnode->data = create_bitmap_data();
+
+ /* set up name of VerseNode */
+ vnode->name = (char*)MEM_mallocN(sizeof(char*)*(strlen(image->id.name)-1), "object node name");
+ vnode->name[0] = '\0';
+ strcat(vnode->name, image->id.name+2);
+
+ /* set up dimension of image */
+ if(image->ibuf) {
+ ((VBitmapData*)vnode->data)->width = image->ibuf->x;
+ ((VBitmapData*)vnode->data)->height = image->ibuf->y;
+ }
+ else {
+ ((VBitmapData*)vnode->data)->width = 0;
+ ((VBitmapData*)vnode->data)->height = 0;
+ }
+ ((VBitmapData*)(vnode->data))->height = 1;
+
+ /* set up pointers between Object and VerseNode */
+ ((VBitmapData*)vnode->data)->image = (void*)image;
+ image->vnode = (void*)vnode;
+
+ /* add node to sending queue */
+ add_item_to_send_queue(&(session->queue), vnode, VERSE_NODE);
+}
+
+/*
+ * synchronize blender image channel (R,G,B,A) with verse bitmap layer
+ */
+void sync_blender_image_channel_with_verse_layer(VNode *vnode, VBitmapLayer *vblayer)
+{
+ struct Image *image = (Image*)((VBitmapData*)(vnode->data))->image;
+ struct ImBuf *ibuf;
+ unsigned char *rect;
+ int x, y, height, t_width, i, channel=0;
+
+ if(!image) return;
+
+ ibuf = image->ibuf;
+ if(!ibuf) return;
+
+ rect = (unsigned char*)ibuf->rect;
+
+ /* select channel due to verse layer name */
+ if(strcmp(vblayer->name,"col_r")==0)
+ channel = 0;
+ else if(strcmp(vblayer->name,"col_g")==0)
+ channel = 1;
+ else if(strcmp(vblayer->name, "col_b")==0)
+ channel = 2;
+ else if(strcmp(vblayer->name,"alpha")==0)
+ channel = 3;
+
+#ifdef VERSE_DEBUG_PRINT
+ printf(" %s:%d\n", vblayer->name, channel);
+#endif
+
+ height = ((VBitmapData*)(vnode->data))->height;
+ t_width = ((VBitmapData*)(vnode->data))->t_width;
+
+ i = (height-1)*t_width;
+
+#ifdef VERSE_DEBUG_PRINT
+ printf("\ti:%d\n", i);
+#endif
+
+ if(vblayer->type==VN_B_LAYER_UINT8) {
+ unsigned char *vuint8 = (unsigned char*)vblayer->data;
+ for(y=height-1; y>=0; y--, i=y*t_width)
+ for(x=0; x<ibuf->x; x++, rect+=4, i++)
+ rect[channel] = (char)vuint8[i];
+ }
+
+ allqueue(REDRAWIMAGE, 0);
+ allqueue(REDRAWVIEW3D, 0);
+}
+
+/*
+ * synchronize blender image with verse image
+ */
+void sync_blender_image_with_verse_bitmap_node(VNode *vnode)
+{
+ struct VBitmapLayer *vblayer;
+
+ vblayer = ((VBitmapData*)(vnode->data))->layers.lb.first;
+
+ while(vblayer) {
+#ifdef VERSE_DEBUG_PRINT
+ printf("\tsyncing layer:");
+#endif
+ sync_blender_image_channel_with_verse_layer(vnode, vblayer);
+ vblayer = vblayer->next;
+ }
+}
+
+/*
+ * This function is called, when some other verse client change dimension of image.
+ * It is neccesary to reallocate blender image too, when dimension of verse image
+ * is different from blender image.
+ */
+void post_bitmap_dimension_set(VNode *vnode)
+{
+ struct Image *image = (Image*)((VBitmapData*)(vnode->data))->image;
+ struct ImBuf *ibuf;
+
+ if(!image) return;
+
+ ibuf = image->ibuf;
+ if(!ibuf) return;
+
+ if(vnode->owner_id == VN_OWNER_MINE) {
+ if( ((VBitmapData*)vnode->data)->layers.lb.first == NULL ) {
+ /* send all verse bitmap layers (RGBA) to verse server */
+ printf("\tsending all bitmap layers to verse server\n");
+ verse_send_b_layer_create(vnode->id, -1, "col_r", VN_B_LAYER_UINT8);
+ verse_send_b_layer_create(vnode->id, -1, "col_g", VN_B_LAYER_UINT8);
+ verse_send_b_layer_create(vnode->id, -1, "col_b", VN_B_LAYER_UINT8);
+ verse_send_b_layer_create(vnode->id, -1, "alpha", VN_B_LAYER_UINT8);
+
+ return;
+ }
+ }
+
+ if((ibuf->x!=((VBitmapData*)vnode->data)->width) || (ibuf->y!=((VBitmapData*)vnode->data)->height)) {
+ struct VBitmapLayer *vblayer;
+ struct ImBuf *new_ibuf;
+
+ /* allocate new ibuf */
+ new_ibuf= IMB_allocImBuf(((VBitmapData*)vnode->data)->width,
+ ((VBitmapData*)vnode->data)->height, 24, IB_rect, 0);
+ /* free old ibuf */
+ IMB_freeImBuf(ibuf);
+ /* set up pointer at new ibuf */
+ image->ibuf = new_ibuf;
+
+ /* sync blender image with all verse layers */
+ vblayer = ((VBitmapData*)(vnode->data))->layers.lb.first;
+ while(vblayer) {
+ sync_blender_image_channel_with_verse_layer(vnode, vblayer);
+ vblayer = vblayer->next;
+ }
+ }
+}
+
+/*
+ * when blender tries to upload image to verse server, then it is neccessary
+ * to push coresponding channel data to verse server, when verse bitmap layer
+ * was created
+ */
+void post_bitmap_layer_create(VBitmapLayer *vblayer)
+{
+ struct VNode *vnode = vblayer->vnode;
+ struct Image *image = (Image*)((VBitmapData*)(vnode->data))->image;
+ struct ImBuf *ibuf;
+ unsigned char *rect;
+ short channel;
+/* VNBTile tile[VN_B_TILE_SIZE*VN_B_TILE_SIZE];
+ unsigned int width, t_width, height, t_height, x, y, i, j; */
+
+ /* if this application doesn't try to upload this image to verse
+ * server then do nothing */
+ if(vnode->owner_id != VN_OWNER_MINE) return;
+
+ if(!image) return;
+
+ ibuf = image->ibuf;
+ if(!ibuf) return;
+
+ rect = (unsigned char*)ibuf->rect;
+
+ if(strncmp(vblayer->name, "col_r", 5))
+ channel = 0;
+ else if(strncmp(vblayer->name, "col_g", 5))
+ channel = 1;
+ else if(strncmp(vblayer->name, "col_b", 5))
+ channel = 2;
+ else if(strncmp(vblayer->name, "alpha", 5))
+ channel = 3;
+
+ /* TODO: send all data of channel to verse server */
+}
+
+/*
+ * dummy function now
+ */
+void post_bitmap_layer_destroy(VBitmapLayer *vblayer)
+{
+}
+
+/*
+ * this function is executed, when some image changed tile comes from verse server,
+ * it is neccessary to do some crazy transformation here, because blender uses
+ * different (very unstandard) image coordinate system (begining of coordinate
+ * system is in bottom left corner) ... all other programs (including verse) has
+ * begining of image coordinate system in left top corner
+ */
+void post_bitmap_tile_set(VBitmapLayer *vblayer, unsigned int xs, unsigned int ys)
+{
+ struct VNode *vnode = vblayer->vnode;
+ struct Image *image = (Image*)((VBitmapData*)(vnode->data))->image;
+ struct ImBuf *ibuf;
+ unsigned char *rect, *i_rect;
+ unsigned int x, y, t_width, t_height, height, m_ys, m_y, d, i, j, channel=0;
+
+ if(!image) return;
+
+ ibuf = image->ibuf;
+ if(!ibuf) return;
+
+ /* select channel due to verse layer name */
+ if(strcmp(vblayer->name,"col_r")==0)
+ channel = 0;
+ else if(strcmp(vblayer->name,"col_g")==0)
+ channel = 1;
+ else if(strcmp(vblayer->name, "col_b")==0)
+ channel = 2;
+ else if(strcmp(vblayer->name,"alpha")==0)
+ channel = 3;
+
+ i_rect = rect = (unsigned char*)ibuf->rect;
+
+ /* width of verse image including all tiles */
+ t_width =((VBitmapData*)vnode->data)->t_width;
+ /* height of verse image including all tiles */
+ t_height =((VBitmapData*)vnode->data)->t_height;
+ /* height of blender image */
+ height = ((VBitmapData*)vnode->data)->height;
+
+ /* if the bitmap's dimensions are not integer multiples of the tile
+ * side length, eight, then d will not be zero (height of "uncomplete
+ * tile") */
+ d = VN_B_TILE_SIZE - (t_height - height);
+ /* mirrored coordination of received tile */
+ m_ys = t_height - ys - VN_B_TILE_SIZE;
+
+ /* ys and m_ys are y axis, where we will do some changes */
+ if(ys + VN_B_TILE_SIZE > height) {
+ m_ys = 0;
+ ys = ys + d - 1;
+ }
+ else {
+ m_ys = m_ys - VN_B_TILE_SIZE + d;
+ ys = ys + VN_B_TILE_SIZE - 1;
+ }
+
+ /* "index" of blender image */
+ j = m_ys*ibuf->x + xs;
+ /* index of verse image */
+ i = ys*t_width + xs;
+
+ /* pointer at image data, that will be changed in following loop */
+ rect = i_rect + 4*j;
+
+ /* it seems hackish, but I didn't find better solution :-/ */
+ if(vblayer->type==VN_B_LAYER_UINT8) {
+ unsigned char *vuint8 = (unsigned char*)vblayer->data;
+ for(y=ys, m_y = m_ys;
+ (m_y<m_ys+VN_B_TILE_SIZE) && (m_y<ibuf->y);
+ y--, m_y++, i=y*t_width+xs, j=m_y*ibuf->x+xs, rect=i_rect+4*j)
+ for(x=xs; (x<xs+VN_B_TILE_SIZE) && (x<ibuf->x); x++, rect+=4, i++, j++)
+ rect[channel] = (char)vuint8[i];
+ }
+
+ free_realtime_image(image);
+
+ /* redraw preview of image ... uncommented, because rendering
+ * was computed too often */
+/* BIF_preview_changed(ID_TE); */
+ allqueue(REDRAWIMAGE, 0);
+ allqueue(REDRAWVIEW3D, 0);
+}
+
+#endif
+
diff --git a/source/blender/src/verse_mesh.c b/source/blender/src/verse_mesh.c
new file mode 100644
index 00000000000..7e3479e3144
--- /dev/null
+++ b/source/blender/src/verse_mesh.c
@@ -0,0 +1,1611 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Contributor(s): Jiri Hnidek.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifdef WITH_VERSE
+
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "mydevice.h"
+
+#include "DNA_object_types.h"
+#include "DNA_mesh_types.h"
+
+#include "BLI_dynamiclist.h"
+#include "BLI_blenlib.h"
+#include "BLI_editVert.h"
+
+#include "BKE_global.h"
+#include "BKE_verse.h"
+#include "BKE_mesh.h"
+#include "BKE_depsgraph.h"
+#include "BKE_utildefines.h"
+
+#include "BIF_verse.h"
+#include "BIF_editmesh.h"
+#include "BIF_space.h"
+#include "BIF_screen.h"
+
+#include "BSE_edit.h"
+
+#include "editmesh.h"
+
+#include "verse.h"
+
+/* prototypes of static functions */
+
+static void mark_changed_face_obsolete(struct VerseFace *vface);
+static void sync_verseface_with_editface(struct VLayer *vlayer, struct VerseFace *vface);
+
+void createVerseVertNL(struct EditVert *ev, struct VNode *vnode, struct VLayer *vlayer);
+static void createAllVerseVerts(struct VNode *vnode, struct VLayer *vlayer);
+void createVerseFaceNL(struct EditFace *efa, struct VNode *vnode, struct VLayer *vlayer);
+static void createAllVerseFaces(struct VNode *vnode, struct VLayer *vlayer);
+
+/*=============================================================================
+ *
+ * functions handling verse/blender FACES
+ *
+ *===========================================================================*/
+
+/*
+ * create new VerseFace (polygon), due to information about EditFace
+ * put VerseFace to queue ... send to verse host (server)
+ */
+void createVerseFace(EditFace *efa)
+{
+ if(G.editMesh->vnode) {
+ struct VLayer *vlayer = find_verse_layer_type((VGeomData*)((VNode*)G.editMesh->vnode)->data, POLYGON_LAYER);
+ createVerseFaceNL(efa, (VNode*)G.editMesh->vnode, vlayer);
+ }
+ else efa->vface = NULL;
+}
+
+/*
+ * create new VerseFace (polygon), due to information about EditFace
+ * put VerseFace to queue ... send to verse host (server)
+ * NL version of function (infomration about verse node and
+ * layer is known ... optimalisation)
+ */
+void createVerseFaceNL(EditFace *efa, VNode *vnode, VLayer *vlayer)
+{
+ struct VerseFace *vface;
+
+ vface = (VerseFace*)create_verse_face(vlayer, vlayer->counter, -1, -1, -1, -1);
+
+ vface->face = (void*)efa;
+ efa->vface = (void*)vface;
+
+ vface->flag |= FACE_SEND_READY;
+
+ /* EditVert #1 */
+ if(efa->v1) {
+ if(efa->v1->vvert) {
+ vface->vvert0 = (VerseVert*)efa->v1->vvert;
+ if(((VerseVert*)efa->v1->vvert)->flag & VERT_RECEIVED) {
+ vface->v0 = ((VerseVert*)efa->v1->vvert)->id;
+ vface->counter--;
+ }
+ else
+ vface->flag &= ~FACE_SEND_READY;
+ }
+ }
+ else
+ vface->counter--;
+
+ /* EditVert #2 */
+ if(efa->v2) {
+ if(efa->v2->vvert) {
+ vface->vvert1 = (VerseVert*)efa->v2->vvert;
+ if(((VerseVert*)efa->v2->vvert)->flag & VERT_RECEIVED) {
+ vface->v1 = ((VerseVert*)efa->v2->vvert)->id;
+ vface->counter--;
+ }
+ else
+ vface->flag &= ~FACE_SEND_READY;
+ }
+ }
+ else
+ vface->counter--;
+ /* EditVert #3 */
+ if(efa->v3) {
+ if(efa->v3->vvert) {
+ vface->vvert2 = (VerseVert*)efa->v3->vvert;
+ if(((VerseVert*)efa->v3->vvert)->flag & VERT_RECEIVED) {
+ vface->v2 = ((VerseVert*)efa->v3->vvert)->id;
+ vface->counter--;
+ }
+ else
+ vface->flag &= ~FACE_SEND_READY;
+ }
+ }
+ else
+ vface->counter--;
+ /* EditVert #4 */
+ if(efa->v4) {
+ if(efa->v4->vvert) {
+ vface->vvert3 = (VerseVert*)efa->v4->vvert;
+ if(((VerseVert*)efa->v4->vvert)->flag & VERT_RECEIVED) {
+ vface->v3 = ((VerseVert*)efa->v4->vvert)->id;
+ vface->counter--;
+ }
+ else
+ vface->flag &= ~FACE_SEND_READY;
+ }
+ }
+ else
+ vface->counter--;
+
+ add_item_to_send_queue(&(vlayer->queue), (void*)vface, VERSE_FACE);
+}
+
+/*
+ * creates new verse faces, add all of then to queue ... send to verse server
+ */
+static void createAllVerseFaces(VNode *vnode, VLayer *vlayer)
+{
+ if(G.obedit) {
+ struct EditMesh *em;
+ struct EditFace *efa;
+
+ em = G.editMesh;
+
+ efa = em->faces.first;
+ /* push all EditFaces to the verse server */
+ while(efa){
+ createVerseFaceNL(efa, vnode, vlayer);
+ efa = efa->next;
+ }
+ }
+}
+
+/*
+ * When verse face is changed during sending/receiving from verse server, then
+ * this verse face is marked as obsolete and it will be send again, when it
+ * will be received from verse server
+ */
+static void mark_changed_face_obsolete(VerseFace *vface)
+{
+ struct EditFace *efa = (EditFace*)vface->face;
+
+ if(efa) {
+ if(vface->vvert0->vertex != efa->v1) vface->flag |= FACE_OBSOLETE;
+ if(vface->vvert1->vertex != efa->v2) vface->flag |= FACE_OBSOLETE;
+ if(vface->vvert2->vertex != efa->v3) vface->flag |= FACE_OBSOLETE;
+ if(vface->vvert3 && (vface->vvert3->vertex != efa->v4)) vface->flag |= FACE_OBSOLETE;
+ }
+}
+
+/*
+ * this function will sync EditFace and VerseFace and it will send changes to
+ * verse server too
+ */
+static void sync_verseface_with_editface(VLayer *vlayer, VerseFace *vface)
+{
+ struct EditFace *efa = (EditFace*)vface->face;
+ int dosend = 0;
+
+ /* edit face and probably verse face was deleted */
+ if(!efa || (vface->flag & FACE_DELETED)) return;
+
+ /* blender nor verse don't support such crazy things */
+ if(!(vface->vvert0) || !(vface->vvert1) || !(vface->vvert2)) {
+ printf("\tERROR: vface->vvert0: %p, vface->vvert1: %p, vface->vvert2: %p\n", vface->vvert0, vface->vvert1, vface->vvert2);
+ return;
+ }
+
+ /* initialize verse face flag */
+ vface->flag |= FACE_SEND_READY;
+
+ /* debug print */
+#if 0
+ printf("\n");
+ if(efa->v4) {
+ printf("\tefa->v1,v2,v3,v4->vvert->id: %d, %d, %d, %d\n",
+ ((VerseVert*)efa->v1->vvert)->id,
+ ((VerseVert*)efa->v2->vvert)->id,
+ ((VerseVert*)efa->v3->vvert)->id,
+ ((VerseVert*)efa->v4->vvert)->id);
+ printf("\tefa->v1,v2,v3,v4->vvert: %p, %p, %p, %p\n",
+ efa->v1->vvert,
+ efa->v2->vvert,
+ efa->v3->vvert,
+ efa->v4->vvert);
+ }
+ else {
+ printf("\tefa->v1,v2,v3->vvert->id: %d, %d, %d, NULL\n",
+ ((VerseVert*)efa->v1->vvert)->id,
+ ((VerseVert*)efa->v2->vvert)->id,
+ ((VerseVert*)efa->v3->vvert)->id);
+ printf("\tefa->v1,v2,v3,v4->vvert: %p, %p, %p, NULL\n",
+ efa->v1->vvert,
+ efa->v2->vvert,
+ efa->v3->vvert);
+ }
+ printf("\tvface->vvert0, vvvert1, vvvert2, vvvert3: %p, %p, %p, %p\n",
+ vface->vvert0,
+ vface->vvert1,
+ vface->vvert2,
+ vface->vvert3);
+
+ printf("\tefa->v1, v2, v3, v4: %p, %p, %p, %p\n",
+ efa->v1,
+ efa->v2,
+ efa->v3,
+ efa->v4);
+ if(vface->vvert3) {
+ printf("\tvface->v0,v1,v2,v3: %d, %d, %d, %d\n",
+ vface->v0,
+ vface->v1,
+ vface->v2,
+ vface->v3);
+ printf("\tvface->vvert0,vvvert1,vvvert2,vvvert3->vertex: %p, %p, %p, %p\n",
+ vface->vvert0->vertex,
+ vface->vvert1->vertex,
+ vface->vvert2->vertex,
+ vface->vvert3->vertex);
+ }
+ else {
+ printf("\tvface->v0,v1,v2,v3: %d, %d, %d, NULL\n",
+ vface->v0,
+ vface->v1,
+ vface->v2);
+ printf("\tvface->vvert0,vvvert1,vvvert2->vertex: %p, %p, %p, NULL\n",
+ vface->vvert0->vertex,
+ vface->vvert1->vertex,
+ vface->vvert2->vertex);
+ }
+#endif
+
+ /* initialize counter of unreceived vertexes */
+ vface->counter = 4;
+
+ /* 1st vertex */
+ if(vface->vvert0->vertex != efa->v1) {
+ dosend = 1;
+ vface->vvert0->counter--;
+ vface->vvert0 = (VerseVert*)efa->v1->vvert;
+ vface->v0 = vface->vvert0->id;
+ if(vface->vvert0->flag & VERT_RECEIVED)
+ vface->counter--;
+ else
+ vface->flag &= ~FACE_SEND_READY;
+ }
+ else
+ vface->counter--;
+
+ /* 2nd vertex */
+ if(vface->vvert1->vertex != efa->v2) {
+ dosend = 1;
+ vface->vvert1->counter--;
+ vface->vvert1 = (VerseVert*)efa->v2->vvert;
+ vface->v1 = vface->vvert1->id;
+ if(vface->vvert1->flag & VERT_RECEIVED)
+ vface->counter--;
+ else
+ vface->flag &= ~FACE_SEND_READY;
+ }
+ else
+ vface->counter--;
+
+ /* 3th vertex */
+ if(vface->vvert2->vertex != efa->v3) {
+ dosend = 1;
+ vface->vvert2->counter--;
+ vface->vvert2 = (VerseVert*)efa->v3->vvert;
+ vface->v2 = vface->vvert2->id;
+ if(vface->vvert2->flag & VERT_RECEIVED)
+ vface->counter--;
+ else
+ vface->flag &= ~FACE_SEND_READY;
+ }
+ else
+ vface->counter--;
+
+ /* 4th vertex */
+ if(vface->vvert3 && ((vface->vvert3->vertex != efa->v4) || (vface->vvert3 && !efa->v4) || (vface->v3 != vface->vvert3->id))) {
+ dosend = 1;
+ if(efa->v4) {
+ vface->vvert3->counter--;
+ vface->vvert3 = (VerseVert*)efa->v4->vvert;
+ vface->v3 = vface->vvert3->id;
+ if(vface->vvert3->flag & VERT_RECEIVED)
+ vface->counter--;
+ else
+ vface->flag &= ~FACE_SEND_READY;
+ }
+ else {
+ vface->vvert3->counter--;
+ vface->vvert3 = NULL;
+ vface->v3 = -1;
+ vface->counter--;
+ }
+ }
+ /* verse face has 4 vertexes now, not 3 vertexes as in past */
+ else if(!(vface->vvert3) && efa->v4) {
+ dosend = 1;
+ vface->vvert3 = (VerseVert*)efa->v4->vvert;
+ vface->v3 = vface->vvert3->id;
+ if(vface->vvert3->flag & VERT_RECEIVED)
+ vface->counter--;
+ else
+ vface->flag &= ~FACE_SEND_READY;
+ }
+ else
+ vface->counter--;
+
+ if(dosend) {
+ /* printf("\tsending CHANGED FACE\n");
+ printf("\t\tnew: %d %d %d %d\n", vface->v0, vface->v1, vface->v2, vface->v3);*/
+ vface->flag |= FACE_CHANGED;
+ /* remove verse face from list of received faces */
+ BLI_dlist_rem_item(&(vlayer->dl), vface->id);
+ /* and add verse face again to sending queue */
+ add_item_to_send_queue(&(vlayer->queue), (void*)vface, VERSE_FACE);
+ }
+}
+
+/*
+ * this function will sync all VerseFaces with coresponding EditFaces,
+ * this is useful, when some editmesh tool has changed editface pointers at
+ * vertexes (edges), parameter of this function is geometry node
+ */
+void sync_all_versefaces_with_editfaces(VNode *vnode)
+{
+ struct VLayer *vlayer;
+ struct VerseFace *vface, *nvface;
+
+ if(vnode->type != V_NT_GEOMETRY) return;
+
+ vlayer = find_verse_layer_type((VGeomData*)vnode->data, POLYGON_LAYER);
+
+ /* mark changed verse faces in sending queue as obsolete at the first time */
+ vface = vlayer->queue.first;
+ while(vface) {
+ mark_changed_face_obsolete(vface);
+ vface = vface->next;
+ }
+
+ /* send all received and changed verse face again to verse server */
+ vface = vlayer->dl.lb.first;
+ while(vface) {
+ nvface = vface->next;
+ sync_verseface_with_editface(vlayer, vface);
+ vface = nvface;
+ }
+}
+
+/*
+ * send delete polygon command to verse server
+ */
+void b_verse_send_face_delete(EditFace *efa)
+{
+ ((VerseFace*)efa->vface)->face = NULL;
+ send_verse_face_delete((VerseFace*)efa->vface);
+ efa->vface = NULL;
+}
+
+/*=============================================================================
+ *
+ * functions handling verse/blender VERTEXES
+ *
+ *===========================================================================*/
+
+/*
+ * this function will sync position of all VerseVerts with EditVerts
+ * this function is called after actions: Smooth, Noise and To Sphere,
+ * because position of vertexes isn't managed by transform system
+ */
+void sync_all_verseverts_with_editverts(VNode *vnode)
+{
+ struct VLayer *vlayer;
+ struct VerseVert *vvert;
+
+ if(vnode->type != V_NT_GEOMETRY) return;
+
+ vlayer = find_verse_layer_type((VGeomData*)vnode->data, VERTEX_LAYER);
+
+ vvert = vlayer->dl.lb.first;
+
+ /* sync all received vertexes */
+ while(vvert) {
+ send_versevert_pos(vvert);
+ vvert = vvert->next;
+ }
+
+ vvert = vlayer->queue.first;
+
+ /* sync all unreceived vertexes (mar pos as obsolete, when
+ * actual position was changed) */
+ while(vvert) {
+ send_versevert_pos(vvert);
+ vvert = vvert->next;
+ }
+
+ verse_callback_update(0);
+}
+
+/*
+ * send delete vertex command to verse server
+ */
+void b_verse_send_vertex_delete(EditVert *eve)
+{
+ ((VerseVert*)eve->vvert)->vertex = NULL;
+ send_verse_vertex_delete((VerseVert*)eve->vvert);
+ eve->vvert = NULL;
+}
+
+/*
+ * send position of verse vertex to verse server
+ */
+void send_versevert_pos(VerseVert *vvert)
+{
+ /* don't send position of verse vertex to verse server, because it could create
+ * new vertex */
+ if(vvert->flag & VERT_RECEIVED && !(vvert->flag & VERT_DELETED)) {
+ if(vvert->flag & VERT_LOCKED) {
+ /* when position of verse vert was sent to verse server
+ * and it wasn't received yet, then mark sent position
+ * as obsolete ... blender will automaticaly send actual
+ * position, when old will be received */
+ vvert->flag |= VERT_POS_OBSOLETE;
+/* printf("\tsend_versevert_pos: %d mark OBSOLETE\n", vvert->id);*/
+ }
+ else {
+ struct EditVert *eve = (EditVert*)vvert->vertex;
+ /* send position to verse server, when it is different from actual position */
+ if(eve && (eve->co[0]!=vvert->co[0] || eve->co[1]!=vvert->co[1] || eve->co[2]!=vvert->co[2])) {
+ /* lock vertex and send its position to verse server */
+ vvert->flag |= VERT_LOCKED;
+ VECCOPY(vvert->co, eve->co);
+/* printf("\tsend_versevert_pos: %d send and LOCK \n", vvert->id);*/
+ send_verse_vertex(vvert);
+ }
+ }
+ }
+
+ if(!(vvert->flag & VERT_RECEIVED) && (vvert->flag & VERT_LOCKED)) {
+ struct EditVert *eve = (EditVert*)vvert->vertex;
+ if(eve && (eve->co[0]!=vvert->co[0] || eve->co[1]!=vvert->co[1] || eve->co[2]!=vvert->co[2])) {
+/* printf("\tsend_versevert_pos: %d mark VERT_POS_OBSOLETE\n", vvert->id); */
+ vvert->flag |= VERT_POS_OBSOLETE;
+ }
+ }
+
+ verse_callback_update(0);
+}
+
+/*
+ * create new VerseVert due to information about EditVert,
+ * put VerseVert to queue ... send to verse host (server)
+ */
+void createVerseVert(EditVert *eve)
+{
+ if(G.editMesh->vnode) {
+ struct VLayer *vlayer = find_verse_layer_type((VGeomData*)((VNode*)G.editMesh->vnode)->data, VERTEX_LAYER);
+ createVerseVertNL(eve, (VNode*)G.editMesh->vnode, vlayer);
+ }
+ else eve->vvert = NULL;
+}
+
+/*
+ * create new VerseVert due to information about EditVert,
+ * put VerseVert to queue ... send to verse host (server)
+ * NL version of function (infomration about verse node and
+ * layer is known ... optimalisation)
+ */
+void createVerseVertNL(EditVert *eve, VNode *vnode, VLayer *vlayer)
+{
+ struct VerseVert *vvert;
+
+ vvert = create_verse_vertex(vlayer, vlayer->counter, eve->co[0], eve->co[1], eve->co[2]);
+
+ vvert->vertex = (void*)eve;
+ eve->vvert = (void*)vvert;
+
+ vvert->flag |= VERT_LOCKED;
+
+/* printf("\tsend_versevert_pos: %d create and LOCK \n", vvert->id);*/
+
+ /* add vvert to sending queue */
+ add_item_to_send_queue(&(vlayer->queue), (void*)vvert, VERSE_VERT);
+}
+
+/*
+ * create new verse vertexes due to all vertexes and send all of them to verse server
+ */
+static void createAllVerseVerts(VNode *vnode, VLayer *vlayer)
+{
+ if(G.obedit) {
+ struct EditMesh *em;
+ struct EditVert *eve;
+
+ em = G.editMesh;
+ eve = em->verts.first;
+
+ /* push all EditVertexes to the verse server */
+ while(eve){
+ createVerseVertNL(eve, vnode, vlayer);
+ eve = eve->next;
+ }
+ }
+}
+
+/*
+ * unsubscribe from verse geometry layers of verse geometry node
+ * and clear bindings between verse node and mesh
+ */
+void unsubscribe_from_geom_node(VNode *vnode)
+{
+ struct VerseSession *session = vnode->session;
+
+ struct VLayer *vlayer = ((VGeomData*)vnode->data)->layers.lb.first;
+
+ if(vnode->type != V_NT_GEOMETRY) return;
+
+ if(((VGeomData*)vnode->data)->mesh) {
+ ((Mesh*)((VGeomData*)vnode->data)->mesh)->vnode = NULL;
+ ((VGeomData*)vnode->data)->mesh = NULL;
+ }
+
+ if(((VGeomData*)vnode->data)->editmesh) {
+ ((EditMesh*)((VGeomData*)vnode->data)->editmesh)->vnode = NULL;
+ ((VGeomData*)vnode->data)->editmesh = NULL;
+ }
+
+ while(vlayer) {
+ BLI_dlist_reinit(&(vlayer->dl));
+ BLI_freelistN(&(vlayer->queue));
+ BLI_freelistN(&(vlayer->orphans));
+
+ if(session->flag & VERSE_CONNECTED)
+ verse_send_g_layer_unsubscribe(vnode->id, vlayer->id);
+
+ vlayer = vlayer->next;
+ }
+
+}
+
+/* ===================================================================================
+ *
+ * Function executed after execution of callback functions
+ *
+ * ===================================================================================*/
+
+/*
+ * Actions executed after new VerseLayer is created
+ */
+void post_layer_create(struct VLayer *vlayer)
+{
+ /* if we are owners of VerseNode, then push geometry to verse server */
+ if(vlayer->vnode->owner_id == VN_OWNER_MINE) {
+ switch(vlayer->type){
+ case VN_G_LAYER_VERTEX_XYZ:
+/* if(vlayer->id==0) createAllVerseVerts(vlayer->vnode, vlayer);
+ break;*/
+ case VN_G_LAYER_POLYGON_CORNER_UINT32:
+/* if(vlayer->id==1) createAllVerseFaces(vlayer->vnode, vlayer);
+ break;*/
+ case VN_G_LAYER_VERTEX_UINT32:
+ case VN_G_LAYER_VERTEX_REAL:
+ case VN_G_LAYER_POLYGON_CORNER_REAL:
+ case VN_G_LAYER_POLYGON_FACE_UINT8:
+ case VN_G_LAYER_POLYGON_FACE_UINT32:
+ case VN_G_LAYER_POLYGON_FACE_REAL:
+ break;
+ }
+ }
+ else {
+ switch(vlayer->type) {
+ case VN_G_LAYER_VERTEX_XYZ:
+ case VN_G_LAYER_POLYGON_CORNER_UINT32:
+ case VN_G_LAYER_VERTEX_UINT32:
+ case VN_G_LAYER_VERTEX_REAL:
+ case VN_G_LAYER_POLYGON_CORNER_REAL:
+ case VN_G_LAYER_POLYGON_FACE_UINT8:
+ case VN_G_LAYER_POLYGON_FACE_UINT32:
+ case VN_G_LAYER_POLYGON_FACE_REAL:
+ break;
+ }
+ }
+}
+
+/*
+ * Actions after destroying of VerseLayer
+ */
+void post_layer_destroy(struct VLayer *vlayer)
+{
+}
+
+/*
+ * Actions executed after creating of new VerseVert, when object is in edit
+ * mode, and this client didn't create this VerseVert (vvert->vertex is NULL),
+ * then new editvert is created
+ */
+void post_vertex_create(VerseVert *vvert)
+{
+ struct VNode *obj_vnode;
+ struct VNode *geom_vnode = vvert->vlayer->vnode;
+ struct EditMesh *em=NULL;
+
+ if(G.obedit && (((Mesh*)G.obedit->data)->vnode==geom_vnode)) {
+ em = (EditMesh*)((VGeomData*)geom_vnode->data)->editmesh;
+ }
+
+ /* when vert was changed during sending to verse server, then
+ * we have to send it to verse server again */
+ if(vvert->flag & VERT_POS_OBSOLETE) {
+ vvert->flag &= ~VERT_POS_OBSOLETE;
+
+ if(em && (vvert->vertex)) {
+ struct EditVert *eve = (EditVert*)vvert->vertex;
+ VECCOPY(vvert->co, eve->co);
+/* printf("\tpost_vertex_create: %d send and NOT_OBSOLETE\n", vvert->id);*/
+ send_verse_vertex(vvert);
+ verse_callback_update(0);
+
+ return;
+ }
+ }
+
+ if(em && !(vvert->vertex)) {
+ struct EditVert *eve;
+
+ /* to prevent never ending loop of sending and receiving
+ * vertexes, because addvertlist() sends new vertex to verse
+ * server if em->vnode isn't NULL */
+ em->vnode = NULL;
+ eve = addvertlist(vvert->co);
+ em->vnode = (void*)geom_vnode;
+
+ eve->vvert = (void*)vvert;
+ vvert->vertex = (void*)eve;
+
+ countall();
+
+ recalc_editnormals();
+ }
+
+ if(((VGeomData*)geom_vnode->data)->vlink) {
+ obj_vnode = ((VGeomData*)geom_vnode->data)->vlink->source;
+ DAG_object_flush_update(G.scene, (Object*)((VObjectData*)obj_vnode->data)->object, OB_RECALC_DATA);
+
+ allqueue(REDRAWVIEW3D, 1);
+ }
+}
+
+/*
+ * Actions executed, when position of VerseVert was changed
+ * position of EditVert is changed in edit mode
+ */
+void post_vertex_set_xyz(VerseVert *vvert)
+{
+ struct VNode *obj_vnode;
+ struct VNode *geom_vnode = vvert->vlayer->vnode;
+ struct EditVert *eve = NULL;
+
+ /* when vert was changed during sending to verse server, then
+ * we have to send it to verse server again */
+ if(vvert->flag & VERT_POS_OBSOLETE) {
+ if(vvert->vertex) {
+ vvert->flag &= ~VERT_POS_OBSOLETE;
+ vvert->flag |= VERT_LOCKED;
+
+ eve = (EditVert*)vvert->vertex;
+ VECCOPY(vvert->co, eve->co);
+/* printf("\tpost_vertex_set_xyz: %d send and NOT_OBSOLETE\n", vvert->id); */
+ send_verse_vertex(vvert);
+ verse_callback_update(0);
+ }
+ else {
+ printf("\terror: vvert->vertex shouldn't be NULL\n");
+ }
+
+ return;
+ }
+
+ /* when shared object is in edit mode, then update editmesh */
+ if(G.obedit && (((Mesh*)G.obedit->data)->vnode==geom_vnode)) {
+ if(vvert->vertex) {
+ eve = (EditVert*)vvert->vertex;
+/* printf("\tupdate pos of edit vert %d\n", vvert->id); */
+ VECCOPY(eve->co, vvert->co);
+ recalc_editnormals();
+ }
+ else {
+ printf("\terror: vvert->vertex shouldn't be NULL\n");
+ }
+ }
+
+ if(((VGeomData*)geom_vnode->data)->vlink) {
+ obj_vnode = ((VGeomData*)geom_vnode->data)->vlink->source;
+ DAG_object_flush_update(G.scene, (Object*)((VObjectData*)obj_vnode->data)->object, OB_RECALC_DATA);
+
+ allqueue(REDRAWVIEW3D, 1);
+ }
+}
+
+/*
+ * Actions executed after deleting of VerseVert
+ */
+void post_vertex_delete(VerseVert *vvert)
+{
+ struct VNode *obj_vnode;
+ struct VNode *geom_vnode = vvert->vlayer->vnode;
+ struct EditMesh *em = NULL;
+ struct EditEdge *ed, *edn;
+ struct EditVert *eve = NULL;
+
+ if(G.obedit && (((Mesh*)G.obedit->data)->vnode==geom_vnode)) {
+ em = (EditMesh*)((VGeomData*)geom_vnode->data)->editmesh;
+ eve = (EditVert*)vvert->vertex;
+ }
+
+ if(em && eve) {
+ /*printf("\tPOST_VERTEX_DELETE()\n");*/
+
+ /* delete all edges needing eve vertex */
+ ed = em->edges.first;
+ while(ed) {
+ edn = ed->next;
+ if(ed->v1==eve || ed->v2==eve) {
+ remedge(ed);
+ free_editedge(ed);
+ }
+ ed = edn;
+ }
+
+ eve->vvert = NULL;
+ BLI_remlink(&em->verts, eve);
+ free_editvert(eve);
+ vvert->vertex = NULL;
+
+ countall();
+
+ recalc_editnormals();
+ }
+
+ if(((VGeomData*)geom_vnode->data)->vlink) {
+ obj_vnode = ((VGeomData*)geom_vnode->data)->vlink->source;
+ DAG_object_flush_update(G.scene, (Object*)((VObjectData*)obj_vnode->data)->object, OB_RECALC_DATA);
+
+ allqueue(REDRAWVIEW3D, 1);
+ }
+}
+
+/*
+ * free constraint between VerseVert and EditVert
+ */
+void post_vertex_free_constraint(VerseVert *vvert)
+{
+ if(vvert->vertex) {
+ ((EditVert*)vvert->vertex)->vvert=NULL;
+ vvert->vertex=NULL;
+ }
+}
+
+/*
+ * Action executed after setting up uint8 value of polygon
+ */
+void post_polygon_set_uint8(VerseFace *vface)
+{
+}
+
+/*
+ * Action executed after creating of new VerseFace
+ */
+void post_polygon_create(VerseFace *vface)
+{
+ struct VNode *obj_vnode;
+ struct VNode *geom_vnode = vface->vlayer->vnode;
+ struct EditMesh *em = NULL;
+
+ /* if verse face was set as deleted during sending to verse server, then send
+ * delete command to verse server now ... we know verse face id */
+/* if(vface->flag & FACE_DELETED) {
+ send_verse_face_delete(vface);
+ return;
+ }*/
+
+ if(G.obedit && (((Mesh*)G.obedit->data)->vnode==geom_vnode)) {
+ em = (EditMesh*)((VGeomData*)geom_vnode->data)->editmesh;
+ }
+
+ /* when face was changed during sending to verse server, then
+ * we have to send it to verse server again */
+ if(vface->flag & FACE_OBSOLETE) {
+ vface->flag &= ~FACE_OBSOLETE;
+ sync_verseface_with_editface(vface->vlayer, vface);
+ return;
+ }
+
+ if(em && !(vface->face) && (vface->counter==0)) {
+ struct VLayer *vlayer;
+ struct VerseVert *vvert;
+ struct EditFace *efa;
+ struct EditVert *eves[4]={NULL, NULL, NULL, NULL};
+ uint32 vert_ids[4]={vface->v0, vface->v1, vface->v2, vface->v3};
+ int i;
+
+ /*printf("\tPOST_POLYGON_CREATE()\n");*/
+
+ vlayer = find_verse_layer_type((VGeomData*)geom_vnode->data, VERTEX_LAYER);
+
+ for(i=0; i<4; i++) {
+ if(vert_ids[i] != -1) {
+ vvert = BLI_dlist_find_link(&(vlayer->dl), vert_ids[i]);
+ if(vvert) eves[i] = (EditVert*)vvert->vertex;
+ }
+ }
+
+ /* to prevent never ending loop of sending and receiving
+ * faces, because addfacelist() sends new face to verse
+ * server if em->vnode isn't NULL */
+ em->vnode = NULL;
+ efa = addfacelist(eves[0], eves[1], eves[2], eves[3], NULL, NULL);
+ em->vnode = geom_vnode;
+
+ if(efa) {
+ efa->vface = vface;
+ vface->face = efa;
+ }
+
+ countall();
+
+ recalc_editnormals();
+ }
+
+ if(((VGeomData*)geom_vnode->data)->vlink) {
+ obj_vnode = ((VGeomData*)geom_vnode->data)->vlink->source;
+ DAG_object_flush_update(G.scene, (Object*)((VObjectData*)obj_vnode->data)->object, OB_RECALC_DATA);
+
+ allqueue(REDRAWVIEW3D, 1);
+ }
+}
+
+/*
+ * Action executed after changes of VerseFace
+ * ... order of vertexes was fliped, etc.
+ */
+void post_polygon_set_corner(VerseFace *vface)
+{
+ struct VNode *obj_vnode;
+ struct VNode *geom_vnode = vface->vlayer->vnode;
+ struct EditMesh *em = NULL;
+ struct EditFace *efa = NULL;
+ struct EditEdge *eed, *eedn;
+
+ if(G.obedit && (((Mesh*)G.obedit->data)->vnode==geom_vnode)) {
+ em = (EditMesh*)((VGeomData*)geom_vnode->data)->editmesh;
+ efa = (EditFace*)vface->face;
+ }
+
+ if(em && efa) {
+
+ /* when face was changed during sending to verse server, then
+ * we have to send it to verse server again */
+ if(vface->flag & FACE_OBSOLETE) {
+ vface->flag &= ~FACE_OBSOLETE;
+ sync_verseface_with_editface(vface->vlayer, vface);
+ return;
+ }
+
+ /* mark all edges, which are part of face efa */
+ efa->e1->f2 = 1;
+ efa->e2->f2 = 1;
+ efa->e3->f2 = 1;
+ if(efa->e4) efa->e4->f2 = 1;
+
+ /* change pointers at EdtitVerts and decrease counters of "old"
+ * VerseVertexes reference ... less VerseFaces will need them */
+ if(vface->vvert0 != efa->v1->vvert)
+ efa->v1 = (EditVert*)vface->vvert0->vertex;
+ if(vface->vvert1 != efa->v2->vvert)
+ efa->v2 = (EditVert*)vface->vvert1->vertex;
+ if(vface->vvert2 != efa->v3->vvert)
+ efa->v3 = (EditVert*)vface->vvert2->vertex;
+ if(efa->v4) {
+ if(!vface->vvert3)
+ efa->v4 = NULL;
+ else if(vface->vvert3 != efa->v4->vvert)
+ efa->v4 = (EditVert*)vface->vvert3->vertex;
+ }
+
+ /* change pointers at EditEdges */
+
+ /* 1st edge */
+ eed = findedgelist(efa->v1, efa->v2);
+ if(eed) efa->e1 = eed;
+ else efa->e1 = addedgelist(efa->v1, efa->v2, NULL);
+
+ /* 2nd edge */
+ eed = findedgelist(efa->v2, efa->v3);
+ if(eed) efa->e2 = eed;
+ else efa->e2 = addedgelist(efa->v2, efa->v3, NULL);
+
+ if(efa->v4) {
+ /* 3th edge */
+ eed = findedgelist(efa->v2, efa->v3);
+ if(eed) efa->e3 = eed;
+ else efa->e3 = addedgelist(efa->v2, efa->v3, NULL);
+ /* 4th edge */
+ eed = findedgelist(efa->v4, efa->v1);
+ if(eed) efa->e4 = eed;
+ else efa->e4 = addedgelist(efa->v4, efa->v1, NULL);
+ }
+ else {
+ /* 3th edge */
+ eed = findedgelist(efa->v3, efa->v1);
+ if(eed) efa->e3 = eed;
+ else efa->e3 = addedgelist(efa->v3, efa->v1, NULL);
+ /* 4th edge */
+ efa->e4 = NULL;
+ }
+
+ /* unmark needed edges */
+ efa = em->faces.first;
+ while(efa) {
+ efa->e1->f2 = 0;
+ efa->e2->f2 = 0;
+ efa->e3->f2 = 0;
+ if(efa->e4) efa->e4->f2 = 0;
+ efa = efa->next;
+ }
+
+ /* delete all unneeded edges */
+ eed = em->edges.first;
+ while(eed) {
+ eedn = eed->next;
+ if(eed->f2) {
+ remedge(eed);
+ free_editedge(eed);
+ }
+ eed = eedn;
+ }
+
+ countall();
+
+ recalc_editnormals();
+ }
+
+ if(((VGeomData*)geom_vnode->data)->vlink) {
+ obj_vnode = ((VGeomData*)geom_vnode->data)->vlink->source;
+ DAG_object_flush_update(G.scene, (Object*)((VObjectData*)obj_vnode->data)->object, OB_RECALC_DATA);
+
+ allqueue(REDRAWVIEW3D, 1);
+ }
+}
+
+/*
+ * Action executed after deleting of VerseFace
+ */
+void post_polygon_delete(VerseFace *vface)
+{
+ struct VNode *obj_vnode;
+ struct VNode *geom_vnode = vface->vlayer->vnode;
+ struct EditMesh *em = NULL;
+ struct EditFace *efa = NULL;
+ struct EditEdge *eed, *eedn;
+
+ if(G.obedit && (((Mesh*)G.obedit->data)->vnode==geom_vnode)) {
+ em = (EditMesh*)((VGeomData*)geom_vnode->data)->editmesh;
+ efa = (EditFace*)vface->face;
+ }
+
+ if(em && efa) {
+ /*printf("\tPOST_POLYGON_DELETE()\n");*/
+
+ /* mark all edges, which are part of face efa */
+ efa->e1->f2 = 1;
+ efa->e2->f2 = 1;
+ efa->e3->f2 = 1;
+ if(efa->e4) efa->e4->f2 = 1;
+
+ efa->vface = NULL;
+ BLI_remlink(&em->faces, efa);
+ free_editface(efa);
+ vface->face = NULL;
+
+ /* following two crazy loops wouldn't be neccessary if verse spec
+ * would support edges */
+
+ /* unmark needed edges */
+ efa = em->faces.first;
+ while(efa) {
+ efa->e1->f2 = 0;
+ efa->e2->f2 = 0;
+ efa->e3->f2 = 0;
+ if(efa->e4) efa->e4->f2 = 0;
+ efa = efa->next;
+ }
+
+ /* delete all unneeded edges */
+ eed = em->edges.first;
+ while(eed) {
+ eedn = eed->next;
+ if(eed->f2) {
+ remedge(eed);
+ free_editedge(eed);
+ }
+ eed = eedn;
+ }
+
+ countall();
+ }
+
+ if(((VGeomData*)geom_vnode->data)->vlink) {
+ obj_vnode = ((VGeomData*)geom_vnode->data)->vlink->source;
+ DAG_object_flush_update(G.scene, (Object*)((VObjectData*)obj_vnode->data)->object, OB_RECALC_DATA);
+
+ allqueue(REDRAWVIEW3D, 1);
+ }
+}
+
+/*
+ * free constraint between VerseFace and EditFace
+ */
+void post_polygon_free_constraint(VerseFace *vface)
+{
+ if(vface->face) {
+ ((EditFace*)vface->face)->vface = NULL;
+ vface->face = NULL;
+ }
+}
+
+/*
+ * free constraint between VGeomData, EditMesh and Mesh
+ */
+void post_geometry_free_constraint(VNode *vnode)
+{
+ if(((VGeomData*)vnode->data)->editmesh) {
+ G.editMesh->vnode = NULL;
+ ((VGeomData*)vnode->data)->editmesh = NULL;
+ }
+ if(((VGeomData*)vnode->data)->mesh) {
+ ((Mesh*)((VGeomData*)vnode->data)->mesh)->vnode = NULL;
+ ((VGeomData*)vnode->data)->mesh = NULL;
+ }
+}
+
+/* =========================================================================
+ *
+ * Functions influencing whole EditMesh or VerseMesh
+ *
+ * ========================================================================= */
+
+/*
+ * free all bindings between EditMesh and "verse mesh" ... it is called between
+ * restorng editmesh from undo stack
+ */
+void destroy_versemesh(VNode *vnode)
+{
+ struct VLayer *vert_vlayer, *face_vlayer;
+ struct VerseVert *vvert;
+ struct VerseFace *vface;
+
+ if(vnode->type != V_NT_GEOMETRY) return;
+
+ vert_vlayer = find_verse_layer_type((VGeomData*)vnode->data, VERTEX_LAYER);
+ face_vlayer = find_verse_layer_type((VGeomData*)vnode->data, POLYGON_LAYER);
+
+
+ /* send delete command to all received verse faces */
+ vface = face_vlayer->dl.lb.first;
+ while(vface) {
+ if(vface->face) ((EditFace*)vface->face)->vface = NULL;
+ vface->face = NULL;
+ send_verse_face_delete(vface);
+ vface = vface->next;
+ }
+ /* send delete command to all verse faces waiting in orphan list */
+ vface = face_vlayer->orphans.first;
+ while(vface) {
+ if(vface->face) ((EditFace*)vface->face)->vface = NULL;
+ vface->face = NULL;
+ send_verse_face_delete(vface);
+ vface = vface->next;
+ }
+ /* mark all verse faces waiting in sending queue as deleted,
+ * send delete command, when this verse face was changed */
+ vface = face_vlayer->queue.first;
+ while(vface) {
+ if(vface->face) ((EditFace*)vface->face)->vface = NULL;
+ vface->face = NULL;
+ if(vface->flag & FACE_CHANGED)
+ send_verse_face_delete(vface);
+ else {
+ vface->flag |= FACE_DELETED;
+ }
+ vface = vface->next;
+ }
+
+ /* send delete command to all received verse vertexes */
+ vvert = vert_vlayer->dl.lb.first;
+ while(vvert) {
+ if(vvert->vertex) ((EditVert*)vvert->vertex)->vvert = NULL;
+ vvert->vertex = NULL;
+ send_verse_vertex_delete(vvert);
+ vvert = vvert->next;
+ }
+ /* mark all verse vertexes waiting in sending queue as deleted
+ * ... verse vertexes will be deleted, when received */
+ vvert = vert_vlayer->queue.first;
+ while(vvert) {
+ if(vvert->vertex) ((EditVert*)vvert->vertex)->vvert = NULL;
+ vvert->vertex = NULL;
+ vvert = vvert->next;
+ }
+}
+
+/*
+ * duplicate geometry verse node, this can be handy, when you duplicate some
+ * object or make object single user
+ */
+VNode *create_geom_vnode_from_geom_vnode(VNode *vnode)
+{
+ struct VNode *n_vnode; /* new verse geometry node */
+ struct VGeomData *geom_data; /* new geometry data */
+ struct VLayer *n_vert_vlayer, *n_face_vlayer; /* new vertex and polygon layer */
+ struct VLayer *vert_vlayer, *face_vlayer;
+ struct VerseVert *n_vvert, *vvert;
+ struct VerseFace *n_vface, *vface;
+ int i;
+
+ if(!vnode) return NULL;
+
+ if(vnode->type != V_NT_GEOMETRY) return NULL;
+
+ /* create new verse node, when no one exist */
+ n_vnode= create_verse_node(vnode->session, -1 , V_NT_GEOMETRY, VN_OWNER_MINE);
+ /* create new geometry data */
+ geom_data = create_geometry_data();
+ n_vnode->data = (void*)geom_data;
+
+ /* set up name of VerseNode */
+ n_vnode->name = (char*)MEM_mallocN(sizeof(char*)*(strlen(vnode->name)-1), "new geom node name");
+ n_vnode->name[0] = '\0';
+ strcat(n_vnode->name, vnode->name);
+
+ /* add node to sending queue */
+ add_item_to_send_queue(&(vnode->session->queue), n_vnode, VERSE_NODE);
+
+ /* create vertex verse layer */
+ n_vert_vlayer = create_verse_layer(n_vnode, 0, "vertex", VN_G_LAYER_VERTEX_XYZ, 0, 0);
+ add_item_to_send_queue(&(geom_data->queue), n_vert_vlayer, VERSE_LAYER);
+
+ /* create polygon verse layer */
+ n_face_vlayer = create_verse_layer(n_vnode, 1, "polygon", VN_G_LAYER_POLYGON_CORNER_UINT32, 0, 0);
+ add_item_to_send_queue(&(geom_data->queue), n_face_vlayer, VERSE_LAYER);
+
+ /* find vertex layer of old verse node */
+ vert_vlayer = find_verse_layer_type((VGeomData*)vnode->data, VERTEX_LAYER);
+ /* find polygon layer of old verse node */
+ face_vlayer = find_verse_layer_type((VGeomData*)vnode->data, POLYGON_LAYER);
+
+ /* duplicate verse vertexes */
+ for(i=0, vvert = (VerseVert*)vert_vlayer->dl.lb.first; vvert; vvert = vvert->next, i++) {
+ n_vvert = create_verse_vertex(n_vert_vlayer, i, vvert->co[0], vvert->co[1], vvert->co[2]);
+ vvert->tmp.vvert = n_vvert;
+ add_item_to_send_queue(&(n_vert_vlayer->queue), n_vvert, VERSE_VERT);
+ }
+
+ /* duplicate verse faces (polyons) */
+ for(i=0, vface = (VerseFace*)face_vlayer->dl.lb.first; vface; vface = vface->next, i++) {
+ n_vface = create_verse_face(n_face_vlayer, i, -1, -1, -1, -1);
+ n_vface->vvert0 = vface->vvert0->tmp.vvert;
+ n_vface->vvert1 = vface->vvert1->tmp.vvert;
+ n_vface->vvert2 = vface->vvert2->tmp.vvert;
+ if(vface->vvert3)
+ n_vface->vvert3 = vface->vvert3->tmp.vvert;
+ else
+ n_vface->vvert3 = NULL;
+ add_item_to_send_queue(&(n_face_vlayer->queue), n_vface, VERSE_FACE);
+ }
+
+ return n_vnode;
+}
+
+/*
+ * create new geometry node, make bindings between geometry node and editmesh,
+ * make bindings between editverts and verseverts, make bindings between editfaces
+ * and versefaces
+ */
+VNode *create_geom_vnode_data_from_editmesh(VerseSession *session, EditMesh *em)
+{
+ struct VNode *vnode;
+ struct Mesh *me;
+ struct VGeomData *geom_data;
+ struct VLayer *vert_vlayer, *face_vlayer;
+
+ if(!session) return NULL;
+
+ if(!em) return NULL;
+
+ /* some verse geometry node already exists */
+ if(em->vnode) return NULL;
+
+ /* we will need mesh too (mesh name, creating bindings between verse node, etc.) */
+ me = get_mesh(G.obedit);
+
+ /* create new verse node, when no one exist */
+ vnode = create_verse_node(session, -1 , V_NT_GEOMETRY, VN_OWNER_MINE);
+ /* create new geometry data */
+ geom_data = create_geometry_data();
+ vnode->data = (void*)geom_data;
+
+ /* set up name of VerseNode */
+ vnode->name = (char*)MEM_mallocN(sizeof(char*)*(strlen(me->id.name)-1), "geom node name");
+ vnode->name[0] = '\0';
+ strcat(vnode->name, me->id.name+2);
+
+ /* set up bindings */
+ me->vnode = (void*)vnode;
+ em->vnode = (void*)vnode;
+ geom_data->mesh = (void*)me;
+ geom_data->editmesh = (void*)em;
+
+ /* add node to sending queue */
+ add_item_to_send_queue(&(session->queue), vnode, VERSE_NODE);
+
+ /* create vertex verse layer */
+ vert_vlayer = create_verse_layer(vnode, 0, "vertex", VN_G_LAYER_VERTEX_XYZ, 0, 0);
+ add_item_to_send_queue(&(geom_data->queue), vert_vlayer, VERSE_LAYER);
+
+ /* create polygon verse layer */
+ face_vlayer = create_verse_layer(vnode, 1, "polygon", VN_G_LAYER_POLYGON_CORNER_UINT32, 0, 0);
+ add_item_to_send_queue(&(geom_data->queue), face_vlayer, VERSE_LAYER);
+
+ /* create all verse verts and add them to sending queue */
+ createAllVerseVerts(vnode, vert_vlayer);
+
+ /* create all verse faces and add tehm to sending queue */
+ createAllVerseFaces(vnode, face_vlayer);
+
+ return vnode;
+}
+
+/*
+ * create new geometry node, make bindings between geometry node and mesh and
+ * fill geometry node with new data based at mesh data
+ */
+VNode *create_geom_vnode_data_from_mesh(VerseSession *session, Mesh *me)
+{
+ struct VNode *vnode;
+ struct VGeomData *geom_data;
+ struct VLayer *vert_vlayer, *face_vlayer;
+ struct VerseVert *vvert, **vverts;
+ struct VerseFace *vface;
+ struct MVert *mvert;
+ struct MFace *mface;
+ int i;
+
+ if(!session) return NULL;
+
+ if(!me) return NULL;
+
+ /* some verse geometry node already exists */
+ if(me->vnode) return NULL;
+
+ /* create new verse node, when no one exist */
+ vnode = create_verse_node(session, -1 , V_NT_GEOMETRY, VN_OWNER_MINE);
+ /* create new geometry data */
+ geom_data = create_geometry_data();
+ vnode->data = (void*)geom_data;
+
+ /* set up name of VerseNode */
+ vnode->name = (char*)MEM_mallocN(sizeof(char*)*(strlen(me->id.name)-1), "geom node name");
+ vnode->name[0] = '\0';
+ strcat(vnode->name, me->id.name+2);
+
+ /* set up bindings */
+ me->vnode = (void*)vnode;
+ geom_data->mesh = (void*)me;
+
+ /* add node to sending queue */
+ add_item_to_send_queue(&(session->queue), vnode, VERSE_NODE);
+
+ /* create vertex verse layer */
+ vert_vlayer = create_verse_layer(vnode, 0, "vertex", VN_G_LAYER_VERTEX_XYZ, 0, 0);
+ add_item_to_send_queue(&(geom_data->queue), vert_vlayer, VERSE_LAYER);
+
+ /* create polygon verse layer */
+ face_vlayer = create_verse_layer(vnode, 1, "polygon", VN_G_LAYER_POLYGON_CORNER_UINT32, 0, 0);
+ add_item_to_send_queue(&(geom_data->queue), face_vlayer, VERSE_LAYER);
+
+ /* temporary array of VerseVerts */
+ vverts = (VerseVert**)MEM_mallocN(sizeof(VerseVert*)*me->totvert,"temp array of vverts");
+
+ /* "fill vertex layer with vertexes" and add them to sending queue (send them to verse server) */
+ for(i=0, mvert=me->mvert; i<me->totvert; i++, mvert++) {
+ vverts[i] = vvert = create_verse_vertex(vert_vlayer, i, mvert->co[0], mvert->co[1], mvert->co[2]);
+ add_item_to_send_queue(&(vert_vlayer->queue), vvert, VERSE_VERT);
+ }
+
+ /* "fill face/polygon layer with faces" and them to sending queue */
+ for(i=0, mface = me->mface; i<me->totface; i++, mface++) {
+ if(mface->v4) {
+ vface = create_verse_face(face_vlayer, i, mface->v1, mface->v2, mface->v3, mface->v4);
+ vface->vvert0 = vverts[mface->v1];
+ vface->vvert1 = vverts[mface->v2];
+ vface->vvert2 = vverts[mface->v3];
+ vface->vvert3 = vverts[mface->v4];
+ vface->counter = 4;
+ }
+ else {
+ vface = create_verse_face(face_vlayer, i, mface->v1, mface->v2, mface->v3, -1);
+ vface->vvert0 = vverts[mface->v1];
+ vface->vvert1 = vverts[mface->v2];
+ vface->vvert2 = vverts[mface->v3];
+ vface->counter = 3;
+ }
+ add_item_to_send_queue(&(face_vlayer->queue), vface, VERSE_FACE);
+ }
+
+ MEM_freeN(vverts);
+
+ return vnode;
+}
+
+/*
+ * creates Mesh from verse geometry node and create bindings
+ * between them
+ */
+Mesh *create_mesh_from_geom_node(VNode *vnode)
+{
+ struct Mesh *me;
+
+ if(vnode->type != V_NT_GEOMETRY) return NULL;
+
+ /* add new empty mesh*/
+ me = add_mesh();
+ /* set up bindings between mesh and verse node */
+ me->vnode = (void*)vnode;
+ ((VGeomData*)vnode->data)->mesh = (void*)me;
+
+ return me;
+}
+
+/*
+ * create mesh from verse mesh
+ */
+void create_meshdata_from_geom_node(Mesh *me, VNode *vnode)
+{
+ struct VLayer *vert_vlayer, *face_vlayer;
+ struct VerseVert *vvert;
+ struct VerseFace *vface;
+ struct MVert *mvert;
+ struct MFace *mface;
+ int index;
+
+ if(!me || !vnode) return;
+
+ if(vnode->type != V_NT_GEOMETRY) return;
+
+ vert_vlayer = find_verse_layer_type((VGeomData*)vnode->data, VERTEX_LAYER);
+ face_vlayer = find_verse_layer_type((VGeomData*)vnode->data, POLYGON_LAYER);
+
+ if(me->mvert) {
+ MEM_freeN(me->mvert);
+ me->mvert = NULL;
+ }
+ if(me->mface) {
+ MEM_freeN(me->mface);
+ me->mface = NULL;
+ }
+ if(me->tface) {
+ MEM_freeN(me->tface);
+ me->tface = NULL;
+ }
+ if(me->medge) {
+ MEM_freeN(me->medge);
+ me->medge = NULL;
+ }
+ if(me->dvert) {
+ MEM_freeN(me->dvert);
+ me->dvert = NULL;
+ }
+ if(me->mcol) {
+ MEM_freeN(me->mcol);
+ me->mcol = NULL;
+ }
+ if(me->msticky) {
+ MEM_freeN(me->msticky);
+ me->msticky = NULL;
+ }
+ if(me->mselect) {
+ MEM_freeN(me->mselect);
+ me->mselect = NULL;
+ }
+
+ me->totvert = vert_vlayer->dl.da.count;
+ me->totface = face_vlayer->dl.da.count;
+ me->totedge = 0;
+ me->totselect = 0;
+
+ mvert = me->mvert = (MVert*)MEM_mallocN(sizeof(MVert)*me->totvert, "mesh_from_verse vert");
+ mface = me->mface = (MFace*)MEM_mallocN(sizeof(MFace)*me->totface, "mesh_from_verse face");
+
+ index = 0;
+ vvert = vert_vlayer->dl.lb.first;
+ while(vvert) {
+ VECCOPY(mvert->co, vvert->co);
+ VECCOPY(mvert->no, vvert->no);
+ mvert->flag = 0;
+ mvert->mat_nr = 0;
+ vvert->tmp.index = index++;
+ vvert = vvert->next;
+ mvert++;
+ }
+
+ vface = face_vlayer->dl.lb.first;
+ 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->flag = 0;
+ mface->pad = 0;
+ mface->mat_nr = 0;
+ mface->edcode = 0;
+
+ /* index 0 isn't allowed at location 3 or 4 */
+ test_index_face(mface, NULL, NULL, vface->vvert3?4:3);
+/* printf("\t mface: %d, %d, %d, %d\n", mface->v1, mface->v2, mface->v3, mface->v4);*/
+
+ vface = vface->next;
+ mface++;
+ }
+
+ mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL);
+}
+
+/*
+ * Create EditMesh from VerseMesh and keep system in consitant state, this
+ * function is called, when edit mode is entered ... edit mesh is generated
+ * from verse mesh (not from Mesh: (Mesh*)ob->data)
+ */
+void create_edit_mesh_from_geom_node(VNode *vnode)
+{
+ struct VLayer *vert_layer, *face_layer;
+ struct VerseVert *vvert;
+ struct VerseFace *vface;
+ struct Mesh *me;
+ struct EditVert *eve, *eve0, *eve1, *eve2, *eve3;
+ struct EditFace *efa;
+ unsigned int keyindex;
+
+ if(!(G.obedit && G.obedit->type==OB_MESH)) return;
+ me = (Mesh*)G.obedit->data;
+ if(vnode!=(VNode*)me->vnode || 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);
+
+ if(!(vert_layer && face_layer)) return;
+
+ waitcursor(1);
+
+ /* free old editMesh */
+ free_editMesh(G.editMesh);
+
+ G.editMesh->vnode = NULL;
+
+ vvert = vert_layer->dl.lb.first;
+
+ keyindex = 0;
+
+ /* create all EditVerts */
+ while(vvert) {
+ eve = addvertlist(vvert->co);
+
+ eve->f = 0;
+ eve->h = 0;
+ eve->dw = NULL;
+ eve->keyindex = keyindex;
+ eve->vvert = (void*)vvert;
+
+ vvert->vertex = (void*)eve;
+
+ keyindex++;
+ vvert = vvert->next;
+ }
+
+ vface = face_layer->dl.lb.first;
+
+ /* create all EditFaces and EditEdges */
+ while(vface) {
+ if(vface->vvert0) eve0= vface->vvert0->vertex;
+ else eve0 = NULL;
+ if(vface->vvert1) eve1= vface->vvert1->vertex;
+ else eve1 = NULL;
+ if(vface->vvert2) eve2= vface->vvert2->vertex;
+ else eve2 = NULL;
+ if(vface->vvert3) eve3= vface->vvert3->vertex;
+ else eve3 = NULL;
+
+ efa= addfacelist(eve0, eve1, eve2, eve3, NULL, NULL);
+ if(efa) {
+ efa->f = 0;
+ efa->h = 0;
+ efa->vface = (void*)vface;
+ vface->face = (void*)efa;
+ }
+ vface = vface->next;
+ }
+
+ countall();
+
+ recalc_editnormals();
+
+ G.editMesh->vnode = (void*)vnode;
+ ((VGeomData*)vnode->data)->editmesh = (void*)G.editMesh;
+
+ waitcursor(0);
+}
+
+/*
+ * destroy bindings between EditMesh and VerseMesh and send delete commands
+ * for all VerseVerts and VerseFaces to verse server, Verse Node has to be
+ * geometry node
+ */
+
+void destroy_verse_mesh(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) {
+ ((EditFace*)vface->face)->vface = NULL;
+ vface->face = NULL;
+ vface = vface->next;
+ }
+
+ vert_vlayer = find_verse_layer_type((VGeomData*)vnode->data, VERTEX_LAYER);
+ vvert = vert_vlayer->dl.lb.first;
+
+ while(vvert) {
+ ((EditVert*)vvert->vertex)->vvert = NULL;
+ vvert->vertex = NULL;
+ vvert = vvert->next;
+ }
+
+ destroy_geometry(vnode);
+}
+
+#endif
+
diff --git a/source/blender/src/verse_object.c b/source/blender/src/verse_object.c
new file mode 100644
index 00000000000..3327ac4e5de
--- /dev/null
+++ b/source/blender/src/verse_object.c
@@ -0,0 +1,587 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Contributor(s): Jiri Hnidek.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifdef WITH_VERSE
+
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "mydevice.h"
+
+#include "DNA_object_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_image_types.h"
+#include "DNA_listBase.h"
+
+#include "BLI_dynamiclist.h"
+#include "BLI_blenlib.h"
+#include "BLI_editVert.h"
+#include "BLI_arithb.h"
+
+#include "BIF_verse.h"
+#include "BIF_space.h"
+#include "BIF_editmesh.h"
+#include "BIF_drawimage.h"
+#include "BIF_editmode_undo.h"
+#include "BIF_toolbox.h"
+
+#include "BKE_verse.h"
+#include "BKE_global.h"
+#include "BKE_object.h"
+#include "BKE_utildefines.h"
+#include "BKE_depsgraph.h"
+#include "BKE_image.h"
+#include "BKE_library.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_mesh.h"
+#include "BKE_displist.h"
+
+#include "BDR_editobject.h"
+
+#include "verse.h"
+
+/* button callback function, it test object name and send new name to verse server */
+void test_and_send_idbutton_cb(void *obj, void *ob_name)
+{
+ struct Object *ob = (Object*)obj;
+ char *name= (char*)ob_name;
+
+ test_idbutton(name+2);
+
+ if(ob->vnode) verse_send_node_name_set(((VNode*)ob->vnode)->id, name+2);
+}
+
+/*
+ * duplicate verse object nodes
+ */
+void b_verse_duplicate_object(VerseSession *session, Object *ob, Object *n_ob)
+{
+ struct VNode *obj_vnode;
+
+ if(!session) return;
+
+ if(!(session->flag & VERSE_CONNECTED)) return;
+
+ /* create "my" new object VerseNode */
+ obj_vnode= create_verse_node(session, -1 , V_NT_OBJECT, VN_OWNER_MINE);
+ /* create object data */
+ obj_vnode->data = create_object_data();
+
+ /* set up name of VerseNode */
+ obj_vnode->name = (char*)MEM_mallocN(sizeof(char*)*(strlen(n_ob->id.name)-1), "object node name");
+ obj_vnode->name[0] = '\0';
+ strcat(obj_vnode->name, n_ob->id.name+2);
+
+ /* set up object node transformation */
+ VECCOPY(((VObjectData*)obj_vnode->data)->pos, n_ob->loc);
+ EulToQuat(n_ob->rot, ((VObjectData*)obj_vnode->data)->rot);
+ VECCOPY(((VObjectData*)obj_vnode->data)->scale, n_ob->size);
+
+ /* set up pointers between Object and VerseNode */
+ ((VObjectData*)obj_vnode->data)->object = (void*)n_ob;
+ n_ob->vnode = (void*)obj_vnode;
+
+ /* add node to sending queue */
+ add_item_to_send_queue(&(session->queue), obj_vnode, VERSE_NODE);
+
+ if(ob->type==OB_MESH) {
+ struct Mesh *me;
+ struct VNode *geom_vnode;
+ struct VLink *vlink;
+
+ /* when current mesh already shared at verse server, then only set up link
+ * between object node and geometry node */
+ if(ob->data == n_ob->data) {
+ geom_vnode = (VNode*)((Mesh*)ob->data)->vnode;
+ }
+ else {
+ geom_vnode = create_geom_vnode_from_geom_vnode((VNode*)((Mesh*)ob->data)->vnode);
+ me = (Mesh*)n_ob->data;
+ me->vnode = (void*)geom_vnode;
+ ((VGeomData*)geom_vnode->data)->mesh = (void*)me;
+
+ }
+ /* create new link between VereseNodes */
+ vlink = create_verse_link(session, obj_vnode, geom_vnode, -1, -1, "geometry");
+ /* "send" link to verse server */
+ add_item_to_send_queue(&(((VObjectData*)obj_vnode->data)->queue), vlink, VERSE_LINK);
+ }
+}
+
+/*
+ * temp hack: this function push mesh objects (edit mode only) to verse server
+ */
+void b_verse_push_object(VerseSession *session, Object *ob)
+{
+ struct VNode *obj_vnode;
+
+ if(!session) return;
+
+ if(!(session->flag & VERSE_CONNECTED)) return;
+
+ /* create "my" new object VerseNode */
+ obj_vnode= create_verse_node(session, -1 , V_NT_OBJECT, VN_OWNER_MINE);
+ /* create object data */
+ obj_vnode->data = create_object_data();
+
+ /* set up name of VerseNode */
+ obj_vnode->name = (char*)MEM_mallocN(sizeof(char*)*(strlen(ob->id.name)-1), "object node name");
+ obj_vnode->name[0] = '\0';
+ strcat(obj_vnode->name, ob->id.name+2);
+
+ /* set up object node transformation */
+ VECCOPY(((VObjectData*)obj_vnode->data)->pos, ob->loc);
+ EulToQuat(ob->rot, ((VObjectData*)obj_vnode->data)->rot);
+ VECCOPY(((VObjectData*)obj_vnode->data)->scale, ob->size);
+
+ /* set up pointers between Object and VerseNode */
+ ((VObjectData*)obj_vnode->data)->object = (void*)ob;
+ ob->vnode = (void*)obj_vnode;
+
+ /* add node to sending queue */
+ add_item_to_send_queue(&(session->queue), obj_vnode, VERSE_NODE);
+
+ if(ob->type==OB_MESH) {
+ struct VNode *geom_vnode;
+ struct VLink *vlink;
+
+ if(G.obedit)
+ geom_vnode = create_geom_vnode_data_from_editmesh(session, G.editMesh);
+ else
+ geom_vnode = create_geom_vnode_data_from_mesh(session, get_mesh(ob));
+
+ if(geom_vnode) {
+ /* create new link between VereseNodes */
+ vlink = create_verse_link(session, obj_vnode, geom_vnode, -1, -1, "geometry");
+ /* send link to verse server */
+ add_item_to_send_queue(&(((VObjectData*)obj_vnode->data)->queue), vlink, VERSE_LINK);
+ }
+ }
+}
+
+/*
+ * creates blender object from verse object node and it
+ * will create links between them
+ */
+Object *create_object_from_verse_node(VNode *vnode)
+{
+ struct Object *ob;
+
+ if(vnode->type != V_NT_OBJECT) return NULL;
+
+ /* create new object*/
+ ob = add_object(OB_MESH);
+ /* set up bindings between verse node and blender object */
+ ob->vnode = (void*)vnode;
+ ((VObjectData*)vnode->data)->object = (void*)ob;
+ /* set up flags */
+ ((VObjectData*)vnode->data)->flag |= POS_RECEIVE_READY;
+ ((VObjectData*)vnode->data)->flag |= ROT_RECEIVE_READY;
+ ((VObjectData*)vnode->data)->flag |= SCALE_RECEIVE_READY;
+ /* copy name from verse node to object */
+ if(vnode->name) {
+ char *str;
+ str = (char*)MEM_mallocN(sizeof(char)*(strlen(vnode->name)+3), "temp object name");
+ str[0] = '\0';
+ strcat(str, "OB");
+ strcat(str, vnode->name);
+ strncpy(ob->id.name, str, 23);
+ MEM_freeN(str);
+ }
+ /* subscribe for object transformation */
+ verse_send_o_transform_subscribe(vnode->id, 0);
+
+ return ob;
+}
+
+/*
+ * Create blender object-mesh from verse object node, verse geometry node,
+ */
+void b_verse_pop_node(VNode *vnode)
+{
+ if((!vnode) || (!(vnode->data))) return;
+
+ if(vnode->type==V_NT_OBJECT) {
+ struct VNode *geom_node=NULL;
+ struct VLink *vlink;
+ struct VLayer *vlayer;
+ struct Object *ob;
+ struct Mesh *me;
+
+ if(((VObjectData*)vnode->data)->object) {
+ printf("\tError: already subscribed to object node.\n");
+ return;
+ }
+
+ vlink = ((VObjectData*)vnode->data)->links.lb.first;
+
+ /* try to find geometry node */
+ while(vlink) {
+ if(vlink->target && vlink->target->type==V_NT_GEOMETRY){
+ geom_node = vlink->target;
+ break;
+ }
+ vlink = vlink->next;
+ }
+
+ /* we are not interested now in avatars node, etc. (vnodes without
+ * links at geometry node) */
+ if(!geom_node) return;
+
+ /* subscribe to all verse geometry layer */
+ vlayer = ((VGeomData*)geom_node->data)->layers.lb.first;
+ while(vlayer) {
+ verse_send_g_layer_subscribe(geom_node->id, vlayer->id, 0);
+ vlayer = vlayer->next;
+ }
+
+ ob = create_object_from_verse_node(vnode);
+
+ me = create_mesh_from_geom_node(geom_node);
+
+ /* set up bindings between object and mesh */
+ if(ob && me) ob->data = me;
+ }
+ else if(vnode->type==V_NT_BITMAP) {
+ struct VBitmapData *vbitmap;
+ struct VBitmapLayer *vblayer;
+
+ vbitmap = (VBitmapData*)vnode->data;
+
+ vblayer = vbitmap->layers.lb.first;
+
+ while(vblayer) {
+ if(!(vblayer->flag & VBLAYER_SUBSCRIBED)) {
+ /* 0 means level of subscription (full resolution) */
+ verse_send_b_layer_subscribe(vnode->id, vblayer->id, 0);
+ vblayer->flag |= VBLAYER_SUBSCRIBED;
+ }
+ vblayer = vblayer->next;
+ }
+
+ if(vbitmap->image) {
+ printf("\tError: already subscribed to image node.\n");
+ return;
+ }
+
+ vbitmap->image = (void*)new_image(
+ vbitmap->width,
+ vbitmap->height,
+ vnode->name,
+ 0);
+ ((Image*)vbitmap->image)->vnode = (void*)vnode;
+ sync_blender_image_with_verse_bitmap_node(vnode);
+
+ allqueue(REDRAWIMAGE, 0);
+ allqueue(REDRAWVIEW3D, 0);
+ }
+}
+
+/*
+ * this function will unsubscribe object node from transformation, but it will
+ * keep all tags and links at other nodes ... user could subscribe to this node
+ * again in future
+ */
+void unsubscribe_from_obj_node(VNode *vnode)
+{
+ struct VerseSession *session = vnode->session;
+ struct VLink *vlink;
+
+ if(vnode->type != V_NT_OBJECT) return;
+
+ /* unsubscribe from receiving changes of transformation matrix */
+ if(session->flag & VERSE_CONNECTED)
+ verse_send_o_transform_unsubscribe(vnode->id, 0);
+
+ /* we have to reinitialize object node transformation */
+ ((VObjectData*)vnode->data)->pos[0] = 0.0f;
+ ((VObjectData*)vnode->data)->pos[1] = 0.0f;
+ ((VObjectData*)vnode->data)->pos[2] = 0.0f;
+
+ ((VObjectData*)vnode->data)->rot[0] = 0.0f;
+ ((VObjectData*)vnode->data)->rot[1] = 0.0f;
+ ((VObjectData*)vnode->data)->rot[2] = 0.0f;
+ ((VObjectData*)vnode->data)->rot[3] = 0.0f;
+
+ ((VObjectData*)vnode->data)->scale[0] = 0.0f;
+ ((VObjectData*)vnode->data)->scale[1] = 0.0f;
+ ((VObjectData*)vnode->data)->scale[2] = 0.0f;
+
+ /* clear bindings between object and object node */
+ if(((VObjectData*)vnode->data)->object) {
+ ((Object*)((VObjectData*)vnode->data)->object)->vnode = NULL;
+ ((VObjectData*)vnode->data)->object = NULL;
+ }
+
+ /* unsubscribe from all supported verse nodes */
+ vlink = ((VObjectData*)vnode->data)->links.lb.first;
+ while(vlink) {
+ if(vlink->target->counter==1) {
+ switch(vlink->target->type) {
+ case V_NT_OBJECT:
+ unsubscribe_from_obj_node(vlink->target);
+ break;
+ case V_NT_GEOMETRY:
+ unsubscribe_from_geom_node(vlink->target);
+ break;
+ case V_NT_BITMAP:
+ unsubscribe_from_bitmap_node(vlink->target);
+ break;
+ default:
+ break;
+ }
+ }
+ vlink = vlink->next;
+ }
+}
+
+/*
+ * when blender Object is deleted, then we have to unsubscribe and free all
+ * VerseNode dependent on this object
+ */
+void b_verse_delete_object(Object *object)
+{
+ struct VNode *vnode;
+
+ vnode = (VNode*)object->vnode;
+
+ if(vnode) unsubscribe_from_obj_node(vnode);
+}
+
+/*
+ * "fake" unsubscribing from object node and all child nodes
+ */
+void b_verse_unsubscribe(VNode *vnode)
+{
+ struct VLink *vlink = ((VObjectData*)vnode->data)->links.lb.first;
+ struct Object *ob = (Object*)((VObjectData*)vnode->data)->object;
+
+ if(vnode->type != V_NT_OBJECT) return;
+
+ if(G.obedit && G.obedit->vnode == (void*)vnode)
+ exit_editmode(2);
+
+ /* create mesh data */
+ while(vlink){
+ if(vlink->target->type == V_NT_GEOMETRY) {
+ struct Mesh *me;
+ me = ((VGeomData*)vnode->data)->mesh;
+ create_meshdata_from_geom_node(me, vnode);
+ break;
+ }
+ vlink = vlink->next;
+ }
+
+ /* unsubscribe from object transformation and clear bindings between
+ * verse object node and object */
+ unsubscribe_from_obj_node(vnode);
+
+ /* when geometry node was shared with more object nodes, then make
+ * data single user */
+ if(ob->type == OB_MESH) {
+ struct ID *id = ob->data;
+ if(id && id->us>1 && id->lib==0) {
+ ob->recalc= OB_RECALC_DATA;
+ ob->data = copy_mesh(ob->data);
+ id->us--;
+ id->newid= ob->data;
+ }
+ }
+
+ /* reinitialize object derived mesh */
+ makeDispListMesh(ob);
+
+ DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
+ allqueue(REDRAWVIEW3D, 1);
+
+}
+
+/*
+ * whe VerseLink is created between two nodes, the Object start to point at
+ * coresponding data
+ */
+void post_link_set(VLink *vlink)
+{
+ struct VNode *target, *source;
+ struct Object *ob=NULL;
+ struct Mesh *me=NULL;
+
+ source = vlink->source;
+ target = vlink->target;
+
+ if(source->type==V_NT_OBJECT && target->type==V_NT_GEOMETRY){
+ if(((VObjectData*)source->data)->object)
+ ob = (Object*)((VObjectData*)source->data)->object;
+ if(((VGeomData*)target->data)->mesh)
+ me = (Mesh*)((VGeomData*)target->data)->mesh;
+ if(ob && me && ob->data!=me) {
+ ob->data = me;
+ makeDispListMesh(ob);
+ }
+ }
+
+ allqueue(REDRAWALL, 1);
+}
+
+/*
+ * when VerseLink is deleted, then bindings between Object and data should be removed
+ */
+void post_link_destroy(VLink *vlink)
+{
+ struct VNode *source, *target;
+ struct Object *ob;
+
+ source = vlink->source;
+ target = vlink->target;
+
+ if(source->type==V_NT_OBJECT && target->type==V_NT_GEOMETRY) {
+ if(((VObjectData*)source->data)->object) {
+ ob = (Object*)((VObjectData*)source->data)->object;
+ ob->data=NULL;
+ }
+ }
+
+ allqueue(REDRAWALL, 1);
+}
+
+/*
+ * recalculate transformation matrix of object
+ */
+void post_transform(VNode *vnode)
+{
+ struct VObjectData *obj_data = (VObjectData*)vnode->data;
+ struct Object *ob = (Object*)obj_data->object;
+ float mat_s[4][4];
+ float mat_r[4][4];
+ float mat_p[4][4];
+ float mat[4][4];
+
+ if(!obj_data->object) return;
+
+ Mat4One(mat_s);
+ Mat4One(mat_r);
+ Mat4One(mat_p);
+
+ /* scale */
+ mat_s[0][0] = ob->size[0] = obj_data->scale[0];
+ mat_s[1][1] = ob->size[1] = obj_data->scale[1];
+ mat_s[2][2] = ob->size[2] = obj_data->scale[2];
+
+ /* rotate */
+ QuatToEul(obj_data->rot, ob->rot);
+ QuatToMat4(obj_data->rot, mat_r);
+
+ /* position */
+ mat_p[3][0] = ob->loc[0] = obj_data->pos[0];
+ mat_p[3][1] = ob->loc[1] = obj_data->pos[1];
+ mat_p[3][2] = ob->loc[2] = obj_data->pos[2];
+
+ /* matrix multiplication */
+ Mat4MulMat4(mat, mat_r, mat_p);
+ Mat4MulMat4(ob->obmat, mat_s, mat);
+
+ DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);
+
+ allqueue(REDRAWVIEW3D, 1);
+}
+
+/*
+ * send transformation of Object to verse server
+ */
+void b_verse_send_transformation(Object *ob)
+{
+ struct VNode *vnode= ob->vnode;
+ float quat[4];
+
+ if(!vnode) return;
+
+ /* if last sent position wasn't received yet, then next change of position
+ * can't be send until last send change is received */
+ if( ((VObjectData*)vnode->data)->flag & POS_SEND_READY ) {
+ if((((VObjectData*)vnode->data)->pos[0]!=ob->loc[0]) ||
+ (((VObjectData*)vnode->data)->pos[1]!=ob->loc[1]) ||
+ (((VObjectData*)vnode->data)->pos[2]!=ob->loc[2])) {
+ VECCOPY(((VObjectData*)vnode->data)->pos, ob->loc);
+ send_verse_object_position(vnode);
+ }
+ }
+
+ /* if last sent rotation wasn't received yet, then next change of rotation
+ * can't be send until last send change is received */
+ if( ((VObjectData*)vnode->data)->flag & ROT_SEND_READY ) {
+ EulToQuat(ob->rot, quat);
+
+ if((((VObjectData*)vnode->data)->rot[0] != quat[0]) ||
+ (((VObjectData*)vnode->data)->rot[1] != quat[1]) ||
+ (((VObjectData*)vnode->data)->rot[2] != quat[2]) ||
+ (((VObjectData*)vnode->data)->rot[3] != quat[3])) {
+ QUATCOPY(((VObjectData*)vnode->data)->rot, quat);
+ send_verse_object_rotation(vnode);
+ }
+ }
+
+ /* if last sent object size wasn't received yet, then next change of object size
+ * can't be send until last send change is received */
+ if( ((VObjectData*)vnode->data)->flag & SCALE_SEND_READY ) {
+ if((((VObjectData*)vnode->data)->scale[0]!=ob->size[0]) ||
+ (((VObjectData*)vnode->data)->scale[1]!=ob->size[1]) ||
+ (((VObjectData*)vnode->data)->scale[2]!=ob->size[2])) {
+ VECCOPY(((VObjectData*)vnode->data)->scale, ob->size);
+ send_verse_object_scale(vnode);
+ }
+ }
+
+ verse_callback_update(0);
+}
+
+/*
+ * free constraint between object VerseNode and blender Object
+ */
+void post_object_free_constraint(VNode *vnode)
+{
+ if(((VObjectData*)vnode->data)->object) {
+ /* free pointer at verse derived mesh */
+ struct Object *ob = (Object*)((VObjectData*)vnode->data)->object;
+ if(ob) {
+ if(ob->derivedFinal) {
+ ((DerivedMesh*)ob->derivedFinal)->release((DerivedMesh*)ob->derivedFinal);
+ ob->derivedFinal = NULL;
+ }
+ if(ob->derivedDeform) {
+ ((DerivedMesh*)ob->derivedDeform)->release((DerivedMesh*)ob->derivedDeform);
+ ob->derivedDeform = NULL;
+ }
+ }
+ /* free constraint */
+ ((Object*)((VObjectData*)vnode->data)->object)->vnode = NULL;
+ ((VObjectData*)vnode->data)->object = NULL;
+ }
+}
+
+#endif
+
diff --git a/source/creator/creator.c b/source/creator/creator.c
index baf122f7484..c31f66d1973 100644
--- a/source/creator/creator.c
+++ b/source/creator/creator.c
@@ -357,7 +357,6 @@ int main(int argc, char **argv)
case 'v':
print_version();
exit(0);
-
default:
break;
}
diff --git a/source/nan_compile.mk b/source/nan_compile.mk
index d356d13be42..3bdd79cce24 100644
--- a/source/nan_compile.mk
+++ b/source/nan_compile.mk
@@ -143,8 +143,8 @@ ifeq ($(OS),linux)
CFLAGS += -pipe -fPIC
CCFLAGS += -pipe -fPIC
# CCFLAGS += -pipe
- REL_CFLAGS += -O2
- REL_CCFLAGS += -O2
+ REL_CFLAGS += -ggdb
+ REL_CCFLAGS += -ggdb
NAN_DEPEND = true
ifeq ($(CPU),alpha)
CFLAGS += -mieee
diff --git a/source/nan_definitions.mk b/source/nan_definitions.mk
index 123b76d86b8..b2dc37c1568 100644
--- a/source/nan_definitions.mk
+++ b/source/nan_definitions.mk
@@ -98,6 +98,10 @@ endif
export NAN_FFMPEGCFLAGS ?= -I$(NAN_FFMPEG)/include
endif
+ ifeq ($(WITH_VERSE), true)
+ export NAN_VERSE ?= $(LCGDIR)/verse
+ endif
+
export WITH_OPENEXR ?= true
ifeq ($(OS),windows)
ifeq ($(FREE_WINDOWS), true)
diff --git a/source/nan_link.mk b/source/nan_link.mk
index 35eb80b2cc7..9314f2d708f 100644
--- a/source/nan_link.mk
+++ b/source/nan_link.mk
@@ -136,6 +136,9 @@ ifeq ($(OS),windows)
LDFLAGS += -mwindows -mno-cygwin -mconsole
DADD += -L/usr/lib/w32api -lnetapi32 -lopengl32 -lglu32 -lshfolder
DADD += -L/usr/lib/w32api -lwinmm -lwsock32
+ ifeq ($(WITH_VERSE),true)
+ DADD += -lws2_32
+ endif
else
DADD = kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib
DADD += advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib