|
|
|
|
@ -53,6 +53,11 @@ MAGNUM_GLUTAPPLICATION_MAIN(MyApplication)
|
|
|
|
|
*/ |
|
|
|
|
class GlutApplication { |
|
|
|
|
public: |
|
|
|
|
class InputEvent; |
|
|
|
|
class KeyEvent; |
|
|
|
|
class MouseEvent; |
|
|
|
|
class MouseMoveEvent; |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Constructor |
|
|
|
|
* @param argc Count of arguments of `main()` function |
|
|
|
|
@ -79,9 +84,9 @@ class GlutApplication {
|
|
|
|
|
/**
|
|
|
|
|
* @brief Viewport event |
|
|
|
|
* |
|
|
|
|
* Called when viewport size changes. You should pass the new size to |
|
|
|
|
* Framebuffer::setViewport() (and SceneGraph::AbstractCamera::setViewport(), |
|
|
|
|
* if using scene graph). |
|
|
|
|
* Called when window size changes. You should pass the new size to |
|
|
|
|
* DefaultFramebuffer::setViewport() and possibly elsewhere (cameras, |
|
|
|
|
* other framebuffers...). |
|
|
|
|
*/ |
|
|
|
|
virtual void viewportEvent(const Vector2i& size) = 0; |
|
|
|
|
|
|
|
|
|
@ -119,63 +124,18 @@ class GlutApplication {
|
|
|
|
|
|
|
|
|
|
/** @{ @name Keyboard handling */ |
|
|
|
|
|
|
|
|
|
public: |
|
|
|
|
/**
|
|
|
|
|
* @brief Key |
|
|
|
|
* |
|
|
|
|
* @see keyPressEvent() |
|
|
|
|
*/ |
|
|
|
|
enum class Key: int { |
|
|
|
|
Up = GLUT_KEY_UP, /**< Up arrow */ |
|
|
|
|
Down = GLUT_KEY_DOWN, /**< Down arrow */ |
|
|
|
|
Left = GLUT_KEY_LEFT, /**< Left arrow */ |
|
|
|
|
Right = GLUT_KEY_RIGHT, /**< Right arrow */ |
|
|
|
|
F1 = GLUT_KEY_F1, /**< F1 */ |
|
|
|
|
F2 = GLUT_KEY_F2, /**< F2 */ |
|
|
|
|
F3 = GLUT_KEY_F3, /**< F3 */ |
|
|
|
|
F4 = GLUT_KEY_F4, /**< F4 */ |
|
|
|
|
F5 = GLUT_KEY_F5, /**< F5 */ |
|
|
|
|
F6 = GLUT_KEY_F6, /**< F6 */ |
|
|
|
|
F7 = GLUT_KEY_F7, /**< F7 */ |
|
|
|
|
F8 = GLUT_KEY_F8, /**< F8 */ |
|
|
|
|
F9 = GLUT_KEY_F9, /**< F9 */ |
|
|
|
|
F10 = GLUT_KEY_F10, /**< F10 */ |
|
|
|
|
F11 = GLUT_KEY_F11, /**< F11 */ |
|
|
|
|
F12 = GLUT_KEY_F12, /**< F12 */ |
|
|
|
|
Home = GLUT_KEY_HOME, /**< Home */ |
|
|
|
|
End = GLUT_KEY_END, /**< End */ |
|
|
|
|
PageUp = GLUT_KEY_PAGE_UP, /**< Page up */ |
|
|
|
|
PageDown = GLUT_KEY_PAGE_DOWN /**< Page down */ |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
protected: |
|
|
|
|
/**
|
|
|
|
|
* @brief Key press event |
|
|
|
|
* @param key Key pressed |
|
|
|
|
* @param position Cursor position |
|
|
|
|
* |
|
|
|
|
* Called when an key is pressed. Default implementation does nothing. |
|
|
|
|
*/ |
|
|
|
|
virtual void keyPressEvent(Key key, const Vector2i& position); |
|
|
|
|
virtual void keyPressEvent(KeyEvent& event); |
|
|
|
|
|
|
|
|
|
/*@}*/ |
|
|
|
|
|
|
|
|
|
/** @{ @name Mouse handling */ |
|
|
|
|
|
|
|
|
|
public: |
|
|
|
|
/**
|
|
|
|
|
* @brief Mouse button |
|
|
|
|
* |
|
|
|
|
* @see mousePressEvent(), mouseReleaseEvent() |
|
|
|
|
*/ |
|
|
|
|
enum class MouseButton: int { |
|
|
|
|
Left = GLUT_LEFT_BUTTON, /**< Left button */ |
|
|
|
|
Middle = GLUT_MIDDLE_BUTTON, /**< Middle button */ |
|
|
|
|
Right = GLUT_RIGHT_BUTTON, /**< Right button */ |
|
|
|
|
WheelUp = 3, /**< Wheel up */ |
|
|
|
|
WheelDown = 4 /**< Wheel down */ |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Mouse cursor |
|
|
|
|
* |
|
|
|
|
@ -193,7 +153,7 @@ class GlutApplication {
|
|
|
|
|
* when no button is pressed. Mouse tracking is disabled by default. |
|
|
|
|
*/ |
|
|
|
|
inline void setMouseTracking(bool enabled) { |
|
|
|
|
glutPassiveMotionFunc(enabled ? staticMouseMotionEvent : nullptr); |
|
|
|
|
glutPassiveMotionFunc(enabled ? staticMouseMoveEvent : nullptr); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** @brief Set mouse cursor */ |
|
|
|
|
@ -213,7 +173,7 @@ class GlutApplication {
|
|
|
|
|
* Called when mouse button is pressed. Default implementation does |
|
|
|
|
* nothing. |
|
|
|
|
*/ |
|
|
|
|
virtual void mousePressEvent(MouseButton button, const Vector2i& position); |
|
|
|
|
virtual void mousePressEvent(MouseEvent& event); |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Mouse release event |
|
|
|
|
@ -221,16 +181,16 @@ class GlutApplication {
|
|
|
|
|
* Called when mouse button is released. Default implementation does |
|
|
|
|
* nothing. |
|
|
|
|
*/ |
|
|
|
|
virtual void mouseReleaseEvent(MouseButton button, const Vector2i& position); |
|
|
|
|
virtual void mouseReleaseEvent(MouseEvent& event); |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Mouse motion event |
|
|
|
|
* @brief Mouse move event |
|
|
|
|
* |
|
|
|
|
* Called when any mouse button is pressed and mouse is moved. Default |
|
|
|
|
* implementation does nothing. |
|
|
|
|
* @see setMouseTracking() |
|
|
|
|
*/ |
|
|
|
|
virtual void mouseMotionEvent(const Vector2i& position); |
|
|
|
|
virtual void mouseMoveEvent(MouseMoveEvent& event); |
|
|
|
|
|
|
|
|
|
/*@}*/ |
|
|
|
|
|
|
|
|
|
@ -239,20 +199,11 @@ class GlutApplication {
|
|
|
|
|
instance->viewportEvent({x, y}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
inline static void staticKeyEvent(int key, int x, int y) { |
|
|
|
|
instance->keyPressEvent(static_cast<Key>(key), {x, y}); |
|
|
|
|
} |
|
|
|
|
static void staticKeyEvent(int key, int x, int y); |
|
|
|
|
|
|
|
|
|
inline static void staticMouseEvent(int button, int state, int x, int y) { |
|
|
|
|
if(state == GLUT_DOWN) |
|
|
|
|
instance->mousePressEvent(static_cast<MouseButton>(button), {x, y}); |
|
|
|
|
else |
|
|
|
|
instance->mouseReleaseEvent(static_cast<MouseButton>(button), {x, y}); |
|
|
|
|
} |
|
|
|
|
static void staticMouseEvent(int button, int state, int x, int y); |
|
|
|
|
|
|
|
|
|
inline static void staticMouseMotionEvent(int x, int y) { |
|
|
|
|
instance->mouseMotionEvent({x, y}); |
|
|
|
|
} |
|
|
|
|
static void staticMouseMoveEvent(int x, int y); |
|
|
|
|
|
|
|
|
|
inline static void staticDrawEvent() { |
|
|
|
|
instance->drawEvent(); |
|
|
|
|
@ -263,11 +214,151 @@ class GlutApplication {
|
|
|
|
|
Context* c; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@brief Base for input events |
|
|
|
|
|
|
|
|
|
@see KeyEvent, MouseEvent, MouseMoveEvent, keyPressEvent(), mousePressEvent(), |
|
|
|
|
mouseReleaseEvent(), mouseMoveEvent() |
|
|
|
|
*/ |
|
|
|
|
class GlutApplication::InputEvent { |
|
|
|
|
InputEvent(const InputEvent& other) = delete; |
|
|
|
|
InputEvent(InputEvent&& other) = delete; |
|
|
|
|
InputEvent& operator=(const InputEvent& other) = delete; |
|
|
|
|
InputEvent& operator=(InputEvent&& other) = delete; |
|
|
|
|
|
|
|
|
|
public: |
|
|
|
|
inline virtual ~InputEvent() {} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Set event as accepted |
|
|
|
|
* |
|
|
|
|
* If the event is ignored (i.e., not set as accepted), it might be |
|
|
|
|
* propagated elsewhere. By default is each event ignored. |
|
|
|
|
*/ |
|
|
|
|
inline void setAccepted(bool accepted = true) { _accepted = accepted; } |
|
|
|
|
|
|
|
|
|
/** @brief Whether the event is accepted */ |
|
|
|
|
inline bool isAccepted() { return _accepted; } |
|
|
|
|
|
|
|
|
|
#ifndef DOXYGEN_GENERATING_OUTPUT |
|
|
|
|
protected: |
|
|
|
|
inline InputEvent(): _accepted(false) {} |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
private: |
|
|
|
|
bool _accepted; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@brief Key event |
|
|
|
|
|
|
|
|
|
@see keyPressEvent() |
|
|
|
|
*/ |
|
|
|
|
class GlutApplication::KeyEvent: public GlutApplication::InputEvent { |
|
|
|
|
friend class GlutApplication; |
|
|
|
|
|
|
|
|
|
public: |
|
|
|
|
/**
|
|
|
|
|
* @brief Key |
|
|
|
|
* |
|
|
|
|
* @see key() |
|
|
|
|
*/ |
|
|
|
|
enum class Key: int { |
|
|
|
|
Up = GLUT_KEY_UP, /**< Up arrow */ |
|
|
|
|
Down = GLUT_KEY_DOWN, /**< Down arrow */ |
|
|
|
|
Left = GLUT_KEY_LEFT, /**< Left arrow */ |
|
|
|
|
Right = GLUT_KEY_RIGHT, /**< Right arrow */ |
|
|
|
|
F1 = GLUT_KEY_F1, /**< F1 */ |
|
|
|
|
F2 = GLUT_KEY_F2, /**< F2 */ |
|
|
|
|
F3 = GLUT_KEY_F3, /**< F3 */ |
|
|
|
|
F4 = GLUT_KEY_F4, /**< F4 */ |
|
|
|
|
F5 = GLUT_KEY_F5, /**< F5 */ |
|
|
|
|
F6 = GLUT_KEY_F6, /**< F6 */ |
|
|
|
|
F7 = GLUT_KEY_F7, /**< F7 */ |
|
|
|
|
F8 = GLUT_KEY_F8, /**< F8 */ |
|
|
|
|
F9 = GLUT_KEY_F9, /**< F9 */ |
|
|
|
|
F10 = GLUT_KEY_F10, /**< F10 */ |
|
|
|
|
F11 = GLUT_KEY_F11, /**< F11 */ |
|
|
|
|
F12 = GLUT_KEY_F12, /**< F12 */ |
|
|
|
|
Home = GLUT_KEY_HOME, /**< Home */ |
|
|
|
|
End = GLUT_KEY_END, /**< End */ |
|
|
|
|
PageUp = GLUT_KEY_PAGE_UP, /**< Page up */ |
|
|
|
|
PageDown = GLUT_KEY_PAGE_DOWN /**< Page down */ |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
/** @brief Key */ |
|
|
|
|
inline Key key() const { return _key; } |
|
|
|
|
|
|
|
|
|
/** @brief Position */ |
|
|
|
|
inline Vector2i position() const { return _position; } |
|
|
|
|
|
|
|
|
|
private: |
|
|
|
|
inline KeyEvent(Key key, const Vector2i& position): _key(key), _position(position) {} |
|
|
|
|
|
|
|
|
|
const Key _key; |
|
|
|
|
const Vector2i _position; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@brief Mouse event |
|
|
|
|
|
|
|
|
|
@see MouseMoveEvent, mousePressEvent(), mouseReleaseEvent() |
|
|
|
|
*/ |
|
|
|
|
class GlutApplication::MouseEvent: public GlutApplication::InputEvent { |
|
|
|
|
friend class GlutApplication; |
|
|
|
|
|
|
|
|
|
public: |
|
|
|
|
/**
|
|
|
|
|
* @brief Mouse button |
|
|
|
|
* |
|
|
|
|
* @see button() |
|
|
|
|
*/ |
|
|
|
|
enum class Button: int { |
|
|
|
|
Left = GLUT_LEFT_BUTTON, /**< Left button */ |
|
|
|
|
Middle = GLUT_MIDDLE_BUTTON, /**< Middle button */ |
|
|
|
|
Right = GLUT_RIGHT_BUTTON, /**< Right button */ |
|
|
|
|
WheelUp = 3, /**< Wheel up */ |
|
|
|
|
WheelDown = 4 /**< Wheel down */ |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
/** @brief Button */ |
|
|
|
|
inline Button button() const { return _button; } |
|
|
|
|
|
|
|
|
|
/** @brief Position */ |
|
|
|
|
inline Vector2i position() const { return _position; } |
|
|
|
|
|
|
|
|
|
private: |
|
|
|
|
inline MouseEvent(Button button, const Vector2i& position): _button(button), _position(position) {} |
|
|
|
|
|
|
|
|
|
const Button _button; |
|
|
|
|
const Vector2i _position; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@brief Mouse move event |
|
|
|
|
|
|
|
|
|
@see MouseEvent, mouseMoveEvent() |
|
|
|
|
*/ |
|
|
|
|
class GlutApplication::MouseMoveEvent: public GlutApplication::InputEvent { |
|
|
|
|
friend class GlutApplication; |
|
|
|
|
|
|
|
|
|
public: |
|
|
|
|
/** @brief Position */ |
|
|
|
|
inline Vector2i position() const { return _position; } |
|
|
|
|
|
|
|
|
|
private: |
|
|
|
|
inline MouseMoveEvent(const Vector2i& position): _position(position) {} |
|
|
|
|
|
|
|
|
|
const Vector2i _position; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
/** @hideinitializer
|
|
|
|
|
@brief Entry point for GLUT-based applications |
|
|
|
|
@param className Class name |
|
|
|
|
|
|
|
|
|
Can be used as equivalent to the following code to achieve better portability, |
|
|
|
|
see @ref portability-applications for more information. |
|
|
|
|
Can be with GlutApplication subclasses used as equivalent to the following |
|
|
|
|
code to achieve better portability, see @ref portability-applications for more |
|
|
|
|
information. |
|
|
|
|
@code |
|
|
|
|
int main(int argc, char** argv) { |
|
|
|
|
className app(argc, argv); |
|
|
|
|
@ -292,10 +383,10 @@ When no other application header is included this macro is also aliased to
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
/* Implementations for inline functions with unused parameters */ |
|
|
|
|
inline void GlutApplication::keyPressEvent(Key, const Vector2i&) {} |
|
|
|
|
inline void GlutApplication::mousePressEvent(MouseButton, const Vector2i&) {} |
|
|
|
|
inline void GlutApplication::mouseReleaseEvent(MouseButton, const Vector2i&) {} |
|
|
|
|
inline void GlutApplication::mouseMotionEvent(const Vector2i&) {} |
|
|
|
|
inline void GlutApplication::keyPressEvent(KeyEvent&) {} |
|
|
|
|
inline void GlutApplication::mousePressEvent(MouseEvent&) {} |
|
|
|
|
inline void GlutApplication::mouseReleaseEvent(MouseEvent&) {} |
|
|
|
|
inline void GlutApplication::mouseMoveEvent(MouseMoveEvent&) {} |
|
|
|
|
|
|
|
|
|
}} |
|
|
|
|
|
|
|
|
|
|