Project::OSiRiON - Git repositories
Project::OSiRiON
News . About . Screenshots . Downloads . Forum . Wiki . Tracker . Git
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStijn Buys <ingar@osirion.org>2008-11-09 11:43:28 +0000
committerStijn Buys <ingar@osirion.org>2008-11-09 11:43:28 +0000
commit9d39702824e8fae5127e09fb5a05b521b48cd028 (patch)
treea56fdfc6e85a2405461be22bc80e43b33c8b8b48
parent6cd1a38f1d3a0a45846d63a75475400372af1277 (diff)
docking menus
-rw-r--r--src/client/client.cc10
-rw-r--r--src/client/input.cc8
-rw-r--r--src/client/view.cc18
-rw-r--r--src/core/Makefile.am9
-rw-r--r--src/core/descriptions.cc245
-rw-r--r--src/core/descriptions.h128
-rw-r--r--src/core/entity.cc29
-rw-r--r--src/core/entity.h19
-rw-r--r--src/core/net.h2
-rw-r--r--src/core/netclient.cc21
-rw-r--r--src/core/netclient.h7
-rw-r--r--src/core/netconnection.cc37
-rw-r--r--src/core/netserver.cc25
-rw-r--r--src/core/parser.cc16
-rw-r--r--src/core/parser.h3
-rw-r--r--src/core/player.cc48
-rw-r--r--src/game/base/base.cc63
-rw-r--r--src/game/base/base.h1
-rw-r--r--src/render/camera.cc11
-rw-r--r--src/render/camera.h1
-rw-r--r--src/ui/Makefile.am9
-rw-r--r--src/ui/container.cc25
-rw-r--r--src/ui/container.h11
-rw-r--r--src/ui/menu.cc23
-rw-r--r--src/ui/menuview.cc95
-rw-r--r--src/ui/menuview.h42
-rw-r--r--src/ui/ui.cc48
-rw-r--r--src/ui/ui.h8
-rw-r--r--src/ui/widget.cc5
-rw-r--r--src/ui/widget.h6
30 files changed, 838 insertions, 135 deletions
diff --git a/src/client/client.cc b/src/client/client.cc
index a83beb7..617b569 100644
--- a/src/client/client.cc
+++ b/src/client/client.cc
@@ -187,11 +187,21 @@ void Client::frame(unsigned long timestamp)
// show the join menu when player does not control an entity
} else if (core::game()->time() && !core::localcontrol()) {
ui::root()->show_menu("join");
+
+ // show the view menu when docked
+ } else if (core::localcontrol() && core::localplayer()->view()) {
+ ui::root()->show_menuview("main");
}
+
} else {
if (core::localcontrol()) {
+ // hide join menu
if (ui::root()->active()->label().compare("join") == 0) {
ui::root()->hide_menu();
+
+ // hide view menu
+ } else if (!core::localplayer()->view() && (ui::root()->active()->label().compare("view") == 0)) {
+ ui::root()->hide_menu();
}
}
}
diff --git a/src/client/input.cc b/src/client/input.cc
index 9cb48a1..dcddea3 100644
--- a/src/client/input.cc
+++ b/src/client/input.cc
@@ -133,7 +133,7 @@ void func_ui_control(std::string const &args)
void func_view_next(std::string const &args)
{
- if (core::application()->connected() && core::localcontrol()) {
+ if (!core::localplayer()->view() && core::application()->connected() && core::localcontrol()) {
render::Camera::view_next();
local_roll = 0;
local_pitch = 0;
@@ -144,7 +144,7 @@ void func_view_next(std::string const &args)
void func_view_prev(std::string const &args)
{
- if (core::application()->connected() && core::localcontrol()) {
+ if (!core::localplayer()->view() && core::application()->connected() && core::localcontrol()) {
render::Camera::view_previous();
local_roll = 0;
local_pitch = 0;
@@ -511,7 +511,7 @@ void key_pressed(Key *key)
if (ui::root()->input_key(true, Keyboard::translate_keysym(key->sym(), keyboard_modifiers), keyboard_modifiers)) {
return;
- } else if (core::application()->connected() && core::localcontrol()) {
+ } else if (!core::localplayer()->view() && core::application()->connected() && core::localcontrol()) {
char c = key->bind(convert_SDL_modifier(keyboard_modifiers)).c_str()[0];
if (c == '@') {
@@ -529,7 +529,7 @@ void key_pressed(Key *key)
} else if (core::application()->connected()) {
char c = key->bind(convert_SDL_modifier(keyboard_modifiers)).c_str()[0];
- if (c && c != '+') {
+ if (c && c != '+' && c != '@') {
// normal bind
core::cmd() << key->bind(convert_SDL_modifier(keyboard_modifiers)) << "\n";
}
diff --git a/src/client/view.cc b/src/client/view.cc
index 9eb9c33..304d2a5 100644
--- a/src/client/view.cc
+++ b/src/client/view.cc
@@ -455,6 +455,15 @@ void draw_entity_target(core::Entity *entity, bool is_active_target)
glVertex3f(cx, cy-r+2, 0);
render::gl::end();
+ if ((entity->flags() & core::Entity::Dockable) == core::Entity::Dockable) {
+ render::gl::begin(render::gl::LineLoop);
+ glVertex3f(cx+ (r*0.25f), cy+2, 0);
+ glVertex3f(cx, cy+(r*0.25f)+2, 0);
+ glVertex3f(cx-(r*0.25f), cy+2, 0);
+ glVertex3f(cx, cy-(r*0.25f)+2, 0);
+ render::gl::end();
+ }
+
if (entity == core::localplayer()->mission_target()) {
render::gl::color(1, 0.5f, 1, 1); // FIXME mission color
} else if (entity->type() == core::Entity::Controlable) {
@@ -471,6 +480,15 @@ void draw_entity_target(core::Entity *entity, bool is_active_target)
glVertex3f(cx, cy-r, 0);
render::gl::end();
+ if ((entity->flags() & core::Entity::Dockable) == core::Entity::Dockable) {
+ render::gl::begin(render::gl::LineLoop);
+ glVertex3f(cx+(r*0.25f), cy, 0);
+ glVertex3f(cx, cy+(r*0.25f), 0);
+ glVertex3f(cx-(r*0.25f), cy, 0);
+ glVertex3f(cx, cy-(r*0.25f), 0);
+ render::gl::end();
+ }
+
render::gl::enable(GL_TEXTURE_2D);
if (is_active_target) {
diff --git a/src/core/Makefile.am b/src/core/Makefile.am
index 61622e0..2c90dec 100644
--- a/src/core/Makefile.am
+++ b/src/core/Makefile.am
@@ -2,9 +2,9 @@ METASOURCES = AUTO
INCLUDES = -I$(top_srcdir)/src
libcore_la_SOURCES = application.cc clientstate.cc commandbuffer.cc core.cc \
- cvar.cc entity.cc func.cc gameconnection.cc gameinterface.cc gameserver.cc \
- module.cc netclient.cc netconnection.cc netplayer.cc netserver.cc parser.cc \
- player.cc stats.cc timer.cc zone.cc
+ cvar.cc descriptions.cc entity.cc func.cc gameconnection.cc gameinterface.cc \
+ gameserver.cc module.cc netclient.cc netconnection.cc netplayer.cc netserver.cc \
+ parser.cc player.cc stats.cc timer.cc zone.cc
libcore_la_LDFLAGS = -avoid-version -no-undefined
libcore_la_LIBADD = $(top_builddir)/src/model/libmodel.la \
$(top_builddir)/src/filesystem/libfilesystem.la $(top_builddir)/src/math/libmath.la $(top_builddir)/src/sys/libsys.la \
@@ -14,5 +14,4 @@ noinst_LTLIBRARIES = libcore.la
noinst_HEADERS = application.h clientstate.h commandbuffer.h core.h cvar.h \
entity.h func.h gameconnection.h gameinterface.h gameserver.h message.h module.h \
net.h netclient.h netconnection.h netserver.h player.h range.h stats.h \
- timer.h parser.h
-
+ timer.h parser.h descriptions.h
diff --git a/src/core/descriptions.cc b/src/core/descriptions.cc
new file mode 100644
index 0000000..fe37d2c
--- /dev/null
+++ b/src/core/descriptions.cc
@@ -0,0 +1,245 @@
+/*
+ core/descriptions.cc
+ This file is part of the Osirion project and is distributed under
+ the terms of the GNU General Public License version 2
+*/
+
+#include "core/descriptions.h"
+#include "auxiliary/functions.h"
+#include "sys/sys.h"
+
+namespace core {
+
+/* ---- class ButtonDescription ------------------------------------ */
+
+ButtonDescription::ButtonDescription()
+{
+ button_model = 0;
+ button_align = Center;
+}
+
+ButtonDescription::~ButtonDescription()
+{
+}
+
+void ButtonDescription::set_text(const std::string &text)
+{
+ button_text.assign(text);
+}
+
+void ButtonDescription::set_command(const std::string &command)
+{
+ button_command.assign(command);
+}
+
+void ButtonDescription::set_modelname(const std::string &modelname)
+{
+ button_modelname.assign(modelname);
+
+ button_model = model::Model::load(modelname);
+}
+
+void ButtonDescription::set_alignment(Align align)
+{
+ button_align = align;
+}
+
+/* ---- class MenuDescription -------------------------------------- */
+
+MenuDescription::MenuDescription()
+{
+}
+
+MenuDescription::~MenuDescription()
+{
+ for (Buttons::iterator it = buttons().begin(); it != buttons().end(); it++) {
+ delete (*it);
+ }
+
+ buttons().clear();
+}
+
+void MenuDescription::set_text(const std::string &text)
+{
+ menu_text.assign(text);
+}
+
+void MenuDescription::set_label(const std::string &label)
+{
+ menu_label.assign(label);
+}
+
+void MenuDescription::add_button(ButtonDescription *button)
+{
+ buttons().push_back(button);
+}
+
+/* ---- class Descriptions ----------------------------------------- */
+
+
+void Descriptions::serialize(MenuDescription *menu, std::ostream & os)
+{
+ os << menu->label() << " "
+ << "\"" << menu->text() << "\" "
+ << menu->buttons().size() << " ";
+
+ for (MenuDescription::Buttons::iterator it = menu-> buttons().begin(); it != menu->buttons().end(); it++) {
+ ButtonDescription *button = (*it);
+ os << "\"" << button->text() << "\" "
+ << button->alignment() << " "
+ << "\"" << button->command() << "\" "
+ << "\"" << button->modelname() << "\" ";
+ }
+}
+
+MenuDescription * Descriptions::receive(std::istream &is)
+{
+ MenuDescription *menu = new MenuDescription();
+
+ int a;
+ std::string n;
+ size_t nb;
+ char c;
+
+ // menu label
+ is >> n;
+ menu->set_label(n);
+
+ // menu text
+ n.clear();
+ while ( (is.get(c)) && (c != '"'));
+ while ( (is.get(c)) && (c != '"'))
+ n += c;
+
+ if (n.size())
+ menu->set_text(n);
+
+ // menu buttons
+ is >> nb;
+ for (size_t i=0; i < nb; i++) {
+ ButtonDescription *button = new ButtonDescription();
+ // button text
+ n.clear();
+ while ( (is.get(c)) && (c != '"'));
+ while ( (is.get(c)) && (c != '"'))
+ n += c;
+ if (n.size()) button->set_text(n);
+
+ // button alignment
+ a = ButtonDescription::Center;
+ is >> a;
+ if (a == ButtonDescription::Left)
+ button->set_alignment(ButtonDescription::Left);
+ else if (a == ButtonDescription::Right)
+ button->set_alignment(ButtonDescription::Right);
+ else
+ button->set_alignment(ButtonDescription::Center);
+
+ // button command
+ n.clear();
+ while ( (is.get(c)) && (c != '"'));
+ while ( (is.get(c)) && (c != '"'))
+ n += c;
+ if (n.size()) button->set_command(n);
+
+ // button modelname
+ n.clear();
+ while ( (is.get(c)) && (c != '"'));
+ while ( (is.get(c)) && (c != '"'))
+ n += c;
+ if (n.size()) button->set_modelname(n);
+
+ menu->add_button(button);
+ }
+
+ return menu;
+
+}
+
+bool Descriptions::load_entity_menus(core::Entity *entity, const std::string &menufilename)
+{
+ filesystem::IniFile inifile;
+ inifile.open(menufilename);
+
+ if (!inifile.is_open()) {
+ return false;
+ }
+
+ con_debug << " " << inifile.name() << std::endl;
+
+ std::string strval;
+ MenuDescription *menu = 0;
+ ButtonDescription *button = 0;
+
+ while (inifile.getline()) {
+
+ if (inifile.got_section()) {
+ if (inifile.got_section("menu")) {
+ menu = new MenuDescription;
+ entity->add_menu(menu);
+
+ } else if (inifile.got_section("button")) {
+ if (menu) {
+ button = new ButtonDescription();
+ menu->add_button(button);
+ }
+ } else {
+ inifile.unknown_section();
+ }
+
+ } else if (inifile.got_key()) {
+
+ if (inifile.in_section("menu")) {
+
+ if (inifile.got_key_string("label", strval)) {
+ aux::to_label(strval);
+ menu->set_label(strval);
+ } else if (inifile.got_key_string("text", strval)) {
+ aux::strip_quotes(strval);
+ menu->set_text(strval);
+ } else {
+ inifile.unkown_key();
+ }
+
+ } else if (inifile.in_section("button")) {
+
+ if (!button) {
+ continue;
+ } else if (inifile.got_key_string("text", strval)) {
+ aux::strip_quotes(strval);
+ button->set_text(strval);
+ } else if (inifile.got_key_string("command", strval)) {
+ for (size_t i =0; i <= strval.size(); i++) {
+ if (strval[i] == ',') strval[i] = ';';
+ }
+ aux::strip_quotes(strval);
+ button->set_command(strval);
+ } else if (inifile.got_key_string("model", strval)) {
+ button->set_modelname(strval);
+ } else if (inifile.got_key_string("align", strval)) {
+ aux::to_label(strval);
+ if (strval.compare("left") == 0) {
+ button->set_alignment(ButtonDescription::Left);
+ } else if (strval.compare("center") == 0) {
+ button->set_alignment(ButtonDescription::Center);
+ } else if (strval.compare("right") == 0) {
+ button->set_alignment(ButtonDescription::Right);
+ } else {
+ inifile.unknown_value();
+ }
+ } else {
+ inifile.unkown_key();
+ }
+
+ }
+ }
+ }
+
+ inifile.close();
+ return true;
+}
+
+}
+
+
+
diff --git a/src/core/descriptions.h b/src/core/descriptions.h
new file mode 100644
index 0000000..345d354
--- /dev/null
+++ b/src/core/descriptions.h
@@ -0,0 +1,128 @@
+/*
+ core/descriptions.h
+ This file is part of the Osirion project and is distributed under
+ the terms of the GNU General Public License version 2
+*/
+
+#ifndef __INCLUDED_CORE_DESCRIPTIONS_H__
+#define __INCLUDED_CORE_DESCRIPTIONS_H__
+
+#include <string>
+#include <list>
+#include <iostream>
+
+namespace core {
+class ButtonDescription;
+class MenuDescription;
+}
+
+#include "core/entity.h"
+#include "model/model.h"
+#include "filesystem/inifile.h"
+
+namespace core {
+
+/// description of a menu button
+class ButtonDescription
+{
+public:
+ enum Align {Center=0, Left=1, Right=2};
+
+ ButtonDescription();
+ ~ButtonDescription();
+
+ /* -- inspectors ------------------------------------------- */
+
+ /// button text
+ inline const std::string & text() const { return button_text; }
+
+ /// button command
+ inline const std::string & command() const { return button_command; }
+
+ /// button info view model name
+ inline const std::string & modelname() const { return button_modelname; }
+
+ /// button info view model
+ inline const model::Model *model() { return button_model; }
+
+ /// button text alignment
+ inline Align alignment() const { return button_align; }
+
+ /* -- mutators -------------------------------------------- */
+
+ /// set button text
+ void set_text(const std::string &text);
+
+ /// set button command
+ void set_command(const std::string &command);
+
+ /// set button name
+ void set_modelname(const std::string &modelname);
+
+ /// set text alignment
+ void set_alignment(Align align);
+
+private:
+ std::string button_text;
+ std::string button_command;
+ std::string button_modelname;
+ Align button_align;
+
+ model::Model *button_model;
+};
+
+/// description of an entity menu
+class MenuDescription
+{
+public:
+ MenuDescription();
+ ~MenuDescription();
+
+ typedef std::list<ButtonDescription *> Buttons;
+
+ /* -- inspectors ------------------------------------------- */
+
+ /// menu label
+ inline const std::string & label() const { return menu_label; }
+
+ /// menu text
+ inline const std::string & text() const { return menu_text; }
+
+ /// menu buttons
+ inline Buttons &buttons() { return menu_buttons; }
+
+ /* -- mutators -------------------------------------------- */
+
+ /// set menu text
+ void set_text(const std::string &text);
+
+ /// set menu label
+ void set_label(const std::string &label);
+
+ /// add a menu button
+ void add_button(ButtonDescription *button);
+
+private:
+ std::string menu_label;
+ std::string menu_text;
+
+ Buttons menu_buttons;
+};
+
+
+/// descriptions loader class
+class Descriptions {
+public:
+ /// read entity menus from ini file
+ static bool load_entity_menus(core::Entity *entity, const std::string &menufilename);
+ /// serialize entity menus to a stream
+ static void serialize(MenuDescription *menu, std::ostream & os);
+ /// read entity menus from a stream
+ static MenuDescription * receive(std::istream &is);
+};
+
+}
+
+#endif // __INCLUDED_CORE_DESCRIPTIONS_H__
+
+
diff --git a/src/core/entity.cc b/src/core/entity.cc
index 9bc3f3c..e2aac1c 100644
--- a/src/core/entity.cc
+++ b/src/core/entity.cc
@@ -133,6 +133,12 @@ Entity::Entity(std::istream & is)
Entity::~Entity()
{
+ // delete entity menus
+ for (Menus::iterator it = menus().begin(); it != menus().end(); it++) {
+ delete (*it);
+ }
+ menus().clear();
+
if (entity_clientstate) {
delete entity_clientstate;
entity_clientstate = 0;
@@ -346,6 +352,29 @@ void Entity::frame(float seconds)
{
}
+void Entity::add_menu(MenuDescription *menu)
+{
+ entity_menus.push_back(menu);
+}
+
+MenuDescription *Entity::find_menu(std::string const &label)
+{
+ for (Menus::iterator it = menus().begin(); it != menus().end(); it++) {
+ if (label.compare((*it)->label()) == 0)
+ return (*it);
+ }
+ return 0;
+}
+
+void Entity::remove_menu(std::string const &label)
+{
+ for (Menus::iterator it = menus().begin(); it != menus().end(); it++) {
+ if (label.compare((*it)->label()) == 0)
+ menus().erase(it);
+ return;
+ }
+}
+
/* ---- class EntityDynamic ---------------------------------------- */
EntityDynamic::EntityDynamic(unsigned int flags) :
diff --git a/src/core/entity.h b/src/core/entity.h
index 09b52a1..2e3b443 100644
--- a/src/core/entity.h
+++ b/src/core/entity.h
@@ -10,6 +10,7 @@
#include <iostream>
#include <string>
#include <map>
+#include <list>
#include "model/model.h"
#include "math/axis.h"
@@ -24,6 +25,7 @@ class EntityControlable;
}
#include "core/clientstate.h"
+#include "core/descriptions.h"
#include "core/player.h"
#include "core/zone.h"
@@ -46,6 +48,9 @@ public:
/// EntityDynamic event state classes
enum Event {Normal=0, NoPower=1, ImpulseInitiate=2, Impulse=3, JumpInitiate=4, Jump=5, Docked=6};
+ /// entity menus collection typedef
+ typedef std::list<MenuDescription *> Menus;
+
/// create a new entity and add it to the registry
Entity(unsigned int flags = 0);
@@ -117,6 +122,12 @@ public:
/// general visibility
inline bool visible() const { return entity_visible; }
+ /// entity menus
+ inline Menus &menus() { return entity_menus; }
+
+ /// find a menu
+ MenuDescription *find_menu(std::string const &label);
+
/*----- serializers ----------------------------------------------- */
/// serialize the entity to a stream
@@ -191,6 +202,12 @@ public:
/// unset a flag
void unset_flag(Flags flag);
+ /// add an entity menu
+ void add_menu(MenuDescription *menu);
+
+ /// remove an entity menu
+ void remove_menu(std::string const &label);
+
/// clear all update flags
virtual void clear_updates();
@@ -252,6 +269,8 @@ private:
model::Model *entity_model;
std::string entity_modelname;
+ Menus entity_menus;
+
static Registry entity_registry;
static size_t entity_nextid;
diff --git a/src/core/net.h b/src/core/net.h
index fe264e8..f3774b5 100644
--- a/src/core/net.h
+++ b/src/core/net.h
@@ -11,7 +11,7 @@ namespace core
{
/// network protocol version
-const unsigned int PROTOCOLVERSION = 13;
+const unsigned int PROTOCOLVERSION = 14;
/// maximum lenght of a (compressed) network message block
const unsigned int FRAMESIZE = 1152;
diff --git a/src/core/netclient.cc b/src/core/netclient.cc
index f75d8f3..253cf4f 100644
--- a/src/core/netclient.cc
+++ b/src/core/netclient.cc
@@ -18,19 +18,24 @@
namespace core
{
-NetClient::NetClient(std::string host, int port) :
+NetClient::NetClient(std::string host, int port, int fd) :
client_host(host)
{
client_error = true;
client_state = Connecting;
+ client_fd = fd;
+ client_host = host;
+ client_port = port;
client_player = new NetPlayer(this);
+ if (!fd) {
+ con_warn << "Network invalid client file descriptor!" << std::endl;
+ abort();
+ return;
+ }
con_print << host << ":" << port << " connected." << std::endl;
- client_host = host;
- client_port = port;
-
client_addr.sin_family = AF_INET;
client_addr.sin_port = htons(port);
client_addr.sin_addr.s_addr = inet_addr(host.c_str());
@@ -120,10 +125,14 @@ void NetClient::send_raw(std::string const &msg)
if (error())
return;
+ if ((sendq.size()) && (sendq.size() + msg.size() >= BLOCKSIZE - 16 )) {
+ transmit();
+ }
+
sendq.append(msg);
}
-void NetClient::transmit(int serverfd)
+void NetClient::transmit()
{
if (!sendq.size()) {
if (client_keepalive + NETTIMEOUT/2 < application()->time()) {
@@ -166,7 +175,7 @@ void NetClient::transmit(int serverfd)
size_t total_sent = 0;
while (total_sent < total_size && !error()) {
- ssize_t bytes_sent = ::sendto(serverfd, data, total_size - total_sent, 0,
+ ssize_t bytes_sent = ::sendto(fd(), data, total_size - total_sent, 0,
(struct sockaddr *)&client_addr, sizeof(client_addr));
if (bytes_sent < 0) {
diff --git a/src/core/netclient.h b/src/core/netclient.h
index 6e5bcf9..c0cdf8d 100644
--- a/src/core/netclient.h
+++ b/src/core/netclient.h
@@ -43,7 +43,7 @@ namespace core
class NetClient
{
public:
- NetClient(std::string host, int port);
+ NetClient(std::string host, int port, int fd);
~NetClient();
/// the remote hostname the client is connected to
@@ -68,7 +68,7 @@ public:
void retreive(std::string & message);
/// transmit messages in the send queue to the remote client
- void transmit(int serverfd);
+ void transmit();
inline bool error() const { return client_error; }
@@ -84,9 +84,12 @@ public:
float client_keepalive;
private:
+ inline int fd() const { return client_fd; }
+
struct sockaddr_in client_addr;
std::string client_host;
int client_port;
+ int client_fd;
bool client_error;
NetPlayer *client_player;
diff --git a/src/core/netconnection.cc b/src/core/netconnection.cc
index ba23df3..0bb33db 100644
--- a/src/core/netconnection.cc
+++ b/src/core/netconnection.cc
@@ -515,7 +515,7 @@ void NetConnection::parse_incoming_message(const std::string & message)
entity = new EntityGlobe(msgstream);
break;
default:
- con_warn << "Received create for unknown entity type " << type << std::endl;
+ con_warn << "Received create for unknown entity type " << type << "!" << std::endl;
return;
break;
}
@@ -527,6 +527,37 @@ void NetConnection::parse_incoming_message(const std::string & message)
game()->update_entity_clientstate(entity);
}
+ } else if (command == "menu") {
+
+ unsigned int id = 0;
+ if (msgstream >> id) {
+ if (!id) {
+ con_warn << "Received menu for NULL entity!" << std::endl;
+ return;
+ }
+
+ Entity *entity = Entity::find(id);
+ if (!entity) {
+ con_warn << "Received menu for unknown entity " << id << "!" << std::endl;
+ return;
+ }
+
+ MenuDescription *menu = Descriptions::receive(msgstream);
+ if (!menu->label().size()) {
+ con_warn << "Received menu without label for entity " << id << "!" << std::endl;
+ delete menu;
+ return;
+ }
+
+ // remove the menu if it already exists
+ entity->remove_menu(menu->label());
+
+ //con_debug << "receiving menu " << entity->label() << " " << menu->label() << std::endl;
+ entity->add_menu(menu);
+ } else {
+ con_warn << "Received illegal menu message!" << std::endl;
+ }
+
} else if (command.compare("zone") == 0) {
unsigned int id;
@@ -554,7 +585,7 @@ void NetConnection::parse_incoming_message(const std::string & message)
int player_id;
if (!(msgstream >> player_id)) {
- con_warn << "Received illegal update player info for player!" << std::endl;
+ con_warn << "Received illegal player info message!" << std::endl;
return;
}
@@ -607,7 +638,7 @@ void NetConnection::parse_incoming_message(const std::string & message)
Entity *entity = Entity::find(id);
if (!entity) {
// FIXME request entity from the server
- con_warn << "Update for unknown entity " << id << std::endl;
+ con_warn << "Update for unknown entity " << id << "!" << std::endl;
} else {
// FIXME check of the received update matches the actual entity
entity->receive_server_update(msgstream);
diff --git a/src/core/netserver.cc b/src/core/netserver.cc
index 3f0d2e8..b61ae1f 100644
--- a/src/core/netserver.cc
+++ b/src/core/netserver.cc
@@ -104,7 +104,7 @@ NetServer::~NetServer()
server()->player_disconnect((*it)->player());
(*it)->send_raw(netmsg);
- (*it)->transmit(fd());
+ (*it)->transmit();
delete (*it);
}
@@ -265,7 +265,7 @@ NetClient * NetServer::client_connect(std::string const host, int const port)
{
con_debug << "client_connect " << host << ":" << port << "\n";
- NetClient *client = new NetClient(host, port);
+ NetClient *client = new NetClient(host, port, fd());
if (client->error()) {
con_warn << client->host() << ":" << client->port() << " connection failed!\n";
delete(client);
@@ -283,7 +283,7 @@ void NetServer::client_initialize(NetClient *client) {
std::string welcome("^B");
welcome.append(Cvar::sv_name->str());
client->player()->send(welcome);
- client->transmit(fd());
+ client->transmit();
// send zones
for (Zone::Registry::iterator it = Zone::registry().begin(); it != Zone::registry().end(); it++) {
@@ -293,7 +293,7 @@ void NetServer::client_initialize(NetClient *client) {
// send connect completed
std::string connect("connect\n");
client->send_raw(connect);
- client->transmit(fd());
+ client->transmit();
// set client state to pending
client->client_state = NetClient::Pending;
@@ -373,7 +373,7 @@ void NetServer::frame(unsigned long timestamp)
for (Clients::iterator it = clients.begin(); it != clients.end(); it++) {
NetClient *client = *it;
- client->transmit(fd());
+ client->transmit();
if (client->state() == NetClient::Connected)
client_frame(client, timestamp);
@@ -386,7 +386,7 @@ void NetServer::frame(unsigned long timestamp)
client->player()->player_dirty = false;
client->player()->player_zonechange = false;
}
- client->transmit(fd());
+ client->transmit();
}
}
@@ -425,7 +425,7 @@ void NetServer::send_message(NetClient *client, const char *channel, std::string
void NetServer::send_disconnect(NetClient *client)
{
client->send_raw("disconnect\n");
- client->transmit(netserver_fd);
+ client->transmit();
client->abort();
}
@@ -450,6 +450,17 @@ void NetServer::send_entity_create(NetClient *client, Entity *entity)
entity->serialize_server_create(msg);
msg << '\n';
client->send_raw(msg.str());
+
+ // send entity menus
+ for (Entity::Menus::iterator it = entity->menus().begin(); it != entity->menus().end(); it++) {
+ msg.clear();
+ msg.str("");
+ msg << "menu " << entity->id() << " ";
+ Descriptions::serialize((*it), msg);
+ msg << '\n';
+ client->send_raw(msg.str());
+ // con_debug << "sending menu " << entity->label() << " " << (*it)->label() << std::endl;
+ }
}
}
diff --git a/src/core/parser.cc b/src/core/parser.cc
index 6af3903..1b35592 100644
--- a/src/core/parser.cc
+++ b/src/core/parser.cc
@@ -4,26 +4,12 @@
the terms of the GNU General Public License version 2
*/
-#include "core/parser.h"
#include "auxiliary/functions.h"
+#include "core/parser.h"
#include "sys/sys.h"
namespace core {
-bool Parser::read_entity_menu(core::Entity *entity, const std::string &menufilename)
-{
- filesystem::IniFile inifile;
- inifile.open(menufilename);
-
- if (!inifile.is_open()) {
- return false;
- }
-
- con_debug << " " << inifile.name() << std::endl;
-
- inifile.close();
- return true;
-}
bool Parser::got_entity_key(filesystem::IniFile &inifile, core::Entity *entity)
{
diff --git a/src/core/parser.h b/src/core/parser.h
index fec27c4..78a1087 100644
--- a/src/core/parser.h
+++ b/src/core/parser.h
@@ -18,9 +18,6 @@ class Parser {
public:
/// read default entity keys from an ini file
static bool got_entity_key(filesystem::IniFile &inifile, core::Entity *entity);
-
- /// read entity menus
- static bool read_entity_menu(core::Entity *entity, const std::string &menufilename);
};
}
diff --git a/src/core/player.cc b/src/core/player.cc
index ca985ab..f968fc3 100644
--- a/src/core/player.cc
+++ b/src/core/player.cc
@@ -133,7 +133,7 @@ void Player::serialize_client_update(std::ostream & os)
os << player_color << " "
<< player_color_second << " "
<< "\"" << player_name << "\" "
- << "\"" << player_rconpassword << "\"";
+ << "\"" << player_rconpassword << "\" ";
}
@@ -162,52 +162,53 @@ void Player::receive_client_update(std::istream &is)
void Player::serialize_server_update(std::ostream & os) const
{
- unsigned int zo = (zone() ? zone()->id() : 0);
- unsigned int co = (player_control ? player_control->id() : 0);
- unsigned int mission = (player_mission_target ? player_mission_target->id() : 0);
- unsigned int view = (player_view ? player_view->id() : 0);
+ unsigned int zone_id = (zone() ? zone()->id() : 0);
+ unsigned int view_id = (player_view ? player_view->id() : 0);
+ unsigned int control_id = (player_control ? player_control->id() : 0);
+ unsigned int mission_id = (player_mission_target ? player_mission_target->id() : 0);
- os << player_id << " " << zo << " " << view << " " << co << " " << mission << " " << player_color << " \"" << player_name << "\"";
+ os << player_id << " " << zone_id << " " << view_id << " " << control_id << " " << mission_id << " " << player_color << " ";
}
void Player::receive_server_update(std::istream &is)
{
is >> player_id;
- unsigned int zo = 0;
- is >> zo;
- set_zone(Zone::find(zo));
+ unsigned int zone_id = 0;
+ is >> zone_id;
+ set_zone(Zone::find(zone_id));
- unsigned int view = 0;
- is >> view;
- set_view(Entity::find(view));
+ unsigned int view_id = 0;
+ is >> view_id;
+ set_view(Entity::find(view_id));
- unsigned int co = 0;
- is >> co;
- if (co) {
- Entity *e = Entity::find(co);
+ unsigned int control_id = 0;
+ is >> control_id;
+ if (control_id) {
+ Entity *e = Entity::find(control_id);
if (e && e->type() == Entity::Controlable) {
player_control = static_cast<EntityControlable *>(e);
} else {
player_control = 0;
- con_warn << "control set to unknown entity " << co << "\n";
+ con_warn << "control set to unknown entity " << control_id << "\n";
}
} else {
player_control = 0;
}
- unsigned int mission = 0;
- is >> mission;
- if (mission) {
- player_mission_target = Entity::find(mission);
+ unsigned int mission_id = 0;
+ is >> mission_id;
+ if (mission_id) {
+ player_mission_target = Entity::find(mission_id);
if (!player_mission_target) {
- con_warn << "mission target set to unknown entity " << co << "\n";
+ con_warn << "mission target set to unknown entity " << mission_id << "\n";
}
} else {
player_mission_target = 0;
}
is >> player_color;
-
+
+ /*
std::string n;
char c;
while ( (is.get(c)) && (c != '"'));
@@ -216,6 +217,7 @@ void Player::receive_server_update(std::istream &is)
if (n.size())
player_name = n;
+ */
}
void Player::add_asset(EntityControlable *entity)
diff --git a/src/game/base/base.cc b/src/game/base/base.cc
index 7fa5299..ce5eb1c 100644
--- a/src/game/base/base.cc
+++ b/src/game/base/base.cc
@@ -11,6 +11,7 @@
#include "auxiliary/functions.h"
#include "core/gameserver.h"
#include "core/parser.h"
+#include "core/descriptions.h"
#include "filesystem/filesystem.h"
#include "filesystem/inifile.h"
#include "base/base.h"
@@ -54,11 +55,13 @@ void Base::func_join(core::Player *player, std::string const &args)
ship->set_zone(player->zone());
player->set_control(ship);
-/*
core::Entity *dock = ship->zone()->default_view();
- ship->entity_location.assign(dock->location() + (dock->axis().forward() * dock->radius()*2.0f));
- ship->entity_axis.assign(dock->axis());
-*/
+ if (dock) {
+ ship->entity_location.assign(dock->location() + (dock->axis().forward() * ((ship->radius()+ dock->radius())*2.0f)));
+ ship->entity_axis.assign(dock->axis());
+ ship->set_eventstate(core::Entity::Docked);
+ player->set_view(dock);
+ }
player->sound("game/buy-ship");
std::string message("^B");
@@ -118,15 +121,19 @@ void Base::func_buy(core::Player *player, std::string const &args)
player->remove_asset(player->control());
}
+ core::Entity *dock = player->view();
Ship * ship = new Ship(player, shipmodel);
ship->set_zone(player->zone());
- if (player->view()) {
- core::Entity *dock = player->view();
- ship->entity_location.assign(dock->location() + (dock->axis().forward() * dock->radius()*2.0f));
+ player->set_control(ship);
+
+ if (dock) {
+ player->control()->location().assign(dock->location());
+ player->control()->set_eventstate(core::Entity::Docked);
ship->entity_axis.assign(dock->axis());
+ ship->entity_axis.change_direction(180.0f);
+ player->set_view(dock);
}
- player->set_control(ship);
core::server()->broadcast("^B" + player->name() + " ^Bpurchased " + aux::article(shipmodel->name()));
player->sound("game/buy-ship");
@@ -200,7 +207,7 @@ void Base::func_dock(core::Player *player,core::Entity *entity)
if (player->control()->eventstate() == core::Entity::Docked)
return;
- if (math::distance(entity->location(), player->control()->location()) > 2.0f * entity->radius()) {
+ if (math::distance(entity->location(), player->control()->location()) > 2.0f * (entity->radius() + player->control()->radius())) {
player->send("^B" + entity->name() + " is out of range!");
return;
}
@@ -226,12 +233,43 @@ void Base::func_launch(core::Player *player, std::string const &args)
assert(player->view()->zone() == player->control()->zone());
core::Entity *dock = player->view();
- player->control()->entity_location.assign(dock->location() + (dock->axis().forward() * dock->radius()*2.0f));
+ player->control()->entity_location.assign(dock->location() + (dock->axis().forward() * (player->control()->radius()+ dock->radius())*2.0f));
player->control()->entity_axis.assign(dock->axis());
player->control()->set_eventstate(core::Entity::Normal);
player->set_view(0);
}
+// instantaniously goto a specified entity within the zone
+void Base::func_goto(core::Player *player, const std::string &args)
+{
+ if (!args.size())
+ return;
+
+ if (!g_devel->value())
+ return;
+
+ if (!player->control())
+ return;
+
+ std::string label(args);
+ aux::to_label(label);
+
+ core::Zone *zone = player->control()->zone();
+ for (core::Zone::Content::iterator it = zone->content().begin(); it != zone->content().end(); it ++) {
+ core::Entity *dock = (*it);
+ std::string str(dock->label());
+ aux::to_label(str);
+ if (str.find(label) != std::string::npos) {
+ player->control()->entity_location.assign(dock->location() + (dock->axis().forward() * (player->control()->radius()+dock->radius())*2.0f));
+ player->control()->entity_axis.assign(dock->axis());
+ player->control()->entity_axis.change_direction(180.0f);
+ player->control()->set_eventstate(core::Entity::Normal);
+ player->set_view(0);
+ return;
+ }
+ }
+}
+
/* -- class Base -------------------------------------------------- */
Base::Base() : core::Module("base", "Project::OSiRiON", true)
@@ -285,6 +323,9 @@ void Base::init()
func = core::Func::add("launch", Base::func_launch);
func->set_info("launch to space when docked");
+ func = core::Func::add("goto", Base::func_goto);
+ func->set_info("[string] goto to an entity within the zone");
+
func = core::Func::add("@dock", Base::func_dock);
func->set_info("dock with target object");
@@ -556,7 +597,7 @@ bool Base::load_zone(core::Zone *zone)
} else if (zoneini.got_key_bool("dock", b)) {
if (b) {
entity->set_flag(core::Entity::Dockable);
- //core::Parser::read_entity_menu(entity, "zones/" + zone->label() + "/" + entity->label());
+ core::Descriptions::load_entity_menus(entity, "zones/" + zone->label() + "/" + entity->label());
} else {
entity->unset_flag(core::Entity::Dockable);
}
diff --git a/src/game/base/base.h b/src/game/base/base.h
index 6979335..926060c 100644
--- a/src/game/base/base.h
+++ b/src/game/base/base.h
@@ -94,6 +94,7 @@ private:
static void func_impulse(core::Player *player, std::string const &args);
static void func_dock(core::Player *player,core::Entity *entity);
static void func_launch(core::Player *player, std::string const &args);
+ static void func_goto(core::Player *player, const std::string &args);
};
}
diff --git a/src/render/camera.cc b/src/render/camera.cc
index 04d899f..4544b75 100644
--- a/src/render/camera.cc
+++ b/src/render/camera.cc
@@ -32,6 +32,7 @@ math::Vector3f Camera::camera_eye;
math::Vector3f Camera::camera_target;
math::Axis Camera::camera_axis;
Camera::Mode Camera::camera_mode;
+Camera::Mode Camera::camera_previous_mode;
// current and target yaw angle in XZ plane, positive is looking left
float Camera::direction_current;
@@ -65,6 +66,8 @@ void Camera::init()
distance = 0.4f;
+ camera_mode = Overview;
+ camera_previous_mode = Track;
set_mode(Track);
camera_axis.clear();
@@ -100,6 +103,9 @@ void Camera::set_mode(Mode newmode) {
camera_axis.clear();
+ if (camera_mode != Overview)
+ camera_previous_mode = camera_mode;
+
switch(newmode) {
case Track:
// switch camera to Track mode
@@ -213,7 +219,7 @@ void Camera::frame(float seconds)
}
} else if (core::localcontrol()) {
if (camera_mode == Overview) {
- set_mode(Track);
+ set_mode(camera_previous_mode);
}
} else {
if (camera_mode != Overview) {
@@ -230,13 +236,14 @@ void Camera::frame(float seconds)
camera_axis.assign(core::localplayer()->view()->axis());
camera_axis.change_direction(180.0f);
distance = math::max(core::localplayer()->view()->radius(), 1.0f) * 2.0f;
-
+/*
} else if (core::localplayer()->zone()->default_view()) {
// default zone view entity
camera_target.assign(core::localplayer()->zone()->default_view()->location());
camera_axis.assign(core::localplayer()->zone()->default_view()->axis());
camera_axis.change_direction(180.0f);
distance = math::max(core::localplayer()->zone()->default_view()->radius(), 1.0f) * 2.0f;
+*/
} else {
// default location (0,0,0)
camera_target.clear();
diff --git a/src/render/camera.h b/src/render/camera.h
index b19521e..5394d1b 100644
--- a/src/render/camera.h
+++ b/src/render/camera.h
@@ -89,6 +89,7 @@ private:
static math::Vector3f camera_target;
static math::Axis camera_axis;
static Mode camera_mode;
+ static Mode camera_previous_mode;
static float camera_aspect;
static float camera_frustum_size;
static float camera_frustum_front;
diff --git a/src/ui/Makefile.am b/src/ui/Makefile.am
index b2126fd..e230203 100644
--- a/src/ui/Makefile.am
+++ b/src/ui/Makefile.am
@@ -7,10 +7,11 @@ else
noinst_LTLIBRARIES = libui.la
endif
-noinst_HEADERS = bitmap.h button.h console.h container.h definitions.h font.h inputbox.h label.h \
- menu.h paint.h palette.h scrollpane.h ui.h widget.h window.h
+noinst_HEADERS = bitmap.h button.h console.h container.h definitions.h font.h \
+ inputbox.h label.h menu.h menuview.h paint.h palette.h scrollpane.h ui.h \
+ widget.h window.h
libui_la_SOURCES = bitmap.cc button.cc console.cc console.h container.cc \
- font.cc inputbox.cc label.cc menu.cc paint.cc palette.cc scrollpane.cc ui.cc \
- widget.cc window.cc
+ font.cc inputbox.cc label.cc menu.cc menuview.cc paint.cc palette.cc \
+ scrollpane.cc ui.cc widget.cc window.cc
libui_la_LDFLAGS = -avoid-version -no-undefined
diff --git a/src/ui/container.cc b/src/ui/container.cc
index 977ff4d..915ec98 100644
--- a/src/ui/container.cc
+++ b/src/ui/container.cc
@@ -7,6 +7,7 @@
#include "ui/container.h"
#include "ui/paint.h"
+#include "ui/ui.h"
namespace ui
{
@@ -19,9 +20,6 @@ Container::Container(Widget *parent) : Window(parent)
set_border(true);
set_background(true);
-
- container_childsize.assign(256, 48);
- container_margin = 24;
}
Container::~Container()
@@ -30,31 +28,22 @@ Container::~Container()
void Container::resize()
{
- float w = container_childsize.width() * 1.5f;
- float h = children().size() * (container_childsize.height() + margin()) + container_childsize.height();
+ float w = UI::elementsize.width() * 1.5f;
+ float h = children().size() * (UI::elementsize.height() + UI::elementmargin) + UI::elementsize.height();
set_size(w, h);
- const float x = container_childsize.width() * 0.25f;
- float y = container_childsize.height() * 0.5f;
+ const float x = UI::elementsize.width() * 0.25f;
+ float y = UI::elementsize.height() * 0.5f;
// reposition all children within the container
for (Children::iterator it = children().begin(); it != children().end(); it++) {
Widget *w = (*it);
- w->set_size(container_childsize);
+ w->set_size(UI::elementsize);
w->set_location(x, y);
- y += container_childsize.height() + container_margin;
+ y += UI::elementsize.height() + UI::elementmargin;
}
}
-void Container::set_childsize(const float w, const float h)
-{
- container_childsize.assign(w, h);
-}
-
-void Container::set_margin(const float margin)
-{
- container_margin = margin;
-}
void Container::draw_border()
{
diff --git a/src/ui/container.h b/src/ui/container.h
index 5556759..2045772 100644
--- a/src/ui/container.h
+++ b/src/ui/container.h
@@ -19,21 +19,10 @@ public:
Container(Widget *parent);
~Container();
- void set_margin(const float);
- void set_childsize(const float width, const float height);
-
- inline const math::Vector2f & childsize() const { return container_childsize; }
-
- inline float margin() const { return container_margin; }
-
protected:
virtual void draw_border();
virtual void resize();
-
-private:
- float container_margin;
- math::Vector2f container_childsize;
};
}
diff --git a/src/ui/menu.cc b/src/ui/menu.cc
index 8421f7f..36599be 100644
--- a/src/ui/menu.cc
+++ b/src/ui/menu.cc
@@ -47,16 +47,11 @@ void Menu::load()
std::string strval;
Button *button = 0;
Label *label = 0;
- float w = menu_container->childsize().width();
- float h = menu_container->childsize().height();
- float m = menu_container->margin();
while (ini.getline()) {
if (ini.got_section()) {
-
- //con_debug << " " << ini.name() << " [" << ini.section() << "]" << std::endl;
-
if (ini.got_section("menu")) {
+ continue;
} else if (ini.got_section("button")) {
button = add_button();
@@ -67,31 +62,23 @@ void Menu::load()
} else if (ini.got_section()) {
ini.unknown_section();
}
-
- } else if (ini.got_key()) {
-
- //con_debug << " " << ini.name() << " " << ini.key() << "=" << ini.value() << std::endl;
-
+ } else if (ini.got_key()) {
if (ini.in_section("menu")) {
if (ini.got_key_string("background", strval)) {
menu_background->set_texture(strval);
- } else if (ini.got_key_float("elementwidth", w)) {
- menu_container->set_childsize(w,h);
- } else if (ini.got_key_float("elementheight", h)) {
- menu_container->set_childsize(w,h);
- } else if (ini.got_key_float("elementmargin", m)) {
- menu_container->set_margin(m);
} else {
ini.unkown_key();
}
} else if (ini.in_section("button")) {
if (ini.got_key_string("text", strval)) {
+ aux::strip_quotes(strval);
button->set_text(strval);
} else if (ini.got_key_string("command", strval)) {
for (size_t i =0; i <= strval.size(); i++) {
if (strval[i] == ',') strval[i] = ';';
}
+ aux::strip_quotes(strval);
button->set_command(strval);
} else if (ini.got_key_string("align", strval)) {
@@ -157,7 +144,7 @@ void Menu::resize()
{
set_size(parent()->size());
menu_background->set_size(size());
- menu_container->set_location(menu_container->childsize().width() * 0.25, (height() - menu_container->height()) / 2.0f);
+ menu_container->set_location(UI::elementsize.width() * 0.25, (height() - menu_container->height()) / 2.0f);
}
}
diff --git a/src/ui/menuview.cc b/src/ui/menuview.cc
new file mode 100644
index 0000000..71bdd1a
--- /dev/null
+++ b/src/ui/menuview.cc
@@ -0,0 +1,95 @@
+/*
+ ui/menuview.cc
+ This file is part of the Osirion project and is distributed under
+ the terms of the GNU General Public License version 2
+*/
+
+#include "ui/menuview.h"
+#include "ui/ui.h"
+
+namespace ui
+{
+
+MenuView::MenuView(Window *parent, const char * label) : Window(parent)
+{
+ set_border(false);
+ set_background(false);
+ set_label(label);
+
+ menu_container = new Container(this);
+ menu_label = new Label(this);
+
+ hide();
+}
+
+MenuView::~MenuView()
+{
+}
+
+void MenuView::resize()
+{
+ set_size(parent()->size());
+ menu_label->set_location(UI::elementsize.width() * 0.25, UI::elementsize.width() * 0.25);
+ menu_label->set_size(UI::elementsize.width() * 1.5f, UI::elementsize.height());
+
+ menu_container->set_location(UI::elementsize.width() * 0.25, (height() - menu_container->height()) / 2.0f);
+}
+
+void MenuView::generate(core::Entity *entity, const char *menulabel)
+{
+ if (!menulabel)
+ return;
+
+
+ con_debug << "generating menu " << entity->label() << " " << menulabel << std::endl;
+
+ remove_children();
+ menu_container = new Container(this);
+
+ menu_label = new Label(this, entity->name().c_str());
+ menu_label->set_background(true);
+ menu_label->set_alignment(AlignCenter);
+ menu_label->set_font(ui::root()->font_large());
+
+ core::MenuDescription *menudescr = 0;
+ for (core::Entity::Menus::iterator it = entity->menus().begin(); it != entity->menus().end(); it++) {
+ if ((*it)->label().compare(menulabel) == 0) {
+ menudescr = (*it);
+ }
+ }
+
+ if (!menudescr) {
+ menu_container->event_resize();
+ resize();
+ return;
+ }
+
+ if (menudescr->text().size()) {
+ Label *label = new Label(menu_container);
+ label->set_text(menudescr->text());
+ label->set_alignment(AlignCenter);
+ label->set_border(false);
+ label->set_font(ui::root()->font_large());
+ }
+
+ for (core::MenuDescription::Buttons::iterator it = menudescr->buttons().begin(); it != menudescr->buttons().end(); it++) {
+ core::ButtonDescription *buttondescr = (*it);
+ Button *button = new Button(menu_container, buttondescr->text().c_str(), buttondescr->command().c_str());
+ switch (buttondescr->alignment()) {
+ case core::ButtonDescription::Center:
+ button->set_alignment(AlignCenter);
+ break;
+ case core::ButtonDescription::Left:
+ button->set_alignment(AlignLeft | AlignVCenter);
+ break;
+ case core::ButtonDescription::Right:
+ button->set_alignment(AlignRight | AlignVCenter);
+ break;
+ }
+ }
+
+ menu_container->event_resize();
+ resize();
+}
+
+}
diff --git a/src/ui/menuview.h b/src/ui/menuview.h
new file mode 100644
index 0000000..041d71a
--- /dev/null
+++ b/src/ui/menuview.h
@@ -0,0 +1,42 @@
+/*
+ ui/menuview.h
+ This file is part of the Osirion project and is distributed under
+ the terms of the GNU General Public License version 2
+*/
+
+#ifndef __INCLUDED_UI_MENUVIEW_H__
+#define __INCLUDED_UI_MENUVIEW_H__
+
+#include "core/entity.h"
+#include "ui/bitmap.h"
+#include "ui/container.h"
+#include "ui/button.h"
+#include "ui/label.h"
+#include "ui/window.h"
+
+namespace ui
+{
+
+/// a menu container
+class MenuView : public Window
+{
+public:
+ /// create a new menu
+ MenuView(Window *parent, const char * label);
+ ~MenuView();
+
+ /// generate a menu from menu descriptions
+ void generate(core::Entity *entity, const char *menulabel);
+
+protected:
+ /// resize event
+ virtual void resize();
+
+private:
+ Container *menu_container;
+ Label *menu_label;
+};
+
+}
+
+#endif // __INCLUDED_UI_MENUVIEW_H__
diff --git a/src/ui/ui.cc b/src/ui/ui.cc
index 4774387..7d57ce0 100644
--- a/src/ui/ui.cc
+++ b/src/ui/ui.cc
@@ -16,6 +16,7 @@
#include "ui/button.h"
#include "ui/label.h"
#include "ui/menu.h"
+#include "ui/menuview.h"
#include "ui/paint.h"
#include "ui/ui.h"
#include "ui/widget.h"
@@ -27,6 +28,9 @@ namespace ui
bool UI::ui_debug = false;
+float UI::elementmargin = 16;
+math::Vector2f UI::elementsize(256, 48);
+
UI *global_ui = 0;
void func_list_ui(std::string const &args)
@@ -137,6 +141,12 @@ void func_menu(std::string const &args)
} else if (command.compare("list") == 0) {
root()->list_menus();
+ } else if (command.compare("view") == 0) {
+ std::string label;
+ if (!(argstr >> label)) {
+ label.assign("main");
+ }
+ root()->show_menuview(label);
} else {
root()->show_menu(command.c_str());
}
@@ -244,6 +254,8 @@ void UI::load()
}
ui_menus.clear();
+ add_menu(new MenuView(this, "view"));
+
ui_mouse_focus = this;
ui_active_menu = 0;
@@ -261,6 +273,11 @@ void UI::load()
std::string strval;
math::Color color;
Menu *menu = 0;
+
+ float w = elementsize.width();
+ float h = elementsize.height();
+ float m = elementmargin;
+
while (ini.getline()) {
@@ -291,6 +308,12 @@ void UI::load()
add_menu(menu);
menu->load();
continue;
+ } else if (ini.got_key_float("elementwidth", w)) {
+ elementsize.assign(w, h);
+ } else if (ini.got_key_float("elementheight", h)) {
+ elementsize.assign(w, h);
+ } else if (ini.got_key_float("elementmargin", m)) {
+ elementmargin = m;
} else {
ini.unkown_key();
}
@@ -402,6 +425,20 @@ void UI::add_menu(Window *menu)
}
+void UI::show_menuview(const std::string &label)
+{
+ if (!core::localplayer()->view())
+ return;
+
+ if (!core::localplayer()->view()->menus().size())
+ return;
+
+ MenuView *menuview = static_cast<MenuView *>(find_menu("view"));
+ menuview->generate(core::localplayer()->view(), label.c_str());
+
+ show_menu("view");
+}
+
void UI::show_menu(const char *label)
{
Window *menu = find_menu(label);
@@ -501,8 +538,15 @@ bool UI::on_keypress(const int key, const unsigned int modifier)
case SDLK_ESCAPE:
if (active()) {
- hide_menu();
- audio::play("ui/menu");
+ if (active()->label().compare("view") == 0) {
+ if (core::application()->connected()) {
+ show_menu("game");
+ audio::play("ui/menu");
+ }
+ } else {
+ hide_menu();
+ audio::play("ui/menu");
+ }
} else {
if (core::application()->connected()) {
show_menu("game");
diff --git a/src/ui/ui.h b/src/ui/ui.h
index f41df24..ae42ad6 100644
--- a/src/ui/ui.h
+++ b/src/ui/ui.h
@@ -37,6 +37,9 @@ public:
/// make a window the active window
void show_menu(const char *label);
+ /// make the entity view menu the active window
+ void show_menuview(const std::string &label);
+
/// hide the active window
void hide_menu();
@@ -89,6 +92,11 @@ public:
static bool ui_debug;
+
+
+ static float elementmargin;
+ static math::Vector2f elementsize;
+
protected:
typedef std::list<Window *> Menus;
diff --git a/src/ui/widget.cc b/src/ui/widget.cc
index 046cb01..1270997 100644
--- a/src/ui/widget.cc
+++ b/src/ui/widget.cc
@@ -35,6 +35,11 @@ Widget::Widget(Widget *parent)
Widget::~Widget()
{
+ remove_children();
+}
+
+void Widget::remove_children()
+{
for (Children::iterator it = widget_children.begin(); it != widget_children.end(); it++) {
delete(*it);
(*it) = 0;
diff --git a/src/ui/widget.h b/src/ui/widget.h
index 60670b6..c002c73 100644
--- a/src/ui/widget.h
+++ b/src/ui/widget.h
@@ -278,8 +278,14 @@ protected:
/// draw the widget border
virtual void draw_border();
+ /// add a child widget
virtual void add_child(Widget *child);
+
+ /// remove a child widget
virtual void remove_child(Widget *child);
+
+ /// remove all child widgets
+ virtual void remove_children();
private:
void draw_debug_border();