Add Verse master-server functionality

* added two files from verse-master
* server list is available in outliner (new mode "Verse Servers")
* verse sessions are now also in new mode "Verse Sessions" in outliner
* fixed drawing of verse sessions and their nodes
* in user preferences System & OpenGL master-server ip setting (default master.uni-verse.org)
* in File>Verse entry "Get Servers" to get server list or
* RMB on "Available Verse Servers" in outliner to "Refresh" server list

Enjoy :)
This commit is contained in:
Nathan Letwory
2006-10-12 11:53:50 +00:00
parent 86e192ea40
commit b2a8417fce
17 changed files with 640 additions and 29 deletions

View File

@@ -30,7 +30,8 @@ LIBVERSE_SRC = $(PROT_OUT) v_bignum.c v_cmd_buf.c v_connect.c \
v_connection.c v_connection.h v_encryption.c \ v_connection.c v_connection.h v_encryption.c \
v_func_storage.c v_internal_verse.h v_man_pack_node.c \ v_func_storage.c v_internal_verse.h v_man_pack_node.c \
v_network.c v_network.h v_network_in_que.c v_network_out_que.c \ v_network.c v_network.h v_network_in_que.c v_network_out_que.c \
v_pack.c v_pack.h v_pack_method.c v_prime.c v_randgen.c v_util.c v_pack.c v_pack.h v_pack_method.c v_prime.c v_randgen.c v_util.c \
verse_ms.c
LIBVERSE_OBJ = $(patsubst %h,, $(LIBVERSE_SRC:%.c=%.o)) LIBVERSE_OBJ = $(patsubst %h,, $(LIBVERSE_SRC:%.c=%.o))

View File

@@ -110,7 +110,8 @@ lib_source_files = (['v_cmd_buf.c',
'v_prime.c', 'v_prime.c',
'v_randgen.c', 'v_randgen.c',
'v_util.c', 'v_util.c',
'v_bignum.c' 'v_bignum.c',
'verse_ms.c'
]) ])
lib_source_files.extend(cmd_gen_deps) lib_source_files.extend(cmd_gen_deps)
@@ -135,10 +136,11 @@ verselib_env.Append(CPPDEFINES = defines)
verseserver_env = verse_env.Copy() verseserver_env = verse_env.Copy()
verseserver_env.Append(CPPDEFINES = defines) verseserver_env.Append(CPPDEFINES = defines)
verseserver_env.Append (LIBPATH = ['.']) verseserver_env.Append (LIBPATH = ['.'])
verseserver_env.Append (LIBS= ['verse'])
verseserver_env.Append (LIBS= platform_libs) verseserver_env.Append (LIBS= platform_libs)
verselib_env.BlenderLib(libname='verse', sources=lib_source_files, includes=["."], defines = defines, libtype=['core', 'intern'], priority = [5, 5]) verselib_env.BlenderLib(libname='verse', sources=lib_source_files, includes=["."], defines = defines, libtype=['core', 'intern'], priority = [5, 5])
verseserver_env.BlenderProg(builddir="#"+root_build_dir+os.sep, progname='verse', sources=server_source_files, libs=['verse'], verseserver_env.BlenderProg(builddir="#"+root_build_dir+os.sep, progname='verse', sources=server_source_files, libs=[],
libpath='#'+env['BF_BUILDDIR']+'/lib') libpath='#'+env['BF_BUILDDIR']+'/lib')

286
extern/verse/dist/verse_ms.c vendored Normal file
View File

