[Add] Uhm, apparently the new project stuff wasn't added. My bad.
46
Makefile.am
Normal file
@ -0,0 +1,46 @@
|
||||
## Process this file with automake to produce Makefile.in
|
||||
SUBDIRS = src/
|
||||
|
||||
EXTRA_DIST = icons/button_f10.png \
|
||||
icons/button_f7.png \
|
||||
icons/button_f8.png \
|
||||
icons/button_f9.png \
|
||||
icons/cam_external.png \
|
||||
icons/cam_front.png \
|
||||
icons/cam_rear.png \
|
||||
icons/cpanel.png \
|
||||
icons/cpan_f2_map.png \
|
||||
icons/cpan_f2_normal.png \
|
||||
icons/object_brown_dwarf.png \
|
||||
icons/object_planet_dwarf.png \
|
||||
icons/object_planet_large_gas_giant.png \
|
||||
icons/object_planet_medium_gas_giant.png \
|
||||
icons/object_planet_small_gas_giant.png \
|
||||
icons/object_planet_small.png \
|
||||
icons/object_planet_life.png \
|
||||
icons/object_star_a.png \
|
||||
icons/object_star_b.png \
|
||||
icons/object_star_f.png \
|
||||
icons/object_star_g.png \
|
||||
icons/object_star_k.png \
|
||||
icons/object_star_m.png \
|
||||
icons/object_star_o.png \
|
||||
icons/sectorview_f6_systeminfo.png \
|
||||
icons/timeaccel0_on.png \
|
||||
icons/timeaccel0.png \
|
||||
icons/timeaccel1_on.png \
|
||||
icons/timeaccel1.png \
|
||||
icons/timeaccel2_on.png \
|
||||
icons/timeaccel2.png \
|
||||
icons/timeaccel3_on.png \
|
||||
icons/timeaccel3.png \
|
||||
icons/timeaccel4_on.png \
|
||||
icons/timeaccel4.png \
|
||||
icons/zoom_in_f7.png \
|
||||
icons/zoom_out_f8.png \
|
||||
icons/hyperspace_f8.png \
|
||||
icons/comms_f4.png \
|
||||
icons/sysview_accel_f1_on.png icons/sysview_accel_f1.png icons/sysview_accel_f2_on.png icons/sysview_accel_f2.png icons/sysview_accel_f3_on.png icons/sysview_accel_f3.png icons/sysview_accel_r1_on.png icons/sysview_accel_r1.png icons/sysview_accel_r2_on.png icons/sysview_accel_r2.png icons/sysview_accel_r3_on.png icons/sysview_accel_r3.png \
|
||||
config.ini
|
||||
|
||||
|
6
config.ini
Normal file
@ -0,0 +1,6 @@
|
||||
ScrWidth=800
|
||||
ScrHeight=600
|
||||
# 16 or 32.
|
||||
ScrDepth=16
|
||||
StartFullscreen=0
|
||||
|
36
configure.ac
Normal file
@ -0,0 +1,36 @@
|
||||
# Process this file with autoconf to create configure.
|
||||
|
||||
AC_PREREQ(2.59)
|
||||
|
||||
AC_INIT([Lephisto3D], [0.0.1], [allanis.saracraft.studios@gmail.com])
|
||||
#AC_CONFIG_HEADERS([config.h])
|
||||
|
||||
AM_INIT_AUTOMAKE([1.9 foreign])
|
||||
|
||||
AC_PROG_CC
|
||||
AC_PROG_CXX
|
||||
AC_C_CONST
|
||||
AC_PROG_RANLIB
|
||||
#AC_PROG_LIBTOOL
|
||||
|
||||
#AM_PATH_LIB3DS([1.2.0])
|
||||
#CFLAGS="$CFLAGS $LIB3DS_CFLAGS"
|
||||
#LIBS="$LIBS $LIB3DS_LIBS"
|
||||
|
||||
CFLAGS="-g -O2 -Wall"
|
||||
|
||||
CFLAGS="$CFLAGS `pkg-config --cflags sigc++-2.0`"
|
||||
LIBS="$LIBS `pkg-config --libs sigc++-2.0` -lGL -lGLU"
|
||||
CFLAGS="$CFLAGS `pkg-config --cflags freetype2`"
|
||||
LIBS="$LIBS `pkg-config --libs freetype2`"
|
||||
CFLAGS="$CFLAGS `ode-config --cflags`"
|
||||
LIBS="$LIBS `ode-config --libs`"
|
||||
|
||||
PKG_CHECK_MODULES(SDL, sdl)
|
||||
CFLAGS="$CFLAGS $SDL_CFLAGS"
|
||||
LIBS="$LIBS $SDL_LIBS -lSDL_image"
|
||||
|
||||
CXXFLAGS="$CFLAGS"
|
||||
|
||||
AC_CONFIG_FILES([Makefile src/Makefile src/sbre/Makefile])
|
||||
AC_OUTPUT
|
BIN
icons/button_f10.png
Normal file
After Width: | Height: | Size: 209 B |
BIN
icons/button_f7.png
Normal file
After Width: | Height: | Size: 199 B |
BIN
icons/button_f8.png
Normal file
After Width: | Height: | Size: 220 B |
BIN
icons/button_f9.png
Normal file
After Width: | Height: | Size: 210 B |
BIN
icons/cam_external.png
Normal file
After Width: | Height: | Size: 299 B |
BIN
icons/cam_front.png
Normal file
After Width: | Height: | Size: 280 B |
BIN
icons/cam_rear.png
Normal file
After Width: | Height: | Size: 275 B |
BIN
icons/comms_f4.png
Normal file
After Width: | Height: | Size: 294 B |
BIN
icons/cpan_f2_map.png
Normal file
After Width: | Height: | Size: 308 B |
BIN
icons/cpan_f2_normal.png
Normal file
After Width: | Height: | Size: 450 B |
BIN
icons/cpanel.png
Normal file
After Width: | Height: | Size: 2.3 KiB |
BIN
icons/hyperspace_f8.png
Normal file
After Width: | Height: | Size: 371 B |
BIN
icons/object_brown_dwarf.png
Normal file
After Width: | Height: | Size: 399 B |
BIN
icons/object_planet_dwarf.png
Normal file
After Width: | Height: | Size: 275 B |
BIN
icons/object_planet_large_gas_giant.png
Normal file
After Width: | Height: | Size: 2.0 KiB |
BIN
icons/object_planet_life.png
Normal file
After Width: | Height: | Size: 779 B |
BIN
icons/object_planet_medium_gas_giant.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
icons/object_planet_small.png
Normal file
After Width: | Height: | Size: 323 B |
BIN
icons/object_planet_small_gas_giant.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
icons/object_star_a.png
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
icons/object_star_b.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
icons/object_star_f.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
icons/object_star_g.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
icons/object_star_k.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
icons/object_star_m.png
Normal file
After Width: | Height: | Size: 798 B |
BIN
icons/object_star_o.png
Normal file
After Width: | Height: | Size: 602 B |
BIN
icons/sectorview_f6_systeminfo.png
Normal file
After Width: | Height: | Size: 490 B |
BIN
icons/sysview_accel_f1.png
Normal file
After Width: | Height: | Size: 254 B |
BIN
icons/sysview_accel_f1_on.png
Normal file
After Width: | Height: | Size: 231 B |
BIN
icons/sysview_accel_f2.png
Normal file
After Width: | Height: | Size: 268 B |
BIN
icons/sysview_accel_f2_on.png
Normal file
After Width: | Height: | Size: 247 B |
BIN
icons/sysview_accel_f3.png
Normal file
After Width: | Height: | Size: 280 B |
BIN
icons/sysview_accel_f3_on.png
Normal file
After Width: | Height: | Size: 241 B |
BIN
icons/sysview_accel_r1.png
Normal file
After Width: | Height: | Size: 259 B |
BIN
icons/sysview_accel_r1_on.png
Normal file
After Width: | Height: | Size: 231 B |
BIN
icons/sysview_accel_r2.png
Normal file
After Width: | Height: | Size: 271 B |
BIN
icons/sysview_accel_r2_on.png
Normal file
After Width: | Height: | Size: 246 B |
BIN
icons/sysview_accel_r3.png
Normal file
After Width: | Height: | Size: 429 B |
BIN
icons/sysview_accel_r3_on.png
Normal file
After Width: | Height: | Size: 396 B |
BIN
icons/timeaccel0.png
Normal file
After Width: | Height: | Size: 237 B |
BIN
icons/timeaccel0_on.png
Normal file
After Width: | Height: | Size: 213 B |
BIN
icons/timeaccel1.png
Normal file
After Width: | Height: | Size: 261 B |
BIN
icons/timeaccel1_on.png
Normal file
After Width: | Height: | Size: 228 B |
BIN
icons/timeaccel2.png
Normal file
After Width: | Height: | Size: 296 B |
BIN
icons/timeaccel2_on.png
Normal file
After Width: | Height: | Size: 241 B |
BIN
icons/timeaccel3.png
Normal file
After Width: | Height: | Size: 308 B |
BIN
icons/timeaccel3_on.png
Normal file
After Width: | Height: | Size: 238 B |
BIN
icons/timeaccel4.png
Normal file
After Width: | Height: | Size: 518 B |
BIN
icons/timeaccel4_on.png
Normal file
After Width: | Height: | Size: 353 B |
BIN
icons/zoom_in_f7.png
Normal file
After Width: | Height: | Size: 426 B |
BIN
icons/zoom_out_f8.png
Normal file
After Width: | Height: | Size: 419 B |
19
src/Makefile.am
Normal file
@ -0,0 +1,19 @@
|
||||
## Process this file with automake to produce Makefile.in
|
||||
SUBDIRS = sbre/
|
||||
|
||||
bin_PROGRAMS = Lephisto3D
|
||||
Lephisto3D_SOURCES = main.cpp gui_button.cpp gui.cpp gui_fixed.cpp gui_screen.cpp gui_label.cpp glfreetype.cpp \
|
||||
objimport.cpp body.cpp space.cpp ship.cpp player.cpp gui_toggle_button.cpp gui_radio_button.cpp \
|
||||
gui_radio_group.cpp rigid_body.cpp planet.cpp star.cpp frame.cpp gui_image_button.cpp gui_image.cpp \
|
||||
gui_image_radio_button.cpp gui_multi_state_image_button.cpp ship_cpanel.cpp gui_widget.cpp sector_view.cpp \
|
||||
mtrand.cpp world_view.cpp system_view.cpp star_system.cpp sector.cpp system_info_view.cpp generic_system_view.cpp \
|
||||
gui_container.cpp date.cpp space_station.cpp space_station_view.cpp static_rigid_body.cpp ship_type.cpp
|
||||
Lephisto3D_LDADD = sbre/libsbre.a
|
||||
|
||||
include_HEADERS = body.h frame.h generic_system_view.h glfreetype.h gui_button.h gui_container.h gui_events.h gui_fixed.h \
|
||||
gui.h gui_image_button.h gui_image.h gui_image_radio_button.h gui_label.h gui_multi_state_image_button.h gui_radio_button.h \
|
||||
gui_radio_group.h gui_screen.h gui_toggle_button.h gui_widget.h libs.h matrix4x4.h mtrand.h objimport.h l3d.h \
|
||||
planet.h player.h rigid_body.h sector.h sector_view.h ship_cpanel.h ship.h space.h star.h star_system.h system_info_view.h \
|
||||
system_view.h vector3.h view.h world_view.h date.h space_station.h space_station_view.h static_rigid_body.h gui_iselectable.h \
|
||||
ship_type.h object.h
|
||||
|
14
src/body.cpp
Normal file
@ -0,0 +1,14 @@
|
||||
#include "libs.h"
|
||||
#include "body.h"
|
||||
#include "frame.h"
|
||||
|
||||
Body::Body(void) {
|
||||
m_frame = 0;
|
||||
m_flags = 0;
|
||||
}
|
||||
|
||||
/* f == NULL, then absolute position within system. */
|
||||
vector3d Body::GetPositionRelTo(const Frame* relTo) {
|
||||
return m_frame->GetPosRelativeToOtherFrame(relTo) + GetPosition();
|
||||
}
|
||||
|
40
src/body.h
Normal file
@ -0,0 +1,40 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
|
||||
#include "vector3.h"
|
||||
#include "matrix4x4.h"
|
||||
#include "object.h"
|
||||
|
||||
class Frame;
|
||||
class ObjMesh;
|
||||
|
||||
class Body: public Object {
|
||||
public:
|
||||
Body(void);
|
||||
virtual ~Body(void) { };
|
||||
virtual Object::Type GetType(void) { return Object::BODY; }
|
||||
virtual void SetPosition(vector3d p) = 0;
|
||||
virtual vector3d GetPosition(void) = 0; /* Within frame. */
|
||||
vector3d GetPositionRelTo(const Frame*);
|
||||
virtual void Render(const Frame* camFrame) = 0;
|
||||
virtual void TransformToModelCoords(const Frame* camFrame) = 0;
|
||||
virtual void TransformCameraTo(void) = 0;
|
||||
virtual void SetFrame(Frame* f) { m_frame = f; }
|
||||
Frame* GetFrame(void) { return m_frame; }
|
||||
void SetLabel(const char* label) { m_label = label; }
|
||||
std::string& GetLabel(void) { return m_label; }
|
||||
unsigned int GetFlags(void) { return m_flags; }
|
||||
/* Return true if we should apply damage. */
|
||||
virtual bool OnCollision(Body* b) { return false; }
|
||||
|
||||
enum { FLAG_CAN_MOVE_FRAME = 1 };
|
||||
|
||||
protected:
|
||||
unsigned int m_flags;
|
||||
|
||||
private:
|
||||
/* Frame of reference. */
|
||||
Frame* m_frame;
|
||||
std::string m_label;
|
||||
};
|
||||
|
77
src/date.cpp
Normal file
@ -0,0 +1,77 @@
|
||||
#include "date.h"
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include "libs.h"
|
||||
|
||||
/* Urgh... */
|
||||
static const char *i_am_a_little_teapot[365] =
|
||||
{ "Jan 1","Jan 2","Jan 3","Jan 4","Jan 5","Jan 6","Jan 7",
|
||||
"Jan 8","Jan 9","Jan 10","Jan 11","Jan 12","Jan 13","Jan 14",
|
||||
"Jan 15","Jan 16","Jan 17","Jan 18","Jan 19","Jan 20","Jan 21",
|
||||
"Jan 22","Jan 23","Jan 24","Jan 25","Jan 26","Jan 27","Jan 28",
|
||||
"Jan 29","Jan 30","Jan 31","Feb 1","Feb 2","Feb 3","Feb 4",
|
||||
"Feb 5","Feb 6","Feb 7","Feb 8","Feb 9","Feb 10","Feb 11","Feb 12",
|
||||
"Feb 13","Feb 14","Feb 15","Feb 16","Feb 17","Feb 18","Feb 19",
|
||||
"Feb 20","Feb 21","Feb 22","Feb 23","Feb 24","Feb 25","Feb 26",
|
||||
"Feb 27","Feb 28","Mar 1","Mar 2","Mar 3","Mar 4","Mar 5","Mar 6",
|
||||
"Mar 7","Mar 8","Mar 9","Mar 10","Mar 11","Mar 12","Mar 13",
|
||||
"Mar 14","Mar 15","Mar 16","Mar 17","Mar 18","Mar 19","Mar 20",
|
||||
"Mar 21","Mar 22","Mar 23","Mar 24","Mar 25","Mar 26","Mar 27",
|
||||
"Mar 28","Mar 29","Mar 30","Mar 31","Apr 1","Apr 2","Apr 3",
|
||||
"Apr 4","Apr 5","Apr 6","Apr 7","Apr 8","Apr 9","Apr 10","Apr 11",
|
||||
"Apr 12","Apr 13","Apr 14","Apr 15","Apr 16","Apr 17","Apr 18",
|
||||
"Apr 19","Apr 20","Apr 21","Apr 22","Apr 23","Apr 24","Apr 25",
|
||||
"Apr 26","Apr 27","Apr 28","Apr 29","Apr 30","May 1","May 2",
|
||||
"May 3","May 4","May 5","May 6","May 7","May 8","May 9","May 10",
|
||||
"May 11","May 12","May 13","May 14","May 15","May 16","May 17",
|
||||
"May 18","May 19","May 20","May 21","May 22","May 23","May 24",
|
||||
"May 25","May 26","May 27","May 28","May 29","May 30","May 31",
|
||||
"Jun 1","Jun 2","Jun 3","Jun 4","Jun 5","Jun 6","Jun 7","Jun 8",
|
||||
"Jun 9","Jun 10","Jun 11","Jun 12","Jun 13","Jun 14","Jun 15",
|
||||
"Jun 16","Jun 17","Jun 18","Jun 19","Jun 20","Jun 21","Jun 22",
|
||||
"Jun 23","Jun 24","Jun 25","Jun 26","Jun 27","Jun 28","Jun 29",
|
||||
"Jun 30","Jul 1","Jul 2","Jul 3","Jul 4","Jul 5","Jul 6","Jul 7",
|
||||
"Jul 8","Jul 9","Jul 10","Jul 11","Jul 12","Jul 13","Jul 14",
|
||||
"Jul 15","Jul 16","Jul 17","Jul 18","Jul 19","Jul 20","Jul 21",
|
||||
"Jul 22","Jul 23","Jul 24","Jul 25","Jul 26","Jul 27","Jul 28",
|
||||
"Jul 29","Jul 30","Jul 31","Aug 1","Aug 2","Aug 3","Aug 4","Aug 5",
|
||||
"Aug 6","Aug 7","Aug 8","Aug 9","Aug 10","Aug 11","Aug 12",
|
||||
"Aug 13","Aug 14","Aug 15","Aug 16","Aug 17","Aug 18","Aug 19",
|
||||
"Aug 20","Aug 21","Aug 22","Aug 23","Aug 24","Aug 25","Aug 26",
|
||||
"Aug 27","Aug 28","Aug 29","Aug 30","Aug 31","Sep 1","Sep 2",
|
||||
"Sep 3","Sep 4","Sep 5","Sep 6","Sep 7","Sep 8","Sep 9","Sep 10",
|
||||
"Sep 11","Sep 12","Sep 13","Sep 14","Sep 15","Sep 16","Sep 17",
|
||||
"Sep 18","Sep 19","Sep 20","Sep 21","Sep 22","Sep 23","Sep 24",
|
||||
"Sep 25","Sep 26","Sep 27","Sep 28","Sep 29","Sep 30","Oct 1",
|
||||
"Oct 2","Oct 3","Oct 4","Oct 5","Oct 6","Oct 7","Oct 8","Oct 9",
|
||||
"Oct 10","Oct 11","Oct 12","Oct 13","Oct 14","Oct 15","Oct 16",
|
||||
"Oct 17","Oct 18","Oct 19","Oct 20","Oct 21","Oct 22","Oct 23",
|
||||
"Oct 24","Oct 25","Oct 26","Oct 27","Oct 28","Oct 29","Oct 30",
|
||||
"Oct 31","Nov 1","Nov 2","Nov 3","Nov 4","Nov 5","Nov 6","Nov 7",
|
||||
"Nov 8","Nov 9","Nov 10","Nov 11","Nov 12","Nov 13","Nov 14",
|
||||
"Nov 15","Nov 16","Nov 17","Nov 18","Nov 19","Nov 20","Nov 21",
|
||||
"Nov 22","Nov 23","Nov 24","Nov 25","Nov 26","Nov 27","Nov 28",
|
||||
"Nov 29","Nov 30","Dec 1","Dec 2","Dec 3","Dec 4","Dec 5","Dec 6",
|
||||
"Dec 7","Dec 8","Dec 9","Dec 10","Dec 11","Dec 12","Dec 13",
|
||||
"Dec 14","Dec 15","Dec 16","Dec 17","Dec 18","Dec 19","Dec 20",
|
||||
"Dec 21","Dec 22","Dec 23","Dec 24","Dec 25","Dec 26","Dec 27",
|
||||
"Dec 28","Dec 29","Dec 30","Dec 31"
|
||||
};
|
||||
|
||||
int mod(int a, int b) {
|
||||
int r = a%b;
|
||||
return r >= 0 ? r : r*b;
|
||||
}
|
||||
|
||||
std::string date_format(double t) {
|
||||
int year = floor(t/(60*60*24*365)); year += 3200;
|
||||
int day = floor(t/(60*60*24)); day = mod(day, 365);
|
||||
int hour = floor(t/(60*60)); hour = mod(hour, 24);
|
||||
int min = floor(t/60); min = mod(min, 60);
|
||||
int sec = mod(t, 60);
|
||||
char buf[128];
|
||||
snprintf(buf, sizeof(buf), "%02d:%02d:%02d %s %d", hour, min, sec,
|
||||
i_am_a_little_teapot[day], year);
|
||||
return buf;
|
||||
}
|
||||
|
5
src/date.h
Normal file
@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
|
||||
std::string date_format(double time);
|
||||
|
55
src/frame.cpp
Normal file
@ -0,0 +1,55 @@
|
||||
#include "frame.h"
|
||||
#include "space.h"
|
||||
|
||||
Frame::Frame(void) {
|
||||
Init(NULL, "", 0);
|
||||
}
|
||||
|
||||
Frame::Frame(Frame* parent, const char* label) {
|
||||
Init(parent, label, 0);
|
||||
}
|
||||
|
||||
Frame::Frame(Frame* parent, const char* label, unsigned int flags) {
|
||||
Init(parent, label, flags);
|
||||
}
|
||||
|
||||
void Frame::RemoveChild(Frame* f) {
|
||||
m_children.remove(f);
|
||||
}
|
||||
|
||||
void Frame::Init(Frame* parent, const char* label, unsigned int flags) {
|
||||
m_parent = parent;
|
||||
m_flags = flags;
|
||||
m_radius = 0;
|
||||
m_dSpaceID = dHashSpaceCreate(0);
|
||||
if(m_parent) {
|
||||
m_parent->m_children.push_back(this);
|
||||
}
|
||||
if(label) m_label = label;
|
||||
}
|
||||
|
||||
Frame::~Frame(void) {
|
||||
dSpaceDestroy(m_dSpaceID);
|
||||
for(std::list<Frame*>::iterator i = m_children.begin(); i != m_children.end(); ++i) delete *i;
|
||||
}
|
||||
|
||||
vector3d Frame::GetFramePosRelativeToOther(const Frame* frame, const Frame* relTo) {
|
||||
vector3d pos = vector3d(0,0,0);
|
||||
|
||||
const Frame* f = frame;
|
||||
const Frame* root = Space::GetRootFrame();
|
||||
|
||||
while((f!=root) && (relTo !=f)) {
|
||||
pos += f->m_pos;
|
||||
f = f->m_parent;
|
||||
}
|
||||
|
||||
/* Now pos is relative to root, or to desired frame. */
|
||||
while(relTo != f) {
|
||||
pos -= relTo->m_pos;
|
||||
relTo = relTo->m_parent;
|
||||
}
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
47
src/frame.h
Normal file
@ -0,0 +1,47 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <list>
|
||||
#include "libs.h"
|
||||
|
||||
/* Frame of reference. */
|
||||
class Frame {
|
||||
public:
|
||||
Frame(void);
|
||||
Frame(Frame* parent, const char* label);
|
||||
Frame(Frame* parent, const char* label, unsigned int flags);
|
||||
~Frame(void);
|
||||
|
||||
const char* GetLabel(void) { return m_label.c_str(); }
|
||||
void SetLabel(const char* label) { m_label = label; }
|
||||
void SetPosition(const vector3d &pos) { m_pos = pos; }
|
||||
void SetRadius(double radius) { m_radius = radius; }
|
||||
void RemoveChild(Frame* f);
|
||||
void AddGeom(dGeomID g) { dSpaceAdd(m_dSpaceID, g); }
|
||||
void RemoveGeom(dGeomID g) { dSpaceRemove(m_dSpaceID, g); }
|
||||
dSpaceID GetSpaceID(void) { return m_dSpaceID; }
|
||||
|
||||
static vector3d GetFramePosRelativeToOther(const Frame* frame, const Frame* relTo);
|
||||
|
||||
vector3d GetPosRelativeToOtherFrame(const Frame* relTo) const {
|
||||
return GetFramePosRelativeToOther(this, relTo);
|
||||
}
|
||||
|
||||
bool IsLocalPosInFrame(const vector3d& pos) {
|
||||
return (pos.Length() < m_radius);
|
||||
}
|
||||
|
||||
/* If parent is null then frame position is absolute. */
|
||||
Frame* m_parent;
|
||||
std::list<Frame*> m_children;
|
||||
|
||||
enum { TEMP_VIEWING=1 };
|
||||
|
||||
private:
|
||||
void Init(Frame* parent, const char* label, unsigned int flags);
|
||||
vector3d m_pos;
|
||||
std::string m_label;
|
||||
double m_radius;
|
||||
int m_flags;
|
||||
dSpaceID m_dSpaceID;
|
||||
};
|
||||
|
51
src/generic_system_view.cpp
Normal file
@ -0,0 +1,51 @@
|
||||
#include "l3d.h"
|
||||
#include "generic_system_view.h"
|
||||
#include "sector_view.h"
|
||||
|
||||
GenericSystemView::GenericSystemView(void) : View() {
|
||||
px = py = pidx = 0xdeadbeef;
|
||||
m_scannerLayout = new Gui::Fixed(140, 2, 360, 60);
|
||||
m_scannerLayout->SetTransparency(true);
|
||||
|
||||
m_systemName = new Gui::Label("");
|
||||
m_systemName->SetColor(1, 1, 0);
|
||||
m_scannerLayout->Add(m_systemName, 40, 44);
|
||||
|
||||
m_distance = new Gui::Label("");
|
||||
m_distance->SetColor(1, 0, 0);
|
||||
m_scannerLayout->Add(m_distance, 150, 44);
|
||||
|
||||
m_starType = new Gui::Label("");
|
||||
m_starType->SetColor(1, 0, 1);
|
||||
m_scannerLayout->Add(m_starType, 22, 26);
|
||||
|
||||
m_shortDesc = new Gui::Label("");
|
||||
m_shortDesc->SetColor(1, 0, 1);
|
||||
m_scannerLayout->Add(m_shortDesc, 5, 8);
|
||||
}
|
||||
|
||||
void GenericSystemView::Draw3D(void) {
|
||||
StarSystem* s = L3D::GetSelectedSystem();
|
||||
|
||||
if(s && !s->IsSystem(px, py, pidx)) {
|
||||
s->GetPos(&px, &py, &pidx);
|
||||
|
||||
m_systemName->SetText(s->rootBody->name);
|
||||
m_distance->SetText("Dist. XX.XX light years.");
|
||||
m_starType->SetText(s->rootBody->GetAstroDescription());
|
||||
m_shortDesc->SetText("Short description of system");
|
||||
|
||||
onSelectedSystemChanged.emit(s);
|
||||
}
|
||||
}
|
||||
|
||||
void GenericSystemView::ShowAll(void) {
|
||||
View::ShowAll();
|
||||
if(m_scannerLayout) m_scannerLayout->ShowAll();
|
||||
}
|
||||
|
||||
void GenericSystemView::HideAll(void) {
|
||||
View::HideAll();
|
||||
if(m_scannerLayout) m_scannerLayout->HideAll();
|
||||
}
|
||||
|
25
src/generic_system_view.h
Normal file
@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
#include "libs.h"
|
||||
#include "gui.h"
|
||||
#include "view.h"
|
||||
#include "star_system.h"
|
||||
|
||||
class SystemInfoScannerText;
|
||||
|
||||
class GenericSystemView: public View {
|
||||
public:
|
||||
GenericSystemView(void);
|
||||
virtual void Draw3D(void);
|
||||
virtual void ShowAll(void);
|
||||
virtual void HideAll(void);
|
||||
sigc::signal<void,StarSystem*> onSelectedSystemChanged;
|
||||
|
||||
private:
|
||||
Gui::Fixed* m_scannerLayout;
|
||||
Gui::Label* m_systemName;
|
||||
Gui::Label* m_distance;
|
||||
Gui::Label* m_starType;
|
||||
Gui::Label* m_shortDesc;
|
||||
int px, py, pidx;
|
||||
};
|
||||
|
374
src/glfreetype.cpp
Normal file
@ -0,0 +1,374 @@
|
||||
#include <SDL_opengl.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <map>
|
||||
#include <ft2build.h>
|
||||
#include "glfreetype.h"
|
||||
|
||||
#include FT_FREETYPE_H
|
||||
#include FT_GLYPH_H
|
||||
#include FT_OUTLINE_H
|
||||
|
||||
#ifdef _WIN32
|
||||
typedef GLvoid(APIENTRY* _GLUfuncptr)(void);
|
||||
#endif
|
||||
|
||||
FT_Library library;
|
||||
|
||||
#include <vector>
|
||||
|
||||
static GLUtesselator* tobj;
|
||||
|
||||
static inline double fac(int n) {
|
||||
double r = 1.0;
|
||||
|
||||
for(int i = 2; i < n; i++) {
|
||||
r *= (double)i;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline double binomial_coeff(int n, int m) {
|
||||
return fac(n)/(fac(m)*(fac(n-m)));
|
||||
}
|
||||
|
||||
static void eval_bezier(GLdouble* out, double t, int n_points, double* points) {
|
||||
std::vector<double> c(n_points);
|
||||
|
||||
for(int i = 0; i < n_points; i++) {
|
||||
c[i] = pow(1.0f-t, n_points-(i+1)) * pow(t, i) *
|
||||
binomial_coeff(n_points-1, i);
|
||||
}
|
||||
|
||||
out[0] = out[1] = out[2] = 0;
|
||||
|
||||
for(int i = 0; i < n_points; i++) {
|
||||
out[0] += points[3*i] * c[i];
|
||||
out[1] += points[3*i+1] * c[i];
|
||||
out[2] += points[3*i+2] * c[i];
|
||||
}
|
||||
}
|
||||
|
||||
#define DIV 2048.0f
|
||||
|
||||
bool GenContourPoints(int a_char, FT_Outline* a_outline, const int a_contour,
|
||||
int a_bezierIters, std::vector<double>* ao_points) {
|
||||
#define push_point(__p) { \
|
||||
ao_points->push_back((__p)[0]); \
|
||||
ao_points->push_back((__p)[1]); \
|
||||
ao_points->push_back((__p)[2]); \
|
||||
}
|
||||
|
||||
int cont = (a_contour-1 < 0 ? 0 : 1 + a_outline->contours[a_contour-1]);
|
||||
|
||||
double point_buf[256][3];
|
||||
char point_type[256];
|
||||
int pos = 0;
|
||||
|
||||
for(; cont <= a_outline->contours[a_contour]; cont++, pos++) {
|
||||
point_type[pos] = a_outline->tags[cont];
|
||||
point_buf[pos][0] = a_outline->points[cont].x/DIV;
|
||||
point_buf[pos][1] = a_outline->points[cont].y/DIV;
|
||||
point_buf[pos][2] = 0;
|
||||
}
|
||||
if(!point_type[pos-1]) {
|
||||
/*
|
||||
* Need to duplicate first vertex if last
|
||||
* section is a bezier.
|
||||
*/
|
||||
point_type[pos] = 1;
|
||||
point_buf[pos][0] = point_buf[0][0];
|
||||
point_buf[pos][1] = point_buf[0][1];
|
||||
point_buf[pos][2] = 0;
|
||||
pos++;
|
||||
}
|
||||
|
||||
int start = -1;
|
||||
for(int k = 0; k < pos; k++) {
|
||||
if(!(point_type[k] & 1)) continue;
|
||||
|
||||
if(start == -1) { start = k; continue; }
|
||||
|
||||
int len = 1+k-start;
|
||||
/* Trace segment. */
|
||||
if(len == 2) {
|
||||
/* Staight line. */
|
||||
push_point(point_buf[k-1]);
|
||||
push_point(point_buf[k]);
|
||||
} else {
|
||||
/* Bezier. */
|
||||
double b_in[3][3];
|
||||
double v[3];
|
||||
|
||||
/*
|
||||
* Truetype is all quadratic bezier,
|
||||
* using average points between
|
||||
* 'control points' as end points.
|
||||
*/
|
||||
|
||||
/* First bezier. */
|
||||
b_in[0][0] = point_buf[start][0];
|
||||
b_in[0][1] = point_buf[start][1];
|
||||
b_in[0][2] = 0;
|
||||
|
||||
b_in[1][0] = point_buf[start+1][0];
|
||||
b_in[1][1] = point_buf[start+1][1];
|
||||
b_in[1][2] = 0;
|
||||
|
||||
if(len > 3) {
|
||||
b_in[2][0] = 0.5 * (point_buf[start+1][0] + point_buf[start+2][0]);
|
||||
b_in[2][1] = 0.5 * (point_buf[start+1][1] + point_buf[start+2][1]);
|
||||
b_in[2][2] = 0;
|
||||
} else {
|
||||
b_in[2][0] = point_buf[start+2][0];
|
||||
b_in[2][1] = point_buf[start+2][1];
|
||||
b_in[2][2] = 0;
|
||||
}
|
||||
|
||||
for(int l = 0; l <= a_bezierIters; l++) {
|
||||
double t = (1.0/a_bezierIters)*l;
|
||||
eval_bezier(v, t, 3, &b_in[0][0]);
|
||||
v[2] = 0.0;
|
||||
push_point(v);
|
||||
}
|
||||
|
||||
/* Middle beziers. */
|
||||
if(len > 4) {
|
||||
for(int _p = 1; _p < len-3; _p++) {
|
||||
b_in[0][0] = 0.5*(point_buf[start+_p][0]+point_buf[start+_p+1][0]);
|
||||
b_in[0][1] = 0.5*(point_buf[start+_p][1]+point_buf[start+_p+1][1]);
|
||||
|
||||
b_in[0][2] = 0;
|
||||
|
||||
b_in[1][0] = point_buf[start+_p+1][0];
|
||||
b_in[1][1] = point_buf[start+_p+1][1];
|
||||
b_in[1][2] = 0;
|
||||
|
||||
b_in[2][0] = 0.5*(point_buf[start+_p+1][0] + point_buf[start+_p+2][0]);
|
||||
b_in[2][1] = 0.5*(point_buf[start+_p+1][1] + point_buf[start+_p+2][1]);
|
||||
b_in[2][2] = 0;
|
||||
|
||||
for(int l = 0; l <= a_bezierIters; l++) {
|
||||
double t = (1.0/a_bezierIters)*l;
|
||||
eval_bezier(v, t, 3, &b_in[0][0]);
|
||||
v[2] = 0.0;
|
||||
push_point(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* End. */
|
||||
if(len > 3) {
|
||||
const int _p = start+len-3;
|
||||
b_in[0][0] = 0.5 * (point_buf[_p][0] + point_buf[_p+1][0]);
|
||||
b_in[0][1] = 0.5 * (point_buf[_p][1] + point_buf[_p+1][1]);
|
||||
b_in[0][2] = 0;
|
||||
|
||||
b_in[1][0] = point_buf[_p+1][0];
|
||||
b_in[1][1] = point_buf[_p+1][1];
|
||||
b_in[1][2] = 0;
|
||||
|
||||
b_in[2][0] = point_buf[_p+2][0];
|
||||
b_in[2][1] = point_buf[_p+2][1];
|
||||
b_in[2][2] = 0;
|
||||
|
||||
for(int l = 0; l <= a_bezierIters; l++) {
|
||||
double t = (1.0/a_bezierIters)*l;
|
||||
eval_bezier(v, t, 3, &b_in[0][0]);
|
||||
v[2] = 0.0;
|
||||
push_point(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
start = k;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifndef CALLBACK
|
||||
# ifdef WIN32
|
||||
# define CALLBACK __attribute__ ((__stdcall__))
|
||||
# else
|
||||
# define CALLBACK
|
||||
# endif
|
||||
#endif /* CALLBACK */
|
||||
|
||||
struct TessData {
|
||||
std::vector<double>* pts; /* Inputs, added by combine. */
|
||||
int numvtx;
|
||||
|
||||
std::vector<Uint16> index; /* Output index list. */
|
||||
GLenum lasttype;
|
||||
int state; /* 0, no vertices, 1, 1 vertex, 2, 2 or more. 0x4 => clockwise. */
|
||||
|
||||
Uint16 vtx[2];
|
||||
};
|
||||
|
||||
static Uint16 g_index[65536];
|
||||
|
||||
void CALLBACK beginCallback(GLenum which, GLvoid* poly_data) {
|
||||
TessData* pData = (TessData*)poly_data;
|
||||
pData->lasttype = which;
|
||||
pData->state = 0;
|
||||
}
|
||||
|
||||
void CALLBACK errorCallback(GLenum errorCode) {
|
||||
const GLubyte* estr;
|
||||
|
||||
estr = gluErrorString(errorCode);
|
||||
fprintf(stderr, "Tesserlation Error: %s\n", estr);
|
||||
}
|
||||
|
||||
void CALLBACK endCallback(void) {
|
||||
|
||||
}
|
||||
|
||||
void CALLBACK vertexCallback(GLvoid* vertex, GLvoid* poly_data) {
|
||||
TessData* pData = (TessData*)poly_data;
|
||||
Uint16 index = *(Uint16*)vertex;
|
||||
switch(pData->lasttype) {
|
||||
case GL_TRIANGLES:
|
||||
pData->index.push_back(index);
|
||||
break;
|
||||
case GL_TRIANGLE_STRIP:
|
||||
if((pData->state & 3) < 2)
|
||||
pData->vtx[pData->state++] = index;
|
||||
else {
|
||||
pData->index.push_back(index);
|
||||
if(pData->state & 0x4) {
|
||||
pData->index.push_back(pData->vtx[1]);
|
||||
pData->index.push_back(pData->vtx[0]);
|
||||
} else {
|
||||
pData->index.push_back(pData->vtx[0]);
|
||||
pData->index.push_back(pData->vtx[1]);
|
||||
}
|
||||
pData->vtx[0] = pData->vtx[1];
|
||||
pData->vtx[1] = index;
|
||||
pData->state ^= 0x4;
|
||||
}
|
||||
break;
|
||||
case GL_TRIANGLE_FAN:
|
||||
if((pData->state & 3) < 2)
|
||||
pData->vtx[pData->state++] = index;
|
||||
else {
|
||||
pData->index.push_back(index);
|
||||
pData->index.push_back(pData->vtx[0]);
|
||||
pData->index.push_back(pData->vtx[1]);
|
||||
pData->vtx[1] = index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CALLBACK combineCallback(GLdouble coords[3],
|
||||
GLdouble* vertex_data[4],
|
||||
GLfloat weight[4], void** dataOut, void* poly_data) {
|
||||
|
||||
TessData* pData = (TessData*)poly_data;
|
||||
pData->pts->push_back(coords[0]);
|
||||
pData->pts->push_back(coords[1]);
|
||||
pData->pts->push_back(coords[2]);
|
||||
*dataOut = (void*)&g_index[pData->numvtx++];
|
||||
}
|
||||
|
||||
#define BEZIER_STEPS 2
|
||||
|
||||
void FontFace::RenderGlyph(int chr) {
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
|
||||
glfglyph_t* glyph = &m_glyphs[chr];
|
||||
glVertexPointer(3, GL_FLOAT, 3*sizeof(float), glyph->varray);
|
||||
glDrawElements(GL_TRIANGLES, glyph->numidx, GL_UNSIGNED_SHORT, glyph->iarray);
|
||||
}
|
||||
|
||||
void FontFace::RenderString(const char* str) {
|
||||
glPushMatrix();
|
||||
for(unsigned int i = 0; i < strlen(str); i++) {
|
||||
if(str[i] == '\n') {
|
||||
glPopMatrix();
|
||||
glTranslatef(0, -m_height, 0);
|
||||
glPushMatrix();
|
||||
} else {
|
||||
glfglyph_t* glyph = &m_glyphs[str[i]];
|
||||
if(glyph->numidx) RenderGlyph(str[i]);
|
||||
glTranslatef(glyph->advx, 0, 0);
|
||||
}
|
||||
}
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
FontFace::FontFace(const char* filename_ttf) {
|
||||
FT_Face face;
|
||||
if(0 != FT_New_Face(library, filename_ttf, 0, &face)) {
|
||||
fprintf(stderr, "Error: Couldn't load '%s'\n", filename_ttf);
|
||||
} else {
|
||||
FT_Set_Char_Size(face, 50*64, 0, 100, 0);
|
||||
for(int chr = 32; chr < 127; chr++) {
|
||||
if(0 != FT_Load_Char(face, chr, FT_LOAD_NO_SCALE)) {
|
||||
printf("Couldn't load glyph\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
assert(face->glyph->format == FT_GLYPH_FORMAT_OUTLINE);
|
||||
FT_Outline* outline = &face->glyph->outline;
|
||||
|
||||
std::vector<double> temppts;
|
||||
std::vector<Uint16> indices;
|
||||
std::vector<double> pts;
|
||||
int nv = 0;
|
||||
|
||||
TessData tessdata;
|
||||
tessdata.pts = &pts;
|
||||
|
||||
gluTessNormal(tobj, 0, 0, 1);
|
||||
gluTessProperty(tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD);
|
||||
gluTessBeginPolygon(tobj, &tessdata);
|
||||
for(int contour = 0; contour < outline->n_contours; contour++) {
|
||||
gluTessBeginContour(tobj);
|
||||
temppts.clear();
|
||||
GenContourPoints(chr, outline, contour, BEZIER_STEPS, &temppts);
|
||||
for(size_t i = 0; i < temppts.size(); i++) pts.push_back(temppts[i]);
|
||||
for(size_t i = 0; i < temppts.size(); i+=4, nv++)
|
||||
gluTessVertex(tobj, &pts[nv*3], &g_index[nv]);
|
||||
gluTessEndContour(tobj);
|
||||
}
|
||||
tessdata.numvtx = nv;
|
||||
gluTessEndPolygon(tobj);
|
||||
|
||||
glfglyph_t _face;
|
||||
|
||||
nv = tessdata.numvtx;
|
||||
_face.varray = (float*)malloc(nv*3*sizeof(float));
|
||||
for(int i = 0; i < nv*3; i++) _face.varray[i] = (float)pts[i];
|
||||
|
||||
_face.numidx = (int)tessdata.index.size();
|
||||
_face.iarray = (Uint16*)malloc(_face.numidx*sizeof(Uint16));
|
||||
for(int i = 0; i < _face.numidx; i++) _face.iarray[i] = tessdata.index[i];
|
||||
|
||||
_face.advx = face->glyph->linearHoriAdvance/(float)(1<<16)/72.0f;
|
||||
_face.advy = face->glyph->linearVertAdvance/(float)(1<<16)/72.0f;
|
||||
//printf(%f,%f\n", _face.advx, _face.advy);
|
||||
m_glyphs[chr] = _face;
|
||||
}
|
||||
m_height = m_glyphs['M'].advy;
|
||||
m_width = m_glyphs['M'].advx;
|
||||
}
|
||||
}
|
||||
|
||||
void GLFTInit(void) {
|
||||
if(0 != FT_Init_FreeType(&library)) {
|
||||
printf("Couldn't init freetype library.\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
tobj = gluNewTess();
|
||||
gluTessCallback(tobj, GLU_TESS_VERTEX_DATA, (_GLUfuncptr) vertexCallback);
|
||||
gluTessCallback(tobj, GLU_TESS_BEGIN_DATA, (_GLUfuncptr) beginCallback);
|
||||
gluTessCallback(tobj, GLU_TESS_END, (_GLUfuncptr) endCallback);
|
||||
gluTessCallback(tobj, GLU_TESS_ERROR, (_GLUfuncptr) errorCallback);
|
||||
gluTessCallback(tobj, GLU_TESS_COMBINE_DATA, (_GLUfuncptr) combineCallback);
|
||||
|
||||
for(Uint16 i = 0; i < 65535; i++) g_index[i] = i;
|
||||
}
|
28
src/glfreetype.h
Normal file
@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
#include <map>
|
||||
#include <SDL_stdinc.h>
|
||||
|
||||
class FontFace {
|
||||
public:
|
||||
FontFace(const char* filename_ttf);
|
||||
void RenderGlyph(int chr);
|
||||
void RenderString(const char* str);
|
||||
|
||||
/* Of Ms. */
|
||||
float GetHeight(void) { return m_height; }
|
||||
float GetWidth(void) { return m_width; }
|
||||
|
||||
private:
|
||||
float m_height;
|
||||
float m_width;
|
||||
|
||||
struct glfglyph_t {
|
||||
float* varray;
|
||||
Uint16* iarray;
|
||||
int numidx;
|
||||
float advx, advy;
|
||||
};
|
||||
std::map<int, glfglyph_t> m_glyphs;
|
||||
};
|
||||
void GLFTInit(void);
|
||||
|
46
src/gui.cpp
Normal file
@ -0,0 +1,46 @@
|
||||
#include "libs.h"
|
||||
#include "gui.h"
|
||||
|
||||
namespace Gui {
|
||||
namespace RawEvents {
|
||||
sigc::signal<void, SDL_MouseButtonEvent*> onMouseDown;
|
||||
sigc::signal<void, SDL_MouseButtonEvent*> onMouseUp;
|
||||
sigc::signal<void, SDL_KeyboardEvent*> onKeyDown;
|
||||
sigc::signal<void, SDL_KeyboardEvent*> onKeyUp;
|
||||
}
|
||||
|
||||
namespace Color {
|
||||
const float bg[] = { .25, .37, .63 };
|
||||
const float bgShadow[] = { .08, .12, .21 };
|
||||
}
|
||||
|
||||
void HandleSDLEvent(SDL_Event* event) {
|
||||
switch(event->type) {
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
Screen::OnClick(&event->button);
|
||||
RawEvents::onMouseDown.emit(&event->button);
|
||||
break;
|
||||
case SDL_MOUSEBUTTONUP:
|
||||
Screen::OnClick(&event->button);
|
||||
RawEvents::onMouseUp.emit(&event->button);
|
||||
break;
|
||||
case SDL_KEYDOWN:
|
||||
Screen::OnKeyDown(&event->key.keysym);
|
||||
RawEvents::onKeyDown.emit(&event->key);
|
||||
break;
|
||||
case SDL_KEYUP:
|
||||
RawEvents::onKeyUp.emit(&event->key);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Draw(void) {
|
||||
Screen::Draw();
|
||||
}
|
||||
|
||||
void Init(int screen_width, int screen_height, int ui_width, int ui_height) {
|
||||
Screen::Init(screen_width, screen_height, ui_width, ui_height);
|
||||
}
|
||||
|
||||
}
|
||||
|
102
src/gui_button.cpp
Normal file
@ -0,0 +1,102 @@
|
||||
#include "libs.h"
|
||||
#include "gui.h"
|
||||
|
||||
#define BUTTON_SIZE 16
|
||||
|
||||
namespace Gui {
|
||||
|
||||
Button::Button(void) {
|
||||
m_isPressed = false;
|
||||
m_eventMask = EVENT_MOUSEDOWN | EVENT_MOUSEUP;
|
||||
SetSize(BUTTON_SIZE, BUTTON_SIZE);
|
||||
}
|
||||
|
||||
void Button::OnMouseDown(MouseButtonEvent* e) {
|
||||
if(e->button == 1) {
|
||||
m_isPressed = true;
|
||||
onPress.emit();
|
||||
/* Wait for mouse release, regardless of where on screen. */
|
||||
_m_release = RawEvents::onMouseUp.connect(sigc::mem_fun(this, &Button::OnRawMouseUp));
|
||||
}
|
||||
}
|
||||
|
||||
void Button::OnMouseUp(MouseButtonEvent* e) {
|
||||
if((e->button == 1) && m_isPressed) {
|
||||
m_isPressed = false;
|
||||
onClick.emit();
|
||||
}
|
||||
}
|
||||
|
||||
void Button::OnActivate(void) {
|
||||
/* Activated by keyboard shortcut. */
|
||||
m_isPressed = true;
|
||||
onPress.emit();
|
||||
_m_kbrelease = RawEvents::onKeyUp.connect(sigc::mem_fun(this, &Button::OnRawKeyUp));
|
||||
}
|
||||
|
||||
void Button::OnRawKeyUp(SDL_KeyboardEvent* e) {
|
||||
if(e->keysym.sym == m_shortcut.sym) {
|
||||
m_isPressed = false;
|
||||
onRelease.emit();
|
||||
onClick.emit();
|
||||
_m_kbrelease.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
void Button::OnRawMouseUp(SDL_MouseButtonEvent* e) {
|
||||
if(e->button == 1) {
|
||||
m_isPressed = false;
|
||||
_m_release.disconnect();
|
||||
onRelease.emit();
|
||||
}
|
||||
}
|
||||
|
||||
void SolidButton::GetSizeRequested(float size[2]) {
|
||||
size[0] = size[1] = BUTTON_SIZE;
|
||||
}
|
||||
|
||||
void TransparentButton::GetSizeRequested(float size[2]) {
|
||||
size[0] = size[1] = BUTTON_SIZE;
|
||||
}
|
||||
|
||||
void SolidButton::Draw(void) {
|
||||
glBegin(GL_QUADS);
|
||||
glColor3f(.6, .6, .6);
|
||||
glVertex2f(0, 0);
|
||||
glVertex2f(15, 0);
|
||||
glVertex2f(15, 15);
|
||||
glVertex2f(0, 15);
|
||||
|
||||
glColor3fv(Color::bgShadow);
|
||||
glVertex2f(2, 0);
|
||||
glVertex2f(15, 0);
|
||||
glVertex2f(15, 13);
|
||||
glVertex2f(2, 13);
|
||||
|
||||
glColor3fv(Color::bg);
|
||||
glVertex2f(2, 2);
|
||||
glVertex2f(13, 2);
|
||||
glVertex2f(13, 13);
|
||||
glVertex2f(2, 13);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
void TransparentButton::Draw(void) {
|
||||
glColor3f(1, 1, 1);
|
||||
glBegin(GL_LINE_LOOP);
|
||||
glVertex2f(0, 0);
|
||||
glVertex2f(15, 0);
|
||||
glVertex2f(15, 15);
|
||||
glVertex2f(0, 15);
|
||||
glEnd();
|
||||
|
||||
glBegin(GL_LINE_LOOP);
|
||||
glVertex2f(1, 1);
|
||||
glVertex2f(14, 1);
|
||||
glVertex2f(14, 14);
|
||||
glVertex2f(1, 14);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
}
|
||||
|
47
src/gui_button.h
Normal file
@ -0,0 +1,47 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include "gui_widget.h"
|
||||
|
||||
namespace Gui {
|
||||
class Button: public Widget {
|
||||
public:
|
||||
Button(void);
|
||||
virtual ~Button(void) {}
|
||||
virtual void OnMouseDown(MouseButtonEvent* e);
|
||||
virtual void OnMouseUp(MouseButtonEvent* e);
|
||||
virtual void OnActivate(void);
|
||||
|
||||
/*
|
||||
* onClick only happens when press and release are both on widget,
|
||||
* (release can be elsewhere).
|
||||
*/
|
||||
sigc::signal<void> onPress;
|
||||
sigc::signal<void> onRelease;
|
||||
sigc::signal<void> onClick;
|
||||
bool IsPressed(void) { return m_isPressed; }
|
||||
private:
|
||||
void OnRawMouseUp(SDL_MouseButtonEvent* e);
|
||||
void OnRawKeyUp(SDL_KeyboardEvent* e);
|
||||
|
||||
bool m_isPressed;
|
||||
sigc::connection _m_release;
|
||||
sigc::connection _m_kbrelease;
|
||||
};
|
||||
|
||||
class SolidButton: public Button {
|
||||
public:
|
||||
SolidButton(void) : Button() {}
|
||||
virtual ~SolidButton(void) {}
|
||||
virtual void GetSizeRequested(float size[2]);
|
||||
virtual void Draw(void);
|
||||
};
|
||||
|
||||
class TransparentButton : public Button {
|
||||
public:
|
||||
TransparentButton(void) : Button() {}
|
||||
virtual ~TransparentButton(void) {}
|
||||
virtual void GetSizeRequested(float size[2]);
|
||||
virtual void Draw(void);
|
||||
};
|
||||
}
|
||||
|
92
src/gui_container.cpp
Normal file
@ -0,0 +1,92 @@
|
||||
#include "gui.h"
|
||||
#include "gui_container.h"
|
||||
|
||||
namespace Gui {
|
||||
|
||||
void Container::HandleMouseEvent(MouseButtonEvent* e) {
|
||||
float x = e->x;
|
||||
float y = e->y;
|
||||
for(std::list<widget_pos>::iterator i = m_children.begin(); i != m_children.end(); ++i) {
|
||||
float pos[2], size[2];
|
||||
if(!(*i).w->IsVisible()) continue;
|
||||
int evmask = (*i).w->GetEventMask();
|
||||
if(e->isdown) {
|
||||
if(!(evmask & Widget::EVENT_MOUSEDOWN)) continue;
|
||||
} else {
|
||||
if(!(evmask & Widget::EVENT_MOUSEUP)) continue;
|
||||
}
|
||||
(*i).w->GetPosition(pos);
|
||||
(*i).w->GetSize(size);
|
||||
|
||||
if((x >= pos[0]) && (x < pos[0]+size[0]) &&
|
||||
(y >= pos[1]) && (y < pos[1]+size[1])) {
|
||||
e->x = x-pos[0];
|
||||
e->y = y-pos[1];
|
||||
if(e->isdown) {
|
||||
(*i).w->OnMouseDown(e);
|
||||
} else {
|
||||
(*i).w->OnMouseUp(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Container::DeleteAllChildren(void) {
|
||||
for(std::list<widget_pos>::iterator i = m_children.begin(); i != m_children.end(); ++i) {
|
||||
delete (*i).w;
|
||||
}
|
||||
m_children.clear();
|
||||
}
|
||||
|
||||
void Container::PrependChild(Widget* child, float x, float y) {
|
||||
widget_pos wp;
|
||||
wp.w = child;
|
||||
wp.pos[0] = x; wp.pos[1] = y;
|
||||
child->SetPosition(x, y);
|
||||
child->SetParent(this);
|
||||
m_children.push_front(wp);
|
||||
}
|
||||
|
||||
void Container::AppendChild(Widget* child, float x, float y) {
|
||||
widget_pos wp;
|
||||
wp.w = child;
|
||||
wp.pos[0] = x; wp.pos[1] = y;
|
||||
child->SetPosition(x, y);
|
||||
child->SetParent(this);
|
||||
m_children.push_back(wp);
|
||||
}
|
||||
|
||||
void Container::Draw(void) {
|
||||
for(std::list<widget_pos>::iterator i = m_children.begin(); i != m_children.end(); ++i) {
|
||||
if(!(*i).w->IsVisible()) continue;
|
||||
glPushMatrix();
|
||||
glTranslatef((*i).pos[0], (*i).pos[1], 0);
|
||||
(*i).w->Draw();
|
||||
glPopMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
void Container::OnMouseDown(MouseButtonEvent* e) {
|
||||
HandleMouseEvent(e);
|
||||
}
|
||||
|
||||
void Container::OnMouseUp(MouseButtonEvent* e) {
|
||||
HandleMouseEvent(e);
|
||||
}
|
||||
|
||||
void Container::ShowAll(void) {
|
||||
for(std::list<widget_pos>::iterator i = m_children.begin(); i != m_children.end(); ++i) {
|
||||
(*i).w->Show();
|
||||
}
|
||||
Show();
|
||||
}
|
||||
|
||||
void Container::HideAll(void) {
|
||||
for(std::list<widget_pos>::iterator i = m_children.begin(); i != m_children.end(); ++i) {
|
||||
(*i).w->Hide();
|
||||
}
|
||||
Hide();
|
||||
}
|
||||
|
||||
}
|
||||
|
29
src/gui_container.h
Normal file
@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
/* Parent of all widgets that contain other widgets. */
|
||||
|
||||
#include <list>
|
||||
#include "gui_widget.h"
|
||||
|
||||
namespace Gui {
|
||||
class Container : public Widget {
|
||||
public:
|
||||
void OnMouseDown(MouseButtonEvent* e);
|
||||
void OnMouseUp(MouseButtonEvent* e);
|
||||
void DeleteAllChildren(void);
|
||||
virtual void Draw(void);
|
||||
virtual void ShowAll(void);
|
||||
virtual void HideAll(void);
|
||||
private:
|
||||
void HandleMouseEvent(MouseButtonEvent* e);
|
||||
protected:
|
||||
void PrependChild(Widget* w, float x, float y);
|
||||
void AppendChild(Widget* w, float x, float y);
|
||||
|
||||
struct widget_pos {
|
||||
Widget* w;
|
||||
float pos[2];
|
||||
};
|
||||
std::list<widget_pos> m_children;
|
||||
};
|
||||
}
|
||||
|
9
src/gui_events.h
Normal file
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
namespace Gui {
|
||||
struct MouseButtonEvent {
|
||||
Uint8 isdown;
|
||||
Uint8 button;
|
||||
float x, y;
|
||||
};
|
||||
}
|
||||
|
62
src/gui_fixed.cpp
Normal file
@ -0,0 +1,62 @@
|
||||
#include "libs.h"
|
||||
#include "gui.h"
|
||||
#include "l3d.h"
|
||||
|
||||
namespace Gui {
|
||||
|
||||
Fixed::Fixed(float x, float y, float w, float h) {
|
||||
SetPosition(x, y);
|
||||
SetSize(w, h);
|
||||
memcpy(m_bgcol, Color::bg, 3*sizeof(float));
|
||||
m_w = w; m_h = h;
|
||||
m_transparent = false;
|
||||
m_eventMask = EVENT_ALL;
|
||||
Screen::AddBaseWidget(this);
|
||||
}
|
||||
|
||||
void Fixed::GetSizeRequested(float size[2]) {
|
||||
GetSize(size);
|
||||
}
|
||||
|
||||
Fixed::~Fixed(void) {
|
||||
Screen::RemoveBaseWidget(this);
|
||||
}
|
||||
|
||||
void Fixed::Draw(void) {
|
||||
if(!m_transparent) {
|
||||
glBegin(GL_QUADS);
|
||||
glColor3f(m_bgcol[0], m_bgcol[1], m_bgcol[2]);
|
||||
glVertex2f(m_w, 0);
|
||||
glVertex2f(m_w, m_h);
|
||||
glVertex2f(0, m_h);
|
||||
glVertex2f(0, 0);
|
||||
glEnd();
|
||||
}
|
||||
Container::Draw();
|
||||
}
|
||||
|
||||
void Fixed::Add(Widget* child, float x, float y) {
|
||||
AppendChild(child, x, y);
|
||||
}
|
||||
|
||||
void Fixed::Remove(Widget* child) {
|
||||
for(std::list<widget_pos>::iterator i = m_children.begin(); i != m_children.end(); ++i) {
|
||||
if((*i).w == child) {
|
||||
m_children.erase(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Fixed::SetBgColor(float rgb[3]) {
|
||||
SetBgColor(rgb[0], rgb[1], rgb[2]);
|
||||
}
|
||||
|
||||
void Fixed::SetBgColor(float r, float g, float b) {
|
||||
m_bgcol[0] = r;
|
||||
m_bgcol[1] = g;
|
||||
m_bgcol[2] = b;
|
||||
}
|
||||
|
||||
}
|
||||
|
25
src/gui_fixed.h
Normal file
@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
#include "gui_widget.h"
|
||||
#include "gui_container.h"
|
||||
|
||||
/* Fixed position widget container. */
|
||||
|
||||
namespace Gui {
|
||||
class Fixed : public Container {
|
||||
public:
|
||||
Fixed(float x, float y, float w, float h);
|
||||
void Add(Widget* child, float x, float y);
|
||||
void Remove(Widget* child);
|
||||
virtual void Draw(void);
|
||||
virtual ~Fixed(void);
|
||||
virtual void GetSizeRequested(float size[2]);
|
||||
void SetBgColor(float rgb[3]);
|
||||
void SetBgColor(float r, float g, float b);
|
||||
void SetTransparency(bool a) { m_transparent = a; }
|
||||
private:
|
||||
float m_w, m_h;
|
||||
float m_bgcol[3];
|
||||
bool m_transparent;
|
||||
};
|
||||
}
|
||||
|
103
src/gui_image.cpp
Normal file
@ -0,0 +1,103 @@
|
||||
#include "libs.h"
|
||||
#include "gui_image.h"
|
||||
#include "l3d.h"
|
||||
|
||||
namespace Gui {
|
||||
|
||||
Image::~Image(void) {
|
||||
#pragma message("Warning: Leaking GL textures..")
|
||||
}
|
||||
|
||||
Image::Image(const char* filename) : Widget() {
|
||||
SDL_Surface* is = IMG_Load(filename);
|
||||
if(!is) {
|
||||
fprintf(stderr, "Could not load %s\n", filename);
|
||||
L3D::Quit();
|
||||
}
|
||||
m_imgw = is->w;
|
||||
m_imgh = is->h;
|
||||
|
||||
SetSize(m_imgw, m_imgh);
|
||||
|
||||
/* GL textures must be POT, dim > 64. */
|
||||
int texw, texh;
|
||||
{
|
||||
int nbit = 0;
|
||||
int sz = m_imgw;
|
||||
while(sz) { sz >>= 1; nbit++; }
|
||||
texw = MAX(64, 1<<nbit);
|
||||
|
||||
sz = m_imgh;
|
||||
nbit = 0;
|
||||
while(sz) { sz >>= 1; nbit++; }
|
||||
texh = MAX(64, 1<<nbit);
|
||||
}
|
||||
m_invtexw = 1.0f / texw;
|
||||
m_invtexh = 1.0f / texh;
|
||||
|
||||
SDL_Rect src, dest;
|
||||
SDL_Surface* s = SDL_CreateRGBSurface(SDL_SWSURFACE, texw, texh, 32,
|
||||
0xff, 0xff00, 0xff0000, 0xff000000);
|
||||
|
||||
/* Just want to directly copy RGBA values, not blend using alpha. */
|
||||
SDL_SetAlpha(s, 0, 0);
|
||||
SDL_SetAlpha(is, 0, 0);
|
||||
SDL_BlitSurface(is, NULL, s, NULL);
|
||||
/*
|
||||
* A silly workaround for the GL_LINEAR filtering of the texture, which
|
||||
* leads to the black bits of the texture leaking in via bilinear filtering.
|
||||
*/
|
||||
dest.x = m_imgw; dest.y = 0; dest.w = m_imgw; dest.h = m_imgh;
|
||||
src.x = m_imgw-1; src.y = 0; src.w=1; src.h = m_imgh;
|
||||
SDL_BlitSurface(is, &src, s, &dest);
|
||||
|
||||
dest.x = 0; dest.y = m_imgh; dest.w = m_imgw; dest.h = m_imgh;
|
||||
src.x = 0; src.y = m_imgh-1; src.w=m_imgw; src.h = 1;
|
||||
SDL_BlitSurface(is, &src, s, &dest);
|
||||
|
||||
SDL_FreeSurface(is);
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glGenTextures(1, &m_tex);
|
||||
glBindTexture(GL_TEXTURE_2D, m_tex);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texw, texh, 0, GL_RGBA, GL_UNSIGNED_BYTE, s->pixels);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
SDL_FreeSurface(s);
|
||||
}
|
||||
|
||||
void Image::GetSizeRequested(float size[2]) {
|
||||
size[0] = m_imgw;
|
||||
size[1] = m_imgh;
|
||||
}
|
||||
|
||||
void Image::Draw(void) {
|
||||
float allocSize[2];
|
||||
GetSize(allocSize);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D, m_tex);
|
||||
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
||||
glBegin(GL_QUADS);
|
||||
float w = m_imgw * m_invtexw;
|
||||
float h = m_imgh * m_invtexh;
|
||||
glTexCoord2f(0, h);
|
||||
glVertex2f(0, 0);
|
||||
glTexCoord2f(w, h);
|
||||
glVertex2f(allocSize[0],0);
|
||||
glTexCoord2f(w, 0);
|
||||
glVertex2f(allocSize[0], allocSize[1]);
|
||||
glTexCoord2f(0, 0);
|
||||
glVertex2f(0, allocSize[1]);
|
||||
glEnd();
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
}
|
||||
|
18
src/gui_image.h
Normal file
@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include "gui_widget.h"
|
||||
|
||||
namespace Gui {
|
||||
class Image : public Widget {
|
||||
public:
|
||||
Image(const char* filename);
|
||||
virtual void Draw(void);
|
||||
virtual ~Image(void);
|
||||
virtual void GetSizeRequested(float size[2]);
|
||||
private:
|
||||
GLuint m_tex;
|
||||
int m_imgw, m_imgh;
|
||||
float m_invtexw, m_invtexh;
|
||||
};
|
||||
}
|
||||
|
43
src/gui_image_button.cpp
Normal file
@ -0,0 +1,43 @@
|
||||
#include "libs.h"
|
||||
#include "gui.h"
|
||||
#include "gui_image_button.h"
|
||||
#include "l3d.h"
|
||||
|
||||
namespace Gui {
|
||||
|
||||
ImageButton::ImageButton(const char* img_normal) : Button() {
|
||||
LoadImages(img_normal, NULL);
|
||||
}
|
||||
|
||||
ImageButton::ImageButton(const char* img_normal, const char* img_pressed) : Button() {
|
||||
LoadImages(img_normal, img_pressed);
|
||||
}
|
||||
|
||||
void ImageButton::LoadImages(const char* img_normal, const char* img_pressed) {
|
||||
m_imgNormal = new Image(img_normal);
|
||||
float size[2];
|
||||
m_imgNormal->GetSizeRequested(size);
|
||||
SetSize(size[0], size[1]);
|
||||
|
||||
if(img_pressed) m_imgPressed = new Image(img_pressed);
|
||||
else m_imgPressed = NULL;
|
||||
}
|
||||
|
||||
void ImageButton::GetSizeRequested(float size[2]) {
|
||||
m_imgNormal->GetSizeRequested(size);
|
||||
}
|
||||
|
||||
void ImageButton::Draw(void) {
|
||||
float size[2];
|
||||
GetSize(size);
|
||||
Gui::Image* img;
|
||||
if(m_imgPressed && IsPressed())
|
||||
img = m_imgPressed;
|
||||
else
|
||||
img = m_imgNormal;
|
||||
img->SetSize(size[0], size[1]);
|
||||
img->Draw();
|
||||
}
|
||||
|
||||
}
|
||||
|
21
src/gui_image_button.h
Normal file
@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
|
||||
#include "gui_widget.h"
|
||||
#include "gui_button.h"
|
||||
|
||||
namespace Gui {
|
||||
class ImageButton : public Button {
|
||||
public:
|
||||
ImageButton(const char* img_normal);
|
||||
ImageButton(const char* img_normal, const char* img_pressed);
|
||||
virtual void Draw(void);
|
||||
virtual ~ImageButton(void) {}
|
||||
virtual void GetSizeRequested(float size[2]);
|
||||
private:
|
||||
void LoadImages(const char* img_normal, const char* img_pressed);
|
||||
Image* m_imgNormal;
|
||||
Image* m_imgPressed;
|
||||
};
|
||||
}
|
||||
|
30
src/gui_image_radio_button.cpp
Normal file
@ -0,0 +1,30 @@
|
||||
#include "libs.h"
|
||||
#include "gui.h"
|
||||
#include "gui_image_radio_button.h"
|
||||
#include "l3d.h"
|
||||
|
||||
namespace Gui {
|
||||
|
||||
ImageRadioButton::ImageRadioButton(RadioGroup* g, const char* img_normal,
|
||||
const char* img_pressed) : RadioButton(g) {
|
||||
m_imgNormal = new Image(img_normal);
|
||||
m_imgPressed = new Image(img_pressed);
|
||||
float size[2];
|
||||
m_imgNormal->GetSizeRequested(size);
|
||||
SetSize(size[0], size[1]);
|
||||
}
|
||||
|
||||
void ImageRadioButton::GetSizeRequested(float size[2]) {
|
||||
m_imgNormal->GetSizeRequested(size);
|
||||
}
|
||||
|
||||
void ImageRadioButton::Draw(void) {
|
||||
if(m_pressed) {
|
||||
m_imgPressed->Draw();
|
||||
} else {
|
||||
m_imgNormal->Draw();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
18
src/gui_image_radio_button.h
Normal file
@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include "gui_radio_button.h"
|
||||
|
||||
class RadioButton;
|
||||
|
||||
namespace Gui {
|
||||
class ImageRadioButton : public RadioButton {
|
||||
public:
|
||||
ImageRadioButton(RadioGroup*, const char* img_normal, const char* img_pressed);
|
||||
virtual void Draw(void);
|
||||
virtual void GetSizeRequested(float size[2]);
|
||||
private:
|
||||
Image* m_imgNormal;
|
||||
Image* m_imgPressed;
|
||||
};
|
||||
}
|
||||
|
10
src/gui_iselectable.h
Normal file
@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
namespace Gui {
|
||||
class ISelectable {
|
||||
public:
|
||||
sigc::signal<void, ISelectable*> onSelect;
|
||||
virtual void SetSelected(bool) = 0;
|
||||
};
|
||||
}
|
||||
|
41
src/gui_label.cpp
Normal file
@ -0,0 +1,41 @@
|
||||
#include "gui.h"
|
||||
|
||||
namespace Gui {
|
||||
|
||||
Label::Label(const char* text) {
|
||||
SetText(text);
|
||||
m_color[0] = m_color[1] = m_color[2] = 1.0f;
|
||||
}
|
||||
|
||||
Label::Label(std::string& text) {
|
||||
SetText(text);
|
||||
m_color[0] = m_color[1] = m_color[2] = 1.0f;
|
||||
}
|
||||
|
||||
void Label::SetText(const char* text) {
|
||||
m_text = text;
|
||||
}
|
||||
|
||||
void Label::SetText(std::string& text) {
|
||||
m_text = text;
|
||||
}
|
||||
|
||||
void Label::Draw(void) {
|
||||
glColor3fv(m_color);
|
||||
Screen::RenderString(m_text);
|
||||
}
|
||||
|
||||
void Label::GetSizeRequested(float size[2]) {
|
||||
#pragma message("Not setting size correctly.")
|
||||
size[0] = 70;
|
||||
size[1] = 10;
|
||||
}
|
||||
|
||||
void Label::SetColor(float r, float g, float b) {
|
||||
m_color[0] = r;
|
||||
m_color[1] = g;
|
||||
m_color[2] = b;
|
||||
}
|
||||
|
||||
}
|
||||
|
21
src/gui_label.h
Normal file
@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include "gui_widget.h"
|
||||
|
||||
namespace Gui {
|
||||
class Label : public Widget {
|
||||
public:
|
||||
Label(const char* text);
|
||||
Label(std::string& text);
|
||||
virtual void Draw(void);
|
||||
virtual ~Label(void) {}
|
||||
virtual void GetSizeRequested(float size[2]);
|
||||
void SetText(const char* text);
|
||||
void SetText(std::string& text);
|
||||
void SetColor(float r, float g, float b);
|
||||
private:
|
||||
std::string m_text;
|
||||
float m_color[3];
|
||||
};
|
||||
}
|
||||
|
62
src/gui_multi_state_image_button.cpp
Normal file
@ -0,0 +1,62 @@
|
||||
#include "libs.h"
|
||||
#include "gui.h"
|
||||
|
||||
namespace Gui {
|
||||
|
||||
MultiStateImageButton::MultiStateImageButton(void) : Button() {
|
||||
m_curState = 0;
|
||||
m_isSelected = true;
|
||||
Button::onClick.connect(sigc::mem_fun(this, &MultiStateImageButton::OnActivate));
|
||||
}
|
||||
|
||||
MultiStateImageButton::~MultiStateImageButton(void) {
|
||||
for(std::vector<State>::iterator i = m_states.begin(); i != m_states.end(); ++i) {
|
||||
delete (*i).image;
|
||||
}
|
||||
}
|
||||
|
||||
void MultiStateImageButton::StateNext(void) {
|
||||
m_curState++;
|
||||
if(m_curState >= (signed)m_states.size()) m_curState = 0;
|
||||
}
|
||||
|
||||
void MultiStateImageButton::StatePrev(void) {
|
||||
m_curState--;
|
||||
if(m_curState < 0) m_curState = (signed)m_states.size()-1;
|
||||
}
|
||||
|
||||
void MultiStateImageButton::OnActivate(void) {
|
||||
/* Only iterate through states once widget is selected. */
|
||||
if(m_isSelected) StateNext();
|
||||
else {
|
||||
m_isSelected = true;
|
||||
onSelect.emit(this);
|
||||
}
|
||||
onClick.emit(this);
|
||||
}
|
||||
|
||||
void MultiStateImageButton::SetSelected(bool state) {
|
||||
m_isSelected = state;
|
||||
}
|
||||
|
||||
void MultiStateImageButton::GetSizeRequested(float size[2]) {
|
||||
assert(m_states.size());
|
||||
m_states[0].image->GetSizeRequested(size);
|
||||
}
|
||||
|
||||
void MultiStateImageButton::Draw(void) {
|
||||
m_states[m_curState].image->Draw();
|
||||
}
|
||||
|
||||
void MultiStateImageButton::AddState(int state, const char* filename) {
|
||||
State s;
|
||||
s.state = state;
|
||||
s.image = new Image(filename);
|
||||
m_states.push_back(s);
|
||||
float size[2];
|
||||
s.image->GetSizeRequested(size);
|
||||
SetSize(size[0], size[1]);
|
||||
}
|
||||
|
||||
}
|
||||
|
31
src/gui_multi_state_image_button.h
Normal file
@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include "gui_button.h"
|
||||
#include "gui_iselectable.h"
|
||||
|
||||
namespace Gui {
|
||||
class MultiStateImageButton : public Button, public ISelectable {
|
||||
public:
|
||||
MultiStateImageButton(void);
|
||||
virtual void Draw(void);
|
||||
virtual ~MultiStateImageButton(void);
|
||||
virtual void GetSizeRequested(float size[2]);
|
||||
void AddState(int state, const char* filename);
|
||||
int GetState(void) { return m_states[m_curState].state; }
|
||||
void StateNext(void);
|
||||
void StatePrev(void);
|
||||
virtual void OnActivate(void);
|
||||
sigc::signal<void, MultiStateImageButton*> onClick;
|
||||
virtual void SetSelected(bool state);
|
||||
private:
|
||||
struct State {
|
||||
int state;
|
||||
Image* image;
|
||||
};
|
||||
std::vector<State> m_states;
|
||||
int m_curState;
|
||||
bool m_isSelected;
|
||||
};
|
||||
}
|
||||
|
78
src/gui_radio_button.cpp
Normal file
@ -0,0 +1,78 @@
|
||||
#include "libs.h"
|
||||
#include "gui.h"
|
||||
|
||||
#define BUTTON_SIZE 16
|
||||
|
||||
namespace Gui {
|
||||
|
||||
RadioButton::RadioButton(Gui::RadioGroup* g) {
|
||||
m_pressed = false;
|
||||
SetSize(BUTTON_SIZE, BUTTON_SIZE);
|
||||
g->Add(this);
|
||||
}
|
||||
|
||||
RadioButton::~RadioButton(void) {
|
||||
|
||||
}
|
||||
|
||||
void RadioButton::OnMouseDown(MouseButtonEvent* e) {
|
||||
onPress.emit();
|
||||
OnActivate();
|
||||
}
|
||||
|
||||
void RadioButton::OnActivate(void) {
|
||||
if(!m_pressed) onSelect.emit(this);
|
||||
m_pressed = true;
|
||||
}
|
||||
|
||||
void RadioButton::GetSizeRequested(float& w, float& h) {
|
||||
w = BUTTON_SIZE;
|
||||
h = BUTTON_SIZE;
|
||||
}
|
||||
|
||||
void RadioButton::Draw(void) {
|
||||
if(m_pressed) {
|
||||
glBegin(GL_QUADS);
|
||||
glColor3fv(Color::bgShadow);
|
||||
glVertex2f(0, 0);
|
||||
glVertex2f(15, 0);
|
||||
glVertex2f(15, 15);
|
||||
glVertex2f(0, 15);
|
||||
|
||||
glColor3f(.6, .6, .6);
|
||||
glVertex2f(2, 0);
|
||||
glVertex2f(15, 0);
|
||||
glVertex2f(15, 13);
|
||||
glVertex2f(2, 13);
|
||||
|
||||
glColor3fv(Color::bg);
|
||||
glVertex2f(2, 2);
|
||||
glVertex2f(13, 2);
|
||||
glVertex2f(13, 13);
|
||||
glVertex2f(2, 13);
|
||||
glEnd();
|
||||
} else {
|
||||
glBegin(GL_QUADS);
|
||||
glColor3f(.6, .6, .6);
|
||||
glVertex2f(0, 0);
|
||||
glVertex2f(15, 0);
|
||||
glVertex2f(15, 15);
|
||||
glVertex2f(0, 15);
|
||||
|
||||
glColor3fv(Color::bgShadow);
|
||||
glVertex2f(2, 0);
|
||||
glVertex2f(15, 0);
|
||||
glVertex2f(15, 13);
|
||||
glVertex2f(2, 13);
|
||||
|
||||
glColor3fv(Color::bg);
|
||||
glVertex2f(2, 2);
|
||||
glVertex2f(13, 2);
|
||||
glVertex2f(13, 13);
|
||||
glVertex2f(2, 13);
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
27
src/gui_radio_button.h
Normal file
@ -0,0 +1,27 @@
|
||||
#ifndef _GUIRADIOBUTTON_H
|
||||
#define _GUIRADIOBUTTON_H
|
||||
|
||||
#include "gui_widget.h"
|
||||
#include "gui_iselectable.h"
|
||||
#include <string>
|
||||
|
||||
namespace Gui {
|
||||
class RadioGroup;
|
||||
|
||||
class RadioButton: public Button, public ISelectable {
|
||||
public:
|
||||
RadioButton(RadioGroup *);
|
||||
virtual ~RadioButton();
|
||||
virtual void Draw();
|
||||
virtual void GetSizeRequested(float &w, float &h);
|
||||
virtual void OnMouseDown(MouseButtonEvent *e);
|
||||
virtual void OnActivate();
|
||||
virtual void SetSelected(bool state) { m_pressed = state; }
|
||||
bool GetSelected() { return m_pressed; }
|
||||
protected:
|
||||
int m_pressed;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* _GUIRADIOBUTTON_H */
|
21
src/gui_radio_group.cpp
Normal file
@ -0,0 +1,21 @@
|
||||
#include "libs.h"
|
||||
#include "gui_radio_group.h"
|
||||
#include "gui_iselectable.h"
|
||||
|
||||
namespace Gui {
|
||||
|
||||
void RadioGroup::Add(ISelectable* b) {
|
||||
b->onSelect.connect(sigc::mem_fun(*this, &RadioGroup::OnSelected));
|
||||
m_members.push_back(b);
|
||||
}
|
||||
|
||||
void RadioGroup::OnSelected(ISelectable* b) {
|
||||
for(std::list<ISelectable*>::iterator i = m_members.begin(); i != m_members.end(); ++i) {
|
||||
if(*i != b) {
|
||||
(*i)->SetSelected(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
16
src/gui_radio_group.h
Normal file
@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
#include <list>
|
||||
#include "gui.h"
|
||||
|
||||
namespace Gui {
|
||||
class RadioGroup {
|
||||
public:
|
||||
RadioGroup(void) {};
|
||||
virtual ~RadioGroup(void) {};
|
||||
void Add(ISelectable* b);
|
||||
private:
|
||||
void OnSelected(ISelectable* b);
|
||||
std::list<ISelectable*> m_members;
|
||||
};
|
||||
}
|
||||
|
195
src/gui_screen.cpp
Normal file
@ -0,0 +1,195 @@
|
||||
#include "gui.h"
|
||||
#include "glfreetype.h"
|
||||
|
||||
namespace Gui {
|
||||
|
||||
FontFace* Screen::font;
|
||||
bool Screen::init = false;
|
||||
int Screen::width;
|
||||
int Screen::height;
|
||||
int Screen::realWidth;
|
||||
int Screen::realHeight;
|
||||
float Screen::invRealWidth;
|
||||
float Screen::invRealHeight;
|
||||
std::list<Widget*> Screen::widgets;
|
||||
std::list<Widget*> Screen::kbshortcut_widgets;
|
||||
float Screen::font_xsize;
|
||||
float Screen::font_ysize;
|
||||
std::vector<Screen::LabelPos> Screen::labelPositions;
|
||||
|
||||
void Screen::Init(int real_width, int real_height, int ui_width, int ui_height) {
|
||||
Screen::width = ui_width;
|
||||
Screen::height = ui_height;
|
||||
Screen::realWidth = real_width;
|
||||
Screen::realHeight = real_height;
|
||||
Screen::invRealWidth = 1.0f/real_width;
|
||||
Screen::invRealHeight = 1.0f/real_height;
|
||||
Screen::init = true;
|
||||
Screen::font = new FontFace("font.ttf");
|
||||
Screen::font_xsize = 16*0.8;
|
||||
Screen::font_ysize = 16;
|
||||
}
|
||||
|
||||
GLint Screen::Project(GLdouble objX, GLdouble objY, GLdouble objZ, const GLdouble* model,
|
||||
const GLdouble* proj, const GLint* view,
|
||||
GLdouble* winX, GLdouble* winY, GLdouble* winZ) {
|
||||
|
||||
GLint o = gluProject(objX, objY, objZ, model, proj, view, winX, winY, winZ);
|
||||
*winX = (*winX) * width * invRealWidth;
|
||||
*winY = (*winY) * height * invRealHeight;
|
||||
return o;
|
||||
}
|
||||
|
||||
void Screen::EnterOrtho(void) {
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_LIGHTING);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
//glOrtho(9, 320, 0, 200, -1, 1);
|
||||
glOrtho(0, width, 0, height, -1, 1);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
}
|
||||
|
||||
void Screen::LeaveOrtho(void) {
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPopMatrix();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPopMatrix();
|
||||
glEnable(GL_LIGHTING);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
}
|
||||
|
||||
void Screen::Draw(void) {
|
||||
assert(Screen::init);
|
||||
labelPositions.clear();
|
||||
EnterOrtho();
|
||||
|
||||
for(std::list<Widget*>::iterator i = Screen::widgets.begin(); i != Screen::widgets.end(); ++i) {
|
||||
if(!(*i)->IsVisible()) continue;
|
||||
glPushMatrix();
|
||||
float pos[2];
|
||||
(*i)->GetPosition(pos);
|
||||
glTranslatef(pos[0], pos[1], 0);
|
||||
(*i)->Draw();
|
||||
glPopMatrix();
|
||||
}
|
||||
LeaveOrtho();
|
||||
}
|
||||
|
||||
void Screen::AddBaseWidget(Widget* w) {
|
||||
Screen::widgets.push_back(w);
|
||||
}
|
||||
|
||||
void Screen::RemoveBaseWidget(Widget* w) {
|
||||
Screen::widgets.remove(w);
|
||||
}
|
||||
|
||||
void Screen::OnClick(SDL_MouseButtonEvent* e) {
|
||||
MouseButtonEvent ev;
|
||||
float x = e->x;
|
||||
float y = e->y;
|
||||
y = height-(y*height*invRealHeight);
|
||||
x = x*width*invRealWidth;
|
||||
ev.button = e->button;
|
||||
ev.isdown = (e->type == SDL_MOUSEBUTTONDOWN);
|
||||
ev.x = x;
|
||||
ev.y = y;
|
||||
OnClickTestLabels(ev);
|
||||
for(std::list<Widget*>::iterator i = Screen::widgets.begin(); i != Screen::widgets.end(); ++i) {
|
||||
float size[2], pos[2];
|
||||
if(!(*i)->IsVisible()) continue;
|
||||
int evmask = (*i)->GetEventMask();
|
||||
if(ev.isdown) {
|
||||
if(!(evmask & Widget::EVENT_MOUSEDOWN)) continue;
|
||||
} else {
|
||||
if(!(evmask & Widget::EVENT_MOUSEUP)) continue;
|
||||
}
|
||||
(*i)->GetPosition(pos);
|
||||
(*i)->GetSize(size);
|
||||
|
||||
if((x >= pos[0]) && (x < pos[0]+size[0]) &&
|
||||
(y >= pos[1]) && (y < pos[1]+size[1])) {
|
||||
|
||||
ev.x = x-pos[0];
|
||||
ev.y = y-pos[1];
|
||||
|
||||
if(ev.isdown) {
|
||||
(*i)->OnMouseDown(&ev);
|
||||
} else {
|
||||
(*i)->OnMouseUp(&ev);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Screen::OnClickTestLabels(const Gui::MouseButtonEvent& ev) {
|
||||
/* Hm, shame the UI is fixed size for this purpose.. */
|
||||
for(std::vector<LabelPos>::iterator l = labelPositions.begin(); l != labelPositions.end(); ++l) {
|
||||
float dx = abs((*l).x - ev.x);
|
||||
float dy = abs((*l).y - ev.y);
|
||||
|
||||
if((dx < 5) && (dy < 5)) {
|
||||
(*l).onClick.emit(&ev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Screen::OnKeyDown(const SDL_keysym* sym) {
|
||||
for(std::list<Widget*>::iterator i = kbshortcut_widgets.begin(); i != kbshortcut_widgets.end(); ++i) {
|
||||
if(!(*i)->IsVisible()) continue;
|
||||
(*i)->OnPreShortcut(sym);
|
||||
}
|
||||
}
|
||||
|
||||
void Screen::RenderString(const std::string& s) {
|
||||
glPushMatrix();
|
||||
glScalef(Screen::font_xsize, Screen::font_ysize, 1);
|
||||
font->RenderString(s.c_str());
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
bool Screen::CanPutLabel(float x, float y) {
|
||||
for(std::vector<LabelPos>::iterator i = labelPositions.begin(); i != labelPositions.end(); ++i) {
|
||||
if((fabs(x-(*i).x) < 5) &&
|
||||
(fabs(y-(*i).y) < 5)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Screen::RenderLabel(const std::string& s, float x, float y) {
|
||||
if(CanPutLabel(x, y)) {
|
||||
labelPositions.push_back(LabelPos(x, y));
|
||||
glPushMatrix();
|
||||
glTranslatef(x, y, 0);
|
||||
glScalef(Screen::font_xsize, Screen::font_ysize, 1);
|
||||
glTranslatef(0.5*font->GetWidth(), -0.4*font->GetHeight(), 0);
|
||||
font->RenderString(s.c_str());
|
||||
glPopMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
void Screen::PutClickableLabel(const std::string& s, float x, float y,
|
||||
sigc::slot<void, const Gui::MouseButtonEvent*> slot) {
|
||||
|
||||
if(CanPutLabel(x, y)) {
|
||||
LabelPos p = LabelPos(x, y);
|
||||
p.onClick.connect(slot);
|
||||
labelPositions.push_back(p);
|
||||
glPushMatrix();
|
||||
glTranslatef(x, y, 0);
|
||||
glScalef(Screen::font_xsize, Screen::font_ysize, 1);
|
||||
glTranslatef(0.5*font->GetWidth(), -0.4*font->GetHeight(), 0);
|
||||
font->RenderString(s.c_str());
|
||||
glPopMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
void Screen::AddShortcutWidget(Widget* w) {
|
||||
kbshortcut_widgets.push_back(w);
|
||||
}
|
||||
|
||||
}
|
||||
|
51
src/gui_screen.h
Normal file
@ -0,0 +1,51 @@
|
||||
#pragma once
|
||||
#include <list>
|
||||
#include "gui.h"
|
||||
|
||||
class FontFace;
|
||||
|
||||
namespace Gui {
|
||||
class Screen {
|
||||
public:
|
||||
static void Init(int real_width, int real_height, int ui_width, int ui_height);
|
||||
static void Draw(void);
|
||||
static void AddBaseWidget(Widget* w);
|
||||
static void RemoveBaseWidget(Widget* w);
|
||||
static void OnClick(SDL_MouseButtonEvent* e);
|
||||
static void OnKeyDown(const SDL_keysym* sym);
|
||||
static void RenderString(const std::string& s);
|
||||
static void PutClickableLabel(const std::string& s, float x, float y,
|
||||
sigc::slot<void, const Gui::MouseButtonEvent*> slot);
|
||||
static void RenderLabel(const std::string& s, float x, float y);
|
||||
static void EnterOrtho(void);
|
||||
static void LeaveOrtho(void);
|
||||
static int GetWidth(void) { return width; }
|
||||
static int GetHeight(void) { return height; }
|
||||
/* gluProject but fixes UI/screen size mismatch. */
|
||||
static GLint Project(GLdouble objX, GLdouble objY, GLdouble objZ, const GLdouble* model,
|
||||
const GLdouble* proj, const GLint* view, GLdouble* winX,
|
||||
GLdouble* winY, GLdouble* winZ);
|
||||
friend void Widget::SetShortcut(SDLKey key, SDLMod mod);
|
||||
private:
|
||||
struct LabelPos {
|
||||
LabelPos(float _x, float _y) : x(_x), y(_y) {}
|
||||
float x, y;
|
||||
sigc::signal<void, const Gui::MouseButtonEvent*> onClick;
|
||||
};
|
||||
static std::vector<LabelPos> labelPositions;
|
||||
static void OnClickTestLabels(const Gui::MouseButtonEvent& ev);
|
||||
static bool CanPutLabel(float x, float y);
|
||||
static void AddShortcutWidget(Widget* w);
|
||||
|
||||
static bool init;
|
||||
static int width, height;
|
||||
static int realWidth, realHeight;
|
||||
static float invRealWidth, invRealHeight;
|
||||
static std::list<Widget*> widgets;
|
||||
static std::list<Widget*> kbshortcut_widgets;
|
||||
static FontFace* font;
|
||||
static float font_xsize;
|
||||
static float font_ysize;
|
||||
};
|
||||
}
|
||||
|
75
src/gui_toggle_button.cpp
Normal file
@ -0,0 +1,75 @@
|
||||
#include "libs.h"
|
||||
#include "gui.h"
|
||||
|
||||
#define BUTTON_SIZE 16
|
||||
|
||||
namespace Gui {
|
||||
|
||||
ToggleButton::ToggleButton(void) {
|
||||
m_pressed = false;
|
||||
SetSize(BUTTON_SIZE, BUTTON_SIZE);
|
||||
}
|
||||
|
||||
void ToggleButton::OnMouseDown(MouseButtonEvent* e) {
|
||||
if(e->button == 1) {
|
||||
onPress.emit();
|
||||
m_pressed = !m_pressed;
|
||||
if(m_pressed) {
|
||||
onSelect.emit(this);
|
||||
} else {
|
||||
onDeselect.emit(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ToggleButton::GetSizeRequested(float& w, float& h) {
|
||||
w = BUTTON_SIZE;
|
||||
h = BUTTON_SIZE;
|
||||
}
|
||||
|
||||
void ToggleButton::Draw(void) {
|
||||
if(m_pressed) {
|
||||
glBegin(GL_QUADS);
|
||||
glColor3fv(Color::bgShadow);
|
||||
glVertex2f(0, 0);
|
||||
glVertex2f(15, 0);
|
||||
glVertex2f(15, 15);
|
||||
glVertex2f(0, 15);
|
||||
|
||||
glColor3f(.6, .6, .6);
|
||||
glVertex2f(2, 0);
|
||||
glVertex2f(15, 0);
|
||||
glVertex2f(15, 13);
|
||||
glVertex2f(2, 13);
|
||||
|
||||
glColor3fv(Color::bg);
|
||||
glVertex2f(2, 2);
|
||||
glVertex2f(13, 2);
|
||||
glVertex2f(13, 13);
|
||||
glVertex2f(2, 13);
|
||||
glEnd();
|
||||
} else {
|
||||
glBegin(GL_QUADS);
|
||||
glColor3f(.6, .6, .6);
|
||||
glVertex2f(0, 0);
|
||||
glVertex2f(15, 0);
|
||||
glVertex2f(15, 15);
|
||||
glVertex2f(0, 15);
|
||||
|
||||
glColor3fv(Color::bgShadow);
|
||||
glVertex2f(2, 0);
|
||||
glVertex2f(15, 0);
|
||||
glVertex2f(15, 13);
|
||||
glVertex2f(2, 13);
|
||||
|
||||
glColor3fv(Color::bg);
|
||||
glVertex2f(2, 2);
|
||||
glVertex2f(13, 2);
|
||||
glVertex2f(13, 13);
|
||||
glVertex2f(2, 13);
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
22
src/gui_toggle_button.h
Normal file
@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include "gui_widget.h"
|
||||
|
||||
namespace Gui {
|
||||
class ToggleButton : public Button {
|
||||
public:
|
||||
ToggleButton(void);
|
||||
virtual void Draw(void);
|
||||
virtual ~ToggleButton(void) {}
|
||||
virtual void GetSizeRequested(float& w, float& h);
|
||||
virtual void OnMouseDown(MouseButtonEvent* e);
|
||||
void SetPressed(bool s) { m_pressed = s; }
|
||||
bool GetPressed(void) { return m_pressed; }
|
||||
|
||||
sigc::signal<void, ToggleButton*> onSelect;
|
||||
sigc::signal<void, ToggleButton*> onDeselect;
|
||||
private:
|
||||
int m_pressed;
|
||||
};
|
||||
}
|
||||
|
24
src/gui_widget.cpp
Normal file
@ -0,0 +1,24 @@
|
||||
#include "gui.h"
|
||||
|
||||
namespace Gui {
|
||||
|
||||
Widget::Widget(void) {
|
||||
m_visible = false;
|
||||
m_eventMask = EVENT_NONE;
|
||||
}
|
||||
|
||||
void Widget::SetShortcut(SDLKey key, SDLMod mod) {
|
||||
m_shortcut.sym = key;
|
||||
m_shortcut.mod = mod;
|
||||
Screen::AddShortcutWidget(this);
|
||||
}
|
||||
|
||||
void Widget::OnPreShortcut(const SDL_keysym* sym) {
|
||||
int mod = sym->mod & 0xfff; /* Filters out numlock, capslock, which screws things up.. */
|
||||
if((sym->sym == m_shortcut.sym) && (mod == m_shortcut.mod)) {
|
||||
OnActivate();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
51
src/gui_widget.h
Normal file
@ -0,0 +1,51 @@
|
||||
#pragma once
|
||||
#include "gui_events.h"
|
||||
|
||||
namespace Gui {
|
||||
class Container;
|
||||
class Widget {
|
||||
public:
|
||||
Widget(void);
|
||||
virtual void Draw(void) = 0;
|
||||
virtual ~Widget(void) {}
|
||||
virtual void GetSizeRequested(float size[2]) = 0;
|
||||
void GetPosition(float pos[2]) { pos[0] = m_size.x; pos[1] = m_size.y; }
|
||||
void SetPosition(float x, float y) { m_size.x = x; m_size.y = y; }
|
||||
void GetSize(float size[2]) { size[0] = m_size.w; size[1] = m_size.h; }
|
||||
void SetSize(float w, float h) { m_size.w = w; m_size.h = h; };
|
||||
void SetShortcut(SDLKey key, SDLMod mod);
|
||||
virtual void Show(void) { m_visible = true; }
|
||||
virtual void Hide(void) { m_visible = false; }
|
||||
bool IsVisible(void) { return m_visible; }
|
||||
Container* GetParent(void) { return m_parent; }
|
||||
void SetParent(Container* p) { m_parent = p; }
|
||||
|
||||
virtual void OnMouseDown(MouseButtonEvent* e) {}
|
||||
virtual void OnMouseUp(MouseButtonEvent* e) {}
|
||||
virtual void OnActivate(void) {}
|
||||
/* Only to be called by Screen::OnKeyDown. */
|
||||
void OnPreShortcut(const SDL_keysym* sym);
|
||||
enum EventMask {
|
||||
EVENT_NONE = 0,
|
||||
EVENT_KEYDOWN = 1<<0,
|
||||
EVENT_KEYUP = 1<<1,
|
||||
EVENT_MOUSEDOWN = 1<<2,
|
||||
EVENT_MOUSEUP = 1<<3,
|
||||
EVENT_ALL = 0xffffffff
|
||||
};
|
||||
unsigned int GetEventMask(void) { return m_eventMask; }
|
||||
protected:
|
||||
unsigned int m_eventMask;
|
||||
struct {
|
||||
SDLKey sym;
|
||||
SDLMod mod;
|
||||
} m_shortcut;
|
||||
private:
|
||||
struct {
|
||||
float x,y,w,h;
|
||||
} m_size;
|
||||
bool m_visible;
|
||||
Container* m_parent;
|
||||
};
|
||||
}
|
||||
|
99
src/l3d.h
Normal file
@ -0,0 +1,99 @@
|
||||
#pragma once
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include "libs.h"
|
||||
#include "gui.h"
|
||||
#include "view.h"
|
||||
#include "mtrand.h"
|
||||
|
||||
class Player;
|
||||
class SectorView;
|
||||
class SystemView;
|
||||
class WorldView;
|
||||
class SystemInfoView;
|
||||
class ShipCpanel;
|
||||
class StarSystem;
|
||||
class SpaceStationView;
|
||||
|
||||
class IniConfig: private std::map<std::string, std::string> {
|
||||
public:
|
||||
IniConfig(const char* filename);
|
||||
int Int(const char* key) {
|
||||
return atoi((*this)[key].c_str());
|
||||
}
|
||||
float Float(const char* key) {
|
||||
float val;
|
||||
if(sscanf((*this)[key].c_str(), "%f", &val)==1) return val;
|
||||
else return 0;
|
||||
}
|
||||
std::string String(const char* key) {
|
||||
return (*this)[key];
|
||||
}
|
||||
};
|
||||
|
||||
/* Implementation is done in main.cpp, just to confuse you. :D */
|
||||
class L3D {
|
||||
public:
|
||||
static void Init(IniConfig& config);
|
||||
static void MainLoop(void);
|
||||
static void Quit(void);
|
||||
static float GetFrameTime(void) { return frameTime; }
|
||||
static double GetGameTime(void) { return gameTime; }
|
||||
static void SetTimeStep(float s) { timeStep = s; }
|
||||
static float GetTimeStep(void) { return timeStep; }
|
||||
static int GetScrWidth(void) { return scrWidth; }
|
||||
static int GetScrHeight(void) { return scrHeight; }
|
||||
static int GetScrAspect(void) { return scrAspect; }
|
||||
static int KeyState(SDLKey k) { return keyState[k]; }
|
||||
static int MouseButtonState(int button) { return mouseButton[button]; }
|
||||
static void GetMouseMotion(int motion[2]) {
|
||||
memcpy(motion, mouseMotion, sizeof(int)*2);
|
||||
}
|
||||
|
||||
static sigc::signal<void, SDL_keysym*> onKeyPress;
|
||||
static sigc::signal<void, SDL_keysym*> onKeyRelease;
|
||||
static sigc::signal<void, int, int, int> onMouseButtonUp;
|
||||
static sigc::signal<void, int, int, int> onMouseButtonDown;
|
||||
|
||||
static MTRand rng;
|
||||
|
||||
static void HyperspaceTo(StarSystem* destination);
|
||||
enum CamType { CAM_FRONT, CAM_REAR, CAM_EXTERNAL };
|
||||
enum MapView { MAP_NOMAP, MAP_SECTOR, MAP_SYSTEM };
|
||||
static void SetCamType(enum CamType);
|
||||
static void SetMapView(enum MapView);
|
||||
static enum CamType GetCamType(void) { return cam_type; }
|
||||
static enum MapView GetMapView(void) { return map_view; }
|
||||
static void SetView(View* v);
|
||||
static View* GetView(void) { return current_view; }
|
||||
static StarSystem* GetSelectedSystem(void);
|
||||
|
||||
static Player* player;
|
||||
static SectorView* sector_view;
|
||||
static SystemInfoView* system_info_view;
|
||||
static WorldView* world_view;
|
||||
static SpaceStationView* spaceStationView;
|
||||
|
||||
static ShipCpanel* cpan;
|
||||
|
||||
private:
|
||||
static void InitOpenGL(void);
|
||||
static void HandleEvents(void);
|
||||
|
||||
static View* current_view;
|
||||
static SystemView* system_view;
|
||||
|
||||
static double gameTime;
|
||||
static StarSystem* selected_system;
|
||||
static enum CamType cam_type;
|
||||
static enum MapView map_view;
|
||||
static float timeStep;
|
||||
static float frameTime;
|
||||
static int scrWidth, scrHeight;
|
||||
static float scrAspect;
|
||||
static SDL_Surface* scrSurface;
|
||||
static char keyState[SDLK_LAST];
|
||||
static char mouseButton[5];
|
||||
static int mouseMotion[2];
|
||||
};
|
||||
|
50
src/libs.h
Normal file
@ -0,0 +1,50 @@
|
||||
#pragma once
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <sigc++/sigc++.h>
|
||||
#include <SDL.h>
|
||||
#include <SDL_opengl.h>
|
||||
#include <SDL_image.h>
|
||||
#include <ode/ode.h>
|
||||
#include <float.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#define snprintf _snprintf
|
||||
#define alloca _alloca
|
||||
#endif
|
||||
|
||||
#include "vector3.h"
|
||||
#include "matrix4x4.h"
|
||||
#include "mtrand.h"
|
||||
|
||||
#include "date.h"
|
||||
|
||||
#ifndef dDOUBLE
|
||||
#error LibODE is not compiled with double-precision floating point. Please get/compile libode with \
|
||||
double-precision floating point.
|
||||
#endif
|
||||
|
||||
#define DEBUG
|
||||
|
||||
/*
|
||||
* Normal use:
|
||||
* foreach(container, iter) { do_something(*iter); }
|
||||
*
|
||||
* When removing items:
|
||||
* foreach(container, iter) {
|
||||
* if(*iter == some_value) {
|
||||
* iter = container.erase(iter); // Assign not necessary for maps.
|
||||
* --iter;
|
||||
* continue;
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
#define foreach(_collection,_iterator) \
|
||||
for(__typeof__ (_collection.end()) _iterator = (collection).begin (); \
|
||||
_iterator 1= (_collection).end(); ++(_iterator));
|
||||
|
||||
#define MIN(x,y) ((x)<(y)?(x):(y))
|
||||
#define MAX(x,y) ((x)>(y)?(x):(y))
|
||||
#define CLAMP(a, min, max) (((a) > (max)) ? (max) : (((a) < (min)) ? (min) : (a)))
|
||||
|
362
src/main.cpp
Normal file
@ -0,0 +1,362 @@
|
||||
#include "libs.h"
|
||||
#include "l3d.h"
|
||||
#include "gui.h"
|
||||
#include "glfreetype.h"
|
||||
#include "objimport.h"
|
||||
#include "player.h"
|
||||
#include "space.h"
|
||||
#include "planet.h"
|
||||
#include "star.h"
|
||||
#include "frame.h"
|
||||
#include "ship_cpanel.h"
|
||||
#include "sector_view.h"
|
||||
#include "system_view.h"
|
||||
#include "system_info_view.h"
|
||||
#include "world_view.h"
|
||||
#include "star_system.h"
|
||||
#include "space_station.h"
|
||||
#include "space_station_view.h"
|
||||
|
||||
float L3D::timeStep = 1.0f;
|
||||
int L3D::scrWidth;
|
||||
int L3D::scrHeight;
|
||||
float L3D::scrAspect;
|
||||
SDL_Surface* L3D::scrSurface;
|
||||
sigc::signal<void, SDL_keysym*> L3D::onKeyPress;
|
||||
sigc::signal<void, SDL_keysym*> L3D::onKeyRelease;
|
||||
sigc::signal<void, int, int, int> L3D::onMouseButtonUp;
|
||||
sigc::signal<void, int, int, int> L3D::onMouseButtonDown;
|
||||
char L3D::keyState[SDLK_LAST];
|
||||
char L3D::mouseButton[5];
|
||||
int L3D::mouseMotion[2];
|
||||
enum L3D::CamType L3D::cam_type;
|
||||
enum L3D::MapView L3D::map_view;
|
||||
Player* L3D::player;
|
||||
View* L3D::current_view;
|
||||
WorldView* L3D::world_view;
|
||||
SpaceStationView* L3D::spaceStationView;
|
||||
SectorView* L3D::sector_view;
|
||||
SystemView* L3D::system_view;
|
||||
SystemInfoView* L3D::system_info_view;
|
||||
ShipCpanel* L3D::cpan;
|
||||
StarSystem* L3D::selected_system;
|
||||
MTRand L3D::rng;
|
||||
double L3D::gameTime;
|
||||
float L3D::frameTime;
|
||||
|
||||
void L3D::Init(IniConfig& config) {
|
||||
int width = config.Int("ScrWidth");
|
||||
int height = config.Int("ScrHeight");
|
||||
const SDL_VideoInfo* info = NULL;
|
||||
if(SDL_Init(SDL_INIT_VIDEO) < 0) {
|
||||
fprintf(stderr, "Video initialization failed: %s\n", SDL_GetError());
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
info = SDL_GetVideoInfo();
|
||||
|
||||
switch(config.Int("ScrDepth")) {
|
||||
case 16:
|
||||
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
|
||||
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE,6);
|
||||
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
|
||||
break;
|
||||
case 32:
|
||||
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
|
||||
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE,8);
|
||||
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Fatal error: Invalid screen depth in config.ini.\n");
|
||||
L3D::Quit();
|
||||
}
|
||||
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
|
||||
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
||||
|
||||
Uint32 flags = SDL_OPENGL;
|
||||
if(config.Int("StartFullscreen")) flags |= SDL_FULLSCREEN;
|
||||
|
||||
if((L3D::scrSurface = SDL_SetVideoMode(width, height, info->vfmt->BitsPerPixel, flags)) == 0) {
|
||||
fprintf(stderr, "Video mode set failed: %s\n", SDL_GetError());
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
L3D::scrWidth = width;
|
||||
L3D::scrHeight = height;
|
||||
L3D::scrAspect = width / (float)height;
|
||||
|
||||
InitOpenGL();
|
||||
|
||||
dInitODE();
|
||||
GLFTInit();
|
||||
Space::Init();
|
||||
}
|
||||
|
||||
void L3D::InitOpenGL() {
|
||||
glShadeModel(GL_SMOOTH);
|
||||
glCullFace(GL_BACK);
|
||||
glFrontFace(GL_CCW);
|
||||
glEnable(GL_CULL_FACE);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnable(GL_LIGHTING);
|
||||
glEnable(GL_LIGHT0);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
glClearColor(0, 0, 0, 0);
|
||||
glViewport(0, 0, scrWidth, scrHeight);
|
||||
}
|
||||
|
||||
void L3D::Quit(void) {
|
||||
SDL_Quit();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void L3D::SetCamType(enum CamType c) {
|
||||
cam_type = c;
|
||||
map_view = MAP_NOMAP;
|
||||
SetView(world_view);
|
||||
}
|
||||
|
||||
void L3D::SetMapView(enum MapView v) {
|
||||
map_view = v;
|
||||
if(v == MAP_SECTOR)
|
||||
SetView(sector_view);
|
||||
else
|
||||
SetView(system_view);
|
||||
}
|
||||
|
||||
void L3D::SetView(View* v) {
|
||||
if(current_view) current_view->HideAll();
|
||||
current_view = v;
|
||||
current_view->ShowAll();
|
||||
}
|
||||
|
||||
void L3D::HandleEvents(void) {
|
||||
SDL_Event event;
|
||||
|
||||
L3D::mouseMotion[0] = L3D::mouseMotion[1] = 0;
|
||||
while(SDL_PollEvent(&event)) {
|
||||
Gui::HandleSDLEvent(&event);
|
||||
switch(event.type) {
|
||||
case SDL_KEYDOWN:
|
||||
if(event.key.keysym.sym == SDLK_q) L3D::Quit();
|
||||
if(event.key.keysym.sym == SDLK_F11) SDL_WM_ToggleFullScreen(L3D::scrSurface);
|
||||
|
||||
L3D::keyState[event.key.keysym.sym] = 1;
|
||||
L3D::onKeyPress.emit(&event.key.keysym);
|
||||
break;
|
||||
case SDL_KEYUP:
|
||||
L3D::keyState[event.key.keysym.sym] = 0;
|
||||
L3D::onKeyRelease.emit(&event.key.keysym);
|
||||
break;
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
L3D::mouseButton[event.button.button] = 1;
|
||||
L3D::onMouseButtonDown.emit(event.button.button,
|
||||
event.button.x, event.button.y);
|
||||
break;
|
||||
case SDL_MOUSEBUTTONUP:
|
||||
L3D::mouseButton[event.button.button] = 1;
|
||||
L3D::onMouseButtonUp.emit(event.button.button,
|
||||
event.button.x, event.button.y);
|
||||
break;
|
||||
case SDL_MOUSEMOTION:
|
||||
SDL_GetRelativeMouseState(&L3D::mouseMotion[0], &L3D::mouseMotion[1]);
|
||||
break;
|
||||
case SDL_QUIT:
|
||||
L3D::Quit();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void L3D::MainLoop(void) {
|
||||
Frame* earth_frame = new Frame(Space::GetRootFrame(), "Earth");
|
||||
earth_frame->SetPosition(vector3d(149598000000.0, 0, 0));
|
||||
earth_frame->SetRadius(2*380000000); /* 2 moon orbital radii. */
|
||||
|
||||
player = new Player();
|
||||
player->SetLabel("Me");
|
||||
player->SetFrame(earth_frame);
|
||||
player->SetPosition(vector3d(100, 0, 0));
|
||||
Space::AddBody(player);
|
||||
|
||||
for(int i = 0; i < 4; i++) {
|
||||
Ship* body = new Ship();
|
||||
char buf[64];
|
||||
snprintf(buf, sizeof(buf), "X%c-0%02d", "A"+i, i);
|
||||
body->SetLabel(buf);
|
||||
body->SetFrame(earth_frame);
|
||||
body->SetPosition(vector3d(i*200, 0, -200));
|
||||
Space::AddBody(body);
|
||||
}
|
||||
|
||||
{
|
||||
SpaceStation* body = new SpaceStation();
|
||||
body->SetLabel("Some Back Country Joint");
|
||||
body->SetFrame(earth_frame);
|
||||
body->SetPosition(vector3d(0, 0, 6000));
|
||||
Space::AddBody(body);
|
||||
}
|
||||
|
||||
Planet* planet = new Planet(StarSystem::SBody::SUBTYPE_PLANET_INDIGENOUS_LIFE);
|
||||
planet->SetLabel("Earth");
|
||||
planet->SetPosition(vector3d(0, 0, -8000000.0));
|
||||
planet->SetFrame(earth_frame);
|
||||
Space::AddBody(planet);
|
||||
|
||||
Frame* moon_frame = new Frame(earth_frame, "Moon");
|
||||
moon_frame->SetPosition(vector3d(0, -380000000.0, 0));
|
||||
moon_frame->SetRadius(10*1738140.0); /* 10 moon radii. */
|
||||
Planet* moon = new Planet(StarSystem::SBody::SUBTYPE_PLANET_DWARF);
|
||||
moon->SetLabel("Moon");
|
||||
moon->SetPosition(vector3d(0, 0, 0));
|
||||
moon->SetRadius(1738140.0);
|
||||
moon->SetFrame(moon_frame);
|
||||
Space::AddBody(moon);
|
||||
|
||||
Star* sol = new Star(StarSystem::SBody::SUBTYPE_STAR_G);
|
||||
sol->SetLabel("Sol");
|
||||
sol->SetRadius(6.955e8);
|
||||
sol->SetPosition(vector3d(0, 0, 0));
|
||||
sol->SetFrame(Space::GetRootFrame());
|
||||
Space::AddBody(sol);
|
||||
|
||||
Gui::Init(scrWidth, scrHeight, 640, 480);
|
||||
|
||||
cpan = new ShipCpanel();
|
||||
cpan->ShowAll();
|
||||
|
||||
sector_view = new SectorView();
|
||||
system_view = new SystemView();
|
||||
system_info_view = new SystemInfoView();
|
||||
world_view = new WorldView();
|
||||
spaceStationView = new SpaceStationView();
|
||||
|
||||
SetView(world_view);
|
||||
|
||||
GLUquadric* quad = gluNewQuadric();
|
||||
gluQuadricOrientation(quad, GLU_INSIDE);
|
||||
|
||||
Uint32 last_stats = SDL_GetTicks();
|
||||
int frame_stat = 0;
|
||||
char fps_readout[32];
|
||||
Uint32 time_before_frame = SDL_GetTicks();
|
||||
|
||||
for(;;) {
|
||||
frame_stat++;
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
glLoadIdentity();
|
||||
|
||||
current_view->Draw3D();
|
||||
/*
|
||||
* TODO: HandleEvents at the moment must be after view->Draw3D and before
|
||||
* Gui::Draw so that labels drawn to screen can have mouse events correctly
|
||||
* detected. Gui::Draw wipes memory of label positions.
|
||||
*/
|
||||
L3D::HandleEvents();
|
||||
/* Hide cursor for ship control. */
|
||||
if(L3D::MouseButtonState(3)) {
|
||||
SDL_ShowCursor(0);
|
||||
SDL_WM_GrabInput(SDL_GRAB_ON);
|
||||
} else {
|
||||
SDL_ShowCursor(1);
|
||||
SDL_WM_GrabInput(SDL_GRAB_OFF);
|
||||
}
|
||||
|
||||
Gui::Draw();
|
||||
#ifdef DEBUG
|
||||
{
|
||||
Gui::Screen::EnterOrtho();
|
||||
glColor3f(1, 1, 1);
|
||||
glTranslatef(0, Gui::Screen::GetHeight()-20, 0);
|
||||
Gui::Screen::RenderString(fps_readout);
|
||||
Gui::Screen::LeaveOrtho();
|
||||
}
|
||||
#endif
|
||||
|
||||
glFlush();
|
||||
SDL_GL_SwapBuffers();
|
||||
//if(glGetError()) printf("GL: %s\n", gluErrorString(glGetError()));
|
||||
|
||||
L3D::frameTime = 0.001*(SDL_GetTicks() - time_before_frame);
|
||||
float step = L3D::timeStep * L3D::frameTime;
|
||||
|
||||
time_before_frame = SDL_GetTicks();
|
||||
/* Game state update stuff. */
|
||||
if(step) {
|
||||
Space::TimeStep(step);
|
||||
gameTime += step;
|
||||
}
|
||||
current_view->Update();
|
||||
|
||||
if(SDL_GetTicks() - last_stats > 1000) {
|
||||
snprintf(fps_readout, sizeof(fps_readout), "%d fps", frame_stat);
|
||||
frame_stat = 0;
|
||||
last_stats += 1000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StarSystem* L3D::GetSelectedSystem(void) {
|
||||
int sector_x, sector_y, system_idx;
|
||||
L3D::sector_view->GetSelectedSystem(§or_x, §or_y, &system_idx);
|
||||
if(system_idx == -1) {
|
||||
selected_system = 0;
|
||||
return NULL;
|
||||
}
|
||||
if(selected_system) {
|
||||
if(!selected_system->IsSystem(sector_x, sector_y, system_idx)) {
|
||||
delete selected_system;
|
||||
selected_system = 0;
|
||||
}
|
||||
}
|
||||
if(!selected_system) {
|
||||
selected_system = new StarSystem(sector_x, sector_y, system_idx);
|
||||
}
|
||||
return selected_system;
|
||||
}
|
||||
|
||||
void L3D::HyperspaceTo(StarSystem* dest) {
|
||||
Space::Clear();
|
||||
Space::BuildSystem(dest);
|
||||
float ang = rng(M_PI);
|
||||
L3D::player->SetPosition(vector3d(sin(ang)*8*AU, cos(ang)*8*AU, 0));
|
||||
}
|
||||
|
||||
IniConfig::IniConfig(const char* filename) {
|
||||
FILE* f = fopen(filename, "r");
|
||||
if(!f) {
|
||||
fprintf(stderr, "Could not open '%s'.\n", filename);
|
||||
L3D::Quit();
|
||||
}
|
||||
char buf[1024];
|
||||
while(fgets(buf, sizeof(buf), f)) {
|
||||
if(buf[0] == '#') continue;
|
||||
char* sep = strchr(buf, '=');
|
||||
char* kend = sep;
|
||||
if(!sep) continue;
|
||||
*sep = 0;
|
||||
/* Strip whitespace. */
|
||||
while(isspace(*(--kend))) *kend = 0;
|
||||
while(isspace(*(++sep))) *sep = 0;
|
||||
/* Snip \r, \n. */
|
||||
char* vend = sep;
|
||||
while(*(++vend)) if((*vend == '\r') || (*vend == '\n')) { *vend = 0; break; }
|
||||
std::string key = std::string(buf);
|
||||
std::string val = std::string(sep);
|
||||
(*this)[key] = val;
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
printf("Lephisto3D's super high tech demo!\n");
|
||||
|
||||
IniConfig cfg("config.ini");
|
||||
|
||||
L3D::Init(cfg);
|
||||
L3D::MainLoop();
|
||||
return 0;
|
||||
}
|
||||
|
226
src/matrix4x4.h
Normal file
@ -0,0 +1,226 @@
|
||||
#pragma once
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include "vector3.h"
|
||||
|
||||
template <typename T>
|
||||
|
||||
class matrix4x4 {
|
||||
private:
|
||||
T cell[16];
|
||||
public:
|
||||
matrix4x4(void) { }
|
||||
matrix4x4(T val) {
|
||||
cell[0] = cell[1] = cell[2] = cell[3] = cell[4] = cell[5] = cell[6] =
|
||||
cell[7] = cell[8] = cell[9] = cell[10] = cell[11] = cell[12] = cell[13] =
|
||||
cell[14] = cell[15] = val;
|
||||
}
|
||||
|
||||
/* Row-major 4x3 matrix. */
|
||||
void LoadFromOdeMatrix(const T* r) {
|
||||
cell[ 0] = r[ 0];cell[ 1] = r[ 4]; cell[ 2] = r[ 8];cell[ 3] = 0;
|
||||
cell[ 4] = r[ 1];cell[ 5] = r[ 5]; cell[ 6] = r[ 9];cell[ 7] = 0;
|
||||
cell[ 8] = r[ 2];cell[ 9] = r[ 6]; cell[10] = r[10];cell[11] = 0;
|
||||
cell[12] = 0; cell[13] = 0; cell[14] = 0; cell[15] = 1;
|
||||
}
|
||||
|
||||
/* Row-major 3x3 matrix. */
|
||||
void LoadFrom3x3Matrix(const T* r) {
|
||||
cell[ 0] = r[ 0]; cell[ 4] = r[ 1]; cell[ 8] = r[ 2]; cell[12] = 0;
|
||||
cell[ 1] = r[ 3]; cell[ 5] = r[ 4]; cell[ 9] = r[ 5]; cell[13] = 0;
|
||||
cell[ 2] = r[ 6]; cell[ 6] = r[ 7]; cell[10] = r[ 8]; cell[14] = 0;
|
||||
cell[ 3] = 0; cell[ 7] = 0; cell[11] = 0; cell[15] = 1;
|
||||
}
|
||||
|
||||
/* Row-major. */
|
||||
void SaveTo3x3Matrix(T* r) {
|
||||
r[0] = cell[0]; r[1] = cell[4]; r[2] = cell[8];
|
||||
r[3] = cell[1]; r[4] = cell[5]; r[5] = cell[9];
|
||||
r[6] = cell[2]; r[7] = cell[6]; r[8] = cell[10];
|
||||
}
|
||||
|
||||
void SaveToOdeMatrix(T r[12]) {
|
||||
r[0] = cell[0]; r[1] = cell[4]; r[ 2] = cell[ 8]; r[ 3] = 0;
|
||||
r[4] = cell[1]; r[5] = cell[5]; r[ 6] = cell[ 9]; r[ 7] = 0;
|
||||
r[8] = cell[2]; r[9] = cell[6]; r[10] = cell[10]; r[11] = 0;
|
||||
}
|
||||
|
||||
static matrix4x4 Identity(void) {
|
||||
matrix4x4 m = matrix4x4(0);
|
||||
m.cell[0] = m.cell[5] = m.cell[10] = m.cell[15] = 1.0f;
|
||||
return m;
|
||||
}
|
||||
|
||||
static matrix4x4 ScaleMatrix(T x, T y, T z) {
|
||||
matrix4x4 m;
|
||||
m[ 0] = x; m[ 1] = m[ 2] = m[ 3] = 0;
|
||||
m[ 5] = y; m[ 4] = m[ 6] = m[ 7] = 0;
|
||||
m[10] = z; m[ 8] = m[ 9] = m[11] = 0;
|
||||
m[12] = m[13] = m[14] = 0; m[15] = 1;
|
||||
return m;
|
||||
}
|
||||
|
||||
void RotateZ(T radians) { *this = (*this) * RotateZMatrix(radians); }
|
||||
void RotateY(T radians) { *this = (*this) * RotateYMatrix(radians); }
|
||||
void rotateX(T radians) { *this = (*this) * RotateXMatrix(radians); }
|
||||
|
||||
static matrix4x4 RotateXMatrix(T radians) {
|
||||
matrix4x4 m;
|
||||
T cos_r = cosf(radians);
|
||||
T sin_r = sinf(radians);
|
||||
m[ 0] = 1.0f;
|
||||
m[ 1] = 0;
|
||||
m[ 2] = 0;
|
||||
m[ 3] = 0;
|
||||
|
||||
m[ 4] = 0;
|
||||
m[ 5] = cos_r;
|
||||
m[ 6] = -sin_r;
|
||||
m[ 7] = 0;
|
||||
|
||||
m[ 8] = 0;
|
||||
m[ 9] = sin_r;
|
||||
m[10] = cos_r;
|
||||
m[11] = 0;
|
||||
|
||||
m[12] = 0;
|
||||
m[13] = 0;
|
||||
m[14] = 0;
|
||||
m[15] = 1.0f;
|
||||
return m;
|
||||
}
|
||||
|
||||
static matrix4x4 RotateYMatrix(T radians) {
|
||||
matrix4x4 m;
|
||||
T cos_r = cosf(radians);
|
||||
T sin_r = sinf(radians);
|
||||
m[ 0] = cos_r;
|
||||
m[ 1] = 0;
|
||||
m[ 2] = sin_r;
|
||||
m[ 3] = 0;
|
||||
|
||||
m[ 4] = 0;
|
||||
m[ 5] = 1;
|
||||
m[ 6] = 0;
|
||||
m[ 7] = 0;
|
||||
|
||||
m[ 8] = -sin_r;
|
||||
m[ 9] = 0;
|
||||
m[10] = cos_r;
|
||||
m[11] = 0;
|
||||
|
||||
m[12] = 0;
|
||||
m[13] = 0;
|
||||
m[14] = 0;
|
||||
m[15] = 1.0f;
|
||||
return m;
|
||||
}
|
||||
|
||||
static matrix4x4 RotateZMatrix(T radians) {
|
||||
matrix4x4 m;
|
||||
T cos_r = cosf(radians);
|
||||
T sin_r = sinf(radians);
|
||||
m[ 0] = cos_r;
|
||||
m[ 1] = -sin_r;
|
||||
m[ 2] = 0;
|
||||
m[ 3] = 0;
|
||||
|
||||
m[ 4] = sin_r;
|
||||
m[ 5] = cos_r;
|
||||
m[ 6] = 0;
|
||||
m[ 7] = 0;
|
||||
|
||||
m[ 8] = 0;
|
||||
m[ 9] = 0;
|
||||
m[10] = 1.9f;
|
||||
m[11] = 0;
|
||||
|
||||
m[12] = 0;
|
||||
m[13] = 0;
|
||||
m[14] = 0;
|
||||
m[15] = 1.0f;
|
||||
return m;
|
||||
}
|
||||
|
||||
T& operator[] (const int i) { return cell[i]; }
|
||||
friend matrix4x4 operator+(const matrix4x4& a, const matrix4x4& b) {
|
||||
matrix4x4 m;
|
||||
for(int i = 0; i < 16; i++) m.cell[i] = a.cell[i] + b.cell[i];
|
||||
return m;
|
||||
}
|
||||
friend matrix4x4 operator-(const matrix4x4& a, const matrix4x4& b) {
|
||||
matrix4x4 m;
|
||||
for(int i = 0; i < 16; i++) m.cell[i] = a.cell[i] - b.cell[i];
|
||||
return m;
|
||||
}
|
||||
|
||||
friend matrix4x4 operator*(const matrix4x4& a, const matrix4x4& b) {
|
||||
matrix4x4 m;
|
||||
m.cell[ 0] = a.cell[0]*b.cell[ 0]+a.cell[4]*b.cell[ 1]+a.cell[ 8]*b.cell[ 2]+a.cell[12]*b.cell[ 3];
|
||||
m.cell[ 1] = a.cell[1]*b.cell[ 0]+a.cell[5]*b.cell[ 1]+a.cell[ 9]*b.cell[ 2]+a.cell[13]*b.cell[ 3];
|
||||
m.cell[ 2] = a.cell[2]*b.cell[ 0]+a.cell[6]*b.cell[ 1]+a.cell[10]*b.cell[ 2]+a.cell[14]*b.cell[ 3];
|
||||
m.cell[ 3] = a.cell[3]*b.cell[ 0]+a.cell[7]*b.cell[ 1]+a.cell[11]*b.cell[ 2]+a.cell[15]*b.cell[ 3];
|
||||
m.cell[ 4] = a.cell[0]*b.cell[ 4]+a.cell[4]*b.cell[ 5]+a.cell[ 8]*b.cell[ 6]+a.cell[12]*b.cell[ 7];
|
||||
m.cell[ 5] = a.cell[1]*b.cell[ 4]+a.cell[5]*b.cell[ 5]+a.cell[ 9]*b.cell[ 6]+a.cell[13]*b.cell[ 7];
|
||||
m.cell[ 6] = a.cell[2]*b.cell[ 4]+a.cell[6]*b.cell[ 5]+a.cell[10]*b.cell[ 6]+a.cell[14]*b.cell[ 7];
|
||||
m.cell[ 7] = a.cell[3]*b.cell[ 4]+a.cell[7]*b.cell[ 5]+a.cell[11]*b.cell[ 6]+a.cell[15]*b.cell[ 7];
|
||||
m.cell[ 8] = a.cell[0]*b.cell[ 8]+a.cell[4]*b.cell[ 9]+a.cell[ 8]*b.cell[10]+a.cell[12]*b.cell[11];
|
||||
m.cell[ 9] = a.cell[1]*b.cell[ 8]+a.cell[5]*b.cell[ 9]+a.cell[ 9]*b.cell[10]+a.cell[13]*b.cell[11];
|
||||
m.cell[10] = a.cell[2]*b.cell[ 8]+a.cell[6]*b.cell[ 9]+a.cell[10]*b.cell[10]+a.cell[14]*b.cell[11];
|
||||
m.cell[11] = a.cell[3]*b.cell[ 8]+a.cell[7]*b.cell[ 9]+a.cell[11]*b.cell[10]+a.cell[15]*b.cell[11];
|
||||
m.cell[12] = a.cell[0]*b.cell[12]+a.cell[4]*b.cell[13]+a.cell[ 8]*b.cell[14]+a.cell[12]*b.cell[15];
|
||||
m.cell[13] = a.cell[1]*b.cell[12]+a.cell[5]*b.cell[13]+a.cell[ 9]*b.cell[14]+a.cell[13]*b.cell[15];
|
||||
m.cell[14] = a.cell[2]*b.cell[12]+a.cell[6]*b.cell[13]+a.cell[10]*b.cell[14]+a.cell[14]*b.cell[15];
|
||||
m.cell[15] = a.cell[3]*b.cell[12]+a.cell[7]*b.cell[13]+a.cell[11]*b.cell[14]+a.cell[15]*b.cell[15];
|
||||
return m;
|
||||
}
|
||||
|
||||
friend vector3<T> operator*(const matrix4x4& a, const vector3<T> &v) {
|
||||
vector3<T> out;
|
||||
out.x = a.cell[0]*v.x + a.cell[4]*v.y + a.cell[ 8]*v.z + a.cell[12];
|
||||
out.y = a.cell[1]*v.x + a.cell[5]*v.y + a.cell[ 9]*v.z + a.cell[13];
|
||||
out.z = a.cell[2]*v.x + a.cell[6]*v.y + a.cell[10]*v.z + a.cell[14];
|
||||
return out;
|
||||
}
|
||||
|
||||
vector3<T> ApplyRotationOnly(const vector3<T>& v) const {
|
||||
vector3<T> out;
|
||||
out.x = cell[0]*v.x + cell[4]*v.y + cell[ 8]*v.z;
|
||||
out.y = cell[1]*v.x + cell[5]*v.y + cell[ 9]*v.z;
|
||||
out.z = cell[2]*v.x + cell[6]*v.y + cell[10]*v.z;
|
||||
return out;
|
||||
}
|
||||
|
||||
void Translatef(T x, T y, T z) {
|
||||
matrix4x4 m = Identity();
|
||||
m[12] = x;
|
||||
m[13] = y;
|
||||
m[14] = z;
|
||||
*this = (*this) * m;
|
||||
}
|
||||
|
||||
matrix4x4 InverseOf(void) const {
|
||||
matrix4x4 m;
|
||||
/* This only works for matrices containing only rotation and transform. */
|
||||
m[ 0] = cell[0]; m[1] = cell[4]; m[ 2] = cell[ 8];
|
||||
m[ 4] = cell[1]; m[5] = cell[5]; m[ 6] = cell[ 9];
|
||||
m[ 8] = cell[2]; m[9] = cell[6]; m[10] = cell[10];
|
||||
m[12] = -(cell[0]*cell[12] + cell[1]*cell[13] + cell[ 2]*cell[14]);
|
||||
m[13] = -(cell[4]*cell[12] + cell[5]*cell[13] + cell[ 6]*cell[14]);
|
||||
m[14] = -(cell[8]*cell[12] + cell[9]*cell[13] + cell[10]*cell[14]);
|
||||
m[ 3] = m[7] = m[11] = 0;
|
||||
m[15] = 1.0f;
|
||||
return m;
|
||||
}
|
||||
|
||||
void Print(void) const {
|
||||
for(int i = 0; i < 4; i++) {
|
||||
printf("%.2f %.2f %.2f %.2f\n", cell[i], cell[i+4], cell[i+8], cell[i+12]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
};
|
||||
|
||||
typedef matrix4x4<float>matrix4x4f;
|
||||
typedef matrix4x4<double>matrix4x4d;
|
||||
|