mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-10-18 11:33:23 +03:00
A bunch of minor bug fixes related to incorrect pixel density usage in different widget types. Optimized drainAsyncResourceMainThreadQueue to avoid in most common cases heap-allocating and to correctly call functions in the right UISceneNode context.
This commit is contained in:
@@ -271,7 +271,7 @@ void UIListBox::setRowHeight() {
|
||||
fontSize =
|
||||
fontStyleConfig.getFont()->getFontHeight( fontStyleConfig.getFontCharacterSize() );
|
||||
|
||||
mRowHeight = PixelDensity::pxToDp( fontSize ) + PixelDensity::dpToPx( 4 );
|
||||
mRowHeight = PixelDensity::pxToDp( fontSize ) + 4;
|
||||
}
|
||||
|
||||
if ( tOldRowHeight != mRowHeight ) {
|
||||
|
||||
@@ -12,7 +12,7 @@ UILoader* UILoader::New() {
|
||||
UILoader::UILoader() :
|
||||
UIWidget( "loader" ),
|
||||
mRadius( 0 ),
|
||||
mOutlineThickness( PixelDensity::dpToPx( 8 ) ),
|
||||
mOutlineThickness( 8 ),
|
||||
mColor( Color::White ),
|
||||
mArcAngle( 0 ),
|
||||
mArcStartAngle( 0 ),
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#include <eepp/core/small_vector.hpp>
|
||||
#include <eepp/core/string.hpp>
|
||||
#include <eepp/graphics/fontservice.hpp>
|
||||
#include <eepp/graphics/fonttruetype.hpp>
|
||||
@@ -57,12 +58,13 @@ struct PendingAsyncResourceMainThread {
|
||||
enum class AsyncResourceMainThreadQueueState : Uint8 { Closed, Open, Closing };
|
||||
|
||||
std::mutex sAsyncResourceMainThreadMutex;
|
||||
std::vector<PendingAsyncResourceMainThread> sAsyncResourceMainThreadQueue;
|
||||
using AsyncResourceMainThreadQueue = SmallVector<PendingAsyncResourceMainThread, 4>;
|
||||
AsyncResourceMainThreadQueue sAsyncResourceMainThreadQueue;
|
||||
std::atomic<AsyncResourceMainThreadQueueState> sAsyncResourceMainThreadQueueState{
|
||||
AsyncResourceMainThreadQueueState::Closed };
|
||||
|
||||
void drainAsyncResourceMainThreadQueue() {
|
||||
std::vector<PendingAsyncResourceMainThread> pending;
|
||||
AsyncResourceMainThreadQueue pending;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock( sAsyncResourceMainThreadMutex );
|
||||
if ( sAsyncResourceMainThreadQueueState.load( std::memory_order_relaxed ) !=
|
||||
@@ -71,7 +73,7 @@ void drainAsyncResourceMainThreadQueue() {
|
||||
pending.swap( sAsyncResourceMainThreadQueue );
|
||||
}
|
||||
|
||||
std::vector<PendingAsyncResourceMainThread> delayed;
|
||||
AsyncResourceMainThreadQueue delayed;
|
||||
for ( auto& item : pending ) {
|
||||
if ( !UISceneNode::isAsyncResourceLoadCurrent( item.resourceState, item.generation ) )
|
||||
continue;
|
||||
@@ -82,8 +84,10 @@ void drainAsyncResourceMainThreadQueue() {
|
||||
}
|
||||
|
||||
UISceneNode* owner = item.resourceState->owner.load( std::memory_order_acquire );
|
||||
if ( owner && item.func )
|
||||
if ( owner && item.func ) {
|
||||
auto context = owner->makeCurrent();
|
||||
item.func( owner );
|
||||
}
|
||||
}
|
||||
|
||||
if ( !delayed.empty() ) {
|
||||
@@ -2323,8 +2327,10 @@ void UISceneNode::runAsyncResourceOnMainThread(
|
||||
if ( isAsyncResourceLoadCurrent( resourceState, generation ) && Engine::isMainThread() &&
|
||||
delay <= Time::Zero ) {
|
||||
UISceneNode* owner = resourceState->owner.load( std::memory_order_acquire );
|
||||
if ( owner )
|
||||
if ( owner ) {
|
||||
auto context = owner->makeCurrent();
|
||||
func( owner );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2342,7 +2348,7 @@ void UISceneNode::runAsyncResourceOnMainThread(
|
||||
}
|
||||
|
||||
void UISceneNode::openAsyncResourceMainThreadQueue() {
|
||||
std::vector<PendingAsyncResourceMainThread> stale;
|
||||
AsyncResourceMainThreadQueue stale;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock( sAsyncResourceMainThreadMutex );
|
||||
stale.swap( sAsyncResourceMainThreadQueue );
|
||||
@@ -2358,7 +2364,7 @@ void UISceneNode::beginAsyncResourceMainThreadQueueShutdown() {
|
||||
}
|
||||
|
||||
void UISceneNode::finishAsyncResourceMainThreadQueueShutdown() {
|
||||
std::vector<PendingAsyncResourceMainThread> pending;
|
||||
AsyncResourceMainThreadQueue pending;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock( sAsyncResourceMainThreadMutex );
|
||||
sAsyncResourceMainThreadQueueState.store( AsyncResourceMainThreadQueueState::Closed,
|
||||
|
||||
@@ -20,7 +20,7 @@ UIViewPager::UIViewPager() :
|
||||
mOrientation( UIOrientation::Horizontal ),
|
||||
mDragging( false ),
|
||||
mLocked( false ),
|
||||
mDragResistance( PixelDensity::dpToPx( 8 ) ),
|
||||
mDragResistance( 8 ),
|
||||
mInitialDisplacement( 0 ),
|
||||
mDisplacement( 0 ),
|
||||
mChangePagePercent( 0.33f ),
|
||||
|
||||
@@ -1011,7 +1011,7 @@ UIWidget* UIWidget::setPaddingBottom( const Float& paddingBottom ) {
|
||||
UIWidget* UIWidget::setPaddingPixels( const Rectf& padding ) {
|
||||
if ( padding != mPadding ) {
|
||||
mPaddingPx = padding;
|
||||
mPadding = PixelDensity::pxToDp( mPadding ).ceil();
|
||||
mPadding = PixelDensity::pxToDp( mPaddingPx ).ceil();
|
||||
onAutoSize();
|
||||
onPaddingChange();
|
||||
notifyLayoutAttrChange( LayoutInvalidation::Self );
|
||||
@@ -1023,7 +1023,7 @@ UIWidget* UIWidget::setPaddingPixels( const Rectf& padding ) {
|
||||
UIWidget* UIWidget::setPaddingPixelsLeft( const Float& paddingLeft ) {
|
||||
if ( paddingLeft != mPadding.Left ) {
|
||||
mPaddingPx.Left = paddingLeft;
|
||||
mPadding.Left = eeceil( PixelDensity::pxToDp( mPadding.Left ) );
|
||||
mPadding.Left = eeceil( PixelDensity::pxToDp( mPaddingPx.Left ) );
|
||||
onAutoSize();
|
||||
onPaddingChange();
|
||||
notifyLayoutAttrChange( LayoutInvalidation::Self );
|
||||
@@ -1035,7 +1035,7 @@ UIWidget* UIWidget::setPaddingPixelsLeft( const Float& paddingLeft ) {
|
||||
UIWidget* UIWidget::setPaddingPixelsRight( const Float& paddingRight ) {
|
||||
if ( paddingRight != mPadding.Right ) {
|
||||
mPaddingPx.Right = paddingRight;
|
||||
mPadding.Right = eeceil( PixelDensity::pxToDp( mPadding.Right ) );
|
||||
mPadding.Right = eeceil( PixelDensity::pxToDp( mPaddingPx.Right ) );
|
||||
onAutoSize();
|
||||
onPaddingChange();
|
||||
notifyLayoutAttrChange( LayoutInvalidation::Self );
|
||||
@@ -1047,7 +1047,7 @@ UIWidget* UIWidget::setPaddingPixelsRight( const Float& paddingRight ) {
|
||||
UIWidget* UIWidget::setPaddingPixelsTop( const Float& paddingTop ) {
|
||||
if ( paddingTop != mPadding.Top ) {
|
||||
mPaddingPx.Top = paddingTop;
|
||||
mPadding.Top = eeceil( PixelDensity::pxToDp( mPadding.Top ) );
|
||||
mPadding.Top = eeceil( PixelDensity::pxToDp( mPaddingPx.Top ) );
|
||||
onAutoSize();
|
||||
onPaddingChange();
|
||||
notifyLayoutAttrChange( LayoutInvalidation::Self );
|
||||
@@ -1059,7 +1059,7 @@ UIWidget* UIWidget::setPaddingPixelsTop( const Float& paddingTop ) {
|
||||
UIWidget* UIWidget::setPaddingPixelsBottom( const Float& paddingBottom ) {
|
||||
if ( paddingBottom != mPadding.Bottom ) {
|
||||
mPaddingPx.Bottom = paddingBottom;
|
||||
mPadding.Bottom = eeceil( PixelDensity::pxToDp( mPadding.Bottom ) );
|
||||
mPadding.Bottom = eeceil( PixelDensity::pxToDp( mPaddingPx.Bottom ) );
|
||||
onAutoSize();
|
||||
onPaddingChange();
|
||||
notifyLayoutAttrChange( LayoutInvalidation::Self );
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <eepp/window/engine.hpp>
|
||||
#include <eepp/window/input.hpp>
|
||||
#include <eepp/window/runtime.hpp>
|
||||
#include <thread>
|
||||
|
||||
using namespace EE;
|
||||
using namespace EE::Graphics;
|
||||
@@ -134,6 +135,53 @@ UTEST( UISceneNode, ScopedContextBindsNodesAndRestoresNestedScene ) {
|
||||
eeDelete( sceneA );
|
||||
}
|
||||
|
||||
UTEST( UISceneNode, AsyncResourceCallbacksBindOwnerSceneAndRestorePreviousScene ) {
|
||||
auto* engine = Engine::instance();
|
||||
auto* window = engine->getCurrentWindow();
|
||||
if ( !window ) {
|
||||
window = engine->createWindow( WindowSettings( 320, 240, "Async Resource Context Test",
|
||||
WindowStyle::Default, WindowBackend::Default,
|
||||
32, {}, 1, false, true ),
|
||||
ContextSettings( false, 0, 0, GLv_default, true, false ) );
|
||||
}
|
||||
|
||||
auto* sceneA = UISceneNode::New( window );
|
||||
auto* sceneB = UISceneNode::New( window );
|
||||
auto* sceneManager = SceneManager::instance();
|
||||
sceneManager->add( sceneA );
|
||||
sceneManager->add( sceneB );
|
||||
sceneManager->setCurrentUISceneNode( sceneA );
|
||||
|
||||
auto state = sceneB->getAsyncResourceLoadState();
|
||||
const Uint64 generation = state->generation.load( std::memory_order_acquire );
|
||||
bool immediateBound = false;
|
||||
bool queuedBound = false;
|
||||
{
|
||||
auto context = sceneA->makeCurrent();
|
||||
UISceneNode::runAsyncResourceOnMainThread( state, generation, [&]( UISceneNode* owner ) {
|
||||
immediateBound = owner == sceneB && sceneManager->getUISceneNode() == sceneB;
|
||||
} );
|
||||
EXPECT_EQ( sceneManager->getUISceneNode(), sceneA );
|
||||
|
||||
std::thread producer( [&] {
|
||||
UISceneNode::runAsyncResourceOnMainThread(
|
||||
state, generation, [&]( UISceneNode* owner ) {
|
||||
queuedBound = owner == sceneB && sceneManager->getUISceneNode() == sceneB;
|
||||
} );
|
||||
} );
|
||||
producer.join();
|
||||
sceneA->update( Time::Zero );
|
||||
EXPECT_EQ( sceneManager->getUISceneNode(), sceneA );
|
||||
}
|
||||
|
||||
EXPECT_TRUE( immediateBound );
|
||||
EXPECT_TRUE( queuedBound );
|
||||
sceneManager->remove( sceneB );
|
||||
sceneManager->remove( sceneA );
|
||||
eeDelete( sceneB );
|
||||
eeDelete( sceneA );
|
||||
}
|
||||
|
||||
class TestUIApplication : public UIApplication {
|
||||
public:
|
||||
using UIApplication::UIApplication;
|
||||
|
||||
Reference in New Issue
Block a user