@@ -0,0 +1,286 @@
/*
* A helper library to send and parse master server pings. See the relevant
* header for details.
*
* This code was written in 2006 by Emil Brink. It is released as public domain.
*/
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "verse.h"
#include "verse_ms.h"
/* Build and send a MS:GET packet. */
void verse_ms_get_send(const char *address, int fields, const char *tags)
{
char req[128];
strcpy(req, "MS:GET IP=");
if(fields & VERSE_MS_FIELD_DESCRIPTION)
strcat(req, "DE");
if(tags != NULL)
{
strcat(req, " TA=");
strcat(req, tags);
}
verse_send_ping(address, req);
}
/* Skip assign, i.e. "NAME=" string, at <msg>. Stores name into <put>, and then updates
* it. Returns NULL on parse error, in which case the <put> pointer is not advanced.
*/
static const char * skip_assign(char **put, const char *msg)
{
if(isalpha(*msg))
{
char *p = put != NULL ? *put : NULL;
if(p != NULL)
*p++ = *msg;
msg++;
while(*msg && (isalnum(*msg) || *msg == '_'))
{
if(p != NULL)
*p++ = *msg;
msg++;
}
if(*msg == '=')
{
if(p != NULL)
*p++ = '\0';
if(put != NULL)
*put = p;
return msg + 1;
}
}
return NULL;
}
/** Skip value at <msg>, optionally storing de-quoted version through <put>,
* which is advanced. Returns NULL on parse error, without updating <put>.
*/
static const char * skip_value(char **put, const char *msg)
{
char *p = (put != NULL) ? *put : NULL;
if(*msg == '"')
{
msg++;
while(*msg != '\0' && *msg != '"')
{
if(*msg == '\\')
{
if(msg[1] != '\0')
msg++;
else
return NULL;
}
if(p != NULL)
*p++ = *msg;
msg++;
}
if(*msg == '"')
{
if(p != NULL)
*p++ = '\0';
if(put != NULL)
*put = p;
msg++;
if(*msg == '\0' || isspace(*msg))
return msg;
}
return NULL;
}
while(*msg && !isspace(*msg))
{
if(*msg == '"')
return NULL;
if(p != NULL)
*p++ = *msg;
msg++;
}
if(p != NULL)
*p++ = '\0';
if(put != NULL)
*put = p;
return msg;
}
static const char * put_field(VMSField *field, char **put, const char *src)
{
const char *ptr;
char *base = *put;
if((ptr = skip_assign(put, src)) != NULL && ptr - src > 1)
{
field->name = base;
src = ptr;
base = *put;
if((ptr = skip_value(put, src)) != NULL)
{
field->value = base;
return ptr;
}
}
return NULL;
}
static int cmp_fields(const void *a, const void *b)
{
return strcmp(((const VMSField *) a)->name, ((const VMSField *) b)->name);
}
VMSServer ** verse_ms_list_parse(const char *msg)
{
const char *word[384]; /* Takes quite a lot of stack space. */
const char *ptr;
char *put;
size_t num_word = 0, i, j, num_ip = 0, num_field, space = 0;
VMSServer **desc, *next;
VMSField *field;
if(strncmp(msg, "MS:LIST", 7) == 0)
msg += 7;
if(*msg != ' ')
return NULL;
/* Step one: split the string into words, at whitespace. Split is aware
* of quoting rules for value assignment, this is crucial. This split is
* non-invasive, meaning each "word" will be a suffix.
*/
while(*msg)
{
while(isspace(*msg))
msg++;
ptr = skip_assign(NULL, msg);
if(ptr != NULL)
{
space += ptr - msg;
word[num_word++] = msg;
msg = ptr;
ptr = skip_value(NULL, msg);
if(ptr == NULL)
{
fprintf(stderr, "Parse error\n");
return NULL;
}
space += ptr - msg + 1;
msg = ptr;
}
else if(*msg != '\0')
{
fprintf(stderr, "Parse error\n");
return NULL;
}
}
/* Now, count how many words begin with "IP=". */
for(i = 0; i < num_word; i++)
{
if(strncmp(word[i], "IP=", 3) == 0)
num_ip++;
}
/* printf("found %u IPs, %u bytes\n", num_ip, space);
printf("%u IP and %u words -> %u fields total\n", num_ip, num_word, num_word - num_ip);
*/ num_field = num_word - num_ip;
/* Allocate the descriptions. */
/* printf("allocating %u bytes\n", (num_ip + 1) * (sizeof *desc) + num_ip * sizeof **desc + num_field * sizeof (VMSField) + space);
printf(" %u for pointers, %u for structs, %u for fields, %u string\n",
(num_ip + 1) * (sizeof *desc), num_ip * sizeof **desc, num_field * sizeof (VMSField), space);
*/ desc = malloc((num_ip + 1) * (sizeof *desc) + num_ip * sizeof **desc + num_field * sizeof (VMSField) + space);
next = (VMSServer *) (desc + (num_ip + 1));
/* printf("desc store at %u\n", (char *) next - (char *) desc);*/
field = (VMSField *) (next + num_ip);
/* printf("field store at %u\n", (char *) field - (char *) desc);*/
put = (char *) (field + num_field);
/* printf("string store at %u\n", put - (char *) desc);*/
for(i = j = 0; i < num_word;)
{
if(strncmp(word[i], "IP=", 3) == 0)
{
desc[j] = next;
next->ip = put;
ptr = skip_value(&put, word[i] + 3);
next->num_fields = 0;
next->field = field;
for(i++; i < num_word && strncmp(word[i], "IP=", 3) != 0; i++, next->num_fields++, field++)
put_field(&next->field[next->num_fields], &put, word[i]);
if(next->num_fields > 0) /* Sort the fields, for binary search later. */
qsort(next->field, next->num_fields, sizeof *next->field, cmp_fields);
j++;
next++;
}
else
i++;
}
desc[j] = NULL;
return desc;
}
/* A binary search, exploiting that the fields are sorted. */
static const VMSField * field_find(const VMSServer *ms, const char *name)
{
int lo, hi, mid, rel;
if(ms == NULL || name == NULL)
return NULL;
lo = 0;
hi = ms->num_fields;
while(lo <= hi)
{
mid = (lo + hi) / 2;
rel = strcmp(name, ms->field[mid].name);
if(rel == 0)
return &ms->field[mid];
if(rel < 0)
hi = mid - 1;
else
lo = mid + 1;
}
return NULL;
}
int verse_ms_field_exists(const VMSServer *ms, const char *name)
{
if(ms == NULL || name == NULL)
return 0;
return field_find(ms, name) != NULL;
}
const char * verse_ms_field_value(const VMSServer *ms, const char *name)
{
const VMSField *f;
if((f = field_find(ms, name)) != NULL)
return f->value;
return NULL;
}
#if defined VERSE_MS_STANDALONE
int main(void)
{
VMSServer **servers = verse_ms_list_parse("MS:LIST IP=127.0.0.1:4951 DE=\"A test server, mainly for Eskil\" COOL=yes BACKUP=daily LANG=sv_SE "
"IP=130.237.221.74 DE=\"Test server on a puny laptop\" COOL=yes DORKY=no OPEN=absolutely "
"IP=127.0.0.1:5151 DE=\"This is a back slash: '\\\\', cool huh?\" "
"IP=127.0.0.1:6676 DE=\"a quote looks like this: \\\"\" IP=127.0.0.1:1122 ");
if(servers != NULL)
{
int i, j;
printf("Server info:\n");
for(i = 0; servers[i] != NULL; i++)
{
printf("%u: IP=%s\n", i, servers[i]->ip);
for(j = 0; j < servers[i]->num_fields; j++)
printf(" %s='%s'\n", servers[i]->field[j].name, servers[i]->field[j].value);
}
free(servers);
}
return EXIT_SUCCESS;
}
#endif /* VERSE_MS_STANDALONE */

