Skip to content

Commit

Permalink
added event list
Browse files Browse the repository at this point in the history
  • Loading branch information
Tomatower committed Jun 13, 2017
1 parent 7a11749 commit 8b3e6bf
Show file tree
Hide file tree
Showing 9 changed files with 388 additions and 81 deletions.
1 change: 1 addition & 0 deletions libopenage/curve/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ add_sources(libopenage
continuous.cpp
curve.cpp
discrete.cpp
events.cpp
iterator.cpp
map.cpp
map_filter_iterator.cpp
Expand Down
67 changes: 65 additions & 2 deletions libopenage/curve/datatypes.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,5 +53,68 @@ The queue container represents a random access queue while keeping the ordering
It is usually used for pushing in the back and popping at the front (FIFO-Stlye) but offers random access insertion and deletion as well.
This container is useful for example for action queues and buildung queues.

TUBE FILES
============
TUBE SERIALIZATION
==================

Serialization condenses data into change sets:

Repeat the following blob:
+-----------------------------------------------------------+
| ID (24Bit) |
| flags (delete, del_after, time, time2, data, add) (8Bit) | # In the first quadruple it is stored which data fields are set.
| if (flag & time) time1 | # In the second quadruple the usage of the data is stored
| if (flag & time2) time2 | # | time | time2 | data | UNUSED | delete | add | del_after | UNUSED |
| if (flag & data) keyframe: size(16) | data |
+-----------------------------------------------------------+

Meaning of Flags
----------------

== DELETE ==

After DELETE it is allowed to reuse the ID
When no Time is defined, then the deletion is "now", if TIME1 is defined, then the element will be deleted at this time.

== ADD ==

Create a new element with the given ID. Add has to have at least TIME1 and DATA set.

== DEL_AFTER ==

Delete all keyframes after TIME.

== TIME1 ==

Set the Keyframe time or the creation time of an element

== TIME2 ==

Set the Destruction time of a container element

== DATA ==

The Keyframe data prefixed by data length



Serialization of keyframes for different data types
----------------------------------------------------

Simple types: Binary Serialization of the data types, interpolation mode does not matter

Containers
For Containers DELETE_AFTER is not supported.

== Map ==

Store TIME2 as death time - if the element has a death time yet.
The ID of the object is submitted at creation as its own curve.

== Set ==

This container is simple to store only times (birth (TIME1) and death (TIME2) of each unit) and only update the keyframe data when neccesary

== Queue ==

Elements here have only one single time, so TIME2 is not used.
They can be created with ADD and removed with DELETE.
58 changes: 58 additions & 0 deletions libopenage/curve/events.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// Copyright 2017-2017 the openage authors. See copying.md for legal info.

#include "events.h"

namespace openage {
namespace curve {

void EventQueue::addcallback (const curve_time_t &at,
const EventQueue::condition &precond,
const EventQueue::callback &trigger) {
Event e;
e.event = trigger;
e.precond = precond;
e.time = at;

addcallback(e);
}

void EventQueue::addcallback (const curve_time_t &at,
const EventQueue::condition_void &precond,
const EventQueue::callback_void &trigger) {
Event e;
e.event = [trigger](const curve_time_t &) { trigger(); };
e.precond = [precond](const curve_time_t &) { return precond(); };
e.time = at;

addcallback(e);
}

void EventQueue::addcallback (const curve_time_t &at,
const EventQueue::callback &trigger) {
this->addcallback(at, &EventQueue::_true, trigger);
}

void EventQueue::addcallback (const curve_time_t &at,
const EventQueue::callback_void &trigger) {
this->addcallback(at, &EventQueue::_true, [trigger](const curve_time_t &) {
trigger();
});
}

void EventQueue::addcallback (const EventQueue::Event &e) {
queue.insert(e.time, e);
}

void EventQueue::trigger(const curve_time_t &from, const curve_time_t &to) {
for (auto it = queue.between(from, to); it != queue.end(); ++it) {
if (it.value().precond(it.value().time)) {
it.value().event(it.value().time);
}
}
}

bool EventQueue::_true(const curve_time_t &) {
return true;
}

}} // namespace openage::curve
45 changes: 45 additions & 0 deletions libopenage/curve/events.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Copyright 2017-2017 the openage authors. See copying.md for legal info.

#pragma once

#include "curve.h"
#include "queue.h"

#include <functional>

namespace openage {
namespace curve {

class EventQueue {

public:
typedef std::function<void(const curve_time_t &)> callback;
typedef std::function<bool(const curve_time_t &)> condition;

typedef std::function<void(void)> callback_void;
typedef std::function<bool(void)> condition_void;

class Event {
public:
callback event;
condition precond;
curve_time_t time;
};

void addcallback (const curve_time_t &at, const condition &, const callback &);
void addcallback (const curve_time_t &at, const condition_void &, const callback_void &);

void addcallback (const curve_time_t &at, const callback &);
void addcallback (const curve_time_t &at, const callback_void &);

void addcallback (const Event &);

void trigger(const curve_time_t &from, const curve_time_t &to);

private:
Queue<Event> queue;

static bool _true(const curve_time_t &);
};

}} // namespace openage::curve
176 changes: 103 additions & 73 deletions libopenage/curve/queue.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

#pragma once


#include "curve.h"
#include "queue_filter_iterator.h"

Expand Down Expand Up @@ -30,98 +29,129 @@ class Queue {
typedef typename std::deque<queue_wrapper> container_t;
typedef typename container_t::iterator iterator;
// Reading Access
const _T &front(const curve_time_t &) const {
return container.front();
}
const _T &front(const curve_time_t &) const;

// Modifying access
QueueFilterIterator<_T, Queue<_T>> begin(
const curve_time_t &t = -std::numeric_limits<curve_time_t>::infinity())
{
for (auto it = this->container.begin(); it != this->container.end(); ++it) {
if (it->time() >= t) {
return QueueFilterIterator<_T, Queue<_T>>(
it,
container.end(),
t,
std::numeric_limits<curve_time_t>::infinity());
}
}

return this->end(t);
}
const curve_time_t &t = -std::numeric_limits<curve_time_t>::infinity());

QueueFilterIterator<_T, Queue<_T>> end(
const curve_time_t &t = std::numeric_limits<curve_time_t>::infinity())
{
return QueueFilterIterator<_T, Queue<_T>>(container.end(),
container.end(),
t,
std::numeric_limits<curve_time_t>::infinity());
}
const curve_time_t &t = std::numeric_limits<curve_time_t>::infinity());

