Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Thor C++ Library – An SFML extension  (Read 138561 times)

0 Members and 2 Guests are viewing this topic.

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Thor C++ Library – An SFML extension
« Reply #60 on: June 21, 2011, 11:54:33 pm »
Thanks, but I have already implemented a Delaunay triangulation algorithm, so it should theoretically be possible to use it for the polygons. The question is rather how powerful the Thor.Geometry module should be, at the moment it exists mainly for the particle emitter zones. But as stated, there are more important tasks for the next time ;)
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

gavintlgold

  • Newbie
  • *
  • Posts: 21
    • View Profile
Thor C++ Library – An SFML extension
« Reply #61 on: June 27, 2011, 07:20:06 am »
Hi there, I've been working on wrapping my head around the proper way to go about handling events with Thor's Action and EventSystem. So far I have a system that works but it seems clunky and it also does not provide the event information to the callbacks. Here's what I have:

Code: [Select]
(in constructor)
m_action_map["on-jump"] = thor::Action(sf::Key::T, thor::Action::PressOnce);
m_event_system.Connect("on-jump", std::tr1::bind(&SomeClass::onJump, &m_someclass));
... (continue for other events) ...

(in event function, per event)
m_action_map.PushEvent(event);

(in update function)
m_action_map.VisitEachFunction(thor::ActionForwarder(m_event_system) );
m_action_map.ClearEvents();


So anyway this code works properly for calling callbacks on events, and even adding in unchanging parameters but if I wanted to place something where the mouse cursor is when the action happens I wouldn't be able to do that since the callbacks don't know about the input or the event. Since my sfml window is in a singleton, I could just do
Code: [Select]
Game::singleton()->GetWindow()->GetInput().GetX()
but that's not a nice way to do it at all. SfmlEventSystem seems like it does this properly but the examples don't show a way to link specific string-based actions like "on-jump" with sfml events. The closest snippet I found was the following:

Code: [Select]
thor::ActionMap<std::string> actionMap(myWindow.GetInput());
thor::SfmlEventSystem sfmlEventSystem(myWindow);
sfmlEventSystem.ForwardEvents( thor::EventForwarder(actionMap) );


But there's not enough context in that snippet for me to understand how to get it to work as I'd like it.

Am I at least doing things somewhat as intended? Is there an easier way to bind custom actions to keypresses? For now I wrote a little macro to get the two lines down to one, but that's obviously not something I'm proud of. Thanks for any advice you can give.

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Thor C++ Library – An SFML extension
« Reply #62 on: June 27, 2011, 11:03:33 am »
Quote from: "gavintlgold"
So anyway this code works properly for calling callbacks on events, and even adding in unchanging parameters but if I wanted to place something where the mouse cursor is when the action happens I wouldn't be able to do that since the callbacks don't know about the input or the event.
Couldn't you pass a reference to sf::Input to the callback?
Code: [Select]
void OnJump(const sf::Input& realtimeInput);

sf::RenderWindow window = ...;
thor::EventSystem<std::string> system;
system.Connect( "on-jump", std::tr1::bind(&OnJump, std::tr1::cref(window.GetInput())) );


Quote from: "gavintlgold"
I've been working on wrapping my head around the proper way to go about handling events with Thor's Action and EventSystem. So far I have a system that works but it seems clunky
Yes, I am not very happy about the current way of event handling either. In Thor 1.0, there was mainly the callback system thor::SfmlEventSystem to handle events. Later, I introduced thor::ActionMap and thor::Action (which I think are very useful) but these classes are not very well integrated to the rest. Currently, the Events module contains the following components:
  • ActionMap and Action: Bind combinations of key/mouse/joystick events to action IDs
  • SfmlEventSystem: Map sf::Event objects to callbacks with the signature void Listener(sf::Event)
  • EventSystem: Map any event type to callbacks taking the event object
Generally, I tend to make ActionSystem more powerful and to get rid of SfmlEventSystem; I don't know if the latter is even used by anybody. We have recently had a similar discussion in the french thread about this.

However, for thor::ActionMap to completely replace thor::SfmlEventSystem, it needs to be able to pass the events to the callbacks. And here is my problem: Because ActionMap abstracts the events away (you can use sf::Event as a trigger for actions, as well as sf::Input), there needn't necessarily be a event to forward. So we cannot connect a listener like void OnTextEntered(sf::Event event), but we need the sf::Event object to extract event.Text.Unicode. I have to think more about this...

So, I am open to any suggestions as well as reports about the usefulness of the current Events module (especially the SfmlEventSystem class) :)
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

gavintlgold

  • Newbie
  • *
  • Posts: 21
    • View Profile
Thor C++ Library – An SFML extension
« Reply #63 on: June 27, 2011, 12:47:23 pm »
You're right, a reference to sf::Input should simplify that scenario a bit.

Thanks for the quick response, and I certainly understand the difficulty in getting ActionSystem to pass events properly.

