From 069d253b06ef75b40d3e251bf20dc46c05ec2927 Mon Sep 17 00:00:00 2001 From: dem0nd Date: Sat, 25 Apr 2026 20:44:56 +0300 Subject: [PATCH 1/5] feat: add a smooth animation for selecting an item in a list --- .../skyui/components/list/ScrollingList.as | 13 ++++ .../skyui/components/list/TabularListEntry.as | 77 ++++++++++++++++++- .../CraftingMenu/CraftingListEntry.as | 2 +- .../ItemMenus/InventoryListEntry.as | 2 +- 4 files changed, 91 insertions(+), 3 deletions(-) diff --git a/source/actionscript/Common/skyui/components/list/ScrollingList.as b/source/actionscript/Common/skyui/components/list/ScrollingList.as index 7f38c09f..796a2fb2 100644 --- a/source/actionscript/Common/skyui/components/list/ScrollingList.as +++ b/source/actionscript/Common/skyui/components/list/ScrollingList.as @@ -10,6 +10,9 @@ class skyui.components.list.ScrollingList extends skyui.components.list.BasicLis // The maximum allowed size. Actual size might be smaller if the list is not filled completely. private var _maxListIndex: Number; + // Flag that allows list Entry to disable their animation + public var bDisableAnim: Boolean = false; + public var lastSelectionAnimY: Number = -1; /* STAGE ELEMENTS */ @@ -218,6 +221,8 @@ class skyui.components.list.ScrollingList extends skyui.components.list.BasicLis this._selectedIndex = -1; this.calculateMaxScrollPosition(); + + this.bDisableAnim = true; this.UpdateList(); // Restore selection @@ -229,6 +234,8 @@ class skyui.components.list.ScrollingList extends skyui.components.list.BasicLis this.doSetSelectedIndex(entryClip.itemIndex, skyui.components.list.BasicList.SELECT_MOUSE); } + this.bDisableAnim = false; + if (this.onInvalidate) this.onInvalidate(); } @@ -322,12 +329,18 @@ class skyui.components.list.ScrollingList extends skyui.components.list.BasicLis private function onScroll(event: Object) { + this.bDisableAnim = true; this.updateScrollPosition(Math.floor(event.position + 0.5)); + this.bDisableAnim = false; } // @override BasicList private function doSetSelectedIndex(a_newIndex: Number, a_keyboardOrMouse: Number) { + if (this._selectedIndex == -1 && a_newIndex != -1) { + this.lastSelectionAnimY = -1; + } + if (this.disableSelection || a_newIndex == this._selectedIndex) return; diff --git a/source/actionscript/Common/skyui/components/list/TabularListEntry.as b/source/actionscript/Common/skyui/components/list/TabularListEntry.as index e659b907..0c0ca4a8 100644 --- a/source/actionscript/Common/skyui/components/list/TabularListEntry.as +++ b/source/actionscript/Common/skyui/components/list/TabularListEntry.as @@ -1,6 +1,13 @@ // @abstract class skyui.components.list.TabularListEntry extends skyui.components.list.BasicListEntry { + /* CONSTANTS */ + + private static var ANIM_FADE_STEP: Number = 10; + private static var ANIM_MAX_JUMP_Y: Number = 600; + private static var ANIM_Y_DECAY: Number = 0.6; + private static var ANIM_Y_EPSILON: Number = 0.5; + /* PRIVATE VARIABLES */ private var _layoutUpdateCount: Number = -1; @@ -13,13 +20,23 @@ class skyui.components.list.TabularListEntry extends skyui.components.list.Basic /* PUBLIC FUNCTIONS */ + // @override BasicListEntry + public function initialize(a_index: Number, a_list: BasicList) + { + // It is necessary that when navigating via the keyboard, when the cursor is on a list, + // the keyboard does not get stuck on the item that the mouse cursor is hovering over when moving down the list. + this.hitArea = this.background; + } + // @override BasicListEntry public function setEntry(a_entryObject: Object, a_state: ListState) { var layout: ListLayout = skyui.components.list.TabularList(a_state.list).layout; // Show select area if this is the current entry - this.selectIndicator._visible = (a_entryObject == a_state.list.selectedEntry); + var isSelected: Boolean = (a_entryObject == a_state.list.selectedEntry); + + this.updateSelectionAnimation(isSelected, a_state.list); var curLayoutUpdateCount = layout.layoutUpdateCount; @@ -81,6 +98,56 @@ class skyui.components.list.TabularListEntry extends skyui.components.list.Basic } } + public function updateSelectionAnimation(isSelected: Boolean, a_list: Object) + { + if (isSelected) { + this.selectIndicator._visible = true; + + if (a_list.bDisableAnim) { + this.resetSelectionAnim(true); + a_list.lastSelectionAnimY = this._y; + return; + } + + if (a_list.lastSelectionAnimY == undefined || a_list.lastSelectionAnimY == -1) { + this.selectIndicator._y = 0; + this.selectIndicator._alpha = 0; + a_list.lastSelectionAnimY = this._y; + + this.onEnterFrame = function() { + this.selectIndicator._alpha += skyui.components.list.TabularListEntry.ANIM_FADE_STEP; + if (this.selectIndicator._alpha >= 100) { + this.selectIndicator._alpha = 100; + delete this.onEnterFrame; + } + }; + return; + } + + var prevY: Number = a_list.lastSelectionAnimY; + var diffY: Number = prevY - this._y; + if (diffY == 0) return; + a_list.lastSelectionAnimY = this._y; + + if (Math.abs(diffY) < skyui.components.list.TabularListEntry.ANIM_MAX_JUMP_Y) { + this.selectIndicator._y = diffY; + this.selectIndicator._alpha = 100; + + this.onEnterFrame = function() { + this.selectIndicator._y *= skyui.components.list.TabularListEntry.ANIM_Y_DECAY; + if (Math.abs(this.selectIndicator._y) < skyui.components.list.TabularListEntry.ANIM_Y_EPSILON) { + this.selectIndicator._y = 0; + delete this.onEnterFrame; + } + }; + } else { + this.resetSelectionAnim(true); + } + } else { + this.resetSelectionAnim(false); + } + } + // Do any clip-specific tasks when the view was changed for this entry. // @abstract public function setSpecificEntryLayout(a_entryObject: Object, a_state: ListState) {} @@ -152,4 +219,12 @@ class skyui.components.list.TabularListEntry extends skyui.components.list.Basic return (cleanIndex == tabIndex) ? a_text : a_text.substring(0, cleanIndex); } + + private function resetSelectionAnim(a_visible: Boolean) + { + delete this.onEnterFrame; + this.selectIndicator._visible = a_visible; + this.selectIndicator._y = 0; + this.selectIndicator._alpha = 100; + } } diff --git a/source/actionscript/CraftingMenu/CraftingListEntry.as b/source/actionscript/CraftingMenu/CraftingListEntry.as index d5095cff..5f141641 100644 --- a/source/actionscript/CraftingMenu/CraftingListEntry.as +++ b/source/actionscript/CraftingMenu/CraftingListEntry.as @@ -23,7 +23,7 @@ class CraftingListEntry extends skyui.components.list.TabularListEntry // @override TabularListEntry public function initialize(a_index: Number, a_state: ListState) { - super.initialize(); + super.initialize(a_index); var iconLoader = new MovieClipLoader(); iconLoader.addListener(this); diff --git a/source/actionscript/ItemMenus/InventoryListEntry.as b/source/actionscript/ItemMenus/InventoryListEntry.as index dad2939f..bf46e92c 100644 --- a/source/actionscript/ItemMenus/InventoryListEntry.as +++ b/source/actionscript/ItemMenus/InventoryListEntry.as @@ -27,7 +27,7 @@ class InventoryListEntry extends skyui.components.list.TabularListEntry // @override TabularListEntry public function initialize(a_index: Number, a_state: ListState) { - super.initialize(); + super.initialize(a_index); var iconLoader = new MovieClipLoader(); iconLoader.addListener(this); From 6365e9424fce3fcfdb7c9c6d4564b89258dd1ff3 Mon Sep 17 00:00:00 2001 From: dem0nd Date: Sat, 25 Apr 2026 21:20:26 +0300 Subject: [PATCH 2/5] fix: niptick comments --- .../Common/skyui/components/list/ScrollingList.as | 14 ++++++++++---- .../skyui/components/list/TabularListEntry.as | 7 +++++-- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/source/actionscript/Common/skyui/components/list/ScrollingList.as b/source/actionscript/Common/skyui/components/list/ScrollingList.as index 796a2fb2..081f9321 100644 --- a/source/actionscript/Common/skyui/components/list/ScrollingList.as +++ b/source/actionscript/Common/skyui/components/list/ScrollingList.as @@ -42,10 +42,13 @@ class skyui.components.list.ScrollingList extends skyui.components.list.BasicLis if (a_newPosition == this._scrollPosition || a_newPosition < 0 || a_newPosition > this._maxScrollPosition) return; - if (this.scrollbar != undefined) + if (this.scrollbar != undefined) { this.scrollbar.position = a_newPosition; - else + } else { + this.bDisableAnim = true; this.updateScrollPosition(a_newPosition); + this.bDisableAnim = false; + } } private var _maxScrollPosition: Number = 0; @@ -330,8 +333,11 @@ class skyui.components.list.ScrollingList extends skyui.components.list.BasicLis private function onScroll(event: Object) { this.bDisableAnim = true; - this.updateScrollPosition(Math.floor(event.position + 0.5)); - this.bDisableAnim = false; + try { + this.updateScrollPosition(Math.floor(event.position + 0.5)); + } finally { + this.bDisableAnim = false; + } } // @override BasicList diff --git a/source/actionscript/Common/skyui/components/list/TabularListEntry.as b/source/actionscript/Common/skyui/components/list/TabularListEntry.as index 0c0ca4a8..4e99deda 100644 --- a/source/actionscript/Common/skyui/components/list/TabularListEntry.as +++ b/source/actionscript/Common/skyui/components/list/TabularListEntry.as @@ -98,7 +98,7 @@ class skyui.components.list.TabularListEntry extends skyui.components.list.Basic } } - public function updateSelectionAnimation(isSelected: Boolean, a_list: Object) + public function updateSelectionAnimation(isSelected: Boolean, a_list: ScrollingList) { if (isSelected) { this.selectIndicator._visible = true; @@ -126,7 +126,10 @@ class skyui.components.list.TabularListEntry extends skyui.components.list.Basic var prevY: Number = a_list.lastSelectionAnimY; var diffY: Number = prevY - this._y; - if (diffY == 0) return; + if (diffY == 0) { + this.resetSelectionAnim(true); + return; + } a_list.lastSelectionAnimY = this._y; if (Math.abs(diffY) < skyui.components.list.TabularListEntry.ANIM_MAX_JUMP_Y) { From 2ffd73e8caae25c8d36f1246be196a061c21fef3 Mon Sep 17 00:00:00 2001 From: dem0nd Date: Wed, 29 Apr 2026 11:21:53 +0300 Subject: [PATCH 3/5] feat: add setting for enable/disable smooth anim selection --- data/interface/skyui/config.txt | 6 ++++++ .../Common/skyui/components/list/ScrollingList.as | 1 + .../Common/skyui/components/list/TabularList.as | 3 +++ .../Common/skyui/components/list/TabularListEntry.as | 4 ++-- 4 files changed, 12 insertions(+), 2 deletions(-) diff --git a/data/interface/skyui/config.txt b/data/interface/skyui/config.txt index 0e81f432..bca6b0d3 100644 --- a/data/interface/skyui/config.txt +++ b/data/interface/skyui/config.txt @@ -32,6 +32,12 @@ itemcard.yOffset = 0 quantityMenu.minCount = 6 ; Number of items required to trigger quantity dialog. 0 is disabled +; ===================================================================================================================== +[ScrollingList] +; ===================================================================================================================== +selection.animation = true ; Enable/Disable Smooth Selection Animation (Selection Indicator) + + ; ===================================================================================================================== [Appearance] ; ===================================================================================================================== diff --git a/source/actionscript/Common/skyui/components/list/ScrollingList.as b/source/actionscript/Common/skyui/components/list/ScrollingList.as index 081f9321..e4b792d1 100644 --- a/source/actionscript/Common/skyui/components/list/ScrollingList.as +++ b/source/actionscript/Common/skyui/components/list/ScrollingList.as @@ -13,6 +13,7 @@ class skyui.components.list.ScrollingList extends skyui.components.list.BasicLis // Flag that allows list Entry to disable their animation public var bDisableAnim: Boolean = false; public var lastSelectionAnimY: Number = -1; + public var enableAnimation: Boolean = true; /* STAGE ELEMENTS */ diff --git a/source/actionscript/Common/skyui/components/list/TabularList.as b/source/actionscript/Common/skyui/components/list/TabularList.as index d0c6317f..a032c6e7 100644 --- a/source/actionscript/Common/skyui/components/list/TabularList.as +++ b/source/actionscript/Common/skyui/components/list/TabularList.as @@ -74,6 +74,9 @@ class skyui.components.list.TabularList extends skyui.components.list.ScrollingL { var config = event.config; + if (config.ScrollingList.selection.animation != undefined) + this.enableAnimation = config.ScrollingList.selection.animation; + if (this._platform != 0) { this._previousColumnKey = config["Input"].controls.gamepad.prevColumn; this._nextColumnKey = config["Input"].controls.gamepad.nextColumn; diff --git a/source/actionscript/Common/skyui/components/list/TabularListEntry.as b/source/actionscript/Common/skyui/components/list/TabularListEntry.as index 4e99deda..cad37113 100644 --- a/source/actionscript/Common/skyui/components/list/TabularListEntry.as +++ b/source/actionscript/Common/skyui/components/list/TabularListEntry.as @@ -102,8 +102,8 @@ class skyui.components.list.TabularListEntry extends skyui.components.list.Basic { if (isSelected) { this.selectIndicator._visible = true; - - if (a_list.bDisableAnim) { + + if (a_list.bDisableAnim || a_list.enableAnimation === false) { this.resetSelectionAnim(true); a_list.lastSelectionAnimY = this._y; return; From af2476e32b37f18111e1e070e12e7e78dcabc51c Mon Sep 17 00:00:00 2001 From: dem0nd Date: Wed, 29 Apr 2026 11:22:15 +0300 Subject: [PATCH 4/5] chore(inventory-list): import TabularList.as --- source/swfsources.cmake | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/swfsources.cmake b/source/swfsources.cmake index 699c9fb0..a1b4c316 100644 --- a/source/swfsources.cmake +++ b/source/swfsources.cmake @@ -122,6 +122,7 @@ Add_SWF(craftingmenu Common/skyui/filter/NameFilter.as Common/skyui/filter/SortFilter.as Common/skyui/components/list/BasicListEntry.as + Common/skyui/components/list/TabularList.as Common/skyui/components/list/TabularListEntry.as CraftingMenu/CraftingDataSetter.as CraftingMenu/CraftingIconSetter.as @@ -481,6 +482,7 @@ Add_SWF(skyui_inventorylists Common/skyui/filter/NameFilter.as Common/skyui/filter/SortFilter.as Common/skyui/components/list/BasicListEntry.as + Common/skyui/components/list/TabularList.as Common/skyui/components/list/TabularListEntry.as Common/skyui/components/list/ScrollingList.as ItemMenus/CategoryList.as From 2d941a445071d910e2318bc23bdc6bf1f0d02cdd Mon Sep 17 00:00:00 2001 From: dem0nd Date: Wed, 29 Apr 2026 11:26:08 +0300 Subject: [PATCH 5/5] chore: disable anim by default if parameter in config not found --- .../actionscript/Common/skyui/components/list/ScrollingList.as | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/actionscript/Common/skyui/components/list/ScrollingList.as b/source/actionscript/Common/skyui/components/list/ScrollingList.as index e4b792d1..ef2db778 100644 --- a/source/actionscript/Common/skyui/components/list/ScrollingList.as +++ b/source/actionscript/Common/skyui/components/list/ScrollingList.as @@ -13,7 +13,7 @@ class skyui.components.list.ScrollingList extends skyui.components.list.BasicLis // Flag that allows list Entry to disable their animation public var bDisableAnim: Boolean = false; public var lastSelectionAnimY: Number = -1; - public var enableAnimation: Boolean = true; + public var enableAnimation: Boolean = false; /* STAGE ELEMENTS */