mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-10-01 10:40:20 +03:00
Reduce allocations in actions and CSS style updates
- allocate Action instances from reusable size-class pools
- use inline storage for Runnable callbacks, action sequences, spawned actions,
callback registrations, and main-thread action queues
- preserve action factory and ownership semantics while recycling completed actions
- cache computed transitions in ElementDefinition instead of reparsing them on
every state change
- parse transition and timing-function values through allocation-light string views
and inline parameter storage
- add a non-owning FunctionString view parser with callback-based parameter iteration
- preserve nested functions, quoted parameters, escaped quotes, and early termination
- fix transition timing-function lists to cycle independently from delay lists
- avoid copying variable caches during CSS variable substitution
- parse drawable sizes and positions without allocating split string vectors
- reuse animation state and reduce temporary property parsing allocations
- avoid memory-manager bookkeeping allocations for static source filenames
- consolidate whitespace trimming through the existing String utilities
- add regression coverage for action reuse, transition parsing, computed transition
lookup, timing-list cycling, and non-owning FunctionString parsing
This commit is contained in:
@@ -12,10 +12,12 @@ namespace EE {
|
||||
|
||||
class EE_API AllocatedPointer {
|
||||
public:
|
||||
AllocatedPointer( void* data, const std::string& File, int Line, size_t memory,
|
||||
bool track = false, bool globalAllocation = false );
|
||||
/** file must have static storage duration. All memory-manager entry points pass __FILE__ or a
|
||||
* string literal, so retaining the pointer avoids allocating bookkeeping strings. */
|
||||
AllocatedPointer( void* data, const char* file, int line, size_t memory, bool track = false,
|
||||
bool globalAllocation = false );
|
||||
|
||||
std::string mFile;
|
||||
const char* mFile;
|
||||
int mLine;
|
||||
size_t mMemory;
|
||||
void* mData;
|
||||
|
||||
@@ -0,0 +1,174 @@
|
||||
#ifndef EE_CORE_SMALL_FUNCTION_HPP
|
||||
#define EE_CORE_SMALL_FUNCTION_HPP
|
||||
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
#include <new>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace EE {
|
||||
|
||||
/** Copyable type-erased void callable with inline storage and a heap fallback.
|
||||
*
|
||||
* This intentionally implements only the signature used by the scene scheduler. Ordinary lambdas
|
||||
* stay inside the object; unusually large or over-aligned callables retain std::function-like
|
||||
* fallback behavior.
|
||||
*/
|
||||
template <std::size_t InlineSize = 64> class SmallFunction {
|
||||
public:
|
||||
SmallFunction() noexcept = default;
|
||||
SmallFunction( std::nullptr_t ) noexcept {}
|
||||
|
||||
SmallFunction( const SmallFunction& other ) {
|
||||
if ( other.mVTable )
|
||||
other.mVTable->copy( *this, other );
|
||||
}
|
||||
|
||||
SmallFunction( SmallFunction&& other ) {
|
||||
if ( other.mVTable )
|
||||
other.mVTable->move( *this, other );
|
||||
}
|
||||
|
||||
template <typename Callable, typename Decayed = std::decay_t<Callable>,
|
||||
std::enable_if_t<!std::is_same_v<Decayed, SmallFunction> &&
|
||||
std::is_invocable_r_v<void, Decayed&>,
|
||||
int> = 0>
|
||||
SmallFunction( Callable&& callable ) {
|
||||
emplace<Decayed>( std::forward<Callable>( callable ) );
|
||||
}
|
||||
|
||||
~SmallFunction() { reset(); }
|
||||
|
||||
SmallFunction& operator=( const SmallFunction& other ) {
|
||||
if ( this != &other ) {
|
||||
reset();
|
||||
if ( other.mVTable )
|
||||
other.mVTable->copy( *this, other );
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
SmallFunction& operator=( SmallFunction&& other ) {
|
||||
if ( this != &other ) {
|
||||
reset();
|
||||
if ( other.mVTable )
|
||||
other.mVTable->move( *this, other );
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename Callable, typename Decayed = std::decay_t<Callable>,
|
||||
std::enable_if_t<!std::is_same_v<Decayed, SmallFunction> &&
|
||||
std::is_invocable_r_v<void, Decayed&>,
|
||||
int> = 0>
|
||||
SmallFunction& operator=( Callable&& callable ) {
|
||||
reset();
|
||||
emplace<Decayed>( std::forward<Callable>( callable ) );
|
||||
return *this;
|
||||
}
|
||||
|
||||
SmallFunction& operator=( std::nullptr_t ) noexcept {
|
||||
reset();
|
||||
return *this;
|
||||
}
|
||||
|
||||
explicit operator bool() const noexcept { return nullptr != mVTable; }
|
||||
|
||||
void operator()() const {
|
||||
if ( !mVTable )
|
||||
throw std::bad_function_call();
|
||||
mVTable->invoke( const_cast<SmallFunction&>( *this ) );
|
||||
}
|
||||
|
||||
void reset() noexcept {
|
||||
if ( mVTable ) {
|
||||
mVTable->destroy( *this );
|
||||
mVTable = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr std::size_t inlineSize() noexcept { return InlineSize; }
|
||||
|
||||
private:
|
||||
static constexpr std::size_t StorageSize =
|
||||
InlineSize < sizeof( void* ) ? sizeof( void* ) : InlineSize;
|
||||
using Storage = std::aligned_storage_t<StorageSize, alignof( std::max_align_t )>;
|
||||
|
||||
struct VTable {
|
||||
void ( *invoke )( SmallFunction& );
|
||||
void ( *copy )( SmallFunction&, const SmallFunction& );
|
||||
void ( *move )( SmallFunction&, SmallFunction& );
|
||||
void ( *destroy )( SmallFunction& ) noexcept;
|
||||
};
|
||||
|
||||
template <typename Callable>
|
||||
static constexpr bool FitsInline =
|
||||
sizeof( Callable ) <= StorageSize && alignof( Callable ) <= alignof( Storage );
|
||||
|
||||
template <typename Callable> static Callable*& heapPointer( SmallFunction& function ) {
|
||||
return *reinterpret_cast<Callable**>( &function.mStorage );
|
||||
}
|
||||
|
||||
template <typename Callable> static Callable* inlinePointer( SmallFunction& function ) {
|
||||
return reinterpret_cast<Callable*>( &function.mStorage );
|
||||
}
|
||||
|
||||
template <typename Callable, typename Value> void emplace( Value&& value ) {
|
||||
static_assert( std::is_copy_constructible_v<Callable>,
|
||||
"SmallFunction requires a copy-constructible callable" );
|
||||
if constexpr ( FitsInline<Callable> ) {
|
||||
new ( &mStorage ) Callable( std::forward<Value>( value ) );
|
||||
mVTable = &inlineVTable<Callable>();
|
||||
} else {
|
||||
heapPointer<Callable>( *this ) = new Callable( std::forward<Value>( value ) );
|
||||
mVTable = &heapVTable<Callable>();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Callable> static const VTable& inlineVTable() {
|
||||
static const VTable table{
|
||||
[]( SmallFunction& function ) { ( *inlinePointer<Callable>( function ) )(); },
|
||||
[]( SmallFunction& destination, const SmallFunction& source ) {
|
||||
new ( &destination.mStorage )
|
||||
Callable( *inlinePointer<Callable>( const_cast<SmallFunction&>( source ) ) );
|
||||
destination.mVTable = &inlineVTable<Callable>();
|
||||
},
|
||||
[]( SmallFunction& destination, SmallFunction& source ) {
|
||||
new ( &destination.mStorage )
|
||||
Callable( std::move( *inlinePointer<Callable>( source ) ) );
|
||||
inlinePointer<Callable>( source )->~Callable();
|
||||
destination.mVTable = &inlineVTable<Callable>();
|
||||
source.mVTable = nullptr;
|
||||
},
|
||||
[]( SmallFunction& function ) noexcept {
|
||||
inlinePointer<Callable>( function )->~Callable();
|
||||
} };
|
||||
return table;
|
||||
}
|
||||
|
||||
template <typename Callable> static const VTable& heapVTable() {
|
||||
static const VTable table{
|
||||
[]( SmallFunction& function ) { ( *heapPointer<Callable>( function ) )(); },
|
||||
[]( SmallFunction& destination, const SmallFunction& source ) {
|
||||
heapPointer<Callable>( destination ) =
|
||||
new Callable( *heapPointer<Callable>( const_cast<SmallFunction&>( source ) ) );
|
||||
destination.mVTable = &heapVTable<Callable>();
|
||||
},
|
||||
[]( SmallFunction& destination, SmallFunction& source ) {
|
||||
heapPointer<Callable>( destination ) = heapPointer<Callable>( source );
|
||||
heapPointer<Callable>( source ) = nullptr;
|
||||
destination.mVTable = &heapVTable<Callable>();
|
||||
source.mVTable = nullptr;
|
||||
},
|
||||
[]( SmallFunction& function ) noexcept { delete heapPointer<Callable>( function ); } };
|
||||
return table;
|
||||
}
|
||||
|
||||
Storage mStorage;
|
||||
const VTable* mVTable{ nullptr };
|
||||
};
|
||||
|
||||
} // namespace EE
|
||||
|
||||
#endif
|
||||
@@ -1,8 +1,8 @@
|
||||
#ifndef EE_MATH_EASE
|
||||
#define EE_MATH_EASE
|
||||
|
||||
#include <eepp/system/functionstring.hpp>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
namespace EE { namespace Math {
|
||||
|
||||
@@ -118,7 +118,7 @@ class Ease {
|
||||
return "";
|
||||
}
|
||||
|
||||
static Interpolation fromName( const std::string& name,
|
||||
static Interpolation fromName( std::string_view name,
|
||||
const Interpolation& defaultInterpolation = Ease::Linear ) {
|
||||
if ( "linear" == name )
|
||||
return Ease::Linear;
|
||||
@@ -184,13 +184,22 @@ class Ease {
|
||||
return Ease::ElasticInOut;
|
||||
if ( "cubicbezier" == name || "cubic-bezier" == name )
|
||||
return Ease::CubizBezier;
|
||||
// Handle the case that the name is a function
|
||||
if ( name.find_first_of( '(' ) != std::string::npos ) {
|
||||
System::FunctionString func( System::FunctionString::parse( name ) );
|
||||
return fromName( func.getName(), defaultInterpolation );
|
||||
}
|
||||
// Function parameters do not participate in interpolation-name lookup.
|
||||
const auto functionStart = name.find_first_of( '(' );
|
||||
if ( functionStart != std::string_view::npos )
|
||||
return fromName( name.substr( 0, functionStart ), defaultInterpolation );
|
||||
return defaultInterpolation;
|
||||
}
|
||||
|
||||
static Interpolation fromName( const std::string& name,
|
||||
const Interpolation& defaultInterpolation = Ease::Linear ) {
|
||||
return fromName( std::string_view{ name }, defaultInterpolation );
|
||||
}
|
||||
|
||||
static Interpolation fromName( const char* name,
|
||||
const Interpolation& defaultInterpolation = Ease::Linear ) {
|
||||
return fromName( std::string_view{ name }, defaultInterpolation );
|
||||
}
|
||||
};
|
||||
|
||||
}} // namespace EE::Math
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef EE_SCENEACTION_HPP
|
||||
#define EE_SCENEACTION_HPP
|
||||
|
||||
#include <cstddef>
|
||||
#include <eepp/core.hpp>
|
||||
#include <eepp/system/time.hpp>
|
||||
using namespace EE::System;
|
||||
@@ -21,6 +22,18 @@ class EE_API Action {
|
||||
|
||||
virtual ~Action();
|
||||
|
||||
/** Allocates actions from a shared size-class pool. Existing Action factories and ownership
|
||||
* semantics are unchanged; completed slots are recycled by operator delete. */
|
||||
static void* operator new( std::size_t size );
|
||||
|
||||
static void operator delete( void* ptr ) noexcept;
|
||||
|
||||
static void operator delete( void* ptr, std::size_t size ) noexcept;
|
||||
|
||||
static void* operator new( std::size_t, void* place ) noexcept { return place; }
|
||||
|
||||
static void operator delete( void*, void* ) noexcept {}
|
||||
|
||||
/** Starts the action. */
|
||||
virtual void start() = 0;
|
||||
|
||||
@@ -91,7 +104,12 @@ class EE_API Action {
|
||||
|
||||
protected:
|
||||
friend class Node;
|
||||
typedef UnorderedMap<ActionType, UnorderedMap<Uint32, ActionCallback>> ActionCallbackMap;
|
||||
struct ActionCallbackEntry {
|
||||
ActionType type;
|
||||
Uint32 id;
|
||||
ActionCallback callback;
|
||||
};
|
||||
using ActionCallbackMap = SmallVector<ActionCallbackEntry, 2>;
|
||||
|
||||
Node* mNode{ nullptr };
|
||||
Action::UniqueID mId{ 0 };
|
||||
|
||||
@@ -43,6 +43,9 @@ class EE_API ActionManager {
|
||||
|
||||
std::vector<Action*> getActionsByTagFromTarget( Node* target, const Action::UniqueID& tag );
|
||||
|
||||
void getActionsByTagFromTarget( Node* target, const Action::UniqueID& tag,
|
||||
SmallVector<Action*, 4>& actions );
|
||||
|
||||
void update( const Time& time );
|
||||
|
||||
std::size_t count() const;
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
#ifndef EE_SCENE_ACTION_CALLBACK_HPP
|
||||
#define EE_SCENE_ACTION_CALLBACK_HPP
|
||||
|
||||
#include <eepp/core/small_function.hpp>
|
||||
#include <eepp/scene/actions/delay.hpp>
|
||||
#include <eepp/system/mutex.hpp>
|
||||
#include <functional>
|
||||
|
||||
namespace EE { namespace Scene { namespace Actions {
|
||||
|
||||
class EE_API Runnable : public Delay {
|
||||
public:
|
||||
typedef std::function<void()> RunnableFunc;
|
||||
using RunnableFunc = SmallFunction<48>;
|
||||
|
||||
static Runnable* New( RunnableFunc callback, const Time& time = Seconds( 0 ),
|
||||
bool loop = false );
|
||||
|
||||
@@ -42,11 +42,14 @@ class EE_API Sequence : public Action {
|
||||
virtual ~Sequence();
|
||||
|
||||
protected:
|
||||
std::vector<Action*> mSequence;
|
||||
using ActionContainer = SmallVector<Action*, 4>;
|
||||
ActionContainer mSequence;
|
||||
Time mDuration;
|
||||
Uint32 mCurPos;
|
||||
|
||||
Sequence( const std::vector<Action*> sequence );
|
||||
|
||||
Sequence( ActionContainer sequence );
|
||||
};
|
||||
|
||||
}}} // namespace EE::Scene::Actions
|
||||
|
||||
@@ -42,10 +42,13 @@ class EE_API Spawn : public Action {
|
||||
virtual ~Spawn();
|
||||
|
||||
protected:
|
||||
std::vector<Action*> mSpawn;
|
||||
using ActionContainer = SmallVector<Action*, 4>;
|
||||
ActionContainer mSpawn;
|
||||
bool mAllDone;
|
||||
|
||||
Spawn( const std::vector<Action*> spawn );
|
||||
|
||||
Spawn( ActionContainer spawn );
|
||||
};
|
||||
|
||||
}}} // namespace EE::Scene::Actions
|
||||
|
||||
@@ -1346,6 +1346,9 @@ class EE_API Node : public Transformable {
|
||||
*/
|
||||
std::vector<Action*> getActionsByTag( const Action::UniqueID& tag );
|
||||
|
||||
/** Appends matching actions to inline-capable storage without allocating in the common case. */
|
||||
void getActionsByTag( const Action::UniqueID& tag, SmallVector<Action*, 4>& actions );
|
||||
|
||||
/**
|
||||
* @brief Removes all actions from this node.
|
||||
*
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <eepp/core/string.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
namespace EE { namespace System {
|
||||
|
||||
@@ -14,6 +15,82 @@ class EE_API FunctionString {
|
||||
using Parameters = SmallVector<std::string, 4>;
|
||||
using TypeStringVector = SmallVector<bool, 4>;
|
||||
|
||||
class View {
|
||||
public:
|
||||
View() = default;
|
||||
|
||||
std::string_view getName() const { return mName; }
|
||||
|
||||
bool isEmpty() const { return mName.empty(); }
|
||||
|
||||
template <typename Callback> bool forEachParameter( Callback&& callback ) const {
|
||||
return FunctionString::forEachParameter( mParameters,
|
||||
std::forward<Callback>( callback ) );
|
||||
}
|
||||
|
||||
private:
|
||||
friend class FunctionString;
|
||||
|
||||
View( std::string_view name, std::string_view parameters ) :
|
||||
mName( name ), mParameters( parameters ) {}
|
||||
|
||||
std::string_view mName;
|
||||
std::string_view mParameters;
|
||||
};
|
||||
|
||||
static View parseView( std::string_view function );
|
||||
|
||||
/** Iterates a comma-separated parameter list without allocating. Nested parentheses and
|
||||
* quoted strings protect commas. Quoted parameters are reported without their outer quotes;
|
||||
* escaped quotes remain escaped because the returned views reference the original input.
|
||||
* The callback receives (parameter, parameterWasString) and returns whether to continue. */
|
||||
template <typename Callback>
|
||||
static bool forEachParameter( std::string_view parameters, Callback&& callback ) {
|
||||
std::size_t start = 0;
|
||||
int parenthesisDepth = 0;
|
||||
char quote = 0;
|
||||
bool escaped = false;
|
||||
|
||||
auto emit = [&]( std::size_t end ) {
|
||||
std::string_view parameter =
|
||||
String::trim( parameters.substr( start, end - start ), " \t\n\r\f\v" );
|
||||
bool wasString = parameter.size() >= 2 &&
|
||||
( parameter.front() == '\'' || parameter.front() == '"' ) &&
|
||||
parameter.back() == parameter.front();
|
||||
if ( wasString )
|
||||
parameter = parameter.substr( 1, parameter.size() - 2 );
|
||||
if ( parameter.empty() && !wasString )
|
||||
return true;
|
||||
return callback( parameter, wasString );
|
||||
};
|
||||
|
||||
for ( std::size_t i = 0; i < parameters.size(); ++i ) {
|
||||
const char character = parameters[i];
|
||||
if ( quote ) {
|
||||
if ( escaped ) {
|
||||
escaped = false;
|
||||
} else if ( character == '\\' ) {
|
||||
escaped = true;
|
||||
} else if ( character == quote ) {
|
||||
quote = 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if ( character == '\'' || character == '"' ) {
|
||||
quote = character;
|
||||
} else if ( character == '(' ) {
|
||||
++parenthesisDepth;
|
||||
} else if ( character == ')' && parenthesisDepth > 0 ) {
|
||||
--parenthesisDepth;
|
||||
} else if ( character == ',' && parenthesisDepth == 0 ) {
|
||||
if ( !emit( i ) )
|
||||
return false;
|
||||
start = i + 1;
|
||||
}
|
||||
}
|
||||
return emit( parameters.size() );
|
||||
}
|
||||
|
||||
static FunctionString parse( const std::string& function );
|
||||
|
||||
static FunctionString parse( std::string_view function );
|
||||
@@ -41,7 +118,7 @@ class EE_API FunctionString {
|
||||
Parameters parameters;
|
||||
TypeStringVector typeStringData;
|
||||
|
||||
template <typename StringType> static FunctionString parse( StringType function );
|
||||
static FunctionString parseOwned( std::string_view function );
|
||||
};
|
||||
|
||||
}} // namespace EE::System
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <eepp/math/ease.hpp>
|
||||
#include <eepp/system/time.hpp>
|
||||
#include <eepp/ui/css/stylesheetproperty.hpp>
|
||||
#include <eepp/ui/css/timingfunction.hpp>
|
||||
#include <vector>
|
||||
|
||||
using namespace EE::Math;
|
||||
@@ -56,8 +57,12 @@ class EE_API AnimationDefinition {
|
||||
|
||||
const Ease::Interpolation& getTimingFunction() const;
|
||||
|
||||
/** Kept for source compatibility. Internal animation code uses the inline view below so this
|
||||
* legacy vector is only materialized when an external caller requests it. */
|
||||
const std::vector<double>& getTimingFunctionParameters() const;
|
||||
|
||||
const TimingFunction::Parameters& getTimingFunctionParametersInline() const;
|
||||
|
||||
const AnimationFillMode& getFillMode() const;
|
||||
|
||||
void setName( const std::string& value );
|
||||
@@ -72,6 +77,8 @@ class EE_API AnimationDefinition {
|
||||
|
||||
void setTimingFunctionParameters( const std::vector<double>& timingFunctionParameters );
|
||||
|
||||
void setTimingFunctionParameters( const TimingFunction::Parameters& timingFunctionParameters );
|
||||
|
||||
void setDirection( const AnimationDirection& value );
|
||||
|
||||
void setFillMode( const AnimationFillMode& value );
|
||||
@@ -87,7 +94,9 @@ class EE_API AnimationDefinition {
|
||||
Time mDuration = Time::Zero;
|
||||
Int32 mIterations = 1; /* -1 == "infinite" */
|
||||
Ease::Interpolation mTimingFunction = Ease::Interpolation::Linear;
|
||||
std::vector<double> mTimingFunctionParameters{};
|
||||
TimingFunction::Parameters mTimingFunctionParameters{};
|
||||
mutable std::vector<double> mTimingFunctionParametersVector;
|
||||
mutable bool mTimingFunctionParametersVectorValid{ false };
|
||||
AnimationDirection mDirection = Normal;
|
||||
AnimationFillMode mFillMode = None;
|
||||
bool mPaused = false;
|
||||
@@ -98,7 +107,7 @@ inline bool operator==( const AnimationDefinition& a, const AnimationDefinition&
|
||||
a.getDelay() == b.getDelay() && a.getDirection() == b.getDirection() &&
|
||||
a.isPaused() == b.isPaused() && a.getIterations() == b.getIterations() &&
|
||||
a.getName() == b.getName() &&
|
||||
a.getTimingFunctionParameters() == b.getTimingFunctionParameters();
|
||||
a.getTimingFunctionParametersInline() == b.getTimingFunctionParametersInline();
|
||||
}
|
||||
|
||||
inline bool operator!=( const AnimationDefinition& a, const AnimationDefinition& b ) {
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <eepp/ui/css/propertyidset.hpp>
|
||||
#include <eepp/ui/css/stylesheetproperty.hpp>
|
||||
#include <eepp/ui/css/stylesheetstyle.hpp>
|
||||
#include <eepp/ui/css/transitiondefinition.hpp>
|
||||
|
||||
namespace EE { namespace UI { namespace CSS {
|
||||
|
||||
@@ -22,6 +23,8 @@ class EE_API ElementDefinition : NonCopyable {
|
||||
|
||||
const std::vector<const CSS::StyleSheetProperty*>& getTransitionProperties() const;
|
||||
|
||||
const ComputedTransitions& getTransitions() const;
|
||||
|
||||
const std::vector<const CSS::StyleSheetProperty*>& getAnimationProperties() const;
|
||||
|
||||
const StyleSheetVariables& getVariables() const;
|
||||
@@ -38,6 +41,7 @@ class EE_API ElementDefinition : NonCopyable {
|
||||
StyleSheetVariables mVariables;
|
||||
PropertyIdSet mPropertyIds;
|
||||
std::vector<const CSS::StyleSheetProperty*> mTransitionProperties;
|
||||
ComputedTransitions mTransitions;
|
||||
std::vector<const CSS::StyleSheetProperty*> mAnimationProperties;
|
||||
bool mStructurallyVolatile;
|
||||
|
||||
|
||||
@@ -58,12 +58,21 @@ class EE_API StyleSheetLength {
|
||||
|
||||
static StyleSheetLength fromString( const std::string& str, const Float& defaultValue = 0,
|
||||
bool pxAsDp = false );
|
||||
static StyleSheetLength fromString( std::string_view str, const Float& defaultValue = 0,
|
||||
bool pxAsDp = false );
|
||||
static StyleSheetLength fromString( const char* str, const Float& defaultValue = 0,
|
||||
bool pxAsDp = false ) {
|
||||
return fromString( std::string_view{ str }, defaultValue, pxAsDp );
|
||||
}
|
||||
|
||||
StyleSheetLength();
|
||||
|
||||
StyleSheetLength( const Float& val, const Unit& unit );
|
||||
|
||||
StyleSheetLength( const std::string& val, const Float& defaultValue = 0 );
|
||||
StyleSheetLength( std::string_view val, const Float& defaultValue = 0 );
|
||||
StyleSheetLength( const char* val, const Float& defaultValue = 0 ) :
|
||||
StyleSheetLength( std::string_view{ val }, defaultValue ) {}
|
||||
|
||||
StyleSheetLength( const StyleSheetLength& val );
|
||||
|
||||
@@ -98,7 +107,7 @@ class EE_API StyleSheetLength {
|
||||
protected:
|
||||
static bool isFunctionString( std::string_view str );
|
||||
|
||||
static bool parseFunction( const std::string& str, Unit& outUnit, Arguments& outArgs );
|
||||
static bool parseFunction( std::string_view str, Unit& outUnit, Arguments& outArgs );
|
||||
|
||||
Float resolveFunction( const Float& parentSize, const Sizef& viewSize, const Float& displayDpi,
|
||||
const Float& elFontSize, const Float& globalFontSize,
|
||||
|
||||
@@ -26,7 +26,7 @@ class EE_API StyleSheetPropertyAnimation : public Action {
|
||||
const PropertyDefinition* property, const std::string& startValue,
|
||||
const std::string& endValue,
|
||||
const Ease::Interpolation& timingFunction,
|
||||
const std::vector<double> timingFunctionParameters,
|
||||
const TimingFunction::Parameters& timingFunctionParameters,
|
||||
const Uint32& propertyIndex, const bool& isDone );
|
||||
|
||||
static StyleSheetPropertyAnimation* fromAnimationKeyframes(
|
||||
@@ -48,6 +48,13 @@ class EE_API StyleSheetPropertyAnimation : public Action {
|
||||
const std::vector<double>& timingFunctionParameters,
|
||||
const AnimationOrigin& animationOrigin );
|
||||
|
||||
static StyleSheetPropertyAnimation*
|
||||
New( const PropertyDefinition* property, const std::string& startValue,
|
||||
const std::string& endValue, const Uint32& propertyIndex, const Time& duration,
|
||||
const Time& delay, const Ease::Interpolation& timingFunction,
|
||||
const TimingFunction::Parameters& timingFunctionParameters,
|
||||
const AnimationOrigin& animationOrigin );
|
||||
|
||||
void start() override;
|
||||
|
||||
void stop() override;
|
||||
@@ -87,8 +94,8 @@ class EE_API StyleSheetPropertyAnimation : public Action {
|
||||
protected:
|
||||
AnimationDefinition mAnimation;
|
||||
const PropertyDefinition* mPropertyDef;
|
||||
std::vector<std::string> mStates;
|
||||
std::vector<Float> mAnimationStepsTime;
|
||||
SmallVector<std::string, 4> mStates;
|
||||
SmallVector<Float, 4> mAnimationStepsTime;
|
||||
Time mRealElapsed;
|
||||
Time mElapsed;
|
||||
Int32 mPendingIterations;
|
||||
@@ -103,6 +110,13 @@ class EE_API StyleSheetPropertyAnimation : public Action {
|
||||
std::vector<Float> animationStepsTime, const Uint32& propertyIndex,
|
||||
const AnimationOrigin& animationOrigin );
|
||||
|
||||
StyleSheetPropertyAnimation( const AnimationDefinition& animation,
|
||||
const PropertyDefinition* propertyDef,
|
||||
SmallVector<std::string, 4> states,
|
||||
SmallVector<Float, 4> animationStepsTime,
|
||||
const Uint32& propertyIndex,
|
||||
const AnimationOrigin& animationOrigin );
|
||||
|
||||
void onStart() override;
|
||||
|
||||
void onUpdate( const Time& time ) override;
|
||||
|
||||
@@ -1,20 +1,28 @@
|
||||
#ifndef EE_UI_CSS_TIMINGFUNCTION_HPP
|
||||
#define EE_UI_CSS_TIMINGFUNCTION_HPP
|
||||
|
||||
#include <eepp/core/small_vector.hpp>
|
||||
#include <eepp/core/string.hpp>
|
||||
#include <eepp/math/ease.hpp>
|
||||
|
||||
using namespace EE;
|
||||
using namespace EE::Math;
|
||||
|
||||
namespace EE { namespace UI { namespace CSS {
|
||||
|
||||
class EE_API TimingFunction {
|
||||
public:
|
||||
using Parameters = SmallVector<double, 4>;
|
||||
|
||||
static TimingFunction parse( std::string timingFunction );
|
||||
|
||||
static TimingFunction parse( std::string_view timingFunction );
|
||||
|
||||
static TimingFunction parse( const char* timingFunction ) {
|
||||
return parse( std::string_view{ timingFunction } );
|
||||
}
|
||||
|
||||
Ease::Interpolation interpolation{ Ease::None };
|
||||
std::vector<double> parameters;
|
||||
Parameters parameters;
|
||||
};
|
||||
|
||||
}}} // namespace EE::UI::CSS
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
#ifndef EE_UI_CSS_TRANSITIONDEFINITION_HPP
|
||||
#define EE_UI_CSS_TRANSITIONDEFINITION_HPP
|
||||
|
||||
#include <eepp/core/small_vector.hpp>
|
||||
#include <eepp/math/ease.hpp>
|
||||
#include <eepp/system/time.hpp>
|
||||
#include <eepp/ui/css/stylesheetproperty.hpp>
|
||||
#include <eepp/ui/css/timingfunction.hpp>
|
||||
#include <vector>
|
||||
|
||||
using namespace EE::Math;
|
||||
@@ -37,6 +39,33 @@ class EE_API TransitionDefinition {
|
||||
|
||||
typedef UnorderedMap<std::string, TransitionDefinition> TransitionsMap;
|
||||
|
||||
/** Compact transition data used by computed element definitions. It owns no strings and keeps
|
||||
* the complete CSS timing-function payload inline. */
|
||||
struct ComputedTransitionDefinition {
|
||||
String::HashType propertyNameHash{ 0 };
|
||||
Ease::Interpolation timingFunction{ Ease::Linear };
|
||||
TimingFunction::Parameters timingFunctionParameters;
|
||||
Time delay{ Time::Zero };
|
||||
Time duration{ Time::Zero };
|
||||
};
|
||||
|
||||
class EE_API ComputedTransitions {
|
||||
public:
|
||||
static ComputedTransitions
|
||||
parse( const std::vector<const StyleSheetProperty*>& styleSheetProperties );
|
||||
|
||||
const ComputedTransitionDefinition* get( String::HashType propertyNameHash ) const;
|
||||
|
||||
bool empty() const { return mTransitions.empty(); }
|
||||
|
||||
std::size_t size() const { return mTransitions.size(); }
|
||||
|
||||
private:
|
||||
SmallVector<ComputedTransitionDefinition, 4> mTransitions;
|
||||
|
||||
void set( const ComputedTransitionDefinition& transition );
|
||||
};
|
||||
|
||||
}}} // namespace EE::UI::CSS
|
||||
|
||||
#endif
|
||||
|
||||
@@ -96,7 +96,7 @@ class EE_API UINodeDrawable : public Drawable {
|
||||
|
||||
Sizef calcDrawableSize( const std::string& drawableSizeEq );
|
||||
|
||||
Vector2f calcPosition( std::string positionXEq, std::string positionYEq );
|
||||
Vector2f calcPosition( const std::string& positionXEq, const std::string& positionYEq );
|
||||
|
||||
const std::string& getPositionX() const;
|
||||
|
||||
|
||||
@@ -100,7 +100,6 @@ class EE_API UIStyle : public UIState {
|
||||
std::shared_ptr<CSS::StyleSheetStyle> mElementStyle;
|
||||
std::shared_ptr<CSS::ElementDefinition> mGlobalDefinition;
|
||||
std::shared_ptr<CSS::ElementDefinition> mDefinition;
|
||||
CSS::TransitionsMap mTransitions;
|
||||
CSS::AnimationsMap mAnimations;
|
||||
UnorderedSet<UIWidget*> mRelatedWidgets;
|
||||
UnorderedSet<UIWidget*> mSubscribedWidgets;
|
||||
|
||||
Reference in New Issue
Block a user