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
This commit is contained in:
Jiri Hnidek 2006-08-20 15:22:56 +00:00
parent ffe630b452
commit 2ee42ac01e
56 changed files with 9178 additions and 59 deletions

4
extern/Makefile vendored

@ -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

@ -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

@ -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)

@ -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

@ -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) {

@ -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)

@ -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");
for(i=0; i<numVerts && vvert; vvert = vvert->next, i++) {
VECCOPY(cos[i], vvert->co);
}
return cos;
}
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 */

@ -910,6 +910,11 @@ Object *copy_object(Object *ob)
obn->derivedDeform = NULL;
obn->derivedFinal = NULL;
#ifdef WITH_VERSE
obn->vnode = NULL;
#endif
return obn;
}

@ -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

File diff suppressed because it is too large Load Diff

@ -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

@ -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

@ -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

@ -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.

@ -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

@ -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

@ -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");

@ -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

@ -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);

@ -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

@ -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

@ -89,6 +89,9 @@
#define SELECT 1
#define ACTIVE 2
/*#ifdef WITH_VERSE*/
#define VERSE 3
/*#endif*/
#define DESELECT 0
#define NOT_YET 0

@ -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);

@ -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

@ -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 */

@ -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;

@ -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 {

@ -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

@ -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
}

@ -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);
}
}
}

@ -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");
}

@ -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
}
}

@ -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();
}
}

@ -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)

@ -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 */

@ -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");
}

@ -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");
}

@ -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();

@ -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
}
}

@ -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;
}

@ -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, "");

@ -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, "");

@ -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) {

@ -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) {

@ -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:

@ -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
}

@ -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);
}

@ -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

@ -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

@ -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

File diff suppressed because it is too large Load Diff

@ -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

@ -357,7 +357,6 @@ int main(int argc, char **argv)
case 'v':
print_version();
exit(0);
default:
break;
}

@ -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

@ -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)

@ -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