For now though, it's very nice to be able to set up all the callbacks and actions in one place with ActionMap. I think this will make control preferences much easier as well, since I can probably pass some config file's values to the ActionMap (no more fiddling with switch statements!)

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Thor C++ Library – An SFML extension
« Reply #64 on: June 29, 2011, 02:44:43 am »
Okay, I have spent some work on making thor::ActionMap more powerful and flexible.

You can now pass any SFML events to it (not only key/mouse/joystick press or release), and link actions to callback functions, and extract the sf::Event and sf::Input objects inside the callbacks. The implementation isn't extremely beautiful, but I focus on the ease of use ;)
Code: [Select]
// Callback function for jumps
void OnJump(thor::ActionContext<std::string> context);

int main()
{
sf::Window window(sf::VideoMode(400, 300), "Thor Action Demo");

// Link T key to "jump" action
thor::ActionMap<std::string> map(window.GetInput());
map["jump"] = thor::Action(sf::Key::T, thor::Action::PressOnce);

// Register callback for jumps
thor::ActionMap<std::string>::CallbackSystem system;
system.Connect("jump", &OnJump);

for (;;)
{
// Clear temporarily pushed events
map.ClearEvents();

// Forward all events to the action map
sf::Event event;
while (window.PollEvent(event))
map.PushEvent(event);

// Forward actions to callbacks
map.InvokeCallbacks(system);

window.Display();
}
}

void OnJump(thor::ActionContext<std::string> context)
{
// Get the event that triggered this action
sf::Event event = context.Events[0];
assert(event.Type == sf::Event::KeyPressed && event.Key.Code == sf::Key::T);

// Get the realtime sf::Input
const sf::Input& input = context.RealtimeInput;
assert(input.IsKeyDown(sf::Key::T));

// Get the action identifier "jump"
std::string id = context.ActionId;
assert(id == "jump");
}

And I believe this spells doom for thor::SfmlEventSystem. The class is probably going to be removed during the next days.

I haven't tested the new functionality much yet, I would like to hear your thoughts about the modification of the Events module :)
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

gavintlgold

  • Newbie
  • *
  • Posts: 21
    • View Profile
Thor C++ Library – An SFML extension
« Reply #65 on: June 29, 2011, 04:40:35 am »
So far it's been a great help (and I imagine it'll get better once I use events that involve special data such as text input and mouse position).

One request I would make is an ActionIdentifier that works for both Presses and Releases (shouldn't it be relatively easy to do with an old-style bitwise filtering system?). That way I can set up a connection that will call on both press and release (for example for setting movement). Then inside the callback I can check if it's a press or release in a switch statement.

For now I can do:
Code: [Select]
Action(sf::Key::A, Action::PressOnce) || Action(sf::Key::A, Action::ReleaseOnce)
 in the Connect statement, which is perhaps good enough, but a little clunky. Ideally I'd be able to do something like
Code: [Select]
Action(sf::Key::A, Action::PressOnce | Action::ReleaseOnce)

Thanks again for the work you've been doing on this--it's proven invaluable for this project.

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Thor C++ Library – An SFML extension
« Reply #66 on: June 29, 2011, 11:06:33 am »
I'm glad the actions are helpful for your project :)

What would you say about a fourth enumerator?
Code: [Select]
Action(sf::Key::A, Action::Once)
For a bitwise system, I lose type safety because I need an unsigned int. And I don't think mixing the flag Realtime with PressOnce or ReleaseOnce makes sense... Or does it?
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

panithadrum

  • Sr. Member
  • ****
  • Posts: 304
    • View Profile
    • Skyrpex@Github
    • Email
Thor C++ Library – An SFML extension
« Reply #67 on: June 29, 2011, 04:14:19 pm »
HI Nexus, your library is amazing. I love your programming style!

May I modify your triangulation code to work with Qt's classes directly?

Edit: Could you explain the difference between thor::Triangulate and thor::TriangulatePolygon?

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Thor C++ Library – An SFML extension
« Reply #68 on: June 29, 2011, 05:28:45 pm »
Quote from: "panithadrum"
May I modify your triangulation code to work with Qt's classes directly?
Yes, just regard the license :)
 
But I would like to know if the functions aren't generic and extensible enough to be used with Qt, so that I can improve them if necessary. I also recommend to use the public interface, since the implementation might change in the future. What do you exactly want to modify?


Quote from: "panithadrum"
Edit: Could you explain the difference between thor::Triangulate and thor::TriangulatePolygon?
Sure.
  • thor::Triangulate() computes triangles between all points, i.e. the resulting shape is always convex, as seen in the left picture.
  • thor::TriangulatePolygon() computes only triangles inside a polygon. That is, the resulting shape can be concave, and the order of points is relevant to recognize the polygon outline. The result is visible in the right picture. By the way, this function is used inside thor::ConcaveShape.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

gavintlgold

  • Newbie
  • *
  • Posts: 21
    • View Profile
Thor C++ Library – An SFML extension
« Reply #69 on: June 29, 2011, 06:19:02 pm »
Action::Once sounds like a good solution.

Mixing PressOnce with Realtime could be slightly useful in that it would allow me to initialize a state and then poll it (so PressOnce would call the function once, to set up initial values like the first mouse position in a drag, then Realtime would call every frame to update something, and then perhaps ReleaseOnce would call to clean up or finalize a value).

