Skip to content

Commit 5f52283

Browse files
committed
Selection outline animation: use adaptive timing to improve responsiveness
By default, PD chooses different selection animation frame rates depending on the user's current performance settings (as set in `Tools > Options`). On older PCs and/or very complex magic wand selections, rendering the selection outline can take awhile. To avoid unresponsiveness, PD will now auto-adjust selection animation frame rates to compensate for very-long or very-short render times. This will make selection outline animation more fluid on faster PCs and/or simpler selections, while also improving responsiveness on slower PCs and/or complex selections.
1 parent a8a3a5a commit 5f52283

File tree

2 files changed

+47
-4
lines changed

2 files changed

+47
-4
lines changed

Classes/pdSelection.cls

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,8 @@ Private Const ANT_DASH_SIZE As Single = 4!
162162
Private Const ANT_DASH_SPEED_SLOW As Long = 200 'Frame time for marching ants animation, in ms; 200 = 5 fps (which is plenty)
163163
Private Const ANT_DASH_SPEED_NORMAL As Long = 67 '15 fps (which is plenty)
164164
Private Const ANT_DASH_SPEED_FAST As Long = 33 '30 fps (which is overkill)
165+
Private Const ANT_DASH_SPEED_MIN As Long = 16 '60 fps (potentially nonsense)
166+
Private Const ANT_DASH_ADAPTIVE_SPEED As Boolean = True 'New experiment: auto-determine ant speed based on render performance
165167
Private m_AntDashes() As Single, m_AntDashOffset As Single
166168

167169
'When in outline or marching ant rendering mode, the current on-screen outline (e.g. the selection outline *already transformed*
@@ -2574,7 +2576,7 @@ Private Sub CreateSelectionMask()
25742576
Else
25752577
m_WandImage.ResetDIB 0
25762578
End If
2577-
2579+
m_WandImage.SetInitialAlphaPremultiplicationState True
25782580
m_parentPDImage.GetCompositedImage m_WandImage
25792581

25802582
'In layer mode, however, we want to use the wand image *not* to store a copy of the
@@ -2588,6 +2590,7 @@ Private Sub CreateSelectionMask()
25882590
Else
25892591
m_WandImage.ResetDIB 0
25902592
End If
2593+
m_WandImage.SetInitialAlphaPremultiplicationState True
25912594

25922595
End If
25932596

@@ -4953,6 +4956,11 @@ Private Sub m_AntTimer_Timer()
49534956
'Disallow animations if an external object has forcibly suspended them
49544957
If m_AnimationsAllowed Then
49554958

4959+
'If rendering the outline takes too long (entirely possible on old PCs + complex magic wand selections),
4960+
' we want to reduce animation frame rate to compensate.
4961+
Dim startTime As Currency
4962+
VBHacks.GetHighResTime startTime
4963+
49564964
'Advance the current offset
49574965
m_AntDashOffset = m_AntDashOffset + 1!
49584966
If (m_AntDashOffset >= ANT_DASH_SIZE * 2) Then m_AntDashOffset = 0!
@@ -4968,10 +4976,45 @@ Private Sub m_AntTimer_Timer()
49684976
End If
49694977

49704978
If okayToRender Then
4979+
49714980
Dim tmpViewportParams As PD_ViewportParams
49724981
tmpViewportParams = Viewport.GetDefaultParamObject()
49734982
tmpViewportParams.curPOI = poi_ReuseLast
49744983
Viewport.Stage3_CompositeCanvas PDImages.GetActiveImage(), FormMain.MainCanvas(0), VarPtr(tmpViewportParams)
4984+
4985+
'If the rendering took longer than the timer frequency, reduce timer frequency to compensate
4986+
Dim timeTakenMS As Double
4987+
timeTakenMS = (VBHacks.GetTimerDifferenceNow(startTime) * 1000#)
4988+
4989+
If ANT_DASH_ADAPTIVE_SPEED Then
4990+
4991+
'Compare the render time to the current timer interval.
4992+
Dim intervalChange As Long, curInterval As Double
4993+
curInterval = m_AntTimer.Interval
4994+
4995+
'We are now going to modify the timer in 5% increments (but with a little extra math
4996+
' to ensure that at least 1 ms of time is added/removed, as relevant). Note that
4997+
' built-in Windows power management features can prevent these changes from mattering,
4998+
' but we'll potentially keep toying with the frame rate until a nice balance of
4999+
' responsiveness and fluidity is reached.
5000+
5001+
'If render time exceeds 75% of the timer interval, slow the animation to compensate.
5002+
If (timeTakenMS > curInterval * 0.75) Then
5003+
intervalChange = Int(curInterval * 1.05 - curInterval + 0.5)
5004+
If (intervalChange < 1) Then intervalChange = 1
5005+
5006+
'If render time takes less than 25% of the timer interval, increase animation fluidity
5007+
ElseIf (timeTakenMS < curInterval * 0.25) Then
5008+
intervalChange = Int(curInterval - curInterval * 0.95 + 0.5)
5009+
If (intervalChange > -1) Then intervalChange = -1
5010+
If (curInterval <= ANT_DASH_SPEED_MIN) Then intervalChange = 0
5011+
End If
5012+
5013+
'If a change was made, assign the new timer interval
5014+
If (intervalChange <> 0) Then m_AntTimer.Interval = curInterval + intervalChange
5015+
5016+
End If
5017+
49755018
Else
49765019
m_AntTimer.StopTimer
49775020
End If

PhotoDemon.vbp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Type=Exe
2-
Reference=*\G{50A7E9B0-70EF-11D1-B75A-00A0C90564FE}#1.0#0#..\..\Windows\SysWOW64\shell32.dll#Microsoft Shell Controls And Automation
3-
Reference=*\G{00020430-0000-0000-C000-000000000046}#2.0#0#..\..\Windows\SysWOW64\stdole2.tlb#OLE Automation
2+
Reference=*\G{50A7E9B0-70EF-11D1-B75A-00A0C90564FE}#1.0#0#\\?\C:\Windows\SysWOW64\shell32.dll#Microsoft Shell Controls And Automation
3+
Reference=*\G{00020430-0000-0000-C000-000000000046}#2.0#0#\\?\C:\Windows\SysWOW64\stdole2.tlb#OLE Automation
44
Module=PDMain; Modules\Main.bas
55
Module=Public_Constants; Modules\PublicConstants.bas
66
Module=Public_EnumsAndTypes; Modules\PublicEnumsAndTypes.bas
@@ -527,7 +527,7 @@ Description="PhotoDemon Photo Editor"
527527
CompatibleMode="0"
528528
MajorVer=2024
529529
MinorVer=4
530-
RevisionVer=22
530+
RevisionVer=24
531531
AutoIncrementVer=1
532532
ServerSupportFiles=0
533533
VersionComments="Copyright 2000-2024 Tanner Helland - photodemon.org"

0 commit comments

Comments
 (0)