-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtransition_fade.cpp
124 lines (104 loc) · 4.12 KB
/
transition_fade.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#include <algorithm>
#include <vector>
#include "connection.hpp"
#include "event.hpp"
#include "core/manager.hpp"
#include "core/properties.hpp"
#include "scoped.hpp"
#include "timer.hpp"
#include "transition_fade.hpp"
#include "types.hpp"
#include "utility/algorithm.hpp"
using namespace std;
namespace sc {
/**
* struct FadeTransitionState
*/
struct FadeTransitionState
{
bool polling;
ChannelBuffer output;
ChannelBuffer target;
vector< int > deltas;
double factor;
EventScope pollEventScope;
};
/**
* class FadeTransition
*/
static PropertyKey const speedProperty( "speed" );
FadeTransition::FadeTransition( string&& id, Manager& manager, PropertyNode const& properties )
: Transition( move( id ) )
, manager_( manager )
, deltaPerNs_( ( ChannelValue::maximum - ChannelValue::minimum ) /
properties[ speedProperty ].as< chrono::nanoseconds >().count() )
{
}
std::unique_ptr< TransitionInstance > FadeTransition::instantiate() const
{
return unique_ptr< TransitionInstance >( new TransitionInstanceImpl< FadeTransition, FadeTransitionState >( *this ) );
}
void FadeTransition::transform( FadeTransitionState& state, Connection& connection, ChannelBuffer& values ) const
{
if ( state.output.empty() ) {
state.output = ChannelBuffer( values.size() );
state.deltas.resize( values.size() );
}
Scoped scoped( [&state, &values] { values = state.output; state.polling = false; } );
state.target = move( values );
bool changed = false;
if ( !state.polling ) {
changed = calculateDeltas( state );
}
if ( calculateOutput( state ) ) {
changed = true;
}
if ( !changed ) {
state.pollEventScope = nullptr;
return;
}
if ( !state.polling ) {
Connection* safeConnection = &connection;
FadeTransitionState* safeState = &state;
state.pollEventScope = manager_.pollEvent().subscribe(
[this, safeConnection, safeState]( chrono::nanoseconds elapsed ) {
poll( *safeState, *safeConnection, (double) elapsed.count() * deltaPerNs_ );
} );
}
}
void FadeTransition::poll( FadeTransitionState& state, Connection& connection, double factor ) const
{
state.polling = true;
state.factor = factor;
connection.transfer();
}
bool FadeTransition::calculateDeltas( FadeTransitionState& state ) const
{
auto changed = false;
std::transform( state.target.begin(), state.target.end(), state.output.begin(), state.deltas.begin(),
[&changed]( ChannelValue const& target, ChannelValue const& output ) {
auto delta = target.get() - output.get();
if ( delta == 0.0 ) {
return 0;
}
changed = true;
return signbit( delta ) ? -1 : 1;
} );
return changed;
}
bool FadeTransition::calculateOutput( FadeTransitionState& state ) const
{
auto changed = false;
auto factor = state.factor;
sc::transform( [&changed, factor]( auto const& output, auto const& delta, auto const& target ) {
double result = output.get() + factor * delta;
result = ( delta > 0.0 && result > target.get() ) || ( delta < 0.0 && result < target.get() )
? target.get() : result;
changed = changed || result != output.get();
return ChannelValue( result );
}, state.output.begin(), state.output.end(), state.output.begin(), state.deltas.begin(),
state.target.begin() );
return changed;
}
static TransitionRegistry< FadeTransition > registry( "fade" );
} // namespace sc