InputListener->State and better listening

This commit is contained in:
James Turk 2005-08-12 06:26:00 +00:00
parent 8412cbab72
commit 8db6d31b5d
11 changed files with 197 additions and 317 deletions

View File

@ -1,18 +1,20 @@
Changelog for Photon
$Id: CHANGELOG.txt,v 1.6 2005/08/10 21:22:33 cozman Exp $
$Id: CHANGELOG.txt,v 1.7 2005/08/12 06:26:00 cozman Exp $
+ : New Features
- : Feature Removal
! : Major Changes
* : Minor Changes/Bugfixes
! : Major Changes (potentially breaking existing code)
+ : New Features
* : Minor Changes (bugfixes and behind-the-scenes changes)
0.0.2
! Removed InputListener, opting to move features into State class.
+ Code::Blocks and Dev-C++ support
+ Addition of a State stack allowing for applications to fall back to the
previous state when done with a particular state.
+ Notification of mouse wheel events added.
* Fixed X11 fullscreen mode
* Removed ALUT dependencies by adding custom WAV loading code
* Mouse move events now give relative position.
0.0.1 - Released 2005-08-08
+ State-based design that allows easy creation of applications by simply

View File

@ -30,12 +30,6 @@
<Option link="0"/>
<Option target="default"/>
</Unit>
<Unit filename="..\include\InputListener.hpp">
<Option compilerVar=""/>
<Option compile="0"/>
<Option link="0"/>
<Option target="default"/>
</Unit>
<Unit filename="..\include\Kernel.hpp">
<Option compilerVar=""/>
<Option compile="0"/>
@ -238,10 +232,6 @@
<Option compilerVar="CPP"/>
<Option target="default"/>
</Unit>
<Unit filename="..\src\InputListener.cpp">
<Option compilerVar="CPP"/>
<Option target="default"/>
</Unit>
<Unit filename="..\src\Kernel.cpp">
<Option compilerVar="CPP"/>
<Option target="default"/>

View File