However, this probably is better done in separate functions anyway, so mixing the two is not a big issue for me.

One thing I'd like to add is that it wasn't immediately obvious to me at least that using a Realtime event would not produce an event in the context.Events vector. So I was polling the event and it was segfaulting. Perhaps mentioning this in the documentation would be helpful to some people who are trying to understand the system.

Thanks!

panithadrum

  • Sr. Member
  • ****
  • Posts: 304
    • View Profile
    • Skyrpex@Github
    • Email
Thor C++ Library – An SFML extension
« Reply #70 on: June 29, 2011, 07:49:34 pm »
Quote from: "Nexus"
Quote from: "panithadrum"
May I modify your triangulation code to work with Qt's classes directly?
Yes, just regard the license :)

I just read the license terms, thanks :D

 
Quote from: "Nexus"
But I would like to know if the functions aren't generic and extensible enough to be used with Qt, so that I can improve them if necessary. I also recommend to use the public interface, since the implementation might change in the future. What do you exactly want to modify?

I can actually use your code, but not without converting all my QPointF to thor::Vertex and thor::Triangle<thor::Vertex> to QVector<QPointF> back again. Maybe it's not a need at all to make the triangulation work with Qt directly (at least is not critic for sure).


Quote from: "Nexus"
Quote from: "panithadrum"
Edit: Could you explain the difference between thor::Triangulate and thor::TriangulatePolygon?
Sure.
  • thor::Triangulate() computes triangles between all points, i.e. the resulting shape is always convex, as seen in the left picture.
  • thor::TriangulatePolygon() computes only triangles inside a polygon. That is, the resulting shape can be concave, and the order of points is relevant to recognize the polygon outline. The result is visible in the right picture. By the way, this function is used inside thor::ConcaveShape.

Thanks a lot, just what wanted to see!

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Thor C++ Library – An SFML extension
« Reply #71 on: June 29, 2011, 08:20:50 pm »
Quote from: "gavintlgold"
Action::Once sounds like a good solution.
Okay, I have added thor::Action::Once. The tasks I am going to complete next:
  • Improve documentation of thor::ActionContext.
  • Probably transform the sf::Event vector to a single event. I think it is easier for the user if the callback is invoked multiple times (once for every sf::Event), so there is no need for a loop in every listener. Mostly, there is only one event per frame anyway.
  • Remove thor::SfmlEventSystem.
Quote from: "panithadrum"
I can actually use your code, but not without converting all my QPointF to thor::Vertex and thor::Triangle<thor::Vertex> to QVector<QPointF> back again. Maybe it's not a need at all to make the triangulation work with Qt directly (at least is not critic for sure).
Ah yes, it is a little bit unfortunate that you need to convert these types. Inside the algorithm, I need a type like thor::Vertex that I know, I can't work with arbitrary template parameters because I don't know their interface (besides, the whole algorithm would have to be written in the header).

But If I were you, I would really not modify every single place where thor::Vertex is used, this is just too much work. And if I change something in the algorithm, you'd have to do it again ;)

A relatively comfortable solution would be a class derived from thor::Vertex that provides implicit conversions from and to QPoint. Or use something like std::transform(). This shouldn't be a big performance issue.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

gavintlgold

  • Newbie
  • *
  • Posts: 21
    • View Profile
Thor C++ Library – An SFML extension
« Reply #72 on: June 29, 2011, 08:45:09 pm »
Quote from: "Nexus"
Probably transform the sf::Event vector to a single event. I think it is easier for the user if the callback is invoked multiple times (once for every sf::Event), so there is no need for a loop in every listener. Mostly, there is only one event per frame anyway.


This sounds good. Having a vector of events seemed a bit clunky to me as well, given that one big reason for using events is to remove loop-like behavior.

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Thor C++ Library – An SFML extension
« Reply #73 on: June 29, 2011, 10:36:29 pm »
I have finished the three points. The class template thor::ActionContext now looks like this:
Code: [Select]
template <typename ActionIdentifier>
struct ActionContext
{
const sf::Input* RealtimeInput;
const sf::Event* Event;
ActionIdentifier ActionId;
};
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

gavintlgold

  • Newbie
  • *
  • Posts: 21
    • View Profile
Thor C++ Library – An SFML extension
« Reply #74 on: June 29, 2011, 10:52:02 pm »
Yep, it works nicely for me. The use of pointers is also good as it removes the burden of declaring a const reference and removes the possibility of making an accidental copy.

It's great. One last question: Is there a way to integrate mouse movement? Right now the only thing left in my onEvent function deals with MouseMove events. I may have missed something but I don't see a way to create an action that only involves mouse movement (mousebuttonpressed hooked with realtime would work for when a button is pressed, but not without a press).

I really can't thank you enough for the work you've done so far. This is far easier than trying to set up sigc++ or boost::signals to work with the engine (they work but don't integrate so well with SFML obviously). It also lets me have signals without an implementation that is too complex for what I need, and without having to include yet another library.