72
extern/verse/dist/verse_ms.h vendored Normal file
View File

@@ -0,0 +1,72 @@
/*
* This is Verse Master Server, a small help library to aid application developers
* make their applications interact with a Verse master server.
*
* There are two steps to the process:
*
* 1) Send a MS:GET request to a master server. This is done by the verse_ms_get_send()
* function, which calls verse_send_ping() internally.
*
* 2) Parse any returned MS:LIST packets. This is a two-step process. The application
* still owns the ping callback, and will need to check for received pings that
* start with MS:LIST, and call the verse_ms_list_parse() function to parse those.
*
* A successfully parsed MS:LIST packet will result in an array of VMSServer pointers
* being returned. Each VMSServer instance describes one server. Use the provided
* functions to query each server structure.
*
* The application should call free() on the returned vector, whenever it is done with
* the data (perhaps after copying it into application-defined data structures).
*
* For a lot more detail about the Verse master server protocol, please see
* the spec at <http://verse.blender.org/cms/Master_Server__v2.775.0.html>.
*
* This code was written in 2006 by Emil Brink. It is released as public domain.
*
*/
#define VERSE_MS_VERSION "1.0"
#if defined __cplusplus
extern "C" {
#endif
typedef struct {
const char *name; /* Field name. Upper-case. */
const char *value; /* Field value. Fully parsed, might contain spaces. */
} VMSField;
typedef struct {
const char *ip; /* IP address of server, in dotted decimal:port. */
unsigned int num_fields; /* Number of fields of extra info. */
VMSField *field; /* Vector of fields, or NULL if none. */
} VMSServer;
/* Formats and sends a MS:GET ping packet to the master server. The <fields> argument
* should be a combination of VERSE_MS_FIELD_ mask values. If <tags> is set, it should
* be a comma-separated set of include/exclude tags, like "a,b,-c,d,-e".
*/
#define VERSE_MS_FIELD_DESCRIPTION (1 << 0)
extern void verse_ms_get_send(const char *address, int fields, const char *tags);
/* Parses a master server response. This will be a string of the form "MS:LIST IP=blah ...",
* which is split into one struct per IP, and any additional fields parsed (unquoted etc).
* Returns an array of VMSServer pointers, which is NULL-terminated. Returns NULL if there
* was a parse error somewhere in the string, no partial success is possible.
*/
extern VMSServer ** verse_ms_list_parse(const char *list);
/* This is the only standard field name, currently. */
#define VERSE_MS_FIELD_DESCRIPTION_NAME "DE" /* Human-readable server description. */
/* Checks wether the given server has a field with the given name. */
extern int verse_ms_field_exists(const VMSServer *ms, const char *name);
/* Returns the value for the named field in the given server, if present.
* If not, NULL is returned.
*/
extern const char * verse_ms_field_value(const VMSServer *ms, const char *name);
#if defined __cplusplus
}
#endif

