Hmm ok...I tried to pick what I though is important. Clearly this isn't compilable, but there are a lot of helper classes.
Button.hpp
class Button : public sf::Drawable, public toj::IInput // just know that an IInput will receive input notifications
{
public:
Button(const std::wstring &label = L"", sf::Vector2f pos = sf::Vector2f(0, 0),
sf::Vector2f size = sf::Vector2f(0, 0));
void SetSize(const sf::Vector2f &size) { _size = size; }
void SetLabel(const std::wstring &label) { _label.SetString(label); }
void SetOnClick(Functor &onClick) { _onClick = &onClick; }
void SetOnClickStop(Functor &onClickStop) { _onClickStop = &onClickStop; }
void SetOnHover(Functor &onHover) { _onHover = &onHover; }
void SetOnHoverExit(Functor &onHoverExit) { _onHoverExit = &onHoverExit; }
void ResetPosition() { SetPosition(_startPos); }
private:
virtual void Render(sf::RenderTarget &target, sf::Renderer &renderer) const;
virtual void Input(const sf::Input &input);
Functor *_onClick;
Functor *_onClickStop;
Functor *_onHover;
Functor *_onHoverExit;
sf::Text _label;
sf::Vector2f _size;
sf::Vector2f _startPos;
bool _mouseHovering;
bool _mouseClicking;
};
Button.cpp
/* virtual */ void Button::Input(const sf::Input &input)
{
sf::RenderWindow &window = App::GetInst().GetWindow();
sf::Vector2f mouseCoords = TransformToLocal(window.ConvertCoords(input.GetMouseX(), input.GetMouseY())); // Is there a better way to get mouse coords in...scene view?
mouseCoords.x -= GetPosition().x;
mouseCoords.y -= GetPosition().y;
sf::FloatRect thisRect(0, 0, _size.x, _size.y);
if(thisRect.Contains(mouseCoords.x, mouseCoords.y))
{
if(input.IsMouseButtonDown(sf::Mouse::Left))
{
if(_onClick)
(*_onClick)();
_mouseClicking = true;
}
else
{
if(_onClickStop && _mouseClicking)
(*_onClickStop)();
if(_onHover && !_mouseHovering)
(*_onHover)();
_mouseClicking = false;
}
_mouseHovering = true;
}
else
{
if(_onClickStop && _mouseClicking)
(*_onClickStop)();
if(_onHoverExit && _mouseHovering)
(*_onHoverExit)();
_mouseHovering = false;
_mouseClicking = false;
}
}
HUD.hpp
class HUD : public sf::Drawable, public toj::IInputObjectParent, public toj::IInput
{
class ButtonClickHandler : public toj::Functor // Click handler will call StartDrag with a button reference
class ButtonClickStopHandler : public toj::Functor // Click stop handler will call EndDrag
public:
toj::Button test;
HUD();
private:
virtual void Render(sf::RenderTarget &target, sf::Renderer &renderer) const;
virtual std::vector<toj::IInput*> GetInputObjects();
virtual void Input(const sf::Input &input);
void StartDrag(toj::Button &btn) { _dragged = &btn; }
void EndDrag();
toj::Button *_dragged;
bool _isDragging;
};
HUD.cpp
HUD::HUD() : _onClickTest(this, test), _onClickStop(this),
_dragged(NULL), _isDragging(false),
test(L"dzsd", sf::Vector2f(50.0f, 250.0f), sf::Vector2f(100.0f, 100.0f)) // I don't understand positioning...this appears perfectly flush with...
{
_rect = sf::Shape::Rectangle(0.0f, 500.0f, 800.0f, 600.0f, sf::Color(190, 190, 190)); // ...this, but there's a 250px difference in the y-val
test.SetOnClick(_onClickTest);
test.SetOnClickStop(_onClickStop);
}
void HUD::EndDrag()
{
if(_dragged)
{
_dragged->ResetPosition();
_dragged = NULL;
}
_isDragging = false;
}
/* virtual */ void HUD::Render(sf::RenderTarget &target, sf::Renderer &renderer) const
{
target.Draw(_rect);
target.Draw(test);
}
/* virtual */ std::vector<IInput*> HUD::GetInputObjects()
{
std::vector<IInput*> objects;
objects.push_back(&test); // The button gets input to determine what the mouse is doing to it (i.e. clicking, hovering)
objects.push_back(this); // HUD gets input to manipulate button based on whether or not it's being dragged (input code in 1st post)
return objects;
}
I hope this is enough. I guess I could upload the entire VS2010 project somewhere. I could make a video if that would help.