@ -5,7 +5,7 @@
// James Turk (jpt2433@rit.edu)
//
// Version:
// $Id: Application.hpp,v 1.17 2005/08/10 21:22:33 cozman Exp $
// $Id: Application.hpp,v 1.18 2005/08/12 06:26:00 cozman Exp $
#ifndef PHOTON_APPLICATION_HPP
#define PHOTON_APPLICATION_HPP
@ -21,11 +21,10 @@
#include "State.hpp"
#include "Task.hpp"
#include "Kernel.hpp"
#include "InputListener.hpp"
#include "audio/AudioCore.hpp"
#include "util/Singleton.hpp"
#include <vector>
#include <iostream>
namespace photon
{
@ -246,29 +245,6 @@ public:
// Mouse wheel position, zero assumed to be starting position.
int getMouseWheelPos();
// Group: Input Listeners
public:
// Function: addInputListener
// Registers an <InputListener> to listen for any input events so that it
// is notified when they occur.
//
// Parameters:
// listener - Pointer to <InputListener> to add.
static void addInputListener(InputListener *listener);
// Function: removeInputListener
// Removes an <InputListener> from the list of active listeners.
//
// Parameters:
// listener - Pointer to <InputListener> to remove.
static void removeInputListener(InputListener *listener);
static void GLFWCALL keyCallback(int key, int action);
//static void GLFWCALL charCallback(int character, int action);
static void GLFWCALL mouseButtonCallback(int button, int action);
static void GLFWCALL mouseMoveCallback(int x, int y);
//static void GLFWCALL mouseWheelCallback(int pos);
// Group: Timing
public:
@ -304,7 +280,7 @@ public:
// StateT - Class derived from <State> to set as current.
template<class StateT>
void setState();
// Function: pushState
// Push a new <State>, does not remove old <State>.
//
@ -312,7 +288,7 @@ public:
// StateT - Class derived from <State> to push.
template<class StateT>
void pushState();
// Function: popState
// Pop the current <State>, returning to the prior <State> on the stack.
void popState();
@ -338,6 +314,14 @@ public:
void initAudioCore(const std::string& deviceName="");
#endif //PHOTON_USE_OPENAL
// Callbacks
public:
static void GLFWCALL keyCallback(int key, int action);
//static void GLFWCALL charCallback(int character, int action);
static void GLFWCALL mouseButtonCallback(int button, int action);
static void GLFWCALL mouseMoveCallback(int x, int y);
static void GLFWCALL mouseWheelCallback(int pos);
// API Initialization
private:
util::VersionInfo initPhysFS(const std::string& arg0);
@ -425,11 +409,10 @@ private:
shared_ptr<StateRender> stateRender_;
// input system variables
static std::vector<InputListener*> listeners_;
static std::vector<KeyCode> pressedKeys_;
// state system
std::stack<StatePtr> stateStack_;
static std::stack<StatePtr> stateStack_;
// Cores
#ifdef PHOTON_USE_OPENAL
@ -467,7 +450,6 @@ void Application::pushState()
{
stateStack_.top()->onPause();
}
stateStack_.push(newState); // push newState on top of stack
stateRender_->state_ = stateUpdate_->state_ = newState;

View File

@ -1,96 +0,0 @@
//This file is part of Photon (http://photon.sourceforge.net)
//Copyright (C) 2004-2005 James Turk
//
// Author:
// James Turk (jpt2433@rit.edu)
//
// Version:
// $Id: InputListener.hpp,v 1.2 2005/08/08 19:19:24 cozman Exp $
#ifndef PHOTON_INPUTLISTENER_HPP
#define PHOTON_INPUTLISTENER_HPP
#include "math/Vector2.hpp"
namespace photon
{
// Class: InputListener
// Virtual class to handle user input, classes can derive from this to be
// notified of input events.
class InputListener
{
// Group: (Con/De)structors
public:
// Function: InputListener
// Registers the InputListener to listen for input with <Application>.
InputListener();
// Function: ~InputListener
// Deregisters the listener with <Application>. so that it is no longer
// notified of events.
virtual ~InputListener();
// Group: General
public:
// Function: setActive
// Enable/Disable the InputListener.
//
// Parameters:
// active - Active state of the InputListener.
void setActive(bool active);
// Function: isActive
// Returns true if the InputListener is active.
//
// Returns: true if active, false if deactivated
bool isActive() const;
// Group: Keyboard Actions
public:
// Function: onKeyPress
// Called when a key is pressed.
//
// Parameters:
// key - <KeyCode> of key that has been pressed.
virtual void onKeyPress(KeyCode key);
// Function: onKeyRelease
// Called when a key is released.
//
// Parameters:
// key - <KeyCode> of key that has been released.
virtual void onKeyRelease(KeyCode key);
// Group: Mouse Actions
public:
// Function: onMouseButtonPress
// Called when a mouse button is pressed.
//
// Parameters:
// button - <MouseButton> that was pressed.
virtual void onMouseButtonPress(MouseButton button);
// Function: onMouseButtonRelease
// Called when a mouse button is released.
//
// Parameters:
// button - <MouseButton> that was released.
virtual void onMouseButtonRelease(MouseButton button);
// Function: onMouseMove
// Called when the mouse is moved.
//
// Parameters:
// pos - Position of the mouse.
virtual void onMouseMove(const math::Vector2& pos);
private:
bool active_;
};
}
#endif //PHOTON_INPUTLISTENER_HPP

View File

@ -5,12 +5,16 @@
// James Turk (jpt2433@rit.edu)
//
// Version:
// $Id: State.hpp,v 1.2 2005/08/10 21:22:33 cozman Exp $
// $Id: State.hpp,v 1.3 2005/08/12 06:26:00 cozman Exp $
#ifndef PHOTON_STATE_HPP
#define PHOTON_STATE_HPP
#include "types.hpp"
#include "math/Vector2.hpp"
namespace photon
{
// Class: State
// Pure virtual State class, used as base class for Photon's state system.
@ -18,12 +22,16 @@
// Photon's State system is extremely simple yet also very convenient. Simply
// by creating classes that fulfill the <State> interface you can use Photon
// to manage the state that the game is in.
//
// Implement as many or as few of the members of State as needed (the only
// necessary member being <render>) and make the state as current via
// <Application::setState>. Once a state is made current it's
// update and render methods will be called every frame until either a new
// state is made current or the application ends.
//
// The active state is also notified of events as they occur, overloading any
// of the on* functions will result in the overloaded version being called
// when the particular event happens while the state is active.
class State
{
// Group: (Con/De)structors
@ -66,8 +74,60 @@ public:
// will call onResume allowing the state to undo any work that had been
// done in <onPause>.
virtual void onResume() { };
// Group: Keyboard Actions
public:
// Function: onKeyPress
// Called when a key is pressed.
//
// Parameters:
// key - <KeyCode> of key that has been pressed.
virtual void onKeyPress(KeyCode key) { };
// Function: onKeyRelease
// Called when a key is released.
//
// Parameters:
// key - <KeyCode> of key that has been released.
virtual void onKeyRelease(KeyCode key) { };
// Group: Mouse Actions
public:
// Function: onMouseButtonPress
// Called when a mouse button is pressed.
//
// Parameters:
// button - <MouseButton> that was pressed.
virtual void onMouseButtonPress(MouseButton button) { };
// Function: onMouseButtonRelease
// Called when a mouse button is released.
//
// Parameters:
// button - <MouseButton> that was released.
virtual void onMouseButtonRelease(MouseButton button) { };
// Function: onMouseMove
// Called when the mouse is moved with the amount the mouse was moved by
// NOT with the new position.
//
// If the new position is needed it can be obtained via <getMouseX> and
// <getMouseY>.
//
// Parameters:
// delta - Change in mouse position.
virtual void onMouseMove(const math::Vector2& delta) { };
// Function: onMouseScroll
// Called when mouse wheel is scrolled.
//
// Parameters:
// dir - <ScrollDir> describing if mouse wheel was scrolled up or down.
virtual void onMouseScroll(ScrollDir dir) { };
};
typedef photon::shared_ptr<State> StatePtr;
typedef shared_ptr<State> StatePtr;
}
#endif //PHOTON_STATE_HPP

View File

@ -8,7 +8,6 @@
#include "Task.hpp"
#include "exceptions.hpp"
#include "photon.hpp"
#include "InputListener.hpp"
#include "entrypoint.hpp"
#include "LogSink.hpp"
#include "Log.hpp"

View File

@ -5,7 +5,7 @@
// James Turk (jpt2433@rit.edu)
//
// Version:
// $Id: types.hpp,v 1.7 2005/08/08 19:19:25 cozman Exp $
// $Id: types.hpp,v 1.8 2005/08/12 06:26:00 cozman Exp $
#ifndef PHOTON_TYPES_HPP
#define PHOTON_TYPES_HPP
@ -317,6 +317,16 @@ enum MouseButton
MB_RIGHT =GLFW_MOUSE_BUTTON_RIGHT
};
// Enum: ScrollDir
// Enumeration defining scroll direction of mouse wheel.
//
// SCROLL_UP - Wheel was scrolled up.
// SCROLL_DOWN - Wheel was scrolled down.
enum ScrollDir
{
SCROLL_UP, SCROLL_DOWN
};
}
#endif //PHOTON_TYPES_HPP

