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 7f38c09f..ef2db778 100644 --- a/source/actionscript/Common/skyui/components/list/ScrollingList.as +++ b/source/actionscript/Common/skyui/components/list/ScrollingList.as @@ -10,6 +10,10 @@ 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; + public var enableAnimation: Boolean = false; /* STAGE ELEMENTS */ @@ -39,10 +43,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; @@ -218,6 +225,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 +238,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 +333,21 @@ class skyui.components.list.ScrollingList extends skyui.components.list.BasicLis private function onScroll(event: Object) { - this.updateScrollPosition(Math.floor(event.position + 0.5)); + this.bDisableAnim = true; + try { + this.updateScrollPosition(Math.floor(event.position + 0.5)); + } finally { + 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/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 d5cc8a00..16942df4 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; @@ -21,13 +28,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; @@ -89,6 +106,59 @@ class skyui.components.list.TabularListEntry extends skyui.components.list.Basic } } + public function updateSelectionAnimation(isSelected: Boolean, a_list: ScrollingList) + { + if (isSelected) { + this.selectIndicator._visible = true; + + if (a_list.bDisableAnim || a_list.enableAnimation === false) { + 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) { + this.resetSelectionAnim(true); + 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) {} @@ -160,4 +230,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 aea644f8..e1a4b518 100644 --- a/source/actionscript/CraftingMenu/CraftingListEntry.as +++ b/source/actionscript/CraftingMenu/CraftingListEntry.as @@ -27,24 +27,24 @@ class CraftingListEntry extends skyui.components.list.TabularListEntry /* INITIALIZATION */ - - // @override TabularListEntry - public function initialize(a_index: Number, a_state: ListState) - { - super.initialize(); - - var iconLoader = new MovieClipLoader(); - iconLoader.addListener(this); - iconLoader.loadClip(a_state.iconSource, this.itemIcon); - - this.itemIcon._visible = false; - this.equipIcon._visible = false; - - for (var i = 0; this["textField" + i] != undefined; i++) - this["textField" + i]._visible = false; - } - - + + // @override TabularListEntry + public function initialize(a_index: Number, a_state: ListState) + { + super.initialize(a_index); + + var iconLoader = new MovieClipLoader(); + iconLoader.addListener(this); + iconLoader.loadClip(a_state.iconSource, this.itemIcon); + + this.itemIcon._visible = false; + this.equipIcon._visible = false; + + for (var i = 0; this["textField" + i] != undefined; i++) + this["textField" + i]._visible = false; + } + + /* PUBLIC FUNCTIONS */ // @override TabularListEntry diff --git a/source/actionscript/ItemMenus/InventoryListEntry.as b/source/actionscript/ItemMenus/InventoryListEntry.as index 3da89ed4..58533dab 100644 --- a/source/actionscript/ItemMenus/InventoryListEntry.as +++ b/source/actionscript/ItemMenus/InventoryListEntry.as @@ -31,24 +31,24 @@ class InventoryListEntry extends skyui.components.list.TabularListEntry /* INITIALIZATION */ - - // @override TabularListEntry - public function initialize(a_index: Number, a_state: ListState) - { - super.initialize(); - - var iconLoader = new MovieClipLoader(); - iconLoader.addListener(this); - iconLoader.loadClip(a_state.iconSource, this.itemIcon); - - this.itemIcon._visible = false; - this.equipIcon._visible = false; - - for (var i = 0; this["textField" + i] != undefined; i++) - this["textField" + i]._visible = false; - } - - + + // @override TabularListEntry + public function initialize(a_index: Number, a_state: ListState) + { + super.initialize(a_index); + + var iconLoader = new MovieClipLoader(); + iconLoader.addListener(this); + iconLoader.loadClip(a_state.iconSource, this.itemIcon); + + this.itemIcon._visible = false; + this.equipIcon._visible = false; + + for (var i = 0; this["textField" + i] != undefined; i++) + this["textField" + i]._visible = false; + } + + /* PUBLIC FUNCTIONS */ // @override TabularListEntry diff --git a/source/swfsources.cmake b/source/swfsources.cmake index 30284d33..2d2eced8 100644 --- a/source/swfsources.cmake +++ b/source/swfsources.cmake @@ -205,6 +205,7 @@ Add_SWF(craftingmenu } Common/skyui/components/list { BasicListEntry.as + TabularList.as TabularListEntry.as ScrollingList.as } @@ -661,6 +662,7 @@ Add_SWF(skyui_inventorylists } Common/skyui/components/list { BasicListEntry.as + TabularList.as TabularListEntry.as ScrollingList.as }