View File

@@ -229,6 +229,9 @@ ECHO Done
<File <File
RelativePath="..\..\dist\v_util.c"> RelativePath="..\..\dist\v_util.c">
</File> </File>
<File
RelativePath="..\..\dist\verse_ms.c">
</File>
</Filter> </Filter>
<Filter <Filter
Name="Header Files" Name="Header Files"
@@ -267,6 +270,9 @@ ECHO Done
RelativePath="..\..\dist\v_util.h"> RelativePath="..\..\dist\v_util.h">
</File> </File>
</Filter> </Filter>
<File
RelativePath="..\..\dist\verse_ms.h">
</File>
</Files> </Files>
<Globals> <Globals>
</Globals> </Globals>

View File

@@ -34,6 +34,7 @@
#include "BLI_dynamiclist.h" #include "BLI_dynamiclist.h"
#include "verse.h" #include "verse.h"
#include "verse_ms.h"
struct VNode; struct VNode;
@@ -322,6 +323,13 @@ typedef struct VNode {
void (*post_node_name_set)(struct VNode *vnode); void (*post_node_name_set)(struct VNode *vnode);
} VNode; } VNode;
typedef struct VerseServer {
struct VerseServer *next, *prev;
char *name; /* human-readable server name */
char *ip; /* string containing IP/domain name of verse server and number of port */
short flag; /* flag: VERSE_CONNECTING, VERSE_CONNECTED */
} VerseServer;
/* /*
* Verse Session: verse client can be connected to several verse servers * Verse Session: verse client can be connected to several verse servers
* it is neccessary to store some information about each session * it is neccessary to store some information about each session
@@ -438,6 +446,7 @@ struct VerseSession *current_verse_session(void);
struct VerseSession *create_verse_session(const char *name, const char *pass, const char *address, uint8 *expected_key); 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 free_verse_session(struct VerseSession *session);
void b_verse_update(void); void b_verse_update(void);
void b_vers_ms_get(void);
void b_verse_connect(char *address); void b_verse_connect(char *address);
void end_verse_session(struct VerseSession *session, char free); void end_verse_session(struct VerseSession *session, char free);
void end_all_verse_sessions(void); void end_all_verse_sessions(void);

View File

@@ -34,6 +34,7 @@
#include "DNA_mesh_types.h" /* temp */ #include "DNA_mesh_types.h" /* temp */
#include "DNA_listBase.h" #include "DNA_listBase.h"
#include "DNA_screen_types.h" #include "DNA_screen_types.h"
#include "DNA_userdef_types.h"
#include "BLI_dynamiclist.h" #include "BLI_dynamiclist.h"
#include "BLI_blenlib.h" #include "BLI_blenlib.h"
@@ -43,15 +44,88 @@
#include "BKE_global.h" #include "BKE_global.h"
#include "BKE_verse.h" #include "BKE_verse.h"
#include "verse.h"
struct ListBase session_list={NULL, NULL}; struct ListBase session_list={NULL, NULL};
struct ListBase server_list={NULL, NULL};
static cb_ping_registered = 0;
/* list of static function prototypes */ /* list of static function prototypes */
static void cb_connect_terminate(const char *address, const char *bye); 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 cb_connect_accept(void *user_data, uint32 avatar, void *address, void *connection, const uint8 *host_id);
static void set_all_callbacks(void); static void set_all_callbacks(void);
static void free_verse_session_data(struct VerseSession *session); static void free_verse_session_data(struct VerseSession *session);
static void add_verse_server(VMSServer *server);
static void check_connection_state(struct VerseServer *server);
static void check_connection_state(struct VerseServer *server)
{
struct VerseSession *session;
session = session_list.first;
while(session) {
if(strcmp(server->ip,session->address)==0) {
server->flag = session->flag;
return;
}
session = session->next;
}
}
/*
* add verse server to server_list. Prevents duplicate
* entries
*/
static void add_verse_server(VMSServer *server)
{
struct VerseServer *iter, *niter;
VerseServer *newserver;
const char *name = verse_ms_field_value(server, "DE");
iter = server_list.first;
while(iter) {
niter = iter->next;
if(strcmp(iter->ip, server->ip)==0) {
return;
}
iter = niter;
}
newserver = (VerseServer *)MEM_mallocN(sizeof(VerseServer), "VerseServer");
newserver->ip = (char *)MEM_mallocN(sizeof(char)*(strlen(server->ip)+1), "VerseServer ip");
strcpy(newserver->ip, server->ip);
if(name) {
newserver->name = (char *)MEM_mallocN(sizeof(char)*(strlen(name)+strlen(newserver->ip)+4), "VerseServer name");
strcpy(newserver->name, name);
strcat(newserver->name, " (");
strcat(newserver->name, newserver->ip);
strcat(newserver->name, ")");
}
newserver->flag = 0;
check_connection_state(newserver);
printf("Adding new verse server: %s at %s\n", newserver->name, newserver->ip);
BLI_addtail(&server_list, newserver);
post_server_add();
}
/*
* callback function for ping
*/
static void cb_ping(void *user, const char *address, const char *message)
{
VMSServer **servers = verse_ms_list_parse(message);
if(servers != NULL)
{
int i, j;
for(i = 0; servers[i] != NULL; i++)
{
add_verse_server(servers[i]);
}
free(servers);
}
}
/* /*
* callback function for connection terminated * callback function for connection terminated
@@ -83,6 +157,7 @@ static void cb_connect_accept(
const uint8 *host_id) const uint8 *host_id)
{ {
struct VerseSession *session = (VerseSession*)current_verse_session(); struct VerseSession *session = (VerseSession*)current_verse_session();
struct VerseServer *server = server_list.first;
uint32 i, mask=0; uint32 i, mask=0;
if(!session) return; if(!session) return;
@@ -90,6 +165,14 @@ static void cb_connect_accept(
session->flag |= VERSE_CONNECTED; session->flag |= VERSE_CONNECTED;
session->flag &= ~VERSE_CONNECTING; session->flag &= ~VERSE_CONNECTING;
while(server) {
if(strcmp(session->address, server->ip)==0) {
server->flag |= VERSE_CONNECTED;
server->flag &= ~VERSE_CONNECTING;
}
server = server->next;
}
printf("\tBlender was connected to verse server: %s\n", (char*)address); printf("\tBlender was connected to verse server: %s\n", (char*)address);
printf("\tVerseSession->counter: %d\n", session->counter); printf("\tVerseSession->counter: %d\n", session->counter);
@@ -111,6 +194,7 @@ void set_verse_session_callbacks(void)
verse_callback_set(verse_send_connect_accept, cb_connect_accept, NULL); verse_callback_set(verse_send_connect_accept, cb_connect_accept, NULL);
/* connection was terminated */ /* connection was terminated */
verse_callback_set(verse_send_connect_terminate, cb_connect_terminate, NULL); verse_callback_set(verse_send_connect_terminate, cb_connect_terminate, NULL);
} }
/* /*
@@ -151,6 +235,9 @@ void b_verse_update(void)
} }
session = next_session; session = next_session;
} }
if(cb_ping_registered>0) {
verse_callback_update(10);
}
} }
/* /*
@@ -298,8 +385,27 @@ void end_verse_session(VerseSession *session, char free)
if(free) free_verse_session(session); if(free) free_verse_session(session);
} }
void free_all_servers(void)
{
VerseServer *server, *nextserver;
server = server_list.first;
while(server) {
nextserver = server->next;
BLI_remlink(&server_list, server);
MEM_freeN(server->name);
MEM_freeN(server->ip);
MEM_freeN(server);
server = nextserver;
}
BLI_freelistN(&server_list);
}
/* /*
* end connection to all verse hosts (servers) ... free all VerseSessions * end connection to all verse hosts (servers) ... free all VerseSessions
* free all VerseServers
*/ */
void end_all_verse_sessions(void) void end_all_verse_sessions(void)
{ {
@@ -314,6 +420,25 @@ void end_all_verse_sessions(void)
} }
BLI_freelistN(&session_list); BLI_freelistN(&session_list);
free_all_servers();
}
/*
* do a get from ms
*/
void b_verse_ms_get(void)
{
if(cb_ping_registered==0) {
/* handle ping messages (for master server) */
verse_callback_set(verse_send_ping, cb_ping, NULL);
add_screenhandler(G.curscreen, SCREEN_HANDLER_VERSE, 1);
cb_ping_registered++;
}
free_all_servers();
verse_ms_get_send(U.versemaster, VERSE_MS_FIELD_DESCRIPTION, NULL);
verse_callback_update(10);
} }
/* /*

View File

@@ -120,6 +120,7 @@ void post_node_name_set(struct VNode *vnode);
void post_connect_accept(struct VerseSession *session); void post_connect_accept(struct VerseSession *session);
void post_connect_terminated(struct VerseSession *session); void post_connect_terminated(struct VerseSession *session);
void post_connect_update(struct VerseSession *session); void post_connect_update(struct VerseSession *session);
void post_server_add(void);
/* verse_image.c */ /* verse_image.c */