QueueFilterIterator<_T, Queue<_T>> between(
const curve_time_t &begin = std::numeric_limits<curve_time_t>::infinity(),
const curve_time_t &end = std::numeric_limits<curve_time_t>::infinity())
{
auto it = QueueFilterIterator<_T, Queue<_T>>(
container.begin(),
container.end(),
begin,
end);
if (!it.valid()) {
++it;
}
return it;
}
const curve_time_t &end = std::numeric_limits<curve_time_t>::infinity());

QueueFilterIterator<_T, Queue<_T>> erase(const CurveIterator<_T, Queue<_T>> &t) {
auto it = container.erase(t.base);
auto ct = QueueFilterIterator<_T, Queue<_T>>(
it,
container.end(),
t.from,
t.to);
QueueFilterIterator<_T, Queue<_T>> erase(
const CurveIterator<_T, Queue<_T>> &);

if (!ct.valid(t.from)) {
++ct;
QueueFilterIterator<_T, Queue<_T>> insert(
const curve_time_t &, const _T &e);

void __attribute__((noinline)) dump() {
for (auto i : container) {
std::cout << i.value << " at " << i.time() << std::endl;
}
return ct;
}

QueueFilterIterator<_T, Queue<_T>> insert(const curve_time_t & time, const _T &e) {
iterator insertion_point = this->container.end();
for (auto it = this->container.begin(); it != this->container.end(); ++it) {
if (time < it->time()) {
insertion_point = this->container
.insert(it, queue_wrapper(time, e));
break;
}
}
if (insertion_point == this->container.end()) {
insertion_point = this->container.insert(this->container.end(),
queue_wrapper(time, e));
}
private:
container_t container;
};


template <typename _T>
const _T &Queue<_T>::front(const curve_time_t &) const {
return container.front();
}

auto ct = QueueFilterIterator<_T, Queue<_T>>(
insertion_point,
container.end(),
time, std::numeric_limits<curve_time_t>::infinity());

if (!ct.valid()) {
++ct;
template <typename _T>
QueueFilterIterator<_T, Queue<_T>> Queue<_T>::begin(const curve_time_t &t)
{
for (auto it = this->container.begin(); it != this->container.end(); ++it) {
if (it->time() >= t) {
return QueueFilterIterator<_T, Queue<_T>>(
it,
container.end(),
t,
std::numeric_limits<curve_time_t>::infinity());
}
return ct;
}

void __attribute__((noinline)) dump() {
for (auto i : container) {
std::cout << i.value << " at " << i.time() << std::endl;
return this->end(t);
}


template <typename _T>
QueueFilterIterator<_T, Queue<_T>> Queue<_T>::end(const curve_time_t &t)
{
return QueueFilterIterator<_T, Queue<_T>>(container.end(),
container.end(),
t,
std::numeric_limits<curve_time_t>::infinity());
}


template <typename _T>
QueueFilterIterator<_T, Queue<_T>> Queue<_T>::between(
const curve_time_t &begin,
const curve_time_t &end)
{
auto it = QueueFilterIterator<_T, Queue<_T>>(
container.begin(),
container.end(),
begin,
end);
if (!it.valid()) {
++it;
}
return it;
}


template <typename _T>
QueueFilterIterator<_T, Queue<_T>> Queue<_T>::erase(const CurveIterator<_T, Queue<_T>> &t)
{
auto it = container.erase(t.base);
auto ct = QueueFilterIterator<_T, Queue<_T>>(
it,
container.end(),
t.from,
t.to);

if (!ct.valid(t.from)) {
++ct;
}
return ct;
}


template <typename _T>
QueueFilterIterator<_T, Queue<_T>> Queue<_T>::insert(
const curve_time_t &time,
const _T &e) {
iterator insertion_point = this->container.end();
for (auto it = this->container.begin(); it != this->container.end(); ++it) {
if (time < it->time()) {
insertion_point = this->container
.insert(it, queue_wrapper(time, e));
break;
}
}
if (insertion_point == this->container.end()) {
insertion_point = this->container.insert(this->container.end(),
queue_wrapper(time, e));
}

private:
container_t container;
};
auto ct = QueueFilterIterator<_T, Queue<_T>>(
insertion_point,
container.end(),
time, std::numeric_limits<curve_time_t>::infinity());

if (!ct.valid()) {
++ct;
}
return ct;
}

}} // openage::curve

0 comments on commit 8b3e6bf

Please sign in to comment.