View File

@ -5,7 +5,7 @@
// James Turk (jpt2433@rit.edu)
//
// Version:
// $Id: Application.cpp,v 1.22 2005/08/10 21:22:33 cozman Exp $
// $Id: Application.cpp,v 1.23 2005/08/12 06:26:00 cozman Exp $
#include "Application.hpp"
@ -26,8 +26,8 @@ namespace photon
{
// static class members
std::vector<InputListener*> Application::listeners_;
std::vector<KeyCode> Application::pressedKeys_;
std::stack<StatePtr> Application::stateStack_;
// (Con/De)structors ///////////////////////////////////////////////////////////
@ -98,7 +98,7 @@ void Application::createDisplay(uint width, uint height,
//glfwSetCharCallback(Application::charCallback);
glfwSetMouseButtonCallback(Application::mouseButtonCallback);
glfwSetMousePosCallback(Application::mouseMoveCallback);
//glfwSetMouseWheelCallback(Application::mouseWheelCallback);
glfwSetMouseWheelCallback(Application::mouseWheelCallback);
}
void Application::createDisplay(uint width, uint height, uint bpp,
@ -262,117 +262,6 @@ int Application::getMouseWheelPos()
return glfwGetMouseWheel();
}
// Input Listeners /////////////////////////////////////////////////////////////
void Application::addInputListener(InputListener *listener)
{
// should never happen since listeners add themselves with a this pointer
if(!listener)
{
throw ArgumentException("Null pointer in "
"Application::addInputListener");
}
// add the listener
listeners_.push_back(listener);
}
void Application::removeInputListener(InputListener *listener)
{
// should never happen since listeners remove themselves with a this pointer
if(!listener)
{
throw ArgumentException("Null pointer in "
"Application::removeInputListener");
}
// find and erase the listener
std::vector<InputListener*>::iterator it;
it = std::find(listeners_.begin(), listeners_.end(), listener);
if(it != listeners_.end())
{
listeners_.erase(it);
}
}
void GLFWCALL Application::keyCallback(int key, int action)
{
// notify all listeners
for(std::vector<InputListener*>::iterator listener = listeners_.begin();
listener != listeners_.end();
++listener)
{
// only active listeners get messages
if((*listener)->isActive())
{
if(action == GLFW_PRESS)
{
(*listener)->onKeyPress(KeyCode(key));
}
else
{
(*listener)->onKeyRelease(KeyCode(key));
}
}
}
// maintain a list of pressed keys
if(action == GLFW_PRESS)
{
pressedKeys_.push_back(static_cast<KeyCode>(key));
}
else
{
// delete a key from the vector
std::vector<KeyCode>::iterator it;
it = std::find(pressedKeys_.begin(), pressedKeys_.end(), key);
if(it != pressedKeys_.end())
{
pressedKeys_.erase(it);
}
}
}
void GLFWCALL Application::mouseButtonCallback(int button, int action)
{
// notify all listeners
for(std::vector<InputListener*>::iterator listener = listeners_.begin();
listener != listeners_.end();
++listener)
{
// only active listeners get messages
if((*listener)->isActive())
{
if(action == GLFW_PRESS)
{
(*listener)->onMouseButtonPress(MouseButton(button));
}
else
{
(*listener)->onMouseButtonRelease(MouseButton(button));
}
}
}
}
void GLFWCALL Application::mouseMoveCallback(int x, int y)
{
// notify all listeners
for(std::vector<InputListener*>::iterator listener = listeners_.begin();
listener != listeners_.end();
++listener)
{
// only active listeners get messages
if((*listener)->isActive())
{
(*listener)->onMouseMove(math::Vector2(static_cast<scalar>(x),
static_cast<scalar>(y)));
}
}
}
// Timing //////////////////////////////////////////////////////////////////////
scalar Application::getTime()
@ -394,9 +283,17 @@ double Application::getFramerate()
void Application::popState()
{
stateStack_.pop(); // pop current state from stack
// if there is another state, resume it it
// check for underflow
if(stateStack_.empty())
{
throw PreconditionException("Attempt to popState without at least 2 "
"states on stack.");
}
// pop current state from stack
stateStack_.pop();
// resume new top state & set tasks for next state
if(!stateStack_.empty())
{
stateStack_.top()->onResume();
@ -433,6 +330,82 @@ void Application::initAudioCore(const std::string& deviceName)
#endif //PHOTON_USE_OPENAL
// Callbacks ///////////////////////////////////////////////////////////////////
void GLFWCALL Application::keyCallback(int key, int action)
{
if(!stateStack_.empty())
{
if(action == GLFW_PRESS)
{
stateStack_.top()->onKeyPress(KeyCode(key));
}
else
{
stateStack_.top()->onKeyRelease(KeyCode(key));
}
}
// maintain a list of pressed keys
if(action == GLFW_PRESS)
{
pressedKeys_.push_back(static_cast<KeyCode>(key));
}
else
{
// delete a key from the vector
std::vector<KeyCode>::iterator it;
it = std::find(pressedKeys_.begin(), pressedKeys_.end(), key);
if(it != pressedKeys_.end())
{
pressedKeys_.erase(it);
}
}
}
void GLFWCALL Application::mouseButtonCallback(int button, int action)
{
if(!stateStack_.empty())
{
if(action == GLFW_PRESS)
{
stateStack_.top()->onMouseButtonPress(MouseButton(button));
}
else
{
stateStack_.top()->onMouseButtonRelease(MouseButton(button));
}
}
}
void GLFWCALL Application::mouseMoveCallback(int x, int y)
{
static math::Point2 lastPos;
if(!stateStack_.empty())
{
// calculate change in position and send delta
math::Point2 pos(static_cast<scalar>(x), static_cast<scalar>(y));
stateStack_.top()->onMouseMove(pos - lastPos);
lastPos = pos;
}
}
void GLFWCALL Application::mouseWheelCallback(int pos)
{
static int lastPos(0);
if(!stateStack_.empty())
{
// if pos < lastPos scrolled up, otherwise scrolled down
stateStack_.top()->onMouseScroll( pos < lastPos ?
SCROLL_DOWN :
SCROLL_UP);
lastPos = pos;
}
}
// API initialization //////////////////////////////////////////////////////////
util::VersionInfo Application::initPhysFS(const std::string& arg0)
@ -536,7 +509,7 @@ Application::VideoTask::VideoTask() :
void Application::VideoTask::update()
{
// TODO: clear depth/stencil if requested
glClear(GL_COLOR_BUFFER_BIT);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
}
Application::StateUpdate::StateUpdate() :

View File

@ -1,46 +0,0 @@
//This file is part of Photon (http://photon.sourceforge.net)
//Copyright (C) 2004-2005 James Turk
//
// Author:
// James Turk (jpt2433@rit.edu)
//
// Version:
// $Id: InputListener.cpp,v 1.3 2005/08/08 19:19:22 cozman Exp $
#include "InputListener.hpp"
#include "Application.hpp"
namespace photon
{
InputListener::InputListener() :
active_(true)
{
Application::addInputListener(this);
}
InputListener::~InputListener()
{
Application::removeInputListener(this);
}
void InputListener::setActive(bool active)
{
active_ = active;
}
bool InputListener::isActive() const
{
return active_;
}
// do nothing, overloaded as needed
void InputListener::onKeyPress(KeyCode key) { }
void InputListener::onKeyRelease(KeyCode key) { }
void InputListener::onMouseButtonPress(MouseButton button) { }
void InputListener::onMouseButtonRelease(MouseButton button) { }
void InputListener::onMouseMove(const math::Vector2& pos) { }
}

View File

@ -5,7 +5,7 @@
// James Turk (jpt2433@rit.edu)
//
// Version:
// $Id: Audio_test.cpp,v 1.13 2005/08/10 21:22:33 cozman Exp $
// $Id: Audio_test.cpp,v 1.14 2005/08/12 06:26:00 cozman Exp $
#include "photon.hpp"
using namespace photon;
@ -17,7 +17,7 @@ using namespace photon;
using namespace photon::audio;
// sole task of AudioTest
class MainState : public State , public InputListener
class MainState : public State
{
public:

View File

@ -5,13 +5,13 @@
// James Turk (jpt2433@rit.edu)
//
// Version:
// $Id: Input_test.cpp,v 1.9 2005/08/10 21:22:33 cozman Exp $
// $Id: Input_test.cpp,v 1.10 2005/08/12 06:26:00 cozman Exp $
#include "photon.hpp"
using namespace photon;
#include "FPSDisplayTask.hpp" // used to display FPS in title bar
class MainState : public State, public InputListener
class MainState : public State
{
public:
@ -50,9 +50,15 @@ public:
" released";
}
void onMouseMove(const math::Vector2& pos)
void onMouseMove(const math::Vector2& delta)
{
lastEvent = "mouse moved to " + boost::lexical_cast<std::string>(pos);
lastEvent = "mouse moved by " + boost::lexical_cast<std::string>(delta);
}
void onMouseScroll(ScrollDir dir)
{
lastEvent = "mouse wheel scrolled " +
std::string(dir == SCROLL_UP ? "up" : "down");
}
void render()