View File

@@ -143,6 +143,8 @@ typedef struct Library {
/*#ifdef WITH_VERSE*/ /*#ifdef WITH_VERSE*/
#define ID_VS MAKE_ID2('V', 'S') /* fake id for VerseSession, needed for outliner */ #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 */ #define ID_VN MAKE_ID2('V', 'N') /* fake id for VerseNode, needed for outliner */
#define ID_MS MAKE_ID2('M', 'S') /* fake id for VerseServer root entry, needed for outliner */
#define ID_SS MAKE_ID2('S', 'S') /* fake id for VerseServer entry, needed for ountliner */
/*#endif*/ /*#endif*/

View File

@@ -527,6 +527,8 @@ typedef struct SpaceImaSel {
#define SO_SAME_TYPE 5 #define SO_SAME_TYPE 5
#define SO_GROUPS 6 #define SO_GROUPS 6
#define SO_LIBRARIES 7 #define SO_LIBRARIES 7
#define SO_VERSE_SESSION 8
#define SO_VERSE_MS 9
/* SpaceOops->storeflag */ /* SpaceOops->storeflag */
#define SO_TREESTORE_CLEANUP 1 #define SO_TREESTORE_CLEANUP 1

View File

@@ -172,6 +172,7 @@ typedef struct UserDef {
short obcenter_dia; short obcenter_dia;
short rvisize; /* rotating view icon size */ short rvisize; /* rotating view icon size */
short rvibright; /* rotating view icon brightness */ short rvibright; /* rotating view icon brightness */
char versemaster[160];
short pad1; short pad1;
} UserDef; } UserDef;

View File

@@ -773,6 +773,10 @@ static void do_verse_filemenu(void *arg, int event)
printf("Disconnecting all sessions!\n"); printf("Disconnecting all sessions!\n");
end_all_verse_sessions(); end_all_verse_sessions();
break; break;
case 4:
printf("sending get to master server\n");
b_verse_ms_get();
break;
} }
} }
@@ -799,6 +803,7 @@ static uiBlock *verse_filemenu(void *unusedargs)
} }
} }
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Get Servers", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");
uiBlockSetDirection(block, UI_RIGHT); uiBlockSetDirection(block, UI_RIGHT);
uiTextBoundsBlock(block, 60); uiTextBoundsBlock(block, 60);

