#ifndef _LOGO_H
#define _LOGO_H
#include <gtkmm.h>
#include <gtkglmm.h>
namespace Logo
{
class Scene;
class View : public SigC::Object
{
friend class Scene;
public:
static const float NEAR_CLIP;
static const float FAR_CLIP;
static const float INIT_POS_X;
static const float INIT_POS_Y;
static const float INIT_POS_Z;
static const float INIT_AXIS_X;
static const float INIT_AXIS_Y;
static const float INIT_AXIS_Z;
static const float INIT_ANGLE;
static const float INIT_SCALE;
static const float SCALE_MAX;
static const float SCALE_MIN;
public:
View();
virtual ~View();
public:
void frustum(int w, int h);
void xform();
void reset();
void set_pos(float x, float y, float z)
{ m_Pos[0] = x; m_Pos[1] = y; m_Pos[2] = z; }
void set_quat(float q0, float q1, float q2, float q3)
{ m_Quat[0] = q0; m_Quat[1] = q1; m_Quat[2] = q2; m_Quat[3] = q3; }
void set_scale(float scale)
{ m_Scale = scale; }
protected:
virtual bool on_button_press_event(GdkEventButton* event, Scene* scene);
virtual bool on_motion_notify_event(GdkEventMotion* event, Scene* scene);
private:
float m_Pos[3];
float m_Quat[4];
float m_Scale;
float m_BeginX;
float m_BeginY;
};
class Model
{
friend class Scene;
public:
enum DisplayList {
CUBE = 1,
G_FORWARD,
G_BACKWARD,
T_FORWARD,
T_BACKWARD,
K_FORWARD,
K_BACKWARD
};
static const float MAT_SPECULAR[4];
static const float MAT_SHININESS[1];
static const float MAT_BLACK[4];
static const float MAT_RED[4];
static const float MAT_GREEN[4];
static const float MAT_BLUE[4];
static const unsigned int DEFAULT_ROT_COUNT;
public:
explicit Model(unsigned int rot_count = DEFAULT_ROT_COUNT,
bool enable_anim = true);
virtual ~Model();
private:
void init_gl();
public:
void draw();
void enable_anim()
{ m_EnableAnim = true; }
void disable_anim()
{ m_EnableAnim = false; }
bool anim_is_enabled() const
{ return m_EnableAnim; }
void reset_anim();
void set_pos(float x, float y, float z)
{ m_Pos[0] = x; m_Pos[1] = y; m_Pos[2] = z; }
void set_quat(float q0, float q1, float q2, float q3)
{ m_Quat[0] = q0; m_Quat[1] = q1; m_Quat[2] = q2; m_Quat[3] = q3; }
private:
struct RotMode
{
float *axis;
float sign;
};
static const RotMode ROT_MODE[];
private:
unsigned int m_RotCount;
bool m_EnableAnim;
unsigned int m_Mode;
unsigned int m_Counter;
float m_Pos[3];
float m_Quat[4];
};
class Scene : public Gtk::GL::DrawingArea
{
friend class View;
friend class Model;
public:
static const unsigned int TIMEOUT_INTERVAL;
static const float CLEAR_COLOR[4];
static const float CLEAR_DEPTH;
static const float LIGHT0_POSITION[4];
static const float LIGHT0_DIFFUSE[4];
static const float LIGHT0_SPECULAR[4];
public:
explicit Scene(unsigned int rot_count = Model::DEFAULT_ROT_COUNT,
bool enable_anim = true);
virtual ~Scene();
protected:
virtual void on_realize();
virtual bool on_configure_event(GdkEventConfigure* event);
virtual bool on_expose_event(GdkEventExpose* event);
virtual bool on_button_press_event(GdkEventButton* event);
virtual bool on_map_event(GdkEventAny* event);
virtual bool on_unmap_event(GdkEventAny* event);
virtual bool on_visibility_notify_event(GdkEventVisibility* event);
virtual bool on_timeout();
public:
void invalidate() {
GtkAllocation allocation = get_allocation();
get_window()->invalidate_rect(Gdk::Rectangle(&allocation), false);
}
void update()
{ get_window()->process_updates(false); }
protected:
SigC::Connection m_ConnectionTimeout;
void timeout_add();
void timeout_remove();
public:
bool anim_is_enabled() const
{ return m_Model.anim_is_enabled(); }
void toggle_anim();
void init_anim();
protected:
Gtk::Menu* create_popup_menu();
protected:
Gtk::Menu* m_Menu;
protected:
View m_View;
Model m_Model;
};
class Application : public Gtk::Window
{
public:
static const Glib::ustring APP_NAME;
public:
explicit Application(unsigned int rot_count = Model::DEFAULT_ROT_COUNT,
bool enable_anim = true);
virtual ~Application();
protected:
virtual void on_button_quit_clicked();
virtual bool on_key_press_event(GdkEventKey* event);
protected:
Gtk::VBox m_VBox;
Scene m_Scene;
Gtk::Button m_ButtonQuit;
};
}
#endif // _LOGO_H