View File

@@ -477,10 +477,18 @@ void oops_buttons(void)
} }
#endif #endif
else { else {
if(G.main->library.first) if(G.main->library.first)
#ifdef WITH_VERSE
uiDefButS(block, MENU, B_REDR, "Outliner Display%t|Verse Servers %x9|Verse Sessions %x8|Libraries %x7|All Scenes %x0|Current Scene %x1|Visible Layers %x2|Groups %x6|Same Types %x5|Selected %x3|Active %x4", xco, 0, 100, 20, &soops->outlinevis, 0, 0, 0, 0, "");
#else
uiDefButS(block, MENU, B_REDR, "Outliner Display%t|Libraries %x7|All Scenes %x0|Current Scene %x1|Visible Layers %x2|Groups %x6|Same Types %x5|Selected %x3|Active %x4", xco, 0, 100, 20, &soops->outlinevis, 0, 0, 0, 0, ""); uiDefButS(block, MENU, B_REDR, "Outliner Display%t|Libraries %x7|All Scenes %x0|Current Scene %x1|Visible Layers %x2|Groups %x6|Same Types %x5|Selected %x3|Active %x4", xco, 0, 100, 20, &soops->outlinevis, 0, 0, 0, 0, "");
#endif /* WITH_VERSE */
else else
#ifdef WITH_VERSE
uiDefButS(block, MENU, B_REDR, "Outliner Display%t|Verse Servers %x9|Verse Sessions %x8|All Scenes %x0|Current Scene %x1|Visible Layers %x2|Groups %x6|Same Types %x5|Selected %x3|Active %x4", xco, 0, 100, 20, &soops->outlinevis, 0, 0, 0, 0, "");
#else
uiDefButS(block, MENU, B_REDR, "Outliner Display%t|All Scenes %x0|Current Scene %x1|Visible Layers %x2|Groups %x6|Same Types %x5|Selected %x3|Active %x4", xco, 0, 100, 20, &soops->outlinevis, 0, 0, 0, 0, ""); uiDefButS(block, MENU, B_REDR, "Outliner Display%t|All Scenes %x0|Current Scene %x1|Visible Layers %x2|Groups %x6|Same Types %x5|Selected %x3|Active %x4", xco, 0, 100, 20, &soops->outlinevis, 0, 0, 0, 0, "");
#endif /* WITH_VERSE */
} }
/* always do as last */ /* always do as last */

View File

@@ -124,6 +124,7 @@
#ifdef WITH_VERSE #ifdef WITH_VERSE
extern ListBase session_list; extern ListBase session_list;
extern ListBase server_list;
#endif #endif
/* ******************** PERSISTANT DATA ***************** */ /* ******************** PERSISTANT DATA ***************** */
@@ -724,6 +725,16 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
te->directdata = (void*)session; te->directdata = (void*)session;
te->idcode = ID_VS; te->idcode = ID_VS;
} }
else if(type==ID_MS) {
te->name = "Available Verse Servers";
te->idcode = ID_MS;
}
else if(type==ID_SS) {
struct VerseServer *server = (VerseServer *)idv;
te->name = server->name;
te->directdata = (void *)server;
te->idcode = ID_SS;
}
else if(type==ID_VN) { else if(type==ID_VN) {
struct VNode *vnode = (VNode*)idv; struct VNode *vnode = (VNode*)idv;
te->name = vnode->name; te->name = vnode->name;
@@ -888,31 +899,44 @@ static void outliner_build_tree(SpaceOops *soops)
} }
outliner_make_hierarchy(soops, &soops->tree); outliner_make_hierarchy(soops, &soops->tree);
} }
#ifdef WITH_VERSE
else if(soops->outlinevis == SO_VERSE_SESSION) {
/* 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;
}
}
}
}
}
else if(soops->outlinevis == SO_VERSE_MS) {
te= outliner_add_element(soops, &soops->tree, "MS", NULL, ID_MS, 0);
if(server_list.first!=NULL) {
struct VerseServer *server;
/* add one main entry to root of hierarchy */
for(server=server_list.first; server; server=server->next) {
ten= outliner_add_element(soops, &te->subtree, server, te, ID_SS, 0);
ten->directdata= server;
}
}
}
#endif
else { else {
ten= outliner_add_element(soops, &soops->tree, OBACT, NULL, 0, 0); ten= outliner_add_element(soops, &soops->tree, OBACT, NULL, 0, 0);
if(ten) ten->directdata= BASACT; 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); outliner_sort(soops, &soops->tree);
} }
@@ -1643,6 +1667,30 @@ static int do_outliner_mouse_event(SpaceOops *soops, TreeElement *te, short even
break; break;
} }
} }
else if(te->idcode==ID_MS) {
event = pupmenu("Verse Master Server %t| Refresh %x1");
b_verse_ms_get();
}
else if(te->idcode==ID_SS) {
struct VerseServer *vserver = (VerseServer*)te->directdata;
if(!(vserver->flag & VERSE_CONNECTING) && !(vserver->flag & VERSE_CONNECTED)) {
event = pupmenu("VerseServer %t| Connect %x1");
} else if((vserver->flag & VERSE_CONNECTING) && !(vserver->flag & VERSE_CONNECTED)) {
event = pupmenu("VerseServer %t| Connecting... %x2");
} else if(!(vserver->flag & VERSE_CONNECTING) && (vserver->flag & VERSE_CONNECTED)) {
event = pupmenu("VerseServer %t| Connected %x3");
}
switch(event) {
case 1:
b_verse_connect(vserver->ip);
vserver->flag |= VERSE_CONNECTING;
break;
case 2:
case 3:
break;
}
}
} }
else { else {
#endif #endif
@@ -2330,6 +2378,8 @@ static void tselem_draw_icon(float x, float y, TreeStoreElem *tselem, TreeElemen
BIF_icon_draw(x, y, ICON_WPAINT_DEHLT); break; BIF_icon_draw(x, y, ICON_WPAINT_DEHLT); break;
#ifdef WITH_VERSE #ifdef WITH_VERSE
case ID_VS: case ID_VS:
case ID_MS:
case ID_SS:
BIF_icon_draw(x, y, ICON_VERSE); break; BIF_icon_draw(x, y, ICON_VERSE); break;
case ID_VN: case ID_VN:
BIF_icon_draw(x, y, ICON_VERSE); break; BIF_icon_draw(x, y, ICON_VERSE); break;
@@ -2492,7 +2542,7 @@ static void outliner_draw_tree_element(SpaceOops *soops, TreeElement *te, int st
/* open/close icon, only when sublevels, except for scene */ /* open/close icon, only when sublevels, except for scene */
if(te->subtree.first || te->idcode==ID_SCE) { if(te->subtree.first || te->idcode==ID_SCE) {
int icon_x; int icon_x;
if(tselem->type==0 && (te->idcode==ID_OB || te->idcode==ID_SCE)) if((tselem->type==0 && (te->idcode==ID_OB || te->idcode==ID_SCE)) || te->idcode==ID_VN || te->idcode==ID_VS || te->idcode==ID_MS || te->idcode==ID_SS)
icon_x = startx; icon_x = startx;
else else
icon_x = startx+5; icon_x = startx+5;
@@ -2583,7 +2633,7 @@ static void outliner_draw_hierarchy(SpaceOops *soops, ListBase *lb, int startx,
tselem= TREESTORE(te); tselem= TREESTORE(te);
/* horizontal line? */ /* horizontal line? */
if(tselem->type==0 && (te->idcode==ID_OB || te->idcode==ID_SCE)) if((tselem->type==0 && (te->idcode==ID_OB || te->idcode==ID_SCE)) || ELEM4(te->idcode,ID_VS,ID_VN,ID_MS,ID_SS))
glRecti(startx, *starty, startx+OL_X, *starty-1); glRecti(startx, *starty, startx+OL_X, *starty-1);
*starty-= OL_H; *starty-= OL_H;
@@ -2596,7 +2646,7 @@ static void outliner_draw_hierarchy(SpaceOops *soops, ListBase *lb, int startx,
te= lb->last; te= lb->last;
if(te->parent || lb->first!=lb->last) { if(te->parent || lb->first!=lb->last) {
tselem= TREESTORE(te); tselem= TREESTORE(te);
if(tselem->type==0 && te->idcode==ID_OB) { if((tselem->type==0 && te->idcode==ID_OB) || ELEM4(te->idcode,ID_VS,ID_VN,ID_MS,ID_SS)) {
glRecti(startx, y1+OL_H, startx+1, y2); glRecti(startx, y1+OL_H, startx+1, y2);
} }

View File

@@ -3015,6 +3015,14 @@ void drawinfospace(ScrArea *sa, void *spacedata)
} }
} else if (U.userpref == 4) { /* system & opengl */ } else if (U.userpref == 4) { /* system & opengl */
#ifdef WITH_VERSE
uiDefBut(block, TEX, 0, "Verse Master: ",
(xpos+edgsp),y3label+buth+5,mpref*2,buth,
U.versemaster, 1.0, 63.0, 0, 0,
"The Verse Master-server IP");
#endif
uiDefBut(block, LABEL,0,"Solid OpenGL light:", uiDefBut(block, LABEL,0,"Solid OpenGL light:",
xpos+edgsp, y3label, mpref, buth, xpos+edgsp, y3label, mpref, buth,
0, 0, 0, 0, 0, ""); 0, 0, 0, 0, 0, "");

View File

@@ -352,6 +352,12 @@ static void init_userdef_file(void)
refresh_interface_font(); refresh_interface_font();
#ifdef WITH_VERSE
if(strlen(U.versemaster)<1) {
strcpy(U.versemaster, "master.uni-verse.org");
}
#endif
} }
#ifdef WITH_VERSE #ifdef WITH_VERSE

View File

@@ -45,6 +45,7 @@
#include "BIF_interface.h" #include "BIF_interface.h"
extern ListBase session_list; extern ListBase session_list;
extern ListBase server_list;
/* /*
* this function creates popup menu with all active VerseSessions * this function creates popup menu with all active VerseSessions
@@ -221,10 +222,26 @@ void post_node_name_set(VNode *vnode)
*/ */
void post_connect_accept(VerseSession *session) void post_connect_accept(VerseSession *session)
{ {
VerseServer *server;
G.f |= G_VERSE_CONNECTED; G.f |= G_VERSE_CONNECTED;
session->counter = 0; session->counter = 0;
server = server_list.first;
while(server) {
if(strcmp(server->ip, session->address)==0) {
server->flag = session->flag;
break;
}
server = server->next;
}
allqueue(REDRAWOOPS, 0);
}
void post_server_add(void)
{
allqueue(REDRAWOOPS, 0); allqueue(REDRAWOOPS, 0);
} }
@@ -233,6 +250,16 @@ void post_connect_accept(VerseSession *session)
*/ */
void post_connect_terminated(VerseSession *session) void post_connect_terminated(VerseSession *session)
{ {
VerseServer *server;
server = server_list.first;
while(server) {
if(strcmp(server->ip, session->address)==0) {
server->flag = 0;
break;
}
server = server->next;
}
/* if it is last session, then no other will exist ... set Global flag */ /* if it is last session, then no other will exist ... set Global flag */
if((session->prev==NULL) && (session->next==NULL)) if((session->prev==NULL) && (session->next==NULL))
G.f &= ~G_VERSE_CONNECTED; G.f &= ~G_VERSE_CONNECTED;