Repository: Odie/skyui-vr Branch: master Commit: bbe0c3264e60 Files: 993 Total size: 4.5 MB Directory structure: gitextract_9k0d2l5e/ ├── .gitignore ├── .gitmodules ├── LICENSE ├── README.md ├── build/ │ ├── .gitignore │ ├── exported/ │ │ ├── skyui/ │ │ │ └── .gitkeep │ │ └── widgets/ │ │ └── skyui/ │ │ └── .gitkeep │ └── skyui/ │ └── config.txt ├── dist/ │ ├── .gitignore │ ├── Data/ │ │ ├── Interface/ │ │ │ ├── Translations/ │ │ │ │ ├── SkyUI_czech.txt │ │ │ │ ├── SkyUI_english.txt │ │ │ │ ├── SkyUI_french.txt │ │ │ │ ├── SkyUI_german.txt │ │ │ │ ├── SkyUI_italian.txt │ │ │ │ ├── SkyUI_japanese.txt │ │ │ │ ├── SkyUI_polish.txt │ │ │ │ ├── SkyUI_russian.txt │ │ │ │ └── SkyUI_spanish.txt │ │ │ └── skyui/ │ │ │ ├── config.txt │ │ │ └── res/ │ │ │ └── mcm_logo.dds │ │ ├── Readme - SkyUI.txt │ │ ├── Scripts/ │ │ │ ├── Headers/ │ │ │ │ ├── SKI_ConfigBase.psc │ │ │ │ └── SKI_QuestBase.psc │ │ │ └── Source/ │ │ │ ├── SKI_ActiveEffectsWidget.psc │ │ │ ├── SKI_ConfigBase.psc │ │ │ ├── SKI_ConfigManager.psc │ │ │ ├── SKI_ConfigMenu.psc │ │ │ ├── SKI_FavoritesManager.psc │ │ │ ├── SKI_Main.psc │ │ │ ├── SKI_PlayerInventoryHook.psc │ │ │ ├── SKI_PlayerLoadGameAlias.psc │ │ │ ├── SKI_QF_ConfigManagerInstance.psc │ │ │ ├── SKI_QuestBase.psc │ │ │ ├── SKI_SettingsManager.psc │ │ │ ├── SKI_WidgetBase.psc │ │ │ └── SKI_WidgetManager.psc │ │ ├── SkyUI_SE.esp │ │ └── fomod/ │ │ ├── info.xml │ │ └── script.cs │ ├── Examples/ │ │ └── MCM/ │ │ ├── ConfigMenuTemplate.psc │ │ ├── ExampleConfigMenu.esp │ │ └── ExampleConfigMenu.psc │ ├── bsascript.txt │ ├── filegroup_all.txt │ ├── filegroup_interface.txt │ ├── filegroup_misc.txt │ ├── filegroup_scripts.txt │ ├── make_all.pl │ ├── make_archive.pl │ └── make_scripts.pl ├── misc/ │ ├── ArrowCount/ │ │ ├── Interface/ │ │ │ └── exported/ │ │ │ └── widgets/ │ │ │ └── skyui/ │ │ │ └── arrowcount.swf │ │ └── Scripts/ │ │ └── Source/ │ │ └── PN_ArrowCountWidget.psc │ ├── Configs/ │ │ ├── 5760x1080, by Ismelda/ │ │ │ └── skyui.cfg │ │ ├── 5760x2160, by Ismelda/ │ │ │ └── skyui.cfg │ │ └── ValueWeight Column/ │ │ └── skyui.cfg │ ├── Flash Util/ │ │ ├── SkyUI - make_all.jsfl │ │ ├── SkyUI - make_archive (fast).jsfl │ │ ├── SkyUI - make_archive.jsfl │ │ ├── build-all.jsfl │ │ └── skyui_runscript.bat │ ├── Icon Themes/ │ │ ├── Celtic, by GreatClone/ │ │ │ ├── skyui_icons_cat.swf │ │ │ └── skyui_icons_inv.swf │ │ ├── Curved, by T3T/ │ │ │ ├── skyui_icons_cat.swf │ │ │ └── skyui_icons_inv.swf │ │ └── Straight, by T3T/ │ │ ├── skyui_icons_cat.swf │ │ └── skyui_icons_inv.swf │ ├── Original Translates/ │ │ ├── Translate_ENGLISH.txt │ │ ├── Translate_FRENCH.txt │ │ ├── Translate_GERMAN.txt │ │ ├── Translate_ITALIAN.txt │ │ ├── Translate_Japanese.txt │ │ ├── Translate_RUSSIAN.txt │ │ ├── Translate_SPANISH.txt │ │ ├── Translate_czech.txt │ │ └── translate_polish.txt │ ├── PrimaryNeeds/ │ │ ├── Interface/ │ │ │ └── exported/ │ │ │ └── widgets/ │ │ │ └── pnx/ │ │ │ └── statusicons.swf │ │ ├── PrimaryNeeds.esp │ │ └── Scripts/ │ │ ├── PN_FoodEffect.pex │ │ ├── PN_IconWidget.pex │ │ ├── PN_NeedsManager.pex │ │ └── Source/ │ │ ├── PN_FoodEffect.psc │ │ ├── PN_IconWidget.psc │ │ └── PN_NeedsManager.psc │ ├── Translations/ │ │ ├── SkyUI_Translations.txt │ │ └── make_translations.pl │ ├── cp-built-files │ ├── decompile-pex │ ├── pack-release │ ├── rename-png │ └── reorder-psc ├── sksevr_plugin/ │ ├── .editorconfig │ ├── .gitignore │ ├── README.md │ ├── build.ini │ ├── build.py │ ├── lib/ │ │ └── openvr_api.lib │ ├── lua/ │ │ ├── MainEntry.lua │ │ ├── defaults-general.lua │ │ ├── defaults-knuckles.lua │ │ ├── defaults-oculus.lua │ │ ├── defaults-vive.lua │ │ ├── defaults-wmr.lua │ │ └── inspect.lua │ ├── lua-tests/ │ │ └── core_spec.lua │ ├── luajit.vcxproj │ ├── plugin/ │ │ ├── ControllerStateHook.cpp │ │ ├── ControllerStateHook.h │ │ ├── FormDB.cpp │ │ ├── FormDB.h │ │ ├── Globals.h │ │ ├── Keyboard.cpp │ │ ├── Keyboard.h │ │ ├── PapyrusUIFix.cpp │ │ ├── PapyrusUIFix.h │ │ ├── ScaleformExtendedDataFix.cpp │ │ ├── ScaleformExtendedDataFix.h │ │ ├── Settings.cpp │ │ ├── Settings.h │ │ ├── VRHookAPI.h │ │ ├── exports.def │ │ ├── guicon.cpp │ │ ├── guicon.h │ │ ├── lua_glue.cpp │ │ ├── lua_glue.h │ │ ├── main.cpp │ │ ├── plugin.vcxproj │ │ ├── plugin.vcxproj.filters │ │ └── scripts/ │ │ └── ExportPlugin.psc │ ├── plugin.sln │ └── tools/ │ └── run-lua-tests └── src/ ├── .gitignore ├── CLIK/ │ ├── Mouse.as │ ├── Selection.as │ ├── Stage.as │ ├── System/ │ │ └── capabilities.as │ └── gfx/ │ ├── controls/ │ │ ├── Button.as │ │ ├── ButtonBar.as │ │ ├── ButtonGroup.as │ │ ├── CoreList.as │ │ ├── OptionStepper.as │ │ ├── RadioButton.as │ │ ├── ScrollBar.as │ │ ├── ScrollIndicator.as │ │ ├── ScrollingList.as │ │ ├── Slider.as │ │ ├── TextArea.as │ │ └── TextInput.as │ ├── core/ │ │ └── UIComponent.as │ ├── data/ │ │ └── DataProvider.as │ ├── events/ │ │ └── EventDispatcher.as │ ├── io/ │ │ └── GameDelegate.as │ ├── managers/ │ │ ├── FocusHandler.as │ │ └── InputDelegate.as │ ├── ui/ │ │ ├── InputDetails.as │ │ └── NavigationCode.as │ └── utils/ │ ├── Constraints.as │ └── Locale.as ├── Common/ │ ├── Components/ │ │ ├── BlinkOnDemandMeter.as │ │ ├── BlinkOnEmptyMeter.as │ │ ├── CrossPlatformButtons.as │ │ ├── DeltaMeter.as │ │ ├── Meter.as │ │ └── UniformTimeMeter.as │ ├── MouseRotationInputCatcher.as │ ├── QuantitySlider.as │ ├── SaveLoadPanel.as │ ├── Shared/ │ │ ├── BSScrollingList.as │ │ ├── ButtonChange.as │ │ ├── ButtonTextArtHolder.as │ │ ├── CenteredScrollingList.as │ │ ├── ExtractPlatformText.as │ │ ├── GlobalFunc.as │ │ ├── ListFilterer.as │ │ ├── Macros.as │ │ ├── PlatformChangeUser.as │ │ └── Platforms.as │ ├── mx/ │ │ └── transitions/ │ │ └── Tween.as │ ├── skse.as │ └── skyui/ │ ├── VRInput.as │ ├── components/ │ │ ├── BottomBarMappedButton.as │ │ ├── ButtonPanel.as │ │ ├── MappedButton.as │ │ ├── MaskedTextArea.as │ │ ├── Meter.as │ │ ├── SearchWidget.as │ │ ├── Slider.as │ │ ├── TabBar.as │ │ ├── colorswatch/ │ │ │ ├── ColorSquare.as │ │ │ └── ColorSwatch.as │ │ ├── dialog/ │ │ │ ├── BasicDialog.as │ │ │ └── ColumnSelectDialog.as │ │ └── list/ │ │ ├── BSList.as │ │ ├── BasicEnumeration.as │ │ ├── BasicList.as │ │ ├── BasicListEntry.as │ │ ├── ButtonList.as │ │ ├── ButtonListEntry.as │ │ ├── ColumnDescriptor.as │ │ ├── ColumnLayoutData.as │ │ ├── EntryClipManager.as │ │ ├── FilteredEnumeration.as │ │ ├── IEntryEnumeration.as │ │ ├── IListProcessor.as │ │ ├── ListLayout.as │ │ ├── ListLayoutManager.as │ │ ├── ListState.as │ │ ├── ScrollingList.as │ │ ├── SortedListHeader.as │ │ ├── TabularList.as │ │ └── TabularListEntry.as │ ├── defines/ │ │ ├── Actor.as │ │ ├── Armor.as │ │ ├── ButtonArtNames.as │ │ ├── Form.as │ │ ├── Input.as │ │ ├── Inventory.as │ │ ├── Item.as │ │ ├── Magic.as │ │ ├── Material.as │ │ ├── Screen.as │ │ └── Weapon.as │ ├── filter/ │ │ ├── IFilter.as │ │ ├── ItemTypeFilter.as │ │ ├── NameFilter.as │ │ └── SortFilter.as │ ├── props/ │ │ ├── CompoundProperty.as │ │ ├── ItemFilter.as │ │ ├── PropertyDataExtender.as │ │ └── PropertyLookup.as │ └── util/ │ ├── ColorFunctions.as │ ├── ConfigManager.as │ ├── Debug.as │ ├── DialogManager.as │ ├── EffectIconMap.as │ ├── GlobalFunctions.as │ ├── Hash.as │ ├── Input.as │ ├── MarkupParser.as │ ├── Translator.as │ └── Tween.as ├── CraftingMenu/ │ ├── CraftingDataSetter.as │ ├── CraftingIconSetter.as │ ├── CraftingListEntry.as │ ├── CraftingLists.as │ ├── CraftingMenu.as │ ├── CustomAlchemyDataSetter.as │ ├── CustomConstructDataSetter.as │ ├── EnchantingBar.as │ ├── IconTabList.as │ ├── IconTabListEntry.as │ └── craftingmenu.fla ├── Enderal/ │ ├── ButtonGrid.as │ ├── ButtonGridEntry.as │ ├── DataLoader.as │ ├── SkillMenu.as │ ├── SkillMenu.fla │ ├── SkillMenu.swf │ ├── SkillMenuData.txt │ ├── SkillTreeEntry.as │ └── SkillTreeView.as ├── FavoritesMenu/ │ ├── FavoritesIconSetter.as │ ├── FavoritesListEntry.as │ ├── FavoritesMenu.as │ ├── FilterDataExtender.as │ ├── GroupButton.as │ ├── GroupDataExtender.as │ └── favoritesmenu.fla ├── HUDWidgets/ │ ├── WidgetLoader.as │ ├── activeeffects.fla │ ├── arrowcount.fla │ ├── meter.fla │ ├── minimap.fla │ ├── pnx/ │ │ └── widgets/ │ │ └── StatusIconWidget.as │ ├── skyui/ │ │ └── widgets/ │ │ ├── WidgetBase.as │ │ ├── activeeffects/ │ │ │ ├── ActiveEffect.as │ │ │ ├── ActiveEffectsGroup.as │ │ │ └── ActiveEffectsWidget.as │ │ ├── arrowcount/ │ │ │ └── ArrowCountWidget.as │ │ ├── meter/ │ │ │ └── MeterWidget.as │ │ ├── minimap/ │ │ │ └── MiniMapWidget.as │ │ └── status/ │ │ └── StatusWidget.as │ ├── status.fla │ ├── statusicons.fla │ └── widgetloader.fla ├── ItemMenus/ │ ├── BarterDataSetter.as │ ├── BarterMenu.as │ ├── BottomBar.as │ ├── CategoryList.as │ ├── CategoryListEntry.as │ ├── ContainerMenu.as │ ├── GiftMenu.as │ ├── InventoryDataSetter.as │ ├── InventoryIconSetter.as │ ├── InventoryListEntry.as │ ├── InventoryLists.as │ ├── InventoryMenu.as │ ├── ItemCard.as │ ├── ItemMenu.as │ ├── ItemcardDataExtender.as │ ├── MagicDataSetter.as │ ├── MagicIconSetter.as │ ├── MagicMenu.as │ ├── bartermenu.fla │ ├── bottombar.fla │ ├── containermenu.fla │ ├── giftmenu.fla │ ├── inventorylists.fla │ ├── inventorymenu.fla │ ├── itemcard.fla │ └── magicmenu.fla ├── MapMenu/ │ ├── Map/ │ │ ├── LocalMap.as │ │ ├── LocationFinder.as │ │ ├── LocationListEntry.as │ │ ├── MapMarker.as │ │ ├── MapMenu.as │ │ └── MarkerDescription.as │ └── map.fla ├── MessageBox/ │ ├── MessageBox.as │ └── messagebox.fla ├── ModConfigPanel/ │ ├── ColorDialog.as │ ├── ConfigPanel.as │ ├── MenuDialog.as │ ├── MessageDialog.as │ ├── ModListPanel.as │ ├── MultiColumnScrollBar.as │ ├── MultiColumnScrollingList.as │ ├── OptionDialog.as │ ├── OptionsListEntry.as │ ├── ParticleEmitter.as │ ├── SkyUISplash.as │ ├── SliderDialog.as │ ├── SnowEffect.as │ ├── TextLoader.as │ ├── TextLoader.fla │ ├── configpanel.fla │ ├── mcm_splash.fla │ └── skyui_splash.fla ├── PauseMenu/ │ ├── InputMappingArt.as │ ├── InputMappingList.as │ ├── JournalBottomBar.as │ ├── JournalSaveLoadList.as │ ├── ObjectiveScrollingList.as │ ├── OptionsList.as │ ├── QuestCenteredList.as │ ├── Quest_Journal.as │ ├── QuestsPage.as │ ├── SettingsOptionItem.as │ ├── StatsList.as │ ├── StatsPage.as │ ├── SystemPage.as │ └── quest_journal/ │ ├── DOMDocument.xml │ ├── LIBRARY/ │ │ ├── ButtonArt.xml │ │ ├── ButtonBG.xml │ │ ├── ButtonPanel.xml │ │ ├── DialogButton.xml │ │ ├── Divider.xml │ │ ├── Graphic/ │ │ │ └── ButtonBG Shape.xml │ │ ├── InputMappingArt.xml │ │ ├── InputMappingArtBG.xml │ │ ├── JournalBottomBarCenterReference.xml │ │ ├── MappedButton.xml │ │ ├── MovieClips/ │ │ │ ├── ButtonArtBackground.xml │ │ │ ├── ConfigPanelFader.xml │ │ │ ├── ConfirmPanel.xml │ │ │ ├── ConfirmText.xml │ │ │ ├── EquipIcon.xml │ │ │ ├── HelpList.xml │ │ │ ├── HelpListEntry.xml │ │ │ ├── HelpListPanel.xml │ │ │ ├── HelpTextButtonArtHolder.xml │ │ │ ├── HelpTextHolder.xml │ │ │ ├── HelpTextPanel.xml │ │ │ ├── InputMappingList.xml │ │ │ ├── InputMappingListEntry.xml │ │ │ ├── InputMappingListScrollArrow.xml │ │ │ ├── InputMappingPanel.xml │ │ │ ├── JournalBackground.xml │ │ │ ├── JournalBottomBar.xml │ │ │ ├── JournalTab.xml │ │ │ ├── JournalTabEnd.xml │ │ │ ├── LevelMeterRect.xml │ │ │ ├── LevelProgressBar.xml │ │ │ ├── MeterBar.xml │ │ │ ├── MeterBarBackground.xml │ │ │ ├── MeterBarColor.xml │ │ │ ├── MeterMask.xml │ │ │ ├── ObjectiveListItem.xml │ │ │ ├── ObjectiveScrollingList.xml │ │ │ ├── ObjectivesHeader.xml │ │ │ ├── OptionStepperArrowBtn.xml │ │ │ ├── OptionsLists.xml │ │ │ ├── OptionsListsList.xml │ │ │ ├── OptionsListsListEntry.xml │ │ │ ├── OptionsListsPanel.xml │ │ │ ├── PCQuitList.xml │ │ │ ├── PCQuitListEntry.xml │ │ │ ├── PCQuitPanel.xml │ │ │ ├── PlayerInfoText.xml │ │ │ ├── QuestJournalBase.xml │ │ │ ├── QuestJournalFader.xml │ │ │ ├── QuestTitleEndpieces.xml │ │ │ ├── QuestTitleHolder.xml │ │ │ ├── QuestTitleList.xml │ │ │ ├── QuestTitleListEntry.xml │ │ │ ├── QuestTitleListEntryCentered.xml │ │ │ ├── QuestTitleListEntryDivider.xml │ │ │ ├── QuestsFader.xml │ │ │ ├── QuestsPage.xml │ │ │ ├── SaveLoadList.xml │ │ │ ├── SaveLoadListEntry.xml │ │ │ ├── SaveLoadPanel.xml │ │ │ ├── ScreenshotHolder.xml │ │ │ ├── ScrollableText.xml │ │ │ ├── SettingsCheckBox.xml │ │ │ ├── SettingsCheckBoxBackground.xml │ │ │ ├── SettingsCheckBoxCheck.xml │ │ │ ├── SettingsList.xml │ │ │ ├── SettingsListEntry.xml │ │ │ ├── SettingsOptionStepper.xml │ │ │ ├── SettingsPanel.xml │ │ │ ├── StatsCategoryListEntry.xml │ │ │ ├── StatsCategoryListEntryCentered.xml │ │ │ ├── StatsCategoryListHolder.xml │ │ │ ├── StatsCategoryListList.xml │ │ │ ├── StatsFader.xml │ │ │ ├── StatsList.xml │ │ │ ├── StatsListEntry.xml │ │ │ ├── StatsPage.xml │ │ │ ├── SystemCategoriesList.xml │ │ │ ├── SystemCategoriesListEntry.xml │ │ │ ├── SystemCategoriesListEntryCentered.xml │ │ │ ├── SystemCategoryList.xml │ │ │ ├── SystemFader.xml │ │ │ └── SystemPage.xml │ │ ├── Shapes/ │ │ │ ├── BackgroundRect.xml │ │ │ ├── Endpieces_DLC01.xml │ │ │ ├── Endpieces_DLC02.xml │ │ │ ├── MeterBackground.xml │ │ │ ├── Shape 122.xml │ │ │ ├── Shape 398.xml │ │ │ ├── Shape 400.xml │ │ │ ├── Shape 407.xml │ │ │ ├── Shape 409.xml │ │ │ ├── Shape 411.xml │ │ │ ├── Shape 414.xml │ │ │ ├── Shape 417.xml │ │ │ ├── Shape 432.xml │ │ │ ├── Shape 433.xml │ │ │ ├── Shape 435.xml │ │ │ ├── Shape 439.xml │ │ │ ├── Shape 440.xml │ │ │ ├── Shape 441.xml │ │ │ ├── Shape 442.xml │ │ │ ├── Shape 443.xml │ │ │ ├── Shape 444.xml │ │ │ ├── Shape 445.xml │ │ │ ├── Shape 446.xml │ │ │ ├── Shape 447.xml │ │ │ ├── Shape 468.xml │ │ │ ├── Shape 493.xml │ │ │ ├── Shape 499.xml │ │ │ ├── Shape 505.xml │ │ │ ├── Shape 507.xml │ │ │ ├── Shape 541.xml │ │ │ ├── Shape 548.xml │ │ │ ├── Shape 552.xml │ │ │ ├── Shape 556.xml │ │ │ ├── Shape 558.xml │ │ │ ├── Shape 560.xml │ │ │ ├── Shape 562.xml │ │ │ ├── Shape 569.xml │ │ │ ├── Shape 571.xml │ │ │ ├── Shape 573.xml │ │ │ ├── Shape 575.xml │ │ │ └── Shape 577.xml │ │ ├── TextArea.xml │ │ ├── scrollBar.xml │ │ ├── scrollBarAssets/ │ │ │ ├── scrollBarGraphics/ │ │ │ │ ├── scrollBarOption_thumb_shape.xml │ │ │ │ ├── scrollBar_cap_shape.xml │ │ │ │ ├── scrollBar_thumb_shape.xml │ │ │ │ └── scrollBar_track_shape.xml │ │ │ ├── scrollBarOption_thumb.xml │ │ │ ├── scrollBar_downArrow.xml │ │ │ ├── scrollBar_thumb.xml │ │ │ ├── scrollBar_track.xml │ │ │ └── scrollBar_upArrow.xml │ │ └── scrollBarOption.xml │ ├── META-INF/ │ │ └── metadata.xml │ ├── MobileSettings.xml │ ├── PublishSettings.xml │ ├── bin/ │ │ └── SymDepend.cache │ └── quest_journal.xfl ├── Resources/ │ ├── Assets/ │ │ ├── maskedtextarea.fla │ │ ├── meter.fla │ │ └── scrollbar.fla │ ├── buttonArt/ │ │ ├── DOMDocument.xml │ │ ├── LIBRARY/ │ │ │ ├── ButtonArt.xml │ │ │ ├── ButtonArtBackgrounds/ │ │ │ │ ├── BackgroundBig.xml │ │ │ │ ├── BackgroundLarge.xml │ │ │ │ ├── BackgroundLeft.xml │ │ │ │ ├── BackgroundMedium.xml │ │ │ │ ├── BackgroundRight.xml │ │ │ │ ├── BackgroundRound.xml │ │ │ │ └── BackgroundSmall.xml │ │ │ ├── Controller/ │ │ │ │ ├── 360/ │ │ │ │ │ ├── Back.xml │ │ │ │ │ ├── LB.xml │ │ │ │ │ ├── LS.xml │ │ │ │ │ ├── LSPress.xml │ │ │ │ │ ├── LT.xml │ │ │ │ │ ├── RB.xml │ │ │ │ │ ├── RS.xml │ │ │ │ │ ├── RSPress.xml │ │ │ │ │ └── RT.xml │ │ │ │ ├── PS3/ │ │ │ │ │ ├── Circle.xml │ │ │ │ │ ├── L1.xml │ │ │ │ │ ├── L2.xml │ │ │ │ │ ├── L3.xml │ │ │ │ │ ├── PS3X.xml │ │ │ │ │ ├── R1.xml │ │ │ │ │ ├── R2.xml │ │ │ │ │ ├── R3.xml │ │ │ │ │ ├── Select.xml │ │ │ │ │ ├── Square.xml │ │ │ │ │ └── Triangle.xml │ │ │ │ └── Start.xml │ │ │ ├── FunctionKeys/ │ │ │ │ ├── Alt.xml │ │ │ │ ├── Backspace.xml │ │ │ │ ├── BackspaceWithArrow.xml │ │ │ │ ├── Caps.xml │ │ │ │ ├── Ctrl.xml │ │ │ │ ├── Del.xml │ │ │ │ ├── End.xml │ │ │ │ ├── Enter.xml │ │ │ │ ├── EnterWithArrow.xml │ │ │ │ ├── Esc.xml │ │ │ │ ├── F1.xml │ │ │ │ ├── F10.xml │ │ │ │ ├── F11.xml │ │ │ │ ├── F12.xml │ │ │ │ ├── F2.xml │ │ │ │ ├── F3.xml │ │ │ │ ├── F4.xml │ │ │ │ ├── F5.xml │ │ │ │ ├── F6.xml │ │ │ │ ├── F7.xml │ │ │ │ ├── F8.xml │ │ │ │ ├── F9.xml │ │ │ │ ├── Home.xml │ │ │ │ ├── Ins.xml │ │ │ │ ├── LAlt.xml │ │ │ │ ├── LCtrl.xml │ │ │ │ ├── NumLck.xml │ │ │ │ ├── Pause.xml │ │ │ │ ├── PgDn.xml │ │ │ │ ├── PgUp.xml │ │ │ │ ├── PrtSc.xml │ │ │ │ ├── RAlt.xml │ │ │ │ ├── RCtrl.xml │ │ │ │ ├── ScrLck.xml │ │ │ │ ├── Shift.xml │ │ │ │ ├── ShiftWithArrow.xml │ │ │ │ ├── Space.xml │ │ │ │ └── Tab.xml │ │ │ ├── Letters/ │ │ │ │ ├── A.xml │ │ │ │ ├── B.xml │ │ │ │ ├── C.xml │ │ │ │ ├── D.xml │ │ │ │ ├── E.xml │ │ │ │ ├── F.xml │ │ │ │ ├── G.xml │ │ │ │ ├── H.xml │ │ │ │ ├── I.xml │ │ │ │ ├── J.xml │ │ │ │ ├── K.xml │ │ │ │ ├── L.xml │ │ │ │ ├── M.xml │ │ │ │ ├── N.xml │ │ │ │ ├── O.xml │ │ │ │ ├── P.xml │ │ │ │ ├── Q.xml │ │ │ │ ├── R.xml │ │ │ │ ├── S.xml │ │ │ │ ├── T.xml │ │ │ │ ├── U.xml │ │ │ │ ├── V.xml │ │ │ │ ├── W.xml │ │ │ │ ├── X.xml │ │ │ │ ├── Y.xml │ │ │ │ └── Z.xml │ │ │ ├── Mouse/ │ │ │ │ ├── MouseButtons/ │ │ │ │ │ ├── M1.xml │ │ │ │ │ ├── M2.xml │ │ │ │ │ ├── M3.xml │ │ │ │ │ ├── M4.xml │ │ │ │ │ ├── M5.xml │ │ │ │ │ ├── M6.xml │ │ │ │ │ ├── M7.xml │ │ │ │ │ └── M8.xml │ │ │ │ ├── MouseMove.xml │ │ │ │ └── MouseWheel/ │ │ │ │ ├── MouseWheel.xml │ │ │ │ ├── MouseWheelDown.xml │ │ │ │ └── MouseWheelUp.xml │ │ │ ├── Named Icons/ │ │ │ │ ├── Action_Double_Up.xml │ │ │ │ ├── Action_Up.xml │ │ │ │ ├── Action_Up_Arrow.xml │ │ │ │ ├── OCC BUTTON BASE CIRCLE.xml │ │ │ │ ├── OCC BUTTON BASE SQUARE.xml │ │ │ │ ├── OCC BUTTON MOD BASE 1.xml │ │ │ │ ├── OCC BUTTON MOD BASE 2.xml │ │ │ │ ├── OCC BUTTON MOD BASE 3.xml │ │ │ │ ├── OCC BUTTON MOD BASE 4.xml │ │ │ │ ├── OCC CONTROLLER MC.xml │ │ │ │ ├── OCC CONTROLLER.xml │ │ │ │ ├── OCC MOTION.xml │ │ │ │ ├── OCC THUM REST RIGHT BASE.xml │ │ │ │ ├── OCC THUMB REST BASE.xml │ │ │ │ ├── OCC THUMB REST LEFT BASE.xml │ │ │ │ ├── OCC THUMB_REST.xml │ │ │ │ ├── OCC THUMB_REST_LEFT.xml │ │ │ │ ├── OCC THUMB_REST_RIGHT.xml │ │ │ │ ├── OCC_A.xml │ │ │ │ ├── OCC_A_HOLD.xml │ │ │ │ ├── OCC_B.xml │ │ │ │ ├── OCC_B_HOLD.xml │ │ │ │ ├── OCC_X.xml │ │ │ │ ├── OCC_X_HOLD.xml │ │ │ │ ├── OCC_Y.xml │ │ │ │ ├── OCC_Y_HOLD.xml │ │ │ │ ├── Symbol 163.xml │ │ │ │ ├── Symbol 164.xml │ │ │ │ ├── Symbol 170.xml │ │ │ │ ├── Symbol 171.xml │ │ │ │ ├── Symbol 258.xml │ │ │ │ ├── Symbol 259.xml │ │ │ │ ├── Symbol 260.xml │ │ │ │ ├── Symbol 261.xml │ │ │ │ ├── Symbol 262.xml │ │ │ │ ├── Symbol 264.xml │ │ │ │ ├── Symbol 266.xml │ │ │ │ ├── Symbol 267.xml │ │ │ │ ├── Symbol 268.xml │ │ │ │ ├── Symbol 270.xml │ │ │ │ ├── Symbol 271.xml │ │ │ │ ├── Symbol 272.xml │ │ │ │ ├── Symbol 273.xml │ │ │ │ ├── Symbol 274.xml │ │ │ │ ├── Symbol 275.xml │ │ │ │ ├── Symbol 276.xml │ │ │ │ ├── Symbol 277.xml │ │ │ │ ├── Symbol 278.xml │ │ │ │ ├── Symbol 279.xml │ │ │ │ ├── Symbol 280.xml │ │ │ │ ├── Symbol 281.xml │ │ │ │ ├── Symbol 282.xml │ │ │ │ ├── Symbol 284.xml │ │ │ │ ├── Symbol 285.xml │ │ │ │ ├── Symbol 286.xml │ │ │ │ ├── Symbol 287.xml │ │ │ │ ├── Symbol 288.xml │ │ │ │ ├── Symbol 289.xml │ │ │ │ ├── Symbol 290.xml │ │ │ │ ├── Symbol 291.xml │ │ │ │ ├── Symbol 292.xml │ │ │ │ ├── Symbol 293.xml │ │ │ │ ├── Symbol 294.xml │ │ │ │ ├── Symbol 295.xml │ │ │ │ ├── Symbol 296.xml │ │ │ │ ├── Symbol 297.xml │ │ │ │ ├── Symbol 298.xml │ │ │ │ ├── Symbol 299.xml │ │ │ │ ├── Symbol 302.xml │ │ │ │ ├── Symbol 304.xml │ │ │ │ ├── Symbol 305.xml │ │ │ │ ├── Symbol 306.xml │ │ │ │ ├── Symbol 307.xml │ │ │ │ ├── Symbol 308.xml │ │ │ │ ├── Symbol 309.xml │ │ │ │ ├── Symbol 310.xml │ │ │ │ ├── Symbol 311.xml │ │ │ │ ├── Symbol 312.xml │ │ │ │ ├── Symbol 313.xml │ │ │ │ ├── Symbol 314.xml │ │ │ │ ├── Symbol 315.xml │ │ │ │ ├── Symbol 316.xml │ │ │ │ ├── Symbol 318.xml │ │ │ │ ├── Symbol 319.xml │ │ │ │ ├── Symbol 320.xml │ │ │ │ ├── Symbol 321.xml │ │ │ │ ├── Symbol 322.xml │ │ │ │ ├── Symbol 323.xml │ │ │ │ ├── Symbol 324.xml │ │ │ │ ├── Symbol 325.xml │ │ │ │ ├── Symbol 326.xml │ │ │ │ ├── Symbol 327.xml │ │ │ │ ├── Symbol 328.xml │ │ │ │ ├── Symbol 329.xml │ │ │ │ ├── Symbol 330.xml │ │ │ │ ├── Symbol 331.xml │ │ │ │ ├── Symbol 332.xml │ │ │ │ ├── Symbol 333.xml │ │ │ │ ├── Symbol 334.xml │ │ │ │ ├── Symbol 335.xml │ │ │ │ ├── Symbol 336.xml │ │ │ │ ├── Symbol 337.xml │ │ │ │ ├── Symbol 338.xml │ │ │ │ ├── Symbol 339.xml │ │ │ │ ├── Symbol 340.xml │ │ │ │ ├── Symbol 341.xml │ │ │ │ ├── Symbol 342.xml │ │ │ │ ├── Symbol 343.xml │ │ │ │ ├── Symbol 344.xml │ │ │ │ ├── Symbol 345.xml │ │ │ │ ├── Symbol 346.xml │ │ │ │ ├── Symbol 347.xml │ │ │ │ ├── Symbol 348.xml │ │ │ │ ├── Symbol 349.xml │ │ │ │ ├── Symbol 350.xml │ │ │ │ ├── Symbol 351.xml │ │ │ │ ├── Symbol 352.xml │ │ │ │ ├── Symbol 353.xml │ │ │ │ ├── Symbol 354.xml │ │ │ │ ├── Symbol 355.xml │ │ │ │ ├── Symbol 356.xml │ │ │ │ ├── Symbol 357.xml │ │ │ │ ├── Symbol 358.xml │ │ │ │ ├── Symbol 359.xml │ │ │ │ ├── Symbol 36.xml │ │ │ │ ├── Symbol 360.xml │ │ │ │ ├── Symbol 361.xml │ │ │ │ ├── Symbol 362.xml │ │ │ │ ├── Symbol 363.xml │ │ │ │ ├── Symbol 364.xml │ │ │ │ ├── Symbol 365.xml │ │ │ │ ├── Symbol 366.xml │ │ │ │ ├── Symbol 367.xml │ │ │ │ ├── Symbol 368.xml │ │ │ │ ├── Symbol 369.xml │ │ │ │ ├── Symbol 370.xml │ │ │ │ ├── Symbol 371.xml │ │ │ │ ├── Symbol 372.xml │ │ │ │ ├── Symbol 373.xml │ │ │ │ ├── Symbol 374.xml │ │ │ │ ├── Symbol 375.xml │ │ │ │ ├── Symbol 376.xml │ │ │ │ ├── Symbol 377.xml │ │ │ │ ├── Symbol 378.xml │ │ │ │ ├── Symbol 379.xml │ │ │ │ ├── Symbol 380.xml │ │ │ │ ├── Symbol 381.xml │ │ │ │ ├── Symbol 382.xml │ │ │ │ ├── Symbol 383.xml │ │ │ │ ├── Symbol 384.xml │ │ │ │ ├── Symbol 385.xml │ │ │ │ ├── Symbol 386.xml │ │ │ │ ├── Symbol 387.xml │ │ │ │ ├── Symbol 388.xml │ │ │ │ ├── Symbol 389.xml │ │ │ │ ├── Symbol 390.xml │ │ │ │ ├── Symbol 391.xml │ │ │ │ ├── Symbol 392.xml │ │ │ │ ├── Symbol 393.xml │ │ │ │ ├── Symbol 394.xml │ │ │ │ ├── Symbol 395.xml │ │ │ │ ├── Symbol 396.xml │ │ │ │ ├── Symbol 397.xml │ │ │ │ ├── Symbol 398.xml │ │ │ │ ├── Symbol 399.xml │ │ │ │ ├── Symbol 400.xml │ │ │ │ ├── Symbol 401.xml │ │ │ │ ├── Symbol 402.xml │ │ │ │ ├── Symbol 403.xml │ │ │ │ ├── Symbol 404.xml │ │ │ │ ├── Symbol 406.xml │ │ │ │ ├── Symbol 407.xml │ │ │ │ ├── Symbol 409.xml │ │ │ │ ├── Symbol 412.xml │ │ │ │ ├── Symbol 413.xml │ │ │ │ ├── Symbol 414.xml │ │ │ │ ├── Symbol 415.xml │ │ │ │ ├── Symbol 417.xml │ │ │ │ ├── Symbol 420.xml │ │ │ │ ├── Symbol 421.xml │ │ │ │ ├── Symbol 422.xml │ │ │ │ ├── Symbol 423.xml │ │ │ │ ├── Symbol 424.xml │ │ │ │ ├── Symbol 425.xml │ │ │ │ ├── Symbol 426.xml │ │ │ │ ├── Symbol 427.xml │ │ │ │ ├── Symbol 428.xml │ │ │ │ ├── Symbol 429.xml │ │ │ │ ├── Symbol 430.xml │ │ │ │ ├── Symbol 431.xml │ │ │ │ ├── Symbol 432.xml │ │ │ │ ├── Symbol 433.xml │ │ │ │ ├── Symbol 434.xml │ │ │ │ ├── Symbol 435.xml │ │ │ │ ├── Symbol 436.xml │ │ │ │ ├── Symbol 437.xml │ │ │ │ ├── Symbol 438.xml │ │ │ │ ├── Symbol 439.xml │ │ │ │ ├── Symbol 440.xml │ │ │ │ ├── Symbol 441.xml │ │ │ │ ├── Symbol 442.xml │ │ │ │ ├── Symbol 443.xml │ │ │ │ ├── Symbol 445.xml │ │ │ │ ├── Symbol 446.xml │ │ │ │ ├── Symbol 447.xml │ │ │ │ ├── Symbol 448.xml │ │ │ │ ├── Symbol 449.xml │ │ │ │ ├── Symbol 451.xml │ │ │ │ ├── Symbol 452.xml │ │ │ │ ├── Symbol 453.xml │ │ │ │ ├── Symbol 454.xml │ │ │ │ ├── Symbol 455.xml │ │ │ │ ├── Symbol 457.xml │ │ │ │ ├── Symbol 458.xml │ │ │ │ ├── Symbol 459.xml │ │ │ │ ├── Symbol 460.xml │ │ │ │ ├── Symbol 462.xml │ │ │ │ ├── Symbol 465.xml │ │ │ │ ├── Symbol 466.xml │ │ │ │ ├── Symbol 467.xml │ │ │ │ ├── Symbol 468.xml │ │ │ │ ├── Symbol 469.xml │ │ │ │ ├── Symbol 470.xml │ │ │ │ ├── Symbol 471.xml │ │ │ │ ├── Symbol 472.xml │ │ │ │ ├── Symbol 473.xml │ │ │ │ ├── Symbol 474.xml │ │ │ │ ├── Symbol 475.xml │ │ │ │ ├── Symbol 476.xml │ │ │ │ ├── Symbol 477.xml │ │ │ │ ├── Symbol 478.xml │ │ │ │ ├── Symbol 479.xml │ │ │ │ ├── Symbol 480.xml │ │ │ │ ├── Symbol 481.xml │ │ │ │ ├── Symbol 482.xml │ │ │ │ ├── Symbol 483.xml │ │ │ │ ├── Symbol 484.xml │ │ │ │ ├── Symbol 485.xml │ │ │ │ ├── Symbol 486.xml │ │ │ │ ├── Symbol 487.xml │ │ │ │ ├── Symbol 488.xml │ │ │ │ ├── Symbol 489.xml │ │ │ │ ├── Symbol 490.xml │ │ │ │ ├── Symbol 491.xml │ │ │ │ ├── Symbol 492.xml │ │ │ │ ├── Symbol 493.xml │ │ │ │ ├── Symbol 494.xml │ │ │ │ ├── Symbol 495.xml │ │ │ │ ├── Symbol 496.xml │ │ │ │ ├── Symbol 497.xml │ │ │ │ ├── Symbol 498.xml │ │ │ │ ├── Symbol 499.xml │ │ │ │ ├── Symbol 500.xml │ │ │ │ ├── Symbol 501.xml │ │ │ │ ├── Symbol 502.xml │ │ │ │ ├── Symbol 503.xml │ │ │ │ ├── Symbol 504.xml │ │ │ │ ├── Symbol 505.xml │ │ │ │ ├── Symbol 506.xml │ │ │ │ ├── Symbol 507.xml │ │ │ │ ├── Symbol 508.xml │ │ │ │ ├── Symbol 509.xml │ │ │ │ ├── Symbol 510.xml │ │ │ │ ├── Symbol 511.xml │ │ │ │ ├── Symbol 512.xml │ │ │ │ ├── Symbol 513.xml │ │ │ │ ├── Symbol 514.xml │ │ │ │ ├── Symbol 515.xml │ │ │ │ ├── Symbol 516.xml │ │ │ │ ├── Symbol 517.xml │ │ │ │ ├── Symbol 518.xml │ │ │ │ ├── Symbol 519.xml │ │ │ │ ├── Symbol 520.xml │ │ │ │ ├── Symbol 521.xml │ │ │ │ ├── Symbol 522.xml │ │ │ │ ├── Symbol 523.xml │ │ │ │ ├── Symbol 524.xml │ │ │ │ ├── Symbol 525.xml │ │ │ │ ├── Symbol 526.xml │ │ │ │ ├── Symbol 527.xml │ │ │ │ ├── Symbol 528.xml │ │ │ │ ├── Symbol 529.xml │ │ │ │ ├── Symbol 530.xml │ │ │ │ ├── Symbol 531.xml │ │ │ │ ├── Symbol 532.xml │ │ │ │ ├── Symbol 533.xml │ │ │ │ ├── Symbol 534.xml │ │ │ │ ├── Symbol 535.xml │ │ │ │ ├── Symbol 536.xml │ │ │ │ ├── Symbol 537.xml │ │ │ │ ├── Symbol 538.xml │ │ │ │ ├── Symbol 539.xml │ │ │ │ ├── Symbol 540.xml │ │ │ │ ├── Symbol 541.xml │ │ │ │ ├── Symbol 543.xml │ │ │ │ ├── Symbol 544.xml │ │ │ │ ├── Symbol 545.xml │ │ │ │ ├── Symbol 546.xml │ │ │ │ ├── Symbol 547.xml │ │ │ │ ├── Symbol 548.xml │ │ │ │ ├── Symbol 549.xml │ │ │ │ ├── Symbol 550.xml │ │ │ │ ├── Symbol 551.xml │ │ │ │ ├── Symbol 552.xml │ │ │ │ ├── Symbol 553.xml │ │ │ │ └── Symbol 555.xml │ │ │ ├── NumberPad/ │ │ │ │ ├── NP0.xml │ │ │ │ ├── NP1.xml │ │ │ │ ├── NP2.xml │ │ │ │ ├── NP3.xml │ │ │ │ ├── NP4.xml │ │ │ │ ├── NP5.xml │ │ │ │ ├── NP6.xml │ │ │ │ ├── NP7.xml │ │ │ │ ├── NP8.xml │ │ │ │ ├── NP9.xml │ │ │ │ ├── NPAsterisk.xml │ │ │ │ ├── NPEnter.xml │ │ │ │ ├── NPForwardSlash.xml │ │ │ │ ├── NPMinus.xml │ │ │ │ ├── NPPeriod.xml │ │ │ │ └── NPPlus.xml │ │ │ ├── Numbers/ │ │ │ │ ├── 0.xml │ │ │ │ ├── 1.xml │ │ │ │ ├── 2.xml │ │ │ │ ├── 3.xml │ │ │ │ ├── 4.xml │ │ │ │ ├── 5.xml │ │ │ │ ├── 6.xml │ │ │ │ ├── 7.xml │ │ │ │ ├── 8.xml │ │ │ │ └── 9.xml │ │ │ └── Symbols/ │ │ │ ├── Amersand.xml │ │ │ ├── Arrow.xml │ │ │ ├── Asterisk.xml │ │ │ ├── At.xml │ │ │ ├── BackSlash.xml │ │ │ ├── BrokenBar.xml │ │ │ ├── Caret.xml │ │ │ ├── Colon.xml │ │ │ ├── Comma.xml │ │ │ ├── Dollar Sign.xml │ │ │ ├── Equals.xml │ │ │ ├── Exclamation.xml │ │ │ ├── ForwardSlash.xml │ │ │ ├── Grave.xml │ │ │ ├── GreaterThan.xml │ │ │ ├── LeftCurlyBracket.xml │ │ │ ├── LeftParenthesis.xml │ │ │ ├── LeftSquareBracket.xml │ │ │ ├── LessThan.xml │ │ │ ├── Minus.xml │ │ │ ├── Negation.xml │ │ │ ├── Number.xml │ │ │ ├── Percent.xml │ │ │ ├── Period.xml │ │ │ ├── Plus Original.xml │ │ │ ├── Plus.xml │ │ │ ├── Pound.xml │ │ │ ├── Question.xml │ │ │ ├── Quotation.xml │ │ │ ├── RightCurlyBracket.xml │ │ │ ├── RightParenthesis.xml │ │ │ ├── RightSquareBracket.xml │ │ │ ├── SemiColon.xml │ │ │ ├── SingleQuote.xml │ │ │ ├── Tilde.xml │ │ │ ├── Underscore.xml │ │ │ ├── Unknown.xml │ │ │ └── VerticalBar.xml │ │ ├── META-INF/ │ │ │ └── metadata.xml │ │ ├── MobileSettings.xml │ │ ├── PublishSettings.xml │ │ ├── bin/ │ │ │ └── SymDepend.cache │ │ └── buttonArt.xfl │ ├── buttonArtSymbols.fla │ ├── fonts_en_snk.fla │ ├── gfxfontlib.fla │ ├── icons_category_celtic.fla │ ├── icons_category_curved.fla │ ├── icons_category_psychosteve.fla │ ├── icons_category_straight.fla │ ├── icons_effect_psychosteve.fla │ ├── icons_item_celtic.fla │ ├── icons_item_curved.fla │ ├── icons_item_psychosteve.fla │ ├── mapMarkerArt.fla │ ├── mcm.psd │ ├── skyui_icons.fla │ ├── skyui_icons_psychosteve.fla │ └── skyui_icons_straight.fla └── version.as ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ compile-error.txt ================================================ FILE: .gitmodules ================================================ [submodule "sksevr_plugin/skse"] path = sksevr_plugin/skse url = git@github.com:Odie/sksevr-mirror.git [submodule "sksevr_plugin/common"] path = sksevr_plugin/common url = git@github.com:Odie/sksevr-common-mirror.git [submodule "sksevr_plugin/luajit"] path = sksevr_plugin/luajit url = https://luajit.org/git/luajit.git ignore = dirty ================================================ FILE: LICENSE ================================================ MIT License Copyright (c) 2012 schlangster Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ SkyUI - VR ---------- This repository hosts the source and the packaged releases for a working version of SkyUI (and MCM) for SkyrimVR. ### Getting SkyUI To get the mod, head on over to [the release page](https://github.com/Odie/skyui-vr/releases/) and grab the lastest version. All you need is the .7z file. (Ignore the source code download links.) ### Prerequsite Make sure [SKSE VR](http://skse.silverlock.org/) is installed. (Don't forget the .pex files!) ### Installation For MO2 users, use the "Install from file" icon in the toolbar. For Vortex users, drop the .7z file over the vortex window. VR specific controls -------------------- Currently, there are certain limitations to how the UIs in the game can process inputs from the VR controllers. At the moment, the UI seems to mostly receive up/down/right/left signals from the game. This makes operating a more complex UI like SkyUI a little difficult, but not impossible. Here's what you need to know. ### Toggle trade direction In the barter menu or the gift menu, keep hitting "left" until you've reached the first item on the category list (titled "All"). Hit "left" again and the trade direction should toggle. ### Sorting items This applies to any screen where you can see an inventory list. With the first item in the list selected (or nothing selected), hit "up" once to move the sorted column to the next one. Hit "up" twice in quick succession to change the sort direction. For trackpad users, trying using "slow swipe" and "fast swipe" to differentiate between these two actions. The number of controller vibrations indicates how many "up" events the game has registered. ================================================ FILE: build/.gitignore ================================================ *.swf fontconfig.txt !/fonts_console.swf !/fonts_en.swf !/gfxfontlib.swf !/fontconfig.txt ================================================ FILE: build/exported/skyui/.gitkeep ================================================ ================================================ FILE: build/exported/widgets/skyui/.gitkeep ================================================ ================================================ FILE: build/skyui/config.txt ================================================ ; ===================================================================================================================== [Input] ; ===================================================================================================================== controls.pc.search = 57 ; SPACE controls.pc.switchTab = 56 ; ALT controls.pc.equipMode = 42 ; LSHIFT controls.gamepad.switchTab = 271 ; BACK controls.gamepad.prevColumn = 274 ; LEFT_SHOULDER controls.gamepad.nextColumn = 275 ; RIGHT_SHOULDER controls.gamepad.sortOrder = 272 ; LEFT_THUMB ; ===================================================================================================================== [SearchBox] ; ===================================================================================================================== autoupdate.enable = true autoupdate.delay = 0 ; ===================================================================================================================== [ItemInfo] ; ===================================================================================================================== itemcard.align = center itemcard.xOffset = 0 itemcard.yOffset = 0 ; ===================================================================================================================== [ItemList] ; ===================================================================================================================== quantityMenu.minCount = 6 ; Number of items required to trigger quantity dialog. 0 is disabled ; ===================================================================================================================== [Appearance] ; ===================================================================================================================== icons.category.source = 'skyui/icons_category_psychosteve.swf' icons.item.source = 'skyui/icons_item_psychosteve.swf' icons.item.noColor = false icons.item.showStolen = true colors.text.enabled = 0xffffff colors.stolen.enabled = 0xffffff colors.negative.enabled = 0xff0000 colors.text.disabled = 0x4c4c4c colors.stolen.disabled = 0x4c4c4c colors.negative.disabled = 0x800000 ; ===================================================================================================================== [ListLayout] ; ===================================================================================================================== vars.a_textBorder.value = <0, 0, 1.1, 0> ; left right top bottom vars.n_iconSize.value = 18 defaults.entryWidth = 530 ; Default text format defaults ------------------------------------------------------- defaults.entry.textFormat.font = '$EverywhereMediumFont' defaults.entry.textFormat.align = right defaults.entry.textFormat.bold = false defaults.entry.textFormat.italic = false defaults.entry.textFormat.underline = false defaults.entry.textFormat.size = 18 defaults.entry.textFormat.letterSpacing = 0.8 defaults.entry.textFormat.kerning = false defaults.entry.textFormat.leftMargin = 0 defaults.entry.textFormat.rightMargin = 0 defaults.entry.textFormat.indent = 0 defaults.entry.textFormat.leading = 0 defaults.label.textFormat.font = '$EverywhereMediumFont' defaults.label.textFormat.align = right defaults.label.textFormat.bold = false defaults.label.textFormat.italic = false defaults.label.textFormat.underline = false defaults.label.textFormat.size = 16 defaults.label.textFormat.letterSpacing = 0.8 defaults.label.textFormat.kerning = false defaults.label.textFormat.leftMargin = 0 defaults.label.textFormat.rightMargin = 0 defaults.label.textFormat.indent = 0 defaults.label.textFormat.leading = 0 ; ICONS ------------------------------------------------------- columns.equipColumn.type = EQUIP_ICON columns.equipColumn.passive = true columns.equipColumn.states = 1 columns.equipColumn.indent = -28 columns.equipColumn.icon.size = n_iconSize columns.equipColumn.border = <0, 10, 3, 3> ; left right top bottom columns.equipColumn.state1.label.text = ' ' columns.iconColumn.type = ITEM_ICON columns.iconColumn.states = 2 columns.iconColumn.icon.size = n_iconSize columns.iconColumn.border = <0, 3, 3, 3> ; left right top bottom columns.iconColumn.state1.label.text = ' ' columns.iconColumn.state1.sortAttributes = columns.iconColumn.state1.sortOptions = <{ASCENDING | NUMERIC}, {ASCENDING | NUMERIC}, {ASCENDING | NUMERIC}, {ASCENDING | NUMERIC}, {ASCENDING | NUMERIC}, {DESCENDING | NUMERIC}, {DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}, {ASCENDING | NUMERIC}, {ASCENDING | NUMERIC}, {DESCENDING | NUMERIC}, {DESCENDING | NUMERIC}, {DESCENDING | NUMERIC}, {ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> columns.iconColumn.state2.label.text = ' ' columns.iconColumn.state2.label.arrowDown = true columns.iconColumn.state2.sortAttributes = columns.iconColumn.state2.sortOptions = <{DESCENDING | NUMERIC}, {DESCENDING | NUMERIC}, {DESCENDING | NUMERIC}, {DESCENDING | NUMERIC}, {DESCENDING | NUMERIC}, {ASCENDING | NUMERIC}, {ASCENDING | NUMERIC}, {DESCENDING | CASEINSENSITIVE}, {DESCENDING | NUMERIC}, {DESCENDING | NUMERIC}, {ASCENDING | NUMERIC}, {ASCENDING | NUMERIC}, {ASCENDING | NUMERIC}, {DESCENDING | NUMERIC}, {DESCENDING | CASEINSENSITIVE}> ; ITEM NAME COLUMN ------------------------------------------------------- columns.itemNameColumn.type = NAME columns.itemNameColumn.name = '$NAME' columns.itemNameColumn.states = 4 columns.itemNameColumn.weight = 1.0 columns.itemNameColumn.border = a_textBorder columns.itemNameColumn.label.textFormat.align = left columns.itemNameColumn.state1.label.text = '$NAME' columns.itemNameColumn.state1.entry.text = @text columns.itemNameColumn.state1.sortOptions = {ASCENDING | CASEINSENSITIVE} columns.itemNameColumn.state2.label.text = '$EQUIPPED' columns.itemNameColumn.state2.entry.text = @text columns.itemNameColumn.state2.sortAttributes = columns.itemNameColumn.state2.sortOptions = <{DESCENDING | NUMERIC}, {DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> columns.itemNameColumn.state2.playerOnly = true columns.itemNameColumn.state3.label.text = '$STOLEN' columns.itemNameColumn.state3.entry.text = @text columns.itemNameColumn.state3.sortAttributes = columns.itemNameColumn.state3.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> columns.itemNameColumn.state3.playerOnly = true columns.itemNameColumn.state4.label.text = '$ENCHANTED' columns.itemNameColumn.state4.entry.text = @text columns.itemNameColumn.state4.sortAttributes = columns.itemNameColumn.state4.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; ARMOR RATING COLUMN ------------------------------------------------------- columns.arColumn.type = TEXT columns.arColumn.name = '$ARMOR' columns.arColumn.states = 2 columns.arColumn.width = 0.09 columns.arColumn.border = a_textBorder columns.arColumn.state1.label.text = '$ARM' columns.arColumn.state1.label.arrowDown = true columns.arColumn.state1.entry.text = @infoArmor columns.arColumn.state1.sortAttributes = columns.arColumn.state1.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> columns.arColumn.state2.label.text = '$ARM' columns.arColumn.state2.entry.text = @infoArmor columns.arColumn.state2.sortAttributes = columns.arColumn.state2.sortOptions = <{ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; SUBTYPE COLUMN ------------------------------------------------------- columns.subTypeColumn.type = TEXT columns.subTypeColumn.name = '$TYPE' columns.subTypeColumn.states = 2 columns.subTypeColumn.width = 0.15 columns.subTypeColumn.border = a_textBorder columns.subTypeColumn.state1.label.text = '$TYPE' columns.subTypeColumn.state1.entry.text = @subTypeDisplay columns.subTypeColumn.state1.sortAttributes = columns.subTypeColumn.state1.sortOptions = <{ASCENDING | CASEINSENSITIVE}, {ASCENDING | CASEINSENSITIVE}> columns.subTypeColumn.state2.label.text = '$TYPE' columns.subTypeColumn.state2.entry.text = @subTypeDisplay columns.subTypeColumn.state2.label.arrowDown = true columns.subTypeColumn.state2.sortAttributes = columns.subTypeColumn.state2.sortOptions = <{DESCENDING | CASEINSENSITIVE}, {ASCENDING | CASEINSENSITIVE}> ; MATERIAL COLUMN ------------------------------------------------------- columns.materialColumn.type = TEXT columns.materialColumn.name = '$MATERIAL' columns.materialColumn.states = 2 columns.materialColumn.width = 0.10 columns.materialColumn.border = a_textBorder columns.materialColumn.hidden = true columns.materialColumn.state1.label.text = '$MAT' columns.materialColumn.state1.entry.text = @materialDisplay columns.materialColumn.state1.sortAttributes = columns.materialColumn.state1.sortOptions = <{ASCENDING | CASEINSENSITIVE}, {ASCENDING | CASEINSENSITIVE}> columns.materialColumn.state2.label.text = '$MAT' columns.materialColumn.state2.entry.text = @materialDisplay columns.materialColumn.state2.label.arrowDown = true columns.materialColumn.state2.sortAttributes = columns.materialColumn.state2.sortOptions = <{DESCENDING | CASEINSENSITIVE}, {ASCENDING | CASEINSENSITIVE}> ; CLASS COLUMN ------------------------------------------------------- columns.classColumn.type = TEXT columns.classColumn.name = '$CLASS' columns.classColumn.states = 2 columns.classColumn.width = 0.10 columns.classColumn.border = a_textBorder columns.classColumn.state1.label.text = '$CLASS' columns.classColumn.state1.entry.text = @weightClassDisplay columns.classColumn.state1.sortAttributes = columns.classColumn.state1.sortOptions = <{ASCENDING | CASEINSENSITIVE}, {ASCENDING | CASEINSENSITIVE}> columns.classColumn.state2.label.text = '$CLASS' columns.classColumn.state2.entry.text = @weightClassDisplay columns.classColumn.state2.label.arrowDown = true columns.classColumn.state2.sortAttributes = columns.classColumn.state2.sortOptions = <{DESCENDING | CASEINSENSITIVE}, {ASCENDING | CASEINSENSITIVE}> ; MAGNITUDE COLUMN ------------------------------------------------------- columns.magnitudeColumn.type = TEXT columns.magnitudeColumn.name = '$MAGNITUDE' columns.magnitudeColumn.states = 2 columns.magnitudeColumn.width = 0.09 columns.magnitudeColumn.border = a_textBorder columns.magnitudeColumn.state1.label.text = '$MAG' columns.magnitudeColumn.state1.label.arrowDown = true columns.magnitudeColumn.state1.entry.text = @magnitude columns.magnitudeColumn.state1.sortAttributes = columns.magnitudeColumn.state1.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> columns.magnitudeColumn.state2.label.text = '$MAG' columns.magnitudeColumn.state2.entry.text = @magnitude columns.magnitudeColumn.state2.sortAttributes = columns.magnitudeColumn.state2.sortOptions = <{ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; DURATION COLUMN ------------------------------------------------------- columns.durationColumn.type = TEXT columns.durationColumn.name = '$TIME' columns.durationColumn.states = 2 columns.durationColumn.width = 0.09 columns.durationColumn.border = a_textBorder columns.durationColumn.state1.label.text = '$TIME' columns.durationColumn.state1.label.arrowDown = true columns.durationColumn.state1.entry.text = @duration columns.durationColumn.state1.sortAttributes = columns.durationColumn.state1.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> columns.durationColumn.state2.label.text = '$TIME' columns.durationColumn.state2.entry.text = @duration columns.durationColumn.state2.sortAttributes = columns.durationColumn.state2.sortOptions = <{ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; MAGIC MAGNITUDE COLUMN ------------------------------------------------------- columns.magicMagnitudeColumn.type = TEXT columns.magicMagnitudeColumn.name = '$MAGNITUDE' columns.magicMagnitudeColumn.states = 2 columns.magicMagnitudeColumn.width = 0.15 columns.magicMagnitudeColumn.border = a_textBorder columns.magicMagnitudeColumn.state1.label.text = '$MAG' columns.magicMagnitudeColumn.state1.label.arrowDown = true columns.magicMagnitudeColumn.state1.entry.text = @magnitude columns.magicMagnitudeColumn.state1.sortAttributes = columns.magicMagnitudeColumn.state1.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> columns.magicMagnitudeColumn.state2.label.text = '$MAG' columns.magicMagnitudeColumn.state2.entry.text = @magnitude columns.magicMagnitudeColumn.state2.sortAttributes = columns.magicMagnitudeColumn.state2.sortOptions = <{ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; MAGIC DURATION COLUMN ------------------------------------------------------- columns.magicDurationColumn.type = TEXT columns.magicDurationColumn.name = '$TIME' columns.magicDurationColumn.states = 2 columns.magicDurationColumn.width = 0.15 columns.magicDurationColumn.border = a_textBorder columns.magicDurationColumn.state1.label.text = '$TIME' columns.magicDurationColumn.state1.label.arrowDown = true columns.magicDurationColumn.state1.entry.text = @duration columns.magicDurationColumn.state1.sortAttributes = columns.magicDurationColumn.state1.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> columns.magicDurationColumn.state2.label.text = '$TIME' columns.magicDurationColumn.state2.entry.text = @duration columns.magicDurationColumn.state2.sortAttributes = columns.magicDurationColumn.state2.sortOptions = <{ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; DAMAGE COLUMN ------------------------------------------------------- columns.damageColumn.type = TEXT columns.damageColumn.name = '$DAMAGE' columns.damageColumn.states = 2 columns.damageColumn.width = 0.09 columns.damageColumn.border = a_textBorder columns.damageColumn.state1.label.text = '$DAM' columns.damageColumn.state1.label.arrowDown = true columns.damageColumn.state1.entry.text = @infoDamage columns.damageColumn.state1.sortAttributes = columns.damageColumn.state1.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> columns.damageColumn.state2.label.text = '$DAM' columns.damageColumn.state2.entry.text = @infoDamage columns.damageColumn.state2.sortAttributes = columns.damageColumn.state2.sortOptions = <{ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; WEIGHT COLUMN ------------------------------------------------------- columns.weightColumn.type = TEXT columns.weightColumn.name = '$WEIGHT' columns.weightColumn.states = 2 columns.weightColumn.width = 0.09 columns.weightColumn.border = a_textBorder columns.weightColumn.state1.label.text = '$WGT' columns.weightColumn.state1.label.arrowDown = true columns.weightColumn.state1.entry.text = @infoWeight columns.weightColumn.state1.sortAttributes = columns.weightColumn.state1.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> columns.weightColumn.state2.label.text = '$WGT' columns.weightColumn.state2.entry.text = @infoWeight columns.weightColumn.state2.sortAttributes = columns.weightColumn.state2.sortOptions = <{ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; VALUE COLUMN ------------------------------------------------------- columns.valueColumn.type = TEXT columns.valueColumn.name = '$VALUE' columns.valueColumn.states = 2 columns.valueColumn.width = 0.09 columns.valueColumn.border = a_textBorder columns.valueColumn.state1.label.text = '$VAL' columns.valueColumn.state1.label.arrowDown = true columns.valueColumn.state1.entry.text = @infoValue columns.valueColumn.state1.sortAttributes = columns.valueColumn.state1.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> columns.valueColumn.state2.label.text = '$VAL' columns.valueColumn.state2.entry.text = @infoValue columns.valueColumn.state2.sortAttributes = columns.valueColumn.state2.sortOptions = <{ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; VALUE/WEIGHT COLUMN ------------------------------------------------------- columns.valueWeightColumn.type = TEXT columns.valueWeightColumn.name = '$VALUE/WEIGHT' columns.valueWeightColumn.states = 2 columns.valueWeightColumn.width = 0.09 columns.valueWeightColumn.border = a_textBorder columns.valueWeightColumn.hidden = true columns.valueWeightColumn.state1.label.text = '$V/W' columns.valueWeightColumn.state1.label.arrowDown = true columns.valueWeightColumn.state1.entry.text = @infoValueWeight columns.valueWeightColumn.state1.sortAttributes = columns.valueWeightColumn.state1.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> columns.valueWeightColumn.state2.label.text = '$V/W' columns.valueWeightColumn.state2.entry.text = @infoValueWeight columns.valueWeightColumn.state2.sortAttributes = columns.valueWeightColumn.state2.sortOptions = <{ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; MAGIC NAME COLUMN ------------------------------------------------------- columns.magicNameColumn.type = NAME columns.magicNameColumn.name = '$NAME' columns.magicNameColumn.states = 2 columns.magicNameColumn.weight = 1.0 columns.magicNameColumn.border = a_textBorder columns.magicNameColumn.label.textFormat.align = left columns.magicNameColumn.state1.label.text = '$NAME' columns.magicNameColumn.state1.entry.text = @text columns.magicNameColumn.state1.sortOptions = {ASCENDING | CASEINSENSITIVE} columns.magicNameColumn.state2.label.text = '$FAVORITE' columns.magicNameColumn.state2.entry.text = @text columns.magicNameColumn.state2.sortAttributes = columns.magicNameColumn.state2.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> columns.magicNameColumn.state2.playerOnly = true ; SPELL COST COLUMN ------------------------------------------- columns.spellCostColumn.type = TEXT columns.spellCostColumn.name = '$SPELL COST' columns.spellCostColumn.states = 2 columns.spellCostColumn.width = 0.15 columns.spellCostColumn.border = a_textBorder columns.spellCostColumn.state1.label.text = '$COST' columns.spellCostColumn.state1.label.arrowDown = true columns.spellCostColumn.state1.entry.text = @spellCostDisplay columns.spellCostColumn.state1.sortAttributes = columns.spellCostColumn.state1.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> columns.spellCostColumn.state2.label.text = '$COST' columns.spellCostColumn.state2.label.arrowDown = false columns.spellCostColumn.state2.entry.text = @spellCostDisplay columns.spellCostColumn.state2.sortAttributes = columns.spellCostColumn.state2.sortOptions = <{ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; WORD 1 COLUMN ------------------------------------------- columns.word0Column.type = TEXT columns.word0Column.name = '$FIRST WORD' columns.word0Column.states = 2 columns.word0Column.width = 0.2 columns.word0Column.border = a_textBorder columns.word0Column.state1.label.text = '$FIRST WORD' columns.word0Column.state1.label.arrowDown = true columns.word0Column.state1.entry.text = @word0 columns.word0Column.state1.sortAttributes = columns.word0Column.state1.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> columns.word0Column.state1.colorAttribute = word0Color columns.word0Column.state2.label.text = '$FIRST WORD' columns.word0Column.state2.label.arrowDown = false columns.word0Column.state2.entry.text = @word0 columns.word0Column.state2.sortAttributes = columns.word0Column.state2.sortOptions = <{ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> columns.word0Column.state2.colorAttribute = word0Color ; WORD 2 COLUMN ------------------------------------------- columns.word1Column.type = TEXT columns.word1Column.name = '$SECOND WORD' columns.word1Column.states = 2 columns.word1Column.width = 0.2 columns.word1Column.border = a_textBorder columns.word1Column.state1.label.text = '$SECOND WORD' columns.word1Column.state1.label.arrowDown = true columns.word1Column.state1.entry.text = @word1 columns.word1Column.state1.sortAttributes = columns.word1Column.state1.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> columns.word1Column.state1.colorAttribute = word1Color columns.word1Column.state2.label.text = '$SECOND WORD' columns.word1Column.state2.label.arrowDown = false columns.word1Column.state2.entry.text = @word1 columns.word1Column.state2.sortAttributes = columns.word1Column.state2.sortOptions = <{ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> columns.word1Column.state2.colorAttribute = word1Color ; WORD 3 COLUMN ------------------------------------------- columns.word2Column.type = TEXT columns.word2Column.name = '$THIRD WORD' columns.word2Column.states = 2 columns.word2Column.width = 0.2 columns.word2Column.border = a_textBorder columns.word2Column.state1.label.text = '$THIRD WORD' columns.word2Column.state1.label.arrowDown = true columns.word2Column.state1.entry.text = @word2 columns.word2Column.state1.sortAttributes = columns.word2Column.state1.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> columns.word2Column.state1.colorAttribute = word2Color columns.word2Column.state2.label.text = '$THIRD WORD' columns.word2Column.state2.label.arrowDown = false columns.word2Column.state2.entry.text = @word2 columns.word2Column.state2.sortAttributes = columns.word2Column.state2.sortOptions = <{ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> columns.word2Column.state2.colorAttribute = word2Color ; SCHOOL COLUMN ------------------------------------------- columns.schoolColumn.type = TEXT columns.schoolColumn.name = '$SCHOOL' columns.schoolColumn.states = 2 columns.schoolColumn.width = 0.15 columns.schoolColumn.border = a_textBorder columns.schoolColumn.state1.label.text = '$SCHOOL' columns.schoolColumn.state1.label.arrowDown = false columns.schoolColumn.state1.entry.text = @infoSchoolName columns.schoolColumn.state1.sortAttributes = columns.schoolColumn.state1.sortOptions = <{ASCENDING | CASEINSENSITIVE}, {ASCENDING | CASEINSENSITIVE}> columns.schoolColumn.state2.label.text = '$SCHOOL' columns.schoolColumn.state2.label.arrowDown = true columns.schoolColumn.state2.entry.text = @infoSchoolName columns.schoolColumn.state2.sortAttributes = columns.schoolColumn.state2.sortOptions = <{DESCENDING | CASEINSENSITIVE}, {ASCENDING | CASEINSENSITIVE}> ; LEVEL COLUMN ------------------------------------------- columns.levelColumn.type = TEXT columns.levelColumn.name = '$SKILL LEVEL' columns.levelColumn.states = 2 columns.levelColumn.width = 0.15 columns.levelColumn.border = a_textBorder columns.levelColumn.state1.label.text = '$LEVEL' columns.levelColumn.state1.label.arrowDown = false columns.levelColumn.state1.entry.text = @infoCastLevel columns.levelColumn.state1.sortAttributes = columns.levelColumn.state1.sortOptions = <{ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> columns.levelColumn.state2.label.text = '$LEVEL' columns.levelColumn.state2.label.arrowDown = true columns.levelColumn.state2.entry.text = @infoCastLevel columns.levelColumn.state2.sortAttributes = columns.levelColumn.state2.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; TIME REMAINING COLUMN ------------------------------------------- columns.timeRemainingColumn.type = TEXT columns.timeRemainingColumn.name = '$TIME LEFT' columns.timeRemainingColumn.states = 2 columns.timeRemainingColumn.width = 0.333 columns.timeRemainingColumn.label.textFormat.align = center columns.timeRemainingColumn.entry.textFormat.align = center columns.timeRemainingColumn.state1.label.text = '$TIME LEFT' columns.timeRemainingColumn.state1.label.arrowDown = false columns.timeRemainingColumn.state1.entry.text = @timeRemainingDisplay columns.timeRemainingColumn.state1.sortAttributes = columns.timeRemainingColumn.state1.sortOptions = <{ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> columns.timeRemainingColumn.state2.label.text = '$TIME LEFT' columns.timeRemainingColumn.state2.label.arrowDown = true columns.timeRemainingColumn.state2.entry.text = @timeRemainingDisplay columns.timeRemainingColumn.state2.sortAttributes = columns.timeRemainingColumn.state2.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; EFFECT ITEM COLUMN ------------------------------------------- columns.effectItemColumn.type = TEXT columns.effectItemColumn.name = '$SOURCE' columns.effectItemColumn.states = 2 columns.effectItemColumn.width = 0.333 columns.effectItemColumn.label.textFormat.align = right columns.effectItemColumn.entry.textFormat.align = right columns.effectItemColumn.state1.label.text = '$SOURCE' columns.effectItemColumn.state1.label.arrowDown = false columns.effectItemColumn.state1.entry.text = @cardName columns.effectItemColumn.state1.sortAttributes = columns.effectItemColumn.state1.sortOptions = <{ASCENDING | CASEINSENSITIVE}, {ASCENDING | CASEINSENSITIVE}> columns.effectItemColumn.state2.label.text = '$SOURCE' columns.effectItemColumn.state2.label.arrowDown = true columns.effectItemColumn.state2.entry.text = @cardName columns.effectItemColumn.state2.sortAttributes = columns.effectItemColumn.state2.sortOptions = <{DESCENDING | CASEINSENSITIVE}, {ASCENDING | CASEINSENSITIVE}> ; CRAFT NAME COLUMN ------------------------------------------------------- columns.craftNameColumn.type = NAME columns.craftNameColumn.name = '$NAME' columns.craftNameColumn.states = 1 columns.craftNameColumn.weight = 1.0 columns.craftNameColumn.border = a_textBorder columns.craftNameColumn.label.textFormat.align = left columns.craftNameColumn.state1.label.text = '$NAME' columns.craftNameColumn.state1.entry.text = @text columns.craftNameColumn.state1.sortAttributes = columns.craftNameColumn.state1.sortOptions = <{ASCENDING | CASEINSENSITIVE}> ; DISENCHANT EFFECT COLUMN ------------------------------------------------------- columns.disenchantEffectColumn.type = TEXT columns.disenchantEffectColumn.name = '$EFFECT' columns.disenchantEffectColumn.states = 2 columns.disenchantEffectColumn.width = 0.4 columns.disenchantEffectColumn.label.textFormat.align = right columns.disenchantEffectColumn.entry.textFormat.align = right columns.disenchantEffectColumn.state1.label.text = '$EFFECT' columns.disenchantEffectColumn.state1.label.arrowDown = false columns.disenchantEffectColumn.state1.entry.text = @effectName columns.disenchantEffectColumn.state1.sortAttributes = columns.disenchantEffectColumn.state1.sortOptions = <{ASCENDING | CASEINSENSITIVE}, {DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> columns.disenchantEffectColumn.state2.label.text = '$EFFECT' columns.disenchantEffectColumn.state2.label.arrowDown = true columns.disenchantEffectColumn.state2.entry.text = @effectName columns.disenchantEffectColumn.state2.sortAttributes = columns.disenchantEffectColumn.state2.sortOptions = <{DESCENDING | CASEINSENSITIVE}, {DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; SOUL SIZE COLUMN ------------------------------------------------------- columns.soulSizeColumn.type = TEXT columns.soulSizeColumn.name = '$HK19' columns.soulSizeColumn.states = 2 columns.soulSizeColumn.width = 0.15 columns.soulSizeColumn.label.textFormat.align = right columns.soulSizeColumn.entry.textFormat.align = right columns.soulSizeColumn.state1.label.text = '$HK19' columns.soulSizeColumn.state1.label.arrowDown = false columns.soulSizeColumn.state1.entry.text = @soulSizeDisplay columns.soulSizeColumn.state1.sortAttributes = columns.soulSizeColumn.state1.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> columns.soulSizeColumn.state2.label.text = '$HK19' columns.soulSizeColumn.state2.label.arrowDown = true columns.soulSizeColumn.state2.entry.text = @soulSizeDisplay columns.soulSizeColumn.state2.sortAttributes = columns.soulSizeColumn.state2.sortOptions = <{ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; ALCHEMY WEIGHT COLUMN ------------------------------------------------------- columns.alchWeightColumn.type = TEXT columns.alchWeightColumn.name = '$WEIGHT' columns.alchWeightColumn.states = 2 columns.alchWeightColumn.width = 0.14 columns.alchWeightColumn.border = a_textBorder columns.alchWeightColumn.state1.label.text = '$WGT' columns.alchWeightColumn.state1.label.arrowDown = true columns.alchWeightColumn.state1.entry.text = @infoWeight columns.alchWeightColumn.state1.sortAttributes = columns.alchWeightColumn.state1.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> columns.alchWeightColumn.state2.label.text = '$WGT' columns.alchWeightColumn.state2.entry.text = @infoWeight columns.alchWeightColumn.state2.sortAttributes = columns.alchWeightColumn.state2.sortOptions = <{ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; ALCHEMY VALUE COLUMN ------------------------------------------------------- columns.alchValueColumn.type = TEXT columns.alchValueColumn.name = '$VALUE' columns.alchValueColumn.states = 2 columns.alchValueColumn.width = 0.14 columns.alchValueColumn.border = a_textBorder columns.alchValueColumn.state1.label.text = '$VAL' columns.alchValueColumn.state1.label.arrowDown = true columns.alchValueColumn.state1.entry.text = @infoValue columns.alchValueColumn.state1.sortAttributes = columns.alchValueColumn.state1.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> columns.alchValueColumn.state2.label.text = '$VAL' columns.alchValueColumn.state2.entry.text = @infoValue columns.alchValueColumn.state2.sortAttributes = columns.alchValueColumn.state2.sortOptions = <{ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; ALCHEMY VALUE/WEIGHT COLUMN ------------------------------------------------------- columns.alchValueWeightColumn.type = TEXT columns.alchValueWeightColumn.name = '$VALUE/WEIGHT' columns.alchValueWeightColumn.states = 2 columns.alchValueWeightColumn.width = 0.14 columns.alchValueWeightColumn.border = a_textBorder columns.alchValueWeightColumn.hidden = true columns.alchValueWeightColumn.state1.label.text = '$V/W' columns.alchValueWeightColumn.state1.label.arrowDown = true columns.alchValueWeightColumn.state1.entry.text = @infoValueWeight columns.alchValueWeightColumn.state1.sortAttributes = columns.alchValueWeightColumn.state1.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> columns.alchValueWeightColumn.state2.label.text = '$V/W' columns.alchValueWeightColumn.state2.entry.text = @infoValueWeight columns.alchValueWeightColumn.state2.sortAttributes = columns.alchValueWeightColumn.state2.sortOptions = <{ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; ITEM VIEWS ------------------------------------------------------- views.defaultItemView.primaryColumn = itemNameColumn views.defaultItemView.columns = views.weaponView.primaryColumn = itemNameColumn views.weaponView.columns = views.weaponView.category = views.armorView.primaryColumn = itemNameColumn views.armorView.columns = views.armorView.category = views.magicItemView.primaryColumn = itemNameColumn views.magicItemView.columns = views.magicItemView.category = views.keysView.primaryColumn = itemNameColumn views.keysView.columns = views.keysView.category = ; MAGIC VIEWS ------------------------------------------------------- views.defaultMagicView.primaryColumn = magicNameColumn views.defaultMagicView.columns = views.allMagicView.primaryColumn = magicNameColumn views.allMagicView.columns = views.allMagicView.category = views.shoutsView.primaryColumn = magicNameColumn views.shoutsView.columns = views.shoutsView.category = Inventory.FILTERFLAG_MAGIC_SHOUTS views.powersView.primaryColumn = magicNameColumn views.powersView.columns = views.powersView.category = Inventory.FILTERFLAG_MAGIC_POWERS views.activeEffectView.primaryColumn = magicNameColumn views.activeEffectView.columns = views.activeEffectView.category = Inventory.FILTERFLAG_MAGIC_ACTIVEEFFECTS ; CRAFTING VIEWS ------------------------------------------------------- views.defaultCraftingView.primaryColumn = craftNameColumn views.defaultCraftingView.columns = views.disenchantView.primaryColumn = craftNameColumn views.disenchantView.columns = views.disenchantView.category = Inventory.FILTERFLAG_ENCHANTING_DISENCHANT views.enchantItemView.primaryColumn = craftNameColumn views.enchantItemView.columns = views.enchantItemView.category = Inventory.FILTERFLAG_ENCHANTING_ITEM views.enchantEnchantmentView.primaryColumn = craftNameColumn views.enchantEnchantmentView.columns = views.enchantEnchantmentView.category = Inventory.FILTERFLAG_ENCHANTING_ENCHANTMENT views.enchantSoulView.primaryColumn = craftNameColumn views.enchantSoulView.columns = views.enchantSoulView.category = Inventory.FILTERFLAG_ENCHANTING_SOULGEM views.craftWeaponView.primaryColumn = craftNameColumn views.craftWeaponView.columns = views.craftWeaponView.category = views.craftArmorView.primaryColumn = craftNameColumn views.craftArmorView.columns = views.craftArmorView.category = Inventory.FILTERFLAG_CUST_CRAFT_ARMOR views.alchemyView.primaryColumn = craftNameColumn views.alchemyView.columns = ; LAYOUTS ------------------------------------------------------- layouts.itemListLayout.name = 'ItemListLayout' layouts.itemListLayout.views = layouts.magicListLayout.name = 'MagicListLayout' layouts.magicListLayout.views = layouts.enchantListLayout.name = 'EnchantListLayout' layouts.enchantListLayout.views = layouts.constructListLayout.name = 'ConstructListLayout' layouts.constructListLayout.views = layouts.smithingListLayout.name = 'SmithingListLayout' layouts.smithingListLayout.views = layouts.alchemyListLayout.name = 'AlchemyListLayout' layouts.alchemyListLayout.views = ================================================ FILE: dist/.gitignore ================================================ *.pex *.swf *.bak *.bsa *.bsl Archive.log ================================================ FILE: dist/Data/Interface/skyui/config.txt ================================================ ; ===================================================================================================================== [Input] ; ===================================================================================================================== controls.pc.search = 57 ; SPACE controls.pc.switchTab = 56 ; ALT controls.pc.equipMode = 42 ; LSHIFT controls.gamepad.switchTab = 271 ; BACK controls.gamepad.prevColumn = 274 ; LEFT_SHOULDER controls.gamepad.nextColumn = 275 ; RIGHT_SHOULDER controls.gamepad.sortOrder = 272 ; LEFT_THUMB ; ===================================================================================================================== [SearchBox] ; ===================================================================================================================== autoupdate.enable = true autoupdate.delay = 0 ; ===================================================================================================================== [ItemInfo] ; ===================================================================================================================== itemcard.align = center itemcard.xOffset = 0 itemcard.yOffset = 0 ; ===================================================================================================================== [ItemList] ; ===================================================================================================================== quantityMenu.minCount = 6 ; Number of items required to trigger quantity dialog. 0 is disabled ; ===================================================================================================================== [Appearance] ; ===================================================================================================================== icons.category.source = 'skyui/icons_category_psychosteve.swf' icons.item.source = 'skyui/icons_item_psychosteve.swf' icons.item.noColor = false icons.item.showStolen = true colors.text.enabled = 0xffffff colors.stolen.enabled = 0xffffff colors.negative.enabled = 0xff0000 colors.text.disabled = 0x4c4c4c colors.stolen.disabled = 0x4c4c4c colors.negative.disabled = 0x800000 ; ===================================================================================================================== [ListLayout] ; ===================================================================================================================== vars.a_textBorder.value = <0, 0, 1.1, 0> ; left right top bottom vars.n_iconSize.value = 18 defaults.entryWidth = 530 ; Default text format defaults ------------------------------------------------------- defaults.entry.textFormat.font = '$EverywhereMediumFont' defaults.entry.textFormat.align = right defaults.entry.textFormat.bold = false defaults.entry.textFormat.italic = false defaults.entry.textFormat.underline = false defaults.entry.textFormat.size = 14 defaults.entry.textFormat.letterSpacing = 0.8 defaults.entry.textFormat.kerning = false defaults.entry.textFormat.leftMargin = 0 defaults.entry.textFormat.rightMargin = 0 defaults.entry.textFormat.indent = 0 defaults.entry.textFormat.leading = 0 defaults.label.textFormat.font = '$EverywhereMediumFont' defaults.label.textFormat.align = right defaults.label.textFormat.bold = false defaults.label.textFormat.italic = false defaults.label.textFormat.underline = false defaults.label.textFormat.size = 12 defaults.label.textFormat.letterSpacing = 0.8 defaults.label.textFormat.kerning = false defaults.label.textFormat.leftMargin = 0 defaults.label.textFormat.rightMargin = 0 defaults.label.textFormat.indent = 0 defaults.label.textFormat.leading = 0 ; ICONS ------------------------------------------------------- columns.equipColumn.type = EQUIP_ICON columns.equipColumn.passive = true columns.equipColumn.states = 1 columns.equipColumn.indent = -28 columns.equipColumn.icon.size = n_iconSize columns.equipColumn.border = <0, 10, 3, 3> ; left right top bottom columns.equipColumn.state1.label.text = ' ' columns.iconColumn.type = ITEM_ICON columns.iconColumn.states = 2 columns.iconColumn.icon.size = n_iconSize columns.iconColumn.border = <0, 3, 3, 3> ; left right top bottom columns.iconColumn.state1.label.text = ' ' columns.iconColumn.state1.sortAttributes = columns.iconColumn.state1.sortOptions = <{ASCENDING | NUMERIC}, {ASCENDING | NUMERIC}, {ASCENDING | NUMERIC}, {ASCENDING | NUMERIC}, {ASCENDING | NUMERIC}, {DESCENDING | NUMERIC}, {DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}, {ASCENDING | NUMERIC}, {ASCENDING | NUMERIC}, {DESCENDING | NUMERIC}, {DESCENDING | NUMERIC}, {DESCENDING | NUMERIC}, {ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> columns.iconColumn.state2.label.text = ' ' columns.iconColumn.state2.label.arrowDown = true columns.iconColumn.state2.sortAttributes = columns.iconColumn.state2.sortOptions = <{DESCENDING | NUMERIC}, {DESCENDING | NUMERIC}, {DESCENDING | NUMERIC}, {DESCENDING | NUMERIC}, {DESCENDING | NUMERIC}, {ASCENDING | NUMERIC}, {ASCENDING | NUMERIC}, {DESCENDING | CASEINSENSITIVE}, {DESCENDING | NUMERIC}, {DESCENDING | NUMERIC}, {ASCENDING | NUMERIC}, {ASCENDING | NUMERIC}, {ASCENDING | NUMERIC}, {DESCENDING | NUMERIC}, {DESCENDING | CASEINSENSITIVE}> ; ITEM NAME COLUMN ------------------------------------------------------- columns.itemNameColumn.type = NAME columns.itemNameColumn.name = '$NAME' columns.itemNameColumn.states = 4 columns.itemNameColumn.weight = 1.0 columns.itemNameColumn.border = a_textBorder columns.itemNameColumn.label.textFormat.align = left columns.itemNameColumn.state1.label.text = '$NAME' columns.itemNameColumn.state1.entry.text = @text columns.itemNameColumn.state1.sortAttributes = columns.itemNameColumn.state1.sortOptions = {ASCENDING | CASEINSENSITIVE} columns.itemNameColumn.state2.label.text = '$EQUIPPED' columns.itemNameColumn.state2.entry.text = @text columns.itemNameColumn.state2.sortAttributes = columns.itemNameColumn.state2.sortOptions = <{DESCENDING | NUMERIC}, {DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> columns.itemNameColumn.state2.playerOnly = true columns.itemNameColumn.state3.label.text = '$STOLEN' columns.itemNameColumn.state3.entry.text = @text columns.itemNameColumn.state3.sortAttributes = columns.itemNameColumn.state3.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> columns.itemNameColumn.state3.playerOnly = true columns.itemNameColumn.state4.label.text = '$ENCHANTED' columns.itemNameColumn.state4.entry.text = @text columns.itemNameColumn.state4.sortAttributes = columns.itemNameColumn.state4.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; ARMOR RATING COLUMN ------------------------------------------------------- columns.arColumn.type = TEXT columns.arColumn.name = '$ARMOR' columns.arColumn.states = 2 columns.arColumn.width = 0.09 columns.arColumn.border = a_textBorder columns.arColumn.state1.label.text = '$ARM' columns.arColumn.state1.label.arrowDown = true columns.arColumn.state1.entry.text = @infoArmor columns.arColumn.state1.sortAttributes = columns.arColumn.state1.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> columns.arColumn.state2.label.text = '$ARM' columns.arColumn.state2.entry.text = @infoArmor columns.arColumn.state2.sortAttributes = columns.arColumn.state2.sortOptions = <{ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; SUBTYPE COLUMN ------------------------------------------------------- columns.subTypeColumn.type = TEXT columns.subTypeColumn.name = '$TYPE' columns.subTypeColumn.states = 2 columns.subTypeColumn.width = 0.15 columns.subTypeColumn.border = a_textBorder columns.subTypeColumn.state1.label.text = '$TYPE' columns.subTypeColumn.state1.entry.text = @subTypeDisplay columns.subTypeColumn.state1.sortAttributes = columns.subTypeColumn.state1.sortOptions = <{ASCENDING | CASEINSENSITIVE}, {ASCENDING | CASEINSENSITIVE}> columns.subTypeColumn.state2.label.text = '$TYPE' columns.subTypeColumn.state2.entry.text = @subTypeDisplay columns.subTypeColumn.state2.label.arrowDown = true columns.subTypeColumn.state2.sortAttributes = columns.subTypeColumn.state2.sortOptions = <{DESCENDING | CASEINSENSITIVE}, {ASCENDING | CASEINSENSITIVE}> ; MATERIAL COLUMN ------------------------------------------------------- columns.materialColumn.type = TEXT columns.materialColumn.name = '$MATERIAL' columns.materialColumn.states = 2 columns.materialColumn.width = 0.10 columns.materialColumn.border = a_textBorder columns.materialColumn.hidden = true columns.materialColumn.state1.label.text = '$MAT' columns.materialColumn.state1.entry.text = @materialDisplay columns.materialColumn.state1.sortAttributes = columns.materialColumn.state1.sortOptions = <{ASCENDING | CASEINSENSITIVE}, {ASCENDING | CASEINSENSITIVE}> columns.materialColumn.state2.label.text = '$MAT' columns.materialColumn.state2.entry.text = @materialDisplay columns.materialColumn.state2.label.arrowDown = true columns.materialColumn.state2.sortAttributes = columns.materialColumn.state2.sortOptions = <{DESCENDING | CASEINSENSITIVE}, {ASCENDING | CASEINSENSITIVE}> ; CLASS COLUMN ------------------------------------------------------- columns.classColumn.type = TEXT columns.classColumn.name = '$CLASS' columns.classColumn.states = 2 columns.classColumn.width = 0.10 columns.classColumn.border = a_textBorder columns.classColumn.state1.label.text = '$CLASS' columns.classColumn.state1.entry.text = @weightClassDisplay columns.classColumn.state1.sortAttributes = columns.classColumn.state1.sortOptions = <{ASCENDING | CASEINSENSITIVE}, {ASCENDING | CASEINSENSITIVE}> columns.classColumn.state2.label.text = '$CLASS' columns.classColumn.state2.entry.text = @weightClassDisplay columns.classColumn.state2.label.arrowDown = true columns.classColumn.state2.sortAttributes = columns.classColumn.state2.sortOptions = <{DESCENDING | CASEINSENSITIVE}, {ASCENDING | CASEINSENSITIVE}> ; MAGNITUDE COLUMN ------------------------------------------------------- columns.magnitudeColumn.type = TEXT columns.magnitudeColumn.name = '$MAGNITUDE' columns.magnitudeColumn.states = 2 columns.magnitudeColumn.width = 0.09 columns.magnitudeColumn.border = a_textBorder columns.magnitudeColumn.state1.label.text = '$MAG' columns.magnitudeColumn.state1.label.arrowDown = true columns.magnitudeColumn.state1.entry.text = @magnitude columns.magnitudeColumn.state1.sortAttributes = columns.magnitudeColumn.state1.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> columns.magnitudeColumn.state2.label.text = '$MAG' columns.magnitudeColumn.state2.entry.text = @magnitude columns.magnitudeColumn.state2.sortAttributes = columns.magnitudeColumn.state2.sortOptions = <{ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; DURATION COLUMN ------------------------------------------------------- columns.durationColumn.type = TEXT columns.durationColumn.name = '$TIME' columns.durationColumn.states = 2 columns.durationColumn.width = 0.09 columns.durationColumn.border = a_textBorder columns.durationColumn.state1.label.text = '$TIME' columns.durationColumn.state1.label.arrowDown = true columns.durationColumn.state1.entry.text = @duration columns.durationColumn.state1.sortAttributes = columns.durationColumn.state1.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> columns.durationColumn.state2.label.text = '$TIME' columns.durationColumn.state2.entry.text = @duration columns.durationColumn.state2.sortAttributes = columns.durationColumn.state2.sortOptions = <{ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; MAGIC MAGNITUDE COLUMN ------------------------------------------------------- columns.magicMagnitudeColumn.type = TEXT columns.magicMagnitudeColumn.name = '$MAGNITUDE' columns.magicMagnitudeColumn.states = 2 columns.magicMagnitudeColumn.width = 0.15 columns.magicMagnitudeColumn.border = a_textBorder columns.magicMagnitudeColumn.state1.label.text = '$MAG' columns.magicMagnitudeColumn.state1.label.arrowDown = true columns.magicMagnitudeColumn.state1.entry.text = @magnitude columns.magicMagnitudeColumn.state1.sortAttributes = columns.magicMagnitudeColumn.state1.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> columns.magicMagnitudeColumn.state2.label.text = '$MAG' columns.magicMagnitudeColumn.state2.entry.text = @magnitude columns.magicMagnitudeColumn.state2.sortAttributes = columns.magicMagnitudeColumn.state2.sortOptions = <{ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; MAGIC DURATION COLUMN ------------------------------------------------------- columns.magicDurationColumn.type = TEXT columns.magicDurationColumn.name = '$TIME' columns.magicDurationColumn.states = 2 columns.magicDurationColumn.width = 0.15 columns.magicDurationColumn.border = a_textBorder columns.magicDurationColumn.state1.label.text = '$TIME' columns.magicDurationColumn.state1.label.arrowDown = true columns.magicDurationColumn.state1.entry.text = @duration columns.magicDurationColumn.state1.sortAttributes = columns.magicDurationColumn.state1.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> columns.magicDurationColumn.state2.label.text = '$TIME' columns.magicDurationColumn.state2.entry.text = @duration columns.magicDurationColumn.state2.sortAttributes = columns.magicDurationColumn.state2.sortOptions = <{ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; DAMAGE COLUMN ------------------------------------------------------- columns.damageColumn.type = TEXT columns.damageColumn.name = '$DAMAGE' columns.damageColumn.states = 2 columns.damageColumn.width = 0.09 columns.damageColumn.border = a_textBorder columns.damageColumn.state1.label.text = '$DAM' columns.damageColumn.state1.label.arrowDown = true columns.damageColumn.state1.entry.text = @infoDamage columns.damageColumn.state1.sortAttributes = columns.damageColumn.state1.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> columns.damageColumn.state2.label.text = '$DAM' columns.damageColumn.state2.entry.text = @infoDamage columns.damageColumn.state2.sortAttributes = columns.damageColumn.state2.sortOptions = <{ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; WEIGHT COLUMN ------------------------------------------------------- columns.weightColumn.type = TEXT columns.weightColumn.name = '$WEIGHT' columns.weightColumn.states = 2 columns.weightColumn.width = 0.09 columns.weightColumn.border = a_textBorder columns.weightColumn.state1.label.text = '$WGT' columns.weightColumn.state1.label.arrowDown = true columns.weightColumn.state1.entry.text = @infoWeight columns.weightColumn.state1.sortAttributes = columns.weightColumn.state1.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> columns.weightColumn.state2.label.text = '$WGT' columns.weightColumn.state2.entry.text = @infoWeight columns.weightColumn.state2.sortAttributes = columns.weightColumn.state2.sortOptions = <{ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; VALUE COLUMN ------------------------------------------------------- columns.valueColumn.type = TEXT columns.valueColumn.name = '$VALUE' columns.valueColumn.states = 2 columns.valueColumn.width = 0.09 columns.valueColumn.border = a_textBorder columns.valueColumn.state1.label.text = '$VAL' columns.valueColumn.state1.label.arrowDown = true columns.valueColumn.state1.entry.text = @infoValue columns.valueColumn.state1.sortAttributes = columns.valueColumn.state1.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> columns.valueColumn.state2.label.text = '$VAL' columns.valueColumn.state2.entry.text = @infoValue columns.valueColumn.state2.sortAttributes = columns.valueColumn.state2.sortOptions = <{ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; VALUE/WEIGHT COLUMN ------------------------------------------------------- columns.valueWeightColumn.type = TEXT columns.valueWeightColumn.name = '$VALUE/WEIGHT' columns.valueWeightColumn.states = 2 columns.valueWeightColumn.width = 0.09 columns.valueWeightColumn.border = a_textBorder columns.valueWeightColumn.hidden = true columns.valueWeightColumn.state1.label.text = '$V/W' columns.valueWeightColumn.state1.label.arrowDown = true columns.valueWeightColumn.state1.entry.text = @infoValueWeight columns.valueWeightColumn.state1.sortAttributes = columns.valueWeightColumn.state1.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> columns.valueWeightColumn.state2.label.text = '$V/W' columns.valueWeightColumn.state2.entry.text = @infoValueWeight columns.valueWeightColumn.state2.sortAttributes = columns.valueWeightColumn.state2.sortOptions = <{ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; MAGIC NAME COLUMN ------------------------------------------------------- columns.magicNameColumn.type = NAME columns.magicNameColumn.name = '$NAME' columns.magicNameColumn.states = 2 columns.magicNameColumn.weight = 1.0 columns.magicNameColumn.border = a_textBorder columns.magicNameColumn.label.textFormat.align = left columns.magicNameColumn.state1.label.text = '$NAME' columns.magicNameColumn.state1.entry.text = @text columns.magicNameColumn.state1.sortOptions = {ASCENDING | CASEINSENSITIVE} columns.magicNameColumn.state2.label.text = '$FAVORITE' columns.magicNameColumn.state2.entry.text = @text columns.magicNameColumn.state2.sortAttributes = columns.magicNameColumn.state2.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> columns.magicNameColumn.state2.playerOnly = true ; SPELL COST COLUMN ------------------------------------------- columns.spellCostColumn.type = TEXT columns.spellCostColumn.name = '$SPELL COST' columns.spellCostColumn.states = 2 columns.spellCostColumn.width = 0.15 columns.spellCostColumn.border = a_textBorder columns.spellCostColumn.state1.label.text = '$COST' columns.spellCostColumn.state1.label.arrowDown = true columns.spellCostColumn.state1.entry.text = @spellCostDisplay columns.spellCostColumn.state1.sortAttributes = columns.spellCostColumn.state1.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> columns.spellCostColumn.state2.label.text = '$COST' columns.spellCostColumn.state2.label.arrowDown = false columns.spellCostColumn.state2.entry.text = @spellCostDisplay columns.spellCostColumn.state2.sortAttributes = columns.spellCostColumn.state2.sortOptions = <{ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; WORD 1 COLUMN ------------------------------------------- columns.word0Column.type = TEXT columns.word0Column.name = '$FIRST WORD' columns.word0Column.states = 2 columns.word0Column.width = 0.2 columns.word0Column.border = a_textBorder columns.word0Column.state1.label.text = '$FIRST WORD' columns.word0Column.state1.label.arrowDown = true columns.word0Column.state1.entry.text = @word0 columns.word0Column.state1.sortAttributes = columns.word0Column.state1.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> columns.word0Column.state1.colorAttribute = word0Color columns.word0Column.state2.label.text = '$FIRST WORD' columns.word0Column.state2.label.arrowDown = false columns.word0Column.state2.entry.text = @word0 columns.word0Column.state2.sortAttributes = columns.word0Column.state2.sortOptions = <{ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> columns.word0Column.state2.colorAttribute = word0Color ; WORD 2 COLUMN ------------------------------------------- columns.word1Column.type = TEXT columns.word1Column.name = '$SECOND WORD' columns.word1Column.states = 2 columns.word1Column.width = 0.2 columns.word1Column.border = a_textBorder columns.word1Column.state1.label.text = '$SECOND WORD' columns.word1Column.state1.label.arrowDown = true columns.word1Column.state1.entry.text = @word1 columns.word1Column.state1.sortAttributes = columns.word1Column.state1.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> columns.word1Column.state1.colorAttribute = word1Color columns.word1Column.state2.label.text = '$SECOND WORD' columns.word1Column.state2.label.arrowDown = false columns.word1Column.state2.entry.text = @word1 columns.word1Column.state2.sortAttributes = columns.word1Column.state2.sortOptions = <{ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> columns.word1Column.state2.colorAttribute = word1Color ; WORD 3 COLUMN ------------------------------------------- columns.word2Column.type = TEXT columns.word2Column.name = '$THIRD WORD' columns.word2Column.states = 2 columns.word2Column.width = 0.2 columns.word2Column.border = a_textBorder columns.word2Column.state1.label.text = '$THIRD WORD' columns.word2Column.state1.label.arrowDown = true columns.word2Column.state1.entry.text = @word2 columns.word2Column.state1.sortAttributes = columns.word2Column.state1.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> columns.word2Column.state1.colorAttribute = word2Color columns.word2Column.state2.label.text = '$THIRD WORD' columns.word2Column.state2.label.arrowDown = false columns.word2Column.state2.entry.text = @word2 columns.word2Column.state2.sortAttributes = columns.word2Column.state2.sortOptions = <{ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> columns.word2Column.state2.colorAttribute = word2Color ; SCHOOL COLUMN ------------------------------------------- columns.schoolColumn.type = TEXT columns.schoolColumn.name = '$SCHOOL' columns.schoolColumn.states = 2 columns.schoolColumn.width = 0.15 columns.schoolColumn.border = a_textBorder columns.schoolColumn.state1.label.text = '$SCHOOL' columns.schoolColumn.state1.label.arrowDown = false columns.schoolColumn.state1.entry.text = @infoSchoolName columns.schoolColumn.state1.sortAttributes = columns.schoolColumn.state1.sortOptions = <{ASCENDING | CASEINSENSITIVE}, {ASCENDING | CASEINSENSITIVE}> columns.schoolColumn.state2.label.text = '$SCHOOL' columns.schoolColumn.state2.label.arrowDown = true columns.schoolColumn.state2.entry.text = @infoSchoolName columns.schoolColumn.state2.sortAttributes = columns.schoolColumn.state2.sortOptions = <{DESCENDING | CASEINSENSITIVE}, {ASCENDING | CASEINSENSITIVE}> ; LEVEL COLUMN ------------------------------------------- columns.levelColumn.type = TEXT columns.levelColumn.name = '$SKILL LEVEL' columns.levelColumn.states = 2 columns.levelColumn.width = 0.15 columns.levelColumn.border = a_textBorder columns.levelColumn.state1.label.text = '$LEVEL' columns.levelColumn.state1.label.arrowDown = false columns.levelColumn.state1.entry.text = @infoCastLevel columns.levelColumn.state1.sortAttributes = columns.levelColumn.state1.sortOptions = <{ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> columns.levelColumn.state2.label.text = '$LEVEL' columns.levelColumn.state2.label.arrowDown = true columns.levelColumn.state2.entry.text = @infoCastLevel columns.levelColumn.state2.sortAttributes = columns.levelColumn.state2.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; TIME REMAINING COLUMN ------------------------------------------- columns.timeRemainingColumn.type = TEXT columns.timeRemainingColumn.name = '$TIME LEFT' columns.timeRemainingColumn.states = 2 columns.timeRemainingColumn.width = 0.333 columns.timeRemainingColumn.label.textFormat.align = center columns.timeRemainingColumn.entry.textFormat.align = center columns.timeRemainingColumn.state1.label.text = '$TIME LEFT' columns.timeRemainingColumn.state1.label.arrowDown = false columns.timeRemainingColumn.state1.entry.text = @timeRemainingDisplay columns.timeRemainingColumn.state1.sortAttributes = columns.timeRemainingColumn.state1.sortOptions = <{ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> columns.timeRemainingColumn.state2.label.text = '$TIME LEFT' columns.timeRemainingColumn.state2.label.arrowDown = true columns.timeRemainingColumn.state2.entry.text = @timeRemainingDisplay columns.timeRemainingColumn.state2.sortAttributes = columns.timeRemainingColumn.state2.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; EFFECT ITEM COLUMN ------------------------------------------- columns.effectItemColumn.type = TEXT columns.effectItemColumn.name = '$SOURCE' columns.effectItemColumn.states = 2 columns.effectItemColumn.width = 0.333 columns.effectItemColumn.label.textFormat.align = right columns.effectItemColumn.entry.textFormat.align = right columns.effectItemColumn.state1.label.text = '$SOURCE' columns.effectItemColumn.state1.label.arrowDown = false columns.effectItemColumn.state1.entry.text = @cardName columns.effectItemColumn.state1.sortAttributes = columns.effectItemColumn.state1.sortOptions = <{ASCENDING | CASEINSENSITIVE}, {ASCENDING | CASEINSENSITIVE}> columns.effectItemColumn.state2.label.text = '$SOURCE' columns.effectItemColumn.state2.label.arrowDown = true columns.effectItemColumn.state2.entry.text = @cardName columns.effectItemColumn.state2.sortAttributes = columns.effectItemColumn.state2.sortOptions = <{DESCENDING | CASEINSENSITIVE}, {ASCENDING | CASEINSENSITIVE}> ; CRAFT NAME COLUMN ------------------------------------------------------- columns.craftNameColumn.type = NAME columns.craftNameColumn.name = '$NAME' columns.craftNameColumn.states = 1 columns.craftNameColumn.weight = 1.0 columns.craftNameColumn.border = a_textBorder columns.craftNameColumn.label.textFormat.align = left columns.craftNameColumn.state1.label.text = '$NAME' columns.craftNameColumn.state1.entry.text = @text columns.craftNameColumn.state1.sortAttributes = columns.craftNameColumn.state1.sortOptions = <{ASCENDING | CASEINSENSITIVE}> ; DISENCHANT EFFECT COLUMN ------------------------------------------------------- columns.disenchantEffectColumn.type = TEXT columns.disenchantEffectColumn.name = '$EFFECT' columns.disenchantEffectColumn.states = 2 columns.disenchantEffectColumn.width = 0.4 columns.disenchantEffectColumn.label.textFormat.align = right columns.disenchantEffectColumn.entry.textFormat.align = right columns.disenchantEffectColumn.state1.label.text = '$EFFECT' columns.disenchantEffectColumn.state1.label.arrowDown = false columns.disenchantEffectColumn.state1.entry.text = @effectName columns.disenchantEffectColumn.state1.sortAttributes = columns.disenchantEffectColumn.state1.sortOptions = <{ASCENDING | CASEINSENSITIVE}, {DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> columns.disenchantEffectColumn.state2.label.text = '$EFFECT' columns.disenchantEffectColumn.state2.label.arrowDown = true columns.disenchantEffectColumn.state2.entry.text = @effectName columns.disenchantEffectColumn.state2.sortAttributes = columns.disenchantEffectColumn.state2.sortOptions = <{DESCENDING | CASEINSENSITIVE}, {DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; SOUL SIZE COLUMN ------------------------------------------------------- columns.soulSizeColumn.type = TEXT columns.soulSizeColumn.name = '$HK19' columns.soulSizeColumn.states = 2 columns.soulSizeColumn.width = 0.15 columns.soulSizeColumn.label.textFormat.align = right columns.soulSizeColumn.entry.textFormat.align = right columns.soulSizeColumn.state1.label.text = '$HK19' columns.soulSizeColumn.state1.label.arrowDown = false columns.soulSizeColumn.state1.entry.text = @soulSizeDisplay columns.soulSizeColumn.state1.sortAttributes = columns.soulSizeColumn.state1.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> columns.soulSizeColumn.state2.label.text = '$HK19' columns.soulSizeColumn.state2.label.arrowDown = true columns.soulSizeColumn.state2.entry.text = @soulSizeDisplay columns.soulSizeColumn.state2.sortAttributes = columns.soulSizeColumn.state2.sortOptions = <{ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; ALCHEMY WEIGHT COLUMN ------------------------------------------------------- columns.alchWeightColumn.type = TEXT columns.alchWeightColumn.name = '$WEIGHT' columns.alchWeightColumn.states = 2 columns.alchWeightColumn.width = 0.14 columns.alchWeightColumn.border = a_textBorder columns.alchWeightColumn.state1.label.text = '$WGT' columns.alchWeightColumn.state1.label.arrowDown = true columns.alchWeightColumn.state1.entry.text = @infoWeight columns.alchWeightColumn.state1.sortAttributes = columns.alchWeightColumn.state1.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> columns.alchWeightColumn.state2.label.text = '$WGT' columns.alchWeightColumn.state2.entry.text = @infoWeight columns.alchWeightColumn.state2.sortAttributes = columns.alchWeightColumn.state2.sortOptions = <{ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; ALCHEMY VALUE COLUMN ------------------------------------------------------- columns.alchValueColumn.type = TEXT columns.alchValueColumn.name = '$VALUE' columns.alchValueColumn.states = 2 columns.alchValueColumn.width = 0.14 columns.alchValueColumn.border = a_textBorder columns.alchValueColumn.state1.label.text = '$VAL' columns.alchValueColumn.state1.label.arrowDown = true columns.alchValueColumn.state1.entry.text = @infoValue columns.alchValueColumn.state1.sortAttributes = columns.alchValueColumn.state1.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> columns.alchValueColumn.state2.label.text = '$VAL' columns.alchValueColumn.state2.entry.text = @infoValue columns.alchValueColumn.state2.sortAttributes = columns.alchValueColumn.state2.sortOptions = <{ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; ALCHEMY VALUE/WEIGHT COLUMN ------------------------------------------------------- columns.alchValueWeightColumn.type = TEXT columns.alchValueWeightColumn.name = '$VALUE/WEIGHT' columns.alchValueWeightColumn.states = 2 columns.alchValueWeightColumn.width = 0.14 columns.alchValueWeightColumn.border = a_textBorder columns.alchValueWeightColumn.hidden = true columns.alchValueWeightColumn.state1.label.text = '$V/W' columns.alchValueWeightColumn.state1.label.arrowDown = true columns.alchValueWeightColumn.state1.entry.text = @infoValueWeight columns.alchValueWeightColumn.state1.sortAttributes = columns.alchValueWeightColumn.state1.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> columns.alchValueWeightColumn.state2.label.text = '$V/W' columns.alchValueWeightColumn.state2.entry.text = @infoValueWeight columns.alchValueWeightColumn.state2.sortAttributes = columns.alchValueWeightColumn.state2.sortOptions = <{ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; ITEM VIEWS ------------------------------------------------------- views.defaultItemView.primaryColumn = itemNameColumn views.defaultItemView.columns = views.weaponView.primaryColumn = itemNameColumn views.weaponView.columns = views.weaponView.category = views.armorView.primaryColumn = itemNameColumn views.armorView.columns = views.armorView.category = views.magicItemView.primaryColumn = itemNameColumn views.magicItemView.columns = views.magicItemView.category = views.keysView.primaryColumn = itemNameColumn views.keysView.columns = views.keysView.category = ; MAGIC VIEWS ------------------------------------------------------- views.defaultMagicView.primaryColumn = magicNameColumn views.defaultMagicView.columns = views.allMagicView.primaryColumn = magicNameColumn views.allMagicView.columns = views.allMagicView.category = views.shoutsView.primaryColumn = magicNameColumn views.shoutsView.columns = views.shoutsView.category = Inventory.FILTERFLAG_MAGIC_SHOUTS views.powersView.primaryColumn = magicNameColumn views.powersView.columns = views.powersView.category = Inventory.FILTERFLAG_MAGIC_POWERS views.activeEffectView.primaryColumn = magicNameColumn views.activeEffectView.columns = views.activeEffectView.category = Inventory.FILTERFLAG_MAGIC_ACTIVEEFFECTS ; CRAFTING VIEWS ------------------------------------------------------- views.defaultCraftingView.primaryColumn = craftNameColumn views.defaultCraftingView.columns = views.disenchantView.primaryColumn = craftNameColumn views.disenchantView.columns = views.disenchantView.category = Inventory.FILTERFLAG_ENCHANTING_DISENCHANT views.enchantItemView.primaryColumn = craftNameColumn views.enchantItemView.columns = views.enchantItemView.category = Inventory.FILTERFLAG_ENCHANTING_ITEM views.enchantEnchantmentView.primaryColumn = craftNameColumn views.enchantEnchantmentView.columns = views.enchantEnchantmentView.category = Inventory.FILTERFLAG_ENCHANTING_ENCHANTMENT views.enchantSoulView.primaryColumn = craftNameColumn views.enchantSoulView.columns = views.enchantSoulView.category = Inventory.FILTERFLAG_ENCHANTING_SOULGEM views.craftWeaponView.primaryColumn = craftNameColumn views.craftWeaponView.columns = views.craftWeaponView.category = views.craftArmorView.primaryColumn = craftNameColumn views.craftArmorView.columns = views.craftArmorView.category = Inventory.FILTERFLAG_CUST_CRAFT_ARMOR views.alchemyView.primaryColumn = craftNameColumn views.alchemyView.columns = ; LAYOUTS ------------------------------------------------------- layouts.itemListLayout.name = 'ItemListLayout' layouts.itemListLayout.views = layouts.magicListLayout.name = 'MagicListLayout' layouts.magicListLayout.views = layouts.enchantListLayout.name = 'EnchantListLayout' layouts.enchantListLayout.views = layouts.constructListLayout.name = 'ConstructListLayout' layouts.constructListLayout.views = layouts.smithingListLayout.name = 'SmithingListLayout' layouts.smithingListLayout.views = layouts.alchemyListLayout.name = 'AlchemyListLayout' layouts.alchemyListLayout.views = ================================================ FILE: dist/Data/Readme - SkyUI.txt ================================================ ######################################################################################################################################## _______ _ _ __ __ _ _ _____ |______ |____/ \_/ | | | ______| | \_ | |_____| __|__ ######################################################################################################################################## Team: snakster, Mardoxx, T3T Contributors: ianpatt, behippo, Kratos, psychosteve, MisterPete, GreatClone, gibbed, PurpleLunchBox, Verteiron, Gopher, Indie Version: 4.1 Download: http://skyrim.nexusmods.com/mods/3863 http://steamcommunity.com/sharedfiles/filedetails/?id=8122 Source code: https://github.com/schlangster/skyui ######################################################################################################################################## The following mods/utilities are required for SkyUI: * The Skyrim Script Extender (SKSE), version 1.6.16 or newer http://skse.silverlock.org/ ######################################################################################################################################## 1. Introduction 2. Changelog 3. Installation 4. Uninstallation 5. Troubleshooting 6. Mod Author Guide 7. Credits & Acknowledgements 8. Contact 9. Permissions ######################################################################################################################################## ======================================================================================================================================== 1. Introduction ======================================================================================================================================== SkyUI is a mod that aims to improve Skyrim's User Interface by making it easier to use with mouse and keyboard, less wasteful of available screen space, and nicer to look at. We do all that while keeping true to the style of the original UI, so new and old components are integrated seamlessly. It is not our goal to re-create the complete interface from scratch. Instead we try to identify and change areas that need improvement, while leaving the things that are already good alone. Further general objectives and design concepts are: * Finding a good balance between 'dumbed down' and 'information overkill'. * Easy installation and setup. * Blending features in as well as possible - players shouldn't feel reminded that they're using a mod. * Support for user customization. Since improving the whole UI is a big undertaking, we only release single menus at a time as progress is made. The first menu we addressed was the Inventory. In version 2.0, we included new Barter, Container and Magic menus. Version 3.0 introduced an in-game configuration menu for mods. The most recent addition was the Favorites menu in version 4.0. For a more detailed description, please see our mod description on Skyrim Nexus. ======================================================================================================================================== 2. Changelog ======================================================================================================================================== ------------------------------------------------------------ 4.1: [General] - Updated SKSE version requirement to 1.6.16. [FavoritesMenu] - Included ammo in Gear category. - Transforming into a Vampire Lord no longer resets group data. - Changing the load order index of a mod no longer removes its items from any groups. - Fixed issues when equipping a two-handed weapon that's already equipped via Group Use. - Fixed issue with 'Unequip Armor' flag, which would incorrectly unequip an armor piece if it's already worn. - Fixed Group Use crashes with 2 identical weapons. - Enabled group hotkey rebinding for gamepads. ------------------------------------------------------------ 4.0: [General] - Updated SKSE version requirement to 1.6.15. [ModConfigurationMenu] - Enabled nested translations for option and value text (uses the same format as SetInfoText). - Added OPTION_FLAG_HIDDEN to hide an option. - Added OPTION_FLAG_WITH_UNMAP. When set for keymap options, it enables an unmap button that'll send keycode -1. - Improved menu registration process to avoid missing menus on the first save load. For real this time. - Enabled basic HTML formatting for option label text. Example: "$Hello". - Fixed an issue with gamepad/keyboard navigation where the wrong entry was selected when scrolling. [MapMenu] - Fixed issue where search widget wasn't being completely disabled when hidden. [ActiveEffectsWidget] - With SKSE 1.6.15, inactive effects are now filtered out. - Added a configurable minimum time left to hide long lasting effects like blessings until they are about to expire. [FavoritesMenu] - Initial release ------------------------------------------------------------ 3.4: [ModConfigurationMenu] - Fixed issue that could prevent certain MCM mods from registering correctly (i.e. Wet and Cold). ------------------------------------------------------------ 3.3: [General] - Reverted batch load size to default to avoid delays with lots of saves. - Fixed map.swf filename in conflict warning message. - Fixed "Disable positioning" option. [ModConfigurationMenu] - Reverted menu registration code back to 3.1 until I have more time to resolve all issues with the new method. [HUDWidgetLoader] - Fixed bug that kept health bar permanently visible (or hidden). ------------------------------------------------------------ 3.2: [General] - Updated SKSE version requirement to 1.6.9. - Inventory and magic menus now remember and restore last selected column and sorting state. - Added emblem to indicate read books/scrolls. - Fixed several Dragonborn icons. - Improved visbility of equip icons. - Fixed an issue in the NMM installer that could cause a crash when trying to force the installation. - Fixed issue where closing a menu before any checks are able to complete would cause false error messages to appear. - Optimized memory usage of config menu buffers. - Increased config timeout delay from 1 to 3 seconds. - Added error message to detect invalid Papyrus .ini settings. - Updated quest_journal.swf to support legendary difficulty that has been added in Skyrim 1.9. [ModConfigurationMenu] - Added a repair console command that forces all menus to re-register: setStage SKI_ConfigManagerInstance 1 - Improved SetInfoText to support nested translation strings. See MCM API reference for details. - Added an new method to organize options as states. Fully backward compatible. See state MCM state option guide for details. - Fixed issue where it would take several reloads until all menus registered successfully when running a lot of mods. [MapMenu] - Initial release [ActiveEffectsWidget] - Initial release [HUDWidgetLoader] - Initial release ------------------------------------------------------------ 3.1: [General] - Added MCM option to select the category icon theme. Includes all themes from version 2.2 (Celtic, Curved, Straight). - Added MCM options to configure some gamepad mappings manually. This should resolve conflicts with custom controlmaps. - Added MCM option to disable icon colors. - Added NMM installer script that detects/reports the most common installation problems. - Added runtime check for missing SKSE scripts. - Updated SKSE version requirement to 1.6.6. Fixes the non-functional localization. - Fixed leather strips type identifier. - Fixed minor mistakes in the config. - Fixed issues with PropertyDataExtender to allow custom config.txt overrides. - Fixed MCM logo hat madness. - Made some error messages clearer. ------------------------------------------------------------ 3.0: [General] - Added more columns to item lists and a drop-down menu to show/hide them. - Added a new icon theme by Psychosteve (support for the old themes had to be dropped because they are no longer maintained). - Added type column to group items of the same category into sub-types. - Added dynamic icon coloring. - Added option to configure the minimum stack size that triggers the quantity select dialog. - Added dynamic icon art to bottom bar so it matches the current control mapping. - Replaced NMM installer with an in-game configuration menu. - Replaced old error messages with regular message boxes and added more safety checks for outdated SkyUI components. - Fixed various minor issues and improved performance. - Consolidated package format to BSA+ESP. [ContainerMenu] - Added support for GiftMenu. - Improved input scheme for mouse and keyboard (no more R to Take All and Store, mouse click for Give/Take etc.). [BarterMenu] - Added carry weight display to bottom bar. [MagicMenu] - Fixed locked words being shown as unlocked if one word is known. - Fixed an issue that could cause crashes for spells with missing effect data. [ModConfigurationMenu] - Initial release. Mod authors, see https://github.com/schlangster/skyui/wiki for documentation. ------------------------------------------------------------ 2.1: [General] - Added compatiblity for the Skyrim version 1.4.21. - Added multi-language support for Czech, English, French, German, Italian, Polish, Russian and Spanish. - Added several options to the installer (font size, separate V/W column, special resolution). - Added a BAIN Conversion File (BCF) including an installation wizard for better Wyre Bash support. Thanks to Lojack! - Fixed a bug where selling/dropping/storing stacked items could cause the selected entry to jump to the bottom of the list. - The last selected category, entry and scroll position are now saved and restored when re-opening the inventory/magic menu. - Sorting parameters are now preserved if possible when switching through categories. - Improved the SKSE version check so it will also display a warning when using outdated versions. - Most features of our SKSE plugins have been reworked and are now integrated in SKSE itself. - Various other tweaks and minor fixes. [InventoryMenu] - Fixed a rare bug that could cause crashes after recharging an item. [MagicMenu] - Fixed skill level sorting. - Added 'Favorite' as a sort option. [ContainerMenu] - Fixed stealing text for Russian game version. - Fixed overlapping of to steal/to place text for large itemcards. ------------------------------------------------------------ 2.0: [InventoryMenu] - Fixed enchantment mini-icon so it's no longer displayed for enchanted weapons only. - Fixed missing sort options for name field in the favorites category. - Fixed backspace cancelling the search. - Fixed searching for non-English languages (i.e. Russian). - Improved sorting system. Null/invalid values are now always at the bottom. - Empty categories are greyed out and no longer selectable by mouse or during keyboard/controller navigation. - Included a bundled version of Gibbed's Container Categorization SKSE plugin. Thanks for giving us permission to use it! [MagicMenu] - Initial release [BarterMenu] - Initial release [ContainerMenu] - Initial release ------------------------------------------------------------ 1.1: [InventoryMenu] - Updated Gibbed's interface extensions plugin to support the latest Skyrim version 1.3.10.0. - Improved support for XBOX360 controller: LB/RB can now be used to change the active column; Left Stick changes the sorting order. - Made SKSE warning message less intrusive; it's only shown once after each game restart now. - Fixed LT/RT equip bug with XBOX360 controller. - Fixed bug where 3D model/item card would not update in certain situations (dropping an item, charging an item, etc.). - Removed custom fontconfig.txt to avoid font problems with other font mods, or with the Russian version of the game. - Optimized column layout so it only shows states and information that make sense for the active category. - Updated T3T's straight icon theme to include new inventory icons. - Updated GreatClone's icon theme to the latest version. Now includes inventory icons as well, and category icons have been improved. - Fixed wrong inventory icon for spell tomes. - Various minor tweaks and fixes. ------------------------------------------------------------ 1.0: [InventoryMenu] - Initial release ======================================================================================================================================== 3. Installation ======================================================================================================================================== ------------------------------------------------------------ IMPORTANT: If you were using SkyUI 2.2 or older, you MUST remove it before installing the new version. See section 4 for instructions. ------------------------------------------------------------ There are several ways to install SkyUI: - Subscribe to SkyUI on Steam Workshop. - Let the Nexus Mod Manager (NMM) download and install the archive for you. - Download the archive manually and install it with NMM. - Download and install the archive manually. Pick the method you prefer. ------------------------------------------------------------ a) Subscribe on Steam Workshop ------------------------------------------------------------ 1. Go to http://steamcommunity.com/sharedfiles/filedetails/?id=8122 and click subscribe. 2. The next time you start the Skyrim Launcher, SkyUI will be downloaded and installed automatically. OR ------------------------------------------------------------ b) Automated Download with NMM ------------------------------------------------------------ 1. Click the 'Download with manager' button on top of the file. 2. SkyUI will appear in in NMM's Mods list once it's downloaded. Double-click the SkyUI entry to activate it. OR ------------------------------------------------------------ c) Manual Download with NMM ------------------------------------------------------------ 1. Start NMM and click on 'Mods'. 2. In the left icon bar, click on 'Add Mod From File' and select the downloaded archive file. 3. SkyUI will now appear in the list. Double-click the entry to activate it. OR ------------------------------------------------------------ d) Manual Installation ------------------------------------------------------------ 1. Locate the 'Data/' folder in your Skyrim installation directory. Typically it's found at 'Program Files/Steam/steamapps/common/skyrim/Data/'. 2. Extract the contents of the downloaded archive file to the 'Data/' folder. 3. In the Skyrim Launcher, select 'Data Files' and enable 'SkyUI.esp'. ======================================================================================================================================== 4. Uninstallation ======================================================================================================================================== The uninstallation method depends on which SkyUI version you were using before and how you installed it. Any SkyUI version older than 3.0 (this includes alpha builds) has to be removed before upgrading. For details, see the following instructions that match your current SkyUI version/installation method. ------------------------------------------------------------ NMM installation / Any SkyUI version ------------------------------------------------------------ In NMM's mod list, search for the SkyUI entry and deactivate the mod. ------------------------------------------------------------ Steam workshop / Any SkyUI version ------------------------------------------------------------ Unsubscribe from the mod and deactivate it in Skyrim Launcher (if you haven't already). There, you can also completely remove it by highlighting it and pressing 'Delete Selected'. ------------------------------------------------------------ Manual installation / SkyUI 2.2 or older ------------------------------------------------------------ If you installed the SkyUI files manually, then you also have to remove them manually. So view the contents of the SkyUI archive you are using, locate each file at its install location and remove it. To revert your interface folder to its original state, you can delete the 'Interface/' directory from Skyrim's 'Data/' folder and then use Steam to restore any original files you removed in the process by following these steps: (Backup your interface folder before deleting it in case anything goes wrong) 1. Locate Skyrim in Steam's game library. 2. Open the properties dialog and select the 'Local files' tab. 3. Verify integrity of game cache. Be aware, that this will break any other mods that installed files to the interface folder. You will have to re-install them. ------------------------------------------------------------ Manual installation / SkyUI 3.0 and newer ------------------------------------------------------------ 1. Locate the 'Data/' folder in your Skyrim installation directory. It's typically found at 'Program Files/Steam/steamapps/common/skyrim/Data/'. 2. Delete 'SkyUI.esp' and 'SkyUI.bsa' from the data folder. ------------------------------------------------------------ SkyUI 3.0 alpha versions ------------------------------------------------------------ Before removing any files, it is recommended to make a 'clean' save game with SkyUI deactivated. 1. Start the Skyrim Launcher and select 'Data Files'. 2. Search 'SkyUI.esp' and uncheck it. (If you don't have this file, there's no need for a clean save anyway and you can skip it) 3. In-game, load your latest save, then save the game again. 4. This new save game is now cleaned of SkyUI data. You can now proceed to uninstall the files. The 3.0 alpha packages contained loose script files required by mod authors to create configuration menus. Make absolutely sure to remove these files, because they will override any newer scripts in SkyUI.bsa. 1. Locate the 'Scripts/' folder in your Skyrim data directory. It's typically found at 'Program Files/Steam/steamapps/common/skyrim/Data/Scripts/'. 2. Delete any script files (.pex) that start with SKI_, for example SKI_ConfigBase.pex, SKI_Main.pex, etc. 3. Delete 'SkyUI.esp' and 'SkyUI.bsa' from the data folder if present. ======================================================================================================================================== 5. Troubleshooting ======================================================================================================================================== ------------------------------------------------------------ Problem: There's an error message, reporting "SKYUI ERROR CODE X"... See https://github.com/schlangster/skyui/wiki/SkyUI-Errors for potential problems and their solutions. ------------------------------------------------------------ Problem: There are dollar signs ($) in front of all words in the main menu (and in lots of other places, too)! This happens if you accidently removed 'Data/Interface/Translate_.txt'. To restore it, use Steam to verify the integrity of Skyrim's game-cache (Steam -> Library -> Properties of Skyrim -> Local files tab -> Verify integrity of game cache). ------------------------------------------------------------ Problem: There are mods missing from my MCM list. Is there anything I can do about it? Before starting to reinstall mods, you can try to run a repair script we added in SkyUI 3.2. To do this, open the console and enter "setStage SKI_ConfigManagerInstance 1" (without the quotes). If your problem wasn't listed here, ask for help in the Nexus comments. ======================================================================================================================================== 6. Mod Author Guide ======================================================================================================================================== Since version 3.0, SkyUI provides a Mod Configuration Menu framework that can be utilized by other mods. If you're a mod author interested in using it, have a look at the documentation: https://github.com/schlangster/skyui/wiki ======================================================================================================================================== 7. Credits & Acknowledgements ======================================================================================================================================== Besides the SkyUI team itself, there are other people as well who helped significantly to make this mod a reality. In the following they are listed by name, including a list of their contributions. Kratos: Was a core member of the SkyUI team until version 2.1 and as such contributed significantly to the project in various areas. ianpatt: Added lots of new functions to the Skyrim Script Extender, that greatly helped us during development and enabled new features that would otherwise be impossible. behippo: Helped improving/advancing the interface extensions plugin by decoding the game classes and giving us access to them through SKSE. Gibbed: Created the 'gibbed interface extensions' SKSE plugin, which makes more game data available for display in the inventory. Also allowed us to bundle his container categorization plugin. As of version 2.1, both these plugins have been included in SKSE itself. Indie: Created our trailer and helps with QA and user support. GreatClone: Created an amazing set of alternative category icons. Gopher: Did most of the work on the NMM installer, created an installation tutorial video and promoted SkyUI on his YouTube channel. Lojack: Created a BCF (including an installation wizard) for SkyUI to improve the installation experience for Wyre Bash users. Also added an auto-conversion feature to Wyre Bash itself so this BCF is automatically applied. Ismelda: Provided configs for very high resolutions used with multi-monitor setups. Wakeupbrandon: His mock-up inspired the overall layout of the new inventory. MisterPete: Implemented new column types for improved sorting. Psychosteve: Created our new primary icon theme for version 3.0. He also created the Active Effect icons that have been added in version 3.2. Pelinor: The creator of MCM for Fallout: New Vegas. Allowed us to use his original logo. SkyUI is utilizing TweenLite, a high-performance tweening library (http://www.greensock.com/tweenlite/). Thanks to Jack Doyle and his team for creating it and allowing us to use it under their No Charge license. Thanks to all the testers, who helped a great deal with improving the overall quality of this mod: ToJKa, HellKnight, xporc, MadCat221, Ismelda, Gribbles, freesta, Cartrodus, TheCastle, NewRaven, T-qb, V4N0, Noritep, claudekennilol, dj2005, llfbandit, webrunner, 352, Erelde, tejon, Sagittarius22 (in random order) Thanks to all translators who helped localizing SkyUI to different languages, among them being: Sagittarius22, LLFBandit, xporc (French) xlwarrior, aloot (Spanish) Starfis (Czech) Rhaegal, aloot (Italian) patryk110 (Polish) vova2112 (Russian) Last but not least, thanks to the whole SKSE team, because without their Script Extender creating this mod wouldn't have been possible. ======================================================================================================================================== 8. Contact ======================================================================================================================================== For direct contact, send a PM to schlangster at http://www.skyrimnexus.com/ or http://forums.bethsoft.com/ If you need help, please leave a comment on our Nexus page instead of contacting me directly. ======================================================================================================================================== 9. Permissions ======================================================================================================================================== Some assets in SkyUI belong to other authors. You will need to seek permission from these authors before you can use their assets. You are not allowed to upload this file to other sites unless given permission by me to do so. You are not allowed to convert this file to work on other games. You must get permission from me before you are allowed to modify my files for bug fixes and improvements. You must get permission from me before you are allowed to use any of the assets in this file. ================================================ FILE: dist/Data/Scripts/Headers/SKI_ConfigBase.psc ================================================ scriptname SKI_ConfigBase extends SKI_QuestBase ;################################################################################################## ; API Version: 3 ;################################################################################################## ; ; Base script for custom config menus. ; ; This file contains the public interface of SKI_ConfigBase so you're able to extend it. ; For documentation, see https://github.com/schlangster/skyui/wiki/MCM-API-Reference. ; ; DO NOT MODIFY THIS SCRIPT! ; DO NOT RECOMPILE THIS SCRIPT! ; ;################################################################################################## ; CONSTANTS --------------------------------------------------------------------------------------- int property OPTION_FLAG_NONE = 0x00 autoReadonly int property OPTION_FLAG_DISABLED = 0x01 autoReadonly int property OPTION_FLAG_HIDDEN = 0x02 autoReadonly ; Version 3 int property OPTION_FLAG_WITH_UNMAP = 0x04 autoReadonly ; Version 3 int property LEFT_TO_RIGHT = 1 autoReadonly int property TOP_TO_BOTTOM = 2 autoReadonly ; PROPERTIES ------------------------------------------------------------------------- Version 1 -- string property ModName auto string[] property Pages auto string property CurrentPage string function get() Guard() return "" endFunction endProperty ; EVENTS ----------------------------------------------------------------------------- Version 1 -- event OnConfigInit() {Called when this config menu is initialized} Guard() endEvent event OnConfigRegister() {Called when this config menu registered at the control panel} Guard() endEvent event OnConfigOpen() {Called when this config menu is opened} Guard() endEvent event OnConfigClose() {Called when this config menu is closed} Guard() endEvent event OnVersionUpdate(int a_version) {Called when a version update of this script has been detected} Guard() endEvent event OnPageReset(string a_page) {Called when a new page is selected, including the initial empty page} Guard() endEvent event OnOptionHighlight(int a_option) {Called when highlighting an option} Guard() endEvent event OnOptionSelect(int a_option) {Called when a non-interactive option has been selected} Guard() endEvent event OnOptionDefault(int a_option) {Called when resetting an option to its default value} Guard() endEvent event OnOptionSliderOpen(int a_option) {Called when a slider option has been selected} Guard() endEvent event OnOptionSliderAccept(int a_option, float a_value) {Called when a new slider value has been accepted} Guard() endEvent event OnOptionMenuOpen(int a_option) {Called when a menu option has been selected} Guard() endEvent event OnOptionMenuAccept(int a_option, int a_index) {Called when a menu entry has been accepted} Guard() endEvent event OnOptionColorOpen(int a_option) {Called when a color option has been selected} Guard() endEvent event OnOptionColorAccept(int a_option, int a_color) {Called when a new color has been accepted} Guard() endEvent event OnOptionKeyMapChange(int a_option, int a_keyCode, string a_conflictControl, string a_conflictName) {Called when a key has been remapped} Guard() endEvent ; EVENTS ----------------------------------------------------------------------------- Version 2 -- event OnHighlightST() {Called when highlighting a state option} Guard() endEvent event OnSelectST() {Called when a non-interactive state option has been selected} Guard() endEvent event OnDefaultST() {Called when resetting a state option to its default value} Guard() endEvent event OnSliderOpenST() {Called when a slider state option has been selected} Guard() endEvent event OnSliderAcceptST(float a_value) {Called when a new slider state value has been accepted} Guard() endEvent event OnMenuOpenST() {Called when a menu state option has been selected} Guard() endEvent event OnMenuAcceptST(int a_index) {Called when a menu entry has been accepted for this state option} Guard() endEvent event OnColorOpenST() {Called when a color state option has been selected} Guard() endEvent event OnColorAcceptST(int a_color) {Called when a new color has been accepted for this state option} Guard() endEvent event OnKeyMapChangeST(int a_keyCode, string a_conflictControl, string a_conflictName) {Called when a key has been remapped for this state option} Guard() endEvent ; FUNCTIONS -------------------------------------------------------------------------- Version 1 -- int function GetVersion() {Returns version of this script. Override if necessary} Guard() endFunction string function GetCustomControl(int a_keyCode) {Returns the name of a custom control mapped to given keyCode, or "" if the key is not in use by this config. Override if necessary} Guard() endFunction function ForcePageReset() {Forces a full reset of the current page} Guard() endFunction function SetTitleText(string a_text) {Sets the title text of the control panel} Guard() endFunction function SetInfoText(string a_text) {Sets the text for the info text field below the option panel} Guard() endFunction function SetCursorPosition(int a_position) {Sets the position of the cursor used for the option setters} Guard() endFunction function SetCursorFillMode(int a_fillMode) {Sets the fill direction of the cursor used for the option setters} Guard() endFunction int function AddEmptyOption() {Adds an empty option, which can be used for padding instead of manually re-positioning the cursor} Guard() endFunction int function AddHeaderOption(string a_text, int a_flags = 0) {Adds a header option to group several options together} Guard() endFunction int function AddTextOption(string a_text, string a_value, int a_flags = 0) {Adds a generic text/value option} Guard() endFunction int function AddToggleOption(string a_text, bool a_checked, int a_flags = 0) {Adds a check box option that can be toggled on and off} Guard() endfunction int function AddSliderOption(string a_text, float a_value, string a_formatString = "{0}", int a_flags = 0) {Adds an option that opens a slider dialog when selected} Guard() endFunction int function AddMenuOption(string a_text, string a_value, int a_flags = 0) {Adds an option that opens a menu dialog when selected} Guard() endFunction int function AddColorOption(string a_text, int a_color, int a_flags = 0) {Adds an option that opens a color swatch dialog when selected} Guard() endFunction int function AddKeyMapOption(string a_text, int a_keyCode, int a_flags = 0) {Adds a key mapping option} Guard() endFunction function LoadCustomContent(string a_source, float a_x = 0.0, float a_y = 0.0) {Loads an external file into the option panel} Guard() endFunction function UnloadCustomContent() {Clears any custom content and re-enables the original option list} Guard() endFunction function SetOptionFlags(int a_option, int a_flags, bool a_noUpdate = false) {Sets the option flags} Guard() endFunction function SetTextOptionValue(int a_option, string a_value, bool a_noUpdate = false) {Sets the value(s) of an existing option} Guard() endFunction function SetToggleOptionValue(int a_option, bool a_checked, bool a_noUpdate = false) {Sets the value(s) of an existing option} Guard() endfunction function SetSliderOptionValue(int a_option, float a_value, string a_formatString = "{0}", bool a_noUpdate = false) {Sets the value(s) of an existing option} Guard() endFunction function SetMenuOptionValue(int a_option, string a_value, bool a_noUpdate = false) {Sets the value(s) of an existing option} Guard() endFunction function SetColorOptionValue(int a_option, int a_color, bool a_noUpdate = false) {Sets the value(s) of an existing option} Guard() endFunction function SetKeyMapOptionValue(int a_option, int a_keyCode, bool a_noUpdate = false) {Sets the value(s) of an existing option} Guard() endFunction function SetSliderDialogStartValue(float a_value) {Sets slider dialog parameter(s)} Guard() endFunction function SetSliderDialogDefaultValue(float a_value) {Sets slider dialog parameter(s)} Guard() endFunction function SetSliderDialogRange(float a_minValue, float a_maxValue) {Sets slider dialog parameter(s)} Guard() endFunction function SetSliderDialogInterval(float a_value) {Sets slider dialog parameter(s)} Guard() endFunction function SetMenuDialogStartIndex(int a_value) {Sets menu dialog parameter(s)} Guard() endFunction function SetMenuDialogDefaultIndex(int a_value) {Sets menu dialog parameter(s)} Guard() endFunction function SetMenuDialogOptions(string[] a_options) {Sets menu dialog parameter(s)} Guard() endFunction function SetColorDialogStartColor(int a_color) {Sets menu color parameter(s)} Guard() endFunction function SetColorDialogDefaultColor(int a_color) {Sets menu color parameter(s)} Guard() endFunction bool function ShowMessage(string a_message, bool a_withCancel = true, string a_acceptLabel = "$Accept", string a_cancelLabel = "$Cancel") {Shows a message dialog and waits until the user has closed it} Guard() endFunction ; FUNCTIONS -------------------------------------------------------------------------- Version 2 -- function AddTextOptionST(string a_stateName, string a_text, string a_value, int a_flags = 0) {Adds a generic text/value state option} Guard() endFunction function AddToggleOptionST(string a_stateName, string a_text, bool a_checked, int a_flags = 0) {Adds a check box state option that can be toggled on and off} Guard() endfunction function AddSliderOptionST(string a_stateName, string a_text, float a_value, string a_formatString = "{0}", int a_flags = 0) {Adds a state option that opens a slider dialog when selected} Guard() endFunction function AddMenuOptionST(string a_stateName, string a_text, string a_value, int a_flags = 0) {Adds a state option that opens a menu dialog when selected} Guard() endFunction function AddColorOptionST(string a_stateName, string a_text, int a_color, int a_flags = 0) {Adds a state option that opens a color swatch dialog when selected} Guard() endFunction function AddKeyMapOptionST(string a_stateName, string a_text, int a_keyCode, int a_flags = 0) {Adds a key mapping state option} Guard() endFunction function SetOptionFlagsST(int a_flags, bool a_noUpdate = false, string a_stateName = "") {Sets the state option flags} Guard() endFunction function SetTextOptionValueST(string a_value, bool a_noUpdate = false, string a_stateName = "") {Sets the value(s) of an existing state option} Guard() endFunction function SetToggleOptionValueST(bool a_checked, bool a_noUpdate = false, string a_stateName = "") {Sets the value(s) of an existing state option} Guard() endFunction function SetSliderOptionValueST(float a_value, string a_formatString = "{0}", bool a_noUpdate = false, string a_stateName = "") {Sets the value(s) of an existing state option} Guard() endFunction function SetMenuOptionValueST(string a_value, bool a_noUpdate = false, string a_stateName = "") {Sets the value(s) of an existing state option} Guard() endFunction function SetColorOptionValueST(int a_color, bool a_noUpdate = false, string a_stateName = "") {Sets the value(s) of an existing state option} Guard() endFunction function SetKeyMapOptionValueST(int a_keyCode, bool a_noUpdate = false, string a_stateName = "") {Sets the value(s) of an existing state option} Guard() endFunction ; ------------------------------------------------------------------------------------------------- function Guard() Debug.MessageBox("SKI_ConfigBase: Don't recompile this script!") endFunction ================================================ FILE: dist/Data/Scripts/Headers/SKI_QuestBase.psc ================================================ scriptname SKI_QuestBase extends Quest hidden ;################################################################################################## ; API Version: 1 ;################################################################################################## ; ; Base script for SkyUI quest scripts. ; ; This file contains the public interface of SKI_QuestBase so you're able to extend it. ; ; DO NOT MODIFY THIS SCRIPT! ; DO NOT RECOMPILE THIS SCRIPT! ; ;################################################################################################## event OnInit() endEvent ; ------------------------------------------------------------------------------------------------- ; Version Tracking ; ; Quest implements ; GetVersion, to return the static version number ; OnVersionUpdate to handle the updating ; Update process is triggered by calling CheckVersion() int property CurrentVersion auto hidden function CheckVersion() Guard() endFunction int function GetVersion() Guard() endFunction event OnVersionUpdate(int a_version) Guard() endEvent ; ------------------------------------------------------------------------------------------------- ; Reload Events ; ; Helper to add reload event to quest script. ; 1. Create quest ; 2. Add player alias to quest ; 3. Attach SKI_PlayerLoadGameAlias to player alias event OnGameReload() endEvent function Guard() Debug.MessageBox("SKI_QuestBase: Don't recompile this script!") endFunction ================================================ FILE: dist/Data/Scripts/Source/SKI_ActiveEffectsWidget.psc ================================================ scriptname SKI_ActiveEffectsWidget extends SKI_WidgetBase ; SCRIPT VERSION ---------------------------------------------------------------------------------- ; ; History ; ; 1: - Initial version ; ; 2: - Updated hudModes ; ; 3: - Added MinimumTimeLeft int function GetVersion() return 3 endFunction ; PRIVATE VARIABLES ------------------------------------------------------------------------------- ; -- Version 1 -- ; Make sure defaults match those in ConfigMenuInstance bool _enabled = false float _effectSize = 48.0 int _groupEffectCount = 8 string _orientation = "vertical" ; -- Version 3 -- int _minimumTimeLeft = 180 ; PROPERTIES -------------------------------------------------------------------------------------- bool Property Enabled {Whether the active effects are displayed or not} bool function get() return _enabled endFunction function set(bool a_val) _enabled = a_val if (Ready) UI.InvokeBool(HUD_MENU, WidgetRoot + ".setEnabled", _enabled) endIf endFunction endProperty float property EffectSize {Size of each effect icon in pixels at a resolution of 1280x720} float function get() return _effectSize endFunction function set(float a_val) _effectSize = a_val if (Ready) UI.InvokeFloat(HUD_MENU, WidgetRoot + ".setEffectSize", _effectSize) endIf endFunction endProperty int property GroupEffectCount {Maximum number of widgets displayed until a new group (column, or row) is created} int function get() return _groupEffectCount endFunction function set(int a_val) _groupEffectCount = a_val if (Ready) UI.InvokeInt(HUD_MENU, WidgetRoot + ".setGroupEffectCount", _groupEffectCount) endIf endFunction endProperty string property Orientation {The axis in which new effects will be added to after the total number of effects > GroupEffectCount} string function get() return _orientation endFunction function set(string a_val) _orientation = a_val if (Ready) UI.InvokeString(HUD_MENU, WidgetRoot + ".setOrientation", _orientation) endIf endFunction endProperty int property MinimumTimeLeft {The minimum time left for an effect to be displayed} int function get() return _minimumTimeLeft endFunction function set(int a_val) _minimumTimeLeft = a_val if (Ready) UI.InvokeInt(HUD_MENU, WidgetRoot + ".setMinTimeLeft", _minimumTimeLeft) endIf endFunction endProperty ; INITIALIZATION ---------------------------------------------------------------------------------- ; @implements SKI_QuestBase event OnVersionUpdate(int a_version) ; Version 2 if (a_version >= 2 && CurrentVersion < 2) Debug.Trace(self + ": Updating to script version 2") string[] hudModes = new string[6] hudModes[0] = "All" hudModes[1] = "StealthMode" hudModes[2] = "Favor" hudModes[3] = "Swimming" hudModes[4] = "HorseMode" hudModes[5] = "WarHorseMode" Modes = hudModes endIf endEvent ; EVENTS ------------------------------------------------------------------------------------------ ; @override SKI_WidgetBase event OnWidgetReset() parent.OnWidgetReset() ; Init numbers float[] numberArgs = new float[4] numberArgs[0] = _enabled as float numberArgs[1] = _effectSize numberArgs[2] = _groupEffectCount as float numberArgs[3] = _minimumTimeLeft as float UI.InvokeFloatA(HUD_MENU, WidgetRoot + ".initNumbers", numberArgs) ; Init strings string[] stringArgs = new string[1] stringArgs[0] = _orientation UI.InvokeStringA(HUD_MENU, WidgetRoot + ".initStrings", stringArgs) ; Init commit UI.Invoke(HUD_MENU, WidgetRoot + ".initCommit") endEvent ; FUNCTIONS --------------------------------------------------------------------------------------- ; @overrides SKI_WidgetBase string function GetWidgetSource() return "skyui/activeeffects.swf" endFunction ; @overrides SKI_WidgetBase string function GetWidgetType() return "SKI_ActiveEffectsWidget" endFunction ================================================ FILE: dist/Data/Scripts/Source/SKI_ConfigBase.psc ================================================ scriptname SKI_ConfigBase extends SKI_QuestBase ; CONSTANTS --------------------------------------------------------------------------------------- string property JOURNAL_MENU = "Journal Menu" autoReadonly string property MENU_ROOT = "_root.ConfigPanelFader.configPanel" autoReadonly int property STATE_DEFAULT = 0 autoReadonly int property STATE_RESET = 1 autoReadonly int property STATE_SLIDER = 2 autoReadonly int property STATE_MENU = 3 autoReadonly int property STATE_COLOR = 4 autoReadonly int property STATE_INPUT = 5 autoReadonly int property OPTION_TYPE_EMPTY = 0x00 autoReadonly int property OPTION_TYPE_HEADER = 0x01 autoReadonly int property OPTION_TYPE_TEXT = 0x02 autoReadonly int property OPTION_TYPE_TOGGLE = 0x03 autoReadonly int property OPTION_TYPE_SLIDER = 0x04 autoReadonly int property OPTION_TYPE_MENU = 0x05 autoReadonly int property OPTION_TYPE_COLOR = 0x06 autoReadonly int property OPTION_TYPE_KEYMAP = 0x07 autoReadonly int property OPTION_TYPE_INPUT = 0x08 autoReadonly int property OPTION_FLAG_NONE = 0x00 autoReadonly int property OPTION_FLAG_DISABLED = 0x01 autoReadonly int property OPTION_FLAG_HIDDEN = 0x02 autoReadonly int property OPTION_FLAG_WITH_UNMAP = 0x04 autoReadonly int property LEFT_TO_RIGHT = 1 autoReadonly int property TOP_TO_BOTTOM = 2 autoReadonly ; PRIVATE VARIABLES ------------------------------------------------------------------------------- SKI_ConfigManager _configManager bool _initialized = false int _configID = -1 string _currentPage = "" int _currentPageNum = 0 ; 0 for "", real pages start at 1 ; Keep track of what we're doing at the moment for stupidity checks int _state = 0 int _cursorPosition = 0 int _cursorFillMode = 1 ;LEFT_TO_RIGHT ; Local buffers int[] _optionFlagsBuf ; byte 1 type, byte 2 flags string[] _textBuf string[] _strValueBuf float[] _numValueBuf float[] _sliderParams int[] _menuParams int[] _colorParams int _activeOption = -1 string _infoText string _inputStartText bool _messageResult = false bool _waitForMessage = false string[] _stateOptionMap ; PROPERTIES -------------------------------------------------------------------------------------- string property ModName auto string[] property Pages auto string property CurrentPage string function get() return _currentPage endFunction endProperty ; INITIALIZATION ---------------------------------------------------------------------------------- event OnInit() OnGameReload() endEvent ; @implements SKI_QuestBase event OnGameReload() if (!_initialized) _initialized = true ; Buffer alloc/free on config open/close ;_optionFlagsBuf = new int[128] ;_textBuf = new string[128] ;_strValueBuf = new string[128] ;_numValueBuf = new float[128] ; 0 startValue ; 1 defaultValue ; 2 minValue ; 3 maxValue ; 4 interval _sliderParams = new float[5] ; 0 startIndex ; 1 defaultIndex _menuParams = new int[2] ; 0 currentColor ; 1 defaultColor _colorParams = new int[2] OnConfigInit() Debug.Trace(self + " INITIALIZED") endIf RegisterForModEvent("SKICP_configManagerReady", "OnConfigManagerReady") RegisterForModEvent("SKICP_configManagerReset", "OnConfigManagerReset") CheckVersion() endEvent ; EVENTS ------------------------------------------------------------------------------------------ ; @interface event OnConfigInit() {Called when this config menu is initialized} endEvent ; @interface event OnConfigRegister() {Called when this config menu registered at the control panel} endEvent ; @interface event OnConfigOpen() {Called when this config menu is opened} endEvent ; @interface event OnConfigClose() {Called when this config menu is closed} endEvent ; @interface(SKI_QuestBase) event OnVersionUpdate(int a_version) {Called when a version update of this script has been detected} endEvent ; @interface event OnPageReset(string a_page) {Called when a new page is selected, including the initial empty page} endEvent ; @interface event OnOptionHighlight(int a_option) {Called when highlighting an option} endEvent ; @interface event OnOptionSelect(int a_option) {Called when a non-interactive option has been selected} endEvent ; @interface event OnOptionDefault(int a_option) {Called when resetting an option to its default value} endEvent ; @interface event OnOptionSliderOpen(int a_option) {Called when a slider option has been selected} endEvent ; @interface event OnOptionSliderAccept(int a_option, float a_value) {Called when a new slider value has been accepted} endEvent ; @interface event OnOptionMenuOpen(int a_option) {Called when a menu option has been selected} endEvent ; @interface event OnOptionMenuAccept(int a_option, int a_index) {Called when a menu entry has been accepted} endEvent ; @interface event OnOptionColorOpen(int a_option) {Called when a color option has been selected} endEvent ; @interface event OnOptionColorAccept(int a_option, int a_color) {Called when a new color has been accepted} endEvent ; @interface event OnOptionKeyMapChange(int a_option, int a_keyCode, string a_conflictControl, string a_conflictName) {Called when a key has been remapped} endEvent ; @interface event OnHighlightST() {Called when highlighting a state option} endEvent ; @interface event OnSelectST() {Called when a non-interactive state option has been selected} endEvent ; @interface event OnDefaultST() {Called when resetting a state option to its default value} endEvent ; @interface event OnSliderOpenST() {Called when a slider state option has been selected} endEvent ; @interface event OnSliderAcceptST(float a_value) {Called when a new slider state value has been accepted} endEvent ; @interface event OnMenuOpenST() {Called when a menu state option has been selected} endEvent ; @interface event OnMenuAcceptST(int a_index) {Called when a menu entry has been accepted for this state option} endEvent ; @interface event OnColorOpenST() {Called when a color state option has been selected} endEvent ; @interface event OnColorAcceptST(int a_color) {Called when a new color has been accepted for this state option} endEvent ; @interface event OnKeyMapChangeST(int a_keyCode, string a_conflictControl, string a_conflictName) {Called when a key has been remapped for this state option} endEvent event OnConfigManagerReset(string a_eventName, string a_strArg, float a_numArg, Form a_sender) _configManager = none endEvent event OnConfigManagerReady(string a_eventName, string a_strArg, float a_numArg, Form a_sender) SKI_ConfigManager newManager = a_sender as SKI_ConfigManager ; Already registered? if (_configManager == newManager || newManager == none) return endIf _configID = newManager.RegisterMod(self, ModName) ; Success if (_configID >= 0) _configManager = newManager OnConfigRegister() Debug.Trace(self + ": Registered " + ModName + " at MCM.") endIf endEvent event OnMessageDialogClose(string a_eventName, string a_strArg, float a_numArg, Form a_sender) _messageResult = a_numArg as bool _waitForMessage = false endEvent ; FUNCTIONS --------------------------------------------------------------------------------------- ; @interface(SKI_QuestBase) int function GetVersion() {Returns version of this script} return 1 endFunction ; @interface string function GetCustomControl(int a_keyCode) {Returns the name of a custom control mapped to given keyCode, or "" if the key is not in use by this config} return "" endFunction ; @interface function ForcePageReset() {Forces a full reset of the current page} UI.Invoke(JOURNAL_MENU, MENU_ROOT + ".forcePageReset") endFunction ; @interface function SetTitleText(string a_text) UI.InvokeString(JOURNAL_MENU, MENU_ROOT + ".setTitleText", a_text) endFunction ; @interface function SetInfoText(string a_text) _infoText = a_text endFunction ; @interface function SetCursorPosition(int a_position) if (a_position < 128) _cursorPosition = a_position endIf endFunction ; @interface function SetCursorFillMode(int a_fillMode) if (a_fillMode == LEFT_TO_RIGHT || a_fillMode == TOP_TO_BOTTOM) _cursorFillMode = a_fillMode endIf endFunction ; @interface int function AddEmptyOption() return AddOption(OPTION_TYPE_EMPTY, none, none, 0, 0) endFunction ; @interface int function AddHeaderOption(string a_text, int a_flags = 0) return AddOption(OPTION_TYPE_HEADER, a_text, none, 0, a_flags) endFunction ; @interface int function AddTextOption(string a_text, string a_value, int a_flags = 0) return AddOption(OPTION_TYPE_TEXT, a_text, a_value, 0, a_flags) endFunction ; @interface int function AddToggleOption(string a_text, bool a_checked, int a_flags = 0) return AddOption(OPTION_TYPE_TOGGLE, a_text, none, a_checked as int, a_flags) endfunction ; @interface int function AddSliderOption(string a_text, float a_value, string a_formatString = "{0}", int a_flags = 0) return AddOption(OPTION_TYPE_SLIDER, a_text, a_formatString, a_value, a_flags) endFunction ; @interface int function AddMenuOption(string a_text, string a_value, int a_flags = 0) return AddOption(OPTION_TYPE_MENU, a_text, a_value, 0, a_flags) endFunction ; @interface int function AddColorOption(string a_text, int a_color, int a_flags = 0) return AddOption(OPTION_TYPE_COLOR, a_text, none, a_color, a_flags) endFunction ; @interface int function AddKeyMapOption(string a_text, int a_keyCode, int a_flags = 0) return AddOption(OPTION_TYPE_KEYMAP, a_text, none, a_keyCode, a_flags) endFunction ; @interface function AddTextOptionST(string a_stateName, string a_text, string a_value, int a_flags = 0) AddOptionST(a_stateName, OPTION_TYPE_TEXT, a_text, a_value, 0, a_flags) endFunction ; @interface function AddToggleOptionST(string a_stateName, string a_text, bool a_checked, int a_flags = 0) AddOptionST(a_stateName, OPTION_TYPE_TOGGLE, a_text, none, a_checked as int, a_flags) endfunction ; @interface function AddSliderOptionST(string a_stateName, string a_text, float a_value, string a_formatString = "{0}", int a_flags = 0) AddOptionST(a_stateName, OPTION_TYPE_SLIDER, a_text, a_formatString, a_value, a_flags) endFunction ; @interface function AddMenuOptionST(string a_stateName, string a_text, string a_value, int a_flags = 0) AddOptionST(a_stateName, OPTION_TYPE_MENU, a_text, a_value, 0, a_flags) endFunction ; @interface function AddColorOptionST(string a_stateName, string a_text, int a_color, int a_flags = 0) AddOptionST(a_stateName, OPTION_TYPE_COLOR, a_text, none, a_color, a_flags) endFunction ; @interface function AddKeyMapOptionST(string a_stateName, string a_text, int a_keyCode, int a_flags = 0) AddOptionST(a_stateName, OPTION_TYPE_KEYMAP, a_text, none, a_keyCode, a_flags) endFunction ; @interface function LoadCustomContent(string a_source, float a_x = 0.0, float a_y = 0.0) float[] params = new float[2] params[0] = a_x params[1] = a_y UI.InvokeFloatA(JOURNAL_MENU, MENU_ROOT + ".setCustomContentParams", params) UI.InvokeString(JOURNAL_MENU, MENU_ROOT + ".loadCustomContent", a_source) endFunction ; @interface function UnloadCustomContent() UI.Invoke(JOURNAL_MENU, MENU_ROOT + ".unloadCustomContent") endFunction ; @interface function SetOptionFlags(int a_option, int a_flags, bool a_noUpdate = false) if (_state == STATE_RESET) Error("Cannot set option flags while in OnPageReset(). Pass flags to AddOption instead") return endIf int index = a_option % 0x100 ; Update flags buffer int oldFlags = _optionFlagsBuf[index] as int oldFlags %= 0x100 ; Clear upper bytes, keep type oldFlags += a_flags * 0x100 ; Set new flags ; Update display int[] params = new int[2] params[0] = index params[1] = a_flags UI.InvokeIntA(JOURNAL_MENU, MENU_ROOT + ".setOptionFlags", params) if (!a_noUpdate) UI.Invoke(JOURNAL_MENU, MENU_ROOT + ".invalidateOptionData") endIf endFunction ; @interface function SetTextOptionValue(int a_option, string a_value, bool a_noUpdate = false) int index = a_option % 0x100 int type = _optionFlagsBuf[index] % 0x100 if (type != OPTION_TYPE_TEXT) int pageIdx = ((a_option / 0x100) as int) - 1 if (pageIdx != -1) Error("Option type mismatch. Expected text option, page \"" + Pages[pageIdx] + "\", index " + index) else Error("Option type mismatch. Expected text option, page \"\", index " + index) endIf return endIf SetOptionStrValue(index, a_value, a_noUpdate) endFunction ; @interface function SetToggleOptionValue(int a_option, bool a_checked, bool a_noUpdate = false) int index = a_option % 0x100 int type = _optionFlagsBuf[index] % 0x100 if (type != OPTION_TYPE_TOGGLE) int pageIdx = ((a_option / 0x100) as int) - 1 if (pageIdx != -1) Error("Option type mismatch. Expected toggle option, page \"" + Pages[pageIdx] + "\", index " + index) else Error("Option type mismatch. Expected toggle option, page \"\", index " + index) endIf return endIf SetOptionNumValue(index, a_checked as int, a_noUpdate) endfunction ; @interface function SetSliderOptionValue(int a_option, float a_value, string a_formatString = "{0}", bool a_noUpdate = false) int index = a_option % 0x100 int type = _optionFlagsBuf[index] % 0x100 if (type != OPTION_TYPE_SLIDER) int pageIdx = ((a_option / 0x100) as int) - 1 if (pageIdx != -1) Error("Option type mismatch. Expected slider option, page \"" + Pages[pageIdx] + "\", index " + index) else Error("Option type mismatch. Expected slider option, page \"\", index " + index) endIf return endIf SetOptionValues(index, a_formatString, a_value, a_noUpdate) endFunction ; @interface function SetMenuOptionValue(int a_option, string a_value, bool a_noUpdate = false) int index = a_option % 0x100 int type = _optionFlagsBuf[index] % 0x100 if (type != OPTION_TYPE_MENU) int pageIdx = ((a_option / 0x100) as int) - 1 if (pageIdx != -1) Error("Option type mismatch. Expected menu option, page \"" + Pages[pageIdx] + "\", index " + index) else Error("Option type mismatch. Expected menu option, page \"\", index " + index) endIf return endIf SetOptionStrValue(index, a_value, a_noUpdate) endFunction ; @interface function SetColorOptionValue(int a_option, int a_color, bool a_noUpdate = false) int index = a_option % 0x100 int type = _optionFlagsBuf[index] % 0x100 if (type != OPTION_TYPE_COLOR) int pageIdx = ((a_option / 0x100) as int) - 1 if (pageIdx != -1) Error("Option type mismatch. Expected color option, page \"" + Pages[pageIdx] + "\", index " + index) else Error("Option type mismatch. Expected color option, page \"\", index " + index) endIf return endIf SetOptionNumValue(index, a_color, a_noUpdate) endFunction ; @interface function SetKeyMapOptionValue(int a_option, int a_keyCode, bool a_noUpdate = false) int index = a_option % 0x100 int type = _optionFlagsBuf[index] % 0x100 if (type != OPTION_TYPE_KEYMAP) int pageIdx = ((a_option / 0x100) as int) - 1 if (pageIdx != -1) Error("Option type mismatch. Expected keymap option, page \"" + Pages[pageIdx] + "\", index " + index) else Error("Option type mismatch. Expected keymap option, page \"\", index " + index) endIf return endIf SetOptionNumValue(index, a_keyCode, a_noUpdate) endFunction ; @interface function SetOptionFlagsST(int a_flags, bool a_noUpdate = false, string a_stateName = "") if (_state == STATE_RESET) Error("Cannot set option flags while in OnPageReset(). Pass flags to AddOption instead") return endIf int index = GetStateOptionIndex(a_stateName) if (index < 0) Error("Cannot use SetOptionFlagsST outside a valid option state") return endIf SetOptionFlags(index, a_flags, a_noUpdate) endFunction ; @interface function SetTextOptionValueST(string a_value, bool a_noUpdate = false, string a_stateName = "") int index = GetStateOptionIndex(a_stateName) if (index < 0) Error("Cannot use SetTextOptionValueST outside a valid option state") return endIf SetTextOptionValue(index, a_value, a_noUpdate) endFunction ; @interface function SetToggleOptionValueST(bool a_checked, bool a_noUpdate = false, string a_stateName = "") int index = GetStateOptionIndex(a_stateName) if (index < 0) Error("Cannot use SetToggleOptionValueST outside a valid option state") return endIf SetToggleOptionValue(index, a_checked, a_noUpdate) endFunction ; @interface function SetSliderOptionValueST(float a_value, string a_formatString = "{0}", bool a_noUpdate = false, string a_stateName = "") int index = GetStateOptionIndex(a_stateName) if (index < 0) Error("Cannot use SetSliderOptionValueST outside a valid option state") return endIf SetSliderOptionValue(index, a_value, a_formatString, a_noUpdate) endFunction ; @interface function SetMenuOptionValueST(string a_value, bool a_noUpdate = false, string a_stateName = "") int index = GetStateOptionIndex(a_stateName) if (index < 0) Error("Cannot use SetMenuOptionValueST outside a valid option state") return endIf SetMenuOptionValue(index, a_value, a_noUpdate) endFunction ; @interface function SetColorOptionValueST(int a_color, bool a_noUpdate = false, string a_stateName = "") int index = GetStateOptionIndex(a_stateName) if (index < 0) Error("Cannot use SetColorOptionValueST outside a valid option state") return endIf SetColorOptionValue(index, a_color, a_noUpdate) endFunction ; @interface function SetKeyMapOptionValueST(int a_keyCode, bool a_noUpdate = false, string a_stateName = "") int index = GetStateOptionIndex(a_stateName) if (index < 0) Error("Cannot use SetKeyMapOptionValueST outside a valid option state") return endIf SetKeyMapOptionValue(index, a_keyCode, a_noUpdate) endFunction ; @interface function SetSliderDialogStartValue(float a_value) if (_state != STATE_SLIDER) Error("Cannot set slider dialog params while outside OnOptionSliderOpen()") return endIf _sliderParams[0] = a_value endFunction ; @interface function SetSliderDialogDefaultValue(float a_value) if (_state != STATE_SLIDER) Error("Cannot set slider dialog params while outside OnOptionSliderOpen()") return endIf _sliderParams[1] = a_value endFunction ; @interface function SetSliderDialogRange(float a_minValue, float a_maxValue) if (_state != STATE_SLIDER) Error("Cannot set slider dialog params while outside OnOptionSliderOpen()") return endIf _sliderParams[2] = a_minValue _sliderParams[3] = a_maxValue endFunction ; @interface function SetSliderDialogInterval(float a_value) if (_state != STATE_SLIDER) Error("Cannot set slider dialog params while outside OnOptionSliderOpen()") return endIf _sliderParams[4] = a_value endFunction ; @interface function SetMenuDialogStartIndex(int a_value) if (_state != STATE_MENU) Error("Cannot set menu dialog params while outside OnOptionMenuOpen()") return endIf _menuParams[0] = a_value endFunction ; @interface function SetMenuDialogDefaultIndex(int a_value) if (_state != STATE_MENU) Error("Cannot set menu dialog params while outside OnOptionMenuOpen()") return endIf _menuParams[1] = a_value endFunction ; @interface function SetMenuDialogOptions(string[] a_options) if (_state != STATE_MENU) Error("Cannot set menu dialog params while outside OnOptionMenuOpen()") return endIf UI.InvokeStringA(JOURNAL_MENU, MENU_ROOT + ".setMenuDialogOptions", a_options) endFunction ; @interface function SetColorDialogStartColor(int a_color) if (_state != STATE_COLOR) Error("Cannot set color dialog params while outside OnOptionColorOpen()") return endIf _colorParams[0] = a_color endFunction ; @interface function SetColorDialogDefaultColor(int a_color) if (_state != STATE_COLOR) Error("Cannot set color dialog params while outside OnOptionColorOpen()") return endIf _colorParams[1] = a_color endFunction ; @interface bool function ShowMessage(string a_message, bool a_withCancel = true, string a_acceptLabel = "$Accept", string a_cancelLabel = "$Cancel") if (_waitForMessage) Error("Called ShowMessage() while another message was already open") return false endIf _waitForMessage = true _messageResult = false string[] params = new string[3] params[0] = a_message params[1] = a_acceptLabel if (a_withCancel) params[2] = a_cancelLabel else params[2] = "" endIf RegisterForModEvent("SKICP_messageDialogClosed", "OnMessageDialogClose") UI.InvokeStringA(JOURNAL_MENU, MENU_ROOT + ".showMessageDialog", params) ; Wait for result while (_waitForMessage) Utility.WaitMenuMode(0.1) endWhile UnregisterForModEvent("SKICP_messageDialogClosed") return _messageResult endFunction function Error(string a_msg) Debug.Trace(self + " ERROR: " + a_msg) endFunction function OpenConfig() ; Alloc _optionFlagsBuf = new int[128] _textBuf = new string[128] _strValueBuf = new string[128] _numValueBuf = new float[128] _stateOptionMap = new string[128] SetPage("", -1) OnConfigOpen() UI.InvokeStringA(JOURNAL_MENU, MENU_ROOT + ".setPageNames", Pages) endFunction function CloseConfig() OnConfigClose() ClearOptionBuffers() _waitForMessage = false ; Free _optionFlagsBuf = new int[1] _textBuf = new string[1] _strValueBuf = new string[1] _numValueBuf = new float[1] _stateOptionMap = new string[1] endFunction function SetPage(string a_page, int a_index) _currentPage = a_page _currentPageNum = 1+a_index ; Set default title, can be overridden in OnPageReset if (a_page != "") SetTitleText(a_page) else SetTitleText(ModName) endIf ClearOptionBuffers() _state = STATE_RESET OnPageReset(a_page) _state = STATE_DEFAULT WriteOptionBuffers() endFunction int function AddOption(int a_optionType, string a_text, string a_strValue, float a_numValue, int a_flags) if (_state != STATE_RESET) Error("Cannot add option " + a_text + " outside of OnPageReset()") return -1 endIf int pos = _cursorPosition if (pos == -1) return -1 ; invalid endIf _optionFlagsBuf[pos] = a_optionType + a_flags * 0x100 _textBuf[pos] = a_text _strValueBuf[pos] = a_strValue _numValueBuf[pos] = a_numValue ; Just use numerical value of fill mode _cursorPosition += _cursorFillMode if (_cursorPosition >= 128) _cursorPosition = -1 endIf ; byte 1 - position ; byte 2 - page return pos + _currentPageNum * 0x100 endFunction function AddOptionST(string a_stateName, int a_optionType, string a_text, string a_strValue, float a_numValue, int a_flags) if (_stateOptionMap.find(a_stateName) != -1) Error("State option name " + a_stateName + " is already in use") return endIf int index = AddOption(a_optionType, a_text, a_strValue, a_numValue, a_flags) % 0x100 if (index < 0) return endIf if (_stateOptionMap[index] != "") Error("State option index " + index + " already in use") return endIf _stateOptionMap[index] = a_stateName endFunction int function GetStateOptionIndex(string a_stateName) if (a_stateName == "") a_stateName = GetState() endIf if (a_stateName == "") return -1 endIf return _stateOptionMap.find(a_stateName) endFunction function WriteOptionBuffers() string menu = JOURNAL_MENU string root = MENU_ROOT int t = OPTION_TYPE_EMPTY int i = 0 int optionCount = 0; ; Tell UI where to cut off the buffer i = 0 while (i < 128) if (_optionFlagsBuf[i] != t) optionCount = i + 1 endif i += 1 endWhile UI.InvokeIntA(menu, root + ".setOptionFlagsBuffer", _optionFlagsBuf) UI.InvokeStringA(menu, root + ".setOptionTextBuffer", _textBuf) UI.InvokeStringA(menu, root + ".setOptionStrValueBuffer", _strValueBuf) UI.InvokeFloatA(menu, root + ".setOptionNumValueBuffer", _numValueBuf) UI.InvokeInt(menu, root + ".flushOptionBuffers", optionCount) endFunction function ClearOptionBuffers() int t = OPTION_TYPE_EMPTY int i = 0 while (i < 128) _optionFlagsBuf[i] = t _textBuf[i] = "" _strValueBuf[i] = "" _numValueBuf[i] = 0 ; Also clear state map as it's tied to the buffers _stateOptionMap[i] = "" i += 1 endWhile _cursorPosition = 0 _cursorFillMode = LEFT_TO_RIGHT endFunction function SetOptionStrValue(int a_index, string a_strValue, bool a_noUpdate) if (_state == STATE_RESET) Error("Cannot modify option data while in OnPageReset()") return endIf string menu = JOURNAL_MENU string root = MENU_ROOT UI.SetInt(menu, root + ".optionCursorIndex", a_index) UI.SetString(menu, root + ".optionCursor.strValue", a_strValue) if (!a_noUpdate) UI.Invoke(menu, root + ".invalidateOptionData") endIf endFunction function SetOptionNumValue(int a_index, float a_numValue, bool a_noUpdate) if (_state == STATE_RESET) Error("Cannot modify option data while in OnPageReset()") return endIf string menu = JOURNAL_MENU string root = MENU_ROOT UI.SetInt(menu, root + ".optionCursorIndex", a_index) UI.SetFloat(menu, root + ".optionCursor.numValue", a_numValue) if (!a_noUpdate) UI.Invoke(menu, root + ".invalidateOptionData") endIf endFunction function SetOptionValues(int a_index, string a_strValue, float a_numValue, bool a_noUpdate) if (_state == STATE_RESET) Error("Cannot modify option data while in OnPageReset()") return endIf string menu = JOURNAL_MENU string root = MENU_ROOT UI.SetInt(menu, root + ".optionCursorIndex", a_index) UI.SetString(menu, root + ".optionCursor.strValue", a_strValue) UI.SetFloat(menu, root + ".optionCursor.numValue", a_numValue) if (!a_noUpdate) UI.Invoke(menu, root + ".invalidateOptionData") endIf endFunction function RequestSliderDialogData(int a_index) _activeOption = a_index + _currentPageNum * 0x100 ; Defaults _sliderParams[0] = 0 _sliderParams[1] = 0 _sliderParams[2] = 0 _sliderParams[3] = 1 _sliderParams[4] = 1 _state = STATE_SLIDER string optionState = _stateOptionMap[a_index] if (optionState != "") string oldState = GetState() gotoState(optionState) OnSliderOpenST() gotoState(oldState) else OnOptionSliderOpen(_activeOption) endIf _state = STATE_DEFAULT UI.InvokeFloatA(JOURNAL_MENU, MENU_ROOT + ".setSliderDialogParams", _sliderParams) endFunction function RequestMenuDialogData(int a_index) _activeOption = a_index + _currentPageNum * 0x100 ; Defaults _menuParams[0] = -1 _menuParams[1] = -1 _state = STATE_MENU string optionState = _stateOptionMap[a_index] if (optionState != "") string oldState = GetState() gotoState(optionState) OnMenuOpenST() gotoState(oldState) else OnOptionMenuOpen(_activeOption) endIf _state = STATE_DEFAULT UI.InvokeIntA(JOURNAL_MENU, MENU_ROOT + ".setMenuDialogParams", _menuParams) endFunction function RequestColorDialogData(int a_index) _activeOption = a_index + _currentPageNum * 0x100 ; Defaults _colorParams[0] = -1 _colorParams[1] = -1 _state = STATE_COLOR string optionState = _stateOptionMap[a_index] if (optionState != "") string oldState = GetState() gotoState(optionState) OnColorOpenST() gotoState(oldState) else OnOptionColorOpen(_activeOption) endIf _state = STATE_DEFAULT UI.InvokeIntA(JOURNAL_MENU, MENU_ROOT + ".setColorDialogParams", _colorParams) endFunction function SetSliderValue(float a_value) string optionState = _stateOptionMap[_activeOption % 0x100] if (optionState != "") string oldState = GetState() gotoState(optionState) OnSliderAcceptST(a_value) gotoState(oldState) else OnOptionSliderAccept(_activeOption, a_value) endIf _activeOption = -1 endFunction function SetMenuIndex(int a_index) string optionState = _stateOptionMap[_activeOption % 0x100] if (optionState != "") string oldState = GetState() gotoState(optionState) OnMenuAcceptST(a_index) gotoState(oldState) else OnOptionMenuAccept(_activeOption, a_index) endIf _activeOption = -1 endFunction function SetColorValue(int a_color) string optionState = _stateOptionMap[_activeOption % 0x100] if (optionState != "") string oldState = GetState() gotoState(optionState) OnColorAcceptST(a_color) gotoState(oldState) else OnOptionColorAccept(_activeOption, a_color) endIf _activeOption = -1 endFunction function SelectOption(int a_index) string optionState = _stateOptionMap[a_index] if (optionState != "") string oldState = GetState() gotoState(optionState) OnSelectST() gotoState(oldState) else int option = a_index + _currentPageNum * 0x100 OnOptionSelect(option) endIf endFunction function ResetOption(int a_index) string optionState = _stateOptionMap[a_index] if (optionState != "") string oldState = GetState() gotoState(optionState) OnDefaultST() gotoState(oldState) else int option = a_index + _currentPageNum * 0x100 OnOptionDefault(option) endIf endFunction function HighlightOption(int a_index) _infoText = "" if (a_index != -1) string optionState = _stateOptionMap[a_index] if (optionState != "") string oldState = GetState() gotoState(optionState) OnHighlightST() gotoState(oldState) else int option = a_index + _currentPageNum * 0x100 OnOptionHighlight(option) endIf endIf UI.InvokeString(JOURNAL_MENU, MENU_ROOT + ".setInfoText", _infoText) endFunction function RemapKey(int a_index, int a_keyCode, string a_conflictControl, string a_conflictName) string optionState = _stateOptionMap[a_index] if (optionState != "") string oldState = GetState() gotoState(optionState) OnKeyMapChangeST(a_keyCode, a_conflictControl, a_conflictName) gotoState(oldState) else int option = a_index + _currentPageNum * 0x100 OnOptionKeyMapChange(option, a_keyCode, a_conflictControl, a_conflictName) endIf endFunction function OnOptionInputOpen(Int a_option) {Called when a text input option has been selected} endFunction function OnInputOpenST() {Called when a text input state option has been selected} endFunction function OnOptionInputAccept(Int a_option, String a_input) {Called when a new text input has been accepted} endFunction function OnInputAcceptST(String a_input) {Called when a new text input has been accepted for this state option} endFunction function SetInputOptionValue(Int a_option, String a_value, Bool a_noUpdate) Int index = a_option % 256 Int type = _optionFlagsBuf[index] % 256 if type != self.OPTION_TYPE_INPUT Int pageIdx = a_option / 256 - 1 if pageIdx != -1 self.Error("Option type mismatch. Expected input option, page \"" + Pages[pageIdx] + "\", index " + index as String) else self.Error("Option type mismatch. Expected input option, page \"\", index " + index as String) endIf return endIf self.SetOptionStrValue(index, a_value, a_noUpdate) endFunction function SetInputOptionValueST(String a_value, Bool a_noUpdate, String a_stateName) Int index = self.GetStateOptionIndex(a_stateName) if index < 0 self.Error("Cannot use SetInputOptionValueST outside a valid option state") return endIf self.SetInputOptionValue(index, a_value, a_noUpdate) endFunction function RequestInputDialogData(Int a_index) _activeOption = a_index + _currentPageNum * 256 _inputStartText = "" _state = self.STATE_INPUT String optionState = _stateOptionMap[a_index] if optionState != "" String oldState = self.GetState() self.GotoState(optionState) self.OnInputOpenST() self.GotoState(oldState) else self.OnOptionInputOpen(_activeOption) endIf _state = self.STATE_DEFAULT ui.InvokeString(self.JOURNAL_MENU, self.MENU_ROOT + ".setInputDialogParams", _inputStartText) endFunction Int function AddInputOption(String a_text, String a_value, Int a_flags) return self.AddOption(self.OPTION_TYPE_INPUT, a_text, a_value, 0 as Float, a_flags) endFunction function AddInputOptionST(String a_stateName, String a_text, String a_value, Int a_flags) self.AddOptionST(a_stateName, self.OPTION_TYPE_INPUT, a_text, a_value, 0 as Float, a_flags) endFunction function SetInputDialogStartText(String a_text) if _state != self.STATE_INPUT self.Error("Cannot set input dialog params while outside OnOptionInputOpen()") return endIf _inputStartText = a_text endFunction function SetInputText(String a_text) String optionState = _stateOptionMap[_activeOption % 256] if optionState != "" String oldState = self.GetState() self.GotoState(optionState) self.OnInputAcceptST(a_text) self.GotoState(oldState) else self.OnOptionInputAccept(_activeOption, a_text) endIf _activeOption = -1 endFunction ================================================ FILE: dist/Data/Scripts/Source/SKI_ConfigManager.psc ================================================ scriptname SKI_ConfigManager extends SKI_QuestBase hidden ; SCRIPT VERSION ---------------------------------------------------------------------------------- ; ; History ; ; 1: - Initial version ; ; 2: - Added lock for API functions ; ; 3: - Removed lock again until I have time to test it properly ; ; 4: - Added redundancy for registration process int function GetVersion() return 4 endFunction ; CONSTANTS --------------------------------------------------------------------------------------- string property JOURNAL_MENU = "Journal Menu" autoReadonly string property MENU_ROOT = "_root.ConfigPanelFader.configPanel" autoReadonly ; PRIVATE VARIABLES ------------------------------------------------------------------------------- ; -- Version 1 -- SKI_ConfigBase[] _modConfigs string[] _modNames int _curConfigID = 0 int _configCount = 0 SKI_ConfigBase _activeConfig ; -- Version 2 -- ; keep those for now bool _lockInit = false bool _locked = false ; -- Version 4 -- bool _cleanupFlag = false int _addCounter = 0 int _updateCounter = 0 ; INITIALIZATION ---------------------------------------------------------------------------------- event OnInit() _modConfigs = new SKI_ConfigBase[128] _modNames = new string[128] OnGameReload() endEvent ; @implements SKI_QuestBase event OnGameReload() RegisterForModEvent("SKICP_modSelected", "OnModSelect") RegisterForModEvent("SKICP_pageSelected", "OnPageSelect") RegisterForModEvent("SKICP_optionHighlighted", "OnOptionHighlight") RegisterForModEvent("SKICP_optionSelected", "OnOptionSelect") RegisterForModEvent("SKICP_optionDefaulted", "OnOptionDefault") RegisterForModEvent("SKICP_keymapChanged", "OnKeymapChange") RegisterForModEvent("SKICP_sliderSelected", "OnSliderSelect") RegisterForModEvent("SKICP_sliderAccepted", "OnSliderAccept") RegisterForModEvent("SKICP_menuSelected", "OnMenuSelect") RegisterForModEvent("SKICP_menuAccepted", "OnMenuAccept") RegisterForModEvent("SKICP_colorSelected", "OnColorSelect") RegisterForModEvent("SKICP_colorAccepted", "OnColorAccept") self.RegisterForModEvent("SKICP_inputSelected", "OnInputSelect") self.RegisterForModEvent("SKICP_inputAccepted", "OnInputAccept") RegisterForModEvent("SKICP_dialogCanceled", "OnDialogCancel") RegisterForMenu(JOURNAL_MENU) ; no longer used but better safe than sorry _lockInit = true _cleanupFlag = true CleanUp() SendModEvent("SKICP_configManagerReady") _updateCounter = 0 RegisterForSingleUpdate(5) endEvent ; EVENTS ------------------------------------------------------------------------------------------ event OnUpdate() if (_cleanupFlag) CleanUp() endIf if (_addCounter > 0) Debug.Notification("MCM: Registered " + _addCounter + " new menu(s).") _addCounter = 0 endIf SendModEvent("SKICP_configManagerReady") if (_updateCounter < 6) _updateCounter += 1 RegisterForSingleUpdate(5) else RegisterForSingleUpdate(30) endIf endEvent event OnMenuOpen(string a_menuName) GotoState("BUSY") _activeConfig = none UI.InvokeStringA(JOURNAL_MENU, MENU_ROOT + ".setModNames", _modNames); endEvent event OnMenuClose(string a_menuName) GotoState("") if (_activeConfig) _activeConfig.CloseConfig() endIf _activeConfig = none endEvent event OnModSelect(string a_eventName, string a_strArg, float a_numArg, Form a_sender) int configIndex = a_numArg as int if (configIndex > -1) ; We can clean the buffers of the previous menu now if (_activeConfig) _activeConfig.CloseConfig() endIf _activeConfig = _modConfigs[configIndex] _activeConfig.OpenConfig() endIf UI.InvokeBool(JOURNAL_MENU, MENU_ROOT + ".unlock", true) endEvent event OnPageSelect(string a_eventName, string a_strArg, float a_numArg, Form a_sender) string page = a_strArg int index = a_numArg as int _activeConfig.SetPage(page, index) UI.InvokeBool(JOURNAL_MENU, MENU_ROOT + ".unlock", true) endEvent event OnOptionHighlight(string a_eventName, string a_strArg, float a_numArg, Form a_sender) int optionIndex = a_numArg as int _activeConfig.HighlightOption(optionIndex) endEvent event OnOptionSelect(string a_eventName, string a_strArg, float a_numArg, Form a_sender) int optionIndex = a_numArg as int _activeConfig.SelectOption(optionIndex) UI.InvokeBool(JOURNAL_MENU, MENU_ROOT + ".unlock", true) endEvent event OnOptionDefault(string a_eventName, string a_strArg, float a_numArg, Form a_sender) int optionIndex = a_numArg as int _activeConfig.ResetOption(optionIndex) UI.InvokeBool(JOURNAL_MENU, MENU_ROOT + ".unlock", true) endEvent event OnKeymapChange(string a_eventName, string a_strArg, float a_numArg, Form a_sender) int optionIndex = a_numArg as int int keyCode = UI.GetInt(JOURNAL_MENU, MENU_ROOT + ".selectedKeyCode") ; First test vanilla controls string conflictControl = Input.GetMappedControl(keyCode) string conflictName = "" ; Then test mod controls int i = 0 while (conflictControl == "" && i < _modConfigs.length) if (_modConfigs[i] != none) conflictControl = _modConfigs[i].GetCustomControl(keyCode) if (conflictControl != "") conflictName = _modNames[i] endIf endIf i += 1 endWhile _activeConfig.RemapKey(optionIndex, keyCode, conflictControl, conflictName) UI.InvokeBool(JOURNAL_MENU, MENU_ROOT + ".unlock", true) endEvent event OnSliderSelect(string a_eventName, string a_strArg, float a_numArg, Form a_sender) int optionIndex = a_numArg as int _activeConfig.RequestSliderDialogData(optionIndex) endEvent event OnSliderAccept(string a_eventName, string a_strArg, float a_numArg, Form a_sender) float value = a_numArg _activeConfig.SetSliderValue(value) UI.InvokeBool(JOURNAL_MENU, MENU_ROOT + ".unlock", true) endEvent event OnMenuSelect(string a_eventName, string a_strArg, float a_numArg, Form a_sender) int optionIndex = a_numArg as int _activeConfig.RequestMenuDialogData(optionIndex) endEvent event OnMenuAccept(string a_eventName, string a_strArg, float a_numArg, Form a_sender) int value = a_numArg as int _activeConfig.SetMenuIndex(value) UI.InvokeBool(JOURNAL_MENU, MENU_ROOT + ".unlock", true) endEvent event OnColorSelect(string a_eventName, string a_strArg, float a_numArg, Form a_sender) int optionIndex = a_numArg as int _activeConfig.RequestColorDialogData(optionIndex) endEvent event OnColorAccept(string a_eventName, string a_strArg, float a_numArg, Form a_sender) int color = a_numArg as int _activeConfig.SetColorValue(color) UI.InvokeBool(JOURNAL_MENU, MENU_ROOT + ".unlock", true) endEvent event OnDialogCancel(string a_eventName, string a_strArg, float a_numArg, Form a_sender) UI.InvokeBool(JOURNAL_MENU, MENU_ROOT + ".unlock", true) endEvent ; FUNCTIONS --------------------------------------------------------------------------------------- ; @interface int function RegisterMod(SKI_ConfigBase a_menu, string a_modName) GotoState("BUSY") ;Log("Registering config menu: " + a_menu + "(" + a_modName + ")") if (_configCount >= 128) GotoState("") return -1 endIf ; Already registered? int i = 0 while (i < _modConfigs.length) if (_modConfigs[i] == a_menu) GotoState("") return i endIf i += 1 endWhile ; New registration int configID = NextID() if (configID == -1) GotoState("") return -1 endIf _modConfigs[configID] = a_menu _modNames[configID] = a_modName _configCount += 1 ; Track mods added in the current cycle so we don't have to display one message per mod _addCounter += 1 GotoState("") return configID endFunction ; @interface int function UnregisterMod(SKI_ConfigBase a_menu) GotoState("BUSY") ;Log("Unregistering config menu: " + a_menu) int i = 0 while (i < _modConfigs.length) if (_modConfigs[i] == a_menu) _modConfigs[i] = none _modNames[i] = "" _configCount -= 1 GotoState("") return i endIf i += 1 endWhile GotoState("") return -1 endFunction ; @interface function ForceReset() Log("Forcing config manager reset...") SendModEvent("SKICP_configManagerReset") GotoState("BUSY") int i = 0 while (i < _modConfigs.length) _modConfigs[i] = none _modNames[i] = "" i += 1 endWhile _curConfigID = 0 _configCount = 0 GotoState("") SendModEvent("SKICP_configManagerReady") endFunction function CleanUp() GotoState("BUSY") _cleanupFlag = false _configCount = 0 int i = 0 while (i < _modConfigs.length) if (_modConfigs[i] == none || _modConfigs[i].GetFormID() == 0) _modConfigs[i] = none _modNames[i] = "" else _configCount += 1 endIf i += 1 endWhile GotoState("") endFunction int function NextID() int startIdx = _curConfigID while (_modConfigs[_curConfigID] != none) _curConfigID += 1 if (_curConfigID >= 128) _curConfigID = 0 endIf if (_curConfigID == startIdx) return -1 ; Just to be sure. endIf endWhile return _curConfigID endFunction function Log(string a_msg) Debug.Trace(self + ": " + a_msg) endFunction function OnInputSelect(String a_eventName, String a_strArg, Float a_numArg, Form a_sender) Int optionIndex = a_numArg as Int _activeConfig.RequestInputDialogData(optionIndex) endFunction function OnInputAccept(String a_eventName, String a_strArg, Float a_numArg, Form a_sender) _activeConfig.SetInputText(a_strArg) ui.InvokeBool(self.JOURNAL_MENU, self.MENU_ROOT + ".unlock", true) endFunction ; STATES --------------------------------------------------------------------------------------- state BUSY int function RegisterMod(SKI_ConfigBase a_menu, string a_modName) return -2 endFunction int function UnregisterMod(SKI_ConfigBase a_menu) return -2 endFunction function ForceReset() endFunction function CleanUp() endFunction endState ================================================ FILE: dist/Data/Scripts/Source/SKI_ConfigMenu.psc ================================================ scriptname SKI_ConfigMenu extends SKI_ConfigBase ; SCRIPT VERSION ---------------------------------------------------------------------------------- ; ; History ; ; 1: - Initial version ; ; 2: - Added category icon theme option ; - Added noIconColor option ; - Added controls section for gamepad ; ; 3: - Added disable 3D item positioning option ; ; 4: - Converted script to use state options ; - Added map menu version check ; - Added active effects widget configuration ; ; 5: - Fixed 3DItemDisablePositioning ; ; 6: - Added favorites menu options ; ; 7: - Changed page layout ; ; 8: - Removed unsupported icon themes int function GetVersion() return 9 endFunction ; PRIVATE VARIABLES ------------------------------------------------------------------------------- ; -- Version 1 -- ; Lists string[] _alignments string[] _alignmentValues string[] _sizes ; State int _itemlistFontSizeIdx = 1 int _itemlistQuantityMinCount = 6 int _itemcardAlignIdx = 2 float _itemcardXOffset = 0.0 float _itemcardYOffset = 0.0 float _3DItemXOffset = 0.0 float _3DItemYOffset = 0.0 float _3DItemScale = 1.5 int _searchKey = 57 int _switchTabKey = 56 int _equipModeKey = 42 ; Internal float _itemXBase float _itemXBaseW ; -- Version 2 -- ; Lists string[] _categoryIconThemeShortNames string[] _categoryIconThemeLongNames string[] _categoryIconThemeValues ; State int _categoryIconThemeIdx = 0 bool _itemlistNoIconColors = false int _switchTabButton = 271 ; BACK int _prevColumnButton = 274 ; LEFT_SHOULDER int _nextColumnButton = 275 ; RIGHT_SHOULDER int _sortOrderButton = 272 ; LEFT_THUMB ; -- Version 3 -- ; State bool _3DItemDisablePositioning = false ; Internal float _fInventory3DItemPosXWide float _fInventory3DItemPosX float _fMagic3DItemPosXWide float _fMagic3DItemPosX ; Flags int _3DItemFlags ; -- Version 4 -- ; Lists string[] _orientations string[] _orientationValues string[] _vertAlignments string[] _vertAlignmentValues float[] _effectWidgetIconSizeValues float[] _alignmentBaseOffsets float[] _vertAlignmentBaseOffsets ; State int _effectWidgetIconSizeIdx = 1 ; medium int _effectWidgetVAnchorIdx = 0 ; top int _effectWidgetHAnchorIdx = 1 ; right int _effectWidgetGroupCount = 8 int _effectWidgetOrientationIdx = 1 ; vertical float _effectWidgetXOffset = 0.0 float _effectWidgetYOffset = 0.0 ; Flags int _effectWidgetFlags ; -- Version 5 -- ; Internal float _fInventory3DItemPosZWide float _fInventory3DItemPosZ float _fMagic3DItemPosZWide float _fMagic3DItemPosZ float _fInventory3DItemPosScaleWide float _fMagic3DItemPosScaleWide float _fInventory3DItemPosScale float _fMagic3DItemPosScale ; -- Version 6 -- ; Lists string[] _favGroupNames ; State int _favCurGroupIdx = 0 ; PROPERTIES -------------------------------------------------------------------------------------- ; -- Version 1 -- SKI_SettingsManager property SKI_SettingsManagerInstance auto SKI_Main property SKI_MainInstance auto ; -- Version 4 -- SKI_ActiveEffectsWidget property SKI_ActiveEffectsWidgetInstance auto ; -- Version 6 -- SKI_FavoritesManager property SKI_FavoritesManagerInstance auto ; INITIALIZATION ---------------------------------------------------------------------------------- ; @overrides SKI_ConfigBase event OnConfigInit() ; Translate strings to display in UI _alignments = new string[3] _alignments[0] = "$Left" _alignments[1] = "$Right" _alignments[2] = "$Center" _sizes = new string[3] _sizes[0] = "$Small" _sizes[1] = "$Medium" _sizes[2] = "$Large" ; Strings used as variable values _alignmentValues = new string[3] _alignmentValues[0] = "left" _alignmentValues[1] = "right" _alignmentValues[2] = "center" ApplySettings() endEvent ; @implements SKI_QuestBase event OnGameReload() parent.OnGameReload() ApplySettings() endEvent ; @implements SKI_QuestBase event OnVersionUpdate(int a_version) ; Version 2 if (a_version >= 2 && CurrentVersion < 2) Debug.Trace(self + ": Updating to script version 2") _categoryIconThemeShortNames = new string[4] _categoryIconThemeShortNames[0] = "SKYUI V3" _categoryIconThemeShortNames[1] = "CELTIC" _categoryIconThemeShortNames[2] = "CURVED" _categoryIconThemeShortNames[3] = "STRAIGHT" _categoryIconThemeLongNames = new string[4] _categoryIconThemeLongNames[0] = "SkyUI V3, by PsychoSteve" _categoryIconThemeLongNames[1] = "Celtic, by GreatClone" _categoryIconThemeLongNames[2] = "Curved, by T3T" _categoryIconThemeLongNames[3] = "Straight, by T3T" _categoryIconThemeValues = new string[4] _categoryIconThemeValues[0] = "skyui\\icons_category_psychosteve.swf" _categoryIconThemeValues[1] = "skyui\\icons_category_celtic.swf" _categoryIconThemeValues[2] = "skyui\\icons_category_curved.swf" _categoryIconThemeValues[3] = "skyui\\icons_category_straight.swf" ; Have been renamed, so clear old overrides and set new ones SKI_SettingsManagerInstance.ClearOverride("Input$controls$search") SKI_SettingsManagerInstance.ClearOverride("Input$controls$switchTab") SKI_SettingsManagerInstance.ClearOverride("Input$controls$equipMode") SKI_SettingsManagerInstance.SetOverride("Input$controls$pc$search", _searchKey) SKI_SettingsManagerInstance.SetOverride("Input$controls$pc$switchTab", _switchTabKey) SKI_SettingsManagerInstance.SetOverride("Input$controls$pc$equipMode", _equipModeKey) endIf if (a_version >= 3 && CurrentVersion < 3) Debug.Trace(self + ": Updating to script version 3") _3DItemFlags = OPTION_FLAG_NONE ;The below all reset to true with version 3.2 ;SKI_MainInstance.InventoryMenuCheckEnabled ;SKI_MainInstance.MagicMenuCheckEnabled ;SKI_MainInstance.BarterMenuCheckEnabled ;SKI_MainInstance.ContainerMenuCheckEnabled ;SKI_MainInstance.GiftMenuCheckEnabled endIf if (a_version >= 4 && CurrentVersion < 4) Debug.Trace(self + ": Updating to script version 4") _orientations = new string[2] _orientations[0] = "$Horizontal" _orientations[1] = "$Vertical" _orientationValues = new string[2] _orientationValues[0] = "horizontal" _orientationValues[1] = "vertical" _vertAlignments = new string[3] _vertAlignments[0] = "$Top" _vertAlignments[1] = "$Bottom" _vertAlignments[2] = "$Center" _vertAlignmentValues = new string[3] _vertAlignmentValues[0] = "top" _vertAlignmentValues[1] = "bottom" _vertAlignmentValues[2] = "center" _effectWidgetIconSizeValues = new float[3] _effectWidgetIconSizeValues[0] = 32.0 _effectWidgetIconSizeValues[1] = 48.0 _effectWidgetIconSizeValues[2] = 64.0 _alignmentBaseOffsets = new float[3] _alignmentBaseOffsets[0] = 0.0 _alignmentBaseOffsets[1] = 1280.0 _alignmentBaseOffsets[2] = 640.0 _vertAlignmentBaseOffsets = new float[3] _vertAlignmentBaseOffsets[0] = 0.0 _vertAlignmentBaseOffsets[1] = 720.0 _vertAlignmentBaseOffsets[2] = 360.0 _effectWidgetFlags = OPTION_FLAG_NONE ; Sync widget default values SKI_ActiveEffectsWidgetInstance.Enabled = true SKI_ActiveEffectsWidgetInstance.EffectSize = _effectWidgetIconSizeValues[_effectWidgetIconSizeIdx] SKI_ActiveEffectsWidgetInstance.HAnchor = _alignmentValues[_effectWidgetHAnchorIdx] SKI_ActiveEffectsWidgetInstance.VAnchor = _vertAlignmentValues[_effectWidgetVAnchorIdx] SKI_ActiveEffectsWidgetInstance.GroupEffectCount = _effectWidgetGroupCount SKI_ActiveEffectsWidgetInstance.Orientation = _orientationValues[_effectWidgetOrientationIdx] SKI_ActiveEffectsWidgetInstance.X = _alignmentBaseOffsets[_effectWidgetHAnchorIdx] + _effectWidgetXOffset SKI_ActiveEffectsWidgetInstance.Y = _vertAlignmentBaseOffsets[_effectWidgetVAnchorIdx] + _effectWidgetYOffset endIf if (a_version >= 5 && CurrentVersion < 5) Debug.Trace(self + ": Updating to script version 5") endIf if (a_version >= 6 && CurrentVersion < 6) Debug.Trace(self + ": Updating to script version 6") Pages = new string[3] Pages[0] = "$General" Pages[1] = "$Favorite Groups" Pages[2] = "$Advanced" _favGroupNames = new string[8] _favGroupNames[0] = "$Group {1}" _favGroupNames[1] = "$Group {2}" _favGroupNames[2] = "$Group {3}" _favGroupNames[3] = "$Group {4}" _favGroupNames[4] = "$Group {5}" _favGroupNames[5] = "$Group {6}" _favGroupNames[6] = "$Group {7}" _favGroupNames[7] = "$Group {8}" endIf if (a_version >= 7 && CurrentVersion < 7) Debug.Trace(self + ": Updating to script version 7") Pages = new string[3] Pages[0] = "$General" Pages[1] = "$Controls" Pages[2] = "$Advanced" endIf if (a_version >= 8 && CurrentVersion < 8) Debug.Trace(self + ": Updating to script version 8") _categoryIconThemeShortNames = new string[1] _categoryIconThemeShortNames[0] = "SKYUI V5" _categoryIconThemeLongNames = new string[1] _categoryIconThemeLongNames[0] = "SkyUI V5, by PsychoSteve" _categoryIconThemeValues = new string[1] _categoryIconThemeValues[0] = "skyui\\icons_category_psychosteve.swf" _categoryIconThemeIdx = 0 SKI_SettingsManagerInstance.ClearOverride("Appearance$icons$category$source") SKI_SettingsManagerInstance.SetOverride("Appearance$icons$category$source", _categoryIconThemeValues[_categoryIconThemeIdx]) endIf if a_version >= 9 && CurrentVersion < 9 debug.Trace(self as String + ": Updating to script version 9") _categoryIconThemeShortNames = new String[4] _categoryIconThemeShortNames[0] = "SKYUI V5" _categoryIconThemeShortNames[1] = "CELTIC" _categoryIconThemeShortNames[2] = "CURVED" _categoryIconThemeShortNames[3] = "STRAIGHT" _categoryIconThemeLongNames = new String[4] _categoryIconThemeLongNames[0] = "SkyUI V5, by PsychoSteve" _categoryIconThemeLongNames[1] = "Celtic, by GreatClone" _categoryIconThemeLongNames[2] = "Curved, by T3T" _categoryIconThemeLongNames[3] = "Straight, by T3T" _categoryIconThemeValues = new String[4] _categoryIconThemeValues[0] = "skyui\\icons_category_psychosteve.swf" _categoryIconThemeValues[1] = "skyui\\icons_category_celtic.swf" _categoryIconThemeValues[2] = "skyui\\icons_category_curved.swf" _categoryIconThemeValues[3] = "skyui\\icons_category_straight.swf" endIf endEvent ; EVENTS ------------------------------------------------------------------------------------------ ; @implements SKI_ConfigBase event OnPageReset(string a_page) ; Load custom .swf for animated logo if (a_page == "") LoadCustomContent("skyui/skyui_splash.swf") return else UnloadCustomContent() endIf ; ------------------------------------------------------- if (a_page == "$General") SetCursorFillMode(TOP_TO_BOTTOM) AddHeaderOption("$Item List") AddTextOptionST("ITEMLIST_FONT_SIZE", "$Font Size", _sizes[_itemlistFontSizeIdx]) AddSliderOptionST("ITEMLIST_QUANTITY_MIN_COUNT", "$Quantity Menu Min. Count", _itemlistQuantityMinCount) AddMenuOptionST("ITEMLIST_CATEGORY_ICON_THEME", "$Category Icon Theme", _categoryIconThemeShortNames[_categoryIconThemeIdx]) AddToggleOptionST("ITEMLIST_NO_ICON_COLORS", "$Disable Icon Colors", _itemlistNoIconColors) AddEmptyOption() AddHeaderOption("$Active Effects HUD") AddToggleOptionST("EFFECT_WIDGET_ENABLED", "$Enabled", SKI_ActiveEffectsWidgetInstance.Enabled) AddTextOptionST("EFFECT_WIDGET_ICON_SIZE","$Icon Size", _sizes[_effectWidgetIconSizeIdx], _effectWidgetFlags) AddSliderOptionST("EFFECT_WIDGET_MIN_TIME_LEFT", "$Minimum Time Left", SKI_ActiveEffectsWidgetInstance.MinimumTimeLeft, "{0} s", _effectWidgetFlags) SetCursorPosition(1) AddHeaderOption("$Favorites Menu") AddToggleOptionST("FAV_MENU_HELP_ENABLED", "$Show Button Help", SKI_FavoritesManagerInstance.ButtonHelpEnabled) AddEmptyOption() int ARMOR_FLAG = SKI_FavoritesManagerInstance.GROUP_FLAG_UNEQUIP_ARMOR int HANDS_FLAG = SKI_FavoritesManagerInstance.GROUP_FLAG_UNEQUIP_HANDS AddHeaderOption("$Favorite Groups") AddMenuOptionST("FAV_GROUP_SELECT", "", "$Group {" + (_favCurGroupIdx+1) + "}") AddToggleOptionST("FAV_GROUP_UNEQUIP_ARMOR", "$Unequip Armor", SKI_FavoritesManagerInstance.GetGroupFlag(_favCurGroupIdx, ARMOR_FLAG)) AddToggleOptionST("FAV_GROUP_UNEQUIP_HANDS", "$Unequip Hands", SKI_FavoritesManagerInstance.GetGroupFlag(_favCurGroupIdx, HANDS_FLAG)) ; ------------------------------------------------------- elseIf (a_page == "$Controls") bool isGamepad = Game.UsingGamepad() SetCursorFillMode(TOP_TO_BOTTOM) AddHeaderOption("$Item List") if (! isGamepad) AddKeyMapOptionST("SEARCH_KEY", "$Search", _searchKey) AddKeyMapOptionST("SWITCH_TAB_KEY", "$Switch Tab", _switchTabKey) AddKeyMapOptionST("EQUIP_MODE_KEY", "$Equip Mode", _equipModeKey) else AddKeyMapOptionST("SEARCH_KEY", "$Search", _searchKey, OPTION_FLAG_DISABLED) AddKeyMapOptionST("SWITCH_TAB_BUTTON", "$Switch Tab", _switchTabButton) AddKeyMapOptionST("PREV_COLUMN_BUTTON", "$Previous Column", _prevColumnButton) AddKeyMapOptionST("NEXT_COLUMN_BUTTON", "$Next Column", _nextColumnButton) AddKeyMapOptionST("SORT_ORDER_BUTTON", "$Order", _sortOrderButton) endIf if (! isGamepad) AddEmptyOption() AddHeaderOption("$Favorites Menu") AddKeyMapOptionST("FAV_GROUP_ADD_KEY", "{$Group}/{$Ungroup}", SKI_FavoritesManagerInstance.GroupAddKey) AddKeyMapOptionST("FAV_GROUP_USE_KEY", "$Group Use", SKI_FavoritesManagerInstance.GroupUseKey) AddKeyMapOptionST("FAV_SET_ICON_KEY", "$Set Group Icon", SKI_FavoritesManagerInstance.SetIconKey) AddKeyMapOptionST("FAV_EQUIP_STATE_KEY", "$Save Equip State", SKI_FavoritesManagerInstance.SaveEquipStateKey) AddKeyMapOptionST("FAV_TOGGLE_FOCUS", "$Toggle Focus", SKI_FavoritesManagerInstance.ToggleFocusKey) endIf SetCursorPosition(1) int[] groupHotkeys = SKI_FavoritesManagerInstance.GetGroupHotkeys() AddHeaderOption("$Favorite Groups") AddKeyMapOptionST("FAV_GROUP_USE_HOTKEY1", "$Group {1}", groupHotkeys[0], OPTION_FLAG_WITH_UNMAP) AddKeyMapOptionST("FAV_GROUP_USE_HOTKEY2", "$Group {2}", groupHotkeys[1], OPTION_FLAG_WITH_UNMAP) AddKeyMapOptionST("FAV_GROUP_USE_HOTKEY3", "$Group {3}", groupHotkeys[2], OPTION_FLAG_WITH_UNMAP) AddKeyMapOptionST("FAV_GROUP_USE_HOTKEY4", "$Group {4}", groupHotkeys[3], OPTION_FLAG_WITH_UNMAP) AddKeyMapOptionST("FAV_GROUP_USE_HOTKEY5", "$Group {5}", groupHotkeys[4], OPTION_FLAG_WITH_UNMAP) AddKeyMapOptionST("FAV_GROUP_USE_HOTKEY6", "$Group {6}", groupHotkeys[5], OPTION_FLAG_WITH_UNMAP) AddKeyMapOptionST("FAV_GROUP_USE_HOTKEY7", "$Group {7}", groupHotkeys[6], OPTION_FLAG_WITH_UNMAP) AddKeyMapOptionST("FAV_GROUP_USE_HOTKEY8", "$Group {8}", groupHotkeys[7], OPTION_FLAG_WITH_UNMAP) ; ------------------------------------------------------- elseIf (a_page == "$Advanced") SetCursorFillMode(TOP_TO_BOTTOM) AddHeaderOption("$3D Item") AddSliderOptionST("XD_ITEM_XOFFSET", "$Horizontal Offset", _3DItemXOffset, "{0}", _3DItemFlags) AddSliderOptionST("XD_ITEM_YOFFSET", "$Vertical Offset", _3DItemYOffset, "{0}", _3DItemFlags) AddSliderOptionST("XD_ITEM_SCALE", "$Scale", _3DItemScale, "{1}", _3DItemFlags) AddToggleOptionST("XD_ITEM_POSITIONING", "$Disable Positioning", _3DItemDisablePositioning) AddEmptyOption() AddHeaderOption("$Active Effects HUD") AddTextOptionST("EFFECT_WIDGET_ORIENTATION", "$Orientation", _orientations[_effectWidgetOrientationIdx], _effectWidgetFlags) AddTextOptionST("EFFECT_WIDGET_HORIZONTAL_ANCHOR", "$Horizontal Anchor", _alignments[_effectWidgetHAnchorIdx], _effectWidgetFlags) AddTextOptionST("EFFECT_WIDGET_VERTICAL_ANCHOR", "$Vertical Anchor", _vertAlignments[_effectWidgetVAnchorIdx], _effectWidgetFlags) AddSliderOptionST("EFFECT_WIDGET_GROUP_COUNT", "$Icon Group Count", SKI_ActiveEffectsWidgetInstance.GroupEffectCount, "{0}", _effectWidgetFlags) AddSliderOptionST("EFFECT_WIDGET_XOFFSET", "$Horizontal Offset", _effectWidgetXOffset, "{0}", _effectWidgetFlags) AddSliderOptionST("EFFECT_WIDGET_YOFFSET", "$Vertical Offset", _effectWidgetYOffset, "{0}", _effectWidgetFlags) SetCursorPosition(1) AddHeaderOption("$Item Card") AddTextOptionST("ITEMCARD_ALIGN", "$Align", _alignments[_itemcardAlignIdx]) AddSliderOptionST("ITEMCARD_XOFFSET", "$Horizontal Offset", _itemcardXOffset) AddSliderOptionST("ITEMCARD_YOFFSET", "$Vertical Offset", _itemcardYOffset) AddEmptyOption() AddHeaderOption("$SWF Version Checking") ; AddToggleOptionST("CHECK_MAP_MENU", "Map Menu", SKI_MainInstance.MapMenuCheckEnabled) ; AddToggleOptionST("CHECK_FAVORITES_MENU", "Favorites Menu", SKI_MainInstance.FavoritesMenuCheckEnabled) AddToggleOptionST("CHECK_INVENTORY_MENU", "Inventory Menu", SKI_MainInstance.InventoryMenuCheckEnabled) AddToggleOptionST("CHECK_MAGIC_MENU", "Magic Menu", SKI_MainInstance.MagicMenuCheckEnabled) AddToggleOptionST("CHECK_BARTER_MENU", "Barter Menu", SKI_MainInstance.BarterMenuCheckEnabled) AddToggleOptionST("CHECK_CONTAINER_MENU", "Container Menu", SKI_MainInstance.ContainerMenuCheckEnabled) AddToggleOptionST("CHECK_CRAFTING_MENU", "Crafting Menu", SKI_MainInstance.CraftingMenuCheckEnabled) AddToggleOptionST("CHECK_GIFT_MENU", "Gift Menu", SKI_MainInstance.GiftMenuCheckEnabled) endIf endEvent ; STATE OPTIONS ----------------------------------------------------------------------------------- state FAV_GROUP_ADD_KEY ; KEYMAP event OnKeyMapChangeST(int a_keyCode, string a_conflictControl, string a_conflictName) if (! ValidateKey(a_keyCode, false)) return endIf SKI_FavoritesManagerInstance.GroupAddKey = a_keyCode RefreshFavoriteHotkeys() endEvent event OnDefaultST() SKI_FavoritesManagerInstance.GroupAddKey = 33 RefreshFavoriteHotkeys() endEvent event OnHighlightST() SetInfoText("$SKI_INFO1{F}") endEvent endState state FAV_GROUP_USE_KEY ; KEYMAP event OnKeyMapChangeST(int a_keyCode, string a_conflictControl, string a_conflictName) if (! ValidateKey(a_keyCode, false)) return endIf SKI_FavoritesManagerInstance.GroupUseKey = a_keyCode RefreshFavoriteHotkeys() endEvent event OnDefaultST() SKI_FavoritesManagerInstance.GroupUseKey = 19 RefreshFavoriteHotkeys() endEvent event OnHighlightST() SetInfoText("$SKI_INFO1{R}") endEvent endState state FAV_SET_ICON_KEY ; KEYMAP event OnKeyMapChangeST(int a_keyCode, string a_conflictControl, string a_conflictName) if (! ValidateKey(a_keyCode, false)) return endIf SKI_FavoritesManagerInstance.SetIconKey = a_keyCode RefreshFavoriteHotkeys() endEvent event OnDefaultST() SKI_FavoritesManagerInstance.SetIconKey = 56 RefreshFavoriteHotkeys() endEvent event OnHighlightST() SetInfoText("$SKI_INFO1{LAlt}") endEvent endState state FAV_EQUIP_STATE_KEY ; KEYMAP event OnKeyMapChangeST(int a_keyCode, string a_conflictControl, string a_conflictName) if (! ValidateKey(a_keyCode, false)) return endIf SKI_FavoritesManagerInstance.SaveEquipStateKey = a_keyCode RefreshFavoriteHotkeys() endEvent event OnDefaultST() SKI_FavoritesManagerInstance.SaveEquipStateKey = 20 RefreshFavoriteHotkeys() endEvent event OnHighlightST() SetInfoText("$SKI_INFO1{T}") endEvent endState state FAV_TOGGLE_FOCUS ; KEYMAP event OnKeyMapChangeST(int a_keyCode, string a_conflictControl, string a_conflictName) if (! ValidateKey(a_keyCode, false)) return endIf SKI_FavoritesManagerInstance.ToggleFocusKey = a_keyCode RefreshFavoriteHotkeys() endEvent event OnDefaultST() SKI_FavoritesManagerInstance.ToggleFocusKey = 57 RefreshFavoriteHotkeys() endEvent event OnHighlightST() SetInfoText("$SKI_INFO1{Space}") endEvent endState state FAV_GROUP_USE_HOTKEY1 ; KEYMAP event OnKeyMapChangeST(int a_keyCode, string a_conflictControl, string a_conflictName) SetFavoritesGroupHotkey(0, a_keyCode, a_conflictControl, a_conflictName) endEvent event OnDefaultST() SetFavoritesGroupHotkey(0, 59) endEvent event OnHighlightST() SetInfoText("$SKI_INFO1{F1}") endEvent endState state FAV_GROUP_USE_HOTKEY2 ; KEYMAP event OnKeyMapChangeST(int a_keyCode, string a_conflictControl, string a_conflictName) SetFavoritesGroupHotkey(1, a_keyCode, a_conflictControl, a_conflictName) endEvent event OnDefaultST() SetFavoritesGroupHotkey(1, 60) endEvent event OnHighlightST() SetInfoText("$SKI_INFO1{F2}") endEvent endState state FAV_GROUP_USE_HOTKEY3 ; KEYMAP event OnKeyMapChangeST(int a_keyCode, string a_conflictControl, string a_conflictName) SetFavoritesGroupHotkey(2, a_keyCode, a_conflictControl, a_conflictName) endEvent event OnDefaultST() SetFavoritesGroupHotkey(2, 61) endEvent event OnHighlightST() SetInfoText("$SKI_INFO1{F3}") endEvent endState state FAV_GROUP_USE_HOTKEY4 ; KEYMAP event OnKeyMapChangeST(int a_keyCode, string a_conflictControl, string a_conflictName) SetFavoritesGroupHotkey(3, a_keyCode, a_conflictControl, a_conflictName) endEvent event OnDefaultST() SetFavoritesGroupHotkey(3, 62) endEvent event OnHighlightST() SetInfoText("$SKI_INFO1{F4}") endEvent endState state FAV_GROUP_USE_HOTKEY5 ; KEYMAP event OnKeyMapChangeST(int a_keyCode, string a_conflictControl, string a_conflictName) SetFavoritesGroupHotkey(4, a_keyCode, a_conflictControl, a_conflictName) endEvent event OnDefaultST() SetFavoritesGroupHotkey(4, -1) endEvent event OnHighlightST() SetInfoText("$SKI_INFO1{$Off}") endEvent endState state FAV_GROUP_USE_HOTKEY6 ; KEYMAP event OnKeyMapChangeST(int a_keyCode, string a_conflictControl, string a_conflictName) SetFavoritesGroupHotkey(5, a_keyCode, a_conflictControl, a_conflictName) endEvent event OnDefaultST() SetFavoritesGroupHotkey(5, -1) endEvent event OnHighlightST() SetInfoText("$SKI_INFO1{$Off}") endEvent endState state FAV_GROUP_USE_HOTKEY7 ; KEYMAP event OnKeyMapChangeST(int a_keyCode, string a_conflictControl, string a_conflictName) SetFavoritesGroupHotkey(6, a_keyCode, a_conflictControl, a_conflictName) endEvent event OnDefaultST() SetFavoritesGroupHotkey(6, -1) endEvent event OnHighlightST() SetInfoText("$SKI_INFO1{$Off}") endEvent endState state FAV_GROUP_USE_HOTKEY8 ; KEYMAP event OnKeyMapChangeST(int a_keyCode, string a_conflictControl, string a_conflictName) SetFavoritesGroupHotkey(7, a_keyCode, a_conflictControl, a_conflictName) endEvent event OnDefaultST() SetFavoritesGroupHotkey(7, -1) endEvent event OnHighlightST() SetInfoText("$SKI_INFO1{$Off}") endEvent endState state FAV_MENU_HELP_ENABLED ; TOGGLE event OnSelectST() bool newVal = !SKI_FavoritesManagerInstance.ButtonHelpEnabled SKI_FavoritesManagerInstance.ButtonHelpEnabled = newVal SetToggleOptionValueST(newVal) endEvent event OnDefaultST() SKI_FavoritesManagerInstance.ButtonHelpEnabled = true SetToggleOptionValueST(true) endEvent event OnHighlightST() SetInfoText("$SKI_INFO1{$On}") endEvent endState state FAV_GROUP_SELECT ; MENU event OnMenuOpenST() SetMenuDialogStartIndex(_favCurGroupIdx) SetMenuDialogDefaultIndex(0) SetMenuDialogOptions(_favGroupNames) endEvent event OnMenuAcceptST(int a_index) _favCurGroupIdx = a_index SetCurrentFavoriteGroup(_favCurGroupIdx) SetMenuOptionValueST(_favGroupNames[_favCurGroupIdx]) endEvent event OnDefaultST() _favCurGroupIdx = 0 SetCurrentFavoriteGroup(_favCurGroupIdx) SetTextOptionValueST(_favCurGroupIdx+1) endEvent event OnHighlightST() SetInfoText("$SKI_INFO6") endEvent endState state FAV_GROUP_UNEQUIP_ARMOR ; TOGGLE event OnSelectST() int ARMOR_FLAG = SKI_FavoritesManagerInstance.GROUP_FLAG_UNEQUIP_ARMOR bool newVal = !SKI_FavoritesManagerInstance.GetGroupFlag(_favCurGroupIdx, ARMOR_FLAG) SKI_FavoritesManagerInstance.SetGroupFlag(_favCurGroupIdx, ARMOR_FLAG, newVal) SetToggleOptionValueST(newVal) endEvent event OnDefaultST() int ARMOR_FLAG = SKI_FavoritesManagerInstance.GROUP_FLAG_UNEQUIP_ARMOR SKI_FavoritesManagerInstance.SetGroupFlag(_favCurGroupIdx, ARMOR_FLAG, false) SetToggleOptionValueST(false) endEvent event OnHighlightST() SetInfoText("$SKI_INFO7{$Off}") endEvent endState state FAV_GROUP_UNEQUIP_HANDS ; TOGGLE event OnSelectST() int HANDS_FLAG = SKI_FavoritesManagerInstance.GROUP_FLAG_UNEQUIP_HANDS bool newVal = !SKI_FavoritesManagerInstance.GetGroupFlag(_favCurGroupIdx, HANDS_FLAG) SKI_FavoritesManagerInstance.SetGroupFlag(_favCurGroupIdx, HANDS_FLAG, newVal) SetToggleOptionValueST(newVal) endEvent event OnDefaultST() int HANDS_FLAG = SKI_FavoritesManagerInstance.GROUP_FLAG_UNEQUIP_ARMOR SKI_FavoritesManagerInstance.SetGroupFlag(_favCurGroupIdx, HANDS_FLAG, false) SetToggleOptionValueST(false) endEvent event OnHighlightST() SetInfoText("$SKI_INFO8{$Off}") endEvent endState ; ------------------------------------------------------- state ITEMLIST_FONT_SIZE ; TEXT event OnSelectST() if (_itemlistFontSizeIdx < _sizes.length - 1) _itemlistFontSizeIdx += 1 else _itemlistFontSizeIdx = 0 endif SetTextOptionValueST(_sizes[_itemlistFontSizeIdx]) ApplyItemListFontSize() endEvent event OnDefaultST() _itemlistFontSizeIdx = 1 SetTextOptionValueST(_sizes[_itemlistFontSizeIdx]) ApplyItemListFontSize() endEvent event OnHighlightST() SetInfoText("$SKI_INFO1{" + _sizes[1] + "}") endEvent endState state ITEMLIST_QUANTITY_MIN_COUNT ; SLIDER event OnSliderOpenST() SetSliderDialogStartValue(_itemlistQuantityMinCount) SetSliderDialogDefaultValue(6) SetSliderDialogRange(0, 100) SetSliderDialogInterval(1) endEvent event OnSliderAcceptST(float a_value) _itemlistQuantityMinCount = a_value as int SetSliderOptionValueST(_itemlistQuantityMinCount) SKI_SettingsManagerInstance.SetOverride("ItemList$quantityMenu$minCount", _itemlistQuantityMinCount) endEvent event OnDefaultST() _itemlistQuantityMinCount = 6 SetSliderOptionValueST(_itemlistQuantityMinCount) SKI_SettingsManagerInstance.SetOverride("ItemList$quantityMenu$minCount", _itemlistQuantityMinCount) endEvent event OnHighlightST() SetInfoText("$SKI_INFO2{6}") endEvent endState state ITEMLIST_CATEGORY_ICON_THEME ; MENU event OnMenuOpenST() SetMenuDialogStartIndex(_categoryIconThemeIdx) SetMenuDialogDefaultIndex(0) SetMenuDialogOptions(_categoryIconThemeLongNames) endEvent event OnMenuAcceptST(int a_index) _categoryIconThemeIdx = a_index SetMenuOptionValueST(_categoryIconThemeShortNames[_categoryIconThemeIdx]) SKI_SettingsManagerInstance.SetOverride("Appearance$icons$category$source", _categoryIconThemeValues[_categoryIconThemeIdx]) endEvent event OnDefaultST() _categoryIconThemeIdx = 0 SetTextOptionValueST(_categoryIconThemeShortNames[_categoryIconThemeIdx]) SKI_SettingsManagerInstance.SetOverride("Appearance$icons$category$source", _categoryIconThemeValues[_categoryIconThemeIdx]) endEvent event OnHighlightST() SetInfoText("$SKI_INFO1{" + _categoryIconThemeShortNames[0] + "}") endEvent endState state ITEMLIST_NO_ICON_COLORS ; TOGGLE event OnSelectST() _itemListNoIconColors = !_itemlistNoIconColors SetToggleOptionValueST(_itemlistNoIconColors) SKI_SettingsManagerInstance.SetOverride("Appearance$icons$item$noColor", _itemlistNoIconColors) endEvent event OnDefaultST() _itemlistNoIconColors = false SetToggleOptionValueST(_itemlistNoIconColors) SKI_SettingsManagerInstance.SetOverride("Appearance$icons$item$noColor", _itemlistNoIconColors) endEvent event OnHighlightST() SetInfoText("$SKI_INFO1{$Off}") endEvent endState ; ------------------------------------------------------- state EFFECT_WIDGET_ENABLED ; TOGGLE event OnSelectST() bool newVal = !SKI_ActiveEffectsWidgetInstance.Enabled SKI_ActiveEffectsWidgetInstance.Enabled = newVal if (newVal) _effectWidgetFlags = OPTION_FLAG_NONE else _effectWidgetFlags = OPTION_FLAG_DISABLED endIf SetOptionFlagsST(_effectWidgetFlags, true, "EFFECT_WIDGET_ICON_SIZE") SetOptionFlagsST(_effectWidgetFlags, true, "EFFECT_WIDGET_MIN_TIME_LEFT") SetToggleOptionValueST(newVal) endEvent event OnDefaultST() SKI_ActiveEffectsWidgetInstance.Enabled = true _effectWidgetFlags = OPTION_FLAG_NONE SetOptionFlagsST(_effectWidgetFlags, true, "EFFECT_WIDGET_ICON_SIZE") SetOptionFlagsST(_effectWidgetFlags, true, "EFFECT_WIDGET_MIN_TIME_LEFT") SetToggleOptionValueST(true) endEvent event OnHighlightST() SetInfoText("$SKI_INFO1{$On}") endEvent endState state EFFECT_WIDGET_ICON_SIZE ; TEXT event OnSelectST() if (_effectWidgetIconSizeIdx < _sizes.length - 1) _effectWidgetIconSizeIdx += 1 else _effectWidgetIconSizeIdx = 0 endIf SKI_ActiveEffectsWidgetInstance.EffectSize = _effectWidgetIconSizeValues[_effectWidgetIconSizeIdx] SetTextOptionValueST(_sizes[_effectWidgetIconSizeIdx]) endEvent event OnDefaultST() _effectWidgetIconSizeIdx = 1 SKI_ActiveEffectsWidgetInstance.EffectSize = _effectWidgetIconSizeValues[_effectWidgetIconSizeIdx] SetTextOptionValueST(_sizes[_effectWidgetIconSizeIdx]) endEvent event OnHighlightST() SetInfoText("$SKI_INFO1{" + _sizes[1] + "}") endEvent endState state EFFECT_WIDGET_ORIENTATION ; TEXT event OnSelectST() if (_effectWidgetOrientationIdx < _orientations.length - 1) _effectWidgetOrientationIdx += 1 else _effectWidgetOrientationIdx = 0 endIf SKI_ActiveEffectsWidgetInstance.Orientation = _orientationValues[_effectWidgetOrientationIdx] SetTextOptionValueST(_orientations[_effectWidgetOrientationIdx]) endEvent event OnDefaultST() _effectWidgetOrientationIdx = 1 SKI_ActiveEffectsWidgetInstance.Orientation = _orientationValues[_effectWidgetOrientationIdx] SetTextOptionValueST(_orientations[_effectWidgetOrientationIdx]) endEvent event OnHighlightST() SetInfoText("$SKI_INFO1{" + _orientations[1] + "}") endEvent endState state EFFECT_WIDGET_HORIZONTAL_ANCHOR ; TEXT event OnSelectST() if (_effectWidgetHAnchorIdx < _alignments.length - 1) _effectWidgetHAnchorIdx += 1 else _effectWidgetHAnchorIdx = 0 endIf SKI_ActiveEffectsWidgetInstance.HAnchor = _alignmentValues[_effectWidgetHAnchorIdx] SKI_ActiveEffectsWidgetInstance.X = _alignmentBaseOffsets[_effectWidgetHAnchorIdx] + _effectWidgetXOffset SetTextOptionValueST(_alignments[_effectWidgetHAnchorIdx]) endEvent event OnDefaultST() _effectWidgetVAnchorIdx = 1 SKI_ActiveEffectsWidgetInstance.X = _alignmentBaseOffsets[_effectWidgetHAnchorIdx] + _effectWidgetXOffset SetTextOptionValueST(_alignments[_effectWidgetHAnchorIdx]) endEvent event OnHighlightST() SetInfoText("$SKI_INFO1{" + _alignments[1] + "}") endEvent endState state EFFECT_WIDGET_VERTICAL_ANCHOR ; TEXT event OnSelectST() if (_effectWidgetVAnchorIdx < _vertAlignments.length - 1) _effectWidgetVAnchorIdx += 1 else _effectWidgetVAnchorIdx = 0 endIf SKI_ActiveEffectsWidgetInstance.VAnchor = _vertAlignmentValues[_effectWidgetVAnchorIdx] SKI_ActiveEffectsWidgetInstance.Y = _vertAlignmentBaseOffsets[_effectWidgetVAnchorIdx] + _effectWidgetYOffset SetTextOptionValueST(_vertAlignments[_effectWidgetVAnchorIdx]) endEvent event OnDefaultST() _effectWidgetVAnchorIdx = 0 SKI_ActiveEffectsWidgetInstance.Y = _vertAlignmentBaseOffsets[_effectWidgetVAnchorIdx] + _effectWidgetYOffset SetTextOptionValueST(_vertAlignments[_effectWidgetVAnchorIdx]) endEvent event OnHighlightST() SetInfoText("$SKI_INFO1{" + _vertAlignments[0] + "}") endEvent endState state EFFECT_WIDGET_MIN_TIME_LEFT ; SLIDER event OnSliderOpenST() SetSliderDialogStartValue(SKI_ActiveEffectsWidgetInstance.MinimumTimeLeft) SetSliderDialogDefaultValue(180) SetSliderDialogRange(0, 600) SetSliderDialogInterval(10) endEvent event OnSliderAcceptST(float a_value) SKI_ActiveEffectsWidgetInstance.MinimumTimeLeft = a_value as int SetSliderOptionValueST(a_value as int, "{0} s") endEvent event OnDefaultST() SKI_ActiveEffectsWidgetInstance.MinimumTimeLeft = 180 SetSliderOptionValueST(180) endEvent event OnHighlightST() SetInfoText("$SKI_INFO5{180}") endEvent endState state EFFECT_WIDGET_GROUP_COUNT ; SLIDER event OnSliderOpenST() SetSliderDialogStartValue(SKI_ActiveEffectsWidgetInstance.GroupEffectCount) SetSliderDialogDefaultValue(8) SetSliderDialogRange(1, 16) SetSliderDialogInterval(1) endEvent event OnSliderAcceptST(float a_value) SKI_ActiveEffectsWidgetInstance.GroupEffectCount = a_value as int SetSliderOptionValueST(a_value as int) endEvent event OnDefaultST() SKI_ActiveEffectsWidgetInstance.GroupEffectCount = 8 SetSliderOptionValueST(8) endEvent event OnHighlightST() SetInfoText("$SKI_INFO1{8}") endEvent endState state EFFECT_WIDGET_XOFFSET ; SLIDER event OnSliderOpenST() SetSliderDialogStartValue(_effectWidgetXOffset) SetSliderDialogDefaultValue(0) SetSliderDialogRange(-1280, 1280) SetSliderDialogInterval(1) endEvent event OnSliderAcceptST(float a_value) _effectWidgetXOffset = a_value SKI_ActiveEffectsWidgetInstance.X = _alignmentBaseOffsets[_effectWidgetHAnchorIdx] + _effectWidgetXOffset SetSliderOptionValueST(_effectWidgetXOffset) endEvent event OnDefaultST() _effectWidgetXOffset = 0.0 SKI_ActiveEffectsWidgetInstance.X = _alignmentBaseOffsets[_effectWidgetHAnchorIdx] + _effectWidgetXOffset SetSliderOptionValueST(_effectWidgetXOffset) endEvent event OnHighlightST() SetInfoText("$SKI_INFO1{0}") endEvent endState state EFFECT_WIDGET_YOFFSET ; SLIDER event OnSliderOpenST() SetSliderDialogStartValue(_effectWidgetYOffset) SetSliderDialogDefaultValue(0) SetSliderDialogRange(-720, 720) SetSliderDialogInterval(1) endEvent event OnSliderAcceptST(float a_value) _effectWidgetYOffset = a_value SKI_ActiveEffectsWidgetInstance.Y = _vertAlignmentBaseOffsets[_effectWidgetVAnchorIdx] + _effectWidgetYOffset SetSliderOptionValueST(_effectWidgetYOffset) endEvent event OnDefaultST() _effectWidgetYOffset = 0.0 SKI_ActiveEffectsWidgetInstance.Y = _vertAlignmentBaseOffsets[_effectWidgetVAnchorIdx] + _effectWidgetYOffset SetSliderOptionValueST(_effectWidgetYOffset) endEvent event OnHighlightST() SetInfoText("$SKI_INFO1{0}") endEvent endState ; ------------------------------------------------------- state SEARCH_KEY ; KEYMAP event OnKeyMapChangeST(int a_keyCode, string a_conflictControl, string a_conflictName) if (! ValidateKey(a_keyCode, false)) return endIf SwapItemListKey(a_keyCode, _searchKey) _searchKey = a_keyCode SetKeyMapOptionValueST(_searchKey) SKI_SettingsManagerInstance.SetOverride("Input$controls$pc$search", _searchKey) endEvent event OnDefaultST() _searchKey = 57 SetKeyMapOptionValueST(_searchKey) SKI_SettingsManagerInstance.SetOverride("Input$controls$pc$search", _searchKey) endEvent event OnHighlightST() SetInfoText("$SKI_INFO1{Space}") endEvent endState state SWITCH_TAB_KEY ; KEYMAP event OnKeyMapChangeST(int a_keyCode, string a_conflictControl, string a_conflictName) if (! ValidateKey(a_keyCode, false)) return endIf SwapItemListKey(a_keyCode, _switchTabKey) _switchTabKey = a_keyCode SetKeyMapOptionValueST(_switchTabKey) SKI_SettingsManagerInstance.SetOverride("Input$controls$pc$switchTab", _switchTabKey) endEvent event OnDefaultST() _switchTabKey = 56 SetKeyMapOptionValueST(_switchTabKey) SKI_SettingsManagerInstance.SetOverride("Input$controls$pc$switchTab", _switchTabKey) endEvent event OnHighlightST() SetInfoText("$SKI_INFO1{LAlt}") endEvent endState state EQUIP_MODE_KEY ; KEYMAP event OnKeyMapChangeST(int a_keyCode, string a_conflictControl, string a_conflictName) if (! ValidateKey(a_keyCode, false)) return endIf SwapItemListKey(a_keyCode, _equipModeKey) _equipModeKey = a_keyCode SetKeyMapOptionValueST(_equipModeKey) SKI_SettingsManagerInstance.SetOverride("Input$controls$pc$equipMode", _equipModeKey) endEvent event OnDefaultST() _equipModeKey = 42 SetKeyMapOptionValueST(_equipModeKey) SKI_SettingsManagerInstance.SetOverride("Input$controls$pc$equipMode", _equipModeKey) endEvent event OnHighlightST() SetInfoText("$SKI_INFO1{Shift}") endEvent endState state SWITCH_TAB_BUTTON ; KEYMAP event OnKeyMapChangeST(int a_keyCode, string a_conflictControl, string a_conflictName) if (! ValidateKey(a_keyCode, true)) return endIf SwapItemListKey(a_keyCode, _switchTabButton) _switchTabButton = a_keyCode SetKeyMapOptionValueST(_switchTabButton) SKI_SettingsManagerInstance.SetOverride("Input$controls$gamepad$switchTab", _switchTabButton) endEvent event OnDefaultST() _switchTabButton = 271 SetKeyMapOptionValueST(_switchTabButton) SKI_SettingsManagerInstance.SetOverride("Input$controls$gamepad$switchTab", _switchTabButton) endEvent event OnHighlightST() SetInfoText("$SKI_INFO1{Back}") endEvent endState state PREV_COLUMN_BUTTON ; KEYMAP event OnKeyMapChangeST(int a_keyCode, string a_conflictControl, string a_conflictName) if (! ValidateKey(a_keyCode, true)) return endIf SwapItemListKey(a_keyCode, _prevColumnButton) _prevColumnButton = a_keyCode SetKeyMapOptionValueST(_prevColumnButton) SKI_SettingsManagerInstance.SetOverride("Input$controls$gamepad$prevColumn", _prevColumnButton) endEvent event OnDefaultST() _prevColumnButton = 274 SetKeyMapOptionValueST(_prevColumnButton) SKI_SettingsManagerInstance.SetOverride("Input$controls$gamepad$prevColumn", _prevColumnButton) endEvent event OnHighlightST() SetInfoText("$SKI_INFO1{LB}") endEvent endState state NEXT_COLUMN_BUTTON ; KEYMAP event OnKeyMapChangeST(int a_keyCode, string a_conflictControl, string a_conflictName) if (! ValidateKey(a_keyCode, true)) return endIf SwapItemListKey(a_keyCode, _nextColumnButton) _nextColumnButton = a_keyCode SetKeyMapOptionValueST(_nextColumnButton) SKI_SettingsManagerInstance.SetOverride("Input$controls$gamepad$nextColumn", _nextColumnButton) endEvent event OnDefaultST() _nextColumnButton = 275 SetKeyMapOptionValueST(_nextColumnButton) SKI_SettingsManagerInstance.SetOverride("Input$controls$gamepad$nextColumn", _nextColumnButton) endEvent event OnHighlightST() SetInfoText("$SKI_INFO1{RB}") endEvent endState state SORT_ORDER_BUTTON ; KEYMAP event OnKeyMapChangeST(int a_keyCode, string a_conflictControl, string a_conflictName) if (! ValidateKey(a_keyCode, true)) return endIf SwapItemListKey(a_keyCode, _sortOrderButton) _sortOrderButton = a_keyCode SetKeyMapOptionValueST(_sortOrderButton) SKI_SettingsManagerInstance.SetOverride("Input$controls$gamepad$sortOrder", _sortOrderButton) endEvent event OnDefaultST() _sortOrderButton = 272 SetKeyMapOptionValueST(_sortOrderButton) SKI_SettingsManagerInstance.SetOverride("Input$controls$gamepad$sortOrder", _sortOrderButton) endEvent event OnHighlightST() SetInfoText("$SKI_INFO1{LS}") endEvent endState ; ------------------------------------------------------- state ITEMCARD_ALIGN ; KEYMAP event OnSelectST() if (_itemcardAlignIdx < _alignments.length - 1) _itemcardAlignIdx += 1 else _itemcardAlignIdx = 0 endif SKI_SettingsManagerInstance.SetOverride("ItemInfo$itemcard$align", _alignmentValues[_itemcardAlignIdx]) SetTextOptionValueST(_alignments[_itemcardAlignIdx]) endEvent event OnDefaultST() _itemcardAlignIdx = 2 SKI_SettingsManagerInstance.SetOverride("ItemInfo$itemcard$align", _alignmentValues[_itemcardAlignIdx]) SetTextOptionValueST(_alignments[_itemcardAlignIdx]) endEvent event OnHighlightST() SetInfoText("$SKI_INFO1{" + _alignments[2] + "}") endEvent endState state ITEMCARD_XOFFSET ; SLIDER event OnSliderOpenST() SetSliderDialogStartValue(_itemcardXOffset) SetSliderDialogDefaultValue(0) SetSliderDialogRange(-1000, 1000) SetSliderDialogInterval(1) endEvent event OnSliderAcceptST(float a_value) _itemcardXOffset = a_value SetSliderOptionValueST(_itemcardXOffset) SKI_SettingsManagerInstance.SetOverride("ItemInfo$itemcard$xOffset", _itemcardXOffset) endEvent event OnDefaultST() _itemcardXOffset = 0.0 SetSliderOptionValueST(_itemcardXOffset) SKI_SettingsManagerInstance.SetOverride("ItemInfo$itemcard$xOffset", _itemcardXOffset) endEvent event OnHighlightST() SetInfoText("$SKI_INFO1{0}") endEvent endState state ITEMCARD_YOFFSET ; SLIDER event OnSliderOpenST() SetSliderDialogStartValue(_itemcardYOffset) SetSliderDialogDefaultValue(0) SetSliderDialogRange(-1000, 1000) SetSliderDialogInterval(1) endEvent event OnSliderAcceptST(float a_value) _itemcardYOffset = a_value SetSliderOptionValueST(_itemcardYOffset) SKI_SettingsManagerInstance.SetOverride("ItemInfo$itemcard$yOffset", _itemcardYOffset) endEvent event OnDefaultST() _itemcardYOffset = 0.0 SetSliderOptionValueST(_itemcardYOffset) SKI_SettingsManagerInstance.SetOverride("ItemInfo$itemcard$yOffset", _itemcardYOffset) endEvent event OnHighlightST() SetInfoText("$SKI_INFO1{0}") endEvent endState ; ------------------------------------------------------- state XD_ITEM_XOFFSET ; SLIDER event OnSliderOpenST() SetSliderDialogStartValue(_3DItemXOffset) SetSliderDialogDefaultValue(0) SetSliderDialogRange(-128, 128) SetSliderDialogInterval(1) endEvent event OnSliderAcceptST(float a_value) _3DItemXOffset = a_value SetSliderOptionValueST(_3DItemXOffset) Apply3DItemXOffset() endEvent event OnDefaultST() _3DItemXOffset = 0.0 SetSliderOptionValueST(_3DItemXOffset) Apply3DItemXOffset() endEvent event OnHighlightST() SetInfoText("$SKI_INFO1{0}") endEvent endState state XD_ITEM_YOFFSET ; SLIDER event OnSliderOpenST() SetSliderDialogStartValue(_3DItemYOffset) SetSliderDialogDefaultValue(0) SetSliderDialogRange(-128, 128) SetSliderDialogInterval(1) endEvent event OnSliderAcceptST(float a_value) _3DItemYOffset = a_value SetSliderOptionValueST(_3DItemYOffset) Apply3DItemYOffset() endEvent event OnDefaultST() _3DItemYOffset = 0.0 SetSliderOptionValueST(_3DItemYOffset) Apply3DItemYOffset() endEvent event OnHighlightST() SetInfoText("$SKI_INFO1{0}") endEvent endState state XD_ITEM_SCALE ; SLIDER event OnSliderOpenST() SetSliderDialogStartValue(_3DItemScale) SetSliderDialogDefaultValue(1.5) SetSliderDialogRange(0.5, 5) SetSliderDialogInterval(0.1) endEvent event OnSliderAcceptST(float a_value) _3DItemScale = a_value SetSliderOptionValueST(_3DItemScale, "{1}") Apply3DItemScale() endEvent event OnDefaultST() _3DItemScale = 1.5 SetSliderOptionValueST(_3DItemScale, "{1}") Apply3DItemScale() endEvent event OnHighlightST() SetInfoText("$SKI_INFO1{1.5}") endEvent endState state XD_ITEM_POSITIONING ; SLIDER event OnSelectST() bool newVal = !_3DItemDisablePositioning _3DItemDisablePositioning = newVal if (newVal) _3DItemFlags = OPTION_FLAG_DISABLED else _3DItemFlags = OPTION_FLAG_NONE endIf SetOptionFlagsST(_3DItemFlags, true, "XD_ITEM_XOFFSET") SetOptionFlagsST(_3DItemFlags, true, "XD_ITEM_YOFFSET") SetOptionFlagsST(_3DItemFlags, true, "XD_ITEM_SCALE") SetToggleOptionValueST(newVal) Apply3DItemXOffset() Apply3DItemYOffset() Apply3DItemScale() endEvent event OnDefaultST() _3DItemDisablePositioning = false _3DItemFlags = OPTION_FLAG_NONE SetOptionFlagsST(_3DItemFlags, true, "XD_ITEM_XOFFSET") SetOptionFlagsST(_3DItemFlags, true, "XD_ITEM_YOFFSET") SetOptionFlagsST(_3DItemFlags, true, "XD_ITEM_SCALE") SetToggleOptionValueST(false) Apply3DItemXOffset() Apply3DItemYOffset() Apply3DItemScale() endEvent event OnHighlightST() SetInfoText("$SKI_INFO4{$Off}") endEvent endState ; ------------------------------------------------------- state CHECK_INVENTORY_MENU ; SLIDER event OnSelectST() bool newVal = !SKI_MainInstance.InventoryMenuCheckEnabled SKI_MainInstance.InventoryMenuCheckEnabled = newVal SetToggleOptionValueST(newVal) endEvent event OnDefaultST() SKI_MainInstance.InventoryMenuCheckEnabled = true SetToggleOptionValueST(true) endEvent event OnHighlightST() SetInfoText("$SKI_INFO3{$On}") endEvent endState state CHECK_MAGIC_MENU ; SLIDER event OnSelectST() bool newVal = !SKI_MainInstance.MagicMenuCheckEnabled SKI_MainInstance.MagicMenuCheckEnabled = newVal SetToggleOptionValueST(newVal) endEvent event OnDefaultST() SKI_MainInstance.MagicMenuCheckEnabled = true SetToggleOptionValueST(true) endEvent event OnHighlightST() SetInfoText("$SKI_INFO3{$On}") endEvent endState state CHECK_BARTER_MENU ; SLIDER event OnSelectST() bool newVal = !SKI_MainInstance.BarterMenuCheckEnabled SKI_MainInstance.BarterMenuCheckEnabled = newVal SetToggleOptionValueST(newVal) endEvent event OnDefaultST() SKI_MainInstance.BarterMenuCheckEnabled = true SetToggleOptionValueST(true) endEvent event OnHighlightST() SetInfoText("$SKI_INFO3{$On}") endEvent endState state CHECK_CONTAINER_MENU ; SLIDER event OnSelectST() bool newVal = !SKI_MainInstance.ContainerMenuCheckEnabled SKI_MainInstance.ContainerMenuCheckEnabled = newVal SetToggleOptionValueST(newVal) endEvent event OnDefaultST() SKI_MainInstance.ContainerMenuCheckEnabled = true SetToggleOptionValueST(true) endEvent event OnHighlightST() SetInfoText("$SKI_INFO3{$On}") endEvent endState state CHECK_GIFT_MENU ; SLIDER event OnSelectST() bool newVal = !SKI_MainInstance.GiftMenuCheckEnabled SKI_MainInstance.GiftMenuCheckEnabled = newVal SetToggleOptionValueST(newVal) endEvent event OnDefaultST() SKI_MainInstance.GiftMenuCheckEnabled = true SetToggleOptionValueST(true) endEvent event OnHighlightST() SetInfoText("$SKI_INFO3{$On}") endEvent endState state CHECK_MAP_MENU ; SLIDER event OnSelectST() bool newVal = !SKI_MainInstance.MapMenuCheckEnabled SKI_MainInstance.MapMenuCheckEnabled = newVal SetToggleOptionValueST(newVal) endEvent event OnDefaultST() SKI_MainInstance.MapMenuCheckEnabled = true SetToggleOptionValueST(true) endEvent event OnHighlightST() SetInfoText("$SKI_INFO3{$On}") endEvent endState state CHECK_FAVORITES_MENU ; SLIDER event OnSelectST() bool newVal = !SKI_MainInstance.FavoritesMenuCheckEnabled SKI_MainInstance.FavoritesMenuCheckEnabled = newVal SetToggleOptionValueST(newVal) endEvent event OnDefaultST() SKI_MainInstance.FavoritesMenuCheckEnabled = true SetToggleOptionValueST(true) endEvent event OnHighlightST() SetInfoText("$SKI_INFO3{$On}") endEvent endState state CHECK_CRAFTING_MENU ; SLIDER event OnSelectST() bool newVal = !SKI_MainInstance.CraftingMenuCheckEnabled SKI_MainInstance.CraftingMenuCheckEnabled = newVal SetToggleOptionValueST(newVal) endEvent event OnDefaultST() SKI_MainInstance.CraftingMenuCheckEnabled = true SetToggleOptionValueST(true) endEvent event OnHighlightST() SetInfoText("$SKI_INFO3{$On}") endEvent endState ; FUNCTIONS --------------------------------------------------------------------------------------- ; @interface string function GetCustomControl(int a_keyCode) int[] groupHotkeys = SKI_FavoritesManagerInstance.GetGroupHotkeys() int index = groupHotkeys.Find(a_keyCode) if (index != -1) return ("Group " + (index+1)) endIf return "" endFunction function ApplySettings() ; Apply settings that aren't handled by SKI_SettingsManagerInstance _fInventory3DItemPosXWide = Utility.GetINIFloat("fInventory3DItemPosXWide:Interface") _fInventory3DItemPosX = Utility.GetINIFloat("fInventory3DItemPosX:Interface") _fMagic3DItemPosXWide = Utility.GetINIFloat("fMagic3DItemPosXWide:Interface") _fMagic3DItemPosX = Utility.GetINIFloat("fMagic3DItemPosX:Interface") _fInventory3DItemPosZWide = Utility.GetINIFloat("fInventory3DItemPosZWide:Interface") _fInventory3DItemPosZ = Utility.GetINIFloat("fInventory3DItemPosZ:Interface") _fMagic3DItemPosZWide = Utility.GetINIFloat("fMagic3DItemPosZWide:Interface") _fMagic3DItemPosZ = Utility.GetINIFloat("fMagic3DItemPosZ:Interface") _fInventory3DItemPosScaleWide = Utility.GetINIFloat("fInventory3DItemPosScaleWide:Interface") _fMagic3DItemPosScaleWide = Utility.GetINIFloat("fMagic3DItemPosScaleWide:Interface") _fInventory3DItemPosScale = Utility.GetINIFloat("fInventory3DItemPosScale:Interface") _fMagic3DItemPosScale = Utility.GetINIFloat("fMagic3DItemPosScale:Interface") float h = Utility.GetINIInt("iSize H:Display") float w = Utility.GetINIInt("iSize W:Display") float ar = w / h ; Widescreen if (ar == 1.6) ; 16:10, 1920×1200 _itemXBaseW = -32.458335876465 else _itemXBaseW = -29.122497558594 endIf ; Non-widescreen if (ar == 1.25) ; 5:4, 1280x1024 _itemXBase = -41.622497558594 else _itemXBase = -39.122497558594 endIf Apply3DItemXOffset() Apply3DItemYOffset() Apply3DItemScale() endFunction function ApplyItemListFontSize() ; Small if (_itemlistFontSizeIdx == 0) SKI_SettingsManagerInstance.SetOverride("ListLayout$defaults$label$textFormat$size", "12") SKI_SettingsManagerInstance.SetOverride("ListLayout$defaults$entry$textFormat$size", "13") SKI_SettingsManagerInstance.SetOverride("ListLayout$vars$n_iconSize$value", "16") SKI_SettingsManagerInstance.SetOverride("ListLayout$vars$a_textBorder$value", "<0, 0, 0.3, 0>") SKI_SettingsManagerInstance.SetOverride("ListLayout$columns$equipColumn$indent", "-25") SKI_SettingsManagerInstance.SetOverride("ListLayout$columns$equipColumn$border", "<0, 10, 2, 2>") SKI_SettingsManagerInstance.SetOverride("ListLayout$columns$iconColumn$border", "<0, 3, 2, 2>") ; Medium elseIf (_itemlistFontSizeIdx == 1) SKI_SettingsManagerInstance.SetOverride("ListLayout$defaults$label$textFormat$size", "12") SKI_SettingsManagerInstance.SetOverride("ListLayout$defaults$entry$textFormat$size", "14") SKI_SettingsManagerInstance.SetOverride("ListLayout$vars$n_iconSize$value", "18") SKI_SettingsManagerInstance.SetOverride("ListLayout$vars$a_textBorder$value", "<0, 0, 1.1, 0>") SKI_SettingsManagerInstance.SetOverride("ListLayout$columns$equipColumn$indent", "-28") SKI_SettingsManagerInstance.SetOverride("ListLayout$columns$equipColumn$border", "<0, 10, 3, 3>") SKI_SettingsManagerInstance.SetOverride("ListLayout$columns$iconColumn$border", "<0, 3, 3, 3>") ; Large else SKI_SettingsManagerInstance.SetOverride("ListLayout$defaults$label$textFormat$size", "14") SKI_SettingsManagerInstance.SetOverride("ListLayout$defaults$entry$textFormat$size", "18") SKI_SettingsManagerInstance.SetOverride("ListLayout$vars$n_iconSize$value", "20") SKI_SettingsManagerInstance.SetOverride("ListLayout$vars$a_textBorder$value", "<0, 0, 0.4, 0>") SKI_SettingsManagerInstance.SetOverride("ListLayout$columns$equipColumn$indent", "-30") SKI_SettingsManagerInstance.SetOverride("ListLayout$columns$equipColumn$border", "<0, 10, 3.2, 3.2>") SKI_SettingsManagerInstance.SetOverride("ListLayout$columns$iconColumn$border", "<0, 4, 3.2, 3.2>") endIf endFunction function Apply3DItemXOffset() ; Negative values shift the 3D item to the right if (_3DItemDisablePositioning) Utility.SetINIFloat("fInventory3DItemPosXWide:Interface", _fInventory3DItemPosXWide) Utility.SetINIFloat("fInventory3DItemPosX:Interface", _fInventory3DItemPosX) Utility.SetINIFloat("fMagic3DItemPosXWide:Interface", _fMagic3DItemPosXWide) Utility.SetINIFloat("fMagic3DItemPosX:Interface", _fMagic3DItemPosX) else Utility.SetINIFloat("fInventory3DItemPosXWide:Interface", (_itemXBaseW + _3DItemXOffset)) Utility.SetINIFloat("fInventory3DItemPosX:Interface", (_itemXBase + _3DItemXOffset)) Utility.SetINIFloat("fMagic3DItemPosXWide:Interface", (_itemXBaseW + _3DItemXOffset)) Utility.SetINIFloat("fMagic3DItemPosX:Interface", (_itemXBase + _3DItemXOffset)) endIf endFunction function Apply3DItemYOffset() ; Negative values shift the 3D item to the bottom if (_3DItemDisablePositioning) Utility.SetINIFloat("fInventory3DItemPosZWide:Interface", _fInventory3DItemPosZWide) Utility.SetINIFloat("fInventory3DItemPosZ:Interface", _fInventory3DItemPosZ) Utility.SetINIFloat("fMagic3DItemPosZWide:Interface", _fMagic3DItemPosZWide) Utility.SetINIFloat("fMagic3DItemPosZ:Interface", _fMagic3DItemPosZ) else Utility.SetINIFloat("fInventory3DItemPosZWide:Interface", (12 + _3DItemYOffset)) Utility.SetINIFloat("fInventory3DItemPosZ:Interface", (16 + _3DItemYOffset)) Utility.SetINIFloat("fMagic3DItemPosZWide:Interface", (12 + _3DItemYOffset)) Utility.SetINIFloat("fMagic3DItemPosZ:Interface", (16 + _3DItemYOffset)) endIf endFunction function Apply3DItemScale() if (_3DItemDisablePositioning) Utility.SetINIFloat("fInventory3DItemPosScaleWide:Interface", _fInventory3DItemPosScaleWide) Utility.SetINIFloat("fMagic3DItemPosScaleWide:Interface", _fMagic3DItemPosScaleWide) Utility.SetINIFloat("fInventory3DItemPosScale:Interface", _fInventory3DItemPosScale) Utility.SetINIFloat("fMagic3DItemPosScale:Interface", _fMagic3DItemPosScale) else Utility.SetINIFloat("fInventory3DItemPosScaleWide:Interface", _3DItemScale) Utility.SetINIFloat("fMagic3DItemPosScaleWide:Interface", _3DItemScale) Utility.SetINIFloat("fInventory3DItemPosScale:Interface", _3DItemScale) Utility.SetINIFloat("fMagic3DItemPosScale:Interface", _3DItemScale) endIf endFunction bool function ValidateKey(int a_keyCode, bool a_gamepad) ; Do nothing for ESC if (a_keyCode == 1) return false endIf bool isGamepad = Game.UsingGamepad() if (isGamepad != a_gamepad) return false endIf if (!isGamepad) ; Can't detect for mouse, don't need for gamepad if (a_keyCode > 255) ShowMessage("$SKI_MSG1", false, "$OK") return false endIf else ; If you removed the gamepad while in this menu, ignore other keys if (a_keyCode < 266) return false endIf endIf return true endFunction function SwapItemListKey(int a_newKey, int a_curKey) if (a_newKey == _searchKey) _searchKey = a_curKey SetKeyMapOptionValueST(_searchKey, true, "SEARCH_KEY") SKI_SettingsManagerInstance.SetOverride("Input$controls$pc$search", _searchKey) elseIf (a_newKey == _switchTabKey) _switchTabKey = a_curKey SetKeyMapOptionValueST(_switchTabKey, true, "SWITCH_TAB_KEY") SKI_SettingsManagerInstance.SetOverride("Input$controls$pc$switchTab", _switchTabKey) elseIf (a_newKey == _equipModeKey) _equipModeKey = a_curKey SetKeyMapOptionValueST(_equipModeKey, true, "EQUIP_MODE_KEY") SKI_SettingsManagerInstance.SetOverride("Input$controls$pc$equipMode", _equipModeKey) elseIf (a_newKey == _switchTabButton) _switchTabButton = a_curKey SetKeyMapOptionValueST(_switchTabButton, true, "SWITCH_TAB_BUTTON") SKI_SettingsManagerInstance.SetOverride("Input$controls$gamepad$switchTab", _switchTabButton) elseIf (a_newKey == _prevColumnButton) _prevColumnButton = a_curKey SetKeyMapOptionValueST(_prevColumnButton, true, "PREV_COLUMN_BUTTON") SKI_SettingsManagerInstance.SetOverride("Input$controls$gamepad$prevColumn", _prevColumnButton) elseIf (a_newKey == _nextColumnButton) _nextColumnButton = a_curKey SetKeyMapOptionValueST(_nextColumnButton, true, "NEXT_COLUMN_BUTTON") SKI_SettingsManagerInstance.SetOverride("Input$controls$gamepad$nextColumn", _nextColumnButton) elseIf (a_newKey == _sortOrderButton) _sortOrderButton = a_curKey SetKeyMapOptionValueST(_sortOrderButton, true, "SORT_ORDER_BUTTON") SKI_SettingsManagerInstance.SetOverride("Input$controls$gamepad$sortOrder", _sortOrderButton) endIf endFunction function SetCurrentFavoriteGroup(int a_index) int ARMOR_FLAG = SKI_FavoritesManagerInstance.GROUP_FLAG_UNEQUIP_ARMOR int HANDS_FLAG = SKI_FavoritesManagerInstance.GROUP_FLAG_UNEQUIP_HANDS SetToggleOptionValueST(SKI_FavoritesManagerInstance.GetGroupFlag(_favCurGroupIdx, ARMOR_FLAG), true, "FAV_GROUP_UNEQUIP_ARMOR") SetToggleOptionValueST(SKI_FavoritesManagerInstance.GetGroupFlag(_favCurGroupIdx, HANDS_FLAG), true, "FAV_GROUP_UNEQUIP_HANDS") endFunction function SetFavoritesGroupHotkey(int a_groupIndex, int a_keyCode, string a_conflictControl = "", string a_conflictName = "") bool continue = true if (a_conflictControl != "" && a_conflictName != ModName) string msg if (a_conflictName != "") msg = "$SKI_MSG2{" + a_conflictControl + " (" + a_conflictName + ")}" else msg = "$SKI_MSG2{" + a_conflictControl + "}" endIf continue = ShowMessage(msg, true, "$Yes", "$No") endIf if (!continue) return endIf if (!SKI_FavoritesManagerInstance.SetGroupHotkey(a_groupIndex, a_keyCode)) return endIf ; Update int[] groupHotkeys = SKI_FavoritesManagerInstance.GetGroupHotkeys() SetKeyMapOptionValueST(groupHotkeys[0], true, "FAV_GROUP_USE_HOTKEY1") SetKeyMapOptionValueST(groupHotkeys[1], true, "FAV_GROUP_USE_HOTKEY2") SetKeyMapOptionValueST(groupHotkeys[2], true, "FAV_GROUP_USE_HOTKEY3") SetKeyMapOptionValueST(groupHotkeys[3], true, "FAV_GROUP_USE_HOTKEY4") SetKeyMapOptionValueST(groupHotkeys[4], true, "FAV_GROUP_USE_HOTKEY5") SetKeyMapOptionValueST(groupHotkeys[5], true, "FAV_GROUP_USE_HOTKEY6") SetKeyMapOptionValueST(groupHotkeys[6], true, "FAV_GROUP_USE_HOTKEY7") SetKeyMapOptionValueST(groupHotkeys[7], false, "FAV_GROUP_USE_HOTKEY8") endFunction function RefreshFavoriteHotkeys() SetKeyMapOptionValueST(SKI_FavoritesManagerInstance.GroupAddKey, true, "FAV_GROUP_ADD_KEY") SetKeyMapOptionValueST(SKI_FavoritesManagerInstance.GroupUseKey, true, "FAV_GROUP_USE_KEY") SetKeyMapOptionValueST(SKI_FavoritesManagerInstance.SetIconKey, true, "FAV_SET_ICON_KEY") SetKeyMapOptionValueST(SKI_FavoritesManagerInstance.ToggleFocusKey, true, "FAV_TOGGLE_FOCUS") SetKeyMapOptionValueST(SKI_FavoritesManagerInstance.SaveEquipStateKey, false, "FAV_EQUIP_STATE_KEY") endFunction ; REMOVED DATA ----------------------------------------------------------------------------------- ; -- Version 1 -- ; (remove version) ; int _itemlistFontSizeOID_T ; (4) ; int _itemlistQuantityMinCountOID_S ; (4) ; int _itemcardAlignOID_T ; (4) ; int _itemcardXOffsetOID_S ; (4) ; int _itemcardYOffsetOID_S ; (4) ; int _3DItemXOffsetOID_S ; (4) ; int _3DItemYOffsetOID_S ; (4) ; int _3DItemScaleOID_S ; (4) ; int _checkInventoryMenuOID_B ; (4) ; int _checkMagicMenuOID_B ; (4) ; int _checkBarterMenuOID_B ; (4) ; int _checkContainerMenuOID_B ; (4) ; int _checkGiftMenuOID_B ; (4) ; int _searchKeyOID_K ; (4) ; int _switchTabKeyOID_K ; (4) ; int _equipModeKeyOID_K ; (4) ; -- Version 2 -- ; int _itemlistCategoryIconThemeOID_M ; (4) ; int _itemlistNoIconColorsOID_B ; (4) ; int _switchTabButtonOID_K ; (4) ; int _prevColumnButtonOID_K ; (4) ; int _nextColumnButtonOID_K ; (4) ; int _sortOrderButtonOID_K ; (4) ; -- Version 3 -- ; int _3DItemDisablePositioningOID_B ; (4) ================================================ FILE: dist/Data/Scripts/Source/SKI_FavoritesManager.psc ================================================ scriptname SKI_FavoritesManager extends SKI_QuestBase import Math ; SCRIPT VERSION ---------------------------------------------------------------------------------- ; ; History ; ; 1: - Initial version ; ; 2: - Added check for vampire lord ; ; 3: - Less eagerly clearing of invalid entries int function GetVersion() return 3 endFunction ; CONSTANTS --------------------------------------------------------------------------------------- string property FAVORITES_MENU = "FavoritesMenu" autoReadonly string property MENU_ROOT = "_root.MenuHolder.Menu_mc" autoReadonly int property GROUP_FLAG_UNEQUIP_ARMOR = 1 autoReadonly int property GROUP_FLAG_UNEQUIP_HANDS = 2 autoReadonly ; PROPERTIES -------------------------------------------------------------------------------------- ; -- Version 1 -- Actor Property PlayerREF auto bool property ButtonHelpEnabled = true auto int property GroupAddKey int function get() return _groupAddKey endFunction function set(int a_val) SwapControlKey(a_val, _groupAddKey) _groupAddKey = a_val endFunction endProperty int property GroupUseKey int function get() return _groupUseKey endFunction function set(int a_val) SwapControlKey(a_val, _groupUseKey) _groupUseKey = a_val endFunction endProperty int property SetIconKey int function get() return _setIconKey endFunction function set(int a_val) SwapControlKey(a_val, _setIconKey) _setIconKey = a_val endFunction endProperty int property SaveEquipStateKey int function get() return _saveEquipStateKey endFunction function set(int a_val) SwapControlKey(a_val, _saveEquipStateKey) _saveEquipStateKey = a_val endFunction endProperty int property ToggleFocusKey int function get() return _toggleFocusKey endFunction function set(int a_val) SwapControlKey(a_val, _toggleFocusKey) _toggleFocusKey = a_val endFunction endProperty ; PRIVATE VARIABLES ------------------------------------------------------------------------------- ; -- Version 1 -- Form[] _items1 Form[] _items2 int[] _itemIds1 int[] _itemIds2 int[] _groupFlags Form[] _groupMainHandItems int[] _groupMainHandItemIds Form[] _groupOffHandItems int[] _groupOffHandItemIds Form[] _groupIconItems int[] _groupIconItemIds bool _silenceEquipSounds = false SoundCategory _audioCategoryUI ; Forms to support EquipSlot comparisons EquipSlot _rightHandSlot EquipSlot _eitherHandSlot EquipSlot _leftHandSlot EquipSlot _bothHandsSlot EquipSlot _voiceSlot ; State variables for Group Use bool _usedRightHand = false bool _usedLeftHand = false bool _usedVoice = false int _usedOutfitMask = 0 ; Keys int _groupAddKey = 33 ; F int _groupUseKey = 19 ; R int _setIconKey = 56 ; LAlt int _saveEquipStateKey = 20 ; T int _toggleFocusKey = 57 ; Space int[] _groupHotkeys ; -- Version 2 -- Race _vampireLordRace ; -- Version 3 -- bool[] _itemInvalidFlags1 bool[] _itemInvalidFlags2 ; INITIALIZATION ---------------------------------------------------------------------------------- event OnInit() _items1 = new Form[128] _items2 = new Form[128] _itemIds1 = new int[128] _itemIds2 = new int[128] _groupFlags = new int[8] _groupMainHandItems = new Form[8] _groupMainHandItemIds = new int[8] _groupOffHandItems = new Form[8] _groupOffHandItemIds = new int[8] _groupIconItems = new Form[8] _groupIconItemIds = new int[8] _groupHotkeys = new int[8] _groupHotkeys[0] = 59 ; F1 _groupHotkeys[1] = 60 ; F2 _groupHotkeys[2] = 61 ; F3 _groupHotkeys[3] = 62 ; F4 _groupHotkeys[4] = -1 _groupHotkeys[5] = -1 _groupHotkeys[6] = -1 _groupHotkeys[7] = -1 _audioCategoryUI = Game.GetFormFromFile(0x00064451, "Skyrim.esm") as SoundCategory _rightHandSlot = Game.GetFormFromFile(0x00013f42, "Skyrim.esm") as EquipSlot _leftHandSlot = Game.GetFormFromFile(0x00013f43, "Skyrim.esm") as EquipSlot _eitherHandSlot = Game.GetFormFromFile(0x00013f44, "Skyrim.esm") as EquipSlot _bothHandsSlot = Game.GetFormFromFile(0x00013f45, "Skyrim.esm") as EquipSlot _voiceSlot = Game.GetFormFromFile(0x00025bee, "Skyrim.esm") as EquipSlot OnGameReload() endEvent ; @implements SKI_QuestBase event OnGameReload() CheckVersion() RegisterForModEvent("SKIFM_groupAdd", "OnGroupAdd") RegisterForModEvent("SKIFM_groupRemove", "OnGroupRemove") RegisterForModEvent("SKIFM_groupUse", "OnGroupUse") RegisterForModEvent("SKIFM_saveEquipState", "OnSaveEquipState") RegisterForModEvent("SKIFM_setGroupIcon", "OnSetGroupIcon") RegisterForModEvent("SKIFM_foundInvalidItem", "OnFoundInvalidItem") RegisterForMenu(FAVORITES_MENU) RegisterHotkeys() CleanUp() endEvent ; @implements SKI_QuestBase event OnVersionUpdate(int a_version) ; Version 2 if (a_version >= 2 && CurrentVersion < 2) Debug.Trace(self + ": Updating to script version 2") _vampireLordRace = Game.GetFormFromFile(0x0000283A, "Dawnguard.esm") as Race endIf ; Version 3 if (a_version >= 3 && CurrentVersion < 3) Debug.Trace(self + ": Updating to script version 3") _itemInvalidFlags1 = new bool[128] _itemInvalidFlags2 = new bool[128] endIf endEvent ; EVENTS ------------------------------------------------------------------------------------------ event OnMenuOpen(string a_menuName) int i = 0 while (i < 128) _itemInvalidFlags1[i] = false i += 1 endWhile i = 0 while (i < 128) _itemInvalidFlags2[i] = false i += 1 endWhile InitControls() InitMenuGroupData() endEvent event OnFoundInvalidItem(string a_eventName, string a_strArg, float a_numArg, Form a_sender) InvalidateItem(a_strArg as int,true) endEvent event OnGroupAdd(string a_eventName, string a_strArg, float a_numArg, Form a_sender) int groupIndex = a_numArg as int int itemId = a_strArg as int Form item = a_sender if (GroupAdd(groupIndex, itemId, item)) UpdateMenuGroupData(groupIndex) else UI.InvokeBool(FAVORITES_MENU, MENU_ROOT + ".unlock", true) Debug.Notification("Group full!") endIf endEvent event OnGroupRemove(string a_eventName, string a_strArg, float a_numArg, Form a_sender) int groupIndex = a_numArg as int int itemId = a_strArg as int if (GroupRemove(groupIndex, itemId)) UpdateMenuGroupData(groupIndex) else UI.InvokeBool(FAVORITES_MENU, MENU_ROOT + ".unlock", true) endIf endEvent ; Read the player's current equipment and save it to the target group event OnSaveEquipState(string a_eventName, string a_strArg, float a_numArg, Form a_sender) int groupIndex = a_numArg as int int mainHandItemId = UI.GetInt(FAVORITES_MENU, MENU_ROOT + ".rightHandItemId") int offHandItemId = UI.GetInt(FAVORITES_MENU, MENU_ROOT + ".leftHandItemId") form mainHandForm = GetFormFromItemId(groupIndex,mainHandItemId) ; will return none if not in group if (mainHandForm) _groupMainHandItemIds[groupIndex] = mainHandItemId _groupMainHandItems[groupIndex] = mainHandForm else _groupMainHandItemIds[groupIndex] = 0 _groupMainHandItems[groupIndex] = none endIf form offHandForm = GetFormFromItemId(groupIndex,offHandItemId) if (offHandForm) _groupOffHandItemIds[groupIndex] = offHandItemId _groupOffHandItems[groupIndex] = offHandForm else _groupOffHandItemIds[groupIndex] = 0 _groupOffHandItems[groupIndex] = none endIf UpdateMenuGroupData(groupIndex) endEvent ; This will set a form as the icon form for a group event OnSetGroupIcon(string a_eventName, string a_strArg, float a_numArg, Form a_sender) int groupIndex = a_numArg as int int itemId = a_strArg as int Form item = a_sender _groupIconItems[groupIndex] = item _groupIconItemIds[groupIndex] = itemId UpdateMenuGroupData(groupIndex) endEvent event OnGroupUse(string a_eventName, string a_strArg, float a_numArg, Form a_sender) gotoState("PROCESSING") GroupUse(a_numArg as int) gotoState("") endEvent event OnKeyDown(int a_keyCode) gotoState("PROCESSING") int groupIndex = _groupHotkeys.Find(a_keyCode) if (groupIndex != -1 && !Utility.IsInMenuMode()) GroupUse(groupIndex) endIf gotoState("") endEvent state PROCESSING event OnGroupUse(string a_eventName, string a_strArg, float a_numArg, Form a_sender) endEvent event OnKeyDown(int a_keyCode) endEvent endState ; FUNCTIONS --------------------------------------------------------------------------------------- ;get whether a flag is set for the specified group bool function GetGroupFlag(int a_groupIndex, int a_flag) return LogicalAnd(_groupFlags[a_groupIndex], a_flag) as bool endFunction ;set a flag for the specified group function SetGroupFlag(int a_groupIndex, int a_flag, bool a_value) if (a_value) _groupFlags[a_groupIndex] = LogicalOr(_groupFlags[a_groupIndex], a_flag) else _groupFlags[a_groupIndex] = LogicalAnd(_groupFlags[a_groupIndex], LogicalNot(a_flag)) endIf endFunction int[] function GetGroupHotkeys() ; Return a copy int[] result = new int[8] int i = 0 while (i<8) result[i] = _groupHotkeys[i] i += 1 endWhile return result endFunction bool function SetGroupHotkey(int a_groupIndex, int a_keycode) ; Special case for unmap if (a_keycode == -1) _groupHotkeys[a_groupIndex] = -1 UnregisterForKey(oldKeycode) return true endIf ; Old group index this keycode was bound to int oldIndex = _groupHotkeys.Find(a_keycode) ; Old keycode at the target position int oldKeycode = _groupHotkeys[a_groupIndex] ; Already assigned, no need to do anything if (oldIndex == a_groupIndex) return false endIf ; Swap if (oldIndex != -1 && oldKeycode != -1) _groupHotkeys[oldIndex] = oldKeycode else ; Unset previous group this key was assigned to if (oldIndex != -1) _groupHotkeys[oldIndex] = -1 endIf ; If we replaced a key, unregister it if (oldKeycode != -1) UnregisterForKey(oldKeycode) endIf RegisterForKey(a_keycode) endIf _groupHotkeys[a_groupIndex] = a_keycode return true endFunction ; Send the group data to the UI, so that when the user selects a group, it can filter its entries. function InitControls() int[] args = new int[6] args[0] = ButtonHelpEnabled as int args[1] = _groupAddKey args[2] = _groupUseKey args[3] = _setIconKey args[4] = _saveEquipStateKey args[5] = _toggleFocusKey UI.InvokeIntA(FAVORITES_MENU, MENU_ROOT + ".initControls", args) endFunction ; Send the group data to the UI, so that when the user selects a group, it can filter its entries. function InitMenuGroupData() ; Don't send group data if vampire lord if (_vampireLordRace == PlayerRef.GetRace()) return endIf ; groupCount, mainHandFormId[8], offHandFormId[8], iconFormId[8] int[] args = new int[25] args[0] = 8 int c = 1 int i = 0 while (i<8) args[c] = _groupMainHandItemIds[i] i += 1 c += 1 endWhile i = 0 while (i<8) args[c] = _groupOffHandItemIds[i] i += 1 c += 1 endWhile i = 0 while (i<8) args[c] = _groupIconItemIds[i] i += 1 c += 1 endWhile UI.InvokeIntA(FAVORITES_MENU, MENU_ROOT + ".pushGroupItems", _itemIds1) UI.InvokeIntA(FAVORITES_MENU, MENU_ROOT + ".pushGroupItems", _itemIds2) UI.InvokeIntA(FAVORITES_MENU, MENU_ROOT + ".finishGroupData", args) endFunction function UpdateMenuGroupData(int a_groupIndex) int offset = 32 * a_groupIndex int[] itemIds if (offset >= 128) offset -= 128 itemIds = _itemIds2 else itemIds = _itemIds1 endIf ; groupIndex, mainHandItemId, offHandItemID, iconItemId, itemIds[32] int[] args = new int[36] args[0] = a_groupIndex args[1] = _groupMainHandItemIds[a_groupIndex] args[2] = _groupOffHandItemIds[a_groupIndex] args[3] = _groupIconItemIds[a_groupIndex] int i = 4 int j = offset while (i<36) args[i] = itemIds[j] i += 1 j += 1 endWhile ; This also unlocks the menu, so no need to call unlock UI.InvokeIntA(FAVORITES_MENU, MENU_ROOT + ".updateGroupData", args) endFunction ; Ensure that our data is still valid. Might not be the case if a mod was uninstalled function CleanUp() ; Note on thread safety: ; Since we don't manage an explicit group count, items can just be set or unset from multiple threads int i = 0 while (i < _items1.length) if (_items1[i] == none || _items1[i].GetFormID() == 0) _items1[i] = none _itemIds1[i] = 0 endIf i += 1 endWhile i = 0 while (i < _items2.length) if (_items2[i] == none || _items2[i].GetFormID() == 0) _items2[i] = none _itemIds2[i] = 0 endIf i += 1 endWhile endFunction bool function GroupAdd(int a_groupIndex, int a_itemId, Form a_item) int offset = 32 * a_groupIndex ; Select the target set of arrays, adjust offset Form[] items int[] itemIds bool[] itemInvalidFlags if (offset >= 128) offset -= 128 items = _items2 itemIds = _itemIds2 itemInvalidFlags = _itemInvalidFlags2 else items = _items1 itemIds = _itemIds1 itemInvalidFlags = _itemInvalidFlags1 endIf ; Prevent the same itemId being added to a group twice if (IsItemIdInGroup(a_groupIndex,a_itemId)) return true endIf ; Pick next free slot int index = FindFreeIndex(itemIds, itemInvalidFlags, offset) ; No more space in group? if (index == -1) return false endIf ; Store received data items[index] = a_item itemIds[index] = a_itemId itemInvalidFlags[index] = false ; If there's no icon item set yet, use this one if (_groupIconItems[a_groupIndex] == none) _groupIconItems[a_groupIndex] = a_item _groupIconItemIds[a_groupIndex] = a_itemId endIf return true endFunction bool function GroupRemove(int a_groupIndex, int a_itemId) int offset = 32 * a_groupIndex ; Select the target set of arrays, adjust offset Form[] items int[] itemIds bool[] itemInvalidFlags if (offset >= 128) offset -= 128 items = _items2 itemIds = _itemIds2 itemInvalidFlags = _itemInvalidFlags2 else items = _items1 itemIds = _itemIds1 itemInvalidFlags = _itemInvalidFlags1 endIf int i = offset int n = offset+32 while (i < n) if (itemIds[i] == a_itemId) items[i] = none itemIds[i] = 0 itemInvalidFlags[i] = false i = n else i += 1 endIf endWhile if (a_itemId == _groupMainHandItemIds[a_groupIndex]) _groupMainHandItems[a_groupIndex] = none _groupMainHandItemIds[a_groupIndex] = 0 endIf if (a_itemId == _groupOffHandItemIds[a_groupIndex]) _groupOffHandItems[a_groupIndex] = none _groupOffHandItemIds[a_groupIndex] = 0 endIf if (a_itemId == _groupIconItemIds[a_groupIndex]) ReplaceGroupIcon(a_groupIndex) endIf return true endFunction function GroupUse(int a_groupIndex) int offset = 32 * a_groupIndex ; Select the target set of arrays, adjust offset Form[] items int[] itemIds bool[] itemInvalidFlags if (offset >= 128) offset -= 128 items = _items2 itemIds = _itemIds2 itemInvalidFlags = _itemInvalidFlags2 else items = _items1 itemIds = _itemIds1 itemInvalidFlags = _itemInvalidFlags1 endIf ; Reset state _usedRightHand = false _usedLeftHand = false _usedVoice = false _usedOutfitMask = 0 ; These items are equipped later form[] deferredItems = new Form[32] int deferredIdx = 0 ; Encountered invalid items are removed at the end when speed is no longer an issue int[] invalidItemIds = new int[32] int invalidIdx = 0 ; Turn off UI sounds to avoid annoying clicking noise while swapping spells _audioCategoryUI.Mute() ; Unequip hands first? if (GetGroupFlag(a_groupIndex,GROUP_FLAG_UNEQUIP_HANDS)) UnequipHand(0) UnequipHand(1) endIf ; Process main and offhand items ; Left first, to avoid problems when equipping the same weapon twice Form offHandItem = _groupOffHandItems[a_groupIndex] int offHandItemId = _groupOffHandItemIds[a_groupIndex] if (offHandItem) int itemType = offHandItem.GetType() if (IsItemValid(offHandItem, itemType)) ProcessItem(offHandItem, itemType, false, true, offHandItemId) endIf endIf Form mainHandItem = _groupMainHandItems[a_groupIndex] int mainHandItemId = _groupMainHandItemIds[a_groupIndex] if (mainHandItem) int itemType = mainHandItem.GetType() if (IsItemValid(mainHandItem, itemType)) ProcessItem(mainHandItem, itemType, false, false, mainHandItemId) endIf endIf ; Validate & process items int i = offset int n = offset + 32 while (i < n) Form item = items[i] int itemId = itemIds[i] if (item && item != mainHandItem && item != offHandItem && !itemInvalidFlags[i]) int itemType = item.GetType() if (! IsItemValid(item, itemType)) invalidItemIds[invalidIdx] = itemId invalidIdx += 1 elseIf (! ProcessItem(item, itemType, a_itemId = itemId)) deferredItems[deferredIdx] = item deferredIdx += 1 endIf endIf i += 1 endWhile ; Process deferred items i = 0 while (i < deferredIdx) Form item = deferredItems[i] int itemType = item.GetType() ProcessItem(item, itemType, false) i += 1 endWhile ; Unequip any armor not belonging to current outfit mask if (GetGroupFlag(a_groupIndex,GROUP_FLAG_UNEQUIP_ARMOR)) int h = 0x00000001 while (h < 0x80000000) Form wornForm = PlayerREF.GetWornForm(h) if (wornForm) if (!LogicalAND(h, _usedOutfitMask)) PlayerREF.UnEquipItemEX(wornForm) endIf endIf h = LeftShift(h,1) endWhile endIf _audioCategoryUI.UnMute() ; Turn UI sounds back on i = 0 while (i 0 endIf endFunction bool function ProcessItem(Form a_item, int a_itemType, bool a_allowDeferring = true, bool a_offHandOnly = false, int a_itemId = 0) ; WEAPON ------------ if (a_itemType == 41) ; Any weapon needs at least one free hand if (_usedRightHand && _usedLeftHand) return true endIf Weapon itemWeapon = a_item as Weapon int weaponType = itemWeapon.GetweaponType() ; It's one-handed and the player has a free hand if (weaponType <= 4 || weaponType == 8) ; Fists(0), Swords(1), Daggers(2), War Axes(3), Maces(4), Staffs(8) if (!_usedRightHand && !a_offHandOnly) if (a_item == PlayerREF.GetEquippedObject(1) && a_itemId != PlayerREF.GetEquippedItemId(1)) UnequipHand(1) ; avoid damage-related bug when swapping for enhanced item endIf PlayerREF.EquipItemById(itemWeapon, a_itemId, 1, equipSound = _silenceEquipSounds) _usedRightHand = true elseIf (!_usedLeftHand) if (a_item == PlayerREF.GetEquippedObject(0) && a_itemId != PlayerREF.GetEquippedItemId(0)) UnequipHand(0) endIf PlayerREF.EquipItemById(itemWeapon, a_itemId, 2, equipSound = _silenceEquipSounds) _usedLeftHand = true endIf ; It's two-handed and both hands are free elseIf (weaponType > 4 && !_usedRightHand && !_usedLeftHand) if (a_item == PlayerREF.GetEquippedObject(0) && a_itemId != PlayerREF.GetEquippedItemId(0)) UnequipHand(0) endIf PlayerREF.EquipItemById(itemWeapon, a_itemId, equipSlot = 0, equipSound = _silenceEquipSounds) _usedRightHand = true _usedLeftHand = true endIf return true ; ARMOR ------------ elseIf (a_itemType == 26) int slotMask = (a_item as Armor).GetslotMask() ; It's a shield... if (slotMask == 512) if (!_usedLeftHand) PlayerREF.EquipItemById(a_item, a_itemId, equipSlot = 0, equipSound = _silenceEquipSounds) _usedLeftHand = true _usedOutfitMask += slotMask endIf ; It's not a shield, just equip it if slot is free elseIf (! LogicalAnd(_usedOutfitMask,slotMask)) if (a_item == PlayerREF.GetWornForm(slotMask) && a_itemId != PlayerREF.GetWornItemId(slotMask)) PlayerREF.UnequipItemEx(a_item) endIf PlayerREF.EquipItemById(a_item, a_itemId, equipSlot = 0, equipSound = _silenceEquipSounds) _usedOutfitMask += slotMask endIf return true ; AMMO ------------ elseIf (a_itemType == 42) ;kAmmo PlayerREF.EquipItemEX(a_item, equipSlot = 0, equipSound = _silenceEquipSounds) return true ; SPELL ------------ elseIf (a_itemType == 22) Spell itemSpell = a_item as Spell EquipSlot spellEquipSlot = itemSpell.GetEquipType() if (spellEquipSlot != _voiceSlot) ; Any non power spell needs at least one free hand if (_usedRightHand && _usedLeftHand) return true endIf ; spell is eitherhanded if (spellEquipSlot == _eitherHandSlot) if (!_usedRightHand && !a_offHandOnly) PlayerREF.EquipSpell(itemSpell, 1) _usedRightHand = true elseIf (!_usedLeftHand) PlayerREF.EquipSpell(itemSpell, 0) _usedLeftHand = true endIf ; Spell requires two hands ... elseIf (spellEquipSlot == _bothHandsSlot) if (!_usedRightHand && !_usedLeftHand) PlayerREF.EquipSpell(itemSpell, 1) _usedRightHand = true _usedLeftHand = true endIf ; a lot of NPC spells are left-hand only, so if the player is using PSB they'll need this elseIf (spellEquipSlot == _leftHandSlot) if (!_usedLeftHand) PlayerREF.EquipSpell(itemSpell, 0) _usedLeftHand = true endIf endIf else if (!_usedVoice) PlayerREF.EquipSpell(itemSpell, 2) _usedVoice = true endIf endIf return true ; SCROLL ------------ elseIf (a_itemType == 23) Scroll itemScroll = a_item as Scroll ; Any scroll needs at least one free hand if (_usedRightHand && _usedLeftHand) return true endIf ;FIXME - GetEquipType seems to be broken for scrolls ;If (itemScroll.GetEquipType() == _bothHandsSlot && !_usedLeftHand && !_usedRightHand) ; PlayerREF.EquipItemEX(itemScroll, equipSlot = 0, equipSound = _silenceEquipSounds) ; _usedLeftHand = true ; _usedRightHand = true if (!_usedRightHand && !a_offHandOnly) PlayerREF.EquipItemEX(itemScroll, equipSlot = 1, equipSound = _silenceEquipSounds) _usedRightHand = true elseIf (!_usedLeftHand) PlayerREF.EquipItemEX(itemScroll, equipSlot = 2, equipSound = _silenceEquipSounds) _usedLeftHand = true endIf return true ; SHOUT ------------ elseIf (a_itemType == 119) if (!_usedVoice) PlayerREF.EquipShout(a_item as Shout) _usedVoice = true endIf return true ; POTION ------------ elseIf (a_itemType == 46) if ((a_item as Potion).IsHostile()) ; This is a poison and should only be applied after new weapons have been equipped. if (a_allowDeferring) return false endIf ; This will fail if a poisonable weapon is only equipped in the offhand. That's a Skyrim bug, not my bug. PlayerREF.EquipItem(a_item, abSilent = True) return true endiF ; This is a non-hostile potion, food, or... something? and can be used immediately PlayerREF.EquipItem(a_item as Potion, abSilent = True) return true ; INGREDIENT ------------ elseIf (a_itemType == 30) ;kIngredient PlayerREF.EquipItem(a_item as Ingredient, abSilent = True) return true ; LIGHT (TORCH) ------------ elseIf (a_itemType == 31) if (!_usedLeftHand) PlayerREF.EquipItemEX(a_item, equipSlot = 0, equipSound = _silenceEquipSounds) _usedLeftHand = true endIf return true ; MISC ------------ elseIf a_itemType == 32 PlayerREF.EquipItem(a_item, abSilent = True) return true endIf return true endFunction function InvalidateItem(int a_itemId, bool redrawIcon = false) int index ; GroupData index = _itemIds1.Find(a_itemId) if (index != -1) _itemInvalidFlags1[index] = true endIf index = _itemIds2.Find(a_itemId) if (index != -1) _itemInvalidFlags2[index] = true endIf ; Main hand index = _groupMainHandItemIds.Find(a_itemId) if (index != -1) _groupMainHandItems[index] = none _groupMainHandItemIds[index] = 0 endIf ; Off hand index = _groupOffHandItemIds.Find(a_itemId) if (index != -1) _groupOffHandItems[index] = none _groupOffHandItemIds[index] = 0 endIf ; Icon index = _groupIconItemIds.Find(a_itemId) if (index != -1) ReplaceGroupIcon(index) if (redrawIcon) UpdateMenuGroupData(index) endIf endIf endFunction int function FindFreeIndex(int[] a_itemIds, bool[] a_itemInvalidFlags, int offset) int i = a_itemIds.Find(0,offset) ; First try to find an entry that is 0 if (i >= offset && i < offset + 32) return i endIf ; Failed. Now try to claim an entry flagged as invalid. i = offset int n = offset + 32 while (i < n) if (a_itemInvalidFlags[i]) return i endIf i += 1 endWhile return -1 endFunction function ReplaceGroupIcon(int a_groupIndex) ; If player has MH or OH set for the group, use it first if (_groupMainHandItemIds[a_groupIndex]) _groupIconItems[a_groupIndex] = _groupMainHandItems[a_groupIndex] _groupIconItemIds[a_groupIndex] = _groupMainHandItemIds[a_groupIndex] return elseIf (_groupOffHandItemIds[a_groupIndex]) _groupIconItems[a_groupIndex] = _groupOffHandItems[a_groupIndex] _groupIconItemIds[a_groupIndex] = _groupOffHandItemIds[a_groupIndex] return endIf int offset = a_groupIndex * 32 ; Select the target set of arrays, adjust offset Form[] items int[] itemIds bool[] itemInvalidFlags if (offset >= 128) offset -= 128 items = _items2 itemIds = _itemIds2 itemInvalidFlags = _itemInvalidFlags2 else items = _items1 itemIds = _itemIds1 itemInvalidFlags = _itemInvalidFlags1 endIf int i = offset int n = offset+32 ; Use icon of first found item while (i < n) if (items[i] != none && !itemInvalidFlags[i]) _groupIconItems[a_groupIndex] = items[i] _groupIconItemIds[a_groupIndex] = itemIds[i] return else i += 1 endIf endWhile _groupIconItems[a_groupIndex] = none _groupIconItemIds[a_groupIndex] = 0 endFunction ; utility function to see if form is in the specified group. bool function IsFormInGroup(int a_groupIndex, form a_item) int offset = 32 * a_groupIndex ; Select the target set of arrays, adjust offset Form[] items if (offset >= 128) offset -= 128 items = _items2 else items = _items1 endIf int i = items.Find(a_item,offset) if (i >= offset && i < offset+32) return true endIf return false endFunction ; utility function to see how many of the form are in a group int function GetNumFormsInGroup(int a_groupIndex,form a_item) int offset = 32 * a_groupIndex ; Select the target set of arrays, adjust offset form[] items if (offset >= 128) offset -= 128 items = _items2 else items = _items1 endIf int i = offset int n = offset + 32 int count while (i < n) if (items[i] == a_item) count += 1 endIf i += 1 endWhile return count endFunction form function GetFormFromItemId(int a_groupIndex,int itemId) int offset = 32 * a_groupIndex ; Select the target set of arrays, adjust offset form[] items int[] itemIds if (offset >= 128) offset -= 128 items = _items2 itemIds = _itemIds2 else items = _items1 itemIds = _itemIds1 endIf int i = itemIds.Find(itemId,offset) if (i >= offset && i < offset + 32) return items[i] else return none endIf endFunction ; return the Nth itemId int function GetNthItemIdInGroup(int a_groupIndex,form a_item,int a_num = 1) int offset = 32 * a_groupIndex ; Select the target set of arrays, adjust offset form[] items int[] itemIds if (offset >= 128) offset -= 128 items = _items2 itemIds = _itemIds2 else items = _items1 itemIds = _itemIds1 endIf int i = offset int n = offset + 32 int count = 0 int result = offset while (result >= offset && result < n && count < a_num) result = items.Find(a_item,i) i = result + 1 count += 1 endWhile if (result >= offset && result < n) return itemIds[result] endIf return 0 endFunction ; utility function to see if itemId is in the specified group. bool function IsItemIdInGroup(int a_groupIndex, int a_itemId) int offset = 32 * a_groupIndex ; Select the target set of arrays, adjust offset int[] itemIds if (offset >= 128) offset -= 128 itemIds = _itemIds2 else itemIds = _itemIds1 endIf int i = itemIds.Find(a_itemId,offset) if (i >= offset && i < offset+32) return true endIf return false endFunction function RegisterHotkeys() int i = 0 while (i < _groupHotkeys.Length) if (_groupHotkeys[i] != -1) RegisterForKey(_groupHotkeys[i]) endIf i += 1 endWhile endFunction function SwapControlKey(int a_newKey, int a_curKey) if (a_newKey == _groupAddKey) _groupAddKey = a_curKey elseIf (a_newKey == _groupUseKey) _groupUseKey = a_curKey elseIf (a_newKey == _setIconKey) _setIconKey = a_curKey elseIf (a_newKey == _saveEquipStateKey) _saveEquipStateKey = a_curKey elseIf (a_newKey == _toggleFocusKey) _toggleFocusKey = a_curKey endIf endFunction ; DEBUG ------------------------------------------------------------------------------------------ function PrintGroupItems(int a_groupIndex) ;This is here so I can see what's in the group, because the UI is currently broken Debug.Trace("PrintGroupItems called on group " + a_groupIndex) int offset = 32 * a_groupIndex ; Select the target set of arrays, adjust offset Form[] items int[] itemIds if (offset >= 128) offset -= 128 items = _items2 itemIds = _itemIds2 else items = _items1 itemIds = _itemIds1 endIf int i = offset int n = offset + 32 while (i < n) if (items[i]) Debug.Trace(i + " is " + itemIds[i] + ", form is " + items[i] + ": " + items[i].GetName()) endIf i += 1 endWhile if (_groupIconItemIds[a_groupIndex]) Debug.Trace("Group icon is " + _groupIconItemIds[a_groupIndex] + ", form is " + _groupIconItems[a_groupIndex] + ": " + _groupIconItems[a_groupIndex].GetName()) endIf if (_groupMainHandItemIds[a_groupIndex]) Debug.Trace("Group MH is " + _groupMainHandItemIds[a_groupIndex] + ", form is " + _groupMainHandItems[a_groupIndex] + ": " + _groupMainHandItems[a_groupIndex].GetName()) endIf if (_groupOffHandItemIds[a_groupIndex]) Debug.Trace("Group OH is " + _groupOffHandItemIds[a_groupIndex] + ", form is " + _groupOffHandItems[a_groupIndex] + ": " + _groupOffHandItems[a_groupIndex].GetName()) endIf endFunction ================================================ FILE: dist/Data/Scripts/Source/SKI_Main.psc ================================================ scriptname SKI_Main extends SKI_QuestBase ; CONSTANTS --------------------------------------------------------------------------------------- string property HUD_MENU = "HUD Menu" autoReadOnly string property INVENTORY_MENU = "InventoryMenu" autoReadonly string property MAGIC_MENU = "MagicMenu" autoReadonly string property CONTAINER_MENU = "ContainerMenu" autoReadonly string property BARTER_MENU = "BarterMenu" autoReadonly string property GIFT_MENU = "GiftMenu" autoReadonly string property JOURNAL_MENU = "Journal Menu" autoReadonly string property MAP_MENU = "MapMenu" autoReadonly string property FAVORITES_MENU = "FavoritesMenu" autoReadonly string property CRAFTING_MENU = "Crafting Menu" autoReadonly int property ERR_SKSE_MISSING = 1 autoReadonly int property ERR_SKSE_VERSION_RT = 2 autoReadonly int property ERR_SKSE_VERSION_SCPT = 3 autoReadonly int property ERR_INI_PAPYRUS = 4 autoReadonly int property ERR_SWF_INVALID = 5 autoReadonly int property ERR_SWF_VERSION = 6 autoReadonly int property ERR_SKSE_BROKEN = 7 autoReadonly ; PRIVATE VARIABLES ------------------------------------------------------------------------------- bool _inventoryMenuCheckEnabled = true bool _magicMenuCheckEnabled = true bool _barterMenuCheckEnabled = true bool _containerMenuCheckEnabled = true bool _giftMenuCheckEnabled = true bool _mapMenuCheckEnabled = false ;; SkyUI-VR doesn't come with a custom map bool _favoritesMenuCheckEnabled = false ;; SkyUI-VR doesn't come with a custom favorites menu bool _craftingMenuCheckEnabled = true ; PROPERTIES -------------------------------------------------------------------------------------- int property MinSKSERelease = 53 autoReadonly string property MinSKSEVersion = "2.0.10" autoReadonly int property ReqSWFRelease = 2018 autoReadonly string property ReqSWFVersion = "5.2 SE" autoReadonly bool property ErrorDetected = false auto bool property InventoryMenuCheckEnabled bool function get() return _inventoryMenuCheckEnabled endFunction function set(bool a_val) _inventoryMenuCheckEnabled = a_val if (a_val) RegisterForMenu(INVENTORY_MENU) else UnregisterForMenu(INVENTORY_MENU) endIf endFunction endProperty bool property MagicMenuCheckEnabled bool function get() return _magicMenuCheckEnabled endFunction function set(bool a_val) _magicMenuCheckEnabled = a_val if (a_val) RegisterForMenu(MAGIC_MENU) else UnregisterForMenu(MAGIC_MENU) endIf endFunction endProperty bool property BarterMenuCheckEnabled bool function get() return _barterMenuCheckEnabled endFunction function set(bool a_val) _barterMenuCheckEnabled = a_val if (a_val) RegisterForMenu(BARTER_MENU) else UnregisterForMenu(BARTER_MENU) endIf endFunction endProperty bool property ContainerMenuCheckEnabled bool function get() return _containerMenuCheckEnabled endFunction function set(bool a_val) _containerMenuCheckEnabled = a_val if (a_val) RegisterForMenu(CONTAINER_MENU) else UnregisterForMenu(CONTAINER_MENU) endIf endFunction endProperty bool property GiftMenuCheckEnabled bool function get() return _giftMenuCheckEnabled endFunction function set(bool a_val) _giftMenuCheckEnabled = a_val if (a_val) RegisterForMenu(GIFT_MENU) else UnregisterForMenu(GIFT_MENU) endIf endFunction endProperty bool property MapMenuCheckEnabled bool function get() ;; return _mapMenuCheckEnabled return false endFunction function set(bool a_val) ;; _mapMenuCheckEnabled = a_val ;; if (a_val) ;; RegisterForMenu(MAP_MENU) ;; else ;; UnregisterForMenu(MAP_MENU) ;; endIf endFunction endProperty bool property FavoritesMenuCheckEnabled bool function get() ;; return _favoritesMenuCheckEnabled return false endFunction function set(bool a_val) ;; _favoritesMenuCheckEnabled = a_val ;; if (a_val) ;; RegisterForMenu(FAVORITES_MENU) ;; else ;; UnregisterForMenu(FAVORITES_MENU) ;; endIf endFunction endProperty bool property CraftingMenuCheckEnabled bool function get() return _craftingMenuCheckEnabled endFunction function set(bool a_val) _craftingMenuCheckEnabled = a_val if (a_val) RegisterForMenu(CRAFTING_MENU) else UnregisterForMenu(CRAFTING_MENU) endIf endFunction endProperty ; INITIALIZATION ---------------------------------------------------------------------------------- event OnInit() OnGameReload() endEvent ; @implements SKI_QuestBase event OnGameReload() ErrorDetected = false if (SKSE.GetVersionRelease() == 0) Error(ERR_SKSE_MISSING, "The Skyrim Script Extender (SKSEVR) is not running.\nSkyUI will not work correctly!\n\n" \ + "This message may also appear if a new Skyrim Patch has been released. In this case, wait until SKSEVR has been updated, then install the new version.") return elseIf (GetType() == 0) Error(ERR_SKSE_BROKEN, "The SKSEVR scripts have been overwritten or are not properly loaded.\nReinstalling SKSE might fix this.") return elseIf (SKSE.GetVersionRelease() < MinSKSERelease) Error(ERR_SKSE_VERSION_RT, "SKSEVR is outdated.\nSkyUI will not work correctly!\n" \ + "Required version: " + MinSKSEVersion + " or newer\n" \ + "Detected version: " + SKSE.GetVersion() + "." + SKSE.GetVersionMinor() + "." + SKSE.GetVersionBeta()) return elseIf (SKSE.GetScriptVersionRelease() < MinSKSERelease) Error(ERR_SKSE_VERSION_SCPT, "SKSEVR scripts are outdated.\nYou probably forgot to install/update them with the rest of SKSE.\nSkyUI will not work correctly!") return endIf if (Utility.GetINIInt("iMinMemoryPageSize:Papyrus") <= 0 || Utility.GetINIInt("iMaxMemoryPageSize:Papyrus") <= 0 || Utility.GetINIInt("iMaxAllocatedMemoryBytes:Papyrus") <= 0) Error(ERR_INI_PAPYRUS, "Your Papyrus INI settings are invalid. Please fix this, otherwise SkyUI will stop working at some point.") return endIf ; Check menus, when they're opened if (InventoryMenuCheckEnabled) RegisterForMenu(INVENTORY_MENU) endIf if (MagicMenuCheckEnabled) RegisterForMenu(MAGIC_MENU) endIf if (ContainerMenuCheckEnabled) RegisterForMenu(CONTAINER_MENU) endIf if (BarterMenuCheckEnabled) RegisterForMenu(BARTER_MENU) endIf if (GiftMenuCheckEnabled) RegisterForMenu(GIFT_MENU) endIf if (MapMenuCheckEnabled) RegisterForMenu(MAP_MENU) endIf if (FavoritesMenuCheckEnabled) RegisterForMenu(FAVORITES_MENU) endIf if (CraftingMenuCheckEnabled) RegisterForMenu(CRAFTING_MENU) endIf RegisterForMenu(JOURNAL_MENU) endEvent ; EVENTS ------------------------------------------------------------------------------------------ event OnMenuOpen(string a_menuName) if (a_menuName == INVENTORY_MENU) if (CheckMenuVersion("inventorymenu.swf", a_menuName, "_global.InventoryMenu") && \ CheckItemMenuComponents(a_menuName)) ; Only unregister if all checks have been performed (regardless of check result) UnregisterForMenu(a_menuName) endIf elseIf (a_menuName == MAGIC_MENU) if (CheckMenuVersion("magicmenu.swf", a_menuName, "_global.MagicMenu") && \ CheckItemMenuComponents(a_menuName)) UnregisterForMenu(a_menuName) endIf elseIf (a_menuName == CONTAINER_MENU) if (CheckMenuVersion("containermenu.swf", a_menuName, "_global.ContainerMenu") && \ CheckItemMenuComponents(a_menuName)) UnregisterForMenu(a_menuName) endIf elseIf (a_menuName == BARTER_MENU) if (CheckMenuVersion("bartermenu.swf", a_menuName, "_global.BarterMenu") && \ CheckItemMenuComponents(a_menuName)) UnregisterForMenu(a_menuName) endIf elseIf (a_menuName == GIFT_MENU) if (CheckMenuVersion("giftmenu.swf", a_menuName, "_global.GiftMenu") && \ CheckItemMenuComponents(a_menuName)) UnregisterForMenu(a_menuName) endIf elseIf (a_menuName == JOURNAL_MENU) if (CheckMenuVersion("quest_journal.swf", a_menuName, "_global.Quest_Journal") && \ CheckMenuVersion("skyui/configpanel.swf", a_menuName, "_global.ConfigPanel")) UnregisterForMenu(a_menuName) endIf elseIf (a_menuName == MAP_MENU) ; if (CheckMenuVersion("map.swf", a_menuName, "_global.Map.MapMenu")) ; UnregisterForMenu(a_menuName) ; endIf elseIf (a_menuName == FAVORITES_MENU) ; if (CheckMenuVersion("favoritesmenu.swf", a_menuName, "_global.FavoritesMenu")) ; UnregisterForMenu(a_menuName) ; endIf elseIf (a_menuName == CRAFTING_MENU) if (CheckMenuVersion("craftingmenu.swf", a_menuName, "_global.CraftingMenu")) UnregisterForMenu(a_menuName) endIf endIf endEvent ; FUNCTIONS --------------------------------------------------------------------------------------- function Error(int a_errId, string a_msg) Debug.MessageBox("SKYUI ERROR CODE " + a_errId + "\n\n" + a_msg + "\n\nFor more help, visit the SkyUI download site.") ErrorDetected = true endFunction bool function CheckMenuVersion(string a_swfName, string a_menu, string a_class) ; Returns false if the menu is closed before UI.Get* receive their value int releaseIdx = UI.GetInt(a_menu, a_class + ".SKYUI_RELEASE_IDX") string version = UI.GetString(a_menu, a_class + ".SKYUI_VERSION_STRING") if (!UI.IsMenuOpen(a_menu)) return false endIf if (releaseIdx == 0) Error(ERR_SWF_INVALID, "Incompatible menu file (" + a_swfName + ").\nPlease make sure you installed everything correctly and no other mod has overwritten this file.\n" \ + "If you were using an older SkyUI version, un-install it and re-install the latest version.") elseIf (releaseIdx != ReqSWFRelease) Error(ERR_SWF_VERSION, "Menu file version mismatch for " + a_swfName + ".\n" \ + "Required version: " + ReqSWFVersion + "\n" \ + "Detected version: " + version) endIf return true endFunction bool function CheckItemMenuComponents(string a_menu) ; Returns false if the menu is closed before all checks have finished return CheckMenuVersion("skyui/itemcard.swf", a_menu, "_global.ItemCard") && \ CheckMenuVersion("skyui/bottombar.swf", a_menu, "_global.BottomBar") && \ CheckMenuVersion("skyui/inventorylists.swf", a_menu, "_global.InventoryLists") endFunction ================================================ FILE: dist/Data/Scripts/Source/SKI_PlayerInventoryHook.psc ================================================ scriptname SKI_PlayerInventoryHook extends ReferenceAlias ;; Interface for FormDB Function SetInt(Form form, string fieldName, int val) global native int Function GetInt(Form form, string fieldName, int default_val) global native Function SetBool(Form form, string fieldName, bool val) global native bool Function GetBool(Form form, string fieldName, bool default_val) global native Function RemoveField(Form form, string fieldName) global native Function RemoveAllfields(Form form) global native Event OnInit() ;; Debug.Trace("[PIH] PlayerInventoryHook started") endEvent String function form2str(Form f) return f + " " + f.GetName() endFunction String function obj2str(ObjectReference o) return o + " base: " + form2str(o.GetBaseObject()) endFunction Event OnItemAdded(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer) ;; Debug.Trace("[PIH] OnItemAdded") ;; Debug.Trace("[PIH] baseItem: " + form2str(akBaseItem)) ;; if akSourceContainer != None ;; Debug.Trace("[PIH] SourceContainer: " + obj2str(akSourceContainer)) ;; endIf ;; We want to associate some data with the base Form to indicate that this item is "new". ;; { ;; = {skyui = {newItem: true}} ;; } ;; ;; This "new" status is only useful/meaningful when we're viewing the player's inventory. ;; Care should be taken to ignore this flag when not viewing player inventory. if akSourceContainer != Game.GetPlayer() ;; Add a "new" tag to the item indicating that it is new SetBool(akBaseItem, "skyui/newItem", true) ;; bool val = GetBool(akBaseItem, "skyui/newItem", false) ;; Debug.Trace("[PIH] Setting 'new' flag for " + akBaseItem + " to " + val) endIf endEvent Event OnItemRemoved(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer) ;; Debug.Trace("[PIH] OnItemRemoved") ;; Debug.Trace("[PIH] baseItem: " + form2str(akBaseItem)) ;; if akDestContainer != None ;; Debug.Trace("[PIH] DestContainer: " + obj2str(akDestContainer)) ;; endIf ;; Make sure to clean any data associated with the base Form if the item is removed. ;; Another script might move the item before the player has the opportunity to open the inventory and cause ;; all the "new" tags to be cleared. if akDestContainer != Game.GetPlayer() ;; bool val = GetBool(akBaseItem, "skyui/newItem", false) ;; if val != false ;; Debug.Trace("[PIH] " + akBaseItem + " still has the 'new' flag on it!") ;; endIf RemoveField(akBaseItem, "skyui") ;; Debug.Trace("[PIH] Destroying data associated with " + akBaseItem) endIf endEvent ================================================ FILE: dist/Data/Scripts/Source/SKI_PlayerLoadGameAlias.psc ================================================ scriptname SKI_PlayerLoadGameAlias extends ReferenceAlias ; EVENTS ----------------------------------------------------------------------------------------- event OnPlayerLoadGame() (GetOwningQuest() as SKI_QuestBase).OnGameReload() endEvent ================================================ FILE: dist/Data/Scripts/Source/SKI_QF_ConfigManagerInstance.psc ================================================ ;BEGIN FRAGMENT CODE - Do not edit anything between this and the end comment ;NEXT FRAGMENT INDEX 1 Scriptname SKI_QF_ConfigManagerInstance Extends Quest Hidden ;BEGIN ALIAS PROPERTY PlayerRef ;ALIAS PROPERTY TYPE ReferenceAlias ReferenceAlias Property Alias_PlayerRef Auto ;END ALIAS PROPERTY ;BEGIN FRAGMENT Fragment_0 Function Fragment_0() ;BEGIN AUTOCAST TYPE SKI_ConfigManager Quest __temp = self as Quest SKI_ConfigManager kmyQuest = __temp as SKI_ConfigManager ;END AUTOCAST ;BEGIN CODE kmyQuest.ForceReset() ;END CODE EndFunction ;END FRAGMENT ;END FRAGMENT CODE - Do not edit anything between this and the begin comment ================================================ FILE: dist/Data/Scripts/Source/SKI_QuestBase.psc ================================================ scriptname SKI_QuestBase extends Quest hidden ; ------------------------------------------------------------------------------------------------- ; Version Tracking ; ; Quest implements ; GetVersion, to return the static version number ; OnVersionUpdate to handle the updating ; Update process is triggered by calling CheckVersion() int property CurrentVersion auto hidden function CheckVersion() int version = GetVersion() if (CurrentVersion < version) OnVersionUpdateBase(version) OnVersionUpdate(version) CurrentVersion = version endIf endFunction int function GetVersion() return 1 endFunction event OnVersionUpdateBase(int a_version) endEvent event OnVersionUpdate(int a_version) endEvent ; ------------------------------------------------------------------------------------------------- ; Reload Events ; ; Helper to add reload event to quest script. ; 1. Create quest ; 2. Add player alias to quest ; 3. Attach SKI_PlayerLoadGameAlias to player alias event OnGameReload() endEvent ================================================ FILE: dist/Data/Scripts/Source/SKI_SettingsManager.psc ================================================ scriptname SKI_SettingsManager extends SKI_QuestBase ; CONSTANTS --------------------------------------------------------------------------------------- string property MENU_ROOT = "_global.skyui.util.ConfigManager" autoReadonly string property INVENTORY_MENU = "InventoryMenu" autoReadonly string property MAGIC_MENU = "MagicMenu" autoReadonly string property CONTAINER_MENU = "ContainerMenu" autoReadonly string property BARTER_MENU = "BarterMenu" autoReadonly string property GIFT_MENU = "GiftMenu" autoReadonly string property CRAFTING_MENU = "Crafting Menu" autoReadonly ; PRIVATE VARIABLES ------------------------------------------------------------------------------- int _overrideCount = 0 string[] _overrideKeys string[] _overrideValues string _currentMenu ; INITIALIZATION ---------------------------------------------------------------------------------- event OnInit() _overrideKeys = new string[128] _overrideValues = new string[128] int i = 0 while (i<128) _overrideKeys[i] = "" _overrideValues[i] = "" i += 1 endWhile OnGameReload() endEvent ; @implements SKI_QuestBase event OnGameReload() RegisterForMenu(INVENTORY_MENU) RegisterForMenu(MAGIC_MENU) RegisterForMenu(CONTAINER_MENU) RegisterForMenu(BARTER_MENU) RegisterForMenu(GIFT_MENU) RegisterForMenu(CRAFTING_MENU) RegisterForModEvent("SKICO_setConfigOverride", "OnSetConfigOverride") endEvent ; EVENTS ------------------------------------------------------------------------------------------ event OnMenuOpen(string a_menuName) GotoState("LOCKED") ; Check if it's still open if (UI.IsMenuOpen(a_menuName)) _currentMenu = a_menuName UI.InvokeStringA(a_menuName, MENU_ROOT + ".setExternalOverrideKeys", _overrideKeys) UI.InvokeStringA(a_menuName, MENU_ROOT + ".setExternalOverrideValues", _overrideValues) endIf GotoState("") endEvent event OnSetConfigOverride(string a_eventName, string a_strArg, float a_numArg, Form a_sender) string overrideKey = a_strArg string overrideValue = UI.GetString(_currentMenu, MENU_ROOT + ".out_overrides." + overrideKey) SetOverride(overrideKey, overrideValue) endEvent ; ---------------------------------------------- state LOCKED event OnMenuOpen(string a_menuName) endEvent endState ; FUNCTIONS --------------------------------------------------------------------------------------- ; @interface bool function SetOverride(string a_key, string a_value) if (a_key == "") return false endIf ; Existing override? int index = _overrideKeys.Find(a_key) if (index != -1) _overrideValues[index] = a_value return true ; New override else if (_overrideCount >= 128) return false endIf index = NextFreeIndex() if (index == -1) return false endIf _overrideKeys[index] = a_key _overrideValues[index] = a_value _overrideCount += 1 return true endIf endFunction ; @interface bool function ClearOverride(string a_key) if (a_key == "") return false endIf int index = _overrideKeys.Find(a_key) if (index == -1) return false endIf _overrideKeys[index] = "" _overrideValues[index] = "" _overrideCount -= 1 return true endFunction int function NextFreeIndex() int i = 0 while (i < _overrideKeys.length) if (_overrideKeys[i] == "") return i endIf i += 1 endWhile return -1 endFunction ================================================ FILE: dist/Data/Scripts/Source/SKI_WidgetBase.psc ================================================ scriptname SKI_WidgetBase extends SKI_QuestBase ; CONSTANTS --------------------------------------------------------------------------------------- string property HUD_MENU = "HUD Menu" autoReadOnly ; PRIVATE VARIABLES ------------------------------------------------------------------------------- SKI_WidgetManager _widgetManager bool _initialized = false bool _ready = false int _widgetID = -1 string _widgetRoot = "" string[] _modes string _hAnchor = "left" string _vAnchor = "top" float _x = 0.0 float _y = 0.0 float _alpha = 100.0 ; PROPERTIES -------------------------------------------------------------------------------------- bool property RequireExtend = true auto {Require extending the widget type instead of using it directly.} ; @interface string property WidgetName = "I-forgot-to-set-the-widget name" auto {Name of the widget. Used to identify it in the user interface.} ; @interface int property WidgetID {Unique ID of the widget. ReadOnly} int function get() return _widgetID endFunction endProperty ; @interface bool property Ready {True once the widget has registered. ReadOnly} bool function get() return _initialized endFunction endProperty ; @interface string property WidgetRoot {Path to the root of the widget from _root of HudMenu. ReadOnly} string function get() return _widgetRoot endFunction endProperty string[] property Modes {HUDModes in which the widget is visible, see readme for available modes} string[] function get() return _modes endFunction function set(string[] a_val) _modes = a_val if (Ready) UpdateWidgetModes() endIf endFunction endProperty ; @interface string property HAnchor {Horizontal anchor point of the widget ["left", "center", "right"]. Default: "left"} string function get() return _hAnchor endFunction function set(string a_val) _hAnchor = a_val if (Ready) UpdateWidgetHAnchor() endIf endFunction endProperty ; @interface string property VAnchor {Vertical anchor point of the widget ["top", "center", "bottom"]. Default: "top"} string function get() return _vAnchor endFunction function set(string a_val) _vAnchor = a_val if (Ready) UpdateWidgetVAnchor() endIf endFunction endProperty ; @interface float property X {Horizontal position of the widget in pixels at a resolution of 1280x720 [0.0, 1280.0]. Default: 0.0} float function get() return _x endFunction function set(float a_val) _x = a_val if (Ready) UpdateWidgetPositionX() endIf endFunction endProperty ; @interface float property Y {Vertical position of the widget in pixels at a resolution of 1280x720 [0.0, 720.0]. Default: 0.0} float function get() return _y endFunction function set(float a_val) _y = a_val if (Ready) UpdateWidgetPositionY() endIf endFunction endProperty ; @interface float property Alpha {Opacity of the widget [0.0, 100.0]. Default: 0.0} float function get() return _alpha endFunction function set(float a_val) _alpha = a_val if (Ready) UpdateWidgetAlpha() endIf endFunction endProperty ; INITIALIZATION ---------------------------------------------------------------------------------- event OnInit() OnGameReload() endEvent ; @implements SKI_QuestBase event OnGameReload() _ready = false RegisterForModEvent("SKIWF_widgetManagerReady", "OnWidgetManagerReady") if (!IsExtending() && RequireExtend) Debug.MessageBox("WARNING!\n" + self as string + " must extend a base script type.") endIf if (!_initialized) _initialized = true ; Default Modes if not set via property if (!_modes) _modes = new string[6] _modes[0] = "All" _modes[1] = "StealthMode" _modes[2] = "Favor" _modes[3] = "Swimming" _modes[4] = "HorseMode" _modes[5] = "WarHorseMode" endIf OnWidgetInit() Debug.Trace(self + " INITIALIZED") endIf CheckVersion() endEvent event OnWidgetManagerReady(string a_eventName, string a_strArg, float a_numArg, Form a_sender) SKI_WidgetManager newManager = a_sender as SKI_WidgetManager ; Already registered? if (_widgetManager == newManager) return endIf _widgetManager = newManager _widgetID = _widgetManager.RequestWidgetID(self) if (_widgetID != -1) _widgetRoot = "_root.WidgetContainer." + _widgetID + ".widget" _widgetManager.CreateWidget(_widgetID, GetWidgetSource()) else Debug.Trace("WidgetWarning: " + self as string + ": could not be loaded, too many widgets. Max is 128") endIf endEvent ; EVENTS ------------------------------------------------------------------------------------------ ; @interface event OnWidgetInit() {Handles any custom widget initialization} endEvent ; Executed after each game reload by widget manager. event OnWidgetLoad() _ready = true OnWidgetReset() ; Before that the widget was still hidden. ; Now that everything is done, set modes to show it eventually. UpdateWidgetModes() endEvent event OnWidgetReset() ; Reset base properties except modes to prevent widget from being drawn too early. UpdateWidgetClientInfo() UpdateWidgetHAnchor() UpdateWidgetVAnchor() UpdateWidgetPositionX() UpdateWidgetPositionY() UpdateWidgetAlpha() endEvent ; FUNCTIONS --------------------------------------------------------------------------------------- ; @interface string function GetWidgetSource() return "" endFunction ; @interface string function GetWidgetType() ; Must be the same as scriptname return "" endFunction ; @interface float[] function GetDimensions() {Return the dimensions of the widget (width,height).} float[] dim = new float[2] dim[0] = 0 dim[1] = 0 return dim endFunction ; @interface function TweenToX(float a_x, float a_duration) {Moves the widget to a new x position over time} TweenTo(a_x, _y, a_duration) endFunction ; @interface function TweenToY(float a_y, float a_duration) {Moves the widget to a new y position over time} TweenTo(_x, a_y, a_duration) endFunction ; @interface function TweenTo(float a_x, float a_y, float a_duration) {Moves the widget to a new x, y position over time} float[] args = new float[3] args[0] = a_x args[1] = a_y args[2] = a_duration UI.InvokeFloatA(HUD_MENU, _widgetRoot + ".tweenTo", args) endFunction ; @interface function FadeTo(float a_alpha, float a_duration) {Fades the widget to a new alpha over time} float[] args = new float[2] args[0] = a_alpha args[1] = a_duration UI.InvokeFloatA(HUD_MENU, _widgetRoot + ".fadeTo", args) endFunction bool function IsExtending() string s = self as string string sn = GetWidgetType() + " " s = StringUtil.Substring(s, 1, StringUtil.GetLength(sn)) if (s == sn) return false endIf return true endFunction function UpdateWidgetClientInfo() UI.InvokeString(HUD_MENU, _widgetRoot + ".setClientInfo", self as string) endFunction function UpdateWidgetAlpha() UI.InvokeFloat(HUD_MENU, _widgetRoot + ".setAlpha", Alpha) endFunction function UpdateWidgetHAnchor() UI.InvokeString(HUD_MENU, _widgetRoot + ".setHAnchor", HAnchor) endFunction function UpdateWidgetVAnchor() UI.InvokeString(HUD_MENU, _widgetRoot + ".setVAnchor", VAnchor) endFunction function UpdateWidgetPositionX() UI.InvokeFloat(HUD_MENU, _widgetRoot + ".setPositionX", X) endFunction function UpdateWidgetPositionY() UI.InvokeFloat(HUD_MENU, _widgetRoot + ".setPositionY", Y) endFunction function UpdateWidgetModes() UI.InvokeStringA(HUD_MENU, _widgetRoot + ".setModes", Modes) endFunction ================================================ FILE: dist/Data/Scripts/Source/SKI_WidgetManager.psc ================================================ scriptname SKI_WidgetManager extends SKI_QuestBase ; CONSTANTS --------------------------------------------------------------------------------------- string property HUD_MENU = "HUD Menu" autoReadOnly ; PRIVATE VARIABLES ------------------------------------------------------------------------------- SKI_WidgetBase[] _widgets string[] _widgetSources int _curWidgetID = 0 int _widgetCount = 0 ; INITIALIZATION ---------------------------------------------------------------------------------- event OnInit() _widgets = new SKI_WidgetBase[128] _widgetSources = new string[128] ; Wait until all widgets have registered their callbacks Utility.Wait(0.5) OnGameReload() endEvent event OnGameReload() RegisterForModEvent("SKIWF_widgetLoaded", "OnWidgetLoad") RegisterForModEvent("SKIWF_widgetError", "OnWidgetError") CleanUp() ; Init now, or delay until hudmenu has been loaded if (UI.IsMenuOpen(HUD_MENU)) InitWidgetLoader() else RegisterForMenu(HUD_MENU) endIf endEvent event OnMenuOpen(string a_menuName) if (a_menuName == HUD_MENU) UnregisterForMenu(HUD_MENU) InitWidgetLoader() endIf endEvent function CleanUp() _widgetCount = 0 int i = 0 while (i < _widgets.length) if (_widgets[i] == none || _widgets[i].GetFormID() == 0) ; Widget no longer exists _widgets[i] = none _widgetSources[i] = "" else _widgetCount += 1 endIf i += 1 endWhile endFunction function InitWidgetLoader() Debug.Trace("InitWidgetLoader()") int releaseIdx = UI.GetInt(HUD_MENU, "_global.WidgetLoader.SKYUI_RELEASE_IDX") ; Not injected yet if (releaseIdx == 0) ; Interface/ string rootPath = "" string[] args = new string[2] args[0] = "widgetLoaderContainer" args[1] = "-1000" ; Create empty container clip UI.InvokeStringA(HUD_MENU, "_root.createEmptyMovieClip", args) ; Try to load from Interface/exported/hudmenu.gfx UI.InvokeString(HUD_MENU, "_root.widgetLoaderContainer.loadMovie", "skyui/widgetloader.swf") Utility.Wait(0.5) releaseIdx = UI.GetInt(HUD_MENU, "_global.WidgetLoader.SKYUI_RELEASE_IDX") ; If failed, try to load from Interface/hudmenu.swf if (releaseIdx == 0) ; Interface/exported rootPath = "exported/" UI.InvokeString(HUD_MENU, "_root.widgetLoaderContainer.loadMovie", "exported/skyui/widgetloader.swf") Utility.Wait(0.5) releaseIdx = UI.GetInt(HUD_MENU, "_global.WidgetLoader.SKYUI_RELEASE_IDX") endIf ; Injection failed if (releaseIdx == 0) Debug.Trace("InitWidgetLoader(): load failed") return endIf UI.InvokeString(HUD_MENU, "_root.widgetLoaderContainer.widgetLoader.setRootPath", rootPath) endIf ; Load already registered widgets UI.InvokeStringA(HUD_MENU, "_root.widgetLoaderContainer.widgetLoader.loadWidgets", _widgetSources) SendModEvent("SKIWF_widgetManagerReady") endFunction ; EVENTS ------------------------------------------------------------------------------------------ event OnWidgetLoad(string a_eventName, string a_strArg, float a_numArg, form a_sender) int widgetID = a_strArg as int SKI_WidgetBase client = _widgets[widgetID] if (client != none) client.OnWidgetLoad() endIf endEvent event OnWidgetError(string a_eventName, string a_strArg, float a_numArg, form a_sender) int widgetID = a_numArg as int string errorType = a_strArg Debug.Trace("WidgetError: " + (_widgets[widgetID] as string) + ": " + errorType) endEvent ; FUNCTIONS --------------------------------------------------------------------------------------- int function RequestWidgetID(SKI_WidgetBase a_client) if (_widgetCount >= 128) return -1 endIf int widgetID = NextWidgetID() _widgets[widgetID] = a_client _widgetCount += 1 return widgetID endFunction int function NextWidgetID() int startIdx = _curWidgetID while (_widgets[_curWidgetID] != none) _curWidgetID += 1 if (_curWidgetID >= 128) _curWidgetID = 0 endIf if (_curWidgetID == startIdx) return -1 ; Should never happen because we have widgetCount. Just to be sure. endIf endWhile return _curWidgetID endFunction function CreateWidget(int a_widgetID, string a_widgetSource) _widgetSources[a_widgetID] = a_widgetSource string[] args = new string[2] args[0] = a_widgetID as string args[1] = a_widgetSource UI.InvokeStringA(HUD_MENU, "_root.widgetLoaderContainer.widgetLoader.loadWidget", args); endFunction SKI_WidgetBase[] function GetWidgets() ; Return a copy SKI_WidgetBase[] widgetsCopy = new SKI_WidgetBase[128] int i = 0 while (i < _widgets.length) widgetsCopy[i] = _widgets[i] i += 1 endWhile return widgetsCopy endFunction ================================================ FILE: dist/Data/fomod/script.cs ================================================ using System; using fomm.Scripting; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Text; using System.Text.RegularExpressions; using System.IO; using System.Windows.Forms; using System.Globalization; using System.Collections.Generic; class Script : SkyrimBaseScript { static Version SKSE_MIN_VERSION = new Version("0.1.6.16"); // Main dialog static Form mainInstallForm; static TextBox textArea; static Button refreshButton; static Button installButton; static Button cancelButton; static string[] checkedLooseFiles = { "Scripts/SKI_ActiveEffectsWidget.pex", "Scripts/SKI_ConfigBase.pex", "Scripts/SKI_ConfigManager.pex", "Scripts/SKI_Main.pex", "Scripts/SKI_MeterWidget.pex", "Scripts/SKI_PlayerLoadGameAlias.pex", "Scripts/SKI_QuestBase.pex", "Scripts/SKI_StatusWidget.pex", "Scripts/SKI_WidgetBase.pex", "Scripts/SKI_WidgetManager.pex", "Interface/skyui_cfg.txt", "Interface/skyui_translate.txt", "Interface/bartermenu.swf", "Interface/containermenu.swf", "Interface/inventorymenu.swf", "Interface/magicmenu.swf", "Interface/skyui/inventorylists.swf", "Interface/skyui/tabbedinventorylists.swf", "Interface/skyui/skyui_icons_cat.swf", "Interface/skyui/skyui_icons_inv.swf", "Interface/skyui/skyui_icons_magic.swf" }; static bool install = false; static int problemCount = 0; static List foundLooseFiles = new List(); static bool noSKSE = false; static bool noSKSEScripts = false; static Version skseVersion; public static bool OnActivate() { DetectProblems(); // Detected problems? Show report. Otherwise just install if (problemCount > 0) { InitializeComponents(); mainInstallForm.ShowDialog(); } else { install = true; } if (install) PerformBasicInstall(); return install; } static void DetectProblems() { // Clean up previous data problemCount = 0; foundLooseFiles.Clear(); noSKSE = false; noSKSEScripts = false; skseVersion = new Version(); // 1. Check Loose files foreach (string file in checkedLooseFiles) if (GetExistingDataFile(file) != null) foundLooseFiles.Add(file); if (foundLooseFiles.Count > 0) problemCount++; // 2. Check if skse is present noSKSE = !ScriptExtenderPresent(); if (noSKSE) problemCount++; // 3. Check SKSE version skseVersion = GetSkseVersion(); if (skseVersion == null || skseVersion < SKSE_MIN_VERSION) problemCount++; // 4. Check missing SKSE.pex if (GetExistingDataFile("Scripts/SKSE.pex") == null) { noSKSEScripts = true; problemCount++; } } static void GenerateReport() { int c = 0; textArea.Clear(); if (problemCount == 0) { PrintReport("All problems have been resolved."); return; } PrintReport("This report informs you about potential problems with your SkyUI installation."); PrintReport(""); PrintReport("Fix these problems , then press 'Refresh' to confirm that they're gone."); PrintReport("After all problems have been resolved, you can continue with the installation."); PrintReport(""); if (foundLooseFiles.Count > 0) { c++; PrintReport("-----------"); PrintReport("Problem #" + c + ":"); PrintReport("-----------"); PrintReport("There are files in your 'Data/' folder, which override newer versions from the SkyUI.bsa archive."); PrintReport(""); PrintReport("These files are:"); foreach (string file in foundLooseFiles) PrintReport("\tData/" + file); PrintReport(""); PrintReport("Potential causes:"); PrintReport("* An old SkyUI version was not uninstalled before installing the new one."); PrintReport(""); PrintReport("Solution:"); PrintReport("1. If you have an old SkyUI version installed in NMM, uninstall it, then try again."); PrintReport("2. If there are still problematic files reported, delete them manually."); PrintReport(""); } if (noSKSE) { c++; PrintReport("-----------"); PrintReport("Problem #" + c + ":"); PrintReport("-----------"); PrintReport("The Skyrim Script Extender (SKSE) is not installed."); PrintReport(""); PrintReport("Solution:"); PrintReport("1. Get the latest SKSE version from 'http://skse.silverlock.org/' and install it."); PrintReport(" If you have problems installing it, have a look at this video:"); PrintReport(" http://www.youtube.com/watch?v=xTGnQIiNVqA"); } else if (skseVersion == null || skseVersion < SKSE_MIN_VERSION) { c++; PrintReport("-----------"); PrintReport("Problem #" + c + ":"); PrintReport("-----------"); PrintReport("Your SKSE version is too old."); PrintReport(""); PrintReport("Detected version: " + skseVersion); PrintReport("Required version: " + SKSE_MIN_VERSION + " (or newer)"); PrintReport(""); PrintReport("Solution:"); PrintReport("1. Get the latest SKSE version from 'http://skse.silverlock.org/' and install it."); PrintReport(" If you have problems installing it, have a look at this video:"); PrintReport(" http://www.youtube.com/watch?v=xTGnQIiNVqA"); } else if (noSKSEScripts) { c++; PrintReport("-----------"); PrintReport("Problem #" + c + ":"); PrintReport("-----------"); PrintReport("The SKSE scripts are missing."); PrintReport(""); PrintReport("Potential causes:"); PrintReport("* You didn't install the scripts with the rest of SKSE."); PrintReport(""); PrintReport("Solution:"); PrintReport("1. Re-install SKSE. Make sure you extract the 'Data/' folder from the downloaded archive to your Skyrim installation directory."); } } static void PrintReport(string line) { textArea.AppendText(line + "\n"); } static void InitializeComponents() { textArea = new System.Windows.Forms.TextBox(); refreshButton = new System.Windows.Forms.Button(); installButton = new System.Windows.Forms.Button(); cancelButton = new System.Windows.Forms.Button(); // // textArea // textArea.BackColor = System.Drawing.SystemColors.ControlLightLight; textArea.Location = new System.Drawing.Point(12, 12); textArea.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); textArea.Multiline = true; textArea.Name = "textArea"; textArea.ReadOnly = true; textArea.ScrollBars = System.Windows.Forms.ScrollBars.Both; textArea.Size = new System.Drawing.Size(610, 439); textArea.TabIndex = 0; // // refreshButton // refreshButton.Location = new System.Drawing.Point(280, 457); refreshButton.Name = "refreshButton"; refreshButton.Size = new System.Drawing.Size(75, 23); refreshButton.TabIndex = 1; refreshButton.Text = "Refresh"; refreshButton.UseVisualStyleBackColor = true; refreshButton.Click += new System.EventHandler(refreshButton_Click); // // installButton // installButton.Location = new System.Drawing.Point(547, 457); installButton.Name = "installButton"; installButton.Size = new System.Drawing.Size(75, 23); installButton.TabIndex = 2; installButton.Text = "Install"; installButton.UseVisualStyleBackColor = true; installButton.Click += new System.EventHandler(installButton_Click); // // cancelButton // cancelButton.Location = new System.Drawing.Point(12, 457); cancelButton.Name = "cancelButton"; cancelButton.Size = new System.Drawing.Size(75, 23); cancelButton.TabIndex = 3; cancelButton.Text = "Cancel"; cancelButton.UseVisualStyleBackColor = true; cancelButton.Click += new System.EventHandler(cancelButton_Click); // // mainInstallForm // mainInstallForm = CreateCustomForm(); mainInstallForm.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); mainInstallForm.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; mainInstallForm.ClientSize = new System.Drawing.Size(634, 492); mainInstallForm.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; mainInstallForm.MaximizeBox = false; mainInstallForm.MinimizeBox = false; mainInstallForm.Controls.Add(installButton); mainInstallForm.Controls.Add(refreshButton); mainInstallForm.Controls.Add(cancelButton); mainInstallForm.Controls.Add(textArea); mainInstallForm.Name = "mainInstallForm"; mainInstallForm.Text = "SkyUI Problem Report"; mainInstallForm.Load += new System.EventHandler(mainInstallForm_Load); } static void installButton_Click(object sender, EventArgs e) { install = true; mainInstallForm.Close(); } static void refreshButton_Click(object sender, EventArgs e) { DetectProblems(); GenerateReport(); } static void cancelButton_Click(object sender, EventArgs e) { install = false; mainInstallForm.Close(); } static void mainInstallForm_Load(object sender, EventArgs e) { GenerateReport(); } static bool IsPluginActive(String pluginName) { string[] loadOrder = GetActivePlugins(); for (int i = 0; i < loadOrder.Length; ++i) { if (loadOrder[i].Equals(pluginName, StringComparison.InvariantCultureIgnoreCase)) { return true; } } return false; } } ================================================ FILE: dist/Examples/MCM/ConfigMenuTemplate.psc ================================================ scriptname MyConfigMenu extends SKI_ConfigBase ; SCRIPT VERSION ---------------------------------------------------------------------------------- int function GetVersion() return 1 ; Default version endFunction ; PRIVATE VARIABLES ------------------------------------------------------------------------------- ; OIDs (T:Text B:Toggle S:Slider M:Menu, C:Color, K:Key) int _myTextOID_T int _myToggle_OID_B int _mySliderOID_S int _myMenuOID_M int _myColorOID_C int _myKeyOID_K ; State ; ... ; Internal ; ... ; INITIALIZATION ---------------------------------------------------------------------------------- ; @implements SKI_ConfigBase event OnConfigInit() {Called when this config menu is initialized} ; ... endEvent ; @implements SKI_QuestBase event OnVersionUpdate(int a_version) {Called when a version update of this script has been detected} ; ... endEvent ; EVENTS ------------------------------------------------------------------------------------------ ; @implements SKI_ConfigBase event OnPageReset(string a_page) {Called when a new page is selected, including the initial empty page} ; ... endEvent ; @implements SKI_ConfigBase event OnOptionHighlight(int a_option) {Called when highlighting an option} ; ... endEvent ; @implements SKI_ConfigBase event OnOptionSelect(int a_option) {Called when a non-interactive option has been selected} ; ... endEvent ; @implements SKI_ConfigBase event OnOptionDefault(int a_option) {Called when resetting an option to its default value} ; ... endEvent ; @implements SKI_ConfigBase event OnOptionSliderOpen(int a_option) {Called when a slider option has been selected} ; ... endEvent ; @implements SKI_ConfigBase event OnOptionSliderAccept(int a_option, float a_value) {Called when a new slider value has been accepted} ; ... endEvent ; @implements SKI_ConfigBase event OnOptionMenuOpen(int a_option) {Called when a menu option has been selected} ; ... endEvent ; @implements SKI_ConfigBase event OnOptionMenuAccept(int a_option, int a_index) {Called when a menu entry has been accepted} ; ... endEvent ; @implements SKI_ConfigBase event OnOptionColorOpen(int a_option) {Called when a color option has been selected} ; ... endEvent ; @implements SKI_ConfigBase event OnOptionColorAccept(int a_option, int a_color) {Called when a new color has been accepted} ; ... endEvent ; @implements SKI_ConfigBase event OnOptionKeyMapChange(int a_option, int a_keyCode, string a_conflictControl, string a_conflictName) {Called when a key has been remapped} ; ... endEvent ================================================ FILE: dist/Examples/MCM/ExampleConfigMenu.psc ================================================ scriptname ExampleConfigMenu extends SKI_ConfigBase ; SCRIPT VERSION ---------------------------------------------------------------------------------- ; ; NOTE: ; This is an example to show you how to update scripts after they have been deployed. ; ; History ; ; 1 - Initial version ; 2 - Added color option ; 3 - Added keymap option int function GetVersion() return 3 ; Default version endFunction ; PRIVATE VARIABLES ------------------------------------------------------------------------------- ; --- Version 1 --- ; Lists string[] _difficultyList ; OIDs (T:Text B:Toggle S:Slider M:Menu, C:Color, K:Key) int _toggle1OID_B int _toggle2OID_B int _toggle3OID_B int _textOID_T int _counterOID_T int _sliderFormatOID_S int _difficultyMenuOID_M ; State bool _toggleState1 = false bool _toggleState2 = false bool _toggleState3 = false int _counter = 0 float _sliderPercent = 50.0 int _curDifficulty = 0 ; --- Version 2 --- ; OIDs int _colorOID_C ; State int _color = 0xFFFFFF ; --- Version 3 --- ; OIDs int _keymapOID_K ; State int _myKey = -1 ; INITIALIZATION ---------------------------------------------------------------------------------- ; @overrides SKI_ConfigBase event OnConfigInit() Pages = new string[2] Pages[0] = "Example Page" Pages[1] = "Another Page" _difficultyList = new string[4] _difficultyList[0] = "Casual" _difficultyList[1] = "Easy" _difficultyList[2] = "Normal" _difficultyList[3] = "Hard" endEvent ; @implements SKI_QuestBase event OnVersionUpdate(int a_version) {Called when a version update of this script has been detected} ; Version 2 specific updating code if (a_version >= 2 && CurrentVersion < 2) Debug.Trace(self + ": Updating script to version 2") _color = Utility.RandomInt(0x000000, 0xFFFFFF) ; Set a random color endIf ; Version 3 specific updating code if (a_version >= 3 && CurrentVersion < 3) Debug.Trace(self + ": Updating script to version 3") _myKey = Input.GetMappedKey("Jump") endIf endEvent ; EVENTS ------------------------------------------------------------------------------------------ ; @implements SKI_ConfigBase event OnPageReset(string a_page) {Called when a new page is selected, including the initial empty page} ; Load custom logo in DDS format if (a_page == "") ; Image size 256x256 ; X offset = 376 - (height / 2) = 258 ; Y offset = 223 - (width / 2) = 95 LoadCustomContent("skyui/res/mcm_logo.dds", 258, 95) return else UnloadCustomContent() endIf if (a_page == "Example Page") SetCursorFillMode(TOP_TO_BOTTOM) AddHeaderOption("Toggle Options") _toggle1OID_B = AddToggleOption("Toggle Option 1", _toggleState1) _toggle2OID_B = AddToggleOption("Toggle Option 2", _toggleState2) _toggle3OID_B = AddToggleOption("On or Off?", _toggleState3) AddEmptyOption() AddHeaderOption("Text Options") _textOID_T = AddTextOption("Text Option 1", "CLICK ME") _counterOID_T = AddTextOption("Number of Clicks", _counter) SetCursorPosition(1) AddHeaderOption("All option types") AddTextOption("Text", "VALUE") AddToggleOption("Toggle", false) AddSliderOption("Slider", 1.75) _sliderFormatOID_S = AddSliderOption("Slider (format string)", _sliderPercent, "At {0}%") _difficultyMenuOID_M = AddMenuOption("Difficulty", _difficultyList[_curDifficulty]) _colorOID_C = AddColorOption("Color", _color) _keymapOID_K = AddKeyMapOption("KeyMap", _myKey) elseIf (a_page == "Another Page") SetTitleText("Custom title text") SetCursorFillMode(LEFT_TO_RIGHT) AddHeaderOption("Hitpoints") AddEmptyOption() AddSliderOption("Player Endurance Multiplier", 10) AddSliderOption("NPC Endurance Multiplier", 7) AddSliderOption("Player Level Multiplier", 0) AddSliderOption("NPC Level Multiplier", 0) endIf endEvent ; @implements SKI_ConfigBase event OnOptionSelect(int a_option) {Called when the user selects a non-dialog option} if (a_option == _toggle1OID_B) _toggleState1 = !_toggleState1 SetToggleOptionValue(a_option, _toggleState1) elseIf (a_option == _toggle2OID_B) _toggleState2 = !_toggleState2 SetToggleOptionValue(a_option, _toggleState2) elseIf (a_option == _toggle3OID_B) _toggleState3 = !_toggleState3 SetToggleOptionValue(a_option, _toggleState3) elseIf (a_option == _textOID_T) ; Do something SetTextOptionValue(a_option, "WELL DONE") elseIf (a_option == _counterOID_T) _counter += 1 SetTextOptionValue(a_option, _counter) endIf endEvent ; @implements SKI_ConfigBase event OnOptionSliderOpen(int a_option) {Called when the user selects a slider option} if (a_option == _sliderFormatOID_S) SetSliderDialogStartValue(_sliderPercent) SetSliderDialogDefaultValue(50) SetSliderDialogRange(0, 100) SetSliderDialogInterval(2) endIf endEvent ; @implements SKI_ConfigBase event OnOptionSliderAccept(int a_option, float a_value) {Called when the user accepts a new slider value} if (a_option == _sliderFormatOID_S) _sliderPercent = a_value SetSliderOptionValue(a_option, a_value, "At {0}%") endIf endEvent ; @implements SKI_ConfigBase event OnOptionMenuOpen(int a_option) {Called when the user selects a menu option} if (a_option == _difficultyMenuOID_M) SetMenuDialogStartIndex(_curDifficulty) SetMenuDialogDefaultIndex(0) SetMenuDialogOptions(_difficultyList) endIf endEvent ; @implements SKI_ConfigBase event OnOptionMenuAccept(int a_option, int a_index) {Called when the user accepts a new menu entry} if (a_option == _difficultyMenuOID_M) _curDifficulty = a_index SetMenuOptionValue(a_option, _difficultyList[_curDifficulty]) endIf endEvent ; @implements SKI_ConfigBase event OnOptionColorOpen(int a_option) {Called when a color option has been selected} if (a_option == _colorOID_C) SetColorDialogStartColor(_color) SetColorDialogDefaultColor(0xFFFFFF) endIf endEvent ; @implements SKI_ConfigBase event OnOptionColorAccept(int a_option, int a_color) {Called when a new color has been accepted} if (a_option == _colorOID_C) _color = a_color SetColorOptionValue(a_option, a_color) endIf endEvent ; @implements SKI_ConfigBase event OnOptionKeyMapChange(int a_option, int a_keyCode, string a_conflictControl, string a_conflictName) {Called when a key has been remapped} if (a_option == _keymapOID_K) bool continue = true if (a_conflictControl != "") string msg if (a_conflictName != "") msg = "This key is already mapped to:\n'" + a_conflictControl + "'\n(" + a_conflictName + ")\n\nAre you sure you want to continue?" else msg = "This key is already mapped to:\n'" + a_conflictControl + "'\n\nAre you sure you want to continue?" endIf continue = ShowMessage(msg, true, "$Yes", "$No") endIf if (continue) _myKey = a_keyCode SetKeymapOptionValue(a_option, a_keyCode) endIf endIf endEvent ; @implements SKI_ConfigBase event OnOptionHighlight(int a_option) {Called when the user highlights an option} if (a_option == _toggle1OID_B) SetInfoText("Info text for toggle option 1.") elseIf (a_option == _toggle2OID_B) SetInfoText("Info text for toggle option 2.") elseIf (a_option == _toggle3OID_B) SetInfoText("Sometimes choice can be a burden...") endIf endEvent ================================================ FILE: dist/bsascript.txt ================================================ Log: Archive.log New Archive Check: Menus Check: Misc Check: Retain Directory Names Check: Retain File Names Set File Group Root: Data\ Add File Group: filegroup_all.txt Save Archive: _generated\SkyUI.bsa ================================================ FILE: dist/filegroup_all.txt ================================================ Interface\bartermenu.swf Interface\containermenu.swf Interface\inventorymenu.swf Interface\magicmenu.swf Interface\quest_journal.swf Interface\giftmenu.swf Interface\map.swf Interface\favoritesmenu.swf Interface\craftingmenu.swf Interface\skyui\config.txt Interface\skyui\inventorylists.swf Interface\skyui\bottombar.swf Interface\skyui\itemcard.swf Interface\skyui\buttonart.swf Interface\skyui\mapmarkerart.swf Interface\skyui\configpanel.swf Interface\skyui\icons_category_psychosteve.swf Interface\skyui\icons_item_psychosteve.swf Interface\skyui\skyui_splash.swf Interface\skyui\mcm_splash.swf Interface\skyui\res\mcm_logo.dds Interface\exported\skyui\widgetloader.swf Interface\exported\skyui\icons_effect_psychosteve.swf Interface\exported\widgets\skyui\activeeffects.swf Interface\translations\SkyUI_czech.txt Interface\translations\SkyUI_english.txt Interface\translations\SkyUI_french.txt Interface\translations\SkyUI_german.txt Interface\translations\SkyUI_italian.txt Interface\translations\SkyUI_polish.txt Interface\translations\SkyUI_russian.txt Interface\translations\SkyUI_spanish.txt Interface\translations\SkyUI_japanese.txt Scripts\SKI_ActiveEffectsWidget.pex Scripts\SKI_ConfigBase.pex Scripts\SKI_ConfigManager.pex Scripts\SKI_ConfigMenu.pex Scripts\SKI_FavoritesManager.pex Scripts\SKI_Main.pex Scripts\SKI_PlayerLoadGameAlias.pex Scripts\SKI_QF_ConfigManagerInstance.pex Scripts\SKI_QuestBase.pex Scripts\SKI_SettingsManager.pex Scripts\SKI_WidgetBase.pex Scripts\SKI_WidgetManager.pex Scripts\Source\SKI_ActiveEffectsWidget.psc Scripts\Source\SKI_ConfigBase.psc Scripts\Source\SKI_ConfigManager.psc Scripts\Source\SKI_ConfigMenu.psc Scripts\Source\SKI_FavoritesManager.psc Scripts\Source\SKI_Main.psc Scripts\Source\SKI_PlayerLoadGameAlias.psc Scripts\Source\SKI_QF_ConfigManagerInstance.psc Scripts\Source\SKI_QuestBase.psc Scripts\Source\SKI_SettingsManager.psc Scripts\Source\SKI_WidgetBase.psc Scripts\Source\SKI_WidgetManager.psc Readme - SkyUI.txt ================================================ FILE: dist/filegroup_interface.txt ================================================ Interface\bartermenu.swf Interface\containermenu.swf Interface\inventorymenu.swf Interface\magicmenu.swf Interface\quest_journal.swf Interface\giftmenu.swf Interface\map.swf Interface\favoritesmenu.swf Interface\craftingmenu.swf Interface\skyui\config.txt Interface\skyui\inventorylists.swf Interface\skyui\bottombar.swf Interface\skyui\itemcard.swf Interface\skyui\buttonart.swf Interface\skyui\mapmarkerart.swf Interface\skyui\configpanel.swf Interface\skyui\icons_category_psychosteve.swf Interface\skyui\icons_item_psychosteve.swf Interface\skyui\skyui_splash.swf Interface\skyui\mcm_splash.swf Interface\skyui\res\mcm_logo.dds Interface\exported\skyui\widgetloader.swf Interface\exported\skyui\icons_effect_psychosteve.swf Interface\exported\widgets\skyui\activeeffects.swf Interface\translations\SkyUI_czech.txt Interface\translations\SkyUI_english.txt Interface\translations\SkyUI_french.txt Interface\translations\SkyUI_german.txt Interface\translations\SkyUI_italian.txt Interface\translations\SkyUI_polish.txt Interface\translations\SkyUI_russian.txt Interface\translations\SkyUI_spanish.txt Interface\translations\SkyUI_japanese.txt ================================================ FILE: dist/filegroup_misc.txt ================================================ Readme - SkyUI.txt ================================================ FILE: dist/filegroup_scripts.txt ================================================ Scripts\SKI_ActiveEffectsWidget.pex Scripts\SKI_ConfigBase.pex Scripts\SKI_ConfigManager.pex Scripts\SKI_ConfigMenu.pex Scripts\SKI_FavoritesManager.pex Scripts\SKI_Main.pex Scripts\SKI_PlayerInventoryHook.pex Scripts\SKI_PlayerLoadGameAlias.pex Scripts\SKI_QF_ConfigManagerInstance.pex Scripts\SKI_QuestBase.pex Scripts\SKI_SettingsManager.pex Scripts\SKI_WidgetBase.pex Scripts\SKI_WidgetManager.pex Scripts\Source\SKI_ActiveEffectsWidget.psc Scripts\Source\SKI_ConfigBase.psc Scripts\Source\SKI_ConfigManager.psc Scripts\Source\SKI_ConfigMenu.psc Scripts\Source\SKI_FavoritesManager.psc Scripts\Source\SKI_Main.psc Scripts\Source\SKI_PlayerInventoryHook.psc Scripts\Source\SKI_PlayerLoadGameAlias.psc Scripts\Source\SKI_QF_ConfigManagerInstance.psc Scripts\Source\SKI_QuestBase.psc Scripts\Source\SKI_SettingsManager.psc Scripts\Source\SKI_WidgetBase.psc Scripts\Source\SKI_WidgetManager.psc ================================================ FILE: dist/make_all.pl ================================================ #!/usr/bin/perl system("make_scripts.pl", "1") == 0 or die; system("make_archive.pl", "1") == 0 or die; ================================================ FILE: dist/make_archive.pl ================================================ #!/usr/bin/perl use File::Basename; use File::Copy; use File::Path; sub error { print "\n=========================\n\n" . "ERROR: $_[0]\n"; getc(STDIN); exit(1); } sub copyFile { mkpath(dirname($_[1])); if (copy($_[0], $_[1])) { print "Copy $_[0] to $_[1]\n"; } else { print "SKIP $_[0]\n"; } } $skyrimPath = $ENV{'SkyrimPath'} or error("\$SkyrimPath env var not set."); $archivePath = $skyrimPath . "\\Archive.exe"; $swfBuildPath = "..\\build"; $archiveOutPath = "_generated"; $fileGroupInterfacePath = "filegroup_interface.txt"; $fileGroupMiscPath = "filegroup_misc.txt"; $fileGroupScriptsPath = "filegroup_scripts.txt"; $filegroupPathOut = "filegroup_all.txt"; @filegroupPathsIn = ( $fileGroupInterfacePath, $fileGroupScriptsPath, $fileGroupMiscPath ); # No wait? $noWait = defined($ARGV[0]); # Fetch latest .swf's from build/ print "=== Updating .SWF files...\n\n"; open(IN, $fileGroupInterfacePath) or error("Cannot open $fileGroupInterfacePath: $!"); while (my $file = ) { chomp($file); $file =~ s/^Interface\\//; copyFile("$swfBuildPath\\$file", "Data\\Interface\\$file"); } close(IN); print "Done.\n\n"; # Merge filegroup lists print ("=== Merging filegroup lists...\n\n"); open(OUT, ">$filegroupPathOut") or error("Cannot open $filegroupPathOut: $!"); foreach $f (@filegroupPathsIn) { open(IN, $f) or error("Cannot open $f: $!"); while (my $line = ) { chomp($line); print OUT "$line\n"; } close(IN); } close(OUT); print "Done.\n\n"; # Create archive print "=== Creating archive...\n\n"; system($archivePath, "bsascript.txt") == 0 or exit(1); print "Done.\n\n"; # Install archive print "=== Installing archive...\n\n"; copyFile($_, "$skyrimPath\\Data\\" . basename($_)) foreach (<_generated/*>); print "Done.\n\n"; getc(STDIN) unless $noWait; exit(0); ================================================ FILE: dist/make_scripts.pl ================================================ #!/usr/bin/perl use File::Basename; use File::Copy; use File::Path; sub error { print "\n=========================\n\n" . "ERROR: $_[0]\n"; getc(STDIN); exit(1); } sub copyFile { mkpath(dirname($_[1])); if (copy($_[0], $_[1])) { print "Copy $_[0] to $_[1]\n"; } else { print "SKIP $_[0]\n"; } } $skyrimPath = $ENV{'SkyrimPath'} or error("\$SkyrimPath env var not set."); $scriptPath = $skyrimPath . "\\Data\\Scripts\\Source"; $compilerPath = $skyrimPath . "\\Papyrus Compiler\\PapyrusCompiler.exe"; $compilerFlagPath = $scriptPath . "\\TESV_Papyrus_Flags.flg"; $filegroupPath = "filegroup_scripts.txt"; # Safety check error("Do not run this script in the vanilla scripts folder!") if (-e "Data\\Scripts\\Source\\TESV_Papyrus_Flags.flg"); # No wait? $noWait = defined($ARGV[0]); # Clean old files unlink($_) foreach (); # Compile files in Source/ @argList = ( "$compilerPath", "Data\\Scripts\\Source", "-i=Data\\Scripts\\Source; $scriptPath", "-o=Data\\Scripts", "-f=$compilerFlagPath", # "-op", "-all" ); system(@argList) == 0 or error("Compile failed."); # Generate filegroup list open(OUT, ">$filegroupPath") or error("Cannot open $filegroupPath: $!"); print OUT "Scripts\\" . basename($_) . "\n" foreach (); print OUT "Scripts\\Source\\" . basename($_) . "\n" foreach (); close(OUT); # Copy *.pex to game dir copyFile($_, $skyrimPath . "\\" . $_ ) foreach (); getc(STDIN) unless $noWait; exit(0); ================================================ FILE: misc/ArrowCount/Scripts/Source/PN_ArrowCountWidget.psc ================================================ scriptname PN_ArrowCountWidget extends SKI_WidgetBase ; PRIVATE VARIABLES ------------------------------------------------------------------------------- bool _visible = false int _count = 0 ; PROPERTIES -------------------------------------------------------------------------------------- bool Property Visible bool function get() return _visible endFunction function set(bool a_val) _visible = a_val if (Ready) UI.InvokeBool(HUD_MENU, WidgetRoot + ".setVisible", _visible) endIf endFunction endProperty int property Count int function get() return _count endFunction function set(int a_val) _count = a_val if (Ready) UI.InvokeInt(HUD_MENU, WidgetRoot + ".setCount", _count) endIf endFunction endProperty ; EVENTS ------------------------------------------------------------------------------------------ ; @override SKI_WidgetBase event OnWidgetReset() parent.OnWidgetReset() UI.InvokeBool(HUD_MENU, WidgetRoot + ".setVisible", _visible) UI.InvokeInt(HUD_MENU, WidgetRoot + ".setCount", _count) endEvent ; FUNCTIONS --------------------------------------------------------------------------------------- ; @overrides SKI_WidgetBase string function GetWidgetSource() return "skyui/arrowcount.swf" endFunction ; @overrides SKI_WidgetBase string function GetWidgetType() ; Must be the same as scriptname return "SKI_ArrowCountWidget" endFunction ================================================ FILE: misc/Configs/5760x1080, by Ismelda/skyui.cfg ================================================ ; ===================================================================================================================== [Input] ; ===================================================================================================================== hotkey.search = 32 ; SPACE hotkey.tabToggle = 18 ; ALT ; ===================================================================================================================== [SearchBox] ; ===================================================================================================================== autoupdate.enable = true autoupdate.delay = 0 ; ===================================================================================================================== [ItemInfo] ; ===================================================================================================================== itemcard.align = right itemcard.xOffset = -60 itemcard.yOffset = 0 itemicon.xOffset = 50 itemicon.yOffset = -12 itemicon.scale = 0.8 ; ===================================================================================================================== [ItemList] ; ===================================================================================================================== entry.width = 530 entry.icon.showStolen = true entry.color.enabled.text = 0xffffff entry.color.enabled.stolen = 0xffffff entry.color.enabled.negative = 0xff0000 entry.color.disabled.text = 0x4c4c4c entry.color.disabled.stolen = 0x4c4c4c entry.color.disabled.negative = 0x800000 ; Format defaults ------------------------------------------------------------------------------------------ entry.format.font = '$EverywhereMediumFont' entry.format.align = left entry.format.bold = false entry.format.italic = false entry.format.underline = false entry.format.size = 14 entry.format.letterSpacing = 0.8 entry.format.kerning = false entry.format.leftMargin = 0 entry.format.rightMargin = 0 entry.format.indent = 0 entry.format.leading = 0 label.format.font = '$EverywhereMediumFont' label.format.align = left label.format.bold = false label.format.italic = false label.format.underline = false label.format.size = 12 label.format.letterSpacing = 0.8 label.format.kerning = false label.format.leftMargin = 0 label.format.rightMargin = 0 label.format.indent = 0 label.format.leading = 0 ; ICONS ------------------------------------------------------------------------------------------ equipColumn.type = EQUIP_ICON equipColumn.passive = true equipColumn.indent = -28 equipColumn.label.text = ' ' equipColumn.icon.size = 18 equipColumn.border = <0, 10, 3, 3> ; left right top bottom iconColumn.type = ITEM_ICON iconColumn.passive = true iconColumn.icon.size = 18 iconColumn.label.text = ' ' iconColumn.border = <0, 3, 3, 3> ; left right top bottom ; DEFAULT NAME COLUMN ------------------------------------------------------- nameColumn.type = NAME nameColumn.states = 2 nameColumn.weight = 0.9 nameColumn.border = <0, 0, 1.1, 0> ; left right top bottom nameColumn.state1.label.text = '$NAME' nameColumn.state1.entry.text = @text nameColumn.state1.sortOptions = {ASCENDING | CASEINSENSITIVE} nameColumn.state2.label.text = '$STOLEN' nameColumn.state2.entry.text = @text nameColumn.state2.sortAttributes = nameColumn.state2.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; ALL/FAV NAME COLUMN ------------------------------------------------------- allNameColumn.type = NAME allNameColumn.states = 4 allNameColumn.weight = 0.9 allNameColumn.border = <0, 0, 1.1, 0> ; left right top bottom allNameColumn.state1.label.text = '$NAME' allNameColumn.state1.entry.text = @text allNameColumn.state1.sortOptions = {ASCENDING | CASEINSENSITIVE} allNameColumn.state2.label.text = '$EQUIPPED' allNameColumn.state2.entry.text = @text allNameColumn.state2.sortAttributes = allNameColumn.state2.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> allNameColumn.state3.label.text = '$STOLEN' allNameColumn.state3.entry.text = @text allNameColumn.state3.sortAttributes = allNameColumn.state3.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> allNameColumn.state4.label.text = '$ENCHANTED' allNameColumn.state4.entry.text = @text allNameColumn.state4.sortAttributes = allNameColumn.state4.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; ARMOR/WEAPON NAME COLUMN ------------------------------------------------------- awNameColumn.type = NAME awNameColumn.states = 4 awNameColumn.weight = 0.7 awNameColumn.border = <0, 0, 1.1, 0> ; left right top bottom awNameColumn.state1.label.text = '$NAME' awNameColumn.state1.entry.text = @text awNameColumn.state1.sortOptions = {ASCENDING | CASEINSENSITIVE} awNameColumn.state2.label.text = '$EQUIPPED' awNameColumn.state2.entry.text = @text awNameColumn.state2.sortAttributes = awNameColumn.state2.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> awNameColumn.state3.label.text = '$STOLEN' awNameColumn.state3.entry.text = @text awNameColumn.state3.sortAttributes = awNameColumn.state3.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> awNameColumn.state4.label.text = '$ENCHANTED' awNameColumn.state4.entry.text = @text awNameColumn.state4.sortAttributes = awNameColumn.state4.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; CONTAINER ARMOR/WEAPON NAME COLUMN ------------------------------------------------------- awContNameColumn.type = NAME awContNameColumn.states = 3 awContNameColumn.weight = 0.7 awContNameColumn.border = <0, 0, 1.1, 0> ; left right top bottom awContNameColumn.state1.label.text = '$NAME' awContNameColumn.state1.entry.text = @text awContNameColumn.state1.sortOptions = {ASCENDING | CASEINSENSITIVE} awContNameColumn.state2.label.text = '$STOLEN' awContNameColumn.state2.entry.text = @text awContNameColumn.state2.sortAttributes = awContNameColumn.state2.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> awContNameColumn.state3.label.text = '$ENCHANTED' awContNameColumn.state3.entry.text = @text awContNameColumn.state3.sortAttributes = awContNameColumn.state3.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; CONTAINER ALL NAME COLUMN ------------------------------------------------------- allContNameColumn.type = NAME allContNameColumn.states = 3 allContNameColumn.weight = 0.9 allContNameColumn.border = <0, 0, 1.1, 0> ; left right top bottom allContNameColumn.state1.label.text = '$NAME' allContNameColumn.state1.entry.text = @text allContNameColumn.state1.sortOptions = {ASCENDING | CASEINSENSITIVE} allContNameColumn.state2.label.text = '$STOLEN' allContNameColumn.state2.entry.text = @text allContNameColumn.state2.sortAttributes = allContNameColumn.state2.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> allContNameColumn.state3.label.text = '$ENCHANTED' allContNameColumn.state3.entry.text = @text allContNameColumn.state3.sortAttributes = allContNameColumn.state3.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; ARMOR COLUMN ------------------------------------------------------- arColumn.type = TEXT arColumn.states = 2 arColumn.weight = 0.2 arColumn.border = <0, 0, 1.1, 0> ; left right top bottom arColumn.label.format.align = left arColumn.entry.format.align = left arColumn.state1.label.text = '$ARMOR' arColumn.state1.label.arrowDown = true arColumn.state1.entry.text = @infoArmor arColumn.state1.sortAttributes = arColumn.state1.sortOptions = <{DESCENDING | NUMERIC}, {DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> arColumn.state2.label.text = '$ARMOR' arColumn.state2.entry.text = @infoArmor arColumn.state2.sortAttributes = arColumn.state2.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; DAMAGE COLUMN ------------------------------------------------------- damageColumn.type = TEXT damageColumn.states = 2 damageColumn.weight = 0.2 damageColumn.border = <0, 0, 1.1, 0> ; left right top bottom damageColumn.label.format.align = left damageColumn.entry.format.align = left damageColumn.state1.label.text = '$DAMAGE' damageColumn.state1.label.arrowDown = true damageColumn.state1.entry.text = @infoDamage damageColumn.state1.sortAttributes = damageColumn.state1.sortOptions = <{DESCENDING | NUMERIC}, {DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> damageColumn.state2.label.text = '$DAMAGE' damageColumn.state2.entry.text = @infoDamage damageColumn.state2.sortAttributes = damageColumn.state2.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; WEIGHT COLUMN ------------------------------------------------------- weightColumn.type = TEXT weightColumn.states = 2 weightColumn.weight = 0.2 weightColumn.border = <0, 0, 1.1, 0> ; left right top bottom weightColumn.label.format.align = left weightColumn.entry.format.align = left weightColumn.state1.label.text = '$WEIGHT' weightColumn.state1.label.arrowDown = true weightColumn.state1.entry.text = @infoWeight weightColumn.state1.sortAttributes = weightColumn.state1.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> weightColumn.state2.label.text = '$WEIGHT' weightColumn.state2.entry.text = @infoWeight weightColumn.state2.sortAttributes = weightColumn.state2.sortOptions = <{ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; VALUE COLUMN ------------------------------------------------------- valueColumn.type = TEXT valueColumn.states = 4 valueColumn.weight = 0.1 valueColumn.border = <0, 0, 1.1, 0> ; left right top bottom valueColumn.label.format.align = left valueColumn.entry.format.align = left valueColumn.state1.label.text = '$VALUE' valueColumn.state1.label.arrowDown = true valueColumn.state1.entry.text = @infoValue valueColumn.state1.sortAttributes = valueColumn.state1.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> valueColumn.state2.label.text = '$VALUE' valueColumn.state2.entry.text = @infoValue valueColumn.state2.sortAttributes = valueColumn.state2.sortOptions = <{ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> valueColumn.state3.label.text = '$V/W' valueColumn.state3.label.arrowDown = true valueColumn.state3.entry.text = @infoWeightValue valueColumn.state3.sortAttributes = valueColumn.state3.sortOptions = <{DESCENDING | NUMERIC}, {DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> valueColumn.state4.label.text = '$V/W' valueColumn.state4.entry.text = @infoWeightValue valueColumn.state4.sortAttributes = valueColumn.state4.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; VALUE/WEIGHT COLUMN ------------------------------------------------------- valueWeightColumn.type = TEXT valueWeightColumn.states = 2 valueWeightColumn.weight = 0.1 valueWeightColumn.border = <0, 0, 1.1, 0> ; left right top bottom valueWeightColumn.label.format.align = left valueWeightColumn.entry.format.align = left valueWeightColumn.state1.label.text = '$V/W' valueWeightColumn.state1.label.arrowDown = true valueWeightColumn.state1.entry.text = @infoWeightValue valueWeightColumn.state1.sortAttributes = valueWeightColumn.state1.sortOptions = <{DESCENDING | NUMERIC}, {DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> valueWeightColumn.state2.label.text = '$V/W' valueWeightColumn.state2.entry.text = @infoWeightValue valueWeightColumn.state2.sortAttributes = valueWeightColumn.state2.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; VIEWS ------------------------------------------------------- defaultView.primaryColumn = nameColumn defaultView.columns = weaponView.primaryColumn = awNameColumn weaponView.columns = weaponView.category = CAT_INV_WEAPONS armorView.primaryColumn = awNameColumn armorView.columns = armorView.category = CAT_INV_ARMOR allView.primaryColumn = allNameColumn allView.columns = allView.category = contWeaponView.primaryColumn = awContNameColumn contWeaponView.columns = contWeaponView.category = CAT_CONTAINER_WEAPONS contArmorView.primaryColumn = awContNameColumn contArmorView.columns = contArmorView.category = CAT_CONTAINER_ARMOR contAllView.primaryColumn = allContNameColumn contAllView.columns = contAllView.category = CAT_CONTAINER_ALL views = ; ===================================================================================================================== [MagicList] ; ===================================================================================================================== entry.width = 530 ; Format defaults ------------------------------------------------------------------------------------------ entry.format.font = '$EverywhereMediumFont' entry.format.align = left entry.format.bold = false entry.format.italic = false entry.format.underline = false entry.format.size = 14 entry.format.letterSpacing = 0.8 entry.format.kerning = false entry.format.leftMargin = 0 entry.format.rightMargin = 0 entry.format.indent = 0 entry.format.leading = 0 label.format.font = '$EverywhereMediumFont' label.format.align = left label.format.bold = false label.format.italic = false label.format.underline = false label.format.size = 12 label.format.letterSpacing = 0.8 label.format.kerning = false label.format.leftMargin = 0 label.format.rightMargin = 0 label.format.indent = 0 label.format.leading = 0 ; ICONS ------------------------------------------------------------------------------------------ equipColumn.type = EQUIP_ICON equipColumn.passive = true equipColumn.indent = -28 equipColumn.label.text = ' ' equipColumn.icon.size = 18 equipColumn.border = <0, 10, 3, 3> ; left right top bottom iconColumn.type = ITEM_ICON iconColumn.passive = true iconColumn.icon.size = 18 iconColumn.label.text = ' ' iconColumn.border = <0, 3, 3, 3> ; left right top bottom ; NAME COLUMN ------------------------------------------------------- nameColumn.type = NAME nameColumn.states = 3 nameColumn.weight = 1.1 nameColumn.border = <0, 0, 1.1, 0> ; left right top bottom nameColumn.state1.label.text = '$NAME' nameColumn.state1.entry.text = @text nameColumn.state1.sortOptions = {ASCENDING | CASEINSENSITIVE} nameColumn.state2.label.text = '$NAME' nameColumn.state2.entry.text = @text nameColumn.state2.label.arrowDown = true nameColumn.state2.sortOptions = {DESCENDING | CASEINSENSITIVE} nameColumn.state3.label.text = '$FAVORITE' nameColumn.state3.entry.text = @text nameColumn.state3.sortAttributes = nameColumn.state3.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; ALL NAME COLUMN ------------------------------------------------------- allNameColumn.type = NAME allNameColumn.states = 3 allNameColumn.weight = 0.75 allNameColumn.border = <0, 0, 1.1, 0> ; left right top bottom allNameColumn.state1.label.text = '$NAME' allNameColumn.state1.entry.text = @text allNameColumn.state1.sortOptions = {ASCENDING | CASEINSENSITIVE} allNameColumn.state2.label.text = '$NAME' allNameColumn.state2.entry.text = @text allNameColumn.state2.label.arrowDown = true allNameColumn.state2.sortOptions = {DESCENDING | CASEINSENSITIVE} allNameColumn.state3.label.text = '$FAVORITE' allNameColumn.state3.entry.text = @text allNameColumn.state3.sortAttributes = allNameColumn.state3.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; POWER NAME COLUMN ------------------------------------------------------- powersNameColumn.type = NAME powersNameColumn.states = 3 powersNameColumn.weight = 1.45 powersNameColumn.border = <0, 0, 1.1, 0> ; left right top bottom powersNameColumn.state1.label.text = '$NAME' powersNameColumn.state1.entry.text = @text powersNameColumn.state1.sortOptions = {ASCENDING | CASEINSENSITIVE} powersNameColumn.state2.label.text = '$NAME' powersNameColumn.state2.entry.text = @text powersNameColumn.state2.label.arrowDown = true powersNameColumn.state2.sortOptions = {DESCENDING | CASEINSENSITIVE} powersNameColumn.state3.label.text = '$FAVORITE' powersNameColumn.state3.entry.text = @text powersNameColumn.state3.sortAttributes = powersNameColumn.state3.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; SPELL COST COLUMN ------------------------------------------- spellCostColumn.type = TEXT spellCostColumn.states = 2 spellCostColumn.weight = 0.2 spellCostColumn.border = <0, 0, 1.1, 0> ; left right top bottom spellCostColumn.label.format.align = left spellCostColumn.entry.format.align = left spellCostColumn.state1.label.text = '$SPELL COST' spellCostColumn.state1.label.arrowDown = true spellCostColumn.state1.entry.text = @infoSpellCostStr spellCostColumn.state1.sortAttributes = spellCostColumn.state1.sortOptions = <{DESCENDING | NUMERIC}, {DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> spellCostColumn.state2.label.text = '$SPELL COST' spellCostColumn.state2.label.arrowDown = false spellCostColumn.state2.entry.text = @infoSpellCostStr spellCostColumn.state2.sortAttributes = spellCostColumn.state2.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; WORD 1 COLUMN ------------------------------------------- word1Column.type = TEXT word1Column.states = 2 word1Column.weight = 0.5 word1Column.border = <0, 0, 1.1, 0> ; left right top bottom word1Column.label.format.align = left word1Column.entry.format.align = left word1Column.state1.label.text = '$FIRST WORD' word1Column.state1.label.arrowDown = true word1Column.state1.entry.text = @infoWord1 word1Column.state1.sortAttributes = word1Column.state1.sortOptions = <{DESCENDING | NUMERIC}, {DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> word1Column.state2.label.text = '$FIRST WORD' word1Column.state2.label.arrowDown = false word1Column.state2.entry.text = @infoWord1 word1Column.state2.sortAttributes = word1Column.state2.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; WORD 2 COLUMN ------------------------------------------- word2Column.type = TEXT word2Column.states = 2 word2Column.weight = 0.5 word2Column.border = <0, 0, 1.1, 0> ; left right top bottom word2Column.label.format.align = left word2Column.entry.format.align = left word2Column.state1.label.text = '$SECOND WORD' word2Column.state1.label.arrowDown = true word2Column.state1.entry.text = @infoWord2 word2Column.state1.sortAttributes = word2Column.state1.sortOptions = <{DESCENDING | NUMERIC}, {DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> word2Column.state2.label.text = '$SECOND WORD' word2Column.state2.label.arrowDown = false word2Column.state2.entry.text = @infoWord2 word2Column.state2.sortAttributes = word2Column.state2.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; WORD 3 COLUMN ------------------------------------------- word3Column.type = TEXT word3Column.states = 2 word3Column.weight = 0.35 word3Column.border = <0, 0, 1.1, 0> ; left right top bottom word3Column.label.format.align = left word3Column.entry.format.align = left word3Column.state1.label.text = '$THIRD WORD' word3Column.state1.label.arrowDown = true word3Column.state1.entry.text = @infoWord3 word3Column.state1.sortAttributes = word3Column.state1.sortOptions = <{DESCENDING | NUMERIC}, {DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> word3Column.state2.label.text = '$THIRD WORD' word3Column.state2.label.arrowDown = false word3Column.state2.entry.text = @infoWord3 word3Column.state2.sortAttributes = word3Column.state2.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; SCHOOL COLUMN ------------------------------------------- schoolColumn.type = TEXT schoolColumn.states = 2 schoolColumn.weight = 0.35 schoolColumn.border = <0, 0, 1.1, 0> ; left right top bottom schoolColumn.label.format.align = left schoolColumn.entry.format.align = left schoolColumn.state1.label.text = '$SCHOOL' schoolColumn.state1.label.arrowDown = false schoolColumn.state1.entry.text = @infoSchoolName schoolColumn.state1.sortAttributes = schoolColumn.state1.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}, {ASCENDING | CASEINSENSITIVE}> schoolColumn.state2.label.text = '$SCHOOL' schoolColumn.state2.label.arrowDown = true schoolColumn.state2.entry.text = @infoSchoolName schoolColumn.state2.sortAttributes = schoolColumn.state2.sortOptions = <{DESCENDING | NUMERIC}, {DESCENDING | CASEINSENSITIVE}, {ASCENDING | CASEINSENSITIVE}> ; LEVEL COLUMN ------------------------------------------- levelColumn.type = TEXT levelColumn.states = 2 levelColumn.weight = 0.35 levelColumn.border = <0, 0, 1.1, 0> ; left right top bottom levelColumn.label.format.align = left levelColumn.entry.format.align = left levelColumn.state1.label.text = '$SKILL LEVEL' levelColumn.state1.label.arrowDown = false levelColumn.state1.entry.text = @infoSkillLevel levelColumn.state1.sortAttributes = levelColumn.state1.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}, {ASCENDING | CASEINSENSITIVE}> levelColumn.state2.label.text = '$SKILL LEVEL' levelColumn.state2.label.arrowDown = true levelColumn.state2.entry.text = @infoSkillLevel levelColumn.state2.sortAttributes = levelColumn.state2.sortOptions = <{DESCENDING | NUMERIC}, {DESCENDING | CASEINSENSITIVE}, {ASCENDING | CASEINSENSITIVE}> ; EFFECT NAME COLUMN ------------------------------------------------------- effNameColumn.type = NAME effNameColumn.states = 2 effNameColumn.weight = 0.5 effNameColumn.border = <0, 0, 1.1, 0> ; left right top bottom effNameColumn.state1.label.text = '$NAME' effNameColumn.state1.entry.text = @text effNameColumn.state1.sortOptions = {ASCENDING | CASEINSENSITIVE} effNameColumn.state2.label.text = '$NAME' effNameColumn.state2.entry.text = @text effNameColumn.state2.label.arrowDown = true effNameColumn.state2.sortOptions = {DESCENDING | CASEINSENSITIVE} ; TIME REMAINING COLUMN ------------------------------------------- timeRemainingColumn.type = TEXT timeRemainingColumn.states = 2 timeRemainingColumn.weight = 0.5 timeRemainingColumn.border = <0, 0, 1.1, 0> ; left right top bottom timeRemainingColumn.label.format.align = center timeRemainingColumn.entry.format.align = center timeRemainingColumn.state1.label.text = '$TIME LEFT' timeRemainingColumn.state1.label.arrowDown = false timeRemainingColumn.state1.entry.text = @infoTimeRemainingStr timeRemainingColumn.state1.sortAttributes = timeRemainingColumn.state1.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> timeRemainingColumn.state2.label.text = '$TIME LEFT' timeRemainingColumn.state2.label.arrowDown = true timeRemainingColumn.state2.entry.text = @infoTimeRemainingStr timeRemainingColumn.state2.sortAttributes = timeRemainingColumn.state2.sortOptions = <{DESCENDING | NUMERIC}, {DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; ITEM COLUMN ------------------------------------------- itemColumn.type = TEXT itemColumn.states = 2 itemColumn.weight = 0.5 itemColumn.border = <0, 0, 1.1, 0> ; left right top bottom itemColumn.label.format.align = right itemColumn.entry.format.align = right itemColumn.state1.label.text = '$SOURCE' itemColumn.state1.label.arrowDown = false itemColumn.state1.entry.text = @infoItem itemColumn.state1.sortAttributes = itemColumn.state1.sortOptions = <{ASCENDING | CASEINSENSITIVE}, {ASCENDING | CASEINSENSITIVE}> itemColumn.state2.label.text = '$SOURCE' itemColumn.state2.label.arrowDown = true itemColumn.state2.entry.text = @infoItem itemColumn.state2.sortAttributes = itemColumn.state2.sortOptions = <{DESCENDING | CASEINSENSITIVE}, {ASCENDING | CASEINSENSITIVE}> ; VIEWS ------------------------------------------------------- defaultView.primaryColumn = nameColumn defaultView.columns = allView.primaryColumn = allNameColumn allView.columns = allView.category = shoutsView.primaryColumn = nameColumn shoutsView.columns = shoutsView.category = CAT_MAG_SHOUTS powersView.primaryColumn = powersNameColumn powersView.columns = powersView.category = CAT_MAG_POWERS activeEffectView.primaryColumn = effNameColumn activeEffectView.columns = activeEffectView.category = CAT_MAG_EFFECTS views = ================================================ FILE: misc/Configs/5760x2160, by Ismelda/skyui.cfg ================================================ ; ===================================================================================================================== [Input] ; ===================================================================================================================== hotkey.search = 32 ; SPACE hotkey.tabToggle = 18 ; ALT ; ===================================================================================================================== [SearchBox] ; ===================================================================================================================== autoupdate.enable = true autoupdate.delay = 0 ; ===================================================================================================================== [ItemInfo] ; ===================================================================================================================== itemcard.align = right itemcard.xOffset = -22 itemcard.yOffset = 0 itemicon.xOffset = 42 itemicon.yOffset = -12 itemicon.scale = 1.5 ; ===================================================================================================================== [ItemList] ; ===================================================================================================================== entry.width = 530 entry.icon.showStolen = true entry.color.enabled.text = 0xffffff entry.color.enabled.stolen = 0xffffff entry.color.enabled.negative = 0xff0000 entry.color.disabled.text = 0x4c4c4c entry.color.disabled.stolen = 0x4c4c4c entry.color.disabled.negative = 0x800000 ; Format defaults ------------------------------------------------------------------------------------------ entry.format.font = '$EverywhereMediumFont' entry.format.align = left entry.format.bold = false entry.format.italic = false entry.format.underline = false entry.format.size = 14 entry.format.letterSpacing = 0.8 entry.format.kerning = false entry.format.leftMargin = 0 entry.format.rightMargin = 0 entry.format.indent = 0 entry.format.leading = 0 label.format.font = '$EverywhereMediumFont' label.format.align = left label.format.bold = false label.format.italic = false label.format.underline = false label.format.size = 12 label.format.letterSpacing = 0.8 label.format.kerning = false label.format.leftMargin = 0 label.format.rightMargin = 0 label.format.indent = 0 label.format.leading = 0 ; ICONS ------------------------------------------------------------------------------------------ equipColumn.type = EQUIP_ICON equipColumn.passive = true equipColumn.indent = -28 equipColumn.label.text = ' ' equipColumn.icon.size = 18 equipColumn.border = <0, 10, 3, 3> ; left right top bottom iconColumn.type = ITEM_ICON iconColumn.passive = true iconColumn.icon.size = 18 iconColumn.label.text = ' ' iconColumn.border = <0, 3, 3, 3> ; left right top bottom ; DEFAULT NAME COLUMN ------------------------------------------------------- nameColumn.type = NAME nameColumn.states = 2 nameColumn.weight = 0.9 nameColumn.border = <0, 0, 1.1, 0> ; left right top bottom nameColumn.state1.label.text = '$NAME' nameColumn.state1.entry.text = @text nameColumn.state1.sortOptions = {ASCENDING | CASEINSENSITIVE} nameColumn.state2.label.text = '$STOLEN' nameColumn.state2.entry.text = @text nameColumn.state2.sortAttributes = nameColumn.state2.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; ALL/FAV NAME COLUMN ------------------------------------------------------- allNameColumn.type = NAME allNameColumn.states = 4 allNameColumn.weight = 0.9 allNameColumn.border = <0, 0, 1.1, 0> ; left right top bottom allNameColumn.state1.label.text = '$NAME' allNameColumn.state1.entry.text = @text allNameColumn.state1.sortOptions = {ASCENDING | CASEINSENSITIVE} allNameColumn.state2.label.text = '$EQUIPPED' allNameColumn.state2.entry.text = @text allNameColumn.state2.sortAttributes = allNameColumn.state2.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> allNameColumn.state3.label.text = '$STOLEN' allNameColumn.state3.entry.text = @text allNameColumn.state3.sortAttributes = allNameColumn.state3.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> allNameColumn.state4.label.text = '$ENCHANTED' allNameColumn.state4.entry.text = @text allNameColumn.state4.sortAttributes = allNameColumn.state4.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; ARMOR/WEAPON NAME COLUMN ------------------------------------------------------- awNameColumn.type = NAME awNameColumn.states = 4 awNameColumn.weight = 0.7 awNameColumn.border = <0, 0, 1.1, 0> ; left right top bottom awNameColumn.state1.label.text = '$NAME' awNameColumn.state1.entry.text = @text awNameColumn.state1.sortOptions = {ASCENDING | CASEINSENSITIVE} awNameColumn.state2.label.text = '$EQUIPPED' awNameColumn.state2.entry.text = @text awNameColumn.state2.sortAttributes = awNameColumn.state2.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> awNameColumn.state3.label.text = '$STOLEN' awNameColumn.state3.entry.text = @text awNameColumn.state3.sortAttributes = awNameColumn.state3.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> awNameColumn.state4.label.text = '$ENCHANTED' awNameColumn.state4.entry.text = @text awNameColumn.state4.sortAttributes = awNameColumn.state4.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; CONTAINER ARMOR/WEAPON NAME COLUMN ------------------------------------------------------- awContNameColumn.type = NAME awContNameColumn.states = 3 awContNameColumn.weight = 0.7 awContNameColumn.border = <0, 0, 1.1, 0> ; left right top bottom awContNameColumn.state1.label.text = '$NAME' awContNameColumn.state1.entry.text = @text awContNameColumn.state1.sortOptions = {ASCENDING | CASEINSENSITIVE} awContNameColumn.state2.label.text = '$STOLEN' awContNameColumn.state2.entry.text = @text awContNameColumn.state2.sortAttributes = awContNameColumn.state2.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> awContNameColumn.state3.label.text = '$ENCHANTED' awContNameColumn.state3.entry.text = @text awContNameColumn.state3.sortAttributes = awContNameColumn.state3.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; CONTAINER ALL NAME COLUMN ------------------------------------------------------- allContNameColumn.type = NAME allContNameColumn.states = 3 allContNameColumn.weight = 0.9 allContNameColumn.border = <0, 0, 1.1, 0> ; left right top bottom allContNameColumn.state1.label.text = '$NAME' allContNameColumn.state1.entry.text = @text allContNameColumn.state1.sortOptions = {ASCENDING | CASEINSENSITIVE} allContNameColumn.state2.label.text = '$STOLEN' allContNameColumn.state2.entry.text = @text allContNameColumn.state2.sortAttributes = allContNameColumn.state2.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> allContNameColumn.state3.label.text = '$ENCHANTED' allContNameColumn.state3.entry.text = @text allContNameColumn.state3.sortAttributes = allContNameColumn.state3.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; ARMOR COLUMN ------------------------------------------------------- arColumn.type = TEXT arColumn.states = 2 arColumn.weight = 0.2 arColumn.border = <0, 0, 1.1, 0> ; left right top bottom arColumn.label.format.align = left arColumn.entry.format.align = left arColumn.state1.label.text = '$ARMOR' arColumn.state1.label.arrowDown = true arColumn.state1.entry.text = @infoArmor arColumn.state1.sortAttributes = arColumn.state1.sortOptions = <{DESCENDING | NUMERIC}, {DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> arColumn.state2.label.text = '$ARMOR' arColumn.state2.entry.text = @infoArmor arColumn.state2.sortAttributes = arColumn.state2.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; DAMAGE COLUMN ------------------------------------------------------- damageColumn.type = TEXT damageColumn.states = 2 damageColumn.weight = 0.2 damageColumn.border = <0, 0, 1.1, 0> ; left right top bottom damageColumn.label.format.align = left damageColumn.entry.format.align = left damageColumn.state1.label.text = '$DAMAGE' damageColumn.state1.label.arrowDown = true damageColumn.state1.entry.text = @infoDamage damageColumn.state1.sortAttributes = damageColumn.state1.sortOptions = <{DESCENDING | NUMERIC}, {DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> damageColumn.state2.label.text = '$DAMAGE' damageColumn.state2.entry.text = @infoDamage damageColumn.state2.sortAttributes = damageColumn.state2.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; WEIGHT COLUMN ------------------------------------------------------- weightColumn.type = TEXT weightColumn.states = 2 weightColumn.weight = 0.2 weightColumn.border = <0, 0, 1.1, 0> ; left right top bottom weightColumn.label.format.align = left weightColumn.entry.format.align = left weightColumn.state1.label.text = '$WEIGHT' weightColumn.state1.label.arrowDown = true weightColumn.state1.entry.text = @infoWeight weightColumn.state1.sortAttributes = weightColumn.state1.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> weightColumn.state2.label.text = '$WEIGHT' weightColumn.state2.entry.text = @infoWeight weightColumn.state2.sortAttributes = weightColumn.state2.sortOptions = <{ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; VALUE COLUMN ------------------------------------------------------- valueColumn.type = TEXT valueColumn.states = 4 valueColumn.weight = 0.1 valueColumn.border = <0, 0, 1.1, 0> ; left right top bottom valueColumn.label.format.align = left valueColumn.entry.format.align = left valueColumn.state1.label.text = '$VALUE' valueColumn.state1.label.arrowDown = true valueColumn.state1.entry.text = @infoValue valueColumn.state1.sortAttributes = valueColumn.state1.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> valueColumn.state2.label.text = '$VALUE' valueColumn.state2.entry.text = @infoValue valueColumn.state2.sortAttributes = valueColumn.state2.sortOptions = <{ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> valueColumn.state3.label.text = '$V/W' valueColumn.state3.label.arrowDown = true valueColumn.state3.entry.text = @infoWeightValue valueColumn.state3.sortAttributes = valueColumn.state3.sortOptions = <{DESCENDING | NUMERIC}, {DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> valueColumn.state4.label.text = '$V/W' valueColumn.state4.entry.text = @infoWeightValue valueColumn.state4.sortAttributes = valueColumn.state4.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; VALUE/WEIGHT COLUMN ------------------------------------------------------- valueWeightColumn.type = TEXT valueWeightColumn.states = 2 valueWeightColumn.weight = 0.1 valueWeightColumn.border = <0, 0, 1.1, 0> ; left right top bottom valueWeightColumn.label.format.align = left valueWeightColumn.entry.format.align = left valueWeightColumn.state1.label.text = '$V/W' valueWeightColumn.state1.label.arrowDown = true valueWeightColumn.state1.entry.text = @infoWeightValue valueWeightColumn.state1.sortAttributes = valueWeightColumn.state1.sortOptions = <{DESCENDING | NUMERIC}, {DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> valueWeightColumn.state2.label.text = '$V/W' valueWeightColumn.state2.entry.text = @infoWeightValue valueWeightColumn.state2.sortAttributes = valueWeightColumn.state2.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; VIEWS ------------------------------------------------------- defaultView.primaryColumn = nameColumn defaultView.columns = weaponView.primaryColumn = awNameColumn weaponView.columns = weaponView.category = CAT_INV_WEAPONS armorView.primaryColumn = awNameColumn armorView.columns = armorView.category = CAT_INV_ARMOR allView.primaryColumn = allNameColumn allView.columns = allView.category = contWeaponView.primaryColumn = awContNameColumn contWeaponView.columns = contWeaponView.category = CAT_CONTAINER_WEAPONS contArmorView.primaryColumn = awContNameColumn contArmorView.columns = contArmorView.category = CAT_CONTAINER_ARMOR contAllView.primaryColumn = allContNameColumn contAllView.columns = contAllView.category = CAT_CONTAINER_ALL views = ; ===================================================================================================================== [MagicList] ; ===================================================================================================================== entry.width = 530 ; Format defaults ------------------------------------------------------------------------------------------ entry.format.font = '$EverywhereMediumFont' entry.format.align = left entry.format.bold = false entry.format.italic = false entry.format.underline = false entry.format.size = 14 entry.format.letterSpacing = 0.8 entry.format.kerning = false entry.format.leftMargin = 0 entry.format.rightMargin = 0 entry.format.indent = 0 entry.format.leading = 0 label.format.font = '$EverywhereMediumFont' label.format.align = left label.format.bold = false label.format.italic = false label.format.underline = false label.format.size = 12 label.format.letterSpacing = 0.8 label.format.kerning = false label.format.leftMargin = 0 label.format.rightMargin = 0 label.format.indent = 0 label.format.leading = 0 ; ICONS ------------------------------------------------------------------------------------------ equipColumn.type = EQUIP_ICON equipColumn.passive = true equipColumn.indent = -28 equipColumn.label.text = ' ' equipColumn.icon.size = 18 equipColumn.border = <0, 10, 3, 3> ; left right top bottom iconColumn.type = ITEM_ICON iconColumn.passive = true iconColumn.icon.size = 18 iconColumn.label.text = ' ' iconColumn.border = <0, 3, 3, 3> ; left right top bottom ; NAME COLUMN ------------------------------------------------------- nameColumn.type = NAME nameColumn.states = 3 nameColumn.weight = 1.1 nameColumn.border = <0, 0, 1.1, 0> ; left right top bottom nameColumn.state1.label.text = '$NAME' nameColumn.state1.entry.text = @text nameColumn.state1.sortOptions = {ASCENDING | CASEINSENSITIVE} nameColumn.state2.label.text = '$NAME' nameColumn.state2.entry.text = @text nameColumn.state2.label.arrowDown = true nameColumn.state2.sortOptions = {DESCENDING | CASEINSENSITIVE} nameColumn.state3.label.text = '$FAVORITE' nameColumn.state3.entry.text = @text nameColumn.state3.sortAttributes = nameColumn.state3.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; ALL NAME COLUMN ------------------------------------------------------- allNameColumn.type = NAME allNameColumn.states = 3 allNameColumn.weight = 0.75 allNameColumn.border = <0, 0, 1.1, 0> ; left right top bottom allNameColumn.state1.label.text = '$NAME' allNameColumn.state1.entry.text = @text allNameColumn.state1.sortOptions = {ASCENDING | CASEINSENSITIVE} allNameColumn.state2.label.text = '$NAME' allNameColumn.state2.entry.text = @text allNameColumn.state2.label.arrowDown = true allNameColumn.state2.sortOptions = {DESCENDING | CASEINSENSITIVE} allNameColumn.state3.label.text = '$FAVORITE' allNameColumn.state3.entry.text = @text allNameColumn.state3.sortAttributes = allNameColumn.state3.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; POWER NAME COLUMN ------------------------------------------------------- powersNameColumn.type = NAME powersNameColumn.states = 3 powersNameColumn.weight = 1.45 powersNameColumn.border = <0, 0, 1.1, 0> ; left right top bottom powersNameColumn.state1.label.text = '$NAME' powersNameColumn.state1.entry.text = @text powersNameColumn.state1.sortOptions = {ASCENDING | CASEINSENSITIVE} powersNameColumn.state2.label.text = '$NAME' powersNameColumn.state2.entry.text = @text powersNameColumn.state2.label.arrowDown = true powersNameColumn.state2.sortOptions = {DESCENDING | CASEINSENSITIVE} powersNameColumn.state3.label.text = '$FAVORITE' powersNameColumn.state3.entry.text = @text powersNameColumn.state3.sortAttributes = powersNameColumn.state3.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; SPELL COST COLUMN ------------------------------------------- spellCostColumn.type = TEXT spellCostColumn.states = 2 spellCostColumn.weight = 0.2 spellCostColumn.border = <0, 0, 1.1, 0> ; left right top bottom spellCostColumn.label.format.align = left spellCostColumn.entry.format.align = left spellCostColumn.state1.label.text = '$SPELL COST' spellCostColumn.state1.label.arrowDown = true spellCostColumn.state1.entry.text = @infoSpellCostStr spellCostColumn.state1.sortAttributes = spellCostColumn.state1.sortOptions = <{DESCENDING | NUMERIC}, {DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> spellCostColumn.state2.label.text = '$SPELL COST' spellCostColumn.state2.label.arrowDown = false spellCostColumn.state2.entry.text = @infoSpellCostStr spellCostColumn.state2.sortAttributes = spellCostColumn.state2.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; WORD 1 COLUMN ------------------------------------------- word1Column.type = TEXT word1Column.states = 2 word1Column.weight = 0.5 word1Column.border = <0, 0, 1.1, 0> ; left right top bottom word1Column.label.format.align = left word1Column.entry.format.align = left word1Column.state1.label.text = '$FIRST WORD' word1Column.state1.label.arrowDown = true word1Column.state1.entry.text = @infoWord1 word1Column.state1.sortAttributes = word1Column.state1.sortOptions = <{DESCENDING | NUMERIC}, {DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> word1Column.state2.label.text = '$FIRST WORD' word1Column.state2.label.arrowDown = false word1Column.state2.entry.text = @infoWord1 word1Column.state2.sortAttributes = word1Column.state2.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; WORD 2 COLUMN ------------------------------------------- word2Column.type = TEXT word2Column.states = 2 word2Column.weight = 0.5 word2Column.border = <0, 0, 1.1, 0> ; left right top bottom word2Column.label.format.align = left word2Column.entry.format.align = left word2Column.state1.label.text = '$SECOND WORD' word2Column.state1.label.arrowDown = true word2Column.state1.entry.text = @infoWord2 word2Column.state1.sortAttributes = word2Column.state1.sortOptions = <{DESCENDING | NUMERIC}, {DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> word2Column.state2.label.text = '$SECOND WORD' word2Column.state2.label.arrowDown = false word2Column.state2.entry.text = @infoWord2 word2Column.state2.sortAttributes = word2Column.state2.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; WORD 3 COLUMN ------------------------------------------- word3Column.type = TEXT word3Column.states = 2 word3Column.weight = 0.35 word3Column.border = <0, 0, 1.1, 0> ; left right top bottom word3Column.label.format.align = left word3Column.entry.format.align = left word3Column.state1.label.text = '$THIRD WORD' word3Column.state1.label.arrowDown = true word3Column.state1.entry.text = @infoWord3 word3Column.state1.sortAttributes = word3Column.state1.sortOptions = <{DESCENDING | NUMERIC}, {DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> word3Column.state2.label.text = '$THIRD WORD' word3Column.state2.label.arrowDown = false word3Column.state2.entry.text = @infoWord3 word3Column.state2.sortAttributes = word3Column.state2.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; SCHOOL COLUMN ------------------------------------------- schoolColumn.type = TEXT schoolColumn.states = 2 schoolColumn.weight = 0.35 schoolColumn.border = <0, 0, 1.1, 0> ; left right top bottom schoolColumn.label.format.align = left schoolColumn.entry.format.align = left schoolColumn.state1.label.text = '$SCHOOL' schoolColumn.state1.label.arrowDown = false schoolColumn.state1.entry.text = @infoSchoolName schoolColumn.state1.sortAttributes = schoolColumn.state1.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}, {ASCENDING | CASEINSENSITIVE}> schoolColumn.state2.label.text = '$SCHOOL' schoolColumn.state2.label.arrowDown = true schoolColumn.state2.entry.text = @infoSchoolName schoolColumn.state2.sortAttributes = schoolColumn.state2.sortOptions = <{DESCENDING | NUMERIC}, {DESCENDING | CASEINSENSITIVE}, {ASCENDING | CASEINSENSITIVE}> ; LEVEL COLUMN ------------------------------------------- levelColumn.type = TEXT levelColumn.states = 2 levelColumn.weight = 0.35 levelColumn.border = <0, 0, 1.1, 0> ; left right top bottom levelColumn.label.format.align = left levelColumn.entry.format.align = left levelColumn.state1.label.text = '$SKILL LEVEL' levelColumn.state1.label.arrowDown = false levelColumn.state1.entry.text = @infoSkillLevel levelColumn.state1.sortAttributes = levelColumn.state1.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}, {ASCENDING | CASEINSENSITIVE}> levelColumn.state2.label.text = '$SKILL LEVEL' levelColumn.state2.label.arrowDown = true levelColumn.state2.entry.text = @infoSkillLevel levelColumn.state2.sortAttributes = levelColumn.state2.sortOptions = <{DESCENDING | NUMERIC}, {DESCENDING | CASEINSENSITIVE}, {ASCENDING | CASEINSENSITIVE}> ; EFFECT NAME COLUMN ------------------------------------------------------- effNameColumn.type = NAME effNameColumn.states = 2 effNameColumn.weight = 0.5 effNameColumn.border = <0, 0, 1.1, 0> ; left right top bottom effNameColumn.state1.label.text = '$NAME' effNameColumn.state1.entry.text = @text effNameColumn.state1.sortOptions = {ASCENDING | CASEINSENSITIVE} effNameColumn.state2.label.text = '$NAME' effNameColumn.state2.entry.text = @text effNameColumn.state2.label.arrowDown = true effNameColumn.state2.sortOptions = {DESCENDING | CASEINSENSITIVE} ; TIME REMAINING COLUMN ------------------------------------------- timeRemainingColumn.type = TEXT timeRemainingColumn.states = 2 timeRemainingColumn.weight = 0.5 timeRemainingColumn.border = <0, 0, 1.1, 0> ; left right top bottom timeRemainingColumn.label.format.align = center timeRemainingColumn.entry.format.align = center timeRemainingColumn.state1.label.text = '$TIME LEFT' timeRemainingColumn.state1.label.arrowDown = false timeRemainingColumn.state1.entry.text = @infoTimeRemainingStr timeRemainingColumn.state1.sortAttributes = timeRemainingColumn.state1.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> timeRemainingColumn.state2.label.text = '$TIME LEFT' timeRemainingColumn.state2.label.arrowDown = true timeRemainingColumn.state2.entry.text = @infoTimeRemainingStr timeRemainingColumn.state2.sortAttributes = timeRemainingColumn.state2.sortOptions = <{DESCENDING | NUMERIC}, {DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; ITEM COLUMN ------------------------------------------- itemColumn.type = TEXT itemColumn.states = 2 itemColumn.weight = 0.5 itemColumn.border = <0, 0, 1.1, 0> ; left right top bottom itemColumn.label.format.align = right itemColumn.entry.format.align = right itemColumn.state1.label.text = '$SOURCE' itemColumn.state1.label.arrowDown = false itemColumn.state1.entry.text = @infoItem itemColumn.state1.sortAttributes = itemColumn.state1.sortOptions = <{ASCENDING | CASEINSENSITIVE}, {ASCENDING | CASEINSENSITIVE}> itemColumn.state2.label.text = '$SOURCE' itemColumn.state2.label.arrowDown = true itemColumn.state2.entry.text = @infoItem itemColumn.state2.sortAttributes = itemColumn.state2.sortOptions = <{DESCENDING | CASEINSENSITIVE}, {ASCENDING | CASEINSENSITIVE}> ; VIEWS ------------------------------------------------------- defaultView.primaryColumn = nameColumn defaultView.columns = allView.primaryColumn = allNameColumn allView.columns = allView.category = shoutsView.primaryColumn = nameColumn shoutsView.columns = shoutsView.category = CAT_MAG_SHOUTS powersView.primaryColumn = powersNameColumn powersView.columns = powersView.category = CAT_MAG_POWERS activeEffectView.primaryColumn = effNameColumn activeEffectView.columns = activeEffectView.category = CAT_MAG_EFFECTS views = ================================================ FILE: misc/Configs/ValueWeight Column/skyui.cfg ================================================ ; ===================================================================================================================== [Input] ; ===================================================================================================================== hotkey.search = 32 ; SPACE hotkey.tabToggle = 18 ; ALT ; ===================================================================================================================== [SearchBox] ; ===================================================================================================================== autoupdate.enable = true autoupdate.delay = 0 ; ===================================================================================================================== [ItemInfo] ; ===================================================================================================================== itemcard.align = center itemcard.xOffset = 0 itemcard.yOffset = 0 itemicon.xOffset = 0 itemicon.yOffset = 0 itemicon.scale = 1.5 ; ===================================================================================================================== [ItemList] ; ===================================================================================================================== entry.width = 530 entry.icon.showStolen = true entry.color.enabled.text = 0xffffff entry.color.enabled.stolen = 0xffffff entry.color.enabled.negative = 0xff0000 entry.color.disabled.text = 0x4c4c4c entry.color.disabled.stolen = 0x4c4c4c entry.color.disabled.negative = 0x800000 ; Format defaults ------------------------------------------------------------------------------------------ entry.format.font = '$EverywhereMediumFont' entry.format.align = left entry.format.bold = false entry.format.italic = false entry.format.underline = false entry.format.size = 14 entry.format.letterSpacing = 0.8 entry.format.kerning = false entry.format.leftMargin = 0 entry.format.rightMargin = 0 entry.format.indent = 0 entry.format.leading = 0 label.format.font = '$EverywhereMediumFont' label.format.align = left label.format.bold = false label.format.italic = false label.format.underline = false label.format.size = 12 label.format.letterSpacing = 0.8 label.format.kerning = false label.format.leftMargin = 0 label.format.rightMargin = 0 label.format.indent = 0 label.format.leading = 0 ; ICONS ------------------------------------------------------------------------------------------ equipColumn.type = EQUIP_ICON equipColumn.passive = true equipColumn.indent = -28 equipColumn.label.text = ' ' equipColumn.icon.size = 18 equipColumn.border = <0, 10, 3, 3> ; left right top bottom iconColumn.type = ITEM_ICON iconColumn.passive = true iconColumn.icon.size = 18 iconColumn.label.text = ' ' iconColumn.border = <0, 3, 3, 3> ; left right top bottom ; DEFAULT NAME COLUMN ------------------------------------------------------- nameColumn.type = NAME nameColumn.states = 2 nameColumn.weight = 0.9 nameColumn.border = <0, 0, 1.1, 0> ; left right top bottom nameColumn.state1.label.text = '$NAME' nameColumn.state1.entry.text = @text nameColumn.state1.sortOptions = {ASCENDING | CASEINSENSITIVE} nameColumn.state2.label.text = '$STOLEN' nameColumn.state2.entry.text = @text nameColumn.state2.sortAttributes = nameColumn.state2.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; ALL/FAV NAME COLUMN ------------------------------------------------------- allNameColumn.type = NAME allNameColumn.states = 4 allNameColumn.weight = 0.9 allNameColumn.border = <0, 0, 1.1, 0> ; left right top bottom allNameColumn.state1.label.text = '$NAME' allNameColumn.state1.entry.text = @text allNameColumn.state1.sortOptions = {ASCENDING | CASEINSENSITIVE} allNameColumn.state2.label.text = '$EQUIPPED' allNameColumn.state2.entry.text = @text allNameColumn.state2.sortAttributes = allNameColumn.state2.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> allNameColumn.state3.label.text = '$STOLEN' allNameColumn.state3.entry.text = @text allNameColumn.state3.sortAttributes = allNameColumn.state3.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> allNameColumn.state4.label.text = '$ENCHANTED' allNameColumn.state4.entry.text = @text allNameColumn.state4.sortAttributes = allNameColumn.state4.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; ARMOR/WEAPON NAME COLUMN ------------------------------------------------------- awNameColumn.type = NAME awNameColumn.states = 4 awNameColumn.weight = 0.7 awNameColumn.border = <0, 0, 1.1, 0> ; left right top bottom awNameColumn.state1.label.text = '$NAME' awNameColumn.state1.entry.text = @text awNameColumn.state1.sortOptions = {ASCENDING | CASEINSENSITIVE} awNameColumn.state2.label.text = '$EQUIPPED' awNameColumn.state2.entry.text = @text awNameColumn.state2.sortAttributes = awNameColumn.state2.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> awNameColumn.state3.label.text = '$STOLEN' awNameColumn.state3.entry.text = @text awNameColumn.state3.sortAttributes = awNameColumn.state3.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> awNameColumn.state4.label.text = '$ENCHANTED' awNameColumn.state4.entry.text = @text awNameColumn.state4.sortAttributes = awNameColumn.state4.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; CONTAINER ARMOR/WEAPON NAME COLUMN ------------------------------------------------------- awContNameColumn.type = NAME awContNameColumn.states = 3 awContNameColumn.weight = 0.7 awContNameColumn.border = <0, 0, 1.1, 0> ; left right top bottom awContNameColumn.state1.label.text = '$NAME' awContNameColumn.state1.entry.text = @text awContNameColumn.state1.sortOptions = {ASCENDING | CASEINSENSITIVE} awContNameColumn.state2.label.text = '$STOLEN' awContNameColumn.state2.entry.text = @text awContNameColumn.state2.sortAttributes = awContNameColumn.state2.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> awContNameColumn.state3.label.text = '$ENCHANTED' awContNameColumn.state3.entry.text = @text awContNameColumn.state3.sortAttributes = awContNameColumn.state3.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; CONTAINER ALL NAME COLUMN ------------------------------------------------------- allContNameColumn.type = NAME allContNameColumn.states = 3 allContNameColumn.weight = 0.9 allContNameColumn.border = <0, 0, 1.1, 0> ; left right top bottom allContNameColumn.state1.label.text = '$NAME' allContNameColumn.state1.entry.text = @text allContNameColumn.state1.sortOptions = {ASCENDING | CASEINSENSITIVE} allContNameColumn.state2.label.text = '$STOLEN' allContNameColumn.state2.entry.text = @text allContNameColumn.state2.sortAttributes = allContNameColumn.state2.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> allContNameColumn.state3.label.text = '$ENCHANTED' allContNameColumn.state3.entry.text = @text allContNameColumn.state3.sortAttributes = allContNameColumn.state3.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; ARMOR COLUMN ------------------------------------------------------- arColumn.type = TEXT arColumn.states = 2 arColumn.weight = 0.2 arColumn.border = <0, 0, 1.1, 0> ; left right top bottom arColumn.label.format.align = left arColumn.entry.format.align = left arColumn.state1.label.text = '$ARMOR' arColumn.state1.label.arrowDown = true arColumn.state1.entry.text = @infoArmor arColumn.state1.sortAttributes = arColumn.state1.sortOptions = <{DESCENDING | NUMERIC}, {DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> arColumn.state2.label.text = '$ARMOR' arColumn.state2.entry.text = @infoArmor arColumn.state2.sortAttributes = arColumn.state2.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; DAMAGE COLUMN ------------------------------------------------------- damageColumn.type = TEXT damageColumn.states = 2 damageColumn.weight = 0.2 damageColumn.border = <0, 0, 1.1, 0> ; left right top bottom damageColumn.label.format.align = left damageColumn.entry.format.align = left damageColumn.state1.label.text = '$DAMAGE' damageColumn.state1.label.arrowDown = true damageColumn.state1.entry.text = @infoDamage damageColumn.state1.sortAttributes = damageColumn.state1.sortOptions = <{DESCENDING | NUMERIC}, {DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> damageColumn.state2.label.text = '$DAMAGE' damageColumn.state2.entry.text = @infoDamage damageColumn.state2.sortAttributes = damageColumn.state2.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; WEIGHT COLUMN ------------------------------------------------------- weightColumn.type = TEXT weightColumn.states = 2 weightColumn.weight = 0.2 weightColumn.border = <0, 0, 1.1, 0> ; left right top bottom weightColumn.label.format.align = left weightColumn.entry.format.align = left weightColumn.state1.label.text = '$WEIGHT' weightColumn.state1.label.arrowDown = true weightColumn.state1.entry.text = @infoWeight weightColumn.state1.sortAttributes = weightColumn.state1.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> weightColumn.state2.label.text = '$WEIGHT' weightColumn.state2.entry.text = @infoWeight weightColumn.state2.sortAttributes = weightColumn.state2.sortOptions = <{ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; VALUE COLUMN ------------------------------------------------------- valueColumn.type = TEXT valueColumn.states = 2 valueColumn.weight = 0.2 valueColumn.border = <0, 0, 1.1, 0> ; left right top bottom valueColumn.label.format.align = left valueColumn.entry.format.align = left valueColumn.state1.label.text = '$VALUE' valueColumn.state1.label.arrowDown = true valueColumn.state1.entry.text = @infoValue valueColumn.state1.sortAttributes = valueColumn.state1.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> valueColumn.state2.label.text = '$VALUE' valueColumn.state2.entry.text = @infoValue valueColumn.state2.sortAttributes = valueColumn.state2.sortOptions = <{ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> valueColumn.state3.label.text = '$V/W' valueColumn.state3.label.arrowDown = true valueColumn.state3.entry.text = @infoWeightValue valueColumn.state3.sortAttributes = valueColumn.state3.sortOptions = <{DESCENDING | NUMERIC}, {DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> valueColumn.state4.label.text = '$V/W' valueColumn.state4.entry.text = @infoWeightValue valueColumn.state4.sortAttributes = valueColumn.state4.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; VALUE/WEIGHT COLUMN ------------------------------------------------------- valueWeightColumn.type = TEXT valueWeightColumn.states = 2 valueWeightColumn.weight = 0.1 valueWeightColumn.border = <0, 0, 1.1, 0> ; left right top bottom valueWeightColumn.label.format.align = left valueWeightColumn.entry.format.align = left valueWeightColumn.state1.label.text = '$V/W' valueWeightColumn.state1.label.arrowDown = true valueWeightColumn.state1.entry.text = @infoWeightValue valueWeightColumn.state1.sortAttributes = valueWeightColumn.state1.sortOptions = <{DESCENDING | NUMERIC}, {DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> valueWeightColumn.state2.label.text = '$V/W' valueWeightColumn.state2.entry.text = @infoWeightValue valueWeightColumn.state2.sortAttributes = valueWeightColumn.state2.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; VIEWS ------------------------------------------------------- defaultView.primaryColumn = nameColumn defaultView.columns = weaponView.primaryColumn = awNameColumn weaponView.columns = weaponView.category = CAT_INV_WEAPONS armorView.primaryColumn = awNameColumn armorView.columns = armorView.category = CAT_INV_ARMOR allView.primaryColumn = allNameColumn allView.columns = allView.category = contWeaponView.primaryColumn = awContNameColumn contWeaponView.columns = contWeaponView.category = CAT_CONTAINER_WEAPONS contArmorView.primaryColumn = awContNameColumn contArmorView.columns = contArmorView.category = CAT_CONTAINER_ARMOR contAllView.primaryColumn = allContNameColumn contAllView.columns = contAllView.category = CAT_CONTAINER_ALL views = ; ===================================================================================================================== [MagicList] ; ===================================================================================================================== entry.width = 530 ; Format defaults ------------------------------------------------------------------------------------------ entry.format.font = '$EverywhereMediumFont' entry.format.align = left entry.format.bold = false entry.format.italic = false entry.format.underline = false entry.format.size = 14 entry.format.letterSpacing = 0.8 entry.format.kerning = false entry.format.leftMargin = 0 entry.format.rightMargin = 0 entry.format.indent = 0 entry.format.leading = 0 label.format.font = '$EverywhereMediumFont' label.format.align = left label.format.bold = false label.format.italic = false label.format.underline = false label.format.size = 12 label.format.letterSpacing = 0.8 label.format.kerning = false label.format.leftMargin = 0 label.format.rightMargin = 0 label.format.indent = 0 label.format.leading = 0 ; ICONS ------------------------------------------------------------------------------------------ equipColumn.type = EQUIP_ICON equipColumn.passive = true equipColumn.indent = -28 equipColumn.label.text = ' ' equipColumn.icon.size = 18 equipColumn.border = <0, 10, 3, 3> ; left right top bottom iconColumn.type = ITEM_ICON iconColumn.passive = true iconColumn.icon.size = 18 iconColumn.label.text = ' ' iconColumn.border = <0, 3, 3, 3> ; left right top bottom ; NAME COLUMN ------------------------------------------------------- nameColumn.type = NAME nameColumn.states = 3 nameColumn.weight = 1.1 nameColumn.border = <0, 0, 1.1, 0> ; left right top bottom nameColumn.state1.label.text = '$NAME' nameColumn.state1.entry.text = @text nameColumn.state1.sortOptions = {ASCENDING | CASEINSENSITIVE} nameColumn.state2.label.text = '$NAME' nameColumn.state2.entry.text = @text nameColumn.state2.label.arrowDown = true nameColumn.state2.sortOptions = {DESCENDING | CASEINSENSITIVE} nameColumn.state3.label.text = '$FAVORITE' nameColumn.state3.entry.text = @text nameColumn.state3.sortAttributes = nameColumn.state3.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; ALL NAME COLUMN ------------------------------------------------------- allNameColumn.type = NAME allNameColumn.states = 3 allNameColumn.weight = 0.75 allNameColumn.border = <0, 0, 1.1, 0> ; left right top bottom allNameColumn.state1.label.text = '$NAME' allNameColumn.state1.entry.text = @text allNameColumn.state1.sortOptions = {ASCENDING | CASEINSENSITIVE} allNameColumn.state2.label.text = '$NAME' allNameColumn.state2.entry.text = @text allNameColumn.state2.label.arrowDown = true allNameColumn.state2.sortOptions = {DESCENDING | CASEINSENSITIVE} allNameColumn.state3.label.text = '$FAVORITE' allNameColumn.state3.entry.text = @text allNameColumn.state3.sortAttributes = allNameColumn.state3.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; POWER NAME COLUMN ------------------------------------------------------- powersNameColumn.type = NAME powersNameColumn.states = 3 powersNameColumn.weight = 1.45 powersNameColumn.border = <0, 0, 1.1, 0> ; left right top bottom powersNameColumn.state1.label.text = '$NAME' powersNameColumn.state1.entry.text = @text powersNameColumn.state1.sortOptions = {ASCENDING | CASEINSENSITIVE} powersNameColumn.state2.label.text = '$NAME' powersNameColumn.state2.entry.text = @text powersNameColumn.state2.label.arrowDown = true powersNameColumn.state2.sortOptions = {DESCENDING | CASEINSENSITIVE} powersNameColumn.state3.label.text = '$FAVORITE' powersNameColumn.state3.entry.text = @text powersNameColumn.state3.sortAttributes = powersNameColumn.state3.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; SPELL COST COLUMN ------------------------------------------- spellCostColumn.type = TEXT spellCostColumn.states = 2 spellCostColumn.weight = 0.2 spellCostColumn.border = <0, 0, 1.1, 0> ; left right top bottom spellCostColumn.label.format.align = left spellCostColumn.entry.format.align = left spellCostColumn.state1.label.text = '$SPELL COST' spellCostColumn.state1.label.arrowDown = true spellCostColumn.state1.entry.text = @infoSpellCostStr spellCostColumn.state1.sortAttributes = spellCostColumn.state1.sortOptions = <{DESCENDING | NUMERIC}, {DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> spellCostColumn.state2.label.text = '$SPELL COST' spellCostColumn.state2.label.arrowDown = false spellCostColumn.state2.entry.text = @infoSpellCostStr spellCostColumn.state2.sortAttributes = spellCostColumn.state2.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; WORD 1 COLUMN ------------------------------------------- word1Column.type = TEXT word1Column.states = 2 word1Column.weight = 0.5 word1Column.border = <0, 0, 1.1, 0> ; left right top bottom word1Column.label.format.align = left word1Column.entry.format.align = left word1Column.state1.label.text = '$FIRST WORD' word1Column.state1.label.arrowDown = true word1Column.state1.entry.text = @infoWord1 word1Column.state1.sortAttributes = word1Column.state1.sortOptions = <{DESCENDING | NUMERIC}, {DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> word1Column.state2.label.text = '$FIRST WORD' word1Column.state2.label.arrowDown = false word1Column.state2.entry.text = @infoWord1 word1Column.state2.sortAttributes = word1Column.state2.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; WORD 2 COLUMN ------------------------------------------- word2Column.type = TEXT word2Column.states = 2 word2Column.weight = 0.5 word2Column.border = <0, 0, 1.1, 0> ; left right top bottom word2Column.label.format.align = left word2Column.entry.format.align = left word2Column.state1.label.text = '$SECOND WORD' word2Column.state1.label.arrowDown = true word2Column.state1.entry.text = @infoWord2 word2Column.state1.sortAttributes = word2Column.state1.sortOptions = <{DESCENDING | NUMERIC}, {DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> word2Column.state2.label.text = '$SECOND WORD' word2Column.state2.label.arrowDown = false word2Column.state2.entry.text = @infoWord2 word2Column.state2.sortAttributes = word2Column.state2.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; WORD 3 COLUMN ------------------------------------------- word3Column.type = TEXT word3Column.states = 2 word3Column.weight = 0.35 word3Column.border = <0, 0, 1.1, 0> ; left right top bottom word3Column.label.format.align = left word3Column.entry.format.align = left word3Column.state1.label.text = '$THIRD WORD' word3Column.state1.label.arrowDown = true word3Column.state1.entry.text = @infoWord3 word3Column.state1.sortAttributes = word3Column.state1.sortOptions = <{DESCENDING | NUMERIC}, {DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> word3Column.state2.label.text = '$THIRD WORD' word3Column.state2.label.arrowDown = false word3Column.state2.entry.text = @infoWord3 word3Column.state2.sortAttributes = word3Column.state2.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; SCHOOL COLUMN ------------------------------------------- schoolColumn.type = TEXT schoolColumn.states = 2 schoolColumn.weight = 0.35 schoolColumn.border = <0, 0, 1.1, 0> ; left right top bottom schoolColumn.label.format.align = left schoolColumn.entry.format.align = left schoolColumn.state1.label.text = '$SCHOOL' schoolColumn.state1.label.arrowDown = false schoolColumn.state1.entry.text = @infoSchoolName schoolColumn.state1.sortAttributes = schoolColumn.state1.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}, {ASCENDING | CASEINSENSITIVE}> schoolColumn.state2.label.text = '$SCHOOL' schoolColumn.state2.label.arrowDown = true schoolColumn.state2.entry.text = @infoSchoolName schoolColumn.state2.sortAttributes = schoolColumn.state2.sortOptions = <{DESCENDING | NUMERIC}, {DESCENDING | CASEINSENSITIVE}, {ASCENDING | CASEINSENSITIVE}> ; LEVEL COLUMN ------------------------------------------- levelColumn.type = TEXT levelColumn.states = 2 levelColumn.weight = 0.35 levelColumn.border = <0, 0, 1.1, 0> ; left right top bottom levelColumn.label.format.align = left levelColumn.entry.format.align = left levelColumn.state1.label.text = '$SKILL LEVEL' levelColumn.state1.label.arrowDown = false levelColumn.state1.entry.text = @infoSkillLevel levelColumn.state1.sortAttributes = levelColumn.state1.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}, {ASCENDING | CASEINSENSITIVE}> levelColumn.state2.label.text = '$SKILL LEVEL' levelColumn.state2.label.arrowDown = true levelColumn.state2.entry.text = @infoSkillLevel levelColumn.state2.sortAttributes = levelColumn.state2.sortOptions = <{DESCENDING | NUMERIC}, {DESCENDING | CASEINSENSITIVE}, {ASCENDING | CASEINSENSITIVE}> ; EFFECT NAME COLUMN ------------------------------------------------------- effNameColumn.type = NAME effNameColumn.states = 2 effNameColumn.weight = 0.5 effNameColumn.border = <0, 0, 1.1, 0> ; left right top bottom effNameColumn.state1.label.text = '$NAME' effNameColumn.state1.entry.text = @text effNameColumn.state1.sortOptions = {ASCENDING | CASEINSENSITIVE} effNameColumn.state2.label.text = '$NAME' effNameColumn.state2.entry.text = @text effNameColumn.state2.label.arrowDown = true effNameColumn.state2.sortOptions = {DESCENDING | CASEINSENSITIVE} ; TIME REMAINING COLUMN ------------------------------------------- timeRemainingColumn.type = TEXT timeRemainingColumn.states = 2 timeRemainingColumn.weight = 0.5 timeRemainingColumn.border = <0, 0, 1.1, 0> ; left right top bottom timeRemainingColumn.label.format.align = center timeRemainingColumn.entry.format.align = center timeRemainingColumn.state1.label.text = '$TIME LEFT' timeRemainingColumn.state1.label.arrowDown = false timeRemainingColumn.state1.entry.text = @infoTimeRemainingStr timeRemainingColumn.state1.sortAttributes = timeRemainingColumn.state1.sortOptions = <{DESCENDING | NUMERIC}, {ASCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> timeRemainingColumn.state2.label.text = '$TIME LEFT' timeRemainingColumn.state2.label.arrowDown = true timeRemainingColumn.state2.entry.text = @infoTimeRemainingStr timeRemainingColumn.state2.sortAttributes = timeRemainingColumn.state2.sortOptions = <{DESCENDING | NUMERIC}, {DESCENDING | NUMERIC}, {ASCENDING | CASEINSENSITIVE}> ; ITEM COLUMN ------------------------------------------- itemColumn.type = TEXT itemColumn.states = 2 itemColumn.weight = 0.5 itemColumn.border = <0, 0, 1.1, 0> ; left right top bottom itemColumn.label.format.align = right itemColumn.entry.format.align = right itemColumn.state1.label.text = '$SOURCE' itemColumn.state1.label.arrowDown = false itemColumn.state1.entry.text = @infoItem itemColumn.state1.sortAttributes = itemColumn.state1.sortOptions = <{ASCENDING | CASEINSENSITIVE}, {ASCENDING | CASEINSENSITIVE}> itemColumn.state2.label.text = '$SOURCE' itemColumn.state2.label.arrowDown = true itemColumn.state2.entry.text = @infoItem itemColumn.state2.sortAttributes = itemColumn.state2.sortOptions = <{DESCENDING | CASEINSENSITIVE}, {ASCENDING | CASEINSENSITIVE}> ; VIEWS ------------------------------------------------------- defaultView.primaryColumn = nameColumn defaultView.columns = allView.primaryColumn = allNameColumn allView.columns = allView.category = shoutsView.primaryColumn = nameColumn shoutsView.columns = shoutsView.category = CAT_MAG_SHOUTS powersView.primaryColumn = powersNameColumn powersView.columns = powersView.category = CAT_MAG_POWERS activeEffectView.primaryColumn = effNameColumn activeEffectView.columns = activeEffectView.category = CAT_MAG_EFFECTS views = ================================================ FILE: misc/Flash Util/SkyUI - make_all.jsfl ================================================ FLfile.runCommandLine("skyui_runscript.bat make_all.pl"); ================================================ FILE: misc/Flash Util/SkyUI - make_archive (fast).jsfl ================================================ FLfile.runCommandLine("skyui_runscript.bat make_archive.pl 1"); ================================================ FILE: misc/Flash Util/SkyUI - make_archive.jsfl ================================================ FLfile.runCommandLine("skyui_runscript.bat make_archive.pl"); ================================================ FILE: misc/Flash Util/build-all.jsfl ================================================ var srcDir = "file:///E:/dev/skyui/src/" var flaFiles = [ "CraftingMenu/craftingmenu.fla", //"FavoritesMenu/favoritesmenu.fla", //"HUDWidgets/activeeffects.fla", //"HUDWidgets/widgetloader.fla", "ItemMenus/bartermenu.fla", "ItemMenus/bottombar.fla", "ItemMenus/containermenu.fla", "ItemMenus/giftmenu.fla", "ItemMenus/inventorylists.fla", "ItemMenus/inventorymenu.fla", "ItemMenus/itemcard.fla", "ItemMenus/magicmenu.fla", //"MapMenu/map.fla", "ModConfigPanel/configpanel.fla", //"ModConfigPanel/mcm_splash.fla", //"ModConfigPanel/skyui_splash.fla", "PauseMenu/quest_journal/quest_journal.xfl", "Resources/buttonArt/buttonArt.xfl", //"Resources/icons_category_celtic.fla", //"Resources/icons_category_curved.fla", //"Resources/icons_category_psychosteve.fla", //"Resources/icons_category_straight.fla", //"Resources/icons_effect_psychosteve.fla", //"Resources/icons_item_psychosteve.fla", //"Resources/mapMarkerArt.fla", ]; for(var i = 0; i < flaFiles.length; i++) { flaFiles[i] = srcDir + flaFiles[i]; } // Starting a new compile session // Clear out all errors var logfile = "file:///E:/dev/skyui/compile-error.txt"; FLfile.remove(logfile); fl.compilerErrors.clear(); function build(documentUri) { FLfile.remove(logfile); var doc = fl.openDocument(documentUri); doc.publish(); fl.compilerErrors.save(logfile, true); if( FLfile.getSize(logfile) > 27 ) throw "Compile error encountered!"; } for(idx in flaFiles) { build(flaFiles[idx]); } ================================================ FILE: misc/Flash Util/skyui_runscript.bat ================================================ :: Change this path to the location of your the dist/ directory. :: Example: :: C:\Users\MyName\Projects\Modding\SkyUI\master\dist :: :: Move skyui_runscript.bat and all jsfl's to :: %LocalAppData%\Adobe\Flash CS4\en\Configuration\Commands :: CHANGE ME!!! cd C:\Users\MyName\Projects\Modding\SkyUI\master\dist perl %1 %2 ================================================ FILE: misc/PrimaryNeeds/Scripts/Source/PN_FoodEffect.psc ================================================ scriptname PN_FoodEffect extends ActiveMagicEffect ; PROPERTIES -------------------------------------------------------------------------------------- PN_NeedsManager property NeedsManagerInstance auto ; EVENTS ------------------------------------------------------------------------------------------ event OnEffectStart(Actor a_target, Actor a_caster) ; We use the duration to encode a value NeedsManagerInstance.ReduceHunger(GetDuration() as int) Dispel() endEvent ================================================ FILE: misc/PrimaryNeeds/Scripts/Source/PN_IconWidget.psc ================================================ scriptname PN_IconWidget extends SKI_WidgetBase ; PRIVATE VARIABLES ------------------------------------------------------------------------------- bool _enabled = false int _iconSize = 32 string _orientation = "vertical" ; PROPERTIES -------------------------------------------------------------------------------------- bool Property Enabled bool function get() return _enabled endFunction function set(bool a_val) _enabled = a_val if (Ready) UI.InvokeBool(HUD_MENU, WidgetRoot + ".setEnabled", _enabled) endIf endFunction endProperty int property IconSize int function get() return _iconSize endFunction function set(int a_val) _iconSize = a_val if (Ready) UI.InvokeInt(HUD_MENU, WidgetRoot + ".setIconSize", _iconSize) endIf endFunction endProperty string property Orientation function set(string a_val) _orientation = a_val if (Ready) UI.InvokeString(HUD_MENU, WidgetRoot + ".setOrientation", _orientation) endIf endFunction endProperty PN_NeedsManager property NeedsManagerInstance auto ; EVENTS ------------------------------------------------------------------------------------------ ; @implements SKI_WidgetBase event OnGameReload() parent.OnGameReload() RegisterForModEvent("PNX_statusUpdated", "OnStatusUpdate") endEvent ; @override SKI_WidgetBase event OnWidgetReset() parent.OnWidgetReset() ; Init numbers int[] numberArgs = new int[2] numberArgs[0] = _enabled as int numberArgs[1] = _iconSize as int UI.InvokeIntA(HUD_MENU, WidgetRoot + ".initNumbers", numberArgs) ; Init strings string[] stringArgs = new string[1] stringArgs[0] = _orientation UI.InvokeStringA(HUD_MENU, WidgetRoot + ".initStrings", stringArgs) ; Init commit UI.Invoke(HUD_MENU, WidgetRoot + ".initCommit") UpdateStatus() endEvent event OnStatusUpdate(string a_eventName, string a_strArg, float a_numArg, Form a_sender) UpdateStatus() endEvent ; FUNCTIONS --------------------------------------------------------------------------------------- ; @overrides SKI_WidgetBase string function GetWidgetSource() return "pnx/statusicons.swf" endFunction ; @overrides SKI_WidgetBase string function GetWidgetType() ; Must be the same as scriptname return "PN_IconWidget" endFunction function UpdateStatus() ; We have to pull the data for compatiblity if (Ready) int[] args = new int[6] args[0] = NeedsManagerInstance.HungerPercent args[1] = NeedsManagerInstance.ThirstPercent args[2] = NeedsManagerInstance.FatiguePercent args[3] = NeedsManagerInstance.HungerLevel args[4] = NeedsManagerInstance.ThirstLevel args[5] = NeedsManagerInstance.FatigueLevel UI.InvokeIntA(HUD_MENU, WidgetRoot + ".setStatus", args) endIf endFunction ================================================ FILE: misc/PrimaryNeeds/Scripts/Source/PN_NeedsManager.psc ================================================ scriptname PN_NeedsManager extends Quest ; PRIVATE VARIABLES ------------------------------------------------------------------------------- ; Time in game hours float _curTime = 0.0 float _lastIncreaseTime = 0.0 ; Timers in real seconds float _hungerSoundTimer = 0.0 float _thirstSoundTimer = 0.0 float _fatigueSoundTimer = 0.0 float _soundCooldownTimer = 0.0 ; Current HTF states int _hunger = 0 int _thirst = 0 int _fatigue = 0 int _lastHunger = -1 int _lastThirst = -1 int _lastFatigue = -1 ; Penalty levels (0=none) int _hungerLevel = 0 int _thirstLevel = 0 int _fatigueLevel = 0 ; Sleep tracking float _sleepStartTime float _sleepEndTime int _sleepDuration ; PROPERTIES -------------------------------------------------------------------------------------- int property HungerPercent int function get() return Lerp(0, 100, HungerWarnThreshold, HungerPenaltyThreshold1, _hunger, true) as int endFunction endProperty int property ThirstPercent int function get() return Lerp(0, 100, ThirstWarnThreshold, ThirstPenaltyThreshold1, _thirst, true) as int endFunction endProperty int property FatiguePercent int function get() return Lerp(0, 100, FatigueWarnThreshold, FatiguePenaltyThreshold1, _fatigue, true) as int endFunction endProperty int property HungerLevel int function get() return _hungerLevel endFunction endProperty int property ThirstLevel int function get() return _thirstLevel endFunction endProperty int property FatigueLevel int function get() return _fatigueLevel endFunction endProperty ObjectReference property PlayerRef auto bool property HungerEnabled = true auto bool property ThirstEnabled = true auto bool property FatigueEnabled = true auto ; Real seconds between update checks float property UpdateInterval = 3.0 auto ; Increase per game (sleep) hour int property HungerPerHour = 10 auto int property HungerPerSleepHour = 5 auto int property ThirstPerHour = 10 auto int property ThirstPerSleepHour = 10 auto int property FatiguePerHour = 10 auto int property FatiguePerSleepHour = -20 auto ; Warn threshold starts sound feedback, no penalties ; Level 1 applies penalties ; Level 2 applies severe penalties ; Values are capped at max int property HungerWarnThreshold = 60 auto int property HungerPenaltyThreshold1 = 120 auto int property HungerPenaltyThreshold2 = 350 auto int property HungerMax = 420 auto int property ThirstWarnThreshold = 50 auto int property ThirstPenaltyThreshold1 = 100 auto int property ThirstPenaltyThreshold2 = 200 auto int property ThirstMax = 250 auto int property FatigueWarnThreshold = 160 auto int property FatiguePenaltyThreshold1 = 200 auto int property FatiguePenaltyThreshold2 = 400 auto int property FatigueMax = 480 auto ; Sound feedback interval in real seconds, lerped between min and max float property SoundMinInterval = 40.0 auto float property SoundMaxInterval = 150.0 auto ; Cooldown after any sound feedback in real seconds float property SoundCooldownInterval = 10.0 auto ; Male sounds at index 0, female at 1 Sound[] property HungerSounds auto Sound[] property ThirstSounds auto Sound[] property FatigueSounds auto ; Level 1 penalty at index 0, level 2 at 1 Spell[] property HungerPenalties auto Spell[] property ThirstPenalties auto Spell[] property FatiguePenalties auto GlobalVariable property PlayerIsVampire auto GLobalVariable property PlayerIsWerewolf auto ; INITIALIZATION ---------------------------------------------------------------------------------- event OnInit() _lastIncreaseTime = 24 * Utility.GetCurrentGameTime() RegisterForSingleUpdate(UpdateInterval) RegisterForSleep() endEvent ; EVENTS ------------------------------------------------------------------------------------------ function OnUpdate() _curTime = 24 * Utility.GetCurrentGameTime() CheckValueIncrease() UpdatePenalties() UpdateSounds() ; Causes widget to pull most recent data if (_hunger != _lastHunger || _thirst != _lastThirst || _fatigue != _lastFatigue) _lastHunger = _hunger _lastThirst = _thirst _lastFatigue = _fatigue SendModEvent("PNX_statusUpdated") endIf RegisterForSingleUpdate(UpdateInterval) endFunction event OnSleepStart(float a_sleepStartTime, float a_desiredSleepEndTime) _sleepStartTime = 24 * a_sleepStartTime _sleepEndTime = 24 * a_desiredSleepEndTime ; change later if interrupted endEvent event OnSleepStop(bool a_interrupted) if (a_interrupted) _sleepEndTime = 24 * Utility.GetCurrentGameTime() endIf ; We add up the sleep duration in case player sleeps several times until the main loop is processed again _sleepDuration += (_sleepEndTime - _sleepStartTime) as int ; Play sound again if still sleepy _fatigueSoundTimer = 0.0 endEvent ; PUBLIC FUNCTIONS -------------------------------------------------------------------------------- function ReduceHunger(int a_hours) _hunger -= a_hours * HungerPerHour if (_hunger < 0) _hunger = 0 endIf _hungerSoundTimer = 0.0 endFunction function ReduceThirst(int a_hours) _thirst -= a_hours * ThirstPerHour if (_thirst < 0) _thirst = 0 endIf _thirstSoundTimer = 0.0 endFunction function ReduceFatigue(int a_hours) _fatigue -= a_hours * FatiguePerHour if (_fatigue < 0) _fatigue = 0 endIf _fatigueSoundTimer = 0.0 endFunction ; PRIVATE FUNCTIONS ------------------------------------------------------------------------------- function CheckValueIncrease() bool isVampire = PlayerIsVampire.GetValueInt() > 0 if (!HungerEnabled || isVampire) _hunger = 0 endIf if (!ThirstEnabled || isVampire) _thirst = 0 endIf if (!FatigueEnabled || isVampire) _fatigue = 0 endIf int d = (_curTime - _lastIncreaseTime) as int ; Wait at least one hour between increases if (d < 1) return endIf ; We reset the timers after longer waiting durations to remind the player to be careful if (d > 3) _hungerSoundTimer = 0.0 _thirstSoundTimer = 0.0 _fatigueSoundTimer = 0.0 endIf ; Sleep duration is 0 if not slept at all int awakeDuration = d - _sleepDuration if (HungerEnabled && _hunger < HungerMax && !isVampire) _hunger += awakeDuration * HungerPerHour _hunger += _sleepDuration * HungerPerSleepHour if (_hunger > HungerMax) _hunger = HungerMax elseIf (_hunger < 0) _hunger = 0 endIf endIf if (ThirstEnabled && _thirst < ThirstMax && !isVampire) _thirst += awakeDuration * ThirstPerHour _thirst += _sleepDuration * ThirstPerSleepHour if (_thirst > ThirstMax) _thirst = ThirstMax elseIf (_thirst < 0) _thirst = 0 endIf endIf if (FatigueEnabled && _fatigue < FatigueMax && !isVampire) _fatigue += awakeDuration * FatiguePerHour _fatigue += _sleepDuration * FatiguePerSleepHour if (_fatigue > FatigueMax) _fatigue = FatigueMax elseIf (_fatigue < 0) _fatigue = 0 endIf endIf _lastIncreaseTime = _curTime ; Reset _sleepDuration = 0 endFunction function UpdatePenalties() bool applyHunger = false bool applyThirst = false bool applyFatigue = false Actor player = Game.GetPlayer() if (_hunger > HungerPenaltyThreshold2) applyHunger = (_hungerLevel != 2) _hungerLevel = 2 elseIf (_hunger > HungerPenaltyThreshold1) applyHunger = (_hungerLevel != 1) _hungerLevel = 1 else applyHunger = (_hungerLevel != 0) _hungerLevel = 0 endIf if (_thirst > ThirstPenaltyThreshold2) applyThirst = (_thirstLevel != 2) _thirstLevel = 2 elseIf (_thirst > ThirstPenaltyThreshold1) applyThirst = (_thirstLevel != 1) _thirstLevel = 1 else applyThirst = (_thirstLevel != 0) _thirstLevel = 0 endIf if (_fatigue > FatiguePenaltyThreshold2) applyFatigue = (_fatigueLevel != 2) _fatigueLevel = 2 elseIf (_fatigue > FatiguePenaltyThreshold1) applyFatigue = (_fatigueLevel != 1) _fatigueLevel = 1 else applyFatigue = (_fatigueLevel != 0) _fatigueLevel = 0 endIf if (applyHunger) ; Immediate feedback _hungerSoundTimer = 0.0 if (_hungerLevel == 2) player.RemoveSpell(HungerPenalties[0]) player.AddSpell(HungerPenalties[1], false) elseIf (_hungerLevel == 1) player.AddSpell(HungerPenalties[0], false) player.RemoveSpell(HungerPenalties[1]) else player.RemoveSpell(HungerPenalties[0]) player.RemoveSpell(HungerPenalties[1]) endIf endIf if (applyThirst) _thirstSoundTimer = 0.0 if (_thirstLevel == 2) player.RemoveSpell(ThirstPenalties[0]) player.AddSpell(ThirstPenalties[1], false) elseIf (_thirstLevel == 1) player.AddSpell(ThirstPenalties[0], false) player.RemoveSpell(ThirstPenalties[1]) else player.RemoveSpell(ThirstPenalties[0]) player.RemoveSpell(ThirstPenalties[1]) endIf endIf if (applyFatigue) _fatigueSoundTimer = 0.0 if (_fatigueLevel == 2) player.RemoveSpell(FatiguePenalties[0]) player.AddSpell(FatiguePenalties[1], false) elseIf (_fatigueLevel == 1) player.AddSpell(FatiguePenalties[0], false) player.RemoveSpell(FatiguePenalties[1]) else player.RemoveSpell(FatiguePenalties[0]) player.RemoveSpell(FatiguePenalties[1]) endIf endIf endFunction function UpdateSounds() ; General cooldown so we don't play sounds immediately after each other if (_soundCooldownTimer > 0) _soundCooldownTimer -= UpdateInterval return endIf if (_hungerSoundTimer > 0) _hungerSoundTimer -= UpdateInterval elseIf (_hunger > HungerWarnThreshold) PlaySound(HungerSounds) _hungerSoundTimer = Lerp(SoundMaxInterval, SoundMinInterval, HungerWarnThreshold, HungerMax, _hunger) return endIf if (_thirstSoundTimer > 0) _thirstSoundTimer -= UpdateInterval elseIf (_thirst > ThirstWarnThreshold) PlaySound(ThirstSounds) _thirstSoundTimer = Lerp(SoundMaxInterval, SoundMinInterval, ThirstWarnThreshold, ThirstMax, _thirst) return endIf if (_fatigueSoundTimer > 0) _fatigueSoundTimer -= UpdateInterval elseIf (_fatigue > FatigueWarnThreshold) PlaySound(FatigueSounds) _fatigueSoundTimer = Lerp(SoundMaxInterval, SoundMinInterval, FatigueWarnThreshold, FatigueMax, _fatigue) return endIf endFunction function PlaySound(Sound[] a_sounds) ActorBase playerBase = PlayerRef.GetBaseObject() as ActorBase int idx = playerBase.GetSex() a_sounds[idx].Play(PlayerRef) _soundCooldownTimer = SoundCooldownInterval endFunction float function Lerp(float a_targetMin, float a_targetMax, float a_sourceMin, float a_sourceMax, float a_sourceVal, bool a_bClamp = false) float v = a_targetMin + (a_targetMax - a_targetMin) * ((a_sourceVal - a_sourceMin) / (a_sourceMax - a_sourceMin)) if (a_bClamp) if (v < a_targetMin) v = a_targetMin elseIf (v > a_targetMax) v = a_targetMax endIf endIf return v endFunction ================================================ FILE: misc/Translations/SkyUI_Translations.txt ================================================ Language English French German Italian Spanish Czech Polish Russian Japanese $ALL ALL TOUS ALLE TUTTO TODO VŠECHNO WSZYSTKIE ВСЕ 全て $FILTER FILTER FILTRE FILTER FILTRO FILTRO FILTR FILTR ФИЛЬТР フィルタ $STOLEN STOLEN VOLÉ GESTOHLEN RUBATO ROBADO KRADENÉ SKRADZIONE УКРАДЕНО 盗品 $EQUIPPED EQUIPPED ÉQUIPÉ AUSGERÜSTET EQUIPAGGIATO EQUIPADO POUŽÍVANÉ WYPOSAŻONE НАДЕТО 装備品 $ENCHANTED ENCHANTED ENCHANTÉ VERZAUBERT INCANTATO ENCANTADO OČAROVANÉ ZACZAROWANE ЗАЧАРОВАНО エンチャント $V/W V/W V/P W/G V/P V/P C/H C/W Ц/В 金額/重量 $VALUE/WEIGHT VALUE/WEIGHT VALEUR/POIDS WERT/GEWICHT VALORE/PESO VALOR/PESO CENA/HMOTNOST CENA/WAGA ЦЕНА/ВЕС 金額/重量 $SPELL COST SPELL COST COÛT KOSTEN COSTO COSTE DE HECHIZO MANA KOSZT CZARU СТОИМОСТЬ コスト $FIRST WORD FIRST WORD PREMIER MOT ERSTES WORT PRIMA PAROLA PRIMERO PALABRA PRVNÍ SLOVO PIERWSZY WYRAZ ПЕРВОЕ СЛОВО 第一の言葉 $SECOND WORD SECOND WORD DEUXIÈME MOT ZWEITES WORT SECONDA PAROLA SEGUNDA PALABRA DRUHÉ SLOVO DRUGI WYRAZ ВТОРОЕ СЛОВО 第二の言葉 $THIRD WORD THIRD WORD TROISIÈME MOT DRITTES WORT TERZA PAROLA TERCERA PALABRA TŘETÍ SLOVO TRZECI WYRAZ ТРЕТЬЕ СЛОВО 第三の言葉 $SCHOOL SCHOOL ÉCOLE MAGIESCHULE SCUOLA ESCUELA ŠKOLA SZKOŁA ШКОЛА 系統 $SKILL LEVEL SKILL LEVEL NIVEAU FERTIGKEITSSTUFE LIVELLO NIVEL DE HAB ÚROVEŇ POZIOM УРОВЕНЬ НАВЫКА スキルレベル $TIME LEFT TIME LEFT TEMPS RESTANT VERBLEIBENDE ZEIT TEMPO RIMANENTE TIEMPO RESTANTE VYPRŠÍ ZA POZOSTAŁY CZAS ОСТАВШЕЕСЯ ВРЕМЯ 残り時間 $SOURCE SOURCE ORIGINE QUELLE ORIGINE ORIGEN ZDROJ ŹRÓDŁO ИСТОЧНИК 効果元 $FAVORITE FAVORITE FAVORIS FAVORIT PREFERITO FAVORITO OBLÍBENÉ ULUBIONE ИЗБРАННОЕ お気に入り $TYPE TYPE TYPE TYP TIPO TIPO TYP TYP ТИП 種別 $MATERIAL MATERIAL MATÉRIAU MATERIAL MATERIALE MATERIAL MATERIÁL MATERIAŁ МАТЕРИАЛ 材料 $MAT MAT MAT MAT MAT MAT MAT MAT МАТ 材料 $CLASS CLASS CLASSE KLASSE CLASSE CLASE TŘÍDA KLASA КЛАСС 分類 $MAGNITUDE MAGNITUDE MAGNITUDE STÄRKE MAGNITUDO MAGNITUD SÍLA WIELKOŚĆ ВЕЛИЧИНА 効力 $MAG MAG MAG STÄ MAG MAG SIL WLK ВЕЛ 効力 $DURATION DURATION DURÉE DAUER DURATA DURACIÓN TRVÁNÍ CZAS TRWANIA ПРОДОЛЖИТЕЛЬНОСТЬ 期限 $DUR DUR DUR DAU DUR DUR TRV TRW ПРОД 期限 $TIME TIME TEMPS ZEIT TEMPO TIEMPO ČAS CZAS ВРЕМЯ 時間 $DAM DAM DOMM SCHA DANNI DAÑO POŠK OBR УРОН ダメージ $WGT WGT PDS GEW PESO PESO HMOT WAG ВЕС 重量 $VAL VAL VAL WERT VAL VAL CENA CEN ЦЕНА 金額 $ARM ARM ARM RÜST ARM ARM ZBR ZBR БРОНЯ 防御 $WEAPONS WEAPONS ARMES WAFFEN ARMI ARMAS ZBRANĚ BROŃ ОРУЖИЕ 武器 $AMMO AMMO AMMO MUNITION MUNIZIONI MUNICIONES MUNICE AMUNICJA БОЕПРИПАСЫ 弾薬 $EFFECT EFFECT EFFET EFFEKT EFFETTO EFECTO ÚČINEK EFEKT ВЛИЯНИЕ 影響 $Armor Armor Armure Rüstung Armatura Armadura Zbroj Zbroja Защита 防具 $None None Aucun Kein Nessuno Ninguno Nic Nic Нет なし $Light Light Légère Leicht Leggera Ligera Lehká z. Lekka Легкие 軽装 $Heavy Heavy Lourde Schwer Pesante Pesada Těžká z. Ciężka Тяжелые 重装 $Clothing Clothing Vêtements Kleidung Indumento Ropa Oblečení Ubranie Ткань 衣服 $Jewelry Jewelry Joaillerie Schmuck Gioielleria Joyería Šperk Biżuteria Драгоц. 宝飾品 $Body Body Torse Körper Petto Torso Hrud' Ciało Тело 胴 $Head Head Tête Kopf Testa Cabeza Hlava Głowa Голова 頭 $Hands Hands Mains Hände Braccia Manos Ruce Dłonie Руки 手 $Forearms Forearms Avant-bras Unterarme Avambracci Antebrazos Předloktí Przedramiona Предплечья 腕 $Feet Feet Pieds Füße Piedi Pies Nohy Stopy Ноги 足 $Calves Calves Jambes Unterschenkel Gambe Piernas Lýtka Łydki Голень 脚 $Shield Shield Bouclier Schild Scudo Escudo Štít Tarcza Щит 盾 $Amulet Amulet Amulette Amulett Amuleto Amuleto Amulet Amulet Ожерелье アミュレット $Ring Ring Anneau Ring Anello Anillo Prsten Pierścień Кольцо 指輪 $Mask Mask Masque Maske Maschera Máscara Maska Maska Маска 仮面 $Circlet Circlet Couronne Diadem Tiara Aro Čelenka Diadem Обруч サークレット $Ears Ears Oreilles Ohren Orecchie Orejas Uši Uszy Уши 耳 $Tail Tail Queue Schwanz Coda Capa Ocas Ogon Хвост 尻尾 $Grand Grand Puissant Mächtig $Greater Greater Grand Groß $Common Common Ordinaire Gewöhnlich $Lesser Lesser Petit Klein $Petty Petty Minuscule Winzig $Weapon Weapon Arme Waffe Arma Arma Zbraň Broń Оружие 武器 $Melee Melee Corps à corps Nahkampf Corpo a Corpo Cuerpo a Cuerpo Pěsti Pięści Ближ. бой 挌闘 $Sword Sword Épée Schwert Spada Espada Meč Miecz Меч 剣 $Dagger Dagger Dague Dolch Pugnale Daga Dýka Sztylet Кинжал ダガー $War Axe War Axe Hache Kriegsaxt Ascia Hacha de guerra Válečná Sekera Topór Wojenny Боевой топор 片手斧 $Mace Mace Masse Streitkolben Mazza Maza Palcát Buława Булава メイス $Greatsword Greatsword Espadon Zweihänder Spadone Mandoble Obouruční Meč Wielki Miecz Двуручный меч グレートソード $Warhammer Warhammer Marteau Kriegshammer Martello Martillo Kladivo Młot Bojowy Боевой молот 戦鎚 $Battleaxe Battleaxe Hache de guerre Streitaxt Ascia Hacha de combate Bojová Sekera Topór Bojowy Секира 両手斧 $Bow Bow Arc Bogen Arco Arco Luk Łuk Лук 弓 $Staff Staff Bâton Stab Bastone Bastón Hůl Kostur Посох 杖 $Crossbow Crossbow Arbalète Armbrust Balestra Ballesta Kuše Kusza Арбалет クロスボウ $Spear Spear Lance Speer Lancia Lanza Kopí Włócznia Копьё 槍 $Pickaxe Pickaxe Pioche Spitzhacke Piccone Pico Krumpáč Kilof Кирка つるはし $Wood Axe Wood Axe Hache de bûcheron Holzaxt Accetta del Taglialegna Hacha de Leñador Sekera na dřevo Siekiera Drwala Колун 木こりの斧 $Arrow Arrow Flèche Pfeil Freccia Flecha Šíp Strzała Стрела 矢 $Bolt Bolt Carreau Bolzen Dardo Virote Šipka Bełt Болт ボルト $Potion Potion Potion Trank Pozione Poción Lektvar Mikstura Зелье 水薬 $Poison Poison Poison Gift Veleno Veneno Jed Trucizna Яд 毒薬 $Food Food Nourriture Essen Cibo Comida Jídlo Jedzenie Еда 食料 $Drink Drink Boisson Getränk Bevanda Bebida Pití Napój Напиток 飲料 $Scroll Scroll Parchemin Schriftrolle Pergamena Pergamino Svitek Zwój Свиток 巻物 $Book Book Livre Buch Libro Libro Kniha Książka Книга 書物 $Spell Tome Spell Tome Livre de sort Zauberbuch Libro di Incantesimi Grimorio Kniha Kouzel Księga Czaru Том заклинаний 呪文の書 $Recipe Recipe Recette Rezept Ricetta Receta Recept Przepis Рецепт レシピ $Note Note Note Notiz Nota Nota Poznámka Notatka Записка ノート $Map Map Carte Karte Mappa Mapa Mapa Mapa Карта 地図 $Ingredient Ingredient Ingrédient Zutat Ingrediente Ingrediente Přísada Składnik Ингредиент 材料 $Misc Misc Divers Diverses Varie Varios Různé Pozostałe Разное その他 $Lockpick Lockpick Crochet Dietrich Grimaldello Ganzúa Šperhák Wytrych Отмычка ロックピック $Gem Gem Gemme Edelstein Gemma Gema Drahokam Klejnot Драг. камень 宝石 $Tool Tool Outil Werkzeug Utensile Herramienta Nástroj Narzędzie Инструмент 道具 $Remains Remains Restes Überreste Resti Restos Pozůstatky Szczątki Останки 遺骨 $Leather Leather Cuir Leder Pelle Cuero Kůže Skórzany Кожа 革 $Strips Strips Bandes Streifen Strisce Tiras Odřezky Paski Полоски кожи ひも $Hide Hide Peau Haut Pelle Piel Useň Skóra Шкура 皮 $Ore Ore Minerai Erz Minerale Mineral Ruda Ruda Руда 鉱石 $Ingot Ingot Lingot Barren Lingotto Lingote Ingot Sztaba Слиток インゴット $Claw Claw Griffe Klaue Artiglio Garra Spár Szpon Коготь 爪 $Clutter Clutter Autres Zeug Altro Otros Krámy Klamoty Хлам 雑貨 $Torch Torch Torche Fackel Torcia Antorcha Pochodeň Pochodnia Факел たいまつ $Key Key Clé Schlüssel Chiave Llave Klíč Klucz Ключ 鍵 $Soul Gem Soul Gem Gemme spirituelle Seelenstein Gemma Dell'Anima Gema de Alma Kámen duší Klejnot Duszy Камень Душ 魂石 $Firewood Firewood Feu de bois Feuerholz Legna da Ardere Leña Dřevo Drewno Opałowe Полено 薪 $Gold Gold Or Gold Oro Oro Zlato Złoto Золото ゴールド $Artifact Artifact Artefact Artefakt Artefatto Artefacto Artefakt Artefakt Артефакт アーティファクト $Toy Toy Jouet Spielzeug Giocattolo Juguete Hračka Zabawka Игрушка 玩具 $House Part House Part Partie de maison Hausbau Parte della Casa Parte de la Casa Část domu Część Domu Часть Дома 建材 $Spell Spell Sort Zauber Incantesimo Hechizo Kouzlo Zaklęcie Заклинание スペル $Alteration Alteration Altération Veränderung Alterazione Alteración Proměna Przemiana Изменение 変性 $Destruction Destruction Destruction Zerstörung Distruzione Destrucción Ničení Zniszczenie Разрушение 破壊 $Illusion Illusion Illusion Illusion Illusione Ilusión Iluze Iluzja Иллюзии 幻惑 $Restoration Restoration Restauration Wiederherstellung Recupero Restauración Obnovení Przywrócenie Восстановление 回復 $Other Other Autre Andere Altro Otros Jiné Inne Другое その他 $Magical Magical Magique Magisch Magico Mágica Magické Magiczny Магическое 魔法 $Daedric Daedric Daedrique Daedrisch Daedrico Daédrica Daedrické Daedryczny Даэдрическое デイドラ $Dragonplate Dragonplate Plates de dragon Drachenknochen Piastre di Drago Placas de Dragón Dračí pláty Smoczy Płytowy Драконье Панцирное ドラゴンプレート $Nightingale Nightingale Rossignol Nachtigall Nightingale Ruiseñor Slavíci Słowiczy Соловьиное ナイチンゲール $Ebony Ebony Ébonite Ebenerz Ebano Ébano Ebenit Ebonowy Эбонитовое 黒檀 $Dragonscale Dragonscale Écaille de dragon Drachenschuppen Scaglie di Drago Escamas de Dragón Dračí šupiny Smoczy Łuskowy Драконье Чешуйчатое ドラゴンスケール $Orcish Orcish Orque Orkisch Orchesco Orca Orkský Orkowy Орочье オーク $Steel Plate Steel Plate Plates Stahlharnisch Piastre d'Acciaio Placas de Acero Ocelové pláty Stalowy Płytowy Стальное Пластинчатое スチールプレート $Glass Glass Verre Glas Vetro Cristal Sklo Szklany Стеклянное 碧水晶 $Elven Gilded Elven Gilded Dorée elfique Elfenvergoldet Elfico dorato Dorada Élfica Elfský Zlacený Elficki Pozłacany Эльфийское Золоченое エルフの黄金 $Dwarven Dwarven Dwemer Dwemer Nanico Enana Trpasličí Krasnoludzki Двемерское ドワーフ $Scaled Scaled Écaille Schuppen Scaglie Escamas Šupiny Łuskowy Ламеллярное スケール $Steel Steel Acier Stahl Acciaio Acero Ocel Stalowy Стальное 鋼鉄 $Brotherhood Brotherhood Confrérie Bruderschaft Confraternita Hermandad Bratrstvo Bractwa Братства 闇の一党 $Elven Elven Elfique Elfen Elfico Élfica Elfský Elficki Эльфийское エルフ $Iron Banded Iron Banded Fer bardé Eisenbebändert Ferro Laminato Hierro Bandeado Železo s pásky Żelazny Łączony Прочное Железное 帯鉄 $Leather Leather Cuir Leder Pelle Cuero Kůže Skórzany Кожаное 革 $Imperial Imperial Impérial Kaiserliche Imperiale Imperial Císařští Imperialny Имперское 帝国軍 $Studded Studded Clouté Vernietet Borchiato Tachonada Okované Ćwiekowany Клепаное 鋲付き $Fur Fur Peau Fell Pelliccia Piel Useň Futrzany Меховое 毛皮 $Iron Iron Fer Eisen Ferro Hierro Železo Żelazny Железное 鉄 $Stormcloak Stormcloak Sombrage Sturmmantel Manto della Tempesta Capa de la Tormenta Bouřní Gromowładnych Братьев Бури ストームクローク $Silver Silver Argenté Silber Argento Plata Stříbro Srebrny Серебряное 銀 $Wood Wood Bois Holz Legno Madera Dřevo Drewniany Деревянное 木製 $Nordic Nordic Nordique Nordisch Nordico Nórdica Severský Nordycki Нордское ノルドの刻印 $Bonemold Bonemold Ossement Knochen Ossa Fuse Molde de Hueso Bonemold Bonemold Костяное ボーンモールド $Chitin Chitin Chitine Chitin Chitina Quitina Chitin Chitynowy Хитиновое キチン $Morag Tong Morag Tong Morag Tong Morag Tong Morag Tong Morag Tong Morag Tong Morag Tong Мораг Тонг モラグ・トング $Stalhrim Stalhrim Stalhrim Stalhrim Stalhrim Stalhrim Stalhrim Stalhrim Сталгримовое スタルリム $Deathbrand Deathbrand Balafré Todesmal Marchio Mortale Marca de muerte Deathbrand Deathbrand Клеймо Смерти デスブランド $Draugr Draugr Draugr Draugr Draugr Draugr Draugirský Draugrowy Драургское ドラウグル $Draugr Honed Draugr Honed Draugr affûtée Draugr Geschliffen Draugr Affilata Draugr Afilada Draug. ostřený Draugrowy Naostrzony Хорошее Драугрское $Falmer Falmer Falmer Falmer Falmer Falmer Falmerský Falmerski Фалмерское ファルメル $Falmer Honed Falmer Honed Falmer affûtée Falmer Geschliffen Falmer Affilata Falmer Afilada Falmer. ostřený Falmerski Naostrzony Хорошее Фалмерское $Forsworn Forsworn Parjure Abgeschworene Rinnegato Renegado Zapřisáhlí Renegatów Изгоев フォースウォーン $Dawnguard Dawnguard Garde de l'aube Dämmerwacht Dawnguard Guardia del Alba Strážci Úsvitu Dawnguard Стражи Рассвета ドーンガード $Falmer Hardened Falmer Hardened Falmer renforcée Gehärtete Falmerrüstung Falmer Pesante Falmer endurecida Falmer. tvrzený Falmerski Wzmocniony Фалмерское Укрепленное $Hunter Hunter Chasseur Jäger Cacciatore Cazador Lovci Łowcy Охотничье ハンター $Vampire Vampire Vampire Vampir Vampiro Vampiro Upíři Wampirzy Вампирское 吸血鬼 $Aetherium Aetherium Aetherium Aetherium Eterio Aeterio Aetherit Aetherium Этериевое エセリウム $Dragonbone Dragonbone Os de dragon Drachenknochen Ossa di Drago Hueso de Dragón Dračí kost Smocza Kość Драконье костяное 龍骨 $MOD CONFIGURATION MOD CONFIGURATION CONFIGURATION DU MOD MOD-KONFIGURATION CONFIGURAZIONE MOD CONFIGURACIÓN DE MOD NASTAVENÍ MODŮ KONFIGURACJA MODÓW НАСТРОЙКИ МОДОВ MOD設定 $Default Default Par défaut Voreinstellung Predefinito Por Defecto Základní Domyślny По умолчанию デフォルト $Defaults Defaults Par défauts Voreinstellungen Predefiniti Por Defecto Základní Domyślne По умолчанию デフォルト $Search Search Chercher Suchen Cerca Buscar Hledat Szukaj Поиск 検索 $Magic Magic Magie Magie Magia Magia Magie Magia Магия 魔法 $Inventory Inventory Inventaire Inventar Inventario Inventario Inventář Ekwipunek Инвентарь 所持品 $Switch Tab Switch Tab Changer d'onglet Reiter Wechseln Cambia Scheda Cambiar Pestaña Změnit Záložku Przełącz Kartę Переключение Вкладок タブの切り替え $Equip Mode Equip Mode Gestion d'équipement Ausrüstungsmodus Gestisci Equipaggiamento Modo Equipamiento Režim použití Tryb Wyposażenia Режим Экипировки 装備モード $Column Column Colonne Spalte Colonna Columna Sloupek Kolumna Колонка 列 $Order Order Trier Sortierung Ordina Ordenar Řazení Kolejność Порядок ソート $Open Slider Open Slider Ouvrir le curseur Schieber Öffnen Apri Scorrimento Activar Cursor Otevřít posuvník Otwórz Suwak Открыть Ползунок スライダーを開く $Open Menu Open Menu Ouvrir le menu Menü Öffnen Apri Menu Abrir Menu Otevřít Menu Otwórz Menu Открыть Меню メニューを開く $Toggle Toggle Activer/Désactiver Umschalten Seleziona Seleccionar Zaškrtnout Przełącz Переключить トグル $Pick Color Pick Color Choisir la couleur Farbauswahl Seleziona Colore Seleccionar Color Vybrat barvu Wybierz Kolor Выбор Цвета 色を選択 $Remap Remap Ré-affecter Neuzuweisen Riassegna Reasignar Přenastavit Ponowne Przypisywanie Назначить клавишу 再割り当て $Unmap Unmap Désaffecter Zuordnung Aufheben Dealloca Desasignar Odebrat klávesu Odznacz klawisz Сбросить значение $Find Location Find Location Chercher un lieu Ort Finden Cerca Locazione Descubrir lugar Najít místo Znajdź Miejsce Поиск Локации $General General Général Allgemein Generale General Základní Ogólne Общие 一般 $Favorite Groups Favorite Groups Groupes favoris Favoritengruppen Gruppi Favoriti Grupos Favoritos Oblíbené skupiny Aktywne Группы Избранного $Advanced Advanced Avancé Fortgeschritten Avanzato Avanzado Pokročilé Zaawansowane Дополнительно 高度 $Item List Item List Liste des objets Gegenstandsliste Lista degli Oggetti Lista de Objetos Seznam předmětů Lista Przedmiotów Список Элементов アイテムリスト $Font Size Font Size Taille de police Schriftgröße Dimensione del Font Tamaño de Fuente Velikost písma Wielkość Czcionki Размер Шрифта フォントサイズ $Quantity Menu Min. Count Quantity Menu Min. Count Compte min. du menu de quantité Mindestauswahlmenge Contatore Min. per il Menù di Quantità Número Mín. para Menú de Cantidad Min. Počet Obj. Pro Kvant. Menu Menu Ilości Min. Liczba Мин. Кол-во Элементов в Меню 数量メニュー最小カウント $Category Icon Theme Category Icon Theme Thème des icônes de catégories Symbolthema (Kategorie) Tema delle icone di categoria Tema de iconos de categoría Vzhled ikon kategorií Zestaw Ikon Kategorii Тема Иконок Категорий $Disable Icon Colors Disable Icon Colors Désactiver les couleurs d'icônes Farbige Symbole deaktivieren Disabilita Icone Colorate Desactivar iconos en color Vypnout barvy ikon Wyłącz Kolory Ikon Запретить Цветные Иконки $Previous Column Previous Column Colonne précédente Vorherige Spalte Colonna Precedente Columna Anterior Předchozí sloupek Poprzednia Kolumna Предыдущая Колонка 前の欄 $Next Column Next Column Colonne suivante Nächste Spalte Colonna Successiva Columna Siguiente Další sloupek Następna Kolumna Следующая Колонка 次の欄 $Item Card Item Card Carte d'objets Gegenstandskarte Scheda dell'Oggetto Tarjeta del Objeto Karta předmětu Karta Przedmiotu Окно Просмотра Предмета アイテムカード $3D Item 3D Item Modèle 3D 3D Ansicht Oggetto 3D Objeto 3D 3D Objekt Obiekt 3D 3D Вид Предмета 3D アイテム $Align Align Alignement Ausrichtung Allinea Alinear Zarovnání Wyrównanie Выравнивание 整列する $Horizontal Offset Horizontal Offset Axe horizontal Horizontaler Abstand Spostamento Orizzontale Desplazamiento Horizontal Vodorovné odsazení Przesunięcie Poziome Горизонтальное Смещение 水平オフセット $Vertical Offset Vertical Offset Axe vertical Vertikaler Abstand Spostamento Verticale Desplazamiento Vertical Svislé odsazení Przesunięcie Pionowe Вертикальное Смещение 垂直オフセット $Horizontal Anchor Horizontal Anchor Alignement horizontal Horizontale Ausrichtung Orientamento Orizzontale Alineamiento horizontal Horizontální ukotvení Wyrównanie Poziome Фиксация по Горизонтали $Vertical Anchor Vertical Anchor Alignement vertical Vertikale Ausrichtung Orientamento Verticale Alineamiento vertical Vertikální ukotvení Wyrównanie Pionowe Фиксация по Вертикали $Orientation Orientation Orientation Orientierung Orientamento Alineamiento Orientace Orientacja Ориентация $Icon Size Icon Size Taille d'icône Symbolgröße Dimensione Icona Dimensión del icono Velikost ikon Rozmiar Ikon Размер Иконок $Icon Group Count Icon Group Count Nombre de groupes d'icônes Symbolgruppengröße Numero d'icone raggruppate Icono de Grupo Conde Počet ikon ve skupině Liczba Ikon Grupy Кол-во Групп Иконок $Minimum Time Left Minimum Time Left Temps minimum restant Mindestrestdauer Tempo minimo rimasto Mínimo Tiempo Restante Minimální zbývající čas Minimalny pozostały czas Минимальный Период Задержки $Scale Scale Échelle Größe Scala Escala Měřítko Skala Масштаб スケール $Disable Positioning Disable Positioning Désactiver le positionnement Keine Positionsanpassung Disabilita Posizionamento Desactivar el posicionamiento Zakázat polohování Wyłącz Pozycjonowanie Запретить Позиционирование $SWF Version Checking SWF Version Checking Vérification des versions SWF Versions-Check Controllo Versione SWF Comprobar Versión SWF Kontrola Verze SWF Sprawdzanie Wersji SWF Проверка Версии SWF SWF のバージョンの確認 $Active Effects HUD Active Effects HUD Interface des effets actifs Anzeige für Aktive Effekte HUD degli Effetti Attivi HUD de Effectos Activos Aktivovat HUD Efektů Aktywne Efekty HUD Активные Эффекты HUD $Left Left Gauche Links Sinistra Izquierda Vlevo Lewo Лево 左 $Right Right Droite Rechts Destra Derecha Vpravo Prawo Право 右 $Center Center Centre Mitte Centro Centro Na střed Środek Центр 中央 $Top Top Haut Oben Sopra Alto Nahoře Góra Верх $Bottom Bottom Bas Unten Sotto Abajo Dole Dół Низ $On On Activé An Attivo Activo Zapnuto Włączone Включено $Off Off Désactivé Aus Disattivato Desactivado Vypnuto Wyłączone Выключено $Enabled Enabled Activé Aktiv Abilitato Activado Aktivní Aktywne Разрешено $Vertical Vertical Vertical Vertikal Verticale Vertical Vertikální Pionowe Вертикально $Horizontal Horizontal Horizontal Horizontal Orizzontale Horizontal Horizontální Poziome Горизонтально $SKI_INFO1{} Default: {} Défaut: {} Voreinstellung: {} Predefinito: {} Predefinido: {} Výchozí nastavení: {} Domyślnie: {} По умолчанию: {} デフォルト: {} $SKI_INFO2{} Number of items required to trigger quantity menu, or 0 to disable it.\nDefault: {} Nombre d'objets requis pour activer le menu de quantité, ou 0 pour le désactiver.\nDéfaut : {} Mindestgröße eines Stapels zum Anzeigen des Mengendialogs.\nVoreinstellung: {} Numero di oggetti richiesti per avviare il menù di quantità, o 0 per disabilitarlo.\nPredefinito: {} Número de objetos requeridos para activar el Menú de Cantidad (0 para deshabilitar).\nPredefinido: {} Počet objektů potřebných k otevření menu s posuvníkem, nebo 0 pro vypnutí.\nVýchozí hodnota: {} Liczba elementów wymagana do aktywacji menu ilości lub 0, aby je wyłączyć.\nDomyślnie: {} Количество элементов необходимое для инициализации меню, число или 0 чтобы отключить.\nПо умолчанию: {} $SKI_INFO3{} Incompatible or outdated SWFs may break SkyUI functionality. This only disables the warning message!\nDefault: {} Des SWF incompatibles ou obsolètes peuvent empêcher le fonctionnement de SkyUI. Cela désactive uniquement le message d'avertissement!\nDéfaut : {} Inkompatible oder veraltete SWF Dateien beeinträchtigen möglicherweise die Funktionalität von SkyUI. Mit dieser Option lässt sich lediglich die Warnung unterdrücken!\nVoreinstellung: {} I file SWF incompatibili o datati potrebbero causare un malfunzionamento nelle funzioni di SkyUI. Questo disabilita solamente i messaggi di avviso!\nPredefinito: {} Los archivos SWF incompatibles o desactualizados pueden provocar un malfuncionamiento de SkyUI. ¡Esto sólo deshabilita el mensaje de advertencia!\nPredefinido: {} Nekonpatibilní nebo zastaralé SWF může narušit funkčnost SkyUI. Zaškrtnutím vypnete zobrazování varovných zpráv!\nVýchozí nastavení: {} Niekompatybilny lub przestarzały SWF może zepsuć funkcjonalność SkyUI. Ta opcja tylko wyłącza ostrzeżenie!\nDomyślnie: {} Несовместимый или устаревший SWF файл может нарушить работу SkyUI. Эта функция отключит всплывающее сообщение!\nПо умолчанию: {} $SKI_INFO4{} Disables Positioning of the 3D Item.\nDefault: {} Désactive le positionnement de l'objet 3D.\nDéfaut : {} Deaktiviert Positionsanpassung der 3D Ansicht.\nVoreinstellung: {} Disabilita il posizionamento dell'oggetto 3D.\nDefault: {} Desactiva el posicionamiento del objeto 3D.\nPredefinido: {} Zakáže polohování 3D objektu.\nVýchozí nastavení: {} Wyłącza pozycjonowanie obiektu 3D.\nDomyślnie: {} Запретить позиционирование 3D объекта в окне просмотра.\nПо умолчанию: {} $SKI_INFO5{} Hide effects with a remaining time higher than this. 0 to show all.\nDefault: {} Cacher effets de durée inférieure à ceci. 0 pour afficher tous.\nDéfaut : {} Mindestrestdauer ab der Effekte angezeigt werden. 0 zeigt alles an.\nVoreinstellung: {} Nasconde gli effetticon un tempo rimanente maggiore di questo. 0 per mostrarli tutti.\nPredefinito: {} Esconder efectos con un tiempo restante superior a éste. 0 para mostrar todos. \nPredefinido: {} Skryje efekty, se zbývajícím časem vyšším než je tato hodnota. 0 zobrazí vše.\nVýchozí nastavení: {} Ukryj efekty z pozostałym czasem większym niż. 0 pokaż wszystkie. \nDomyślne: {} Продолжительность отображения от эффектов на дисплее. 0 показывать всегда \nПо умолчанию: {} $SKI_INFO6 Each group can be configured individually. Chaque groupe peut être configuré individuellement. Jede Gruppe kann einzeln konfiguriert werden. Ogni gruppo può essere configurato individualmente. Cada grupo puede ser configurado individualmente. Každá skupina může být nastavena samostatně. Każda grupa może być skonfigurowana oddzielnie. Каждая группа может иметь индивидуальные настройки $SKI_INFO7{} Unequip all armor before Group Use?\nDefault: {} Déséquiper armure avant Utilisation en Groupe ?\nDéfaut : {} Rüstung vorm Benutzen der Gruppe ausziehen? Disequipaggiare tutta l'armatura prima dell'Uso del Gruppo?\nPredefinito: {} ¿Desequipar todas las piezas de armadura antes de Usar Grupo?\nPredefinido: {} Má být před použitím skupiny vysvléknuta zbroj?\nVýchozí nastavení: {} Ściągnij całą zbroję przed użyciem Grup?\nDomyślne: {} Снять всю броню перед использованием группы?\nПо умолчанию: {} $SKI_INFO8{} Unequip both hands before Group Use?\nDefault: {} Déséquiper mains avant Utilisation en Groupe ?\nDéfaut : {} Beide Hände vorm Benutzen der Gruppe freimachen? Disequipaggiare entrambe le mani prima dell'Uso del Gruppo?\nPredefinito: {} ¿Desequipar ambas manos antes de Usar Grupo?\nPredefinido: {} Mají být před použitím skupiny vyprázdněny obě ruce?\nVýchozí nastavení: {} Ściągnij rękawice przed użyciem Grup?\nDomyślne: {} Разоружить обе руки перед использованием группы?\nПо умолчанию: {} $SKI_INFO9{} Unequip any ammo before Group Use?\nDefault: {} Déséquiper munitions avant Utilisation en Groupe ?\nDéfaut : {} Munition vorm Benutzen der Gruppe freimachen? Disequipaggiare qualsiasi munizione prima dell'Uso del Gruppo?\nPredefinito: {} ¿Desequipar cualquier munición antes de Usar Grupo?\nPredefinido {} Má být před použitím skupiny sundána veškerá munice?\nVýchozí nastavení: {} Ściągnij amunicję przed użyciem Grup?\nDomyślne: {} Снять любые боеприпасы перед использованием группы?\nПо умолчанию: {} $SKI_MSG1 This control requires a keyboard mapping. Cette fonction doit être affectée à une touche. Diese Funktion muss einer Tastatureingabe zugewiesen werden. Questo controllo richiede una mappatura della tastiera. Este control necesita ser configurado en el teclado Funkce vyžaduje nastavení klávesy na klávesnici. Ta funkcja wymaga przypisania klawisza. Для этой функции необходимо назначить клавишу. このコントロールは、キーボードのマッピングを必要とします。 $SKI_MSG2{} This key is already mapped to:\n{}\n\nAre you sure you want to continue? Cette touche est déjà affectée à : \n{}\n\nContinuer ? Diese Taste wird bereits verwendet:\n{}\n\nTrotzdem fortfahren? Questo tasto è già stato assegnato a:\n{}\n\nSicuro di voler continuare? Este botón ya está asignado a:\n{}\n\n ¿Estás seguro que quieres continuar? Tato klávesa je již používána:{}\n\nOpravdu chcete pokračovat? Ten klawisz jest przypisany do: \n{}\n\nCzy jesteś pewien, że chcesz kontynuować? Эта клавиша уже используется:\n{}\n\nВы уверены, что хотите продолжить? $NAME $ $ $ $ $ $ NAZWA $ $ $ TO PLACE $ $ $ $ $ $ $ ПОМЕСТИТЬ $ $ TO STEAL $ $ $ $ $ $ $ УКРАСТЬ $ $GEAR GEAR ÉQUIPEMENT AUSRÜSTUNG ATTREZZATURA EQUIPO VYBAVENÍ EKWIPUNEK СНАРЯЖЕНИЕ $AID AID AIDE HILFSMITTEL AIUTO AYUDA POMOC POMOC ЗЕЛЬЯ И ЕДА $GROUP GROUP GROUPE GRUPPE GRUPPO GRUPO SKUPINA GRUPA ГРУППА $Group {} Group {} Groupe {} Gruppe {} Gruppo {} Grupo {} Skupina {} Grupa{} Группа {} $Show Button Help Show Button Help Montrer bouton d'aide Tastenhilfe Anzeigen Mostra il tasto Aiuto Mostrar botón de ayuda Zobrazovat nápovědu ke klávesám Wyświetl pomoc klawiszy Показать Кнопки Помощи $Favorites Menu Favorites Menu Menu Favoris Favoritenmenü Menu dei Preferiti Menu de Favoritos Menu oblíbených Menu ulubionych Меню Избранного $Preferences Preferences Préférences Einstellungen Preferenze Preferencias Nastavení Preferencje Настройки $Confirm Group Confirm Group Confirmer groupe Gruppe Bestätigen Confermare gruppo Confirmar grupo Potvrdit skupinu Potwierdź grupę Подтвердить Группу $Select Group Select Group Choisir groupe Gruppe Auswählen Selezionare gruppo Seleccionar grupo Vybrat skupinu Wybierz grupę Выбрать Группу $Group Group Grouper Gruppieren Raggruppare Agrupar Zařadit Grupuj Добавить в Группу $Ungroup Ungroup Dégrouper Gruppierung Aufheben Anullamento gruppo Desagrupar Odebrat Usuń z grupy Убрать из Группы $Set Group Icon Set Group Icon Choisir icône groupe Symbol Setzen Scegliere icona gruppo Elegir icono de grupo Přiřadit skupině ikonu Wybierz ikonę dla grupy Выбрать Иконку Группы $Set Main Hand Set Main Hand Choisir main principale Primärhand Setzen Scegliere mano principale Elegir mano principal Vybrat hlavní ruku Wybierz główną rękę Выбрать Основную Руку $Save Equip State Save Equip State Sauvegarder équipement Ausrüstung Speichern Salva lo stato dell'Equipaggiamento Guardar estado del equipo Uložit stav vybavení Zapamiętaj stan ekwipunku Сохранить Состояние Экипировки $Group Use Group Use Utiliser groupe Gruppe Benutzen Usare gruppo Usar grupo Použít skupinu Ubierz grupę Использовать Группу $Toggle Focus Toggle Focus Changer Focus Fokus Wechseln Cambiare Focus Cambiar enfoque Přepnout zaměření Przełącz widok Переместить Фокус $Unequip Armor Unequip Armor Déséquiper armure Rüstung Freimachen Disequipaggiare corazza Desequipar Armadura Svléknout zbroj Ściągnij zbroję Снять Броню $Unequip Hands Unequip Hands Déséquiper mains Hände Freimachen Disequipaggiare mani Desequipar manos Vyprázdnit ruce Ściągnij rękawice Разоружить Руки $Unequip Ammo Unequip Ammo Déséquiper munitions Munition Freimachen Disequipaggiare munizione Desequipar munición Sundat munici Ściągnij amunicję Снять Боеприпасы % Completion 100.00% 100.00% 100.00% 97.89% 97.89% 97.89% 97.89% 97.89% 83.03% ================================================ FILE: misc/Translations/make_translations.pl ================================================ #!/usr/bin/perl sub error { print "\n=========================\n\n" . "ERROR: $_[0]\n"; getc(STDIN); exit(1); } my $sourcePath = "SkyUI_Translations.txt"; open SOURCE, "<:utf8", $sourcePath or error("Cannot open $sourcePath: $!"); my @langs = split("\t", ); shift @langs; my @files; foreach $lang (@langs) { chomp($lang); $lang = lc($lang); local *FILE; local $fileName = "SkyUI_$lang.txt"; open(FILE, ">:raw:encoding(UCS2-LE):crlf:utf8", "$fileName"); print FILE ("\x{FEFF}"); # print BOM push(@files,*FILE); } while (my $line = ) { chomp($line); local @buf = split("\t", $line); local $key = shift @buf; next unless $key and $key =~ /^\$/; local $i=0; foreach $file (@files) { local $str = $buf[$i] ? $buf[$i] : $buf[0]; # fall back to english if no translate present print $file ($key . "\t" . $str . "\n") unless $str eq "\$"; $i++; } } close(SOURCE); foreach $file (@files) { close $file; } print "Done.\n\n"; getc(STDIN); exit(0); ================================================ FILE: misc/cp-built-files ================================================ #!/usr/bin/env ruby # This utility copys the newly built files in ../build to the # `destination_dir`. It's also possible to watch the directory # so built files are copied automatically. # # This was written for ruby 2.5 and requires WSL and the 'listen' # gem for the directory watching capability. require('optparse') require('pathname') require('fileutils') options = {} optParser = OptionParser.new do |opts| opts.banner = "Usage: cpBuiltFiles [options] destination_dir" opts.on("-w", "--watch", "Watch built directory") do options[:watch] = true end opts.on_tail("-h", "--help", "Show this message") do puts opts exit end end optParser.parse! destDir = ARGV.pop if not destDir then destDir = ENV["SKYUIVR_TEST_DIR"] end if not destDir then puts optParser exit end # This is where we'll be trying to copy files from srcDirPath = Pathname.new(__FILE__).parent + "../build" # This is where we'll be trying to copy files to destDirPath = Pathname.new(destDir) puts("Checking: #{destDir}\n\n") filesCopied = 0 # For each file in the destination directory... Pathname.glob("#{destDir}/**/*").each do |destPath| # For all files (not a directory)... next if destPath.directory? next if destPath.to_s.include? "/exported/" srcPath = srcDirPath + destPath.relative_path_from(destDirPath) # If the a matching file from the build (src) directory exists, and it appears # to be newer... # This should mean that the file was newly built. if srcPath.exist? && srcPath.mtime() > destPath.mtime() then # Copy the file over to the destination puts("#{srcPath} => #{destPath}") FileUtils::copy_file(srcPath.realpath, destPath.realpath) filesCopied = filesCopied + 1 end end if filesCopied != 0 then puts end puts("#{filesCopied} files copied") def getDestPath(srcBaseDirPath, srcFilePath, destBaseDirPath) return destBaseDirPath + srcFilePath.relative_path_from(srcBaseDirPath) end if options[:watch] then require('listen') require('thread') def waitFileStopsGrowing(filename) oldSize = 0 newSize = File.size(filename) while oldSize != newSize do oldSize = newSize sleep(1) newSize = File.size(filename) end end puts("Watching #{srcDirPath} for changes...") # Create a set that records which files we're waiting for to finish writing semaphore = Mutex.new filesBeingWritten = Set.new # Wait for a file to finish being written then copy it to the destination copierThread = Thread.new do while true do # Wait until we found a file that has been modified sleep(0.25) files = filesBeingWritten.to_a if files.length == 0 then next end # Wait for the file to stop growing modifiedFile = files[0] modifiedPath = Pathname.new(modifiedFile) waitFileStopsGrowing(modifiedPath) # Figure out where to copy the file from & to srcPath = modifiedPath destPath = getDestPath(srcDirPath.realpath, srcPath, destDirPath) # Don't copy the file if it doesn't already exist in the destination next if !destPath.exist? # Actually copy the file when ready time = Time.new while true do begin puts("[#{time.strftime("%H:%M")}] #{srcPath} => #{destPath}") FileUtils::copy_file(srcPath, destPath) break rescue puts("File wasn't ready. Retrying.") sleep(1) next end end # Make sure we stop waiting for the file the next iteration semaphore.synchronize do filesBeingWritten.delete(modifiedFile) end end end listenThread = Thread.new do listener = Listen.to(srcDirPath) do |modified, added, removed| if modified then semaphore.synchronize do modified.each do |f| next if f.include? "/exported/" filesBeingWritten.add(f) end end end end listener.start sleep end # notifier = INotify::Notifier.new # notifier.watch(srcDirPath.to_s, :close) do |event| # # The #name field of the event object contains the name of the affected file # puts "#{event.name} modified" # end # notifier.run sleep end ================================================ FILE: misc/decompile-pex ================================================ #! env ruby def toWinPath(wslPath) cmd = "wslpath -w '#{wslPath}'" return `#{cmd}`.strip end # This utility decompiles every pex file in the target_dir # and places the result file in the same directory. require('optparse') require('pathname') require('fileutils') options = {} optParser = OptionParser.new do |opts| opts.banner = "Usage: decompile-pex [options] target_dir" # opts.on("-w", "--watch", "Watch built directory") do # options[:watch] = true # end opts.on_tail("-h", "--help", "Show this message") do puts opts exit end end optParser.parse! targetDir = ARGV.pop if not targetDir then puts optParser exit end targetDirPath = Pathname.new(targetDir) if !targetDirPath.exist? or !targetDirPath.directory? then puts "Cannot locate target directory: " + targetDirPath; exit 1 end decompiler = ENV['PEX_DECOMPILER'] if !File.exists?(decompiler) then puts "Cannot locate decompiler from $PEX_DECOMPILER"; exit 1 end Dir.chdir targetDirPath Pathname.glob("#{targetDirPath}/**/*.pex").each do |f| next if f.directory? cmd = "\"#{decompiler}\" -p \"#{toWinPath(targetDirPath)}\" \"#{toWinPath(f)}\"" puts `#{cmd}` end ================================================ FILE: misc/pack-release ================================================ #!/usr/bin/env ruby # require('pathname') require('fileutils') require('tmpdir') # Make sure we can find where the files we're packing from testDir = ENV["SKYUIVR_TEST_DIR"] if not testDir then puts "Please set a directory to package from using $SKYUIVR_TEST_DIR" exit end # Make sure we have a place to put the packed file releaseDir = ENV["SKYUIVR_RELEASE_DIR"] if not releaseDir then puts "Please set a directory to package from using $SKYUIVR_RELEASE_DIR" exit end puts "Add a tag?" tag = gets.chomp # Make a temp directory to copy the files to be compressed tempDir = Dir.mktmpdir("skyuivr-pack") tempPath = Pathname.new(tempDir) puts tempPath # Copy the files in the test directory to a new temp directory named "SkyUI" srcPath = Pathname.new(testDir) # contentPath = Pathname.new(tempDir) + "SkyUI" # FileUtils.mkdir_p(contentPath) puts "Copying from #{srcPath} => #{tempPath}" FileUtils::cp_r(srcPath.realpath, tempPath.realpath) contentPath = tempPath + "SkyUI" FileUtils.mv(tempPath + srcPath.basename, contentPath) FileUtils::rm_f(contentPath + "meta.ini") # Zip up the directory if tag[0] == "v" then archiveFilename = tempPath + "SkyUI.#{tag}.7z" else archiveFilename = tempPath + "SkyUI - #{tag}.7z" end puts "ContentPath: #{contentPath}" system("7z a '#{archiveFilename}' '#{contentPath}'") FileUtils::cp(archiveFilename, releaseDir) ================================================ FILE: misc/rename-png ================================================ #! env ruby def toWinPath(wslPath) cmd = "wslpath -w '#{wslPath}'" return `#{cmd}`.strip end # This is a one-off utility to rename png files in a directory. # We're exporting icon pngs from the VR version of the game # to use in the help text. # # Ideally, we would export all the known button art as png # and import them again. I'm being lazy and skipping that for now. require('optparse') require('pathname') require('fileutils') options = {} optParser = OptionParser.new do |opts| opts.banner = "Usage: decompile-pex [options] target_dir" # opts.on("-w", "--watch", "Watch built directory") do # options[:watch] = true # end opts.on_tail("-h", "--help", "Show this message") do puts opts exit end end optParser.parse! targetDir = ARGV.pop if not targetDir then puts optParser exit end targetDirPath = Pathname.new(targetDir) if !targetDirPath.exist? or !targetDirPath.directory? then puts "Cannot locate target directory: " + targetDirPath; exit 1 end def transformName(oldName) oldName = oldName.to_s firstUnderscore = oldName.to_s.index('_') return oldName.slice(firstUnderscore+1, oldName.length - 4 - firstUnderscore - 1) end Pathname.glob(targetDirPath + "*.png.png").each do |f| puts "#{f} => #{targetDirPath + transformName(f)}" f.rename(targetDirPath + transformName(f)) end ================================================ FILE: misc/reorder-psc ================================================ #! env ruby # Reorder/rewrite the psc file so content is sorted into the same order # by entity/construct name. This is useful for comparing two sets of # decompiled pex files. require('optparse') require('pathname') require('fileutils') require('pp') options = {} optParser = OptionParser.new do |opts| opts.banner = "Usage: cpBuiltFiles [options] destination_dir" opts.on("-w", "--watch", "Watch built directory") do options[:watch] = true end opts.on_tail("-h", "--help", "Show this message") do puts opts exit end end optParser.parse! destDir = ARGV.pop if not destDir then puts optParser exit end # This is where the psc files are destDirPath = Pathname.new(destDir) filesProcessed = 0 def lineOffsets(f) offsets = [] curOffset = 0 File.readlines(f).each do |line| offsets.append << curOffset curOffset += line.length end return offsets end def lineNum(lineoffsets, offset) lineoffsets.each_with_index do |entry, index| if entry > offset return index end end return lineoffsets.length end # Retrieve all "property" entries, their names, and their offset into the file def properties(f) singlelineProps = /^.*property\b(.*)\bauto$/ multilineProps = /\bproperty\b(.*?)\b?$.*?\bendproperty\b/m matches = IO.read(f).to_enum(:scan, multilineProps) .map { Regexp.last_match } .map { |match| {name: match.captures.first.strip , offsets: match.offset(0)} } end # Retrieve all "state" entries, their names, and their offset into the file def states(f) regex = /\bstate\b(.*?)\b?$.*?\bendState\b/m matches = IO.read(f).to_enum(:scan, regex) .map { Regexp.last_match } .map { |match| {name: match.captures.first.strip , offsets: match.offset(0)} } end def functions(f) regex = /\bfunction\b(.*?)\b?$.*?\bendFunction\b/m matches = IO.read(f).to_enum(:scan, regex) .map { Regexp.last_match } .map { |match| {name: match.captures.first.strip , offsets: match.offset(0)} } end def variables(f) # TODO!!! This needs to be done over lines instead of over the entire file regex = /\b(.*?)\b(.*?)\b?$/m matches = IO.read(f).to_enum(:scan, regex) .map { Regexp.last_match } .map { |match| {name: match.captures.first.strip , offsets: match.offset(0)} } end # Entries usually contain byte offsets into the file. # This function adds a field that indictes the actual line numbers the entry spans def entryAddLineNum(entry, lineoffsets) entry[:lines] = entry[:offsets].map { |offset| lineNum(lineoffsets, offset)}; entry end def lineSpanExpand(linespan) Range.new(linespan.first, linespan.last).to_a end def unprocessedLines(f, processedLines) Range.new(1, IO.read(f).lines.length).to_a - processedLines end def linespansToLines(linespans) linespans .map { |linespan| lineSpanExpand(linespan) } .reduce([]) { |accum, lines| accum + lines } end Pathname.glob("#{destDir}/*.psc").each do |f| filesProcessed += 1 # next if filesProcessed > 1 puts "Processing: #{f}" lineoffsets = lineOffsets(f) props = properties(f) props = props .map { |entry| entryAddLineNum(entry, lineoffsets) } .sort_by { |entry| entry[:name] } proplines = linespansToLines(props.map { |entry| entry[:lines] }) states = states(f) states = states .map { |entry| entryAddLineNum(entry, lineoffsets) } .sort_by { |entry| entry[:name] } statelines = linespansToLines(states.map { |entry| entry[:lines] }) funcs = functions(f) funcs = funcs .map { |entry| entryAddLineNum(entry, lineoffsets) } .sort_by { |entry| entry[:name] } funclines = linespansToLines(funcs.map { |entry| entry[:lines] }) - proplines - statelines puts "props:" pp props puts "states:" pp states # Figure out all the lines already processed processedLines = props.map { |entry| entry[:lines] } processedLines += states.map { |entry| entry[:lines] } processedLines += funcs.map { |entry| entry[:lines] } processedLines = linespansToLines(processedLines) upl = unprocessedLines(f, processedLines) flines = f.readlines File.open(f.sub_ext(".out"), "w") {|outf| outf.puts(";;; --- Properties ---------------------------------"); proplines.each { |lineNum| outf.write(flines[lineNum-1]) } outf.puts outf.puts outf.puts(";;; --- Functions ----------------------------------"); funclines.each { |lineNum| outf.write(flines[lineNum-1]) } outf.puts outf.puts outf.puts(";;; --- States -------------------------------------"); statelines.each { |lineNum| outf.write(flines[lineNum-1]) } outf.puts outf.puts outf.puts(";;; --- Unprocessed --------------------------------"); upl.each { |lineNum| line = flines[lineNum-1] if !line.strip.empty? then outf.write(flines[lineNum-1]) end } } end ================================================ FILE: sksevr_plugin/.editorconfig ================================================ root = true [*] charset = utf-8 indent_style = space indent_size = 3 end_of_line = lf trim_trailing_whitespace = true insert_final_newline = true ================================================ FILE: sksevr_plugin/.gitignore ================================================ *.user *.suo **/.vs /Build lua-tests/luacov* ================================================ FILE: sksevr_plugin/README.md ================================================ # Skyrim SKSE plugin example This has been adapted from [this example](https://github.com/xanderdunn/skaar/releases/tag/plugin3). It has a simple build script to simplify the build process. It's also been tidied up a bit, and updated to use Visual Studio 2017. ## Requirements - Skyrim - The Creation Kit - [Python 3.6](https://www.python.org/downloads/) for the build script - [Visual Studio 2017](https://visualstudio.microsoft.com/vs/express/) - "VC++ 2017 version 15.8 v14.15 latest v141 tools" - "Windows Universal CRT SDK" ## Getting Started Ignore the `common` and `skse` directories, they are included from SKSE and are required for the plugin to compile. The directory of interest for your plugin is `plugin`. Paths relevant to the build script are stored in `build.ini`, you may need to edit these, particularly if you're not installing with Steam on a 64-bit machine. To compile, run: ``` python build.py ``` This will compile the plugin and any Papyrus scripts in the `plugin\scripts` directory to the `Debug` directory. When you have finished developing and are ready to compile a release version, run the following: ``` python build.py --release ``` This will compile to the `Release` directory. You can then use the following to install the compiled plugin and scripts to your Skyrim installation's directory: ``` python build.py install ``` Or: ``` python build.py install --release ``` From here follow [this guide](https://github.com/xanderdunn/skaar/wiki/SKSE%3A-Getting-Started). ================================================ FILE: sksevr_plugin/build.ini ================================================ [Paths] skyrim=C:\Program Files (x86)\Steam\steamapps\common\Skyrim msbuild=C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\MSBuild.exe ================================================ FILE: sksevr_plugin/build.py ================================================ import configparser import os import shutil import subprocess import sys def search_arguments(needle): found = False for argument in sys.argv[1:]: if argument == needle: found = True break return found def configuration(): return "Release" if search_arguments("--release") else "Debug" def root_path(): return os.path.dirname(os.path.realpath(__file__)) def read_ini(): ini = configparser.ConfigParser() ini_path = os.path.join(root_path(), "build.ini") ini.read(ini_path) return ini def read_paths(): return read_ini()["Paths"] def build_path(): return os.path.join(root_path(), configuration()) def skyrim_path(): return read_paths()["skyrim"] def papyrus_compiler_path(): return os.path.join(skyrim_path(), r"Papyrus Compiler\PapyrusCompiler.exe") def skyrim_compiled_scripts_path(): return os.path.join(skyrim_path(), r"Data\scripts") def skyrim_scripts_path(): return os.path.join(skyrim_compiled_scripts_path(), r"Source") def scripts_path(): return os.path.join(root_path(), r"plugin\scripts") def compiled_scripts_path(): return os.path.join(build_path(), "scripts") def msbuild_path(): return read_paths()["msbuild"] def run_command(command): result = subprocess.run( command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) if result.returncode != 0: print("--- The following command failed with code:", result.returncode) print(command.strip()) print("--- Standard output:") print(result.stdout.decode("utf-8")) print("--- Error output") print(result.stderr.decode("utf-8")) sys.exit(1) def compile_plugin(): project_path = os.path.join(root_path(), "plugin.sln") command = """ \ "{compiler_path}" \ "{project_path}" \ /property:Configuration={configuration} \ """.format( compiler_path=msbuild_path(), project_path=project_path, configuration=configuration() ) run_command(command) def compile_scripts(): output_path = compiled_scripts_path() os.makedirs(output_path, exist_ok=True) command = """ \ "{compiler_path}" \ "{scripts_path}" \ -all \ -flags="TESV_Papyrus_Flags.flg" \ -import="{skyrim_scripts_path};{scripts_path}" \ -output="{output_path}" \ """.format( compiler_path=papyrus_compiler_path(), skyrim_scripts_path=skyrim_scripts_path(), scripts_path=scripts_path(), output_path=output_path ) run_command(command) def build(): compile_plugin() compile_scripts() def copy_plugin(): plugin_path = os.path.join(build_path(), "plugin.dll") plugins_path = os.path.join(skyrim_path(), r"Data\skse\plugins") os.makedirs(plugins_path, exist_ok=True) shutil.copy2(plugin_path, plugins_path) def copy_files(source, destination): with os.scandir(source) as entries: for entry in entries: if entry.is_file(): shutil.copy2(entry.path, destination) def copy_script_sources(): skyrim_scripts_directory = skyrim_scripts_path() os.makedirs(skyrim_scripts_directory, exist_ok=True) copy_files(scripts_path(), skyrim_scripts_directory) def copy_compiled_scripts(): skyrim_compiled_scripts_directory = skyrim_compiled_scripts_path() os.makedirs(skyrim_compiled_scripts_directory, exist_ok=True) copy_files(compiled_scripts_path(), skyrim_compiled_scripts_directory) def install(): copy_plugin() copy_script_sources() copy_compiled_scripts() if __name__ == "__main__": if search_arguments("install"): install() else: build() ================================================ FILE: sksevr_plugin/lua/MainEntry.lua ================================================ function file_exists(name) local f=io.open(name,"r") if f~=nil then io.close(f) return true else return false end end function path_split(path) local steps = {} local idx = 1 for str in string.gmatch(path, "([^/]+)") do steps[idx] = str idx = idx + 1 end return steps end function table_is_empty(t) return next(t) == nil end -- We want to keep the FormDB relatively clean and free of empty tables. -- While it is possible to just walk the entire table tree to locate and -- remove empty tables, this may cause a *LOT* of nodes to be visited. -- -- Instead, we only compact tables along a particular path when something -- is being removed (set to nil). When this happens, we know the exact -- tables and fields we must examine to keep the db compacted. -- function table_trail_compact(trail) -- Starting from the parent of the leaf node, work backwards towards the root for i = #trail, 1, -1 do local post = trail[i] local target = post.t[post.k] assert(type(target) == "table") if table_is_empty(target) then post.t[post.k] = nil else break end end end -- Given a (tree of) tables, starting at `root`... -- Iteratively walk through the `path`, creating tables/nodes if required, -- to set the given 'val' -- -- See clojure's `assoc-in` -- -- For example, the call -- table_set_by_path({}, "hello/world", 1) -- -- Should give us -- { hello = -- { world = 1 } -- } -- -- Returns: -- root - on success -- nil, err_msg - on failure function table_set_by_path(root, path, val) local steps = path_split(path) local step_cnt = #steps local is_delete = val == nil -- Assuming we're dealing with a tree of tables -- Start walking at the passed root local cur = root local trail = nil if is_delete then trail = {} end for i, k in ipairs(steps) do if i == step_cnt then break end -- Try to get the table that's next level down local candidate = cur[k] -- Create the table right now, if it isn't present if not candidate then candidate = {} cur[k] = candidate -- If we reached a leaf node in the tree when we expected to be able to go further... -- Abort the walk with an error messsage elseif type(candidate) ~= "table" then return nil, string.format("[set_by_path] Path '%s' reached a val of type '%s' unexpectedly", table.concat(steps, "/", 1, i), type(candidate)) end if is_delete then table.insert(trail, {t = cur, k = k}) end -- Update the cursor so we can walk deeper into the tree cur = candidate end cur[steps[step_cnt]] = val if is_delete then table_trail_compact(trail) end return root end function inspect(o) local dump = require("inspect") print(dump(o)) end function print_value_recursive(o) inspect(o) end -- Given a (tree of) tables, starting at `root`... -- Iteratively walk through the `path` to fetch a value -- If the item is not present, return the `default` -- -- See clojure's `get-in` -- -- Returns: -- root - on success -- nil, err_msg - on failure function table_get_by_path(root, path, default) local steps = path_split(path) local step_cnt = #steps -- Assuming we're dealing with a tree of tables -- Start walking at the passed root local cur = root for i, k in ipairs(steps) do -- Can we actually move further into the path? if type(cur) ~= "table" then return default, string.format("[get_by_path] Path '%s' reached a val of type '%s' unexpectedly", table.concat(steps, "/", 1, i), type(candidate)) end -- Walk deeper into the tree cur = cur[k] end if cur == nil then return default else return cur end end function load_settings_file(path) local chunk = loadfile(path) local env={} setfenv(chunk, env) chunk() return env end function settings_get_by_path_with_defaults(root, path, defaults_filename, default) local defaultsTop = "SettingsDefaults" local defaults_table = nil print("defaults_filename: ", defaults_filename) -- Try to access "SettingsDefaults/defaults_filename" -- We can't use table_get_by_path() here because the `defaults_filename` will likely -- contain path separators, which interferes with the way the function works. local t = _G[defaultsTop] print("--- 0 ---") print("_G[defaultsTop]") inspect(t) if t then print("--- 1 ---") defaults_table = t[defaults_filename] print("defaults_table") inspect(defaults_table) else print("--- 2 ---") _G[defaultsTop] = {} end print("--- 3 ---") if not defaults_table then -- Load the settings file local file_contents = load_settings_file(defaults_filename) if file_contents then print("--- 4 ---") print("loaded from file") inspect(file_contents) defaults_table = {} print("defaults top: ", defaultsTop) print("defaults_filename: ", defaults_filename) _G[defaultsTop][defaults_filename] = defaults_table defaults_table["Settings"] = file_contents["Settings"] end end print("--- 5 ---") local val = table_get_by_path(root, path, nil); if not val then print("--- 6 ---") print("--- reverting to defaults ---") val = table_get_by_path(defaults_table, path, nil); end if nil == val then return default else print("val") inspect(val) return val end end function Form_FetchDataLazyInit(formID) local o = FormDB[formID] if not o then o = {} FormDB[formID] = o end return o end function Form_SetVal(formID, field_path, val) local o = Form_FetchDataLazyInit(formID) local result = {table_set_by_path(o, field_path, val)} if table_is_empty(o) then Form_RemoveAllFields(formID) end return unpack(result) end function Form_GetVal(formID, field_path, default_val) -- Fetch the table that stores the data associated with the form local o = FormDB[formID] if not o then return default_val end return table_get_by_path(o, field_path, default_val) end function Form_RemoveField(formID, field_path) return Form_SetVal(formID, field_path, nil) end function Form_RemoveAllFields(formID) FormDB[formID] = nil end function FormDB_init() FormDB = {} end -- Do no reinitialize the FormDB if already present if not _G["FormDB"] then FormDB_init() end ================================================ FILE: sksevr_plugin/lua/defaults-general.lua ================================================ Settings = { -- On a per-menu basis, change the keybind used to activate the search function. -- We're just using a bunch of strings try narrowing down when the search function -- should be triggerred. -- -- For example: -- {"thumbstick", "clicked"} => triggers when either thumbstick click starts -- {"leftHand", "thumbstick", "clicked"} => triggers when the left hand thumbstick click starts -- {"rightHand", "touchpad", "center", "touched"} => triggers when the right hand touchpad has its center touched -- -- Strings to indicate handedness: -- "leftHand", "rightHand" -- -- Strings to indicate widget type: -- "touchpad", "thumbstick", "application menu", "grip", "trigger", "b button", "a button", "x button", "y button" -- -- Strings to indicate touchpad region: -- "top", "right", "left", "bottom", "center" -- -- Strings to indicate widget "phase": (touched => pressed => clicked => pressed => touched) -- "touched", "pressed", "clicked" -- -- Strings to trigger either when a phase starts or ends: -- "start", "end" BarterMenu = { search = {} }, ContainerMenu = { search = {} }, CraftingMenu = { search = {} }, GiftMenu = { search = {} }, InventoryMenu = { search = {} }, MagicMenu = { search = {} }, } ================================================ FILE: sksevr_plugin/lua/defaults-knuckles.lua ================================================ Settings = { BarterMenu = { search = {"thumbstick", "clicked"} }, ContainerMenu = { search = {"thumbstick", "clicked"} }, CraftingMenu = { search = {"thumbstick", "clicked"} }, GiftMenu = { search = {"thumbstick", "clicked"} }, InventoryMenu = { search = {"thumbstick", "clicked"} }, MagicMenu = { search = {"thumbstick", "clicked"} }, } ================================================ FILE: sksevr_plugin/lua/defaults-oculus.lua ================================================ Settings = { BarterMenu = { search = {"leftHand", "thumbstick", "clicked"} }, ContainerMenu = { search = {"leftHand", "thumbstick", "clicked"} }, CraftingMenu = { search = {"leftHand", "thumbstick", "clicked"} }, GiftMenu = { search = {"leftHand", "thumbstick", "clicked"} }, InventoryMenu = { search = {"leftHand", "thumbstick", "clicked"} }, MagicMenu = { search = {"leftHand", "thumbstick", "clicked"} }, } ================================================ FILE: sksevr_plugin/lua/defaults-vive.lua ================================================ Settings = { BarterMenu = { search = {"touchpad", "clicked", "bottom"} }, ContainerMenu = { search = {"touchpad", "clicked", "bottom"} }, CraftingMenu = { search = {"application menu", "clicked"} }, GiftMenu = { search = {"touchpad", "clicked", "bottom"} }, InventoryMenu = { search = {"touchpad", "clicked", "bottom"} }, MagicMenu = { search = {"touchpad", "clicked", "bottom"} }, } ================================================ FILE: sksevr_plugin/lua/defaults-wmr.lua ================================================ Settings = { BarterMenu = { search = {"application menu", "clicked"} }, ContainerMenu = { search = {"application menu", "clicked"} }, CraftingMenu = { search = {"application menu", "clicked"} }, GiftMenu = { search = {"application menu", "clicked"} }, InventoryMenu = { search = {"application menu", "clicked"} }, MagicMenu = { search = {"application menu", "clicked"} }, } ================================================ FILE: sksevr_plugin/lua/inspect.lua ================================================ local inspect ={ _VERSION = 'inspect.lua 3.1.0', _URL = 'http://github.com/kikito/inspect.lua', _DESCRIPTION = 'human-readable representations of tables', _LICENSE = [[ MIT LICENSE Copyright (c) 2013 Enrique García Cota Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ]] } local tostring = tostring inspect.KEY = setmetatable({}, {__tostring = function() return 'inspect.KEY' end}) inspect.METATABLE = setmetatable({}, {__tostring = function() return 'inspect.METATABLE' end}) local function rawpairs(t) return next, t, nil end -- Apostrophizes the string if it has quotes, but not aphostrophes -- Otherwise, it returns a regular quoted string local function smartQuote(str) if str:match('"') and not str:match("'") then return "'" .. str .. "'" end return '"' .. str:gsub('"', '\\"') .. '"' end -- \a => '\\a', \0 => '\\0', 31 => '\31' local shortControlCharEscapes = { ["\a"] = "\\a", ["\b"] = "\\b", ["\f"] = "\\f", ["\n"] = "\\n", ["\r"] = "\\r", ["\t"] = "\\t", ["\v"] = "\\v" } local longControlCharEscapes = {} -- \a => nil, \0 => \000, 31 => \031 for i=0, 31 do local ch = string.char(i) if not shortControlCharEscapes[ch] then shortControlCharEscapes[ch] = "\\"..i longControlCharEscapes[ch] = string.format("\\%03d", i) end end local function escape(str) return (str:gsub("\\", "\\\\") :gsub("(%c)%f[0-9]", longControlCharEscapes) :gsub("%c", shortControlCharEscapes)) end local function isIdentifier(str) return type(str) == 'string' and str:match( "^[_%a][_%a%d]*$" ) end local function isSequenceKey(k, sequenceLength) return type(k) == 'number' and 1 <= k and k <= sequenceLength and math.floor(k) == k end local defaultTypeOrders = { ['number'] = 1, ['boolean'] = 2, ['string'] = 3, ['table'] = 4, ['function'] = 5, ['userdata'] = 6, ['thread'] = 7 } local function sortKeys(a, b) local ta, tb = type(a), type(b) -- strings and numbers are sorted numerically/alphabetically if ta == tb and (ta == 'string' or ta == 'number') then return a < b end local dta, dtb = defaultTypeOrders[ta], defaultTypeOrders[tb] -- Two default types are compared according to the defaultTypeOrders table if dta and dtb then return defaultTypeOrders[ta] < defaultTypeOrders[tb] elseif dta then return true -- default types before custom ones elseif dtb then return false -- custom types after default ones end -- custom types are sorted out alphabetically return ta < tb end -- For implementation reasons, the behavior of rawlen & # is "undefined" when -- tables aren't pure sequences. So we implement our own # operator. local function getSequenceLength(t) local len = 1 local v = rawget(t,len) while v ~= nil do len = len + 1 v = rawget(t,len) end return len - 1 end local function getNonSequentialKeys(t) local keys, keysLength = {}, 0 local sequenceLength = getSequenceLength(t) for k,_ in rawpairs(t) do if not isSequenceKey(k, sequenceLength) then keysLength = keysLength + 1 keys[keysLength] = k end end table.sort(keys, sortKeys) return keys, keysLength, sequenceLength end local function countTableAppearances(t, tableAppearances) tableAppearances = tableAppearances or {} if type(t) == 'table' then if not tableAppearances[t] then tableAppearances[t] = 1 for k,v in rawpairs(t) do countTableAppearances(k, tableAppearances) countTableAppearances(v, tableAppearances) end countTableAppearances(getmetatable(t), tableAppearances) else tableAppearances[t] = tableAppearances[t] + 1 end end return tableAppearances end local copySequence = function(s) local copy, len = {}, #s for i=1, len do copy[i] = s[i] end return copy, len end local function makePath(path, ...) local keys = {...} local newPath, len = copySequence(path) for i=1, #keys do newPath[len + i] = keys[i] end return newPath end local function processRecursive(process, item, path, visited) if item == nil then return nil end if visited[item] then return visited[item] end local processed = process(item, path) if type(processed) == 'table' then local processedCopy = {} visited[item] = processedCopy local processedKey for k,v in rawpairs(processed) do processedKey = processRecursive(process, k, makePath(path, k, inspect.KEY), visited) if processedKey ~= nil then processedCopy[processedKey] = processRecursive(process, v, makePath(path, processedKey), visited) end end local mt = processRecursive(process, getmetatable(processed), makePath(path, inspect.METATABLE), visited) if type(mt) ~= 'table' then mt = nil end -- ignore not nil/table __metatable field setmetatable(processedCopy, mt) processed = processedCopy end return processed end ------------------------------------------------------------------- local Inspector = {} local Inspector_mt = {__index = Inspector} function Inspector:puts(...) local args = {...} local buffer = self.buffer local len = #buffer for i=1, #args do len = len + 1 buffer[len] = args[i] end end function Inspector:down(f) self.level = self.level + 1 f() self.level = self.level - 1 end function Inspector:tabify() self:puts(self.newline, string.rep(self.indent, self.level)) end function Inspector:alreadyVisited(v) return self.ids[v] ~= nil end function Inspector:getId(v) local id = self.ids[v] if not id then local tv = type(v) id = (self.maxIds[tv] or 0) + 1 self.maxIds[tv] = id self.ids[v] = id end return tostring(id) end function Inspector:putKey(k) if isIdentifier(k) then return self:puts(k) end self:puts("[") self:putValue(k) self:puts("]") end function Inspector:putTable(t) if t == inspect.KEY or t == inspect.METATABLE then self:puts(tostring(t)) elseif self:alreadyVisited(t) then self:puts('') elseif self.level >= self.depth then self:puts('{...}') else if self.tableAppearances[t] > 1 then self:puts('<', self:getId(t), '>') end local nonSequentialKeys, nonSequentialKeysLength, sequenceLength = getNonSequentialKeys(t) local mt = getmetatable(t) self:puts('{') self:down(function() local count = 0 for i=1, sequenceLength do if count > 0 then self:puts(',') end self:puts(' ') self:putValue(t[i]) count = count + 1 end for i=1, nonSequentialKeysLength do local k = nonSequentialKeys[i] if count > 0 then self:puts(',') end self:tabify() self:putKey(k) self:puts(' = ') self:putValue(t[k]) count = count + 1 end if type(mt) == 'table' then if count > 0 then self:puts(',') end self:tabify() self:puts(' = ') self:putValue(mt) end end) if nonSequentialKeysLength > 0 or type(mt) == 'table' then -- result is multi-lined. Justify closing } self:tabify() elseif sequenceLength > 0 then -- array tables have one extra space before closing } self:puts(' ') end self:puts('}') end end function Inspector:putValue(v) local tv = type(v) if tv == 'string' then self:puts(smartQuote(escape(v))) elseif tv == 'number' or tv == 'boolean' or tv == 'nil' or tv == 'cdata' or tv == 'ctype' then self:puts(tostring(v)) elseif tv == 'table' then self:putTable(v) else self:puts('<', tv, ' ', self:getId(v), '>') end end ------------------------------------------------------------------- function inspect.inspect(root, options) options = options or {} local depth = options.depth or math.huge local newline = options.newline or '\n' local indent = options.indent or ' ' local process = options.process if process then root = processRecursive(process, root, {}, {}) end local inspector = setmetatable({ depth = depth, level = 0, buffer = {}, ids = {}, maxIds = {}, newline = newline, indent = indent, tableAppearances = countTableAppearances(root) }, Inspector_mt) inspector:putValue(root) return table.concat(inspector.buffer) end setmetatable(inspect, { __call = function(_, ...) return inspect.inspect(...) end }) return inspect ================================================ FILE: sksevr_plugin/lua-tests/core_spec.lua ================================================ require("MainEntry") describe("FormDB", function() it("should be a top level table", function() assert.truthy(_G["FormDB"]) assert.True(type(_G["FormDB"]) == "table") end) end) describe("Data access", function() describe("Allow setting values by path", function() it("should allow setting differet types transparently", function() -- Set value by simple key -- This should be the same as a simple assignment like t[k]=v assert.are.same( { hello = 1 }, table_set_by_path({}, "hello", 1)) -- We should be able to deal with different types assert.are.same( { hello = 1.5 }, table_set_by_path({}, "hello", 1.5)) -- We should be able to deal with different types assert.are.same( { hello = "skyrim" }, table_set_by_path({}, "hello", "skyrim")) assert.are.same( { hello = true }, table_set_by_path({}, "hello", true)) -- Assign a new table assert.are.same( { hello = { world = 1 }} , table_set_by_path({}, "hello", { world = 1 })) end) it("should make setting deeply nested tables simple", function() assert.are.same( { hello = { world = 1 }}, table_set_by_path({}, "hello/world", 1)) assert.are.same( { hello = { small = { world = 1}} }, table_set_by_path({}, "hello/small", { world = 1 })) assert.are.same( { hello = { small = { world = { things = { should = { be = "easy" }}}}}}, table_set_by_path({}, "hello/small/world/things/should/be", "easy")) end) it("should not disturb unrelated keys in the table", function() assert.are.same( { hello = 1, skyui = {item_is_new = 1}}, table_set_by_path({hello = 1}, "skyui/item_is_new", 1)) end) it("should tolerate consecutive path separators", function() assert.are.same( { hello = 1 }, table_set_by_path({}, "hello//", 1)) assert.are.same( { hello = { world = 1 }}, table_set_by_path({}, "hello//world", 1)) end) it("should ignore leading or trailing path separators", function() assert.are.same( { hello = 1 }, table_set_by_path({}, "hello/", 1)) assert.are.same( { hello = 1 }, table_set_by_path({}, "/hello", 1)) end) it("should report errors if the path is not reachable", function() local result, err = table_set_by_path({hello = 1}, "hello/world", 1) assert.truthy(err) assert.True(result == nil) end) end) describe("Fetching data by path", function() it("should allow fetching values by path", function() assert.are.same( 1, table_get_by_path({hello = 1}, "hello")) assert.are.same( 1, table_get_by_path({hello = {world = 1}}, "hello/world")) end) it("should reply with the default value if data doesn't exist", function() assert.are.same( "not there", table_get_by_path({a = {b = {}}}, "b/c", "not there")) end) it("should reply with an error if the path cannot be reached", function() local result, err = table_get_by_path({a = {b = 1}}, "a/b/c", "not there") assert.are.same("not there", result) assert.truthy(err) end) end) it("should remove empty tables", function() assert.are.same( { some_field = true }, table_set_by_path({hello = {world = {again = 1}}, some_field = true}, "hello/world/again", nil)) end) end) it("FormDB basics", function() FormDB_init() -- Associate some data with a form Form_SetVal(123, "inv/item_new", true) Form_SetVal(123, "inv/hidden", true) -- Fetch the data again assert.True(Form_GetVal(123, "inv/item_new")) -- The FormDB is just a table assert.are.same( {[123] = {inv = {item_new = true, hidden = true }}}, FormDB) -- Fetch the data again assert.True(Form_GetVal(123, "inv/item_new")) -- Fetching data that doesn't exist results in nil assert.is_nil(Form_GetVal(456, "inv/item_new")) -- Fetching data that doesn't exist can return a default value assert.is_equal("default", Form_GetVal(456, "inv/item_new", "default")) Form_RemoveField(123, "inv/item_new") assert.is_equal("nada", Form_GetVal(123, "inv/item_new", "nada")) assert.are.same( {[123] = {inv = {hidden = true}}}, FormDB) -- FormDB is kept compacted as data is removed out of it Form_RemoveField(123, "inv/hidden") assert.are.same( {}, FormDB) -- Removing all data associated with a FormID all at once Form_SetVal(123, "inv/item_new", true) Form_SetVal(123, "inv/hidden", true) Form_RemoveAllFields(123) assert.are.same( {}, FormDB) end) ================================================ FILE: sksevr_plugin/luajit.vcxproj ================================================ Debug Win32 Release Win32 Debug x64 Release x64 16.0 Win32Proj {38230328-1674-4bfd-b185-885b95075068} luajit123 10.0.19041.0 StaticLibrary true v141 Unicode StaticLibrary false v141 true Unicode StaticLibrary true v141 Unicode StaticLibrary false v141 true Unicode true false true $(SolutionDir)Build\$(Configuration)\luajit\ $(SolutionDir)Build\$(Configuration)\Intermediate\$(ProjectName)\ false $(SolutionDir)Build\$(Configuration)\luajit\ $(SolutionDir)Build\$(Configuration)\Intermediate\$(ProjectName)\ Level3 true WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) true Use pch.h true Level3 true true true WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) true Use pch.h true true true Level3 true _DEBUG;_LIB;%(PreprocessorDefinitions) true Use pch.h true cd "$(SolutionDir)luajit\src\" msvcbuild.bat debug static xcopy /y $(ProjectDir)luajit\src\lua51.lib $(SolutionDir)Build\$(Configuration)\$(ProjectName)\ xcopy /y $(ProjectDir)luajit\src\lua*.h $(SolutionDir)Build\$(Configuration)\$(ProjectName)\ xcopy /y $(ProjectDir)luajit\src\lauxlib.h $(SolutionDir)Build\$(Configuration)\$(ProjectName)\ Level3 true true true NDEBUG;_LIB;%(PreprocessorDefinitions) true Use pch.h true true true cd "$(SolutionDir)luajit\src\" msvcbuild.bat debug static xcopy /y $(ProjectDir)luajit\src\lua51.lib $(SolutionDir)Build\$(Configuration)\$(ProjectName)\ xcopy /y $(ProjectDir)luajit\src\lua*.h $(SolutionDir)Build\$(Configuration)\$(ProjectName)\ xcopy /y $(ProjectDir)luajit\src\lauxlib.h $(SolutionDir)Build\$(Configuration)\$(ProjectName)\ ================================================ FILE: sksevr_plugin/plugin/ControllerStateHook.cpp ================================================ /* ControllerStateHook * * Does 2 things: * - Hooks into Controller State update calls made by the engine via SkyrimVRTools * - Pushes controller states to scaleform for processing * * Similar code has already been in SkyrimVRTools for sometime. However, since we have a * more generic way to get controller updates from it now, having scaleform related * functionality here allows more control over the native code without having to worry * about coordinating release. Users will have a more straightforward time installing and * running skyui as well. */ #include "skse64/InternalVR.h" #include "skse64/ScaleformMovie.h" #include "skse64/Hooks_Scaleform.h" #include "skse64/ScaleformCallbacks.h" #include "skse64/GameEvents.h" #include "skse64/GameMenus.h" #include "VRHookAPI.h" #include #include #include namespace ControllerStateHook { namespace vr = vr_1_0_12; void DispatchControllerState(vr::ETrackedControllerRole controllerHand, const vr::VRControllerState_t* controllerState); OpenVRHookManagerAPI* hookMgr = nullptr; // When we receive ControllerState updates, send it over to Scaleform as needed. bool ControllerStateCB(vr::TrackedDeviceIndex_t unControllerDeviceIndex, const vr::VRControllerState_t* pControllerState, uint32_t unControllerStateSize, vr::VRControllerState_t* pOutputControllerState) { vr::IVRSystem* system = hookMgr->GetVRSystem(); assert(system); vr::ETrackedControllerRole hand = vr::TrackedControllerRole_Invalid; if (unControllerDeviceIndex == system->GetTrackedDeviceIndexForControllerRole(vr::ETrackedControllerRole::TrackedControllerRole_LeftHand)) { hand = vr::TrackedControllerRole_LeftHand; } else if (unControllerDeviceIndex == system->GetTrackedDeviceIndexForControllerRole(vr::ETrackedControllerRole::TrackedControllerRole_RightHand)) { hand = vr::TrackedControllerRole_RightHand; } DispatchControllerState(hand, pControllerState); return true; } bool equalGFxValue(const GFxValue& lhs, const GFxValue& rhs) { if (rhs.type == lhs.type) { switch (rhs.GetType()) { case GFxValue::kType_Null: return true; case GFxValue::kType_Bool: return lhs.GetBool() == rhs.GetBool(); case GFxValue::kType_Number: return lhs.GetNumber() == rhs.GetNumber(); case GFxValue::kType_String: return 0 == strcmp(lhs.GetString(), rhs.GetString()); case GFxValue::kType_WideString: return 0 == wcscmp(lhs.GetWideString(), rhs.GetWideString()); case GFxValue::kType_Object: return lhs.data.obj == rhs.data.obj; case GFxValue::kType_Array: // Not implemented =( return false; case GFxValue::kType_DisplayObject: return lhs.data.obj == rhs.data.obj; case GFxValue::kType_Function: return lhs.data.obj == rhs.data.obj; default: return false; } } return false; } struct ScaleformCallback { GFxMovieView* movieView; GFxValue object; const char* methodName; bool operator==(const ScaleformCallback& rhs) { return equalGFxValue(this->object, rhs.object) && (0 == strcmp(this->methodName, rhs.methodName)); } }; typedef std::list ScaleformCallbackList; static ScaleformCallbackList g_scaleformInputHandlers; void DispatchControllerState(vr::ETrackedControllerRole controllerHand, const vr::VRControllerState_t* controllerState) { for (ScaleformCallbackList::iterator iter = g_scaleformInputHandlers.begin(); iter != g_scaleformInputHandlers.end(); ++iter) { GFxMovieView* movieView = (*iter).movieView; GFxValue* object = &(*iter).object; const char* methodName = (*iter).methodName; GFxValue result, args[7]; args[0].SetNumber(controllerHand); args[1].SetNumber(controllerState->unPacketNum); args[2].SetNumber(controllerState->ulButtonPressed & 0xFFFFFFFF); args[3].SetNumber(controllerState->ulButtonPressed >> 32); args[4].SetNumber(controllerState->ulButtonTouched && 0xFFFFFFFF); args[5].SetNumber(controllerState->ulButtonTouched >> 32); GFxValue axisData; movieView->CreateArray(&args[6]); for (int i = 0; i < vr::k_unControllerStateAxisCount; i++) { GFxValue x, y; x.SetNumber(controllerState->rAxis[i].x); y.SetNumber(controllerState->rAxis[i].y); args[6].PushBack(&x); args[6].PushBack(&y); } object->Invoke(methodName, &result, args, 7); } } class VRInputScaleform_RegisterInputHandler : public GFxFunctionHandler { public: virtual void Invoke(Args* args) { //_MESSAGE("RegisterInputHandler dll fn called!"); ASSERT(args->numArgs == 2); ASSERT(args->args[0].GetType() == GFxValue::kType_DisplayObject || args->args[0].GetType() == GFxValue::kType_Object); ASSERT(args->args[1].GetType() == GFxValue::kType_String); ScaleformCallback callback; callback.movieView = args->movie; callback.object = args->args[0]; callback.object.AddManaged(); callback.methodName = args->args[1].GetString(); // If the same callback has already been registered, do not add it again. // This will cause the callback to triggered twice when input events are sent. for (ScaleformCallbackList::iterator iter = g_scaleformInputHandlers.begin(); iter != g_scaleformInputHandlers.end(); ++iter) { if (*iter == callback) { //_MESSAGE("Duplicate callback found, aborting register..."); return; } } //_MESSAGE("Registering: %s", callback.methodName); g_scaleformInputHandlers.push_back(callback); } }; class VRInputScaleform_UnregisterInputHandler : public GFxFunctionHandler { public: virtual void Invoke(Args* args) { //_MESSAGE("VRInputScaleform_UnregisterInputHandler dll fn called!"); ASSERT(args->numArgs == 2); ASSERT(args->args[0].GetType() == GFxValue::kType_DisplayObject || args->args[0].GetType() == GFxValue::kType_Object); ASSERT(args->args[1].GetType() == GFxValue::kType_String); ScaleformCallback callback; callback.object = args->args[0]; callback.methodName = args->args[1].GetString(); g_scaleformInputHandlers.remove(callback); callback.object.CleanManaged(); //_MESSAGE("Unregistering: %s | remaining: %d", callback.methodName, g_scaleformInputHandlers.size()); } }; std::string GetControllerName(vr::COpenVRContext* vrContext, vr::ETrackedControllerRole role, vr::ETrackedPropertyError* err) { char controllerType[vr::k_unMaxSettingsKeyLength]; auto controllerIdx = vrContext->VRSystem()->GetTrackedDeviceIndexForControllerRole(vr::TrackedControllerRole_LeftHand); vrContext->VRSystem()->GetStringTrackedDeviceProperty(controllerIdx, vr::Prop_ControllerType_String, controllerType, vr::k_unMaxSettingsKeyLength, err); if (*err == vr::TrackedProp_Success) { return controllerType; } else return ""; } class VRInputScaleform_ControllerType : public GFxFunctionHandler { public: virtual void Invoke(Args* args) { ASSERT(args->numArgs == 0); auto vrContext = vr::COpenVRContext(); vr::TrackedPropertyError err; auto controllerName = GetControllerName(&vrContext, vr::TrackedControllerRole_LeftHand, &err); if (err != vr::TrackedProp_Success) { controllerName = GetControllerName(&vrContext, vr::TrackedControllerRole_RightHand, &err); } if (err != vr::TrackedProp_Success) { args->result->SetString("unknown"); return; } GFxValue val; args->movie->CreateString(&val, controllerName.c_str()); *args->result = val; } }; bool RegisterScaleformFuncs(GFxMovieView* view, GFxValue* plugin) { //_MESSAGE("Registering scaleform functions"); RegisterFunction(plugin, view, "RegisterInputHandler"); RegisterFunction(plugin, view, "UnregisterInputHandler"); RegisterFunction(plugin, view, "ControllerType"); return true; } std::unordered_set ignoredMenus({ "WSActivateRollover", "WSEnemyMeters", "LoadWaitSpinner", "HUD Menu", "Cursor Menu", "Fader Menu", "Mist Menu", "LoadWaitSpinner", "Loading Menu", "TweenMenu", }); std::unordered_set forceCleanMenus({ "Journal Menu", "InventoryMenu", "MagicMenu", "ContainerMenu", "BarterMenu", "GiftMenu", "Crafting Menu", }); bool contains(std::unordered_set& set, const char* key) { if (set.find(key) == set.end()) return false; else return true; } class CleanControllerHookOnMenuClose : public BSTEventSink { EventResult ReceiveEvent(MenuOpenCloseEvent* evn, EventDispatcher* dispatcher) { if (evn->opening) return kEvent_Continue; //_MESSAGE(">>> CleanControllerHookOnMenuHook"); //if (!contains(ignoredMenus, evn->menuName)) // _MESSAGE("Closing menu: %s", evn->menuName); // In the menus, the game engine seems to still respond to a lot of the events on its own. // There are places where additional menus are opened without skyui's intervention. // There are also places where menus are closed without skyui receiving notifications. // This means we can't properly unregister VRInput::handleVRButtonUpdate(). // Instead, we listen for the menu close event globally here and forcefully kickout // any registration. // // This only works because VRInput is the only code that registers for these button updates. // We really shouldn't be able to unintentionally remove handlers we don't intend to. // // Examples: // ContainerMenu: // Take all: forcefully closes the menu // CraftingMenu: // "Quit alchemy" prompt forcefully closes the menu //_MESSAGE("Menu name is: %s", evn->menuName); if (contains(forceCleanMenus, evn->menuName)) { //_MESSAGE("Actually cleaning up"); // Any GFxValue we might have tried to hang on are probably gone/destroyed now. // We're removing the "managed" flag manually here we don't try to reference them and // clean them up again, which will result in a crash. for (auto it = g_scaleformInputHandlers.begin(); it != g_scaleformInputHandlers.end(); it++) { ScaleformCallback& cb = *it; cb.object.type &= ~GFxValue::kTypeFlag_Managed; } g_scaleformInputHandlers.clear(); } //_MESSAGE("<<< CleanControllerHookOnMenuHook"); return kEvent_Continue; } }; CleanControllerHookOnMenuClose g_menuCloseHandler; void Init() { // Ask for SkyrimVRTools to send us ConstrollerStates whenever they are requested. hookMgr = RequestOpenVRHookManagerObject(); if (!hookMgr) return; hookMgr->RegisterControllerStateCB(ControllerStateCB); // Handle menu close events MenuManager* mm = MenuManager::GetSingleton(); if (mm) { mm->MenuOpenCloseEventDispatcher()->AddEventSink(&g_menuCloseHandler); } else { _MESSAGE("Failed to register menu close handler!"); } } } ================================================ FILE: sksevr_plugin/plugin/ControllerStateHook.h ================================================ #pragma once namespace ControllerStateHook{ void Init(); bool RegisterScaleformFuncs(GFxMovieView * view, GFxValue * plugin); } ================================================ FILE: sksevr_plugin/plugin/FormDB.cpp ================================================ #include #include #include "FormDB.h" #include "skse64/GameForms.h" #include "skse64/ScaleformValue.h" #include "skse64/ScaleformCallbacks.h" #include "skse64/ScaleformAPI.h" #include "skse64/Hooks_Scaleform.h" #include "skse64/ScaleformMovie.h" #include "skse64/GameExtraData.h" #include "skse64/ScaleformExtendedData.h" #include "skse64/GameRTTI.h" #include "Keyboard.h" lua_State* g_lua = nullptr; namespace FormDB { void Form_SetInt(UInt32 formID, const char* fieldName, SInt32 val) { const char* func_name = "Form_SetVal"; lua_getglobal(g_lua, func_name); // Grab the lua function lua_pushinteger(g_lua, formID); // Push the params lua_pushstring(g_lua, fieldName); lua_pushinteger(g_lua, val); // Call and print any errors if (lua_pcall(g_lua, 3, 1, 0) != 0) _ERROR("Error running `%s`: %s", func_name, lua_tostring(g_lua, -1)); // Pop the return value // The lua function actually returns the updated table. // Since there isn't a great way to interact with it in C/C++, // we're just going to discard it. lua_pop(g_lua, 1); } void Form_SetInt(TESForm* form, BSFixedString fieldName, SInt32 val) { if (form == nullptr) { // _MESSAGE("Form_SetInt: form is null"); return; } // _MESSAGE("Form_SetInt: 0x%x, %s, %d", form->formID, fieldName.c_str(), val); Form_SetInt(form->formID, fieldName.c_str(), val); } void Papyrus_Form_SetInt(StaticFunctionTag*, TESForm* form, BSFixedString fieldName, SInt32 val) { if (form == nullptr) { // _MESSAGE("Papyrus_Form_SetInt: form is null"); return; } // _MESSAGE("Papyrus_Form_SetInt: 0x%x, %s, %d", form->formID, fieldName.c_str(), val); Form_SetInt(form->formID, fieldName.c_str(), val); } SInt32 Form_GetInt(UInt32 formID, const char* fieldName, SInt32 default) { const char* func_name = "Form_GetVal"; lua_getglobal(g_lua, func_name); // Grab the lua function lua_pushinteger(g_lua, formID); // Push the params lua_pushstring(g_lua, fieldName); lua_pushinteger(g_lua, default); // Call and print any errors if (lua_pcall(g_lua, 3, 1, 0) != 0) _ERROR("Error running `%s`: %s", func_name, lua_tostring(g_lua, -1)); if (!lua_isnumber(g_lua, -1)) _ERROR("function `%s` did not return a number", func_name); // Get the fetch result SInt32 val = lua_tointeger(g_lua, -1); lua_pop(g_lua, 1); // Cleanup the result from the stack return val; } SInt32 Form_GetInt(TESForm* form, BSFixedString fieldName, SInt32 default) { if (form == nullptr) { // _MESSAGE("Form_GetInt: form is null"); return default; } // _MESSAGE("Form_GetInt: 0x%x, %s", form->formID, fieldName); auto val = Form_GetInt(form->formID, fieldName.c_str(), default); // _MESSAGE("Form_GetInt result: %d", val); return val; } SInt32 Papyrus_Form_GetInt(StaticFunctionTag*, TESForm* form, BSFixedString fieldName, SInt32 default) { if (form == nullptr) { // _MESSAGE("Papyrus_Form_GetInt: form is null"); return default; } // _MESSAGE("Papyrus_Form_GetInt: 0x%x, %s", form->formID, fieldName); auto val = Form_GetInt(form->formID, fieldName.c_str(), default); // _MESSAGE("Papyrus_Form_GetInt result: %d", val); return val; } const char* boolToStr(bool val) { if (val) return "true"; else return "false"; } void Form_SetBool(UInt32 formID, const char* fieldName, bool val) { const char* func_name = "Form_SetVal"; lua_getglobal(g_lua, func_name); // Grab the lua function lua_pushinteger(g_lua, formID); // Push the params lua_pushstring(g_lua, fieldName); lua_pushboolean(g_lua, val); if (lua_pcall(g_lua, 3, 1, 0) != 0) _ERROR("Error running `%s`: %s", func_name, lua_tostring(g_lua, -1)); lua_pop(g_lua, 1); } void Form_SetBool(TESForm* form, BSFixedString fieldName, bool val) { if (form == nullptr) { // _MESSAGE("Form_SetBool: form is null"); return; } // _MESSAGE("Form_SetBool: 0x%x, %s, %s", form->formID, fieldName.c_str(), boolToStr(val)); Form_SetBool(form->formID, fieldName.c_str(), val); } void Papyrus_Form_SetBool(StaticFunctionTag*, TESForm* form, BSFixedString fieldName, bool val) { if (form == nullptr) { // _MESSAGE("Form_SetBool: form is null"); return; } // _MESSAGE("Papyrus_Form_SetBool: 0x%x, %s, %s", form->formID, fieldName.c_str(), boolToStr(val)); Form_SetBool(form->formID, fieldName.c_str(), val); } bool Form_GetBool(UInt32 formID, const char* fieldName, bool default) { const char* func_name = "Form_GetVal"; lua_getglobal(g_lua, func_name); // Grab the lua function lua_pushinteger(g_lua, formID); // Push the params lua_pushstring(g_lua, fieldName); lua_pushboolean(g_lua, default); // Call and print any errors if (lua_pcall(g_lua, 3, 1, 0) != 0) _ERROR("Error running `%s`: %s", func_name, lua_tostring(g_lua, -1)); if (!lua_isboolean(g_lua, -1)) _ERROR("function `%s` did not return a boolean", func_name); // Get the fetch result bool val = lua_toboolean(g_lua, -1); lua_pop(g_lua, 1); // Cleanup the result from the stack return val; } bool Form_GetBool(TESForm* form, BSFixedString fieldName, bool default) { if (form == nullptr) { // _MESSAGE("Form_GetBool: form is null"); return default; } // _MESSAGE("Form_GetBool: 0x%x, %s", form->formID, fieldName); bool val = Form_GetBool(form->formID, fieldName.c_str(), default); // _MESSAGE("Form_GetBool result: %s", boolToStr(val)); return val; } bool Papyrus_Form_GetBool(StaticFunctionTag*, TESForm* form, BSFixedString fieldName, bool default) { if (form == nullptr) { // _MESSAGE("Papyrus_Form_GetBool: form is null"); return default; } // _MESSAGE("Papyrus_Form_GetBool: 0x%x, %s", form->formID, fieldName); auto val = Form_GetBool(form->formID, fieldName.c_str(), default); // _MESSAGE("Papyrus_Form_GetBool result: %s", boolToStr(val)); return val; } void Form_RemoveField(UInt32 formID, const char* fieldName) { const char* func_name = "Form_RemoveField"; lua_getglobal(g_lua, func_name); // Grab the lua function lua_pushinteger(g_lua, formID); // Push the params lua_pushstring(g_lua, fieldName); // Call and print any errors if (lua_pcall(g_lua, 2, 0, 0) != 0) _ERROR("Error running `%s`: %s", func_name, lua_tostring(g_lua, -1)); } void Form_RemoveField(TESForm* form, BSFixedString fieldName) { if (form == nullptr) { // _MESSAGE("Form_RemoveField: form is null"); return; } // _MESSAGE("Form_RemoveField: 0x%x, %s", form->formID, fieldName); Form_RemoveField(form->formID, fieldName.c_str()); } void Papyrus_Form_RemoveField(StaticFunctionTag*, TESForm* form, BSFixedString fieldName) { if (form == nullptr) { // _MESSAGE("Papyrus_Form_RemoveField: form is null"); return; } // _MESSAGE("Papyrus_Form_RemoveField: 0x%x, %s", form->formID, fieldName); Form_RemoveField(form->formID, fieldName.c_str()); } void Form_RemoveAllFields(UInt32 formID) { const char* func_name = "Form_RemoveAllFields"; lua_getglobal(g_lua, func_name); lua_pushinteger(g_lua, formID); // Call and print any errors if (lua_pcall(g_lua, 1, 0, 0) != 0) _ERROR("Error running `%s`: %s", func_name, lua_tostring(g_lua, -1)); } void Form_RemoveAllFields(TESForm* form) { if (form == nullptr) { // _MESSAGE("Form_RemoveAllFields: form is null"); return; } // _MESSAGE("Form_RemoveAllFields: 0x%x, %s", form->formID); Form_RemoveAllFields(form->formID); } void Papyrus_Form_RemoveAllFields(StaticFunctionTag*, TESForm* form) { if (form == nullptr) { // _MESSAGE("Papyrus_Form_RemoveAllFields: form is null"); return; } // _MESSAGE("Papyrus_Form_RemoveAllFields: 0x%x, %s", form->formID); Form_RemoveAllFields(form->formID); } bool RegisterPapyrusFuncs(VMClassRegistry* registry) { _MESSAGE("Registering Papyrus Functions"); registry->RegisterFunction(new NativeFunction3 ("SetInt", "SKI_PlayerInventoryHook", Papyrus_Form_SetInt, registry)); registry->RegisterFunction(new NativeFunction3 ("GetInt", "SKI_PlayerInventoryHook", Papyrus_Form_GetInt, registry)); registry->RegisterFunction(new NativeFunction3 ("SetBool", "SKI_PlayerInventoryHook", Papyrus_Form_SetBool, registry)); registry->RegisterFunction(new NativeFunction3 ("GetBool", "SKI_PlayerInventoryHook", Papyrus_Form_GetBool, registry)); registry->RegisterFunction(new NativeFunction2 ("RemoveField", "SKI_PlayerInventoryHook", Papyrus_Form_RemoveField, registry)); registry->RegisterFunction(new NativeFunction1 ("RemoveAllFields", "SKI_PlayerInventoryHook", Papyrus_Form_RemoveAllFields, registry)); return true; } bool InitGlobalLuaVM() { if (g_lua) return false; // Setup new lua instance g_lua = lua::lua_new_skyui_state(); if (g_lua) return true; else return false; } class Scaleform_RemoveField : public GFxFunctionHandler { public: virtual void Invoke(Args* args) { //_MESSAGE("In Scaleform_RemoveField"); ASSERT(args->numArgs == 2); ASSERT(args->args[0].GetType() == GFxValue::kType_Number); ASSERT(args->args[1].GetType() == GFxValue::kType_String); //_MESSAGE("Scaleform -> Dll: RemoveField, %d, %s", UInt32(args->args[0].GetNumber()), args->args[1].GetString()); Form_RemoveField(UInt32(args->args[0].GetNumber()), args->args[1].GetString()); } }; bool RegisterScaleformFuncs(GFxMovieView* view, GFxValue* plugin) { RegisterFunction(plugin, view, "FormDB_RemoveField"); Keyboard::RegisterScaleformFuncs(view, plugin); return true; } void InventoryMarkNew(GFxMovieView* view, GFxValue* object, InventoryEntryData* item) { bool new_item = Form_GetBool(item->type->formID, "skyui/newItem", false); // Skip marking gold as new if (item->type->formID == 0x0000000f) return; if (new_item) { //_MESSAGE("Marking [%x] with 'newItem'", item->type->formID); RegisterBool(object, "newItem", new_item); } } void RegisterScaleformInventoryHooks(SKSEScaleformInterface* infc) { infc->RegisterForInventory(InventoryMarkNew); } } ================================================ FILE: sksevr_plugin/plugin/FormDB.h ================================================ #include "skse64/PapyrusNativeFunctions.h" #include "skse64/PluginAPI.h" #include "lua_glue.h" extern lua_State* g_lua; namespace FormDB { void Form_SetInt(TESForm* form, BSFixedString fieldName, SInt32 val); SInt32 Form_GetInt(TESForm* form, BSFixedString fieldName, SInt32 default); void Form_RemoveField(TESForm* form, BSFixedString fieldName); void Form_RemoveAllFields(TESForm* form, BSFixedString fieldName); bool RegisterPapyrusFuncs(VMClassRegistry* registry); bool InitGlobalLuaVM(); bool RegisterScaleformFuncs(GFxMovieView* view, GFxValue* plugin); void RegisterScaleformInventoryHooks(SKSEScaleformInterface* infc); } ================================================ FILE: sksevr_plugin/plugin/Globals.h ================================================ #pragma once #include "skse64/PluginAPI.h" extern PluginHandle g_pluginHandle; extern SKSEPapyrusInterface* g_papyrus; extern SKSEScaleformInterface* g_scaleform; extern SKSETaskInterface* g_SkseTaskInterface; extern SKSEObjectInterface* g_SkseObjectInterface; ================================================ FILE: sksevr_plugin/plugin/Keyboard.cpp ================================================ #include "skse64/PluginAPI.h" #include "skse64/ScaleformValue.h" #include "skse64/ScaleformMovie.h" #include "skse64/ScaleformCallbacks.h" #include "skse64/ScaleformAPI.h" #include "skse64/Hooks_UI.h" #include "common/ICriticalSection.h" #include "skse64/InternalVR.h" #include "skse64/GameVR.h" #include "skse64/Hooks_Threads.h" #include "skse64/InternalVR.h" #include #include #include #include #include namespace Keyboard { namespace vr = vr_1_0_12; auto vrContext = vr::COpenVRContext(); vr::VROverlayHandle_t keyboardOverlayHandle = 0; std::thread* keyboardHandlerThread = nullptr; void WaitForKeyboardInput(GFxValue desc, GFxValue currentText, GFxValue thisValue, GFxValue func) { desc.AddManaged(); currentText.AddManaged(); thisValue.AddManaged(); func.AddManaged(); // In the case where the user is clicking on the search box directly, // wait a short while before activating the keyboard. // If we don't do this, the keyboard might become active before the trigger can be released. // Steamvr may immediately dismiss the keyboard if the keyboard becomes active, because the // controller is pointing away from the keyboard and the trigger is still depressed. // This gives the user a bit of time to release the trigger. // This isn't perfect. A better solution may be to wait for both controller's trigger to become // fully released first. Sleep(100); const int charMax = 255; // Bring up the keyboard vr::EVROverlayError err; err = vrContext.VROverlay()->ShowKeyboardForOverlay(keyboardOverlayHandle, vr::k_EGamepadTextInputModeNormal, vr::k_EGamepadTextInputLineModeSingleLine, desc.GetString(), charMax, currentText.GetString(), false, 0); if (err != vr::EVROverlayError::VROverlayError_None) return; //int i = 0; vr::VREvent_t eventData; while (true) { // Consume all overlay events if (vrContext.VROverlay()->PollNextOverlayEvent(keyboardOverlayHandle, &eventData, sizeof(vr::VREvent_t))) { //_MESSAGE("Keyboard got event %i: %d", i++, eventData.eventType); // Look for event where the keyboard is dismissed if (eventData.eventType == vr::VREvent_KeyboardClosed || eventData.eventType == vr::VREvent_KeyboardDone) { // Grab the entered text in its entirety. char buffer[charMax+1] = "\0"; vrContext.VROverlay()->GetKeyboardText(buffer, charMax); //_MESSAGE("Keyboard got string: %s", buffer); // Invoke the callback to send the result back to the Scaleform UI. GFxValue vals[3]; vals[0] = thisValue; auto objectInterface = func.objectInterface; if (objectInterface) { auto movieRoot = objectInterface->root; if (movieRoot) { movieRoot->CreateString(&vals[1], buffer); } } vals[2].SetNumber(0); func.Invoke("call", nullptr, vals, 3); break; } } Sleep(50); } keyboardHandlerThread->detach(); delete keyboardHandlerThread; keyboardHandlerThread = nullptr; vrContext.VROverlay()->DestroyOverlay(keyboardOverlayHandle); keyboardOverlayHandle = 0; desc.CleanManaged(); currentText.CleanManaged(); thisValue.CleanManaged(); func.CleanManaged(); } class Scaleform_ShowVirtualKeyboard : public GFxFunctionHandler { public: virtual void Invoke(Args* args) { ASSERT(args->numArgs >= 6); ASSERT(args->args[0].GetType() == GFxValue::kType_String); // Key ASSERT(args->args[1].GetType() == GFxValue::kType_String); // Title ASSERT(args->args[2].GetType() == GFxValue::kType_String); // Desc ASSERT(args->args[3].GetType() == GFxValue::kType_String); // Text ASSERT(args->args[4].GetType() == GFxValue::kType_Object || args->args[4].GetType() == GFxValue::kType_DisplayObject); // This ASSERT(args->args[5].GetType() == GFxValue::kType_Object); // Function // Lazily initialize the keyboard overlay vr::EVROverlayError err; assert(keyboardOverlayHandle == 0); err = vrContext.VROverlay()->CreateOverlay(args->args[0].GetString(), args->args[1].GetString(), &keyboardOverlayHandle); if (err != vr::EVROverlayError::VROverlayError_None) return; // Start a thread to wait for keyboard input. assert(keyboardHandlerThread == nullptr); keyboardHandlerThread = new std::thread(WaitForKeyboardInput, args->args[2], args->args[3], args->args[4], args->args[5]); // Tell the caller things have been initiated. args->result->SetBool(true); } }; bool RegisterScaleformFuncs(GFxMovieView* view, GFxValue* plugin) { RegisterFunction(plugin, view, "ShowVirtualKeyboard"); return true; } void RegisterScaleformHooks(SKSEScaleformInterface* infc) { _MESSAGE("Registering keyboard scaleform funcs"); infc->Register("skyui", [](GFxMovieView* view, GFxValue* plugin){ RegisterFunction(plugin, view, "ShowVirtualKeyboard"); return true; }); } } ================================================ FILE: sksevr_plugin/plugin/Keyboard.h ================================================ #pragma once #include "skse64/PluginAPI.h" namespace Keyboard { void Init(); bool RegisterScaleformFuncs(GFxMovieView* view, GFxValue* plugin); void RegisterScaleformHooks(SKSEScaleformInterface* infc); } ================================================ FILE: sksevr_plugin/plugin/PapyrusUIFix.cpp ================================================ #include "PapyrusUIFix.h" #include "skse64/GameMenus.h" #include "skse64/ScaleformCallbacks.h" #include "skse64/ScaleformMovie.h" #include "skse64/PapyrusNativeFunctions.h" #include "skse64/PapyrusUI.h" #include "skse64/Hooks_UI.h" #include "skse64/Serialization.h" #include "Globals.h" namespace PapyrusUIFix { template void SetGFxValue(GFxValue* val, T arg); template <> void SetGFxValue(GFxValue* val, bool arg) { val->SetBool(arg); } template <> void SetGFxValue(GFxValue* val, float arg) { val->SetNumber(arg); } // Disabled so we don't accidentally use this //template <> void SetGFxValue(GFxValue* val, UInt32 arg) { val->SetNumber(arg); } template <> void SetGFxValue(GFxValue* val, SInt32 arg) { val->SetNumber(arg); } template <> void SetGFxValue(GFxValue* val, BSFixedString arg) { // lifetime of this string will not be managed by the scaleform runtime val->SetString(arg.data); } class UIInvokeDelegate : public UIDelegate_v1, public ISKSEObject { public: UIInvokeDelegate(const char* nameBuf, const char* targetBuf) : menuName_(nameBuf), target_(targetBuf) {} explicit UIInvokeDelegate(SerializationTag tag) { } virtual const char* ClassName() const { return "SkyUI-UIInvokeDelegate"; } virtual UInt32 ClassVersion() const { return 1; } virtual void Run() override { MenuManager* mm = MenuManager::GetSingleton(); if (!mm) return; BSFixedString t(menuName_.c_str()); GFxMovieView* view = mm->GetMovieView(&t); if (!view) return; GFxValue* value = NULL; if (args.size() > 0) value = &args[0]; view->Invoke(target_.c_str(), NULL, value, args.size()); } virtual void Dispose() override { delete this; } virtual bool Save(SKSESerializationInterface* intfc) { using namespace Serialization; if (!WriteData(intfc, &menuName_)) return false; if (!WriteData(intfc, &target_)) return false; if (!WriteData(intfc, &type_)) return false; if (!WriteData(intfc, &handle_)) return false; return true; } virtual bool Load(SKSESerializationInterface* intfc, UInt32 version) { using namespace Serialization; if (!ReadData(intfc, &menuName_)) return false; if (!ReadData(intfc, &target_)) return false; if (!ReadData(intfc, &type_)) return false; if (!ReadData(intfc, &handle_)) return false; UInt64 fixedHandle; if (intfc->ResolveHandle(handle_, &fixedHandle)) handle_ = fixedHandle; return true; } std::vector args; private: std::string menuName_; std::string target_; UInt32 type_; UInt64 handle_; }; template void SetT(StaticFunctionTag* thisInput, BSFixedString menuName, BSFixedString targetStr, T value) { if (!menuName.data || !targetStr.data) return; MenuManager* mm = MenuManager::GetSingleton(); if (!mm) return; GFxMovieView* view = mm->GetMovieView(&menuName); if (!view) return; GFxValue fxValue; PapyrusUIFix::SetGFxValue(&fxValue, value); view->SetVariable(targetStr.data, &fxValue, 1); } template void InvokeArgT(StaticFunctionTag* thisInput, BSFixedString menuName, BSFixedString targetStr, T arg) { if (!menuName.data || !targetStr.data) return; if (!g_SkseTaskInterface) return; UIInvokeDelegate* cmd = new UIInvokeDelegate(menuName.data, targetStr.data); cmd->args.resize(1); PapyrusUIFix::SetGFxValue(&cmd->args[0], arg); g_SkseTaskInterface->AddUITask(cmd); } template void InvokeArrayT(StaticFunctionTag* thisInput, BSFixedString menuName, BSFixedString targetStr, VMArray args) { if (!menuName.data || !targetStr.data) return; if (!g_SkseTaskInterface) return; UInt32 argCount = args.Length(); UIInvokeDelegate* cmd = new UIInvokeDelegate(menuName.data, targetStr.data); cmd->args.resize(argCount); for (UInt32 i = 0; i < argCount; i++) { T arg; args.Get(&arg, i); PapyrusUIFix::SetGFxValue(&cmd->args[i], arg); } g_SkseTaskInterface->AddUITask(cmd); } bool RegisterPapyrusFuncs(VMClassRegistry* registry) { SKSEObjectRegistry& objectRegistry = g_SkseObjectInterface->GetObjectRegistry(); objectRegistry.RegisterClass(); registry->RegisterFunction( new NativeFunction3 ("SetInt", "UI", SetT, registry)); registry->RegisterFunction( new NativeFunction3 ("InvokeInt", "UI", InvokeArgT, registry)); registry->RegisterFunction( new NativeFunction3 >("InvokeIntA", "UI", InvokeArrayT, registry)); return true; } } ================================================ FILE: sksevr_plugin/plugin/PapyrusUIFix.h ================================================ #pragma once #include "skse64/PapyrusObjects.h" namespace PapyrusUIFix { bool RegisterPapyrusFuncs(VMClassRegistry* registry); } ================================================ FILE: sksevr_plugin/plugin/ScaleformExtendedDataFix.cpp ================================================ #include "ScaleformExtendedDataFix.h" #include "skse64/ScaleformValue.h" #include "skse64/ScaleformExtendedData.h" #include "skse64/GameRTTI.h" #include "skse64/GameExtraData.h" namespace ExtendDataFix { // As of SKSEVR 2.0.12, the layout of TESAmmo is slightly off, causing the "flags" field to be // read & passed to skyui incorrectly. // The end result is skyui seems to always categorize bolts and arrow as "type: bolt". void AttachAmmoFlags(GFxMovieView* view, GFxValue* pFxVal, InventoryEntryData* item) { TESForm* pForm = item->type; if (!pForm || !pFxVal || !pFxVal->IsObject()) return; switch (pForm->GetFormType()) { case kFormType_Ammo: { TESAmmo* pAmmo = DYNAMIC_CAST(pForm, TESForm, TESAmmo); if (pAmmo) { RegisterNumber(pFxVal, "flags", pAmmo->settings.flags); } } break; default: break; } } void RegisterScaleformInventoryHooks(SKSEScaleformInterface* infc) { infc->RegisterForInventory(AttachAmmoFlags); } } ================================================ FILE: sksevr_plugin/plugin/ScaleformExtendedDataFix.h ================================================ #pragma once #include "skse64/PluginAPI.h" namespace ExtendDataFix{ void RegisterScaleformInventoryHooks(SKSEScaleformInterface* infc); } ================================================ FILE: sksevr_plugin/plugin/Settings.cpp ================================================ #include #include #include #include #include #include #include #include #include "skse64/ScaleformValue.h" #include "skse64/ScaleformMovie.h" #include "skse64/ScaleformCallbacks.h" #include "skse64_common/Utilities.h" #include "lua_glue.h" #include "FormDB.h" namespace Settings { bool GetBool(lua_State* L, const char* path, bool default) { return lua::lua_table_get_bool_by_path(L, LUA_GLOBALSINDEX, path, default); } double GetDouble(lua_State* L, const char* path, double default) { return lua::lua_table_get_double_by_path(L, LUA_GLOBALSINDEX, path, default); } std::string GetString(lua_State* L, const char* path, std::string default) { return lua::lua_table_get_string_by_path(L, LUA_GLOBALSINDEX, path, default); } bool load_settings_file(lua_State* L, const char* path) { const char* func_name = "load_settings_file"; lua_getglobal(L, func_name); // Grab the lua function lua_pushstring(L, path); // Call and print any errors if (lua_pcall(L, 1, 1, 0) != 0) { _ERROR("Error running `%s`: %s", func_name, lua_tostring(g_lua, -1)); return false; } return true; } bool loadLuaConfig(const char* settingFilePath = nullptr) { std::string path; // Figure out which file we're trying to open. if (settingFilePath) { path = settingFilePath; } else { path = GetRuntimeDirectory() + "Data\\SKSE\\Plugins\\SkyUI-VR.settings.lua"; } int top = lua_gettop(g_lua); bool ok = load_settings_file(g_lua, path.c_str()); if (!ok) return false; lua_getfield(g_lua, -1, "Settings"); lua_setglobal(g_lua, "Settings"); lua::lua_pop_to_level(g_lua, top); return true; } bool deepCopyValue(lua_State* L, int index, GFxMovieView* movie, GFxValue* val); bool deepCopyTable(lua_State* L, int index, GFxMovieView* movie, GFxValue* object) { int top = lua_gettop(L); // stack now contains: -1 => table bool isArray = lua::lua_table_is_array(L, index); if (isArray) { movie->CreateArray(object); lua_pushnil(L); // stack now contains: -1 => nil; -2 => table for(int i = 0; lua_next(L, -2); i++) { // stack now contains: -1 => value; -2 => key; -3 => table GFxValue val; //lua::lua_print_value(L, -1); //printf("\n"); // Copy the lua value from the top of the stack into a Scaleform Value deepCopyValue(L, -1, movie, &val); // Add the Scaleform value to the Scaleform array object->PushBack(&val); // pop value, leaving the key lua_pop(L, 1); // stack now contains: -1 => key; -2 => table } } else { movie->CreateObject(object); lua_pushnil(L); // stack now contains: -1 => nil; -2 => table while (lua_next(L, -2)) { // stack now contains: -1 => value; -2 => key; -3 => table const char* key = lua_tostring(L, -2); const char* value = lua_tostring(L, -1); //lua::lua_print_value(L, -2); //printf(" => "); //lua::lua_print_value(L, -1); //printf("\n"); GFxValue val; deepCopyValue(L, -1, movie, &val); object->SetMember(key, &val); // pop value, leaving the key lua_pop(L, 1); // stack now contains: -1 => key; -2 => table } } // stack now contains: -1 => table // (when lua_next returns 0 it pops the key but does not push anything.) // Restore stack to the same state as when we entered the function lua::lua_pop_to_level(L, top); return true; } bool deepCopyValue(lua_State* L, int index, GFxMovieView* movie, GFxValue* val) { switch (lua_type(L, index)) { case LUA_TNONE: val->SetUndefined(); break; case LUA_TNIL: val->SetNull(); break; case LUA_TBOOLEAN: val->SetBool(lua_toboolean(L, index)); break; case LUA_TNUMBER: val->SetBool(lua_tonumber(L, index)); break; case LUA_TSTRING: val->SetString(lua_tostring(L, index)); break; case LUA_TTABLE: deepCopyTable(L, index, movie, val); break; case LUA_TLIGHTUSERDATA: printf("Cannot copy light user data"); break; case LUA_TFUNCTION: printf("Cannot copy function"); break; case LUA_TUSERDATA: printf("Cannot copy userdata"); break; case LUA_TTHREAD: printf("Cannot copy thread"); break; } return true; } class Scaleform_IniGet : public GFxFunctionHandler { public: virtual void Invoke(Args* args) { ASSERT(args->numArgs >= 1); ASSERT(args->args[0].GetType() == GFxValue::kType_String); // Key ASSERT(g_lua); int top = lua_gettop(g_lua); bool ok = lua::lua_table_get_by_path(g_lua, LUA_GLOBALSINDEX, args->args[0].GetString()); if (ok) deepCopyValue(g_lua, -1, args->movie, args->result); else args->result->SetNull(); lua::lua_pop_to_level(g_lua, top); } }; // Used by actionscript code to request VR action bindings. // Here, we're using both the globally loaded settings and another // one to provide defaults if the specified path/value cannot be located. class Scaleform_IniGetWithDefaults : public GFxFunctionHandler { public: virtual void Invoke(Args* args) { ASSERT(args->numArgs >= 1); ASSERT(args->args[0].GetType() == GFxValue::kType_String); // Path ASSERT(args->args[1].GetType() == GFxValue::kType_String); // Defaults filename ASSERT(g_lua); const char* givenFilename = args->args[1].GetString(); std::string defaultsFilename; if (std::filesystem::exists(givenFilename)) { defaultsFilename = givenFilename; } else { std::string candidate = GetRuntimeDirectory() + "Data\\SKSE\\Plugins\\SkyUI-VR\\" + givenFilename + ".lua"; if (std::filesystem::exists(candidate.c_str())) defaultsFilename = candidate; } int top = lua_gettop(g_lua); bool ok; if (defaultsFilename.length() != 0) { ok = lua::lua_settings_get_by_path_with_defaults(g_lua, LUA_GLOBALSINDEX, args->args[0].GetString(), defaultsFilename.c_str()); } else { _ERROR("Unable to locate defaults settings file: %s", givenFilename); ok = lua::lua_table_get_by_path(g_lua, LUA_GLOBALSINDEX, args->args[0].GetString()); } if (ok) deepCopyValue(g_lua, -1, args->movie, args->result); else args->result->SetNull(); lua::lua_pop_to_level(g_lua, top); } }; class Scaleform_IniGetBool : public GFxFunctionHandler { public: virtual void Invoke(Args* args) { ASSERT(args->numArgs >= 1); ASSERT(args->args[0].GetType() == GFxValue::kType_String); // Key ASSERT(g_lua); int top = lua_gettop(g_lua); bool ok = lua::lua_table_get_by_path(g_lua, LUA_GLOBALSINDEX, args->args[0].GetString()); if (ok && lua_isboolean(g_lua, -1)) deepCopyValue(g_lua, -1, args->movie, args->result); else args->result->SetUndefined(); lua::lua_pop_to_level(g_lua, top); } }; class Scaleform_IniGetNumber : public GFxFunctionHandler { public: virtual void Invoke(Args* args) { ASSERT(args->numArgs >= 1); ASSERT(args->args[0].GetType() == GFxValue::kType_String); // Key ASSERT(g_lua); int top = lua_gettop(g_lua); bool ok = lua::lua_table_get_by_path(g_lua, LUA_GLOBALSINDEX, args->args[0].GetString()); if (ok && lua_isnumber(g_lua, -1)) deepCopyValue(g_lua, -1, args->movie, args->result); else args->result->SetUndefined(); lua::lua_pop_to_level(g_lua, top); } }; class Scaleform_IniGetString : public GFxFunctionHandler { public: virtual void Invoke(Args* args) { ASSERT(args->numArgs >= 1); ASSERT(args->args[0].GetType() == GFxValue::kType_String); // Key ASSERT(g_lua); int top = lua_gettop(g_lua); bool ok = lua::lua_table_get_by_path(g_lua, LUA_GLOBALSINDEX, args->args[0].GetString()); if (ok && lua_isstring(g_lua, -1)) deepCopyValue(g_lua, -1, args->movie, args->result); else args->result->SetUndefined(); lua::lua_pop_to_level(g_lua, top); } }; bool RegisterScaleformFuncs(GFxMovieView* view, GFxValue* plugin) { RegisterFunction(plugin, view, "IniGet"); RegisterFunction(plugin, view, "IniGetWithDefaults"); RegisterFunction(plugin, view, "IniGetBool"); RegisterFunction(plugin, view, "IniGetNumber"); RegisterFunction(plugin, view, "IniGetString"); return true; } } ================================================ FILE: sksevr_plugin/plugin/Settings.h ================================================ #pragma once #include "skse64/PluginAPI.h" namespace Settings { bool loadLuaConfig(const char* settingFilePath = nullptr); bool RegisterScaleformFuncs(GFxMovieView* view, GFxValue* plugin); bool GetBool (lua_State* L, const char* path, bool default); double GetDouble(lua_State* L, const char* path, double default); std::string GetString(lua_State* L, const char* path, std::string default); } ================================================ FILE: sksevr_plugin/plugin/VRHookAPI.h ================================================ /* VRHookAPI.h * * Part of SkyrimVRTools. * Provides ability to register callbacks to get Controller States whenever the game engine asks for an update. */ #pragma once #include #include "common/IDebugLog.h" #include "skse64/InternalVR.h" namespace vr = vr_1_0_12; // VR input callbacks // last argument is ptr to VRControllerState that the mod authors can modify and use to block inputs typedef bool (*GetControllerState_CB)(vr::TrackedDeviceIndex_t unControllerDeviceIndex, const vr::VRControllerState_t *pControllerState, uint32_t unControllerStateSize, vr::VRControllerState_t* pOutputControllerState); typedef vr::EVRCompositorError (*WaitGetPoses_CB)(VR_ARRAY_COUNT(unRenderPoseArrayCount) vr::TrackedDevicePose_t* pRenderPoseArray, uint32_t unRenderPoseArrayCount, VR_ARRAY_COUNT(unGamePoseArrayCount) vr::TrackedDevicePose_t* pGamePoseArray, uint32_t unGamePoseArrayCount); class OpenVRHookManagerAPI { public: virtual bool IsInitialized() = 0; virtual void RegisterControllerStateCB(GetControllerState_CB cbfunc) = 0; virtual void RegisterGetPosesCB(WaitGetPoses_CB cbfunc) = 0; virtual void UnregisterControllerStateCB(GetControllerState_CB cbfunc) = 0; virtual void UnregisterGetPosesCB(WaitGetPoses_CB cbfunc) = 0; virtual vr::IVRSystem* GetVRSystem() const = 0; virtual vr::IVRCompositor* GetVRCompositor() const = 0; }; // Request OpenVRHookManagerAPI object from dll if it is available, otherwise return null. Use to initialize raw OpenVR hooking inline OpenVRHookManagerAPI* RequestOpenVRHookManagerObject() { typedef OpenVRHookManagerAPI* (*GetVRHookMgrFuncPtr_t)(); HMODULE skyrimVRToolsModule = LoadLibraryA("skyrimvrtools.dll"); if (skyrimVRToolsModule != nullptr) { GetVRHookMgrFuncPtr_t vrHookGetFunc = (GetVRHookMgrFuncPtr_t)GetProcAddress(skyrimVRToolsModule, "GetVRHookManager"); if (vrHookGetFunc) { return vrHookGetFunc(); } else { _MESSAGE("Failed to get address of function GetVRHookmanager from skyrimvrtools.dll in RequestOpenVRHookManagerObject(). Is your skyrimvrtools.dll out of date?"); } } else { _MESSAGE("Failed to load skyrimvrtools.dll in RequestOpenVRHookManagerObject()"); } return nullptr; } ================================================ FILE: sksevr_plugin/plugin/exports.def ================================================ LIBRARY "SkyUI-VR" EXPORTS SKSEPlugin_Query SKSEPlugin_Load ================================================ FILE: sksevr_plugin/plugin/guicon.cpp ================================================ #include #include #include #include #include #include // maximum mumber of lines the output console should have static const WORD MAX_CONSOLE_LINES = 500; bool RedirectIOToConsole() { CONSOLE_SCREEN_BUFFER_INFO coninfo; // allocate a console for this app AllocConsole(); // set the screen buffer to be big enough to let us scroll text GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &coninfo); coninfo.dwSize.Y = MAX_CONSOLE_LINES; SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coninfo.dwSize); bool result = true; FILE* fp; // Redirect STDIN if the console has an input handle if (GetStdHandle(STD_INPUT_HANDLE) != INVALID_HANDLE_VALUE) if (freopen_s(&fp, "CONIN$", "r", stdin) != 0) result = false; else setvbuf(stdin, NULL, _IONBF, 0); // Redirect STDOUT if the console has an output handle if (GetStdHandle(STD_OUTPUT_HANDLE) != INVALID_HANDLE_VALUE) if (freopen_s(&fp, "CONOUT$", "w", stdout) != 0) result = false; else setvbuf(stdout, NULL, _IONBF, 0); // Redirect STDERR if the console has an error handle if (GetStdHandle(STD_ERROR_HANDLE) != INVALID_HANDLE_VALUE) if (freopen_s(&fp, "CONOUT$", "w", stderr) != 0) result = false; else setvbuf(stderr, NULL, _IONBF, 0); // Make C++ standard streams point to console as well. std::ios::sync_with_stdio(true); // Clear the error state for each of the C++ standard streams. std::wcout.clear(); std::cout.clear(); std::wcerr.clear(); std::cerr.clear(); std::wcin.clear(); std::cin.clear(); return result; } ================================================ FILE: sksevr_plugin/plugin/guicon.h ================================================ #pragma once bool RedirectIOToConsole(); ================================================ FILE: sksevr_plugin/plugin/lua_glue.cpp ================================================ #include "lua_glue.h" #include #include #include "FormDB.h" namespace lua { std::filesystem::path dll_path() { HMODULE hm = nullptr; if (GetModuleHandleEx( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCSTR)&dll_path, &hm) == 0) { int ret = GetLastError(); _ERROR("GetModuleHandle failed, error = %d\n", ret); return L""; } wchar_t path[MAX_PATH]; if (GetModuleFileNameW(hm, path, _countof(path)) == 0) { int ret = GetLastError(); _ERROR("GetModuleFileName failed, error = %d\n", ret); return L""; } return std::filesystem::path(path); } lua_State* lua_new_with_libs() { lua_State* L = luaL_newstate(); if (L) { luaL_openlibs(L); } return L; } int lua_prepend_package_path(lua_State* L, const char* path) { int stack_before = lua_gettop(L); auto new_path = std::string(path); lua_getglobal(L, "package"); lua_getfield(L, -1, "path"); // get field "path" from table at top of stack (-1) const char* cur_path = lua_tostring(L, -1); // grab path string from top of stack lua_pop(L, 1); // Pop the result we just used new_path.append(";"); new_path.append(cur_path); lua_pushstring(L, new_path.c_str()); // push the new one lua_setfield(L, -2, "path"); // set the field "path" in table at -2 with value at top of stack lua_pop(L, 1); // get rid of package table from top of stack assert(stack_before == lua_gettop(L)); return 0; } lua_State* lua_new_skyui_state() { // Setup new lua instance lua_State* state = lua_new_with_libs(); auto dll_dir = dll_path().parent_path(); auto package_path = dll_dir / "SkyUI-VR/?.lua"; lua_prepend_package_path(state, package_path.generic_u8string().c_str()); // Execute our lua file to setup global functions and variables in the vm // FIXME!!! This will probably not work for non-ascii paths. auto mainEntryPath = dll_dir / "SkyUI-VR/MainEntry.lua"; if (luaL_dofile(state, mainEntryPath.generic_u8string().c_str()) != 0) { _ERROR("Could not load lua file '%s': %s", mainEntryPath.generic_u8string().c_str(), lua_tostring(state, lua_gettop(state))); lua_pop(state, 1); } return state; } void lua_pop_to_level(lua_State* L, int targetLevel) { int curLevel = lua_gettop(L); assert(targetLevel <= curLevel); int popCount = curLevel - targetLevel; if (curLevel > 0) lua_pop(L, curLevel - targetLevel); assert(lua_gettop(L) == targetLevel); } bool lua_table_is_array(lua_State* L, int tableIdx) { assert(lua_istable(L, tableIdx)); int top = lua_gettop(L); lua_pushvalue(L, tableIdx); // stack starts with: -1 => table lua_pushnil(L); // stack now contains: -1 => nil; -2 => table // Walk through the table... // We'll consider the table an "array" if all keys are numbers and are consecutive integers bool isArray = true; int index = 1; while (lua_next(L, -2)) { // stack now contains: -1 => value; -2 => key; -3 => table if (0 == lua_isnumber(L, -2) || lua_tonumber(L, -2) != (lua_Number)index) { isArray = false; break; } index++; // Pop the value before continuing with lua_next() lua_pop(L, 1); } // Restore the stack to the level where we entered lua::lua_pop_to_level(L, top); return isArray; } void lua_print_value(lua_State* L, int index) { switch (lua_type(L, index)) { case LUA_TNONE: printf("LUA_TNONE"); break; case LUA_TNIL: printf("LUA_TNIL"); break; case LUA_TBOOLEAN: printf("LUA_TBOOLEAN: %s", lua_toboolean(L, index) ? "true" : "false"); break; case LUA_TNUMBER: printf("LUA_TNUMBER: %f", lua_tonumber(L, index)); break; case LUA_TSTRING: printf("LUA_TSTRING: %s", lua_tostring(L, index)); break; case LUA_TTABLE: printf("LUA_TTABLE: 0x%llx", (uint64_t)lua_topointer(L, index)); break; case LUA_TLIGHTUSERDATA: printf("LUA_TLIGHTUSERDATA: 0x%llx", (uint64_t)lua_topointer(L, index)); break; case LUA_TFUNCTION: printf("LUA_TFUNCTION: 0x%llx", (uint64_t)lua_topointer(L, index)); break; case LUA_TUSERDATA: printf("LUA_TUSERDATA: 0x%llx", (uint64_t)lua_topointer(L, index)); break; case LUA_TTHREAD: printf("LUA_TTHREAD: 0x%llx", (uint64_t)lua_topointer(L, index)); break; } } void lua_print_value_recursive(lua_State* L, int index) { int top = lua_gettop(L); const char* func_name = "print_value_recursive"; lua_getglobal(L, func_name); // Grab the lua function lua_pushvalue(L, index); // Call and print any errors if (lua_pcall(L, 1, 0, 0) != 0) { _ERROR("Error running `%s`: %s", func_name, lua_tostring(g_lua, -1)); } lua::lua_pop_to_level(L, top); } bool lua_table_get_by_path(lua_State* L, int tableIdx, const char* path) { const char* func_name = "table_get_by_path"; lua_getglobal(L, func_name); // Grab the lua function lua_pushvalue(L, tableIdx); lua_pushstring(L, path); lua_pushnil(L); // Call and print any errors if (lua_pcall(L, 3, 1, 0) != 0) { _ERROR("Error running `%s`: %s", func_name, lua_tostring(g_lua, -1)); return false; } return true; } bool lua_settings_get_by_path_with_defaults(lua_State* L, int tableIdx, const char* path, const char* defaultsFilename) { const char* func_name = "settings_get_by_path_with_defaults"; lua_getglobal(L, func_name); // Grab the lua function lua_pushvalue(L, tableIdx); lua_pushstring(L, path); lua_pushstring(L, defaultsFilename); lua_pushnil(L); // Call and print any errors if (lua_pcall(L, 4, 1, 0) != 0) { _ERROR("Error running `%s`: %s", func_name, lua_tostring(g_lua, -1)); return false; } return true; } bool lua_table_get_bool_by_path(lua_State* L, int tableIdx, const char* path, bool default) { bool ok = lua_table_get_by_path(L, tableIdx, path); if (!ok) return default; bool val = lua_toboolean(L, -1); lua_pop(L, 1); return val; } double lua_table_get_double_by_path(lua_State* L, int tableIdx, const char* path, double default) { bool ok = lua_table_get_by_path(L, tableIdx, path); if (!ok) return default; double val = lua_tonumber(L, -1); lua_pop(L, 1); return val; } std::string lua_table_get_string_by_path(lua_State* L, int tableIdx, const char* path, std::string default) { bool ok = lua_table_get_by_path(L, tableIdx, path); if (!ok) return default; std::string val = lua_tostring(L, -1); lua_pop(L, 1); return val; } } ================================================ FILE: sksevr_plugin/plugin/lua_glue.h ================================================ #pragma once #include extern "C" { #include #include #include #include "luajit.h" } namespace lua { std::filesystem::path dll_path(); lua_State* lua_new_skyui_state(); bool lua_table_get_by_path(lua_State* L, int tableIdx, const char* path); void lua_pop_to_level(lua_State* L, int targetLevel); bool lua_table_is_array(lua_State* L, int tableIdx); void lua_print_value(lua_State* L, int index); void lua_print_value_recursive(lua_State* L, int index); bool lua_table_get_bool_by_path(lua_State* L, int tableIdx, const char* path, bool default); double lua_table_get_double_by_path(lua_State* L, int tableIdx, const char* path, double default); std::string lua_table_get_string_by_path(lua_State* L, int tableIdx, const char* path, std::string default); bool lua_settings_get_by_path_with_defaults(lua_State* L, int tableIdx, const char* path, const char* defaultsFilename); } ================================================ FILE: sksevr_plugin/plugin/main.cpp ================================================ #include "skse64/PluginAPI.h" // super #include "skse64_common/skse_version.h" // What version of SKSE is running? #include // CSIDL_MYCODUMENTS #include "FormDB.h" #include "Keyboard.h" #include "ControllerStateHook.h" #include "Settings.h" // SKSE patches #include "ScaleformExtendedDataFix.h" #include "PapyrusUIFix.h" #include "skse64/Hooks_UI.h" #include "guicon.h" PluginHandle g_pluginHandle = kPluginHandle_Invalid; SKSEPapyrusInterface* g_papyrus = nullptr; SKSEScaleformInterface* g_scaleform = nullptr; SKSETaskInterface* g_SkseTaskInterface = nullptr; SKSEObjectInterface* g_SkseObjectInterface = nullptr; void WaitForDebugger(bool should_break = false) { while (!IsDebuggerPresent()) Sleep(100); if (should_break) DebugBreak(); } extern "C" { // Called by SKSE to learn about this plugin and check that it's safe to load it bool SKSEPlugin_Query(const SKSEInterface * skse, PluginInfo * info) { gLog.OpenRelative(CSIDL_MYDOCUMENTS, "\\My Games\\Skyrim VR\\SKSE\\SkyUI-VR.log"); gLog.SetPrintLevel(IDebugLog::kLevel_Error); gLog.SetLogLevel(IDebugLog::kLevel_DebugMessage); _MESSAGE("SkyUI-VR loading"); // populate info structure info->infoVersion = PluginInfo::kInfoVersion; info->name = "SkyUI"; info->version = 1; // store plugin handle so we can identify ourselves later g_pluginHandle = skse->GetPluginHandle(); if (skse->isEditor) { _MESSAGE("loaded in editor, marking as incompatible"); return false; } else if (skse->runtimeVersion != RUNTIME_VR_VERSION_1_4_15) { _MESSAGE("unsupported runtime version %08X", skse->runtimeVersion); return false; } // ### do not do anything else in this callback // ### only fill out PluginInfo and return true/false // supported runtime version return true; } // Called by SKSE to load this plugin bool SKSEPlugin_Load(const SKSEInterface * skse) { _MESSAGE("SkyUI-VR loaded"); #ifdef _DEBUG WaitForDebugger(); RedirectIOToConsole(); #endif // DEBUG // Initialize lua // We're storing all our data in lua FormDB::InitGlobalLuaVM(); Settings::loadLuaConfig(); // Setup pointers to various SKSE interfaces // Parts of the program may need to access these sparatically. g_SkseTaskInterface = (SKSETaskInterface*)skse->QueryInterface(kInterface_Task); g_SkseObjectInterface = (SKSEObjectInterface*)skse->QueryInterface(kInterface_Object); // Register additional Papyrus functions g_papyrus = (SKSEPapyrusInterface *)skse->QueryInterface(kInterface_Papyrus); g_papyrus->Register(FormDB::RegisterPapyrusFuncs); // Expose FormDB lua functions to Papyrus g_papyrus->Register(PapyrusUIFix::RegisterPapyrusFuncs); // Fix Papyrus=>SKSE=>Scaleform SInt32 conversion bug // Register Inventory item hooks g_scaleform = (SKSEScaleformInterface*)skse->QueryInterface(kInterface_Scaleform); FormDB::RegisterScaleformInventoryHooks(g_scaleform); ExtendDataFix::RegisterScaleformInventoryHooks(g_scaleform); // Register additional Scaleform functions g_scaleform->Register("skyui", [](GFxMovieView* view, GFxValue* plugin) { FormDB::RegisterScaleformFuncs(view, plugin); // Expose FormDB lua functions to Scaleform ControllerStateHook::RegisterScaleformFuncs(view, plugin); Keyboard::RegisterScaleformFuncs(view, plugin); Settings::RegisterScaleformFuncs(view, plugin); return true; }); // Start receiving constroller state updates ControllerStateHook::Init(); _MESSAGE("Plugin loaded"); return true; } }; ================================================ FILE: sksevr_plugin/plugin/plugin.vcxproj ================================================ Debug x64 Release x64 {547171CB-F934-40B9-B788-3C520FE66363} Win32Proj plugin 10.0.19041.0 plugin DynamicLibrary true v141 MultiByte DynamicLibrary v141 true MultiByte true $(SolutionDir)Build\$(Configuration)\ $(SolutionDir)Build\$(Configuration)\Intermediate\$(ProjectName)\ SkyUI-VR false $(SolutionDir)Build\$(Configuration)\ $(SolutionDir)Build\$(Configuration)\Intermediate\$(ProjectName)\ SkyUI-VR Level3 Disabled _DEBUG;_WINDOWS;_USRDLL;PLUGIN_EXPORTS;%(PreprocessorDefinitions) $(SolutionDir)common;$(SolutionDir)skse;$(SolutionDir);$(SolutionDir)..;$(SolutionDir)Build\$(Configuration)\luajit;%(AdditionalIncludeDirectories) common/IPrefix.h;%(ForcedIncludeFiles) MultiThreadedDebugDLL EnableFastChecks EditAndContinue stdcpp17 Windows true $(SolutionDir)lib\*;$(SolutionDir)Build\$(Configuration)\luajit\lua51.lib;%(AdditionalDependencies) exports.def if defined SkyUITestPath ( echo Copying built dll to test directory xcopy /y $(TargetPath) "%SkyUITestPath%\SKSE\Plugins" xcopy /y $(TargetDir)SkyUI-VR.pdb "%SkyUITestPath%\SKSE\Plugins" ) else ( echo %%SkyUITestPath%% not defined echo Not copying built artifact to test directory ) Level3 MaxSpeed true true WIN32;NDEBUG;_WINDOWS;_USRDLL;PLUGIN_EXPORTS;%(PreprocessorDefinitions) $(SolutionDir)common;$(SolutionDir)skse;$(SolutionDir);$(SolutionDir)..;$(SolutionDir)Build\$(Configuration)\luajit;%(AdditionalIncludeDirectories) common/IPrefix.h;%(ForcedIncludeFiles) MultiThreadedDLL ProgramDatabase stdcpp17 Windows true true true $(SolutionDir)lib\*;$(SolutionDir)Build\$(Configuration)\luajit\lua51.lib;%(AdditionalDependencies) exports.def if defined SkyUITestPath ( echo Copying built dll to test directory xcopy /y $(TargetPath) "%SkyUITestPath%\SKSE\Plugins" xcopy /y $(TargetDir)SkyUI-VR.pdb "%SkyUITestPath%\SKSE\Plugins" ) else ( echo %%SkyUITestPath%% not defined echo Not copying built artifact to test directory ) {472e19ab-def0-42df-819b-18722e8dc822} {639411c0-fc23-4819-a0c5-429a4e5d8a51} {5fd1c08d-db80-480c-a1c6-f0920005cd13} ================================================ FILE: sksevr_plugin/plugin/plugin.vcxproj.filters ================================================  SKSE Patches SKSE Patches SKSE Patches SKSE Patches {6d3ec361-f98a-4172-b913-8e3f183dad14} ================================================ FILE: sksevr_plugin/plugin/scripts/ExportPlugin.psc ================================================ ScriptName ExportPlugin Hidden float Function MyTest() global native ================================================ FILE: sksevr_plugin/plugin.sln ================================================  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 16.0.31702.278 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "skse64", "skse\skse64\skse64.vcxproj", "{639411C0-FC23-4819-A0C5-429A4E5D8A51}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "skse64_common", "skse\skse64_common\skse64_common.vcxproj", "{5FD1C08D-DB80-480C-A1C6-F0920005CD13}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "common_vc14", "common\common_vc14.vcxproj", "{472E19AB-DEF0-42DF-819B-18722E8DC822}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "plugin", "plugin\plugin.vcxproj", "{547171CB-F934-40B9-B788-3C520FE66363}" ProjectSection(ProjectDependencies) = postProject {38230328-1674-4BFD-B185-885B95075068} = {38230328-1674-4BFD-B185-885B95075068} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "luajit", "luajit.vcxproj", "{38230328-1674-4BFD-B185-885B95075068}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 Release|x64 = Release|x64 Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {639411C0-FC23-4819-A0C5-429A4E5D8A51}.Debug|x64.ActiveCfg = Debug_Lib|x64 {639411C0-FC23-4819-A0C5-429A4E5D8A51}.Debug|x64.Build.0 = Debug_Lib|x64 {639411C0-FC23-4819-A0C5-429A4E5D8A51}.Debug|x86.ActiveCfg = Debug|x64 {639411C0-FC23-4819-A0C5-429A4E5D8A51}.Release|x64.ActiveCfg = Release_Lib|x64 {639411C0-FC23-4819-A0C5-429A4E5D8A51}.Release|x64.Build.0 = Release_Lib|x64 {639411C0-FC23-4819-A0C5-429A4E5D8A51}.Release|x86.ActiveCfg = Release|x64 {5FD1C08D-DB80-480C-A1C6-F0920005CD13}.Debug|x64.ActiveCfg = Debug|x64 {5FD1C08D-DB80-480C-A1C6-F0920005CD13}.Debug|x64.Build.0 = Debug|x64 {5FD1C08D-DB80-480C-A1C6-F0920005CD13}.Debug|x86.ActiveCfg = Debug|x64 {5FD1C08D-DB80-480C-A1C6-F0920005CD13}.Release|x64.ActiveCfg = Release|x64 {5FD1C08D-DB80-480C-A1C6-F0920005CD13}.Release|x64.Build.0 = Release|x64 {5FD1C08D-DB80-480C-A1C6-F0920005CD13}.Release|x86.ActiveCfg = Release|x64 {472E19AB-DEF0-42DF-819B-18722E8DC822}.Debug|x64.ActiveCfg = Debug|x64 {472E19AB-DEF0-42DF-819B-18722E8DC822}.Debug|x64.Build.0 = Debug|x64 {472E19AB-DEF0-42DF-819B-18722E8DC822}.Debug|x86.ActiveCfg = Debug|x64 {472E19AB-DEF0-42DF-819B-18722E8DC822}.Release|x64.ActiveCfg = Release|x64 {472E19AB-DEF0-42DF-819B-18722E8DC822}.Release|x64.Build.0 = Release|x64 {472E19AB-DEF0-42DF-819B-18722E8DC822}.Release|x86.ActiveCfg = Release|x64 {547171CB-F934-40B9-B788-3C520FE66363}.Debug|x64.ActiveCfg = Debug|x64 {547171CB-F934-40B9-B788-3C520FE66363}.Debug|x64.Build.0 = Debug|x64 {547171CB-F934-40B9-B788-3C520FE66363}.Debug|x86.ActiveCfg = Debug|x64 {547171CB-F934-40B9-B788-3C520FE66363}.Release|x64.ActiveCfg = Release|x64 {547171CB-F934-40B9-B788-3C520FE66363}.Release|x64.Build.0 = Release|x64 {547171CB-F934-40B9-B788-3C520FE66363}.Release|x86.ActiveCfg = Release|x64 {38230328-1674-4BFD-B185-885B95075068}.Debug|x64.ActiveCfg = Debug|x64 {38230328-1674-4BFD-B185-885B95075068}.Debug|x64.Build.0 = Debug|x64 {38230328-1674-4BFD-B185-885B95075068}.Debug|x86.ActiveCfg = Debug|Win32 {38230328-1674-4BFD-B185-885B95075068}.Debug|x86.Build.0 = Debug|Win32 {38230328-1674-4BFD-B185-885B95075068}.Release|x64.ActiveCfg = Release|x64 {38230328-1674-4BFD-B185-885B95075068}.Release|x64.Build.0 = Release|x64 {38230328-1674-4BFD-B185-885B95075068}.Release|x86.ActiveCfg = Release|Win32 {38230328-1674-4BFD-B185-885B95075068}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {BACC6EF5-15F4-4A24-A264-596F5928BCDE} EndGlobalSection EndGlobal ================================================ FILE: sksevr_plugin/tools/run-lua-tests ================================================ #!/usr/bin/bash SCRIPT_PATH=`dirname "$(realpath $0)"` cd $SCRIPT_PATH/../lua-tests busted --coverage -m "$SCRIPT_PATH/../lua/?.lua" . ================================================ FILE: src/.gitignore ================================================ .flashProjectProperties .snippets ================================================ FILE: src/CLIK/Mouse.as ================================================ //**************************************************************************** // ActionScript Standard Library // Mouse object //**************************************************************************** intrinsic class Mouse { static function addListener(listener:Object):Void; static function hide():Number; static function removeListener(listener:Object):Boolean; static function show():Number; // scaleform extensions static function getTopMostEntity(arg1:Object,arg2:Number,arg3:Boolean):Object; } ================================================ FILE: src/CLIK/Selection.as ================================================ //**************************************************************************** // ActionScript Standard Library // Selection control //**************************************************************************** intrinsic class Selection { static function addListener(listener:Object):Void; static function getBeginIndex():Number; static function getCaretIndex():Number; static function getEndIndex():Number; static function getFocus():String; static function removeListener(listener:Object):Boolean; static function setFocus(newFocus:Object):Boolean; // newFocus can be string path or Object itself static function setSelection(beginIndex:Number, endIndex:Number):Void; // scaleform extensions static var alwaysEnableArrowKeys:Boolean; static var disableFocusAutoRelease:Boolean; static var disableFocusKeys:Boolean; static var disableFocusRolloverEvent:Boolean; static var numFocusGroups:Number; static var alwaysEnableKeyboardPress:Boolean; static function getControllerMaskByFocusGroup(focusGroupIdx:Number):Number; static function getControllerFocusGroup(controllerIndex:Number):Number; static function findFocus(keyToSimulate:String, parentMovie:Object, loop:Boolean, startFromMovie:Object, includeFocusEnabledChars:Boolean, controllerIndex:Number):Object; static function getFocusBitmask(mc:Object):Number; } ================================================ FILE: src/CLIK/Stage.as ================================================ //**************************************************************************** // ActionScript Standard Library // Stage object //**************************************************************************** import flash.geom.Rectangle; intrinsic class Stage { static var align:String; static var displayState:String; static var height:Number; static var scaleMode:String; static var showMenu:Boolean; static var width:Number; static var fullScreenSourceRect:Rectangle; static var fullScreenWidth:Number; static var fullScreenHeight:Number; static function addListener(listener:Object):Void; static function removeListener(listener:Object):Boolean; function onFullScreen(bFull:Boolean):Void; // scaleform extensions static var visibleRect:Rectangle; static var safeRect:Rectangle; } ================================================ FILE: src/CLIK/System/capabilities.as ================================================ //**************************************************************************** // ActionScript Standard Library // SystemCapabilities object //**************************************************************************** intrinsic class System.capabilities { static var hasAudio:Boolean; static var hasMP3:Boolean; static var hasAudioEncoder:Boolean; static var hasVideoEncoder:Boolean; static var hasIME:Boolean; static var screenResolutionX:Number; static var screenResolutionY:Number; static var screenDPI:Number; static var screenColor:String; static var pixelAspectRatio:Number; static var hasAccessibility:Boolean; static var input:String; static var isDebugger:Boolean; static var language:String; static var manufacturer:String; static var os:String; static var serverString:String; static var version:String; static var hasPrinting:Boolean; static var playerType:String; static var hasStreamingAudio:Boolean; static var hasScreenBroadcast:Boolean; static var hasScreenPlayback:Boolean; static var hasStreamingVideo:Boolean; static var hasEmbeddedVideo:Boolean; static var avHardwareDisable:Boolean; static var localFileReadDisable:Boolean; static var windowlessDisable:Boolean; // Mobile specific static var hasCompoundSound:Boolean; static var hasEmail:Boolean; static var hasMMS:Boolean; static var hasSMS:Boolean; static var hasMFI:Boolean; static var hasMIDI:Boolean; static var hasSMAF:Boolean; static var hasDataLoading:Boolean; static var has4WayKeyAS:Boolean; static var hasMouse:Boolean; static var hasMappableSoftKeys:Boolean; static var hasCMIDI:Boolean; static var hasStylus:Boolean; static var screenOrientation:String; static var hasSharedObjects:Boolean; static var hasQWERTYKeyboard:Boolean; static var softKeyCount:Number; static var audioMIMETypes:Array; static var imageMIMETypes:Array; static var videoMIMETypes:Array; static var MIMETypes:String; static var hasXMLSocket:Boolean; // Scaleform numControllers static var numControllers:Number; } ================================================ FILE: src/CLIK/gfx/controls/Button.as ================================================ dynamic class gfx.controls.Button extends gfx.core.UIComponent { var state: String = "up"; var toggle: Boolean = false; var doubleClickEnabled: Boolean = false; var autoRepeat: Boolean = false; var lockDragStateChange: Boolean = false; var soundMap = {theme: "default", focusIn: "focusIn", focusOut: "focusOut", select: "select", rollOver: "rollOver", rollOut: "rollOut", press: "press", doubleClick: "doubleClick", click: "click"}; var _selected: Boolean = false; var _autoSize: String = "none"; var _disableFocus: Boolean = false; var _disableConstraints: Boolean = false; var doubleClickDuration: Number = 250; var buttonRepeatDuration: Number = 100; var buttonRepeatDelay: Number = 100; var pressedByKeyboard: Boolean = false; var stateMap = {up: ["up"], over: ["over"], down: ["down"], release: ["release", "over"], out: ["out", "up"], disabled: ["disabled"], selecting: ["selecting", "over"], kb_selecting: ["kb_selecting", "up"], kb_release: ["kb_release", "out", "up"], kb_down: ["kb_down", "down"]}; var __height; var __width; var _disabled; var _displayFocus; var _focused; var _group; var _height; var _label; var _name; var _parent; var _width; var _x; var buttonRepeatInterval; var constraints; var dispatchEvent; var dispatchEventAndSound; var doubleClickInterval; var focusEnabled; var focusIndicator; var gotoAndPlay; var initialized; var inspectableGroupName; var invalidate; var onDragOut; var onDragOver; var onPress; var onRelease; var onReleaseOutside; var onRollOut; var onRollOver; var sizeIsInvalid; var tabEnabled; var textField; var validateNow; function Button() { super(); this.focusEnabled = this.tabEnabled = this._disableFocus ? false : !this._disabled; if (this.inspectableGroupName != null && this.inspectableGroupName != "") { this.group = this.inspectableGroupName; } } function get labelID() { return null; } function set labelID(value) { if (value != "") { this.label = gfx.utils.Locale.getTranslatedString(value); } } function get label() { return this._label; } function set label(value) { this._label = value; if (this.initialized) { if (this.textField != null) { this.textField.text = this._label; } if (this.autoSize != "none") { this.sizeIsInvalid = true; } this.updateAfterStateChange(); } } function get disabled() { return this._disabled; } function set disabled(value) { if (this._disabled != value) { super.disabled = value; this.clearRepeatInterval(); this.focusEnabled = this.tabEnabled = this._disableFocus ? false : !this._disabled; this.setState(this._disabled ? "disabled" : "up"); return; } } function get selected() { return this._selected; } function set selected(value) { if (this._selected != value) { this._selected = value; if (this._disabled) { this.setState("disabled"); } else if (this._focused) { if (this.pressedByKeyboard && this.focusIndicator != null) { this.setState("kb_selecting"); } else { this.setState("selecting"); } } else { this.setState(this.displayFocus && this.focusIndicator == null ? "over" : "up"); } if (this.dispatchEvent != null) { this.dispatchEventAndSound({type: "select", selected: this._selected}); } return; } } function get groupName() { return this._group == null ? null : this._group.name; } function set groupName(value) { this.group = value; } function get group() { return this._group; } function set group(value) { var __reg2 = gfx.controls.ButtonGroup(value); if (typeof value == "string") { __reg2 = this._parent["_buttonGroup_" + value]; if (__reg2 == null) { this._parent["_buttonGroup_" + value] = __reg2 = new gfx.controls.ButtonGroup(value.toString(), this._parent); } } if (this._group != __reg2) { if (this._group != null) { this._group.removeButton(this); } this._group = __reg2; if (this._group != null) { __reg2.addButton(this); } return; } } function get disableFocus() { return this._disableFocus; } function set disableFocus(value) { this._disableFocus = value; this.focusEnabled = this.tabEnabled = this._disableFocus ? false : !this._disabled; } function get disableConstraints() { return this._disableConstraints; } function set disableConstraints(value) { this._disableConstraints = value; } function get autoSize() { return this._autoSize; } function set autoSize(value) { if (this._autoSize != value) { this._autoSize = value; if (this.initialized) { this.sizeIsInvalid = true; this.validateNow(); } return; } } function setSize(width, height) { super.setSize(width, height); } function handleInput(details, pathToFocus) { if ((__reg0 = details.navEquivalent) === gfx.ui.NavigationCode.ENTER) { var __reg2 = details.controllerIdx; if (details.value == "keyDown" || details.value == "keyHold") { if (!this.pressedByKeyboard) { this.handlePress(__reg2); } } else { this.handleRelease(__reg2); } return true; } return false; } function toString() { return "[Scaleform Button " + this._name + "]"; } function configUI() { this.constraints = new gfx.utils.Constraints(this, true); if (!this._disableConstraints) { this.constraints.addElement(this.textField, gfx.utils.Constraints.ALL); } super.configUI(); if (this._autoSize != "none") { this.sizeIsInvalid = true; } this.onRollOver = this.handleMouseRollOver; this.onRollOut = this.handleMouseRollOut; this.onPress = this.handleMousePress; this.onRelease = this.handleMouseRelease; this.onReleaseOutside = this.handleReleaseOutside; this.onDragOver = this.handleDragOver; this.onDragOut = this.handleDragOut; if (this.focusIndicator != null && !this._focused && this.focusIndicator._totalFrames == 1) { this.focusIndicator._visible = false; } this.updateAfterStateChange(); } function draw() { if (this.sizeIsInvalid) { this.alignForAutoSize(); this._width = this.__width; this._height = this.__height; } if (this.initialized) { this.constraints.update(this.__width, this.__height); } } function updateAfterStateChange() { if (this.initialized) { if (this.textField != null && this._label != null) { this.textField.text = this._label; } this.validateNow(); if (this.constraints != null) { this.constraints.update(this.width, this.height); } this.dispatchEvent({type: "stateChange", state: this.state}); } } function calculateWidth() { if (this.constraints == null) { this.invalidate(); return 0; } var __reg2 = this.constraints.getElement(this.textField).metrics; var __reg3 = this.textField.textWidth + __reg2.left + __reg2.right + 5; return __reg3; } function alignForAutoSize() { if (!this.initialized || this._autoSize == "none" || this.textField == null) { return undefined; } var __reg2 = this.__width; this.width = this.calculateWidth(); if ((__reg0 = this._autoSize) === "right") { var __reg3 = this._x + __reg2; this._x = __reg3 - this.__width; return; } else if (__reg0 !== "center") { return; } var __reg4 = this._x + __reg2 / 2; this._x = __reg4 - this.__width / 2; return; } function setState(state) { this.state = state; var __reg5 = this.getStatePrefixes(); var __reg3 = this.stateMap[state]; if (__reg3 == null || __reg3.length == 0) { return undefined; } do { var __reg4 = __reg5.pop().toString(); var __reg2 = __reg3.length - 1; while (__reg2 >= 0) { this.gotoAndPlay(__reg4 + __reg3[__reg2]); --__reg2; } } while (__reg5.length > 0); this.updateAfterStateChange(); } function getStatePrefixes() { return this._selected ? ["selected_", ""] : [""]; } function changeFocus() { if (this._disabled) { return undefined; } if (this.focusIndicator == null) { this.setState(this._focused || this._displayFocus ? "over" : "out"); if (this.pressedByKeyboard && !this._focused) { this.pressedByKeyboard = false; } } if (this.focusIndicator != null) { if (this.focusIndicator._totalframes == 1) { this.focusIndicator._visible = this._focused != 0; } else { this.focusIndicator.gotoAndPlay(this._focused ? "show" : "hide"); this.focusIndicator.gotoAndPlay("state" + this._focused); } if (this.pressedByKeyboard && !this._focused) { this.setState("kb_release"); this.pressedByKeyboard = false; } } } function handleMouseRollOver(controllerIdx) { if (this._disabled) { return undefined; } if ((!this._focused && !this._displayFocus) || this.focusIndicator != null) { this.setState("over"); } this.dispatchEventAndSound({type: "rollOver", controllerIdx: controllerIdx}); } function handleMouseRollOut(controllerIdx) { if (this._disabled) { return undefined; } if ((!this._focused && !this._displayFocus) || this.focusIndicator != null) { this.setState("out"); } this.dispatchEventAndSound({type: "rollOut", controllerIdx: controllerIdx}); } function handleMousePress(controllerIdx, keyboardOrMouse, button) { if (this._disabled) { return undefined; } if (!this._disableFocus) { Selection.setFocus(this, controllerIdx); } this.setState("down"); this.dispatchEventAndSound({type: "press", controllerIdx: controllerIdx, button: button}); if (this.autoRepeat) { this.buttonRepeatInterval = setInterval(this, "beginButtonRepeat", this.buttonRepeatDelay, controllerIdx, button); } } function handlePress(controllerIdx) { if (this._disabled) { return undefined; } this.pressedByKeyboard = true; this.setState(this.focusIndicator == null ? "down" : "kb_down"); this.dispatchEventAndSound({type: "press", controllerIdx: controllerIdx}); } function handleMouseRelease(controllerIdx, keyboardOrMouse, button) { if (this._disabled) { return undefined; } clearInterval(this.buttonRepeatInterval); delete this.buttonRepeatInterval; if (this.doubleClickEnabled) { if (this.doubleClickInterval == null) { this.doubleClickInterval = setInterval(this, "doubleClickExpired", this.doubleClickDuration); } else { this.doubleClickExpired(); this.dispatchEventAndSound({type: "doubleClick", controllerIdx: controllerIdx, button: button}); this.setState("release"); return undefined; } } this.setState("release"); this.handleClick(controllerIdx, button); } function handleRelease(controllerIdx) { if (this._disabled) { return undefined; } this.setState(this.focusIndicator == null ? "release" : "kb_release"); this.handleClick(controllerIdx); this.pressedByKeyboard = false; } function handleClick(controllerIdx, button) { if (this.toggle) { this.selected = !this._selected; } this.dispatchEventAndSound({type: "click", controllerIdx: controllerIdx, button: button}); } function handleDragOver(controllerIdx, button) { if (this._disabled || this.lockDragStateChange) { return undefined; } if (this._focused || this._displayFocus) { this.setState(this.focusIndicator == null ? "down" : "kb_down"); } else { this.setState("over"); } this.dispatchEvent({type: "dragOver", controllerIdx: controllerIdx, button: button}); } function handleDragOut(controllerIdx, button) { if (this._disabled || this.lockDragStateChange) { return undefined; } if (this._focused || this._displayFocus) { this.setState(this.focusIndicator == null ? "release" : "kb_release"); } else { this.setState("out"); } this.dispatchEvent({type: "dragOut", controllerIdx: controllerIdx, button: button}); } function handleReleaseOutside(controllerIdx, button) { this.clearRepeatInterval(); if (this._disabled) { return undefined; } if (this.lockDragStateChange) { if (this._focused || this._displayFocus) { this.setState(this.focusIndicator == null ? "release" : "kb_release"); } else { this.setState("kb_release"); } } this.dispatchEvent({type: "releaseOutside", state: this.state, button: button}); } function doubleClickExpired() { clearInterval(this.doubleClickInterval); delete this.doubleClickInterval; } function beginButtonRepeat(controllerIdx, button) { this.clearRepeatInterval(); this.buttonRepeatInterval = setInterval(this, "handleButtonRepeat", this.buttonRepeatDuration, controllerIdx, button); } function handleButtonRepeat(controllerIdx, button) { this.dispatchEventAndSound({type: "click", controllerIdx: controllerIdx, button: button}); } function clearRepeatInterval() { clearInterval(this.buttonRepeatInterval); delete this.buttonRepeatInterval; } } ================================================ FILE: src/CLIK/gfx/controls/ButtonBar.as ================================================ dynamic class gfx.controls.ButtonBar extends gfx.core.UIComponent { var _itemRenderer: String = "Button"; var _spacing: Number = 0; var _direction: String = "horizontal"; var _selectedIndex: Number = -1; var _autoSize: String = "none"; var _buttonWidth: Number = 0; var _labelField: String = "label"; var reflowing: Boolean = false; var _dataProvider; var _disabled; var _focused; var _labelFunction; var _name; var attachMovie; var dispatchEventAndSound; var focusEnabled; var getNextHighestDepth; var initialized; var invalidate; var renderers; var tabChildren; var tabEnabled; function ButtonBar() { super(); this.renderers = []; this.focusEnabled = this.tabEnabled = !this._disabled; this.tabChildren = false; } function get disabled() { return this._disabled; } function set disabled(value) { super.disabled = value; this.focusEnabled = this.tabEnabled = !this._disabled; if (this.initialized) { var __reg3 = 0; while (__reg3 < this.renderers.length) { this.renderers[__reg3].disabled = this._disabled; ++__reg3; } return; } } function get dataProvider() { return this._dataProvider; } function set dataProvider(value) { if (this._dataProvider != value) { if (this._dataProvider != null) { this._dataProvider.removeEventListener("change", this, "onDataChange"); } this._dataProvider = value; if (this._dataProvider != null) { if (value instanceof Array && !value.isDataProvider) { gfx.data.DataProvider.initialize(this._dataProvider); } else if (this._dataProvider.initialize != null) { this._dataProvider.initialize(this); } this._dataProvider.addEventListener("change", this, "onDataChange"); this.selectedIndex = 0; this.tabEnabled = this.focusEnabled = !this._disabled && this._dataProvider.length > 0; this.reflowing = false; this.invalidate(); return; } } } function invalidateData() { this.selectedIndex = Math.min(this._dataProvider.length - 1, this._selectedIndex); this.populateData(); this.invalidate(); } function get itemRenderer() { return this._itemRenderer; } function set itemRenderer(value) { this._itemRenderer = value; while (this.renderers.length > 0) { this.renderers.pop().removeMovieClip(); } this.invalidate(); } function get spacing() { return this._spacing; } function set spacing(value) { this._spacing = value; this.invalidate(); } function get direction() { return this._direction; } function set direction(value) { this._direction = value; this.invalidate(); } function get autoSize() { return this._autoSize; } function set autoSize(value) { if (value != this._autoSize) { this._autoSize = value; var __reg2 = 0; while (__reg2 < this.renderers.length) { this.renderers[__reg2].autoSize = this._autoSize; ++__reg2; } this.invalidate(); return; } } function get buttonWidth() { return this._buttonWidth; } function set buttonWidth(value) { this._buttonWidth = value; this.invalidate(); } function get selectedIndex() { return this._selectedIndex; } function set selectedIndex(value) { if (this._selectedIndex != value) { this._selectedIndex = value; this.selectItem(this._selectedIndex); this.dispatchEventAndSound({type: "change", index: this._selectedIndex, renderer: this.renderers[this._selectedIndex], item: this.selectedItem, data: this.selectedItem.data}); return; } } function get selectedItem() { return this._dataProvider.requestItemAt(this._selectedIndex); } function get data() { return this.selectedItem.data; } function get labelField() { return this._labelField; } function set labelField(value) { this._labelField = value; this.invalidate(); } function get labelFunction() { return this._labelFunction; } function set labelFunction(value) { this._labelFunction = value; this.invalidate(); } function itemToLabel(item) { if (item == null) { return ""; } if (this._labelFunction == null) { if (this._labelField != null && item[this._labelField] != null) { return item[this._labelField]; } } else { return this._labelFunction(item); } return item.toString(); } function handleInput(details, pathToFocus) { var __reg4 = details.value == "keyDown" || details.value == "keyHold"; var __reg2 = undefined; if ((__reg0 = details.navEquivalent) === gfx.ui.NavigationCode.LEFT) { if (this._direction == "horizontal") { __reg2 = this._selectedIndex - 1; } } else if (__reg0 === gfx.ui.NavigationCode.RIGHT) { if (this._direction == "horizontal") { __reg2 = this._selectedIndex + 1; } } else if (__reg0 === gfx.ui.NavigationCode.UP) { if (this._direction == "vertical") { __reg2 = this._selectedIndex - 1; } } else if (__reg0 === gfx.ui.NavigationCode.DOWN) { if (this._direction == "vertical") { __reg2 = this._selectedIndex + 1; } } if (__reg2 != null) { __reg2 = Math.max(0, Math.min(this._dataProvider.length - 1, __reg2)); if (__reg2 != this._selectedIndex) { if (!__reg4) { return true; } this.selectedIndex = __reg2; return true; } } return false; } function toString() { return "[Scaleform ButtonBar " + this._name + "]"; } function draw() { if (!this.reflowing) { var __reg3 = this._dataProvider.length; while (this.renderers.length > __reg3) { var __reg2 = MovieClip(this.renderers.pop()); __reg2.group.removeButton(__reg2); __reg2.removeMovieClip(); } while (this.renderers.length < __reg3) { this.renderers.push(this.createRenderer(this.renderers.length)); } this.populateData(); this.reflowing = true; this.invalidate(); return undefined; } if (this.drawLayout() && this._selectedIndex != -1) { this.selectItem(this._selectedIndex); } } function drawLayout() { if (this.renderers.length > 0 && !this.renderers[this.renderers.length - 1].initialized) { this.reflowing = true; this.invalidate(); return false; } this.reflowing = false; var __reg5 = 0; var __reg4 = 0; var __reg3 = 0; while (__reg3 < this.renderers.length) { var __reg2 = this.renderers[__reg3]; if (this._autoSize == "none" && this._buttonWidth > 0) { __reg2.width = this._buttonWidth; } if (this._direction == "horizontal") { __reg2._y = 0; __reg2._x = __reg5; __reg5 = __reg5 + (__reg2.width + this._spacing); } else { __reg2._x = 0; __reg2._y = __reg4; __reg4 = __reg4 + (__reg2.height + this._spacing); } ++__reg3; } return true; } function createRenderer(index) { var __reg2 = this.attachMovie(this.itemRenderer, "clip" + index, this.getNextHighestDepth(), {toggle: true, focusTarget: this, tabEnabled: false, autoSize: this._autoSize}); if (__reg2 == null) { return null; } __reg2.addEventListener("click", this, "handleItemClick"); __reg2.index = index; __reg2.groupName = this._name + "ButtonGroup"; return __reg2; } function handleItemClick(event) { var __reg2 = event.target; var __reg5 = __reg2.index; this.selectedIndex = __reg5; this.dispatchEventAndSound({type: "itemClick", data: this.selectedItem.data, item: this.selectedItem, index: __reg5, controllerIdx: event.controllerIdx}); } function selectItem(index) { if (this.renderers.length >= 1) { var __reg6 = this.renderers[index]; if (!__reg6.selected) { __reg6.selected = true; } var __reg4 = this.renderers.length; var __reg2 = 0; while (__reg2 < __reg4) { if (__reg2 != index) { var __reg3 = 100 + __reg4 - __reg2; this.renderers[__reg2].swapDepths(__reg3); this.renderers[__reg2].displayFocus = false; } ++__reg2; } __reg6.swapDepths(1000); __reg6.displayFocus = this._focused; } } function changeFocus() { var __reg2 = this.renderers[this._selectedIndex]; if (__reg2 != null) { __reg2.displayFocus = this._focused; } } function onDataChange(event) { this.invalidateData(); } function populateData() { var __reg2 = 0; for (;;) { if (__reg2 >= this.renderers.length) { return; } var __reg3 = this.renderers[__reg2]; __reg3.label = this.itemToLabel(this._dataProvider.requestItemAt(__reg2)); __reg3.data = this._dataProvider.requestItemAt(__reg2); __reg3.disabled = this._disabled; ++__reg2; } } } ================================================ FILE: src/CLIK/gfx/controls/ButtonGroup.as ================================================ dynamic class gfx.controls.ButtonGroup extends gfx.events.EventDispatcher { var name: String = "buttonGroup"; var children; var dispatchEvent; var scope; var selectedButton; function ButtonGroup(name, scope) { super(); this.name = name; this.scope = scope; this.children = []; } function get length() { return this.children.length; } function addButton(button) { this.removeButton(button); this.children.push(button); if (button.selected) { this.setSelectedButton(button); } button.addEventListener("select", this, "handleSelect"); button.addEventListener("click", this, "handleClick"); } function removeButton(button) { var __reg2 = this.indexOf(button); if (__reg2 > -1) { this.children.splice(__reg2, 1); button.removeEventListener("select", this, "handleSelect"); button.removeEventListener("click", this, "handleClick"); } if (this.selectedButton == button) { this.selectedButton = null; } } function indexOf(button) { var __reg4 = this.length; if (__reg4 == 0) { return -1; } var __reg2 = 0; while (__reg2 < this.length) { if (this.children[__reg2] == button) { return __reg2; } ++__reg2; } return -1; } function getButtonAt(index) { return this.children[index]; } function get data() { return this.selectedButton.data; } function setSelectedButton(button) { if (this.selectedButton == button || (this.indexOf(button) == -1 && button != null)) { return undefined; } if (this.selectedButton != null && this.selectedButton._name != null) { this.selectedButton.selected = false; } this.selectedButton = button; if (this.selectedButton != null) { this.selectedButton.selected = true; this.dispatchEvent({type: "change", item: this.selectedButton, data: this.selectedButton.data}); } } function toString() { return "[Scaleform RadioButtonGroup " + this.name + "]"; } function handleSelect(event) { if (event.target.selected) { this.setSelectedButton(event.target); return; } this.setSelectedButton(null); } function handleClick(event) { this.dispatchEvent({type: "itemClick", item: event.target}); this.setSelectedButton(event.target); } } ================================================ FILE: src/CLIK/gfx/controls/CoreList.as ================================================ dynamic class gfx.controls.CoreList extends gfx.core.UIComponent { var soundMap = {theme: "default", focusIn: "focusIn", focusOut: "focusOut", select: "select", change: "change", rollOver: "rollOver", rollOut: "rollOut", itemClick: "itemClick", itemDoubleClick: "itemDoubleClick", itemPress: "itemPress", itemRollOver: "itemRollOver", itemRollOut: "itemRollOut"}; var _itemRenderer: String = "ListItemRenderer"; var _selectedIndex: Number = -1; var _labelField: String = "label"; var externalRenderers: Boolean = false; var deferredScrollIndex: Number = -1; var __height; var __width; var _dataProvider; var _labelFunction; var _name; var _parent; var container; var createEmptyMovieClip; var dispatchEventAndSound; var focusEnabled; var inspectableRendererInstanceName; var invalidate; var owner; var renderers; var tabEnabled; function CoreList() { super(); this.renderers = []; this.dataProvider = []; if (this.container == undefined) { this.container = this.createEmptyMovieClip("container", 1); } this.container.scale9Grid = new flash.geom.Rectangle(0, 0, 1, 1); this.tabEnabled = this.focusEnabled = true; } function get itemRenderer() { return this._itemRenderer; } function set itemRenderer(value) { if (value == this._itemRenderer || value == "") { return; } this._itemRenderer = value; this.resetRenderers(); this.invalidate(); } function get dataProvider() { return this._dataProvider; } function set dataProvider(value) { if (this._dataProvider != value) { if (this._dataProvider != null) { this._dataProvider.removeEventListener("change", this, "onDataChange"); } this._dataProvider = value; if (this._dataProvider != null) { if (value instanceof Array && !value.isDataProvider) { gfx.data.DataProvider.initialize(this._dataProvider); } else if (this._dataProvider.initialize != null) { this._dataProvider.initialize(this); } this._dataProvider.addEventListener("change", this, "onDataChange"); this.invalidate(); return; } } } function get selectedIndex() { return this._selectedIndex; } function set selectedIndex(value) { var __reg3 = this._selectedIndex; this._selectedIndex = value; this.dispatchEventAndSound({type: "change", index: this._selectedIndex, lastIndex: __reg3}); } function scrollToIndex(index) { } function get labelField() { return this._labelField; } function set labelField(value) { this._labelField = value; this.invalidateData(); } function get labelFunction() { return this._labelFunction; } function set labelFunction(value) { this._labelFunction = value; this.invalidateData(); } function itemToLabel(item) { if (item == null) { return ""; } if (this._labelFunction == null) { if (this._labelField != null && item[this._labelField] != null) { return item[this._labelField]; } } else { return this._labelFunction(item); } return item.toString(); } function invalidateData() { } function get availableWidth() { return this.__width; } function get availableHeight() { return this.__height; } function setRendererList(value) { if (this.externalRenderers) { var __reg3 = 0; while (__reg3 < this.renderers.length) { var __reg2 = this.renderers[__reg3]; __reg2.owner = null; __reg2.removeEventListener("click", this, "handleItemClick"); __reg2.removeEventListener("rollOver", this, "dispatchItemEvent"); __reg2.removeEventListener("rollOut", this, "dispatchItemEvent"); __reg2.removeEventListener("press", this, "dispatchItemEvent"); __reg2.removeEventListener("doubleClick", this, "dispatchItemEvent"); Mouse.removeListener(__reg2); ++__reg3; } } else { this.resetRenderers(); } this.externalRenderers = value != null; if (this.externalRenderers) { this.renderers = value; } this.invalidate(); } function get rendererInstanceName() { return null; } function set rendererInstanceName(value) { if (value == null || value == "") { return; } var __reg3 = 0; var __reg4 = []; while (!false) { ++__reg3; var __reg2 = this._parent[value + __reg3]; if (__reg2 == null && __reg3 > 0) { break; } if (__reg2 != null) { this.setUpRenderer(__reg2); Mouse.addListener(__reg2); __reg2.scrollWheel = function (delta) { this.owner.scrollWheel(delta); } ; __reg4.push(__reg2); } } if (__reg4.length == 0) { __reg4 = null; } this.setRendererList(__reg4); } function toString() { return "[Scaleform CoreList " + this._name + "]"; } function configUI() { super.configUI(); if (this._selectedIndex > -1) { this.deferredScrollIndex = this._selectedIndex; } if (this.inspectableRendererInstanceName != "") { this.rendererInstanceName = this.inspectableRendererInstanceName; } Mouse.addListener(this); } function createItemRenderer(index) { var __reg2 = this.container.attachMovie(this._itemRenderer, "renderer" + index, index); if (__reg2 == null) { return null; } this.setUpRenderer(__reg2); return __reg2; } function setUpRenderer(clip) { clip.owner = this; clip.tabEnabled = false; clip.doubleClickEnabled = true; clip.addEventListener("press", this, "dispatchItemEvent"); clip.addEventListener("click", this, "handleItemClick"); clip.addEventListener("doubleClick", this, "dispatchItemEvent"); clip.addEventListener("rollOver", this, "dispatchItemEvent"); clip.addEventListener("rollOut", this, "dispatchItemEvent"); } function createItemRenderers(startIndex, endIndex) { var __reg3 = []; var __reg2 = startIndex; while (__reg2 <= endIndex) { __reg3.push(this.createItemRenderer[__reg2]); ++__reg2; } return __reg3; } function draw() { if (this.deferredScrollIndex != -1) { this.scrollToIndex(this.deferredScrollIndex); this.deferredScrollIndex = -1; } } function drawRenderers(totalRenderers) { while (this.renderers.length > totalRenderers) { this.renderers.pop().removeMovieClip(); } for (;;) { if (this.renderers.length >= totalRenderers) { return; } this.renderers.push(this.createItemRenderer(this.renderers.length)); } } function getRendererAt(index) { return this.renderers[index]; } function resetRenderers() { for (;;) { if (this.renderers.length <= 0) { return; } this.renderers.pop().removeMovieClip(); } } function drawLayout(rendererWidth, rendererHeight) { } function onDataChange(event) { this.invalidateData(); } function dispatchItemEvent(event) { var __reg9 = undefined; if ((__reg0 = event.type) === "press") { __reg9 = "itemPress"; } else if (__reg0 === "click") { __reg9 = "itemClick"; } else if (__reg0 === "rollOver") { __reg9 = "itemRollOver"; } else if (__reg0 === "rollOut") { __reg9 = "itemRollOut"; } else if (__reg0 === "doubleClick") { __reg9 = "itemDoubleClick"; } else { return undefined; } var __reg3 = {target: this, type: __reg9, item: event.target.data, renderer: event.target, index: event.target.index, controllerIdx: event.controllerIdx}; this.dispatchEventAndSound(__reg3); } function handleItemClick(event) { var __reg2 = event.target.index; if (isNaN(__reg2)) { return undefined; } this.selectedIndex = __reg2; this.dispatchItemEvent(event); } } ================================================ FILE: src/CLIK/gfx/controls/OptionStepper.as ================================================ class gfx.controls.OptionStepper extends gfx.core.UIComponent { var soundMap = {theme: "default", focusIn: "focusIn", focusOut: "focusOut", change: "change"}; var _selectedIndex:Number = 0; var _labelField:String = "label"; var __height:Number; var __width:Number; var _dataProvider; var _disabled; var _focused; var _labelFunction; var _name; var constraints; var dispatchEvent; var focusEnabled; var gotoAndPlay; var initialized; var nextBtn; var prevBtn; var selectedItem; var sizeIsInvalid; var tabChildren; var tabEnabled; var textField; var validateNow; function OptionStepper() { super(); tabChildren = false; focusEnabled = tabEnabled = !_disabled; dataProvider = []; } function get disabled() { return _disabled; } function set disabled(value) { if (_disabled != value) { super.disabled = value; focusEnabled = tabEnabled = !_disabled; gotoAndPlay(_disabled ? "disabled" : (_focused ? "focused" : "default")); if (initialized) { updateAfterStateChange(); prevBtn.disabled = nextBtn.disabled = _disabled; return; } } } function get dataProvider() { return _dataProvider; } function set dataProvider(value) { if (value != _dataProvider) { if (_dataProvider != null) { _dataProvider.removeEventListener("change", this, "onDataChange"); } _dataProvider = value; selectedItem = null; if (_dataProvider != null) { if (value instanceof Array && !value.isDataProvider) { gfx.data.DataProvider.initialize(_dataProvider); } else if (_dataProvider.initialize != null) { _dataProvider.initialize(this); } _dataProvider.addEventListener("change", this, "onDataChange"); updateSelectedItem(); return; } } } function get selectedIndex() { return _selectedIndex; } function set selectedIndex(value) { var __reg2 = Math.max(0, Math.min(_dataProvider.length - 1, value)); if (__reg2 != _selectedIndex) { _selectedIndex = __reg2; updateSelectedItem(); return; } } function get labelField() { return _labelField; } function set labelField(value) { _labelField = value; updateLabel(); } function get labelFunction() { return _labelFunction; } function set labelFunction(value) { _labelFunction = value; updateLabel(); } function itemToLabel(item) { if (item == null) { return ""; } if (_labelFunction == null) { if (_labelField != null && item[_labelField] != null) { return item[_labelField]; } } else { return _labelFunction(item); } return item.toString(); } function invalidateData() { _dataProvider.requestItemAt(_selectedIndex, this, "populateText"); } function handleInput(details, pathToFocus) { var __reg2 = details.value == "keyDown" || details.value == "keyHold"; if ((__reg0 = details.navEquivalent) === gfx.ui.NavigationCode.RIGHT) { if (_selectedIndex < _dataProvider.length - 1) { if (__reg2) { onNext(); } return true; } } else if (__reg0 === gfx.ui.NavigationCode.LEFT) { if (_selectedIndex > 0) { if (__reg2) { onPrev(); } return true; } } else if (__reg0 === gfx.ui.NavigationCode.HOME) { if (!__reg2) { selectedIndex = 0; } return true; } else if (__reg0 === gfx.ui.NavigationCode.END) { if (!__reg2) { selectedIndex = _dataProvider.length - 1; } return true; } return false; } function toString() { return "[Scaleform OptionStepper " + _name + "]"; } function configUI() { super.configUI(); nextBtn.addEventListener("click", this, "onNext"); prevBtn.addEventListener("click", this, "onPrev"); prevBtn.focusTarget = nextBtn.focusTarget = this; prevBtn.tabEnabled = nextBtn.tabEnabled = false; prevBtn.autoRepeat = nextBtn.autoRepeat = true; prevBtn.disabled = nextBtn.disabled = _disabled; constraints = new gfx.utils.Constraints(this, true); constraints.addElement(textField, gfx.utils.Constraints.ALL); updateAfterStateChange(); } function draw() { if (sizeIsInvalid) { _width = __width; _height = __height; } super.draw(); if (constraints != null) { constraints.update(__width, __height); } } function changeFocus() { gotoAndPlay(_disabled ? "disabled" : (_focused ? "focused" : "default")); updateAfterStateChange(); prevBtn.displayFocus = nextBtn.displayFocus = _focused != 0; } function updateAfterStateChange() { validateNow(); updateLabel(); if (constraints != null) { constraints.update(__width, __height); } dispatchEvent({type: "stateChange", state: _disabled ? "disabled" : (_focused ? "focused" : "default")}); } function updateLabel() { if (selectedItem != null) { if (textField != null) { textField.text = itemToLabel(selectedItem); } } } function updateSelectedItem() { invalidateData(); } function populateText(item) { selectedItem = item; updateLabel(); dispatchEvent({type: "change"}); } function onNext(evtObj) { selectedIndex = selectedIndex + 1; } function onPrev(evtObj) { selectedIndex = selectedIndex - 1; } function onDataChange(event) { invalidateData(); } function ToggleNextOrAround(evtObj) { if(_selectedIndex < _dataProvider.length - 1) { selectedIndex = selectedIndex + 1; } else { selectedIndex = 0; } } } ================================================ FILE: src/CLIK/gfx/controls/RadioButton.as ================================================ dynamic class gfx.controls.RadioButton extends gfx.controls.Button { var _group; var _name; function RadioButton() { super(); if (this._group == null) { this.group = "buttonGroup"; } } function toString() { return "[Scaleform RadioButton " + this._name + "]"; } function configUI() { super.configUI(); } } ================================================ FILE: src/CLIK/gfx/controls/ScrollBar.as ================================================ dynamic class gfx.controls.ScrollBar extends gfx.controls.ScrollIndicator { var trackScrollPageSize: Number = 1; var _trackMode: String = "scrollPage"; var trackScrollPosition: Number = -1; var __height; var __width; var _disabled; var _name; var _position; var _rotation; var _scrollTarget; var _ymouse; var constraints; var direction; var downArrow; var dragOffset; var gotoAndPlay; var initialized; var invalidate; var isDragging; var maxPosition; var minPosition; var offsetBottom; var offsetTop; var onMouseMove; var onMouseUp; var onRelease; var pageScrollSize; var pageSize; var setScrollProperties; var thumb; var track; var trackDragMouseIndex; var upArrow; function ScrollBar() { super(); } function get disabled() { return this._disabled; } function set disabled(value) { if (this._disabled != value) { super.disabled = value; this.gotoAndPlay(this._disabled ? "disabled" : "default"); if (this.initialized) { this.upArrow.disabled = this._disabled; this.downArrow.disabled = this._disabled; this.track.disabled = this._disabled; } return; } } function get position() { return super.position; } function set position(value) { value = Math.round(value); if (value != this.position) { super.position = value; this.updateScrollTarget(); return; } } function get trackMode() { return this._trackMode; } function set trackMode(value) { if (value != this._trackMode) { this._trackMode = value; if (this.initialized) { this.track.autoRepeat = this.trackMode == "scrollPage"; } return; } } function get availableHeight() { return this.track.height - this.thumb.height + this.offsetBottom + this.offsetTop; } function toString() { return "[Scaleform ScrollBar " + this._name + "]"; } function configUI() { super.configUI(); delete this.onRelease; if (this.upArrow) { this.upArrow.addEventListener("click", this, "scrollUp"); this.upArrow.useHandCursor = !this._disabled; this.upArrow.disabled = this._disabled; this.upArrow.focusTarget = this; this.upArrow.autoRepeat = true; } if (this.downArrow) { this.downArrow.addEventListener("click", this, "scrollDown"); this.downArrow.useHandCursor = !this._disabled; this.downArrow.disabled = this._disabled; this.downArrow.focusTarget = this; this.downArrow.autoRepeat = true; } this.thumb.addEventListener("press", this, "beginDrag"); this.thumb.useHandCursor = !this._disabled; this.thumb.lockDragStateChange = true; this.track.addEventListener("press", this, "beginTrackScroll"); this.track.addEventListener("click", this, "trackScroll"); this.track.disabled = this._disabled; this.track.autoRepeat = this.trackMode == "scrollPage"; Mouse.addListener(this); var __reg3 = this._rotation; this._rotation = 0; this.constraints = new gfx.utils.Constraints(this); if (this.downArrow) { this.constraints.addElement(this.downArrow, gfx.utils.Constraints.BOTTOM); } this.constraints.addElement(this.track, gfx.utils.Constraints.TOP | gfx.utils.Constraints.BOTTOM); this._rotation = __reg3; } function draw() { if (this.direction == "horizontal") { this.constraints.update(this.__height, this.__width); } else { this.constraints.update(this.__width, this.__height); } if (this._scrollTarget instanceof TextField) { this.setScrollProperties(this._scrollTarget.bottomScroll - this._scrollTarget.scroll, 1, this._scrollTarget.maxscroll); return; } this.updateThumb(); } function updateThumb() { if (!this.initialized) { this.invalidate(); return undefined; } if (this._disabled) { return undefined; } var __reg5 = Math.max(1, this.maxPosition - this.minPosition + this.pageSize); var __reg4 = this.track.height + this.offsetTop + this.offsetBottom; var __reg6 = __reg4; this.thumb.height = Math.max(10, Math.min(__reg4, this.pageSize / __reg5 * __reg6)); var __reg2 = (this._position - this.minPosition) / (this.maxPosition - this.minPosition); var __reg3 = this.track._y - this.offsetTop; var __reg7 = __reg2 * this.availableHeight + __reg3; this.thumb._y = Math.max(__reg3, Math.min(this.track._y + this.track.height - this.thumb.height + this.offsetBottom, __reg7)); this.thumb.visible = !(isNaN(__reg2) || this.maxPosition <= 0 || this.maxPosition == Infinity); if (this.thumb.visible) { this.track.disabled = false; if (this.upArrow) { if (this._position == this.minPosition) { this.upArrow.disabled = true; } else { this.upArrow.disabled = false; } } if (this.downArrow) { if (this._position == this.maxPosition) { this.downArrow.disabled = true; } else { this.downArrow.disabled = false; } } return; } if (this.upArrow) { this.upArrow.disabled = true; } if (this.downArrow) { this.downArrow.disabled = true; } this.track.disabled = true; } function scrollUp() { this.position = this.position - this.pageScrollSize; } function scrollDown() { this.position = this.position + this.pageScrollSize; } function beginDrag() { if (this.isDragging != true) { this.isDragging = true; this.onMouseMove = this.doDrag; this.onMouseUp = this.endDrag; this.dragOffset = {y: this._ymouse - this.thumb._y}; } } function doDrag() { var __reg2 = (this._ymouse - this.dragOffset.y - this.track._y) / this.availableHeight; this.position = this.minPosition + __reg2 * (this.maxPosition - this.minPosition); } function endDrag() { delete this.onMouseUp; delete this.onMouseMove; this.isDragging = false; if (this.trackDragMouseIndex != undefined) { if (this.thumb.hitTest(_root._xmouse, _root._ymouse)) { this.thumb.onRelease(this.trackDragMouseIndex); } else { this.thumb.onReleaseOutside(this.trackDragMouseIndex); } } delete this.trackDragMouseIndex; } function beginTrackScroll(e) { var __reg2 = (this._ymouse - this.thumb.height / 2 - this.track._y) / this.availableHeight; this.trackScrollPosition = Math.round(__reg2 * (this.maxPosition - this.minPosition) + this.minPosition); if (Key.isDown(16) || this.trackMode == "scrollToCursor") { this.position = this.trackScrollPosition; this.trackDragMouseIndex = e.controllerIdx; this.thumb.onPress(this.trackDragMouseIndex); this.dragOffset = {y: this.thumb.height / 2}; } } function trackScroll() { if (this.isDragging || this.position == this.trackScrollPosition) { return undefined; } var __reg3 = this.position >= this.trackScrollPosition ? 0 - this.trackScrollPageSize : this.trackScrollPageSize; var __reg2 = this.position + __reg3; this.position = __reg3 >= 0 ? Math.min(__reg2, this.trackScrollPosition) : Math.max(__reg2, this.trackScrollPosition); } function updateScrollTarget() { if (this._scrollTarget != null) { if (this._scrollTarget && !this._disabled) { this._scrollTarget.scroll = this._position; } } } function scrollWheel(delta) { this.position = this.position - delta * this.pageScrollSize; } } ================================================ FILE: src/CLIK/gfx/controls/ScrollIndicator.as ================================================ dynamic class gfx.controls.ScrollIndicator extends gfx.core.UIComponent { var direction: String = "vertical"; var soundMap = {theme: "default", scroll: "scroll"}; var pageScrollSize: Number = 1; var minPosition: Number = 0; var maxPosition: Number = 10; var _position: Number = 5; var offsetTop: Number = 0; var offsetBottom: Number = 0; var isDragging: Boolean = false; var __height; var __width; var _disabled; var _name; var _parent; var _rotation; var _scrollTarget; var dispatchEventAndSound; var focusEnabled; var focusTarget; var initSize; var initialized; var inspectableScrollTarget; var invalidate; var lastVScrollPos; var onRelease; var pageSize; var scrollerIntervalID; var tabChildren; var tabEnabled; var thumb; var track; var useHandCursor; function ScrollIndicator() { super(); this.tabChildren = false; this.focusEnabled = this.tabEnabled = !this._disabled; } function get disabled() { return this._disabled; } function set disabled(value) { if (this._disabled != value) { super.disabled = value; this.focusEnabled = this.tabEnabled = !this._disabled; if (this._scrollTarget) { this.tabEnabled = false; } if (this.initialized) { this.thumb.disabled = this._disabled; } return; } } function setScrollProperties(pageSize, minPosition, maxPosition, pageScrollSize) { this.pageSize = pageSize; if (pageScrollSize != undefined) { this.pageScrollSize = pageScrollSize; } this.minPosition = minPosition; this.maxPosition = maxPosition; this.updateThumb(); } function get position() { return this._position; } function set position(value) { if (value != this._position) { this._position = Math.max(this.minPosition, Math.min(this.maxPosition, value)); this.dispatchEventAndSound({type: "scroll", position: this._position}); this.invalidate(); return; } } function update() { } function get scrollTarget() { return this._scrollTarget; } function set scrollTarget(value) { var __reg2 = this._scrollTarget; this._scrollTarget = value; if (__reg2 && value._parent != __reg2) { __reg2.removeListener(this); if (__reg2.scrollBar != null) { __reg2.scrollBar = null; } this.focusTarget = null; __reg2.noAutoSelection = false; } if (value instanceof gfx.core.UIComponent && value.scrollBar !== null) { value.scrollBar = this; return; } if (this._scrollTarget == null) { this.tabEnabled = true; return; } this._scrollTarget.addListener(this); this._scrollTarget.noAutoSelection = true; this.focusTarget = this._scrollTarget; this.tabEnabled = false; this.onScroller(); } function get availableHeight() { return (this.direction == "horizontal" ? this.__width : this.__height) - this.thumb.height + this.offsetBottom + this.offsetTop; } function toString() { return "[Scaleform ScrollIndicator " + this._name + "]"; } function configUI() { super.configUI(); if (this.track == null) { this.track = new gfx.controls.Button(); } this.thumb.focusTarget = this; this.track.focusTarget = this; this.thumb.disabled = this._disabled; this.onRelease = function () { } ; this.useHandCursor = false; this.initSize(); this.direction = this._rotation == 0 ? "vertical" : "horizontal"; if (this.inspectableScrollTarget != null) { var __reg3 = this._parent[this.inspectableScrollTarget]; if (__reg3 != null) { this.scrollTarget = __reg3; } this.inspectableScrollTarget = null; } } function draw() { this.track._height = this.direction == "horizontal" ? this.__width : this.__height; if (this._scrollTarget instanceof TextField) { this.setScrollProperties(this._scrollTarget.bottomScroll - this._scrollTarget.scroll, 1, this._scrollTarget.maxscroll); return; } this.updateThumb(); } function updateThumb() { if (!this.thumb.initialized) { this.invalidate(); return undefined; } if (this._disabled) { return undefined; } var __reg5 = Math.max(1, this.maxPosition - this.minPosition + this.pageSize); var __reg4 = (this.direction == "horizontal" ? this.__width : this.__height) + this.offsetTop + this.offsetBottom; this.thumb.height = Math.max(10, this.pageSize / __reg5 * __reg4); var __reg2 = (this.position - this.minPosition) / (this.maxPosition - this.minPosition); var __reg3 = 0 - this.offsetTop; var __reg6 = __reg2 * this.availableHeight + __reg3; this.thumb._y = Math.max(__reg3, Math.min(__reg4 - this.offsetTop, __reg6)); this.thumb.visible = !(isNaN(__reg2) || this.maxPosition == 0); } function onScroller() { if (this.isDragging) { return undefined; } if (this.lastVScrollPos == this._scrollTarget.scroll) { delete this.lastVScrollPos; return undefined; } this.setScrollProperties(this._scrollTarget.bottomScroll - this._scrollTarget.scroll, 1, this._scrollTarget.maxscroll); this.position = this._scrollTarget.scroll; this.lastVScrollPos = this._scrollTarget.scroll; if (this.scrollerIntervalID == undefined) { this.scrollerIntervalID = setInterval(this, "scrollerDelayUpdate", 10); } } function scrollerDelayUpdate() { this.onScroller(); clearInterval(this.scrollerIntervalID); delete this.scrollerIntervalID; } } ================================================ FILE: src/CLIK/gfx/controls/ScrollingList.as ================================================ dynamic class gfx.controls.ScrollingList extends gfx.controls.CoreList { var wrapping: String = "normal"; var autoRowCount: Boolean = false; var _scrollPosition: Number = 0; var totalRenderers: Number = 0; var autoScrollBar: Boolean = false; var margin: Number = 1; var paddingTop: Number = 0; var paddingBottom: Number = 0; var paddingLeft: Number = 0; var paddingRight: Number = 0; var thumbOffsetTop: Number = 0; var thumbOffsetBottom: Number = 0; var thumbSizeFactor: Number = 1; var __height; var __width; var _dataProvider; var _disabled; var _focused; var _height; var _name; var _parent; var _rowHeight; var _scrollBar; var _selectedIndex; var _width; var _xscale; var _yscale; var container; var createItemRenderer; var drawRenderers; var externalRenderers; var focusEnabled; var gotoAndPlay; var initialized; var inspectableScrollBar; var invalidate; var itemToLabel; var renderers; var sizeIsInvalid; var tabEnabled; function ScrollingList() { super(); } function get scrollBar() { return this._scrollBar; } function set scrollBar(value) { if (!this.initialized) { this.inspectableScrollBar = value; return; } if (this._scrollBar != null) { this._scrollBar.removeEventListener("scroll", this, "handleScroll"); this._scrollBar.removeEventListener("change", this, "handleScroll"); this._scrollBar.focusTarget = null; if (this.autoScrollBar) { this._scrollBar.removeMovieClip(); } } this.autoScrollBar = false; if (typeof value == "string") { this._scrollBar = MovieClip(this._parent[value.toString()]); if (this._scrollBar == null) { this._scrollBar = this.container.attachMovie(value.toString(), "_scrollBar", 1000, {offsetTop: this.thumbOffsetTop, offsetBottom: this.thumbOffsetBottom}); if (this._scrollBar != null) { this.autoScrollBar = true; } } } else { this._scrollBar = MovieClip(value); } this.invalidate(); if (this._scrollBar != null) { if (this._scrollBar.setScrollProperties == null) { this._scrollBar.addEventListener("change", this, "handleScroll"); } else { this._scrollBar.addEventListener("scroll", this, "handleScroll"); } this._scrollBar.focusTarget = this; this._scrollBar.tabEnabled = false; this.updateScrollBar(); return; } } function get rowHeight() { return this._rowHeight; } function set rowHeight(value) { if (value == 0) { value = null; } this._rowHeight = value; this.invalidate(); } function get scrollPosition() { return this._scrollPosition; } function set scrollPosition(value) { value = Math.max(0, Math.min(this._dataProvider.length - this.totalRenderers, Math.round(value))); if (this._scrollPosition != value) { this._scrollPosition = value; this.invalidateData(); this.updateScrollBar(); return; } } function get selectedIndex() { return this._selectedIndex; } function set selectedIndex(value) { if (value != this._selectedIndex) { var __reg3 = this.getRendererAt(this._selectedIndex); if (__reg3 != null) { __reg3.selected = false; } super.selectedIndex = value; if (this.totalRenderers != 0) { __reg3 = this.getRendererAt(this._selectedIndex); if (__reg3 == null) { this.scrollToIndex(this._selectedIndex); this.getRendererAt(this._selectedIndex).displayFocus = true; } else { __reg3.selected = true; } return; } } } function get disabled() { return this._disabled; } function set disabled(value) { super.disabled = value; if (this.initialized) { this.setState(); } } function scrollToIndex(index) { if (this.totalRenderers != 0) { if (index >= this._scrollPosition && index < this._scrollPosition + this.totalRenderers) { return undefined; } if (index < this._scrollPosition) { this.scrollPosition = index; return; } this.scrollPosition = index - (this.totalRenderers - 1); } } function get rowCount() { return this.totalRenderers; } function set rowCount(value) { var __reg3 = this._rowHeight; if (__reg3 == null) { var __reg2 = this.renderers[0]; if (__reg2 == null) { __reg2 = this.createItemRenderer(0); if (__reg2 == null) { return; } __reg3 = __reg2._height; __reg2.removeMovieClip(); } else { __reg3 = __reg2.height; } if (__reg3 == null || __reg3 == 0) { return; } } this.height = __reg3 * value + this.margin * 2 + this.paddingTop + this.paddingBottom; } function invalidateData() { this._scrollPosition = Math.min(Math.max(0, this._dataProvider.length - this.totalRenderers), this._scrollPosition); this.selectedIndex = Math.min(this._dataProvider.length - 1, this._selectedIndex); this._dataProvider.requestItemRange(this._scrollPosition, Math.min(this._dataProvider.length - 1, this._scrollPosition + this.totalRenderers - 1), this, "populateData"); } function handleInput(details, pathToFocus) { if (pathToFocus == null) { pathToFocus = []; } var __reg3 = this.getRendererAt(this._selectedIndex); if (__reg3 != null && __reg3.handleInput != null) { var __reg6 = __reg3.handleInput(details, pathToFocus.slice(1)); if (__reg6) { return true; } } var __reg2 = details.value == "keyDown" || details.value == "keyHold"; if ((__reg0 = details.navEquivalent) === gfx.ui.NavigationCode.UP) { if (this._selectedIndex > 0) { if (__reg2) { this.selectedIndex = (this.selectedIndex - 1); } return true; } else if (this.wrapping == "stick") { return true; } else if (this.wrapping == "wrap") { if (__reg2) { this.selectedIndex = this._dataProvider.length - 1; } return true; } else { return false; } } else if (__reg0 === gfx.ui.NavigationCode.DOWN) { if (this._selectedIndex < this._dataProvider.length - 1) { if (__reg2) { this.selectedIndex = (this.selectedIndex + 1); } return true; } else if (this.wrapping == "stick") { return true; } else if (this.wrapping == "wrap") { if (__reg2) { this.selectedIndex = 0; } return true; } else { return false; } } else if (__reg0 === gfx.ui.NavigationCode.END) { if (!__reg2) { this.selectedIndex = this._dataProvider.length - 1; } return true; } else if (__reg0 === gfx.ui.NavigationCode.HOME) { if (!__reg2) { this.selectedIndex = 0; } return true; } else if (__reg0 === gfx.ui.NavigationCode.PAGE_UP) { if (__reg2) { this.selectedIndex = Math.max(0, this._selectedIndex - this.totalRenderers); } return true; } else if (__reg0 === gfx.ui.NavigationCode.PAGE_DOWN) { if (__reg2) { this.selectedIndex = Math.min(this._dataProvider.length - 1, this._selectedIndex + this.totalRenderers); } return true; } return false; } function get availableWidth() { return this.autoScrollBar ? this.__width - this._scrollBar._width : this.__width; } function toString() { return "[Scaleform ScrollingList " + this._name + "]"; } function configUI() { super.configUI(); if (this.inspectableScrollBar != "" && this.inspectableScrollBar != null) { this.scrollBar = this.inspectableScrollBar; this.inspectableScrollBar = null; } } function draw() { if (this.sizeIsInvalid) { this._width = this.__width; this._height = this.__height; } if (this.externalRenderers) { this.totalRenderers = this.renderers.length; } else { this.container._xscale = 10000 / this._xscale; this.container._yscale = 10000 / this._yscale; var __reg3 = this._rowHeight; if (__reg3 == null) { var __reg4 = this.createItemRenderer(99); __reg4.enableInitCallback = false; __reg3 = __reg4._height; __reg4.removeMovieClip(); } var __reg5 = this.margin * 2 + this.paddingTop + this.paddingBottom; this.totalRenderers = Math.max(0, (this.__height - __reg5 + 0.05) / __reg3 >> 0); this.drawRenderers(this.totalRenderers); this.drawLayout(this.availableWidth, __reg3); } this.updateScrollBar(); this.invalidateData(); this.setState(); super.draw(); } function drawLayout(rendererWidth, rendererHeight) { var __reg5 = this.paddingLeft + this.paddingRight + this.margin * 2; rendererWidth = rendererWidth - __reg5; var __reg2 = 0; while (__reg2 < this.renderers.length) { this.renderers[__reg2]._x = this.margin + this.paddingLeft; this.renderers[__reg2]._y = __reg2 * rendererHeight + this.margin + this.paddingTop; this.renderers[__reg2].setSize(rendererWidth, rendererHeight); ++__reg2; } this.drawScrollBar(); } function drawScrollBar() { if (this.autoScrollBar) { this._scrollBar._x = this.__width - this._scrollBar._width - this.margin; this._scrollBar._y = this.margin; this._scrollBar.height = this.__height - this.margin * 2; } } function changeFocus() { super.changeFocus(); this.setState(); var __reg3 = this.getRendererAt(this._selectedIndex); if (__reg3 != null) { __reg3.displayFocus = this._focused; } } function populateData(data) { var __reg2 = 0; while (__reg2 < this.renderers.length) { var __reg4 = this.renderers[__reg2]; var __reg3 = this._scrollPosition + __reg2; this.renderers[__reg2].setListData(__reg3, this.itemToLabel(data[__reg2]), this._selectedIndex == __reg3); __reg4.setData(data[__reg2]); ++__reg2; } this.updateScrollBar(); } function handleScroll(event) { var __reg2 = event.target.position; if (isNaN(__reg2)) { return undefined; } this.scrollPosition = __reg2; } function updateScrollBar() { var __reg2 = Math.max(0, this.dataProvider.length - this.totalRenderers); if (this._scrollBar.setScrollProperties == null) { this._scrollBar.minimum = 0; this._scrollBar.maximum = __reg2; } else { this._scrollBar.setScrollProperties(this.totalRenderers * this.thumbSizeFactor, 0, __reg2); } this._scrollBar.position = this._scrollPosition; this._scrollBar.trackScrollPageSize = Math.max(1, this.totalRenderers); } function getRendererAt(index) { return this.renderers[index - this._scrollPosition]; } function scrollWheel(delta) { if (this._disabled) { return undefined; } var __reg2 = this._scrollBar != undefined && this._scrollBar.pageScrollSize != undefined ? this._scrollBar.pageScrollSize : 1; // Version 1.9.26 uses, which seems less safe // var __reg2 = this._scrollBar == undefined ? 1 : this._scrollBar.pageScrollSize; this.scrollPosition = this._scrollPosition - delta * __reg2; } function setState() { this.tabEnabled = this.focusEnabled = !this._disabled; this.gotoAndPlay(this._disabled ? "disabled" : (this._focused ? "focused" : "default")); if (this._scrollBar) { this._scrollBar.disabled = this._disabled; this._scrollBar.tabEnabled = false; } var __reg2 = 0; for (;;) { if (__reg2 >= this.renderers.length) { return; } this.renderers[__reg2].disabled = this._disabled; this.renderers[__reg2].tabEnabled = false; ++__reg2; } } } ================================================ FILE: src/CLIK/gfx/controls/Slider.as ================================================ dynamic class gfx.controls.Slider extends gfx.core.UIComponent { var liveDragging: Boolean = false; var state: String = "default"; var soundMap = {theme: "default", focusIn: "focusIn", focusOut: "focusOut", change: "change"}; var _minimum: Number = 0; var _maximum: Number = 10; var _value: Number = 0; var _snapInterval: Number = 1; var _snapping: Boolean = false; var trackPressed: Boolean = false; var thumbPressed: Boolean = false; var offsetLeft: Number = 0; var offsetRight: Number = 0; var __height; var __width; var _disabled; var _focused; var _name; var _xmouse; var constraints; var dispatchEventAndSound; var dragOffset; var focusEnabled; var gotoAndPlay; var initSize; var initialized; var invalidate; var onMouseMove; var onMouseUp; var tabChildren; var tabEnabled; var thumb; var track; var trackDragMouseIndex; function Slider() { super(); this.tabChildren = false; this.focusEnabled = this.tabEnabled = !this._disabled; } function get maximum() { return this._maximum; } function set maximum(value) { this._maximum = value; this.invalidate(); } function get minimum() { return this._minimum; } function set minimum(value) { this._minimum = value; this.invalidate(); } function get value() { return this._value; } function set value(value) { this._value = this.lockValue(value); this.invalidate(); } function get disabled() { return this._disabled; } function set disabled(value) { if (this._disabled != value) { super.disabled = value; this.focusEnabled = this.tabEnabled = !this._disabled; if (this.initialized) { this.thumb.disabled = this.track.disabled = this._disabled; this.invalidate(); return; } } } function get position() { return this._value; } function set position(value) { this.value = value; } function get snapping() { return this._snapping; } function set snapping(value) { this._snapping = value; this.invalidate(); } function get snapInterval() { return this._snapInterval; } function set snapInterval(value) { this._snapInterval = value; this.invalidate(); } function handleInput(details, pathToFocus) { var __reg2 = details.value == "keyDown" || details.value == "keyHold"; if ((__reg0 = details.navEquivalent) === gfx.ui.NavigationCode.RIGHT) { if (__reg2) { this.value = this.value + this._snapInterval; this.dispatchEventAndSound({type: "change"}); } } else if (__reg0 === gfx.ui.NavigationCode.LEFT) { if (__reg2) { this.value = this.value - this._snapInterval; this.dispatchEventAndSound({type: "change"}); } } else if (__reg0 === gfx.ui.NavigationCode.HOME) { if (!__reg2) { this.value = this.minimum; this.dispatchEventAndSound({type: "change"}); } } else if (__reg0 === gfx.ui.NavigationCode.END) { if (!__reg2) { this.value = this.maximum; this.dispatchEventAndSound({type: "change"}); } } else { return false; } return true; } function toString() { return "[Scaleform Slider " + this._name + "]"; } function configUI() { this.thumb.addEventListener("press", this, "beginDrag"); this.track.addEventListener("press", this, "trackPress"); this.thumb.focusTarget = this.track.focusTarget = this; this.thumb.disabled = this.track.disabled = this._disabled; this.thumb.lockDragStateChange = true; this.initSize(); this.constraints = new gfx.utils.Constraints(this); this.constraints.addElement(this.track, gfx.utils.Constraints.LEFT | gfx.utils.Constraints.RIGHT); Mouse.addListener(this); } function draw() { this.gotoAndPlay(this._disabled ? "disabled" : (this._focused ? "focused" : "default")); if (!this._disabled) { if (!this.thumbPressed) { this.thumb.displayFocus = this._focused != 0; } if (!this.trackPressed) { this.track.displayFocus = this._focused != 0; } } this.constraints.update(this.__width, this.__height); this.updateThumb(); } function changeFocus() { this.invalidate(); } function updateThumb() { if (this._disabled) { return undefined; } var __reg2 = this.__width - this.offsetLeft - this.offsetRight; this.thumb._x = (this._value - this._minimum) / (this._maximum - this._minimum) * __reg2 - this.thumb._width / 2 + this.offsetLeft; } function beginDrag(event) { this.thumbPressed = true; Selection.setFocus(this.thumb, event.controllerIdx); this.dragOffset = {x: this._xmouse - this.thumb._x - this.thumb._width / 2}; this.onMouseMove = this.doDrag; this.onMouseUp = this.endDrag; } function doDrag() { var __reg3 = this._xmouse - this.dragOffset.x; var __reg4 = this.__width - this.offsetLeft - this.offsetRight; var __reg2 = this.lockValue((__reg3 - this.offsetLeft) / __reg4 * (this._maximum - this._minimum) + this._minimum); this.updateThumb(); if (this.value != __reg2) { this._value = __reg2; if (this.liveDragging) { this.dispatchEventAndSound({type: "change"}); } } } function endDrag() { delete this.onMouseUp; delete this.onMouseMove; if (!this.liveDragging) { this.dispatchEventAndSound({type: "change"}); } if (this.trackDragMouseIndex != undefined) { if (this.thumb.hitTest(_root._xmouse, _root._ymouse)) { this.thumb.onRelease(this.trackDragMouseIndex); } else { this.thumb.onReleaseOutside(this.trackDragMouseIndex); } } delete this.trackDragMouseIndex; this.thumbPressed = false; this.trackPressed = false; this.invalidate(); } function trackPress(e) { this.trackPressed = true; Selection.setFocus(this.track, e.controllerIdx); var __reg3 = this.__width - this.offsetLeft - this.offsetRight; var __reg2 = this.lockValue((this._xmouse - this.offsetLeft) / __reg3 * (this._maximum - this._minimum) + this._minimum); if (this.value != __reg2) { this.value = __reg2; if (this.liveDragging) { this.dispatchEventAndSound({type: "change"}); } this.trackDragMouseIndex = e.controllerIdx; this.thumb.onPress(this.trackDragMouseIndex); this.dragOffset = {x: 0}; } } function lockValue(value) { value = Math.max(this._minimum, Math.min(this._maximum, value)); if (!this.snapping) { return value; } return Math.round(value / this.snapInterval) * this.snapInterval; } function scrollWheel(delta) { if (this._focused) { this.value = this.value - delta * this._snapInterval; this.dispatchEventAndSound({type: "change"}); } } } ================================================ FILE: src/CLIK/gfx/controls/TextArea.as ================================================ dynamic class gfx.controls.TextArea extends gfx.controls.TextInput { var soundMap = {theme: "default", focusIn: "focusIn", focusOut: "focusOut", textChange: "textChange", scroll: "scroll"}; var _scrollPolicy: String = "auto"; var _position: Number = 1; var maxscroll: Number = 1; var autoScrollBar: Boolean = false; var resetScrollPosition: Boolean = false; var __height; var __width; var _disabled; var _editable; var _name; var _parent; var _scrollBar; var _xscale; var _yscale; var changeLock; var constraints; var container; var createEmptyMovieClip; var dispatchEventAndSound; var initialized; var inspectableScrollBar; var textField; function TextArea() { super(); } function get position() { return this._position; } function set position(value) { this._position = value; this.textField.scroll = this._position; } function get scrollPolicy() { return this._scrollPolicy; } function set scrollPolicy(value) { this._scrollPolicy = value; this.updateScrollBar(); } function get scrollBar() { return this._scrollBar; } function set scrollBar(value) { if (!this.initialized) { this.inspectableScrollBar = value; return; } if (this._scrollBar != value) { if (this._scrollBar != null) { this._scrollBar.scrollTarget = null; this._scrollBar.focusTarget = null; this._scrollBar.removeEventListener("scroll", this, "handleScroll"); if (this.autoScrollBar) { this._scrollBar.removeMovieClip(); } } this.autoScrollBar = false; if (typeof value == "string") { this._scrollBar = MovieClip(this._parent[value.toString()]); if (this._scrollBar == null) { this._scrollBar = this.container.attachMovie(value.toString(), "_scrollBar", 1000, {_visible: false}); if (this._scrollBar != null) { this.autoScrollBar = true; } } } else { this._scrollBar = MovieClip(value); } if (this._scrollBar != null) { this._scrollBar.focusTarget = this; this._scrollBar.scrollTarget = this.textField; this.maxscroll = this.textField.maxscroll; this.updateScrollBar(); this.changeLock = true; this.onChanged(); this.changeLock = false; return; } } } function get disabled() { return this._disabled; } function set disabled(value) { super.disabled = value; this.updateScrollBar(); } function toString() { return "[Scaleform TextArea " + this._name + "]"; } function handleInput(details, pathToFocus) { if (details.value != "keyDown" && details.value != "keyHold") { return false; } var __reg2 = details.controllerIdx; if (Selection.getFocus(__reg2) == null) { Selection.setFocus(this.textField, __reg2); return true; } if (this._editable) { return false; } if ((__reg0 = details.navEquivalent) === gfx.ui.NavigationCode.UP) { if (this.position == 1) { return false; } this.position = Math.max(1, this.position - 1); return true; } else if (__reg0 === gfx.ui.NavigationCode.DOWN) { if (this.position == this.maxscroll) { return false; } this.position = Math.min(this.maxscroll, this.position + 1); return true; } else if (__reg0 === gfx.ui.NavigationCode.END) { this.position = this.maxscroll; return true; } else if (__reg0 === gfx.ui.NavigationCode.HOME) { this.position = 1; return true; } else if (__reg0 === gfx.ui.NavigationCode.PAGE_UP) { var __reg4 = this.textField.bottomScroll - this.textField.scroll; this.position = Math.max(1, this.position - __reg4); return true; } else if (__reg0 === gfx.ui.NavigationCode.PAGE_DOWN) { __reg4 = this.textField.bottomScroll - this.textField.scroll; this.position = Math.min(this.maxscroll, this.position + __reg4); return true; } return false; } function configUI() { super.configUI(); Mouse.addListener(this); this.container = this.createEmptyMovieClip("container", 1); this.container.scale9Grid = new flash.geom.Rectangle(20, 20, 1, 1); if (this.inspectableScrollBar != "") { this.scrollBar = this.inspectableScrollBar; this.inspectableScrollBar = null; } } function draw() { super.draw(); this.container._xscale = 10000 / this._xscale; this.container._yscale = 10000 / this._yscale; if (this.autoScrollBar) { this._scrollBar._x = this.__width - this._scrollBar._width; this._scrollBar.height = this.__height - 1; } } function updateText() { super.updateText(); this.updateScrollBar(); } function updateTextField() { this.resetScrollPosition = true; super.updateTextField(); if (this.textField != null) { if (this._scrollBar != null) { this._scrollBar.scrollTarget = this.textField; } } } function updateScrollBar() { this.maxscroll = this.textField.maxscroll; if (this._scrollBar != undefined) { var __reg2 = this.constraints.getElement(this.textField); if (this._scrollPolicy == "on" || (this._scrollPolicy == "auto" && this.textField.maxscroll > 1)) { if (this.autoScrollBar && !this._scrollBar.visible) { if (__reg2 != null) { __reg2.metrics.right = __reg2.metrics.right + this._scrollBar._width; this.constraints.update(this.__width, this.__height); } this.maxscroll = this.textField.maxscroll; } this._scrollBar.visible = true; } if (this._scrollPolicy == "off" || (this._scrollPolicy == "auto" && this.textField.maxscroll == 1)) { if (this.autoScrollBar && this._scrollBar.visible) { if (__reg2 != null) { __reg2.metrics.right = __reg2.metrics.right - this._scrollBar._width; this.constraints.update(this.__width, this.__height); } } this._scrollBar.visible = false; } if (this._scrollBar.disabled != this._disabled) { this._scrollBar.disabled = this._disabled; } } } function onChanged(target) { if (this.maxscroll != this.textField.maxscroll) { this.updateScrollBar(); } super.onChanged(target); } function onScroller() { if (this.resetScrollPosition) { this.textField.scroll = this._position; } else { this._position = this.textField.scroll; } this.resetScrollPosition = false; this.dispatchEventAndSound({type: "scroll"}); } function scrollWheel(delta) { this.position = Math.max(1, Math.min(this.maxscroll, this._position - delta)); } } ================================================ FILE: src/CLIK/gfx/controls/TextInput.as ================================================ dynamic class gfx.controls.TextInput extends gfx.core.UIComponent { var defaultText: String = ""; var soundMap = {theme: "default", focusIn: "focusIn", focusOut: "focusOut", textChange: "textChange"}; var _text: String = ""; var _maxChars: Number = 0; var _editable: Boolean = true; var actAsButton: Boolean = false; var hscroll: Number = 0; var changeLock: Boolean = false; var __height; var __width; var _disabled; var _focused; var _height; var _name; var _password; var _selectable; var _width; var constraints; var defaultTextFormat; var dispatchEvent; var dispatchEventAndSound; var focusEnabled; var gotoAndPlay; var initialized; var isHtml; var onPress; var onRollOut; var onRollOver; var sizeIsInvalid; var tabEnabled; var textField; function TextInput() { super(); this.tabEnabled = !this._disabled; this.focusEnabled = !this._disabled; this.defaultTextFormat = this.textField.getNewTextFormat(); this.defaultTextFormat.italic = true; this.defaultTextFormat.color = 11184810; } function get textID() { return null; } function set textID(value) { if (value != "") { this.text = gfx.utils.Locale.getTranslatedString(value); } } function get text() { return this._text; } function set text(value) { this._text = value; this.isHtml = false; this.updateText(); } function get htmlText() { return this._text; } function set htmlText(value) { this._text = value; this.isHtml = true; this.updateText(); } function get editable() { return this._editable; } function set editable(value) { this._editable = value; this.tabEnabled = !this._disabled && !this._editable; this.updateTextField(); } function get password() { return this.textField.password; } function set password(value) { this._password = this.textField.password = value; } function get maxChars() { return this._maxChars; } function set maxChars(value) { this._maxChars = this.textField.maxChars = value; } function get disabled() { return this._disabled; } function set disabled(value) { super.disabled = value; this.tabEnabled = !this._disabled; this.focusEnabled = !this._disabled; if (this.initialized) { this.setMouseHandlers(); this.setState(); this.updateTextField(); } } function appendText(text) { this._text = this._text + text; if (this.isHtml) { this.textField.html = false; } this.isHtml = false; this.textField.appendText(text); } function appendHtml(text) { this._text = this._text + text; if (!this.isHtml) { this.textField.html = true; } this.isHtml = true; this.textField.appendHtml(text); } function get length() { return this.textField.length; } function handleInput(details, pathToFocus) { if (details.value != "keyDown" && details.value != "keyHold") { return false; } var __reg2 = details.controllerIdx; if (Selection.getFocus(__reg2) != null) { return false; } Selection.setFocus(this.textField, __reg2); return true; } function toString() { return "[Scaleform TextInput " + this._name + "]"; } function configUI() { super.configUI(); this.constraints = new gfx.utils.Constraints(this, true); this.constraints.addElement(this.textField, gfx.utils.Constraints.ALL); this.setState(); this.updateTextField(); this.setMouseHandlers(); } function setState() { this.gotoAndPlay(this._disabled ? "disabled" : (this._focused ? "focused" : "default")); } function setMouseHandlers() { if (this.actAsButton != false) { if (this._disabled || this._focused) { delete this.onRollOver; delete this.onRollOut; delete this.onPress; return; } if (this._editable) { this.onRollOver = this.handleMouseRollOver; this.onRollOut = this.handleMouseRollOut; this.onPress = this.handleMousePress; } } } function handleMousePress(controllerIdx, keyboardOrMouse, button) { this.dispatchEvent({type: "press", controllerIdx: controllerIdx, button: button}); Selection.setFocus(this.textField, controllerIdx); } function handleMouseRollOver(controllerIdx) { this.gotoAndPlay("default"); this.gotoAndPlay("over"); if (this.constraints) { this.constraints.update(this.__width, this.__height); } this.updateTextField(); this.dispatchEvent({type: "rollOver", controllerIdx: controllerIdx}); } function handleMouseRollOut(controllerIdx) { this.gotoAndPlay("default"); this.gotoAndPlay("out"); if (this.constraints) { this.constraints.update(this.__width, this.__height); } this.updateTextField(); this.dispatchEvent({type: "rollOut", controllerIdx: controllerIdx}); } function draw() { if (this.sizeIsInvalid) { this._width = this.__width; this._height = this.__height; } super.draw(); this.constraints.update(this.__width, this.__height); } function changeFocus() { this.tabEnabled = !this._disabled; if (!this._focused) { this.hscroll = this.textField.hscroll; } this.setState(); if (this.constraints) { this.constraints.update(this.__width, this.__height); } this.updateTextField(); if (this._focused && this.textField.type == "input") { this.tabEnabled = false; var __reg3 = Selection.getFocusBitmask(this); var __reg2 = 0; while (__reg2 < System.capabilities.numControllers) { if ((__reg3 >> __reg2 & 1) != 0) { Selection.setFocus(this.textField, __reg2); if (this.textField.noAutoSelection) { Selection.setSelection(this.textField.htmlText.length, this.textField.htmlText.length, __reg2); } else { Selection.setSelection(0, this.textField.htmlText.length, __reg2); } } ++__reg2; } } this.setMouseHandlers(); this.textField.hscroll = this.hscroll; } function updateText() { if (this._text != "") { if (this.isHtml) { this.textField.html = true; this.textField.htmlText = this._text; } else { this.textField.html = false; this.textField.text = this._text; } return; } this.textField.text = ""; if (!this._focused && this.defaultText != "") { this.textField.text = this.defaultText; this.textField.setTextFormat(this.defaultTextFormat); } } function updateTextField() { if (this.textField != null) { if (!this._selectable) { this._selectable = this.textField.selectable; } this.updateText(); this.textField.maxChars = this._maxChars; this.textField.noAutoSelection = true; this.textField.password = this._password; this.textField.selectable = this._disabled ? false : this._selectable || this._editable; this.textField.type = this._editable && !this._disabled ? "input" : "dynamic"; this.textField.focusTarget = this; this.textField.hscroll = this.hscroll; this.textField.addListener(this); } } function onChanged(target) { if (this.changeLock) { return; } this._text = this.isHtml ? this.textField.htmlText : this.textField.text; this.dispatchEventAndSound({type: "textChange"}); } } ================================================ FILE: src/CLIK/gfx/core/UIComponent.as ================================================ dynamic class gfx.core.UIComponent extends MovieClip { var initialized: Boolean = false; var enableInitCallback: Boolean = true; var soundMap = {theme: "default", focusIn: "focusIn", focusOut: "focusOut"}; var __width: Number = Number.NaN; var __height: Number = Number.NaN; var _disabled: Boolean = false; var _focused: Number = 0; var _displayFocus: Boolean = false; var sizeIsInvalid: Boolean = false; var _height; var _name; var _visible; var _width; var _xscale; var _yscale; var dispatchEvent; var hitTest; var invalidationIntervalID; var useHandCursor; function UIComponent() { super(); gfx.events.EventDispatcher.initialize(this); } function onLoad() { this.onLoadImpl(); } function onLoadImpl() { if (this.initialized) { return undefined; } if (isNaN(this.__width)) { this.__width = this._width; } if (isNaN(this.__height)) { this.__height = this._height; } this.initialized = true; this.configUI(); this.validateNow(); if (this.enableInitCallback && _global.CLIK_loadCallback) { _global.CLIK_loadCallback(this._name, targetPath(this), this); } if (this._focused != 0 && Selection.getFocusBitmask(this) == 0) { var __reg4 = 0; for (;;) { if (__reg4 >= Selection.numFocusGroups) { return; } var __reg6 = (this._focused >> __reg4 & 1) != 0; if (__reg6) { var __reg5 = Selection.getControllerMaskByFocusGroup(__reg4); var __reg3 = 0; while (__reg3 < System.capabilities.numControllers) { if (__reg5 >> __reg3 & true) { gfx.managers.FocusHandler.instance.onSetFocus(null, this, __reg3); } ++__reg3; } } ++__reg4; } } } function onUnload() { if (this.enableInitCallback && _global.CLIK_unloadCallback) { _global.CLIK_unloadCallback(this._name, targetPath(this), this); } } function get disabled() { return this._disabled; } function set disabled(value) { this._disabled = value; super.enabled = !value; this.useHandCursor = !value; this.invalidate(); } function get visible() { return this._visible; } function set visible(value) { if (this._visible != value) { this._visible = value; if (this.initialized) { var __reg3 = value ? "show" : "hide"; this.dispatchEvent({type: __reg3}); return; } } } function get width() { return this.__width; } function set width(value) { this.setSize(value, this.__height || this._height); } function get height() { return this.__height; } function set height(value) { this.setSize(this.__width || this._width, value); } function setSize(width, height) { if (this.__width == width && this.__height == height) { return undefined; } this.__width = width; this.__height = height; this.sizeIsInvalid = true; this.invalidate(); } function get focused() { return this._focused; } function set focused(value) { if (value != this._focused) { this._focused = value; var __reg3 = 0; while (__reg3 < Selection.numFocusGroups) { var __reg6 = (this._focused >> __reg3 & 1) != 0; if (__reg6) { __reg5 = Selection.getControllerMaskByFocusGroup(__reg3); __reg2 = 0; while (__reg2 < System.capabilities.numControllers) { __reg4 = (__reg5 >> __reg2 & 1) != 0; if (__reg4 && Selection.getFocus(__reg2) != targetPath(this)) { Selection.setFocus(this, __reg2); } ++__reg2; } } else { var __reg5 = Selection.getControllerMaskByFocusGroup(__reg3); var __reg2 = 0; while (__reg2 < System.capabilities.numControllers) { var __reg4 = (__reg5 >> __reg2 & 1) != 0; if (__reg4 && Selection.getFocus(__reg2) == targetPath(this)) { Selection.setFocus(null, __reg2); } ++__reg2; } } ++__reg3; } this.changeFocus(); var __reg8 = value ? "focusIn" : "focusOut"; this.dispatchEventAndSound({type: __reg8}); return; } } function get displayFocus() { return this._displayFocus; } function set displayFocus(value) { if (value != this._displayFocus) { this._displayFocus = value; this.changeFocus(); return; } } function handleInput(details, pathToFocus) { if (pathToFocus && pathToFocus.length > 0) { var __reg2 = pathToFocus[0]; if (__reg2.handleInput) { var __reg3 = __reg2.handleInput(details, pathToFocus.slice(1)); if (__reg3) { return __reg3; } } } return false; } function invalidate() { if (this.invalidationIntervalID) { return undefined; } this.invalidationIntervalID = setInterval(this, "validateNow", 1); } function validateNow() { clearInterval(this.invalidationIntervalID); delete this.invalidationIntervalID; this.draw(); this.sizeIsInvalid = false; } function toString() { return "[Scaleform UIComponent " + this._name + "]"; } function dispatchEventToGame(event) { flash.external.ExternalInterface.call("__handleEvent", this._name, event); } function configUI() { } function initSize() { var __reg3 = this.__width == 0 ? this._width : this.__width; var __reg2 = this.__height == 0 ? this._height : this.__height; this._xscale = this._yscale = 100; this.setSize(__reg3, __reg2); } function draw() { } function changeFocus() { } function onMouseWheel(delta, target) { if (this.visible && this.hitTest(_root._xmouse, _root._ymouse, true)) { var __reg3 = Mouse.getTopMostEntity(); for (;;) { if (!__reg3) { return; } if (__reg3 == this) { this.scrollWheel(delta <= 0 ? -1 : 1); return; } __reg3 = __reg3._parent; } } } function scrollWheel(delta) { } function dispatchEventAndSound(event) { this.dispatchEvent(event); this.dispatchSound(event); } function dispatchSound(event) { var __reg2 = this.soundMap.theme; var __reg3 = this.soundMap[event.type]; if (__reg2 && __reg3) { this.playSound(__reg3, __reg2); } } function playSound(soundEventName, soundTheme) { if (_global.gfxProcessSound) { if (soundTheme == undefined) { soundTheme = "default"; } _global.gfxProcessSound(this, soundTheme, soundEventName); } } } ================================================ FILE: src/CLIK/gfx/data/DataProvider.as ================================================ dynamic class gfx.data.DataProvider extends Array { var isDataProvider: Boolean = true; var cleanUpEvents; var dispatchEvent; var length; var slice; var splice; function DataProvider(total) { super(); gfx.events.EventDispatcher.initialize(this); } static function initialize(data) { if (gfx.data.DataProvider.instance == undefined) { gfx.data.DataProvider.instance = new gfx.data.DataProvider(); } var __reg3 = ["indexOf", "requestItemAt", "requestItemRange", "invalidate", "toString", "cleanUp", "isDataProvider"]; var __reg2 = 0; while (__reg2 < __reg3.length) { data[__reg3[__reg2]] = gfx.data.DataProvider.instance[__reg3[__reg2]]; ++__reg2; } gfx.events.EventDispatcher.initialize(data); _global.ASSetPropFlags(data, __reg3, 1); _global.ASSetPropFlags(data, "addEventListener,removeEventListener,hasEventListener,removeAllEventListeners,dispatchEvent,dispatchQueue,cleanUpEvents", 1); } function indexOf(value, scope, callBack) { var __reg2 = 0; __reg2 = 0; while (__reg2 < this.length) { if (this[__reg2] == value) { break; } ++__reg2; } var __reg4 = __reg2 == this.length ? -1 : __reg2; if (callBack) { scope[callBack].call(scope, __reg4); } return __reg4; } function requestItemAt(index, scope, callBack) { var __reg2 = this[index]; if (callBack) { scope[callBack].call(scope, __reg2); } return __reg2; } function requestItemRange(startIndex, endIndex, scope, callBack) { var __reg2 = this.slice(startIndex, endIndex + 1); if (callBack) { scope[callBack].call(scope, __reg2); } return __reg2; } function invalidate(length) { this.dispatchEvent({type: "change"}); } function cleanUp() { this.splice(0, this.length); this.cleanUpEvents(); } function toString() { return "[DataProvider (" + this.length + ")]"; } } ================================================ FILE: src/CLIK/gfx/events/EventDispatcher.as ================================================ class gfx.events.EventDispatcher { static var _instance; var _listeners; function EventDispatcher() { } static function initialize(target) { if (gfx.events.EventDispatcher._instance == undefined) { gfx.events.EventDispatcher._instance = new gfx.events.EventDispatcher(); } target.dispatchEvent = gfx.events.EventDispatcher._instance.dispatchEvent; target.dispatchQueue = gfx.events.EventDispatcher._instance.dispatchQueue; target.hasEventListener = gfx.events.EventDispatcher._instance.hasEventListener; target.addEventListener = gfx.events.EventDispatcher._instance.addEventListener; target.removeEventListener = gfx.events.EventDispatcher._instance.removeEventListener; target.removeAllEventListeners = gfx.events.EventDispatcher._instance.removeAllEventListeners; target.cleanUpEvents = gfx.events.EventDispatcher._instance.cleanUpEvents; _global.ASSetPropFlags(target, "dispatchQueue", 1); } static function indexOfListener(listeners, scope, callBack) { var __reg3 = listeners.length; var __reg2 = -1; while (++__reg2 < __reg3) { var __reg1 = listeners[__reg2]; if (__reg1.listenerObject == scope && __reg1.listenerFunction == callBack) { return __reg2; } } return -1; } function addEventListener(event, scope, callBack) { if (this._listeners == undefined) { this._listeners = {}; _global.ASSetPropFlags(this, "_listeners", 1); } var __reg3 = this._listeners[event]; if (__reg3 == undefined) { this._listeners[event] = __reg3 = []; } if (gfx.events.EventDispatcher.indexOfListener(__reg3, scope, callBack) == -1) { __reg3.push({listenerObject: scope, listenerFunction: callBack}); } } function removeEventListener(event, scope, callBack) { var __reg2 = this._listeners[event]; if (__reg2 != undefined) { var __reg3 = gfx.events.EventDispatcher.indexOfListener(__reg2, scope, callBack); if (__reg3 != -1) { __reg2.splice(__reg3, 1); } } } function dispatchEvent(event) { if (event.type != "all") { if (event.target == undefined) { event.target = this; } this.dispatchQueue(this, event); } } function hasEventListener(event) { return this._listeners[event] != null && this._listeners[event].length > 0; } function removeAllEventListeners(event) { if (event == undefined) { delete this._listeners; return; } delete this._listeners[event]; } function dispatchQueue(dispatch, event) { var __reg1 = dispatch._listeners[event.type]; if (__reg1 != undefined) { gfx.events.EventDispatcher.$dispatchEvent(dispatch, __reg1, event); } __reg1 = dispatch._listeners.all; if (__reg1 != undefined) { gfx.events.EventDispatcher.$dispatchEvent(dispatch, __reg1, event); } } static function $dispatchEvent(dispatch, listeners, event) { var __reg7 = listeners.length; var __reg3 = 0; for (;;) { if (__reg3 >= __reg7) { return; } var __reg1 = listeners[__reg3].listenerObject; var __reg5 = typeof __reg1; var __reg2 = listeners[__reg3].listenerFunction; if (__reg2 == undefined) { __reg2 = event.type; } if (__reg5 == "function") { if (__reg1[__reg2] == null) { __reg1.apply(dispatch, [event]); } else { __reg1[__reg2](event); } } else if (__reg1.handleEvent != undefined && __reg2 == undefined) { __reg1.handleEvent(event); } else { __reg1[__reg2](event); } ++__reg3; } } function cleanUp() { this.cleanUpEvents(); } function cleanUpEvents() { this.removeAllEventListeners(); } } ================================================ FILE: src/CLIK/gfx/io/GameDelegate.as ================================================ import flash.external.ExternalInterface; class gfx.io.GameDelegate { static var responseHash = {}; static var callBackHash = {}; static var nextID = 0; static var initialized = false; function GameDelegate() { } static function call(methodName, params, scope, callBack) { if (!initialized) { initialize(); } nextID = ++nextID; var _loc1 = nextID; responseHash[_loc1] = [scope, callBack]; params.unshift(methodName, _loc1); ExternalInterface.call.apply(null, params); delete responseHash[_loc1]; } static function receiveResponse(uid) { var _loc2 = responseHash[uid]; if (_loc2 == null) { return; } // end if var _loc3 = _loc2[0]; var _loc4 = _loc2[1]; _loc3[_loc4].apply(_loc3, arguments.slice(1)); } static function addCallBack(methodName, scope, callBack) { if (!initialized) { initialize(); } // end if callBackHash[methodName] = [scope, callBack]; } static function removeCallBack(methodName) { callBackHash[methodName] = null; } static function receiveCall(methodName) { var _loc2 = callBackHash[methodName]; if (_loc2 == null) { return; } var _loc3 = _loc2[0]; var _loc4 = _loc2[1]; _loc3[_loc4].apply(_loc3, arguments.slice(1)); } static function initialize() { initialized = true; ExternalInterface.addCallback("call", GameDelegate, receiveCall); ExternalInterface.addCallback("respond", GameDelegate, receiveResponse); } } ================================================ FILE: src/CLIK/gfx/managers/FocusHandler.as ================================================ import skyui.util.Debug; dynamic class gfx.managers.FocusHandler { static var _instance = gfx.managers.FocusHandler.instance; var inited: Boolean = false; var actualFocusLookup; var currentFocusLookup; var inputDelegate; function FocusHandler() { Selection.addListener(this); _global.gfxExtensions = 1; Selection.alwaysEnableArrowKeys = true; Selection.disableFocusKeys = true; Selection.disableFocusAutoRelease = true; Selection.disableFocusRolloverEvent = true; _root._focusrect = false; this.currentFocusLookup = []; this.actualFocusLookup = []; } static function get instance() { if (_instance == null) { _instance = new FocusHandler(); } return _instance; } function initialize() { this.inited = true; this.inputDelegate = gfx.managers.InputDelegate.instance; this.inputDelegate.addEventListener("input", this, "handleInput"); } function getFocus(focusIdx: Number): MovieClip { return currentFocusLookup[focusIdx]; } function setFocus(focus: MovieClip, focusIdx: Number): Void { if (!inited) { initialize(); } while (focus.focusTarget != null) { focus = focus.focusTarget; } var actualFocus: MovieClip = this.actualFocusLookup[focusIdx]; var currentFocus: MovieClip = this.currentFocusLookup[focusIdx]; if (currentFocus != focus) { currentFocus.focused = currentFocus.focused & ~(1 << focusIdx); currentFocus = focus; currentFocusLookup[focusIdx] = focus; currentFocus.focused = currentFocus.focused | (1 << focusIdx); } if (actualFocus != currentFocus && !(actualFocus instanceof TextField)) { var controllerMask: Number = Selection.getControllerMaskByFocusGroup(focusIdx); for(var i: Number = 0; i < System.capabilities.numControllers; i++) { var controllerHasIdx: Boolean = (controllerMask >> i & 0x1) != 0; if (controllerHasIdx) { Selection.setFocus(currentFocus, i); } } } } function handleInput(event: Object): Void { // Grab the focus path // It appears controllerIdx is always 0 here. var controllerIdx: Number = event.details.controllerIdx; var focusIdx: Number = Selection.getControllerFocusGroup(controllerIdx); var path: Array = getPathToFocus(focusIdx); // Send the input into the first item in the focus list if possible if (path.length == 0 || path[0].handleInput == null || path[0].handleInput(event.details, path.slice(1)) != true) { // If nothing is going to handle the input Or if the handler returned false... // Perform some default handling on "keyup" if (event.details.value != "keyUp") { // Only deal with input with a navEquivalent (aka keys we understand && will deal with) // Keys that we don't understand will be skipped. var nav = event.details.navEquivalent; if (nav != null) { // Get the thing that is in focus var focusedElem = eval(Selection.getFocus(controllerIdx)); var actualFocus = this.actualFocusLookup[focusIdx]; // If the thing in focus is a text field, try to have it handle the input... // If the input is handled, don't do anything further. if (actualFocus instanceof TextField && focusedElem == actualFocus && this.textFieldHandleInput(nav, controllerIdx)) { return; } // We're going to try to find another thing we can focus on... var dirH = nav == gfx.ui.NavigationCode.LEFT || nav == gfx.ui.NavigationCode.RIGHT; var dirV = nav == gfx.ui.NavigationCode.UP || nav == gfx.ui.NavigationCode.DOWN; var focusContext = focusedElem._parent; var focusMode = "default"; if (dirH || dirV) { var focusProp = dirH ? "focusModeHorizontal" : "focusModeVertical"; while (focusContext) { focusMode = focusContext[focusProp]; if (focusMode && focusMode != "default") { break; } focusContext = focusContext._parent; } } else { focusContext = null; } var newFocus: Object = Selection.findFocus(nav, focusContext, focusMode == "loop", null, false, controllerIdx); if (newFocus) { Selection.setFocus(newFocus, controllerIdx); } } } } } function getPathToFocus(focusIdx) { var __reg5 = this.currentFocusLookup[focusIdx]; var __reg3 = __reg5; var __reg4 = [__reg3]; while (__reg3) { __reg3 = __reg3._parent; if (__reg3.handleInput != null) { __reg4.unshift(__reg3); } if (__reg3 == _root) { break; } } return __reg4; } function onSetFocus(oldFocus, newFocus, controllerIdx) { if (oldFocus instanceof TextField && newFocus == null) { return undefined; } var __reg2 = Selection.getControllerFocusGroup(controllerIdx); var __reg6 = this.actualFocusLookup[__reg2]; if (__reg6 == newFocus) { var __reg4 = newFocus instanceof TextField ? newFocus._parent : newFocus; var __reg5 = __reg4.focused; if (__reg5 & 1 << __reg2 == 0) { __reg4.focused = __reg5 | 1 << __reg2; } } this.actualFocusLookup[__reg2] = newFocus; this.setFocus(newFocus, __reg2); } function textFieldHandleInput(nav, controllerIdx) { var __reg3 = Selection.getCaretIndex(controllerIdx); var __reg4 = Selection.getControllerFocusGroup(controllerIdx); var __reg2 = this.actualFocusLookup[__reg4]; if ((__reg0 = nav) === gfx.ui.NavigationCode.UP) { if (!__reg2.multiline) { return false; } return __reg3 > 0; } else if (__reg0 === gfx.ui.NavigationCode.LEFT) { return __reg3 > 0; } else if (__reg0 === gfx.ui.NavigationCode.DOWN) { if (!__reg2.multiline) { return false; } return __reg3 < TextField(__reg2).length; } else if (__reg0 === gfx.ui.NavigationCode.RIGHT) { return __reg3 < TextField(__reg2).length; } return false; } } ================================================ FILE: src/CLIK/gfx/managers/InputDelegate.as ================================================ /* Class InputDelegate * * This is where keydown/keyup events are normally passed to the UI. * We attach some supplimental information from SKSE, then dispatch * the event to the rest of the UI. * */ import gfx.events.EventDispatcher; import gfx.ui.NavigationCode; import gfx.ui.InputDetails; import skyui.defines.Input; import skyui.util.GlobalFunctions; class gfx.managers.InputDelegate extends EventDispatcher { /* SINGLETON */ private static var _instance: InputDelegate; public static function get instance(): InputDelegate { if (_instance == null) _instance = new InputDelegate(); return _instance; } public function Reset() { _keyRepeatStateLookup = {}; } /* PRIVATE VARIABLES */ private var _keyRepeatStateLookup: Object; private var _keyRepeatSuppressLookup: Object; private var _bEnableControlFixup: Boolean = false; private var _acceptKeycode: Number = -1; /* PROPERTIES */ public var isGamepad: Boolean = false; /* INITIALIZATION */ public function InputDelegate() { super(); Key.addListener(this); _keyRepeatSuppressLookup = {}; _keyRepeatStateLookup = {}; } /* PUBLIC FUNCTIONS */ // Certain menus wont receive navEquiv's, i.e. ENTER for activate in MapMenu // Has to be disabled manually for skse.AllowTextInput public function enableControlFixup(a_bEnabled: Boolean): Void { if (a_bEnabled) _acceptKeycode = GlobalFunctions.getMappedKey("Accept", Input.CONTEXT_MENUMODE, isGamepad); _bEnableControlFixup = a_bEnabled; } public function setKeyRepeat(a_code: Number, a_value, a_controllerIdx: Number): Void { var suppressState = this.getKeyRepeatSuppress(a_controllerIdx); suppressState[a_code] = !a_value; } public function readInput(type, code, scope, callBack) { return null; } public function onKeyDown(a_controllerIdx: Number): Void { var code = Key.getCode(a_controllerIdx); var repeatState = getKeyRepeatState(a_controllerIdx); // We can get multiple keydowns for the same key // Possible outcomes: // - send/passthrough the keydown event // - supress the event // - send a keyheld event if (!repeatState[code]) { handleKeyPress("keyDown", code, a_controllerIdx, skse.GetLastControl(true), skse.GetLastKeycode(true)); repeatState[code] = true; } else { var suppressState = getKeyRepeatSuppress(a_controllerIdx); if (!suppressState[code]) handleKeyPress("keyHold", code, a_controllerIdx, skse.GetLastControl(true), skse.GetLastKeycode(true)); } } public function onKeyUp(a_controllerIdx: Number): Void { // Just send through the keyup event var code = Key.getCode(a_controllerIdx); var repeatState = getKeyRepeatState(a_controllerIdx); repeatState[code] = false; handleKeyPress("keyUp", code, a_controllerIdx, skse.GetLastControl(false), skse.GetLastKeycode(false)); } /* PRIVATE FUNCTIONS */ private function handleKeyPress(a_type: String, a_code: Number, a_controllerIdx: Number, a_control: String, a_skseKeycode: Number): Void { var navEquivalent: String = inputToNav(a_code); if (navEquivalent != null) { switch (navEquivalent) { case NavigationCode.UP: case NavigationCode.DOWN: case NavigationCode.LEFT: case NavigationCode.RIGHT: a_control = null; a_skseKeycode = null; break; } // For != null, attempt fixup? } else if (_bEnableControlFixup) { if (a_skseKeycode == _acceptKeycode) { navEquivalent = NavigationCode.ENTER; } } // Dispatch the event. // By default, FocusHandler is the only listener. var details = new InputDetails("key", a_code, a_type, navEquivalent, a_controllerIdx, a_control, a_skseKeycode); dispatchEvent({type: "input", details: details}); } private function getKeyRepeatState(a_controllerIdx: Number): Object { var obj = this._keyRepeatStateLookup[a_controllerIdx]; if (!obj) { obj = new Object(); _keyRepeatStateLookup[a_controllerIdx] = obj; } return obj; } private function getKeyRepeatSuppress(a_controllerIdx: Number): Object { var obj = _keyRepeatSuppressLookup[a_controllerIdx]; if (!obj) { obj = new Object(); _keyRepeatSuppressLookup[a_controllerIdx] = obj; } return obj; } private function inputToNav(a_code: Number): String { // We're usually given just a number that represents the key. // This function is used to map these key numbers to some symbolic // name so we can deal with the key in a more reasonable manner // in the rest of the code. switch (a_code) { case 38: return NavigationCode.UP; case 40: return NavigationCode.DOWN; case 37: return NavigationCode.LEFT; case 39: return NavigationCode.RIGHT; case 13: return NavigationCode.ENTER; case 8: return NavigationCode.BACK; case 9: return Key.isDown(16) ? NavigationCode.SHIFT_TAB : NavigationCode.TAB; case 36: return NavigationCode.HOME; case 35: return NavigationCode.END; case 34: return NavigationCode.PAGE_DOWN; case 33: return NavigationCode.PAGE_UP; case 27: return NavigationCode.ESCAPE; // TODO: should ignore these if platform != 0 case 96: return NavigationCode.GAMEPAD_A; case 97: return NavigationCode.GAMEPAD_B; case 98: return NavigationCode.GAMEPAD_X; case 99: return NavigationCode.GAMEPAD_Y; case 100: return NavigationCode.GAMEPAD_L1; case 101: return NavigationCode.GAMEPAD_L2; case 102: return NavigationCode.GAMEPAD_L3; case 103: return NavigationCode.GAMEPAD_R1; case 104: return NavigationCode.GAMEPAD_R2; case 105: return NavigationCode.GAMEPAD_R3; case 106: return NavigationCode.GAMEPAD_START; case 107: return NavigationCode.GAMEPAD_BACK; } return null; } } ================================================ FILE: src/CLIK/gfx/ui/InputDetails.as ================================================ class gfx.ui.InputDetails { /* PROPERTIES */ public var code: Number; public var controllerIdx: Number; public var navEquivalent: String; public var type: String; // "key" public var value: String; // "keyDown"/"keyUp" public var control: String; // "Jump" public var skseKeycode: Number; /* INITIALIZATION */ public function InputDetails(a_type: String, a_code: Number, a_value, a_navEquivalent: String, a_controllerIdx: Number, a_control: String, a_skseKeycode: Number) { type = a_type; code = a_code; value = a_value; navEquivalent = a_navEquivalent; controllerIdx = a_controllerIdx; control = a_control; skseKeycode = a_skseKeycode; } /* PUBLIC FUNCTIONS */ public function toString(): String { return ["[InputDelegate", "code=" + code, "type=" + type, "value=" + value, "navEquivalent=" + navEquivalent, "controllerIdx=" + controllerIdx + "]"].toString(); } } ================================================ FILE: src/CLIK/gfx/ui/NavigationCode.as ================================================ class gfx.ui.NavigationCode { static var UP: String = "up"; static var DOWN: String = "down"; static var LEFT: String = "left"; static var RIGHT: String = "right"; static var START: String = "start"; static var BACK: String = "back"; static var GAMEPAD_A: String = "enter-gamepad_A"; static var GAMEPAD_B: String = "escape-gamepad_B"; static var GAMEPAD_X: String = "gamepad_X"; static var GAMEPAD_Y: String = "gamepad_Y"; static var GAMEPAD_L1: String = "gamepad_L1"; static var GAMEPAD_L2: String = "gamepad_L2"; static var GAMEPAD_L3: String = "gamepad_L3"; static var GAMEPAD_R1: String = "gamepad_R1"; static var GAMEPAD_R2: String = "gamepad_R2"; static var GAMEPAD_R3: String = "gamepad_R3"; static var GAMEPAD_START: String = "start"; static var GAMEPAD_BACK: String = "back"; static var ENTER: String = "enter-gamepad_A"; static var ESCAPE: String = "escape-gamepad_B"; static var END: String = "end"; static var HOME: String = "home"; static var PAGE_DOWN: String = "pageDown"; static var PAGE_UP: String = "pageUp"; static var TAB: String = "tab"; static var SHIFT_TAB: String = "tab"; } ================================================ FILE: src/CLIK/gfx/utils/Constraints.as ================================================ dynamic class gfx.utils.Constraints { static var LEFT: Number = 1; static var RIGHT: Number = 2; static var TOP: Number = 4; static var BOTTOM: Number = 8; static var ALL = gfx.utils.Constraints.LEFT | gfx.utils.Constraints.RIGHT | gfx.utils.Constraints.TOP | gfx.utils.Constraints.BOTTOM; var scaled: Boolean = false; var elements; var scope; function Constraints(scope, scaled) { this.scope = scope; this.scaled = scaled; this.elements = []; } function addElement(clip, edges) { if (clip != null) { var __reg8 = 100 / this.scope._xscale; var __reg7 = 100 / this.scope._yscale; var __reg6 = this.scope._width; var __reg5 = this.scope._height; if (this.scope == _root) { __reg6 = Stage.width; __reg5 = Stage.height; } var __reg4 = {clip: clip, edges: edges, metrics: {left: clip._x, top: clip._y, right: __reg6 * __reg8 - (clip._x + clip._width), bottom: __reg5 * __reg7 - (clip._y + clip._height), xscale: clip._xscale, yscale: clip._yscale}}; var __reg14 = __reg4.metrics; this.elements.push(__reg4); } } function removeElement(clip) { var __reg2 = 0; for (;;) { if (__reg2 >= this.elements.length) { return; } if (this.elements[__reg2].clip == clip) { this.elements.splice(__reg2, 1); return; } ++__reg2; } } function getElement(clip) { var __reg2 = 0; while (__reg2 < this.elements.length) { if (this.elements[__reg2].clip == clip) { return this.elements[__reg2]; } ++__reg2; } return null; } function update(width, height) { var __reg10 = 100 / this.scope._xscale; var __reg9 = 100 / this.scope._yscale; if (!this.scaled) { this.scope._xscale = 100; this.scope._yscale = 100; } var __reg8 = 0; for (;;) { if (__reg8 >= this.elements.length) { return; } var __reg5 = this.elements[__reg8]; var __reg4 = __reg5.edges; var __reg2 = __reg5.clip; var __reg3 = __reg5.metrics; var __reg14 = __reg2.width == null ? "_width" : "width"; var __reg13 = __reg2.height == null ? "_height" : "height"; if (this.scaled) { __reg2._xscale = __reg3.xscale * __reg10; __reg2._yscale = __reg3.yscale * __reg9; if ((__reg4 & gfx.utils.Constraints.LEFT) > 0) { __reg2._x = __reg3.left * __reg10; if ((__reg4 & gfx.utils.Constraints.RIGHT) > 0) { var __reg7 = width - __reg3.left - __reg3.right; if (!(__reg2 instanceof TextField)) { __reg7 = __reg7 * __reg10; } __reg2[__reg14] = __reg7; } } else if ((__reg4 & gfx.utils.Constraints.RIGHT) > 0) { __reg2._x = (width - __reg3.right) * __reg10 - __reg2._width; } if ((__reg4 & gfx.utils.Constraints.TOP) > 0) { __reg2._y = __reg3.top * __reg9; if ((__reg4 & gfx.utils.Constraints.BOTTOM) > 0) { var __reg6 = height - __reg3.top - __reg3.bottom; if (!(__reg2 instanceof TextField)) { __reg6 = __reg6 * __reg9; } __reg2[__reg13] = __reg6; } } else if ((__reg4 & gfx.utils.Constraints.BOTTOM) > 0) { __reg2._y = (height - __reg3.bottom) * __reg9 - __reg2._height; } } else { if ((__reg4 & gfx.utils.Constraints.RIGHT) > 0) { if ((__reg4 & gfx.utils.Constraints.LEFT) > 0) { __reg2[__reg14] = width - __reg3.left - __reg3.right; } else { __reg2._x = width - __reg2._width - __reg3.right; } } if ((__reg4 & gfx.utils.Constraints.BOTTOM) > 0) { if ((__reg4 & gfx.utils.Constraints.TOP) > 0) { __reg2[__reg13] = height - __reg3.top - __reg3.bottom; } else { __reg2._y = height - __reg2._height - __reg3.bottom; } } } ++__reg8; } } function toString() { return "[Scaleform Constraints]"; } } ================================================ FILE: src/CLIK/gfx/utils/Locale.as ================================================ dynamic class gfx.utils.Locale { function Locale() { } static function getTranslatedString(value) { return value; } } ================================================ FILE: src/Common/Components/BlinkOnDemandMeter.as ================================================ class Components.BlinkOnDemandMeter extends Components.Meter { var BlinkMovieClip: MovieClip; var meterMovieClip: MovieClip; function BlinkOnDemandMeter(aMeterMovieClip: MovieClip, aBlinkMovieClip: MovieClip) { super(aMeterMovieClip); BlinkMovieClip = aBlinkMovieClip; BlinkMovieClip.gotoAndStop("StartFlash"); } function StartBlinking(): Void { meterMovieClip._parent.PlayForward(meterMovieClip._parent._currentframe); BlinkMovieClip.gotoAndPlay("StartFlash"); } } ================================================ FILE: src/Common/Components/BlinkOnEmptyMeter.as ================================================ class Components.BlinkOnEmptyMeter extends Components.Meter { var iCurrentPercent: Number; var iEmpty: Number; var meterMovieClip: MovieClip; function BlinkOnEmptyMeter(aMeterClip: MovieClip) { super(aMeterClip); } function Update(): Void { super.Update(); var iCurrentFrame = meterMovieClip._currentframe; if (iCurrentPercent <= 0) { if (iCurrentFrame == iEmpty) { meterMovieClip.gotoAndPlay(iEmpty + 1); var iCurrentFrame1: Number = meterMovieClip._currentframe; } } } } ================================================ FILE: src/Common/Components/CrossPlatformButtons.as ================================================ // TODO!!! Doesn't look like this file is use at all by skyui. // Consider removing this file completely. import Shared.ButtonChange; class Components.CrossPlatformButtons extends gfx.controls.Button { var border: MovieClip; var ButtonArt: MovieClip; var ButtonArt_mc: MovieClip; var CurrentPlatform: Number; var PCButton: String; var PS3Button: String; var PS3Swapped: Boolean; var XBoxButton: String; function CrossPlatformButtons() { super(); } function onLoad(): Void { super.onLoad(); if (_parent.onButtonLoad != undefined) _parent.onButtonLoad(this); } function SetPlatform(aiPlatform: Number, aSwapPS3: Boolean): Void { if (aiPlatform != undefined) CurrentPlatform = aiPlatform; if (aSwapPS3 != undefined) PS3Swapped = aSwapPS3; RefreshArt(); } function RefreshArt(): Void { if (undefined != ButtonArt) ButtonArt.removeMovieClip(); var iCurrentPlatform: Number = CurrentPlatform; if (iCurrentPlatform === ButtonChange.PLATFORM_PC) { if (PCButton != "None") ButtonArt_mc = attachMovie(PCButton, "ButtonArt", getNextHighestDepth()); } else if (iCurrentPlatform === ButtonChange.PLATFORM_PC_GAMEPAD) { ButtonArt_mc = attachMovie(XBoxButton, "ButtonArt", getNextHighestDepth()); } else if (iCurrentPlatform === ButtonChange.PLATFORM_360) { ButtonArt_mc = attachMovie(XBoxButton, "ButtonArt", getNextHighestDepth()); } else if (iCurrentPlatform === ButtonChange.PLATFORM_PS3) { var strPS3Button: String = PS3Button; if (PS3Swapped) { if (strPS3Button == "PS3_A") strPS3Button = "PS3_B"; else if (strPS3Button == "PS3_B") strPS3Button = "PS3_A"; } ButtonArt_mc = attachMovie(strPS3Button, "ButtonArt", getNextHighestDepth()); } ButtonArt_mc._x = ButtonArt_mc._x - ButtonArt_mc._width; ButtonArt_mc._y = (_height - ButtonArt_mc._height) / 2; border._visible = false; } function GetArt(): Object { return {PCArt: PCButton, XBoxArt: XBoxButton, PS3Art: PS3Button}; } function SetArt(aPlatformArt: Object): Void { PCArt = aPlatformArt.PCArt; XBoxArt = aPlatformArt.XBoxArt; PS3Art = aPlatformArt.PS3Art; RefreshArt(); } function get XBoxArt(): String { return null; } function set XBoxArt(aValue: String): Void { if (aValue != "") XBoxButton = aValue; } function get PS3Art(): String { return null; } function set PS3Art(aValue: String): Void { if (aValue != "") PS3Button = aValue; } function get PCArt(): String { return null; } function set PCArt(aValue: String): Void { if (aValue != "") PCButton = aValue; } } ================================================ FILE: src/Common/Components/DeltaMeter.as ================================================ import Shared.GlobalFunc; class Components.DeltaMeter extends Components.Meter { var DeltaEmpty: Number; var DeltaFull: Number; var DeltaMeterMovieClip: MovieClip; function DeltaMeter(aMovieClip: MovieClip) { super(aMovieClip); DeltaMeterMovieClip = aMovieClip.DeltaIndicatorInstance; DeltaMeterMovieClip.gotoAndStop("Empty"); DeltaEmpty = DeltaMeterMovieClip._currentframe; DeltaMeterMovieClip.gotoAndStop("Full"); DeltaFull = DeltaMeterMovieClip._currentframe; } function SetDeltaPercent(aiPercent: Number): Void { var iPercent: Number = Math.min(100, Math.max(aiPercent, 0)); var iMeterFrame: Number = Math.floor(GlobalFunc.Lerp(DeltaEmpty, DeltaFull, 0, 100, iPercent)); DeltaMeterMovieClip.gotoAndStop(iMeterFrame); } } ================================================ FILE: src/Common/Components/Meter.as ================================================ import Shared.GlobalFunc; class Components.Meter { var CurrentPercent: Number; var Empty: Number; var EmptySpeed: Number; var FillSpeed: Number; var Full: Number; var TargetPercent: Number; var meterMovieClip: MovieClip; function Meter(aMovieClip: MovieClip) { Empty = 0; Full = 0; CurrentPercent = 100; TargetPercent = 100; FillSpeed = 2; EmptySpeed = 3; meterMovieClip = aMovieClip; meterMovieClip.gotoAndStop("Empty"); Empty = meterMovieClip._currentframe; meterMovieClip.gotoAndStop("Full"); Full = meterMovieClip._currentframe; } function SetPercent(aPercent: Number): Void { CurrentPercent = Math.min(100, Math.max(aPercent, 0)); TargetPercent = CurrentPercent; var iMeterFrame: Number = Math.floor(GlobalFunc.Lerp(Empty, Full, 0, 100, CurrentPercent)); meterMovieClip.gotoAndStop(iMeterFrame); } function SetTargetPercent(aPercent: Number): Void { TargetPercent = Math.min(100, Math.max(aPercent, 0)); } function SetFillSpeed(aSpeed: Number): Void { FillSpeed = aSpeed; } function SetEmptySpeed(aSpeed: Number): Void { EmptySpeed = aSpeed; } function Update(): Void { if (TargetPercent > 0 && TargetPercent > CurrentPercent) { if (TargetPercent - CurrentPercent > FillSpeed) { CurrentPercent = CurrentPercent + FillSpeed; var iMeterFrame: Number = GlobalFunc.Lerp(Empty, Full, 0, 100, CurrentPercent); meterMovieClip.gotoAndStop(iMeterFrame); } else { SetPercent(TargetPercent); } return; } if (TargetPercent <= CurrentPercent) { var bAnim: Boolean = CurrentPercent - TargetPercent > EmptySpeed; if ((TargetPercent > 0 && bAnim) || CurrentPercent > EmptySpeed) { if (bAnim) CurrentPercent = CurrentPercent - EmptySpeed; else CurrentPercent = TargetPercent; var iMeterFrame: Number = GlobalFunc.Lerp(Empty, Full, 0, 100, CurrentPercent); meterMovieClip.gotoAndStop(iMeterFrame); return; } if (CurrentPercent >= 0) SetPercent(TargetPercent); } } } ================================================ FILE: src/Common/Components/UniformTimeMeter.as ================================================ import Shared.GlobalFunc; import gfx.io.GameDelegate; class Components.UniformTimeMeter extends Components.Meter { var AnimClip: MovieClip; var AnimStart: String; var CurrentPercent: Number; var Empty: Number; var FinishSound: String; var FrameCount: Number; var FrameNumber: Number; var Full: Number; var TargetPercent: Number; var bFinished: Boolean; var meterMovieClip: MovieClip; function UniformTimeMeter(aMovieClip, aFinishSound: String, aClip: MovieClip, aAnimStart: String) { super(aMovieClip); this.FinishSound = aFinishSound; this.AnimClip = aClip; this.AnimStart = aAnimStart; this.FrameNumber = 48; } function SetTargetPercent(aPercent: Number): Void { super.SetTargetPercent(aPercent); this.bFinished = aPercent >= 100 && this.CurrentPercent < 100; this.FrameCount = 0; } function Update(): Void { if (this.FrameCount <= this.FrameNumber) { var iCurrentFrame: Number = GlobalFunc.Lerp(this.CurrentPercent, this.TargetPercent, 0, this.FrameNumber, this.FrameCount); var iActualFrame: Number = GlobalFunc.Lerp(this.Empty, this.Full, 0, 100, iCurrentFrame); this.meterMovieClip.gotoAndStop(iActualFrame); ++this.FrameCount; if (this.FrameCount == this.FrameNumber && this.bFinished) { GameDelegate.call("PlaySound", [this.FinishSound]); if (this.AnimClip != undefined) this.AnimClip.gotoAndPlay(this.AnimStart); } } } } ================================================ FILE: src/Common/MouseRotationInputCatcher.as ================================================ class MouseRotationInputCatcher extends MovieClip { static var PROCESS_ROTATION_DELAY: Number = 150; var iProcessRotationDelayTimerID: Number; function MouseRotationInputCatcher() { super(); } function onMouseDown(): Void { var topMostEntity: Boolean = Mouse.getTopMostEntity() == this; if (topMostEntity || _parent.bFadedIn == false) _parent.onMouseRotationStart(); if (topMostEntity && iProcessRotationDelayTimerID == undefined) iProcessRotationDelayTimerID = setInterval(this, "onProcessDelayElapsed", MouseRotationInputCatcher.PROCESS_ROTATION_DELAY); } function onProcessDelayElapsed(): Void { clearInterval(iProcessRotationDelayTimerID); iProcessRotationDelayTimerID = undefined; } function onMouseUp(): Void { _parent.onMouseRotationStop(); clearInterval(iProcessRotationDelayTimerID); if (iProcessRotationDelayTimerID != undefined && _parent.bFadedIn != false) _parent.onMouseRotationFastClick(0); iProcessRotationDelayTimerID = undefined; } function onPressAux(): Void { _parent.onMouseRotationFastClick(1); } } ================================================ FILE: src/Common/QuantitySlider.as ================================================ import gfx.ui.InputDetails; import gfx.ui.NavigationCode; import Shared.GlobalFunc; class QuantitySlider extends gfx.controls.Slider { var dispatchEvent: Function; function QuantitySlider() { super(); } function handleInput(details: InputDetails, pathToFocus: Array): Boolean { var bHandledInput: Boolean = super.handleInput(details, pathToFocus); if (!bHandledInput) { if (GlobalFunc.IsKeyPressed(details)) { if (details.navEquivalent == NavigationCode.PAGE_DOWN || details.navEquivalent == NavigationCode.GAMEPAD_L1) { value = Math.floor(value - maximum / 4); dispatchEvent({type: "change"}); bHandledInput = true; } else if (details.navEquivalent == NavigationCode.PAGE_UP || details.navEquivalent == NavigationCode.GAMEPAD_R1) { value = Math.ceil(value + maximum / 4); dispatchEvent({type: "change"}); bHandledInput = true; } } } return bHandledInput; } } ================================================ FILE: src/Common/SaveLoadPanel.as ================================================ import gfx.events.EventDispatcher; import gfx.io.GameDelegate; class SaveLoadPanel extends MovieClip { static var SCREENSHOT_DELAY: Number = 200; //750 static var CONTROLLER_PC = 0; static var CONTROLLER_PC_GAMEPAD = 1; static var CONTROLLER_DURANGO = 2; static var CONTROLLER_ORBIS = 3; var List_mc: MovieClip; var SaveLoadList_mc: MovieClip; var ScreenshotHolder: MovieClip; var ScreenshotRect: MovieClip; var ScreenshotLoader: MovieClipLoader; var PlayerInfoText: TextField; var dispatchEvent: Function; var bSaving: Boolean; var iBatchSize: Number; var iPlatform: Number; var iScreenshotTimerID: Number; var showCharacterBackHint; var showingCharacterList; var lastSelectedIndexMemory; var uiSaveLoadManagerProcessedElements; var uiSaveLoadManagerNumElementsToLoad; var isForceStopping; function SaveLoadPanel() { super(); EventDispatcher.initialize(this); SaveLoadList_mc = List_mc; bSaving = true; showCharacterBackHint = false; showingCharacterList = false; lastSelectedIndexMemory = 0; uiSaveLoadManagerProcessedElements = 0; uiSaveLoadManagerNumElementsToLoad = 0; isForceStopping = false; } function onLoad(): Void { ScreenshotLoader = new MovieClipLoader(); ScreenshotLoader.addListener(this); GameDelegate.addCallBack("ConfirmOKToLoad", this, "onOKToLoadConfirm"); GameDelegate.addCallBack("onSaveLoadBatchComplete", this, "onSaveLoadBatchComplete"); GameDelegate.addCallBack("onFillCharacterListComplete",this,"onFillCharacterListComplete"); GameDelegate.addCallBack("ScreenshotReady", this, "ShowScreenshot"); SaveLoadList_mc.addEventListener("itemPress", this, "onSaveLoadItemPress"); SaveLoadList_mc.addEventListener("selectionChange", this, "onSaveLoadItemHighlight"); iBatchSize = SaveLoadList_mc.maxEntries; //max = 0x7FFFFFFF; PlayerInfoText.createTextField("LevelText", PlayerInfoText.getNextHighestDepth(), 0, 0, 200, 30); PlayerInfoText.LevelText.text = "$Level"; PlayerInfoText.LevelText._visible = false; } function get isSaving(): Boolean { return bSaving; } function set isSaving(abFlag: Boolean): Void { bSaving = abFlag; } function get isShowingCharacterList() { return showingCharacterList; } function set isShowingCharacterList(abFlag) { showingCharacterList = abFlag; if(iPlatform != SaveLoadPanel.CONTROLLER_ORBIS) { ScreenshotHolder._visible = !showingCharacterList; } PlayerInfoText._visible = !showingCharacterList; } function get selectedIndex(): Number { return SaveLoadList_mc.selectedIndex; } function get platform(): Number { return iPlatform; } function set platform(aiPlatform: Number): Void { iPlatform = aiPlatform; } function get batchSize(): Number { return iBatchSize; } function get numSaves(): Number { return SaveLoadList_mc.entryList.length; } function get selectedEntry() { return SaveLoadList_mc.entryList[SaveLoadList_mc.selectedIndex]; } function get LastSelectedIndexMemory() { if(lastSelectedIndexMemory > SaveLoadList_mc.entryList.length -1) { lastSelectedIndexMemory = Math.max(0, SaveLoadList_mc.entryList.length - 1); } return lastSelectedIndexMemory; } function onSaveLoadItemPress(event: Object): Void { lastSelectedIndexMemory = SaveLoadList_mc.selectedIndex; if(this.isShowingCharacterList) { var selected = this.SaveLoadList_mc.entryList[this.SaveLoadList_mc.selectedIndex]; if(selected != undefined) { if(this.iPlatform != 0) { SaveLoadList_mc.selectedIndex = 0; } var flags = selected.flags; if(flags == undefined) { flags = 0; } var id = selected.id; if(id == undefined) { flags = 4294967295; } gfx.io.GameDelegate.call("CharacterSelected",[id, flags, bSaving, SaveLoadList_mc.entryList, iBatchSize]); this.dispatchEvent({type:"OnCharacterSelected"}); return; } } if (!bSaving) { GameDelegate.call("IsOKtoLoad", [SaveLoadList_mc.selectedIndex]); return; } dispatchEvent({type: "saveGameSelected", index: SaveLoadList_mc.selectedIndex}); } function onOKToLoadConfirm(): Void { dispatchEvent({type: "loadGameSelected", index: SaveLoadList_mc.selectedIndex}); } function ForceStopLoading() { isForceStopping = true; if(uiSaveLoadManagerProcessedElements < uiSaveLoadManagerNumElementsToLoad) { GameDelegate.call("ForceStopSaveListLoading",[]); } } function RemoveScreenshot() { if (iScreenshotTimerID != undefined) { clearInterval(iScreenshotTimerID); iScreenshotTimerID = undefined; } if (ScreenshotRect != undefined) { ScreenshotRect.removeMovieClip(); PlayerInfoText.textField.SetText(" "); PlayerInfoText.DateText.SetText(" "); PlayerInfoText.PlayTimeText.SetText(" "); ScreenshotRect = undefined; } } function onSaveLoadItemHighlight(event: Object): Void { if(isForceStopping) return; RemoveScreenshot(); if(isShowingCharacterList) return; if (event.index != -1) iScreenshotTimerID = setInterval(this, "PrepScreenshot", SaveLoadPanel.SCREENSHOT_DELAY); dispatchEvent({type: "saveHighlighted", index: SaveLoadList_mc.selectedIndex}); } function PrepScreenshot(): Void { clearInterval(iScreenshotTimerID); iScreenshotTimerID = undefined; if (bSaving) { GameDelegate.call("PrepSaveGameScreenshot", [SaveLoadList_mc.selectedIndex - 1, SaveLoadList_mc.selectedEntry]); return; } GameDelegate.call("PrepSaveGameScreenshot", [SaveLoadList_mc.selectedIndex, SaveLoadList_mc.selectedEntry]); } function ShowScreenshot(): Void { ScreenshotRect = ScreenshotHolder.createEmptyMovieClip("ScreenshotRect", 0); ScreenshotLoader.loadClip("img://BGSSaveLoadHeader_Screenshot", ScreenshotRect); if (SaveLoadList_mc.selectedEntry.corrupt == true) { PlayerInfoText.textField.SetText("$SAVE CORRUPT"); } else if (SaveLoadList_mc.selectedEntry.obsolete == true) { PlayerInfoText.textField.SetText("$SAVE OBSOLETE"); } else if (SaveLoadList_mc.selectedEntry.name == undefined) { PlayerInfoText.textField.SetText(" "); } else { var strSaveName: String = SaveLoadList_mc.selectedEntry.name; var iSaveNameMaxLength: Number = 20; if (strSaveName.length > iSaveNameMaxLength) strSaveName = strSaveName.substr(0, iSaveNameMaxLength - 3) + "..."; if (SaveLoadList_mc.selectedEntry.raceName != undefined && SaveLoadList_mc.selectedEntry.raceName.length > 0) strSaveName = strSaveName + (", " + SaveLoadList_mc.selectedEntry.raceName); if (SaveLoadList_mc.selectedEntry.level != undefined && SaveLoadList_mc.selectedEntry.level > 0) strSaveName = strSaveName + (", " + PlayerInfoText.LevelText.text + " " + SaveLoadList_mc.selectedEntry.level); PlayerInfoText.textField.textAutoSize = "shrink"; PlayerInfoText.textField.SetText(strSaveName); } if (SaveLoadList_mc.selectedEntry.playTime == undefined) PlayerInfoText.PlayTimeText.SetText(" "); else PlayerInfoText.PlayTimeText.SetText(SaveLoadList_mc.selectedEntry.playTime); if (SaveLoadList_mc.selectedEntry.dateString != undefined) { PlayerInfoText.DateText.SetText(SaveLoadList_mc.selectedEntry.dateString); return; } PlayerInfoText.DateText.SetText(" "); } function onLoadInit(aTargetClip: MovieClip): Void { aTargetClip._width = ScreenshotHolder.sizer._width; aTargetClip._height = ScreenshotHolder.sizer._height; } function onFillCharacterListComplete(abDoInitialUpdate: Boolean): Void { // FIXME? Is this a no-op by mistake? isShowingCharacterList(true); var iSaveNameMaxLength: Number = 20; for (var i: Number = 0; i < SaveLoadList_mc.entryList.length; i++) if (SaveLoadList_mc.entryList[i].text.length > iSaveNameMaxLength) SaveLoadList_mc.entryList[i].text = SaveLoadList_mc.entryList[i].text.substr(0, iSaveNameMaxLength - 3) + "..."; SaveLoadList_mc.InvalidateData(); if(iPlatform != 0) { onSaveLoadItemHighlight({index:LastSelectedIndexMemory}); SaveLoadList_mc.selectedIndex = LastSelectedIndexMemory; SaveLoadList_mc.UpdateList(); } dispatchEvent({type: "saveListCharactersPopulated"}); } function onSaveLoadBatchComplete(abDoInitialUpdate: Boolean, aNumProcessed: Number, aSaveCount: Number): Void { var iSaveNameMaxLength: Number = 20; uiSaveLoadManagerProcessedElements = aNumProcessed; uiSaveLoadManagerNumElementsToLoad = aSaveCount; var cursor = 0; while(cursor < SaveLoadList_mc.entryList.length) { if(iPlatform == SaveLoadPanel.CONTROLLER_ORBIS) { if(SaveLoadList_mc.entryList[cursor].text == undefined) { SaveLoadList_mc.entryList.splice(cursor, 1); } } if(SaveLoadList_mc.entryList[cursor].text.length > iSaveNameMaxLength) { SaveLoadList_mc.entryList[cursor].text = SaveLoadList_mc.entryList[cursor].text.substr(0, iSaveNameMaxLength - 3) + "..."; } cursor++; } var strNewSave: String = "$[NEW SAVE]"; if (bSaving && SaveLoadList_mc.entryList[0].text != strNewSave) { var newSaveObj: Object = {name: " ", playTime: " ", text: strNewSave}; SaveLoadList_mc.entryList.unshift(newSaveObj); } else if (!bSaving && SaveLoadList_mc.entryList[0].text == strNewSave) { SaveLoadList_mc.entryList.shift(); } SaveLoadList_mc.InvalidateData(); if(iPlatform == SaveLoadPanel.CONTROLLER_ORBIS) { lastSelectedIndexMemory = 0; } if (abDoInitialUpdate) { isForceStopping = false; isShowingCharacterList = false; onSaveLoadItemHighlight({index: LastSelectedIndexMemory}); SaveLoadList_mc.selectedIndex(LastSelectedIndexMemory); SaveLoadList_mc.UpdateList(); dispatchEvent({type:"saveListPopulated"}); return; } if(isForceStopping) return; dispatchEvent({type: "saveListOnBatchAdded"}); } function DeleteSelectedSave(): Void { if (!bSaving || SaveLoadList_mc.selectedIndex != 0) { if (bSaving) GameDelegate.call("DeleteSave", [SaveLoadList_mc.selectedIndex - 1]); else GameDelegate.call("DeleteSave", [SaveLoadList_mc.selectedIndex]); SaveLoadList_mc.entryList.splice(SaveLoadList_mc.selectedIndex, 1); SaveLoadList_mc.InvalidateData(); onSaveLoadItemHighlight({index: SaveLoadList_mc.selectedIndex}); } } function PopulateEmptySaveList() { SaveLoadList_mc.ClearList(); SaveLoadList_mc.entryList.push(new Object()); onSaveLoadBatchComplete(true, 0, 0); } function OnSelectClicked() { onSaveLoadItemPress(null); } function OnBackClicked() { dispatchEvent({type:"OnSaveLoadPanelBackClicked"}); } } ================================================ FILE: src/Common/Shared/BSScrollingList.as ================================================ import Shared.GlobalFunc; import gfx.ui.InputDetails; import gfx.ui.NavigationCode; import gfx.events.EventDispatcher; class Shared.BSScrollingList extends MovieClip { static var TEXT_OPTION_NONE: Number = 0; static var TEXT_OPTION_SHRINK_TO_FIT: Number = 1; static var TEXT_OPTION_MULTILINE: Number = 2; var EntriesA: Array; var scrollbar: Object; var ListScrollbar: Object; var ScrollDown: MovieClip; var ScrollUp: MovieClip; var border: MovieClip; var bDisableInput: Boolean; var bDisableSelection: Boolean; var bListAnimating: Boolean; var bMouseDrivenNav: Boolean; var dispatchEvent: Function; var onMousePress: Function; var fListHeight: Number; var iListItemsShown: Number; var iMaxItemsShown: Number; var iMaxScrollPosition: Number; var iPlatform: Number; var iScrollPosition: Number; var iScrollbarDrawTimerID: Number; var iSelectedIndex: Number; var iTextOption: Number; var itemIndex: Number; function BSScrollingList() { super(); EntriesA = new Array(); bDisableSelection = false; bDisableInput = false; bMouseDrivenNav = false; EventDispatcher.initialize(this); Mouse.addListener(this); iSelectedIndex = -1; iScrollPosition = 0; iMaxScrollPosition = 0; iListItemsShown = 0; iPlatform = 1; fListHeight = border._height; ListScrollbar = scrollbar; iMaxItemsShown = 0; for (var item: MovieClip = GetClipByIndex(iMaxItemsShown); item != undefined; item = GetClipByIndex(++iMaxItemsShown)) { item.clipIndex = iMaxItemsShown; item.onRollOver = function () { if (!_parent.listAnimating && !_parent.bDisableInput && itemIndex != undefined) { _parent.doSetSelectedIndex(itemIndex, 0); _parent.bMouseDrivenNav = true; } }; item.onPress = function (aiMouseIndex, aiKeyboardOrMouse) { if (itemIndex != undefined) { _parent.onItemPress(aiKeyboardOrMouse); if (!_parent.bDisableInput && onMousePress != undefined) onMousePress(); } }; item.onPressAux = function (aiMouseIndex, aiKeyboardOrMouse, aiButtonIndex) { if (itemIndex != undefined) _parent.onItemPressAux(aiKeyboardOrMouse, aiButtonIndex); }; } } function onLoad(): Void { if (ListScrollbar != undefined) { ListScrollbar.position = 0; ListScrollbar.addEventListener("scroll", this, "onScroll"); } } function ClearList(): Void { EntriesA.splice(0, EntriesA.length); } function GetClipByIndex(aiIndex: Number): MovieClip { return this["Entry" + aiIndex]; } function handleInput(details: InputDetails, pathToFocus: Array): Boolean { var bHandledInput: Boolean = false; if (!bDisableInput) { var item: MovieClip = GetClipByIndex(selectedIndex - scrollPosition); bHandledInput = item != undefined && item.handleInput != undefined && item.handleInput(details, pathToFocus.slice(1)); if (!bHandledInput && GlobalFunc.IsKeyPressed(details)) { if (details.navEquivalent == NavigationCode.UP) { moveSelectionUp(); bHandledInput = true; } else if (details.navEquivalent == NavigationCode.DOWN) { moveSelectionDown(); bHandledInput = true; } else if (!bDisableSelection && details.navEquivalent == NavigationCode.ENTER) { onItemPress(); bHandledInput = true; } } } return bHandledInput; } function onMouseWheel(delta: Number): Void { if (!bDisableInput) { for (var target = Mouse.getTopMostEntity(); target && target != undefined; target = target._parent) { if (target == this) { doSetSelectedIndex(-1,0); if (delta < 0) scrollPosition = scrollPosition + 1; else if (delta > 0) scrollPosition = scrollPosition - 1; } } } } function get selectedIndex(): Number { return iSelectedIndex; } function set selectedIndex(aiNewIndex: Number): Void { doSetSelectedIndex(aiNewIndex); } function get listAnimating(): Boolean { return bListAnimating; } function set listAnimating(abFlag: Boolean): Void { bListAnimating = abFlag; } function doSetSelectedIndex(aiNewIndex:Number, aiKeyboardOrMouse: Number): Void { if (!bDisableSelection && aiNewIndex != iSelectedIndex) { var iCurrentIndex: Number = iSelectedIndex; iSelectedIndex = aiNewIndex; if (iCurrentIndex != -1) SetEntry(GetClipByIndex(EntriesA[iCurrentIndex].clipIndex),EntriesA[iCurrentIndex]); if (iSelectedIndex != -1) { if (iPlatform != Shared.Platforms.CONTROLLER_PC) { if (iSelectedIndex < iScrollPosition) scrollPosition = iSelectedIndex; else if (iSelectedIndex >= iScrollPosition + iListItemsShown) scrollPosition = Math.min(iSelectedIndex - iListItemsShown + 1, iMaxScrollPosition); else SetEntry(GetClipByIndex(EntriesA[iSelectedIndex].clipIndex),EntriesA[iSelectedIndex]); } else { SetEntry(GetClipByIndex(EntriesA[iSelectedIndex].clipIndex),EntriesA[iSelectedIndex]); } } dispatchEvent({type:"selectionChange", index:iSelectedIndex, keyboardOrMouse:aiKeyboardOrMouse}); } } function get scrollPosition(): Number { return iScrollPosition; } function get maxScrollPosition(): Number { return iMaxScrollPosition; } function set scrollPosition(aiNewPosition: Number): Void { if (aiNewPosition != iScrollPosition && aiNewPosition >= 0 && aiNewPosition <= iMaxScrollPosition) { if (ListScrollbar == undefined) updateScrollPosition(aiNewPosition); else ListScrollbar.position = aiNewPosition; } } function updateScrollPosition(aiPosition: Number): Void { iScrollPosition = aiPosition; UpdateList(); } function get selectedEntry(): Object { return EntriesA[iSelectedIndex]; } function get entryList(): Array { return EntriesA; } function set entryList(anewArray: Array): Void { EntriesA = anewArray; } function get disableSelection(): Boolean { return bDisableSelection; } function set disableSelection(abFlag: Boolean): Void { bDisableSelection = abFlag; } function get disableInput(): Boolean { return bDisableInput; } function set disableInput(abFlag: Boolean): Void { bDisableInput = abFlag; } function get maxEntries(): Number { return iMaxItemsShown; } function get textOption(): Number { return iTextOption; } function set textOption(strNewOption: String): Void { if (strNewOption == "None") iTextOption = Shared.BSScrollingList.TEXT_OPTION_NONE; else if (strNewOption == "Shrink To Fit") iTextOption = Shared.BSScrollingList.TEXT_OPTION_SHRINK_TO_FIT; else if (strNewOption == "Multi-Line") iTextOption = Shared.BSScrollingList.TEXT_OPTION_MULTILINE; } function UpdateList(): Void { var iFirstItemy: Number = GetClipByIndex(0)._y; var iItemHeightSum: Number = 0; var iLastItemShownIndex: Number = 0; while (iLastItemShownIndex < iScrollPosition) { EntriesA[iLastItemShownIndex].clipIndex = undefined; ++iLastItemShownIndex; } iListItemsShown = 0; iLastItemShownIndex = iScrollPosition; while (iLastItemShownIndex < EntriesA.length && iListItemsShown < iMaxItemsShown && iItemHeightSum <= fListHeight) { var item: MovieClip = GetClipByIndex(iListItemsShown); SetEntry(item, EntriesA[iLastItemShownIndex]); EntriesA[iLastItemShownIndex].clipIndex = iListItemsShown; item.itemIndex = iLastItemShownIndex; item._y = iFirstItemy + iItemHeightSum; item._visible = true; iItemHeightSum += item._height; if (iItemHeightSum <= fListHeight && iListItemsShown < iMaxItemsShown) ++iListItemsShown; ++iLastItemShownIndex; } var iLastItemIndex: Number = iListItemsShown; while (iLastItemIndex < iMaxItemsShown) { GetClipByIndex(iLastItemIndex)._visible = false; ++iLastItemIndex; } if (ScrollUp != undefined) ScrollUp._visible = scrollPosition > 0; if (ScrollDown != undefined) ScrollDown._visible = scrollPosition < iMaxScrollPosition; } function InvalidateData(): Void { var iMaxScrollPos: Number = iMaxScrollPosition; fListHeight = border._height; CalculateMaxScrollPosition(); if (ListScrollbar != undefined) { if (iMaxScrollPos == iMaxScrollPosition) { SetScrollbarVisibility(); } else { ListScrollbar._visible = false; ListScrollbar.setScrollProperties(iMaxItemsShown, 0, iMaxScrollPosition); if (iScrollbarDrawTimerID != undefined) clearInterval(iScrollbarDrawTimerID); iScrollbarDrawTimerID = setInterval(this, "SetScrollbarVisibility", 50); } } if (iSelectedIndex >= EntriesA.length) iSelectedIndex = EntriesA.length - 1; if (iScrollPosition > iMaxScrollPosition) iScrollPosition = iMaxScrollPosition; UpdateList(); } function SetScrollbarVisibility(): Void { clearInterval(iScrollbarDrawTimerID); iScrollbarDrawTimerID = undefined; ListScrollbar._visible = iMaxScrollPosition > 0; } function CalculateMaxScrollPosition(): Void { var iItemHeightSum: Number = 0; var iLastItemIndex: Number = EntriesA.length - 1; while (iLastItemIndex >= 0 && iItemHeightSum <= fListHeight) { iItemHeightSum += GetEntryHeight(iLastItemIndex); if (iItemHeightSum <= fListHeight) --iLastItemIndex; } iMaxScrollPosition = iLastItemIndex + 1; } function GetEntryHeight(aiEntryIndex: Number): Number { var item: MovieClip = GetClipByIndex(0); SetEntry(item, EntriesA[aiEntryIndex]); return item._height; } function moveSelectionUp(): Void { if (!bDisableSelection) { if (selectedIndex > 0) selectedIndex = selectedIndex - 1; return; } scrollPosition = scrollPosition - 1; } function moveSelectionDown(): Void { if (!bDisableSelection) { if (selectedIndex < EntriesA.length - 1) selectedIndex = selectedIndex + 1; return; } scrollPosition = scrollPosition + 1; } function onItemPress(aiKeyboardOrMouse: Number): Void { if (!bDisableInput && !bDisableSelection && iSelectedIndex != -1) { dispatchEvent({type: "itemPress", index: iSelectedIndex, entry: EntriesA[iSelectedIndex], keyboardOrMouse: aiKeyboardOrMouse}); return; } dispatchEvent({type: "listPress"}); } function onItemPressAux(aiKeyboardOrMouse: Number, aiButtonIndex: Number) { if (!bDisableInput && !bDisableSelection && iSelectedIndex != -1 && aiButtonIndex == 1) dispatchEvent({type: "itemPressAux", index: iSelectedIndex, entry: EntriesA[iSelectedIndex], keyboardOrMouse: aiKeyboardOrMouse}); } function SetEntry(aEntryClip: MovieClip, aEntryObject: Object): Void { if (aEntryClip != undefined) { if (aEntryObject == selectedEntry) aEntryClip.gotoAndStop("Selected"); else aEntryClip.gotoAndStop("Normal"); SetEntryText(aEntryClip, aEntryObject); } } function SetEntryText(aEntryClip: MovieClip, aEntryObject: Object): Void { if (aEntryClip.textField != undefined) { if (textOption == Shared.BSScrollingList.TEXT_OPTION_SHRINK_TO_FIT) aEntryClip.textField.textAutoSize = "shrink"; else if (textOption == Shared.BSScrollingList.TEXT_OPTION_MULTILINE) aEntryClip.textField.verticalAutoSize = "top"; if (aEntryObject.text == undefined) aEntryClip.textField.SetText(" "); else aEntryClip.textField.SetText(aEntryObject.text); if (aEntryObject.enabled != undefined) aEntryClip.textField.textColor = aEntryObject.enabled == false ? 0x606060 : 0xFFFFFF; if (aEntryObject.disabled != undefined) aEntryClip.textField.textColor = aEntryObject.disabled == true ? 0x606060 : 0xFFFFFF; } } function SetPlatform(aiPlatform: Number, abPS3Switch: Boolean): Void { iPlatform = aiPlatform; bMouseDrivenNav = iPlatform == Shared.Platforms.CONTROLLER_PC; } function onScroll(event: Object): Void { updateScrollPosition(Math.floor(event.position + 0.5)); } } ================================================ FILE: src/Common/Shared/ButtonChange.as ================================================ import gfx.events.EventDispatcher; class Shared.ButtonChange extends gfx.events.EventDispatcher { // Not sure why this is being duplicated from Shared.Platforms static var PLATFORM_PC: Number = 0; static var PLATFORM_PC_GAMEPAD: Number = 1; static var PLATFORM_360: Number = 2; static var PLATFORM_PS3: Number = 3; static var PLATFORM_VIVE: Number = 4; static var PLATFORM_MOVE: Number = 5; static var PLATFORM_OCULUS: Number = 6; static var PLATFORM_WINDOWS_MR: Number = 8; var iCurrPlatform: Number = Shared.ButtonChange.PLATFORM_360; var dispatchEvent: Function; function ButtonChange() { super(); EventDispatcher.initialize(this); } function get Platform(): Number { return iCurrPlatform; } function IsGamepadConnected(): Boolean { return iCurrPlatform == Shared.ButtonChange.PLATFORM_PC_GAMEPAD || iCurrPlatform == Shared.ButtonChange.PLATFORM_360 || iCurrPlatform == Shared.ButtonChange.PLATFORM_PS3; } function SetPlatform(aSetPlatform: Number, aSetSwapPS3: Boolean): Void { iCurrPlatform = aSetPlatform; dispatchEvent({target: this, type: "platformChange", aPlatform: aSetPlatform, aSwapPS3: aSetSwapPS3}); } function SetPS3Swap(aSwap: Boolean): Void { dispatchEvent({target: this, type: "SwapPS3Button", Boolean: aSwap}); } } ================================================ FILE: src/Common/Shared/ButtonTextArtHolder.as ================================================ import gfx.io.GameDelegate; import flash.display.BitmapData; class Shared.ButtonTextArtHolder extends MovieClip { var strButtonName: String; function ButtonTextArtHolder() { super(); } function SetButtonName(aText: String): Void { strButtonName = aText; } function CreateButtonArt(aInputText: TextField): String { return CreateButtonArtCustomSize(aInputText, 26); } function CreateButtonArtCustomSize(aInputText: TextField, aiSize: Number): String { var iReplacerStart: Number = aInputText.text.indexOf("["); var iReplacerEnd: Number = iReplacerStart == -1 ? -1 : aInputText.text.indexOf("]", iReplacerStart); var strTextWithButtons = undefined; var requestedSize = aiSize; if (iReplacerStart != -1 && iReplacerEnd != -1) { strTextWithButtons = aInputText.text.substr(0, iReplacerStart); while (iReplacerStart != -1 && iReplacerEnd != -1) { var strButtonReplacer: String = aInputText.text.substring(iReplacerStart + 1, iReplacerEnd); GameDelegate.call("GetButtonFromUserEvent", [strButtonReplacer], this, "SetButtonName"); if (strButtonName == undefined) { strTextWithButtons = strTextWithButtons + aInputText.text.substring(iReplacerStart, iReplacerEnd + 1); } else { var ButtonImage: BitmapData = BitmapData.loadBitmap(strButtonName + ".png"); if (ButtonImage != undefined && ButtonImage.height > 0) { var iMaxHeight: Number = requestedSize; var iScaledWidth: Number = Math.floor(iMaxHeight / ButtonImage.height * ButtonImage.width); strTextWithButtons = strTextWithButtons + (""); } else { strTextWithButtons = strTextWithButtons + aInputText.text.substring(iReplacerStart, iReplacerEnd + 1); } } var iReplacerStartNext: Number = aInputText.text.indexOf("[", iReplacerEnd); var iReplacerEndNext: Number = iReplacerStartNext == -1 ? -1 : aInputText.text.indexOf("]", iReplacerStartNext); if (iReplacerStartNext != -1 && iReplacerEndNext != -1) strTextWithButtons = strTextWithButtons + aInputText.text.substring(iReplacerEnd + 1, iReplacerStartNext); else strTextWithButtons = strTextWithButtons + aInputText.text.substr(iReplacerEnd + 1); iReplacerStart = iReplacerStartNext; iReplacerEnd = iReplacerEndNext; } } return strTextWithButtons; } } ================================================ FILE: src/Common/Shared/CenteredScrollingList.as ================================================ import Shared.ListFilterer; class Shared.CenteredScrollingList extends Shared.BSScrollingList { var EntriesA: Array; var _filterer: ListFilterer; var bDisableInput: Boolean; var bMouseDrivenNav: Boolean; var bRecenterSelection: Boolean; var border: MovieClip; var dispatchEvent: Function; var doSetSelectedIndex: Function; var GetClipByIndex: Function; var SetEntryText: Function; var fListHeight: Number; var iDividerIndex: Number; var iListItemsShown: Number; var iMaxItemsShown: Number; var iMaxScrollPosition: Number; var iMaxTextLength: Number; var iNumTopHalfEntries: Number; var iNumUnfilteredItems: Number; var iPlatform: Number; var iScrollPosition: Number; var iSelectedIndex: Number; function CenteredScrollingList() { super(); _filterer = new ListFilterer(); _filterer.addEventListener("filterChange", this, "onFilterChange"); bRecenterSelection = false; iMaxTextLength = 256; iDividerIndex = -1; iNumUnfilteredItems = 0; } function get filterer(): ListFilterer { return _filterer; } function set maxTextLength(aLength: Number): Void { if (aLength > 3) iMaxTextLength = aLength; } function get numUnfilteredItems(): Number { return iNumUnfilteredItems; } function get maxTextLength(): Number { return iMaxTextLength; } function get numTopHalfEntries(): Number { return iNumTopHalfEntries; } function set numTopHalfEntries(aiNum: Number): Void { iNumTopHalfEntries = aiNum; } function get centeredEntry(): Object { return EntriesA[GetClipByIndex(iNumTopHalfEntries).itemIndex]; } function IsDivider(aEntry: Object): Boolean { return aEntry.divider == true || aEntry.flag == 0; } // No longer needed? 20120615 /* function IsSelectionAboveDivider(): Boolean { return iDividerIndex == -1 || selectedIndex < iDividerIndex; } */ function get dividerIndex(): Number { return iDividerIndex; } function RestoreScrollPosition(aiNewPosition: Number, abRecenterSelection: Boolean): Void { iScrollPosition = aiNewPosition; if (iScrollPosition < 0) iScrollPosition = 0; if (iScrollPosition > iMaxScrollPosition) iScrollPosition = iMaxScrollPosition; bRecenterSelection = abRecenterSelection; } function UpdateList(): Void { var iItemHeight: Number = GetClipByIndex(0)._y; var iHeightSum: Number = 0; var iEntryIndex: Number = filterer.ClampIndex(0); iDividerIndex = -1; for (var i: Number = 0; i < EntriesA.length; i++) if (IsDivider(EntriesA[i])) iDividerIndex = i; if (bRecenterSelection || iPlatform != Shared.Platforms.CONTROLLER_PC) iSelectedIndex = -1; else iSelectedIndex = filterer.ClampIndex(iSelectedIndex); for (var i: Number = 0; i < iScrollPosition - iNumTopHalfEntries; i++) { EntriesA[iEntryIndex].clipIndex = undefined; iEntryIndex = filterer.GetNextFilterMatch(iEntryIndex); } iListItemsShown = 0; iNumUnfilteredItems = 0; for (var i: Number = 0; i < iNumTopHalfEntries; i++) { var item: MovieClip = GetClipByIndex(i); if (iScrollPosition - iNumTopHalfEntries + i >= 0) { SetEntry(item, EntriesA[iEntryIndex]); item._visible = true; item.itemIndex = IsDivider(EntriesA[iEntryIndex]) == true ? undefined : iEntryIndex; EntriesA[iEntryIndex].clipIndex = i; iEntryIndex = filterer.GetNextFilterMatch(iEntryIndex); ++iNumUnfilteredItems; } else { item._visible = false; item.itemIndex = undefined; } item._y = iItemHeight + iHeightSum; iHeightSum = iHeightSum + item._height; ++iListItemsShown; } if (iEntryIndex != undefined && (bRecenterSelection || iPlatform != Shared.Platforms.CONTROLLER_PC)) iSelectedIndex = iEntryIndex; for (iEntryIndex; iEntryIndex != undefined && iEntryIndex != -1 && iEntryIndex < EntriesA.length && iListItemsShown < iMaxItemsShown && iHeightSum <= fListHeight; iEntryIndex = filterer.GetNextFilterMatch(iEntryIndex)) { var item: MovieClip = GetClipByIndex(iListItemsShown); SetEntry(item, EntriesA[iEntryIndex]); EntriesA[iEntryIndex].clipIndex = iListItemsShown; item.itemIndex = IsDivider(EntriesA[iEntryIndex]) == true ? undefined : iEntryIndex; item._y = iItemHeight + iHeightSum; item._visible = true; iHeightSum = iHeightSum + item._height; if (iHeightSum <= fListHeight && iListItemsShown < iMaxItemsShown) { ++iListItemsShown; ++iNumUnfilteredItems; } } for (var i: Number = iListItemsShown; i < iMaxItemsShown; i++) { GetClipByIndex(i)._visible = false; GetClipByIndex(i).itemIndex = undefined; } if (bMouseDrivenNav && !bRecenterSelection) for (var item: Object = Mouse.getTopMostEntity(); item != undefined; item = item._parent) if (item._parent == this && item._visible && item.itemIndex != undefined) doSetSelectedIndex(item.itemIndex, 0); bRecenterSelection = false; } function InvalidateData(): Void { filterer.filterArray = EntriesA; fListHeight = border._height; CalculateMaxScrollPosition(); if (iScrollPosition > iMaxScrollPosition) iScrollPosition = iMaxScrollPosition; UpdateList(); } function onFilterChange(): Void { iSelectedIndex = filterer.ClampIndex(iSelectedIndex); CalculateMaxScrollPosition(); } function moveSelectionUp(): Void { var itemIndex: Number = filterer.GetPrevFilterMatch(iSelectedIndex); var iInitialScrollPos: Number = iScrollPosition; if (itemIndex != undefined && IsDivider(EntriesA[itemIndex]) == true) { --iScrollPosition; itemIndex = filterer.GetPrevFilterMatch(itemIndex); } if (itemIndex != undefined) { iSelectedIndex = itemIndex; if (iScrollPosition > 0) --iScrollPosition; bMouseDrivenNav = false; UpdateList(); dispatchEvent({type: "listMovedUp", index: iSelectedIndex, scrollChanged: iInitialScrollPos != iScrollPosition}); } } function moveSelectionDown(): Void { var itemIndex: Number = filterer.GetNextFilterMatch(iSelectedIndex); var iInitialScrollPos: Number = iScrollPosition; if (itemIndex != undefined && IsDivider(EntriesA[itemIndex]) == true) { ++iScrollPosition; itemIndex = filterer.GetNextFilterMatch(itemIndex); } if (itemIndex != undefined) { iSelectedIndex = itemIndex; if (iScrollPosition < iMaxScrollPosition) ++iScrollPosition; bMouseDrivenNav = false; UpdateList(); dispatchEvent({type: "listMovedDown", index: iSelectedIndex, scrollChanged: iInitialScrollPos != iScrollPosition}); } } function onMouseWheel(delta: Number): Void { if (bDisableInput) return; for (var item: Object = Mouse.getTopMostEntity(); item && item != undefined; item = item._parent) { if (item == this) { if (delta < 0) { var newItem: MovieClip = GetClipByIndex(iNumTopHalfEntries + 1); if (newItem._visible == true) { if (newItem.itemIndex == undefined) scrollPosition = scrollPosition + 2; else scrollPosition = scrollPosition + 1; } } else if (delta > 0) { var newItem = GetClipByIndex(iNumTopHalfEntries - 1); if (newItem._visible == true) { if (newItem.itemIndex == undefined) scrollPosition = scrollPosition - 2; else scrollPosition = scrollPosition - 1; } } } } bMouseDrivenNav = true; } function CalculateMaxScrollPosition(): Void { iMaxScrollPosition = -1; for (var itemIndex: Number = filterer.ClampIndex(0); itemIndex != undefined; itemIndex = filterer.GetNextFilterMatch(itemIndex)) ++iMaxScrollPosition; if (iMaxScrollPosition == undefined || iMaxScrollPosition < 0) iMaxScrollPosition = 0; } function SetEntry(aEntryClip: MovieClip, aEntryObject: Object): Void { if (aEntryClip != undefined) { if (IsDivider(aEntryObject) == true) aEntryClip.gotoAndStop("Divider"); else aEntryClip.gotoAndStop("Normal"); if (iPlatform == Shared.Platforms.CONTROLLER_PC) { aEntryClip._alpha = aEntryObject == selectedEntry ? 100 : 60; } else { var iAlphaMulti: Number = 4; if (aEntryClip.clipIndex < iNumTopHalfEntries) aEntryClip._alpha = 60 - iAlphaMulti * (iNumTopHalfEntries - aEntryClip.clipIndex); else if (aEntryClip.clipIndex > iNumTopHalfEntries) aEntryClip._alpha = 60 - iAlphaMulti * (aEntryClip.clipIndex - iNumTopHalfEntries); else aEntryClip._alpha = 100; } SetEntryText(aEntryClip, aEntryObject); } } } ================================================ FILE: src/Common/Shared/ExtractPlatformText.as ================================================ class Shared.ExtractPlatformText { function ExtractPlatformText() { } static function IsWhitespace(str) { return str == " " || str == "\n" || str == "\r"; } static function Trim(str) { var i = 0; // Start at the beginning of the string var j = str.length - 1; // Start at the end of the string while(i < str.length) { if(Shared.ExtractPlatformText.IsWhitespace(str.charAt(i)) == false) { break; } i++; } j = str.length - 1; while(j >= 0) { if(Shared.ExtractPlatformText.IsWhitespace(str.charAt(j)) == false) { break; } j--; } return str.substr(i, j - i + 1); } // This looks to be processing a long string that looks like: // <>>> <>>> // The function takes this string and returns string text associated with 'aiPlatform' static function Extract(asText, aiPlatform) { // If there are no platform markers, all platforms will share the same text if(asText.indexOf("<<") < 0) { return asText; } // Determine the name of the platform we're looking for var platformName = undefined; switch(aiPlatform) { case Shared.Platforms.CONTROLLER_PCGAMEPAD: platformName = "PCGAMEPAD"; break; case Shared.Platforms.CONTROLLER_VIVE: platformName = "VIVE"; break; case Shared.Platforms.CONTROLLER_OCULUS: platformName = "OCULUS"; break; case Shared.Platforms.CONTROLLER_WINDOWS_MR: platformName = "WINDOWS_MR"; break; case Shared.Platforms.CONTROLLER_ORBIS_MOVE: platformName = "ORBIS_MOVE"; break; case Shared.Platforms.CONTROLLER_ORBIS: platformName = "ORBIS"; break; default: return asText; } // Attempt to extract the text marked by the platformName var remainingText = asText; while(remainingText.length > 0) { // Look for the next platform marker var startMarker = remainingText.indexOf("<<"); var endMarker = remainingText.indexOf(">>"); // If ther are no platform markers, then we use the text for all platforms if(startMarker < 0 || endMarker < 0) { return remainingText; } // We located a platform marker... // What is the name of the platform we've located? var enclosedText = remainingText.substr(startMarker + 2,endMarker - startMarker - 2); remainingText = remainingText.substr(endMarker + 2); // Did we find the platform we're looking for? if(enclosedText == platformName) { var text = ""; // Grab all the text up to the next platform marker var nextStartMarker = remainingText.indexOf("<<"); if(nextStartMarker < 0) text = remainingText; else text = remainingText.substr(0, nextStartMarker); return Shared.ExtractPlatformText.Trim(text); } // We didn't find the platform we're looking for... // Does it look like there is another platform marker? // If not, whatever remaining text will be used as the text. // This means the very last piece of text is the default text var nextStartMarker = remainingText.indexOf("<<"); if(nextStartMarker < 0) { return remainingText; } // There is more platform text left... // Prep for the next iteration by moving to the beginning of the next // platform marker remainingText = remainingText.substr(nextStartMarker); continue; } } } ================================================ FILE: src/Common/Shared/GlobalFunc.as ================================================ class Shared.GlobalFunc { static var RegisteredTextFields: Object = new Object(); static var RegisteredMovieClips: Object = new Object(); function GlobalFunc() { } static function Lerp(aTargetMin: Number, aTargetMax: Number, aSourceMin: Number, aSourceMax: Number, aSource: Number, abClamp: Boolean): Number { var normVal: Number = aTargetMin + (aSource - aSourceMin) / (aSourceMax - aSourceMin) * (aTargetMax - aTargetMin); if (abClamp) normVal = Math.min(Math.max(normVal, aTargetMin), aTargetMax); return normVal; } static function IsKeyPressed(aInputInfo: Object, abProcessKeyHeldDown: Boolean): Boolean { if (abProcessKeyHeldDown == undefined) abProcessKeyHeldDown = true; return aInputInfo.value == "keyDown" || (abProcessKeyHeldDown && aInputInfo.value == "keyHold"); } static function RoundDecimal(aNumber: Number, aPrecision: Number): Number { var significantFigures: Number = Math.pow(10, aPrecision); return Math.round(significantFigures * aNumber) / significantFigures; } static function MaintainTextFormat(): Void { TextField.prototype.SetText = function (aText: String, abHTMLText: Boolean) { if (aText == undefined || aText == "") aText = " "; var textFormat: TextFormat = this.getTextFormat(); if (abHTMLText) { var letterSpacing: Number = textFormat.letterSpacing; var kerning: Boolean = textFormat.kerning; this.htmlText = aText; textFormat.letterSpacing = letterSpacing; textFormat.kerning = kerning; this.setTextFormat(textFormat); return; } this.text = aText; this.setTextFormat(textFormat); return; }; _global.ASSetPropFlags(TextField.prototype, "SetText" , 0x01, 0x00); } static function SetLockFunction(): Void { MovieClip.prototype.Lock = function (aPosition: String): Void { var minXY: Object = {x: Stage.visibleRect.x + Stage.safeRect.x, y: Stage.visibleRect.y + Stage.safeRect.y}; var maxXY: Object = {x: Stage.visibleRect.x + Stage.visibleRect.width - Stage.safeRect.x, y: Stage.visibleRect.y + Stage.visibleRect.height - Stage.safeRect.y}; this._parent.globalToLocal(minXY); this._parent.globalToLocal(maxXY); // (minXY.x, minXY.y) _____________ (maxXY.x, minXY.y) // | | // | THE | // | STAGE | // (minXY.x, maxXY.y)|_____________|(maxXY.x, maxXY.y) if (aPosition == "T" || aPosition == "TL" || aPosition == "TR") this._y = minXY.y; if (aPosition == "B" || aPosition == "BL" || aPosition == "BR") this._y = maxXY.y; if (aPosition == "L" || aPosition == "TL" || aPosition == "BL") this._x = minXY.x; if (aPosition == "R" || aPosition == "TR" || aPosition == "BR") this._x = maxXY.x; }; _global.ASSetPropFlags(MovieClip.prototype, "Lock" , 0x01, 0x00); } static function AddMovieExploreFunctions(): Void { MovieClip.prototype.getMovieClips = function (): Array { var movieClips: Array = new Array(); for (var i: Number = 0; i < this.length; i++) if (this[i] instanceof MovieClip && this[i] != this) movieClips.push(this[i]); return movieClips; }; MovieClip.prototype.showMovieClips = function (): Void { for (var i: Number = 0; i < this.length; i++) if (this[i] instanceof MovieClip && this[i] != this) { trace(this[i]); this[i].showMovieClips(); } }; _global.ASSetPropFlags(MovieClip.prototype, ["getMovieClips", "showMovieClips"], 0x01, 0x00); } static function AddReverseFunctions(): Void { MovieClip.prototype.PlayReverse = function (): Void { if (this._currentframe > 1) { this.gotoAndStop(this._currentframe - 1); this.onEnterFrame = function () { if (this._currentframe > 1) { this.gotoAndStop(this._currentframe - 1); return; } delete (this.onEnterFrame); } return; } this.gotoAndStop(1); }; MovieClip.prototype.PlayForward = function (aFrameLabel: String): Void { delete (this.onEnterFrame); this.gotoAndPlay(aFrameLabel); }; MovieClip.prototype.PlayForward = function (aFrame: Number): Void { delete (this.onEnterFrame); this.gotoAndPlay(aFrame); }; _global.ASSetPropFlags(MovieClip.prototype, ["PlayReverse", "PlayForward"], 0x01, 0x00); } static function GetTextField(aParentClip: MovieClip, aName: String): TextField { if (Shared.GlobalFunc.RegisteredTextFields[aName + aParentClip._name] != undefined) return Shared.GlobalFunc.RegisteredTextFields[aName + aParentClip._name]; trace(aName + " is not registered a TextField name."); } static function GetMovieClip(aParentClip: MovieClip, aName: String): MovieClip { if (Shared.GlobalFunc.RegisteredMovieClips[aName + aParentClip._name] != undefined) return Shared.GlobalFunc.RegisteredMovieClips[aName + aParentClip._name]; trace(aName + " is not registered a MovieClip name."); } static function AddRegisterTextFields(): Void { TextField.prototype.RegisterTextField = function (aStartingClip): Void { if (Shared.GlobalFunc.RegisteredTextFields[this._name + aStartingClip._name] == undefined) Shared.GlobalFunc.RegisteredTextFields[this._name + aStartingClip._name] = this; }; _global.ASSetPropFlags(TextField.prototype, "RegisterTextField", 0x01, 0x00); } static function RegisterTextFields(aStartingClip: MovieClip) : Void { for (var i: Number = 0; i < aStartingClip.length; i++) if (aStartingClip[i] instanceof TextField) aStartingClip[i].RegisterTextField(aStartingClip); } static function RegisterAllTextFieldsInTimeline(aStartingClip: MovieClip): Void { for (var i: Number = 1; aStartingClip._totalFrames && i <= aStartingClip._totalFrames; i++) { aStartingClip.gotoAndStop(i); Shared.GlobalFunc.RegisterTextFields(aStartingClip); } } static function AddRegisterMovieClips(): Void { MovieClip.prototype.RegisterMovieClip = function (aStartingClip): Void { if (Shared.GlobalFunc.RegisteredMovieClips[this._name + aStartingClip._name] == undefined) Shared.GlobalFunc.RegisteredMovieClips[this._name + aStartingClip._name] = this; }; _global.ASSetPropFlags(MovieClip.prototype, "RegisterMovieClip", 0x01, 0x00); } static function RegisterMovieClips(aStartingClip: MovieClip): Void { for (var i: Number = 0; i < aStartingClip.length; i++) if (aStartingClip[i] instanceof MovieClip) aStartingClip[i].RegisterMovieClip(aStartingClip); } static function RecursiveRegisterMovieClips(aStartingClip: MovieClip, aRootClip: MovieClip): Void { for (var i: Number = 0; i < aStartingClip.length; i++) { if (aStartingClip[i] instanceof MovieClip) { if (aStartingClip[i] != aStartingClip) Shared.GlobalFunc.RecursiveRegisterMovieClips(aStartingClip[i], aRootClip); aStartingClip[i].RegisterMovieClip(aRootClip); } } } static function RegisterAllMovieClipsInTimeline(aStartingClip: MovieClip): Void { for (var i: Number = 0; aStartingClip._totalFrames && i <= aStartingClip._totalFrames; i++) { aStartingClip.gotoAndStop(i); Shared.GlobalFunc.RegisterMovieClips(aStartingClip); } } static function StringTrim(astrText: String): String { var i: Number = 0; var j: Number = 0; var strLength: Number = astrText.length; var trimStr: String = undefined; while (astrText.charAt(i) == " " || astrText.charAt(i) == "\n" || astrText.charAt(i) == "\r" || astrText.charAt(i) == "\t") ++i; trimStr = astrText.substring(i); j = trimStr.length - 1; while (trimStr.charAt(j) == " " || trimStr.charAt(j) == "\n" || trimStr.charAt(j) == "\r" || trimStr.charAt(j) == "\t") --j; trimStr = trimStr.substring(0, j + 1); return trimStr; } static function StringReplaceAll(str:String, search:String, replace:String):String { return str.split(search).join(replace); } } ================================================ FILE: src/Common/Shared/ListFilterer.as ================================================ import gfx.events.EventDispatcher; class Shared.ListFilterer { var EntryMatchesFunc: Function; var _filterArray: Array; var dispatchEvent: Function; var addEventListener: Function; var iItemFilter: Number; function ListFilterer() { iItemFilter = 0xFFFFFFFF; EntryMatchesFunc = EntryMatchesFilter; EventDispatcher.initialize(this); } function get itemFilter(): Number { return iItemFilter; } function set itemFilter(aiNewFilter: Number): Void { var bfilterChanged: Boolean = iItemFilter != aiNewFilter; iItemFilter = aiNewFilter; if (bfilterChanged == true) dispatchEvent({type: "filterChange"}); } function get filterArray(): Array { return _filterArray; } function set filterArray(aNewArray: Array): Void { _filterArray = aNewArray; } function SetPartitionedFilterMode(abPartition: Boolean): Void { EntryMatchesFunc = abPartition ? EntryMatchesPartitionedFilter : EntryMatchesFilter; } function EntryMatchesFilter(aEntry: Object): Boolean { return aEntry != undefined && (aEntry.filterFlag == undefined || (aEntry.filterFlag & iItemFilter) != 0); } function EntryMatchesPartitionedFilter(aEntry: Object): Boolean { var bmatchFound = false; if (aEntry != undefined) { if (iItemFilter == 0xFFFFFFFF) { bmatchFound = true; } else { var ifilterFlag: Number = aEntry.filterFlag; var byte0: Number = (ifilterFlag & 0x000000FF); var byte1: Number = (ifilterFlag & 0x0000FF00) >>> 8; var byte2: Number = (ifilterFlag & 0x00FF0000) >>> 16; var byte3: Number = (ifilterFlag & 0xFF000000) >>> 24; bmatchFound = byte0 == iItemFilter || byte1 == iItemFilter || byte2 == iItemFilter || byte3 == iItemFilter; } } return bmatchFound; } function GetPrevFilterMatch(aiStartIndex: Number): Number { var iPrevMatch: Number = undefined; if (aiStartIndex != undefined) for (var i = aiStartIndex - 1; i >=0 && iPrevMatch == undefined; i--) if (EntryMatchesFunc(_filterArray[i])) iPrevMatch = i; return iPrevMatch; } function GetNextFilterMatch(aiStartIndex: Number): Number { var iNextMatch: Number = undefined; if (aiStartIndex != undefined) for (var i = aiStartIndex + 1; i < _filterArray.length && iNextMatch == undefined; i++) if (EntryMatchesFunc(_filterArray[i])) iNextMatch = i; return iNextMatch; } function ClampIndex(aiStartIndex: Number): Number { var iClampIndex = aiStartIndex; if (aiStartIndex != undefined && !EntryMatchesFunc(_filterArray[iClampIndex])) { var iNextMatch: Number = GetNextFilterMatch(iClampIndex); var iPrevMatch: Number = GetPrevFilterMatch(iClampIndex); if (iNextMatch == undefined) { if (iPrevMatch == undefined) iClampIndex = -1; else iClampIndex = iPrevMatch; } else { iClampIndex = iNextMatch; } if (iNextMatch != undefined && iPrevMatch != undefined && iPrevMatch != iNextMatch && iClampIndex == iNextMatch && _filterArray[iPrevMatch].text == _filterArray[aiStartIndex].text) iClampIndex = iPrevMatch; } return iClampIndex; } } ================================================ FILE: src/Common/Shared/Macros.as ================================================ import gfx.io.GameDelegate; class Shared.Macros { function Macros() { } static function BSOUTPUT(asMessage) { GameDelegate.call("DoActionscriptOutput",[asMessage]); } static function BSASSERT(abConditional, asMessage) { if(!abConditional) { GameDelegate.call("DoActionscriptAssert",[abConditional,asMessage]); } } } ================================================ FILE: src/Common/Shared/PlatformChangeUser.as ================================================ import Shared.ButtonChange; import Shared.PlatformChangeUser.PlatformChange; class Shared.PlatformChangeUser extends MovieClip { static var PlatformChange: ButtonChange; function PlatformChangeUser() { super(); PlatformChange = new ButtonChange(); } function RegisterPlatformChangeListener(aCrossPlatformButton: Object): Void { PlatformChange.addEventListener("platformChange", aCrossPlatformButton, "SetPlatform"); PlatformChange.addEventListener("SwapPS3Button", aCrossPlatformButton, "SetPS3Swap"); } } ================================================ FILE: src/Common/Shared/Platforms.as ================================================ class Shared.Platforms { static var CONTROLLER_PC = 0; static var CONTROLLER_PCGAMEPAD = 1; static var CONTROLLER_DURANGO = 2; static var CONTROLLER_ORBIS = 3; static var CONTROLLER_VIVE = 4; static var CONTROLLER_ORBIS_MOVE = 5; static var CONTROLLER_OCULUS = 6; static var CONTROLLER_VIVE_KNUCKLES = 7; static var CONTROLLER_WINDOWS_MR = 8; function Platforms() { } static function IsUsingWands(aiPlatform) { return aiPlatform == CONTROLLER_VIVE || aiPlatform == CONTROLLER_VIVE_KNUCKLES || aiPlatform == CONTROLLER_ORBIS_MOVE || aiPlatform == CONTROLLER_OCULUS || aiPlatform == CONTROLLER_WINDOWS_MR; } static function IsUsingController(aiPlatform) { return aiPlatform == Shared.Platforms.CONTROLLER_PCGAMEPAD || aiPlatform == Shared.Platforms.CONTROLLER_ORBIS; } } ================================================ FILE: src/Common/mx/transitions/Tween.as ================================================ class mx.transitions.Tween { var obj; var prop; var begin; var useSeconds; var _time; var prevTime; var looping; var _duration; var _fps; var isPlaying; var prevPos; var _pos; var change; var _intervalID; var _startTime; public var onMotionStarted; public var onMotionFinished; public var onMotionStopped; public var onMotionLooped; public var onMotionChanged; public var onMotionResumed; function Tween(obj, prop, func, begin, finish, duration, useSeconds) { if(!arguments.length) { return; } this.obj = obj; this.prop = prop; this.begin = begin; this.position = begin; this.duration = duration; this.useSeconds = useSeconds; if(func) { this.func = func; } this.finish = finish; this.FPS = 30; start(); } function set time(t) { prevTime = _time; if(t > this.duration) { if(looping) { this.rewind(t - this._duration); this.update(); if(this.onMotionLooped) { this.onMotionLooped(); } } else { if(this.useSeconds) { this._time = this._duration; this.update(); } this.stop(); if(this.onMotionFinished) { this.onMotionFinished(); } } } else if(t < 0) { this.rewind(); this.update(); } else { this._time = t; this.update(); } //return this.time; } function get time() { return _time; } function set duration(d) { _duration = !(d == null || d <= 0)?d:_global.Infinity; //return this.duration; } function get duration() { return _duration; } function set FPS(fps) { var _loc2_ = this.isPlaying; this.stopEnterFrame(); this._fps = fps; if(_loc2_) { this.startEnterFrame(); } //return this.__get__FPS(); } function __get__FPS() { return this._fps; } function set position(p) { this.setPosition(p); //return this.__get__position(); } function setPosition(p) { this.prevPos = this._pos; this.obj[this.prop] = this._pos = p; if(this.onMotionChanged) { this.onMotionChanged(this._pos); } updateAfterEvent(); } function get position() { return this.getPosition(); } function getPosition(t) { if(t == undefined) { t = this._time; } return this.func(t,this.begin,this.change,this._duration); } function set finish(f) { this.change = f - this.begin; //return this.finish; } function get finish() { return this.begin + this.change; } function continueTo(finish, duration) { this.begin = this.position; this.finish = finish; if(duration != undefined) { this.duration = duration; } this.start(); } function yoyo() { this.continueTo(this.begin,this.time); } function startEnterFrame() { this._intervalID = setInterval(this,"onEnterFrame",1000 / this._fps); this.isPlaying = true; } function stopEnterFrame() { clearInterval(this._intervalID); this.isPlaying = false; } function start() { this.rewind(); this.startEnterFrame(); if(this.onMotionStarted) { this.onMotionStarted(); } } function stop() { this.stopEnterFrame(); if(this.onMotionStopped) { this.onMotionStopped(); } } function resume() { this.fixTime(); this.startEnterFrame(); if(this.onMotionResumed) { this.onMotionResumed(); } } function rewind(t) { this._time = t != undefined?t:0; this.fixTime(); this.update(); } function fforward() { this.time = _duration; this.fixTime(); } function nextFrame() { if(this.useSeconds) { this.time = (getTimer() - this._startTime) / 1000; } else { this.time = this._time + 1; } } function onEnterFrame() { this.nextFrame(); } function prevFrame() { if(!this.useSeconds) { this.time = this._time - 1; } } function toString() { return "[Tween]"; } function fixTime() { if(this.useSeconds) { this._startTime = getTimer() - this._time * 1000; } } function update() { this.position = getPosition(this._time); } function func(t, b, c, d) { return c * t / d + b; } } ================================================ FILE: src/Common/skse.as ================================================ intrinsic class skse { static function Log(a_string:String):Void; static function AllowTextInput(a_flag:Boolean):Void; static function GetMappedKey(a_name:String, a_deviceType: Number, a_context: Number):Number; static function StartRemapMode(a_scope:Object):Void; static function GetLastControl(a_bKeyDown:Boolean):String; static function GetLastKeycode(a_bKeyDown:Boolean):Number; static function SetINISetting(a_key:String, a_value:Number):Void; static function GetINISetting(a_key:String):Number; static function OpenMenu(a_menu:String):Void; static function CloseMenu(a_menu:String):Void; static function ExtendData(enable:Boolean):Void; static function ExtendAlchemyCategories(enable:Boolean):Void; static function ForceContainerCategorization(enable:Boolean):Void; static function SendModEvent(a_eventName:String, a_strArg:String, a_numArg:Number, a_formId:Number):Void; static function RequestActivePlayerEffects(a_list:Array):Void; static function ExtendForm(a_formid:Number, a_object:Object, a_extraData:Boolean, a_recursive:Boolean):Void; static function EnableMapMenuMouseWheel(a_enable:Boolean):Void; static function ShowOnMap(a_markerIndex:Number):Void; static function StoreIndices(a_key:String, a_indicesIn:Array):Void; static function LoadIndices(a_key:String, a_indicesOut:Array):Void; static function ShowVirtualKeyboard(a_key:String, title:String, desc:String, curText:String, obj:Object, func:Object):Boolean; } ================================================ FILE: src/Common/skyui/VRInput.as ================================================ // The VRInput class is a namespace that holds all functions related // to construction, manipulation, transformation of OpenVR's // ControllerState_t into something meaningful and usable by the UI // // OpenVR gives us a few pieces of data that are packed into bit flags. // However, in an UI, we want to know which widgets are manpulated and // *how* they are being manipulated. // // What we really need is to unpack the bitfields into something that is // reasonable for the UI to work with. // // Something like this looks pretty reasonable: // { // id: (int) [0-64], // OpenVR id for the widget // pressed: (boolean) // do we consider the widget pressed? // touched: (boolean) // do we consider the widget touched? // // // For widgets with associated axis data // axisId: (int) // extracted from OpenVR ControllerState // axis: (vec2) // extracted from OpenVR ControllerState // // type: (string) ["button", // has binary on/off signal // "thumbstick", // has x,y axis // "touchpad", // has x,y axis & touch // "trigger"], // has x axis // // // Added annotation // widgetName: (string), // name of button or axis // controllerName: (string) ["vive", "knuckles", "oculus", "wmr"], // controllerRole: (string) ["rightHand", "leftHand"], // // pressStartTime: clock time when the event started // touchStartTime: clock time when the event started // // eventType: string "up"/"down"/"repeat" // // action: (string), // probable intended action // } // // The rough processing steps should be: // raw controller state data => // add annotation => // generate event obj => // dispatch event for processing import gfx.managers.FocusHandler; import Shared.Platforms; import skyui.util.Debug; import skyui.util.GlobalFunctions; class skyui.VRInput { // GLOBALS --------------------------------------------------------- public var initialized = false; // What is the name of the controller that corresponds to the // current platform public var controllerName_Game: String = ""; // Controller name reported by the game public var controllerName_OpenVR: String = ""; // Controller name reported by OpenVR public var controllerName: String = ""; // Internal logic will cue off of this // Stores the right/left hand controller state that we last saw public var lastControllerStates; // Stores state of each of the widgets on a controller public var lastWidgetStates; public var widgetStates; public var ignoreInput = false; public var errorPrintedFlags = {}; public var logDetails = false; // CONSTANTS ------------------------------------------------------- static public var WIDGET_MAX_COUNT = 64; // A controller state mirrors OpenVR's ControllerState_t // // This is the lowest level data we have access to regarding the // controller buttons. public function makeEmptyControllerState() { return { packetNum: 0, buttonPressedLow: 0, buttonPressedHigh: 0, buttonTouchedLow: 0, buttonTouchedHigh: 0, axis: [] }; } private function init() { if(!initialized) { lastControllerStates = [{}, {}]; lastWidgetStates = makeEmptyWidgetStates(); widgetStates = makeEmptyWidgetStates(); logDetails = skse["plugins"]["skyui"].IniGetBool("Settings/VRInput/logDetails"); } initialized = true; } public function makeEmptyWidgetStates() { var widgetStates = [[], []]; for(var i = 0; i < WIDGET_MAX_COUNT; i++) { widgetStates[0].push({ id: i, controllerRole: "leftHand", axis: [], uninitialized: true }); } for(var i = 0; i < WIDGET_MAX_COUNT; i++) { widgetStates[1].push({ id: i, controllerRole: "rightHand", axis: [], uninitialized: true }); } return widgetStates; } public function controllerNameFromPlatformEnum(platform) { switch(platform) { case Platforms.CONTROLLER_VIVE: return "vive"; case Platforms.CONTROLLER_ORBIS_MOVE: return "orbis"; case Platforms.CONTROLLER_OCULUS: return "oculus"; case Platforms.CONTROLLER_VIVE_KNUCKLES: return "knuckles"; case Platforms.CONTROLLER_WINDOWS_MR: return "wmr"; default: return "unknown"; } } public function controllerNameFromOpenVRName(name) { switch(name){ case "vive_controller": return "vive"; case "knuckles": return "knuckles"; case "oculus": return "oculus"; case "wmr": return "wmr"; default: return "unknown"; } //return "oculus"; //return "knuckles"; } public function getDefaultBindingsFilename() { var conName = controllerName || controllerNameFromOpenVRName(skse["plugins"]["skyui"].ControllerType()); if(conName == "unknown") conName = "general" return "defaults-" + conName; } public function getActionConditionDefs(menuName) { return skse["plugins"]["skyui"].IniGetWithDefaults("Settings/" + menuName, getDefaultBindingsFilename()); } public function getActionConditions(menuName) { return generateActionTriggerConditions(getActionConditionDefs(menuName)); } public function getAxis(axisArray, idx) { return [axisArray[idx*2], axisArray[idx*2+1]]; } public function updatePlatform(platform: Number) { //Debug.log("VRInput.updatePlatform: " + platform); controllerName_Game = controllerNameFromPlatformEnum(platform); controllerName_OpenVR = skse["plugins"]["skyui"].ControllerType(); //Debug.log("[skyui] controllerName_Game: " + controllerName_Game); //Debug.log("[skyui] controllerName_OpenVR: " + controllerName_OpenVR); // We'll prefer controller type reported by OpenVR over the game engine // The game doesn't know how to deal with the index controller. var name = controllerNameFromOpenVRName(controllerName_OpenVR); //Debug.log("[skyui] OpenVR mapped name: " + name); if (name != "unknown") controllerName = name; else controllerName = controllerName_Game; //Debug.log("[skyui] controllerName: " + controllerName); } public function widgetDetectPhaseChange(curState, lastState, phaseName) { var cur = curState[phaseName]; var last = lastState[phaseName]; if(cur == last) return "no-change"; if(cur && !last) return "start"; else return "stop"; } public function widgetDetectPhaseStart(curState, lastState, phaseName) { var cur = curState[phaseName]; var last = lastState[phaseName]; if(cur && !last) return "start"; return "no-change"; } public function widgetDetectPhaseStop(curState, lastState, phaseName) { var cur = curState[phaseName]; var last = lastState[phaseName]; if(!cur && last) return "stop"; return "no-change"; } public function makeWidgetEvent(curState, lastState, phaseName, eventName) { return { curState: curState, lastState: lastState, phaseName: phaseName, eventName: eventName }; } public function copyWidgetState(src, dest) { for (var key:String in src) { if(key != "axis") dest[key] = src[key]; } if(!dest.axis) { dest.axis = []; } dest.axis[0] = src.axis[0]; dest.axis[1] = src.axis[1]; return dest; } static public function axisQuadrant(vec2) { var angle = GlobalFunctions.vec2Angle(vec2); if (angle < 0) angle += 360; if(angle < 45) return "right"; if(angle < 135) return "top"; if(angle < 225) return "left"; if(angle < 315) return "bottom"; return "right"; } static function axisRegion(vec2) { var mag = GlobalFunctions.vec2Mag(vec2); if(mag <= 0.45) return "center"; return axisQuadrant(vec2); } public function interestingWidgetIdxs() { switch(controllerName) { case "vive": return [1, 2, 32, 33]; break; case "knuckles": return [1, 2, 7, 32, 33, 34]; break; case "oculus": return [1, 2, 7, 32, 33]; break; default: if(!errorPrintedFlags["unknown-controller"]) { Debug.log("unknown controller: " + controllerName); Debug.log("controllerName_Game: " + controllerName_Game); Debug.log("controllerName_OpenVR: " + controllerName_OpenVR); Debug.log("controllerName: " + controllerName); errorPrintedFlags["unknown-controller"] = true; } return [1, 2, 32, 33]; } } // Given the new controller state, perform some upkeep and generate // an array of "interesting" events. public function updateControllerState( timestamp: Number, controllerHand: Number, packetNum: Number, buttonPressedLow: Number, buttonPressedHigh: Number, buttonTouchedLow: Number, buttonTouchedHigh: Number, axis: Array): Array { var handIdx = controllerHand-1; var lastButtonState = lastControllerStates[handIdx]; var curButtonState = { packetNum: packetNum, buttonPressedLow: buttonPressedLow, buttonPressedHigh: buttonPressedHigh, buttonTouchedLow: buttonTouchedLow, buttonTouchedHigh: buttonTouchedHigh, axis: axis }; var eventQueue = []; if(lastButtonState.packetNum != curButtonState.packetNum) { //Debug.log("packetNum: " + lastButtonState.packetNum + " => " + curButtonState.packetNum); // Only process widgets that we know may actually be updated var widgetIdxs = interestingWidgetIdxs(); // Prepare to receive a new state // We're about to get an update on the state of the widget, // move the (old) current state of the widget into the last // state array. // // We're just using two arrays to store the previous and // current state of the widgets and reusing the objects // used to store the information. { var lastWidgets = lastWidgetStates[handIdx]; var curWidgets = widgetStates[handIdx]; for(var i = 0; i < widgetIdxs.length; i++) { var id = widgetIdxs[i]; var temp = lastWidgets[id]; lastWidgets[id] = curWidgets[id]; curWidgets[id] = temp; copyWidgetState(lastWidgets[id], curWidgets[id]); } } // Update widget states var widgets = widgetStates[handIdx]; for(var i = 0; i < widgetIdxs.length; i++) { var id = widgetIdxs[i]; var mask = 1 << id; var state = widgets[id]; if(id < 32) { state.pressed = (buttonPressedLow & mask) == 0 ? false : true; state.touched = (buttonTouchedLow & mask) == 0 ? false : true; state.controllerName = controllerName; } else { state.pressed = (buttonPressedHigh & mask) == 0 ? false : true; state.touched = (buttonTouchedHigh & mask) == 0 ? false : true; state.controllerName = controllerName; } delete state["uninitialized"]; } // Wire up additional Vive controller data switch(controllerName) { case "vive": widgets[1].widgetName = "application menu"; widgets[1].type = "button"; widgetAddClickWhenPressed(widgets[1]); widgets[2].widgetName = "grip"; widgets[2].type = "button"; widgetAddClickWhenPressed(widgets[2]); widgets[32].widgetName = "touchpad"; widgets[32].type = "touchpad"; widgets[32].axisId = 0; widgets[32].axis = getAxis(axis, 0); widgetAddClickWhenPressed(widgets[32]); widgets[33].widgetName = "trigger"; widgets[33].type = "trigger"; widgets[33].axisId = 1; widgets[33].axis = getAxis(axis, 1); widgetAddClickForTrigger(widgets[33]); widgetDetectTouchWithAxis(widgets[33]); break; case "knuckles": widgets[1].widgetName = "B button"; widgets[1].type = "button"; widgetAddClickWhenPressed(widgets[1]); widgets[2].widgetName = "grip"; widgets[2].type = "button"; widgets[2].axisId = 2; widgets[2].axis = getAxis(axis, 2); widgetAddClickWhenPressed(widgets[2]); widgets[7].widgetName = "A button"; widgets[7].type = "button"; widgetAddClickWhenPressed(widgets[7]); widgets[32].widgetName = "thumbstick"; widgets[32].type = "thumbstick"; widgets[32].axisId = 0; widgets[32].axis = getAxis(axis, 0); widgetAddClickWhenPressed(widgets[32]); widgets[33].widgetName = "trigger"; widgets[33].type = "trigger"; widgets[33].axisId = 1; widgets[33].axis = getAxis(axis, 1); widgetAddClickForTrigger(widgets[33]); widgetDetectTouchWithAxis(widgets[33]); widgets[34].widgetName = "fingers"; widgets[34].type = "button"; break; case "wmr": widgets[1].widgetName = "application menu"; widgets[1].type = "button"; widgetAddClickWhenPressed(widgets[1]); widgets[2].widgetName = "grip"; widgets[2].type = "button"; widgetAddClickWhenPressed(widgets[2]); widgets[32].widgetName = "touchpad"; widgets[32].type = "touchpad"; widgets[32].axisId = 0; widgets[32].axis = getAxis(axis, 0); widgetAddClickWhenPressed(widgets[32]); widgets[33].widgetName = "trigger"; widgets[33].type = "trigger"; widgets[33].axisId = 1; widgets[33].axis = getAxis(axis, 1); widgetAddClickForTrigger(widgets[33]); widgetDetectTouchWithAxis(widgets[33]); widgets[34].widgetName = "thumbstick"; widgets[34].type = "thumbstick"; widgets[34].axisId = 0; widgets[34].axis = getAxis(axis, 2); widgetAddClickWhenPressed(widgets[34]); break; default: widgets[1].widgetName = "B button"; widgets[1].type = "button"; widgetAddClickWhenPressed(widgets[1]); widgets[2].widgetName = "grip"; widgets[2].type = "button"; widgets[2].axisId = 2; widgets[2].axis = getAxis(axis, 2); widgetAddClickWhenPressed(widgets[2]); widgets[7].widgetName = "A button"; widgets[7].type = "button"; widgetAddClickWhenPressed(widgets[7]); widgets[32].widgetName = "thumbstick"; widgets[32].type = "thumbstick"; widgets[32].axisId = 0; widgets[32].axis = getAxis(axis, 0); widgetAddClickWhenPressed(widgets[32]); widgets[33].widgetName = "trigger"; widgets[33].type = "trigger"; widgets[33].axisId = 1; widgets[33].axis = getAxis(axis, 1); widgetAddClickForTrigger(widgets[33]); widgetDetectTouchWithAxis(widgets[33]); break; } // Generate events as appropriate var lastWidgets = lastWidgetStates[handIdx]; var curWidgets = widgetStates[handIdx]; for(var i = 0; i < widgetIdxs.length; i++) { var id = widgetIdxs[i]; var lastState = lastWidgets[id]; var curState = curWidgets[id]; if(lastState.uninitialized) { copyWidgetState(curState, lastState); delete lastState["uninitialized"]; } // Clean up event timestamps if appropriate if(curState.touchedStart && curState.touchedStop) { delete curState["touchedStart"]; delete curState["touchedStartState"]; delete curState["touchedStop"]; } if(curState.pressedStart && curState.pressedStop) { delete curState["pressedStart"]; delete curState["pressedStartState"]; delete curState["pressedStop"]; } if(curState.clickedStart && curState.clickedStop) { delete curState["clickedStart"]; delete curState["clickedStartState"]; delete curState["clickedStop"]; } // Detect and generate phase events // Note that we take a bit of effort to make sure that the start/stop // events are ordered like this: // touched start => pressed start => clicked start => // clicked end => pressed end => touched end var phases; phases = ["touched", "pressed", "clicked"]; for(var j = 0; j < phases.length; j++) { var phase = phases[j]; var change = widgetDetectPhaseStart(curState, lastState, phase); if(change != "no-change") { var event = makeWidgetEvent(curState, lastState, phase, change); curState[phase + "Start"] = timestamp; curState[phase + "StartState"] = copyWidgetState(curState, {}); eventQueue.push(event); } } phases = ["clicked", "pressed", "touched"]; for(var j = 0; j < phases.length; j++) { var phase = phases[j]; var change = widgetDetectPhaseStop(curState, lastState, phase); if(change != "no-change") { var event = makeWidgetEvent(curState, lastState, phase, change); curState[phase + "Stop"] = timestamp; eventQueue.push(event); } } } // Generate other synthetic events // By reading the event queue if(controllerName == "vive") { widgetTouchpadDetectSwipe(widgets[32], eventQueue); } // Record the current state // We'll use this as the last state when we're called again the next time. lastControllerStates[handIdx] = curButtonState; /* Debug.log("handIdx " + handIdx); Debug.dump("lastControllerStates[handIdx]", lastControllerStates[handIdx]); */ } return eventQueue; } //---------------------------------------------------------------------------- // Native function interop // // Return a timestamp with millisecond resolution. static private function clock(): Number { // We're sure the VRInput plugin is available. // Just call the clock function. return skse["plugins"]["vrinput"].GetClock(); } static private function triggerHapticPulse(controllerRole: String, strength: Number) { skse["plugins"]["vrinput"].TriggerHapticPulse(controllerRole == "leftHand" ? 1 : 2, strength); } //---------------------------------------------------------------------------- // Vec2 utilities // private function cloneVec2(vec2: Array) { return [vec2[0], vec2[1]]; } private function copyVec2(src: Array, dest: Array) { dest[0] = src[0]; dest[1] = src[1]; return dest; } // Widget synthetic attributes ------------------------------------- // // Some widgets may not behave the exact same way we want, // these functions can be used to add some synthetic attributes // to help bridge these differences. function widgetAddClickWhenPressed(widget) { if(widget.pressed) { widget.clicked = true; } else { widget.clicked = false; } } function widgetAddClickForTrigger(widget) { if(widget.axis[0] == 1) { widget.clicked = true; } else { widget.clicked = false; } } function widgetDetectTouchWithAxis(widget) { if(widget.axis[0] != 0.0 || widget.axis[1] != 0.0) { widget.touched = true; } } var touchpadSwipeStates = { leftHand: {}, rightHand: {} }; function widgetTouchpadDetectSwipe(widget, eventQueue) { // Given the current state of the widget, // generate events if swipes are detected... // If the touchpad isn't being touched, do nothing if(!widget.touched) { return; } var curTime = getTimer(); // Fetch the swipe state associated with the widget var hand = touchpadSwipeStates[widget.controllerRole]; var swipeState = hand[widget.id]; // Are we hanging on to state data from a previous swipe? // If so, clean it up now... if(widget.touchedStart && swipeState.startTime != widget.touchedStart) { delete touchpadSwipeStates[widget.controllerRole][widget.id]; swipeState = undefined; } // If we don't have a swipe state either because no data // has been associated with said widget or because associated // state has been cleaned up... // Create empty state to hold the swipe state if(!swipeState) { swipeState = { startTime: widget.touchedStart, lastProcessTime: curTime, lastPosition: cloneVec2(widget.axis) }; touchpadSwipeStates[widget.controllerRole][widget.id] = swipeState; } // Limit the rate at which events can be generated var timeDelta = curTime - swipeState.lastProcessTime; var curPosition = widget.axis; var lastPosition = swipeState.lastPosition var xDelta = curPosition[0] - lastPosition[0]; var yDelta = curPosition[1] - lastPosition[1]; var distanceDelta = Math.sqrt((xDelta * xDelta) + (yDelta * yDelta)); var velocity = distanceDelta / timeDelta; var distanceThreshold; var timeThreshold; var savePosition; var velThreshold = 0.16; if(velocity > 0.005) { distanceThreshold = 0.1; timeThreshold = 10; savePosition = false; } else { distanceThreshold = 0.33; timeThreshold = 10; savePosition = false; } // FIXME!!! Event firing frequency is tied directly to the framerate. if(timeDelta < timeThreshold) { return; } // If the touchpad position moved a certain distance // within the alotted period of time... // Generate an appropriate event. // We'e going to restrict swiping to up/down/right/left // First, determine which direction has received more movement... // That is the dominate axis var eventFired = false; if(Math.abs(xDelta) > Math.abs(yDelta)) { if(xDelta > distanceThreshold) { eventQueue.push({ eventType: "swipe", direction: "right", widget: widget }); eventFired = true; } else if(xDelta < -1 * distanceThreshold) { eventQueue.push({ eventType: "swipe", direction: "left", widget: widget }); eventFired = true; } } else { if(yDelta > distanceThreshold) { eventQueue.push({ eventType: "swipe", direction: "up", widget: widget }); eventFired = true; } else if(yDelta < -1 * distanceThreshold) { eventQueue.push({ eventType: "swipe", direction: "down", widget: widget }); eventFired = true; } } // Only update the last position and processing time // if an event actually fired. // // This means that as long as the user has traveled // a specific distance on the touchpad, the swipe // will be registered. // // This emulates the behavior of the game. Though // it isn't ideal, it will do for now. if(eventFired) { copyVec2(widget.axis, swipeState.lastPosition); swipeState.lastProcessTime = curTime; } } public function vibrateOnSwipe(eventQueue) { // Look a swipe event in the event queue // If found, vibrate the corresponding controller... for(var i = 0; i < eventQueue.length; i++) { var event = eventQueue[i]; if(event.eventType == "swipe") { triggerHapticPulse(event.widget.controllerRole, 0.25); break; } } } // Refactor? Do we really still need this function? // Is this serving the same role as `handleVRButtonUpdates`? public function getInputEvents( timestamp: Number, controllerHand: Number, packetNum: Number, buttonPressedLow: Number, buttonPressedHigh: Number, buttonTouchedLow: Number, buttonTouchedHigh: Number, axis: Array): Array { var eventQueue = updateControllerState( timestamp, controllerHand, packetNum, buttonPressedLow, buttonPressedHigh, buttonTouchedLow, buttonTouchedHigh, axis); vibrateOnSwipe(eventQueue); return eventQueue; } function getFocusPath() { // Skyrim is a single player game. So technically, we're only dealing with "one controller" return FocusHandler.instance.getPathToFocus(Selection.getControllerFocusGroup(0)); } function handleVRButtonUpdate( controllerHand: Number, packetNum: Number, buttonPressedLow: Number, buttonPressedHigh: Number, buttonTouchedLow: Number, buttonTouchedHigh: Number, axis: Array) { //Debug.log(">>> VRInput handleVRButtonUpdate"); // Should we update any button states at all? // This is useful for ignorning inputs when we're supposed to be // blocking, waiting for the OpenVR virtual keyboard. if(ignoreInput) return; var timestamp = getTimer(); var eventQueue = getInputEvents( timestamp, controllerHand, packetNum, buttonPressedLow, buttonPressedHigh, buttonTouchedLow, buttonTouchedHigh, axis); var update = { timestamp: timestamp, controllerHand: controllerHand, packetNum: packetNum, buttonPressedLow: buttonPressedLow, buttonPressedHigh: buttonPressedHigh, buttonTouchedLow: buttonTouchedLow, buttonTouchedHigh: buttonTouchedHigh, axis: axis } var stateText = controllerStateText(update, true); //if(stateText.length != 0) { // Debug.log("-- Button states --"); // Debug.log(stateText); //} var focusPath = getFocusPath(); //if(eventQueue.length != 0) { // Debug.log("focusPath: " + focusPath); // Debug.dump("eventQueue", eventQueue); //} dispatchButtonUpdates(update, focusPath); dispatchInputEvents(eventQueue, focusPath); //Debug.log("<<< VRInput handleVRButtonUpdate"); } public function dispatchButtonUpdates(update, focusPath: Array) { if(focusPath == null) focusPath = getFocusPath(); for(var i = 0; i < focusPath.length; i++) { var obj = focusPath[i]; if(obj.handleVRButtonUpdate != null) { obj.handleVRButtonUpdate(update); } } } public function dispatchInputEvents(eventQueue: Array, focusPath: Array) { if(focusPath == null) focusPath = getFocusPath(); // Take every event in the queue for(var ei = 0; ei < eventQueue.length; ei++) { var event = eventQueue[ei]; //if(ei == 0) { // Debug.log("dispatchInputEvents"); // Debug.dump("focusPath", focusPath); //} //Debug.log("Dispatching event: " + ei); // Send the event to the "handleVRInput" function of every object in the focus path for(var fi = 0; fi < focusPath.length; fi++) { var obj = focusPath[fi]; if(obj.handleVRInput != null) { //Debug.log("focusPath: " + fi + " " + obj); //if(obj.classname != null) // Debug.log("" + fi + ": " + obj.classname()); // An object may signal that it has already handled the event and stop the event // from going further in the focus path. var stop = obj.handleVRInput(event); if(stop) break; } } } } function controllerStateText(update, printFlags): String { var output:String = ""; var lastLength = output.length; for(var i = 0; i < 32; i++) { var mask = 1 << i; if(update.buttonPressedLow & mask) { output += "pressed: " + i + "\n"; } } if(printFlags && lastLength != output.length){ output += "buttonPressedLow: " + update.buttonPressedLow + "\n"; lastLength = output.length; } for(var i = 0; i < 32; i++) { var mask = 1 << i; if(update.buttonPressedHigh & mask) { output += "pressed: " + (i + 32) + "\n"; } } if(printFlags && lastLength != output.length){ output += "buttonPressedHigh: " + update.buttonPressedHigh + "\n"; lastLength = output.length; } for(var i = 0; i < 32; i++) { var mask = 1 << i; if(update.buttonTouchedLow & mask) { output += "touched: " + i + "\n"; } } if(printFlags && lastLength != output.length){ output += "buttonTouchedLow: " + update.buttonTouchedLow + "\n"; lastLength = output.length; } for(var i = 0; i < 32; i++) { var mask = 1 << i; if(update.buttonTouchedHigh & mask) { output += "touched: " + (i + 32) + "\n"; } } if(printFlags && lastLength != output.length){ output += "buttonTouchedHigh: " + update.buttonTouchedHigh + "\n"; lastLength = output.length; } for(var i = 0; i < 5; i++) { var x = update.axis[i*2]; var y = update.axis[i*2 + 1]; if(x != 0.0) { output += "x[" + i + "] = " + x + "\n"; } if(y != 0.0) { output += "y[" + i + "] = " + y + "\n"; } if(x != 0.0 || y != 0.0) { var vec2 = [x, y]; output += "mag: " + GlobalFunctions.vec2Mag(vec2) + "\n"; output += "quadrant: " + axisQuadrant(vec2) + "\n"; output += "region: " + axisRegion(vec2) + "\n"; } } return output; } function widgetToString(widget: Object): String { var output = ""; for (var key:String in widget) { output += key + ": " + widget[key] + "\n"; } return output; } // Build a list of widgets with interesting states function collectInterestingWidgets(handIdx): Array { var idxs = interestingWidgetIdxs(); var result = []; var widgets = widgetStates[handIdx]; for(var i = 0; i < idxs.length; i++) { var widget = widgets[idxs[i]]; if(widget.pressed || widget.touched || GlobalFunctions.vec2Mag(widget.axis)) { result.push(widget); } } return result; } var controllerTexts = ["", ""]; function controllerStateString(update): String { // Output all text prepared for each hand var handIdx = update.controllerHand-1 var text = controllerStateText(update); controllerTexts[handIdx] = text; var collectedWidgets = collectInterestingWidgets(handIdx); // Build a string representation of all interesting widgets var widgetText = ""; for(var i = 0; i < collectedWidgets.length; i++) { var widget = collectedWidgets[i]; widgetText += widgetToString(widget); } // Append widget text to the output for the cooresponding hand if(widgetText.length != 0) controllerTexts[handIdx] += "\n" + widgetText; var output = ""; if(controllerTexts[0].length != 0 || controllerTexts[1].length != 0) { output += "Skryim says: " + controllerName_Game + "\n"; output += "OpenVR says: " + controllerName_OpenVR + "\n"; output += "Skyui will use: " + controllerName + "\n"; output += "\n"; } if(controllerTexts[0].length != 0) { output += "Left controller: \n"; output += controllerTexts[0]; } if(controllerTexts[1].length != 0) { output += "Right controller: \n"; output += controllerTexts[1]; } return output; } private static var _instance: VRInput; public static function get instance(): VRInput { if (_instance == null) _instance = new VRInput(); return _instance; } private function VRInput() { init(); } function setup() { //Debug.log("VRInput.setup()"); var skyui = skse["plugins"]["skyui"]; if(skyui != undefined) { Debug.log("Registering to receive VR input"); skyui.RegisterInputHandler(this, "handleVRButtonUpdate"); } else { Debug.log("skyui plugin not available"); } } function teardown() { //Debug.log("VRInput.teardown()"); var skyui = skse["plugins"]["skyui"]; if(skyui != undefined) { Debug.log("Unregistering to receive VR input"); skyui.UnregisterInputHandler(this, "handleVRButtonUpdate"); } } function pauseInput(type) { switch(type) { case "self": ignoreInput = true; break; case "game": skse["plugins"]["vrinput"].ShutoffButtonEventsToGame(true); break; case "all": pauseInput("game"); pauseInput("self"); break; } } function resumeInput(type) { switch(type) { case "self": ignoreInput = false; break; case "game": skse["plugins"]["vrinput"].ShutoffButtonEventsToGame(false); break; case "all": resumeInput("game"); resumeInput("self"); break; } } static public function inputEventSummary(event): String { return "phase: " + event.phaseName + ", event: " + event.eventName + ", widget: " + event.curState.widgetName; } // Given a single array of strings, describing how an action should be triggered, // fill out an object to help make trigger comparison easier. public function makeActionTriggerCondition(specs: Array) { if(logDetails) { Debug.log(">>> makeActionTriggerCondition"); Debug.dump("specs", specs); } var condition = new Object(); for(var i = 0; i < specs.length; i++) { var spec = specs[i]; if(logDetails) { Debug.log("processing spec: " + spec); Debug.dump("condition cur:", condition); } switch(spec) { case 'leftHand': case 'rightHand': if(logDetails) { Debug.log("--- 1 ---"); } condition["role"] = spec; break; case 'start': case 'end': if(logDetails) { Debug.log("--- 2 ---"); } condition["eventName"] = spec; break; case 'top': case 'right': case 'left': case 'bottom': case 'center': if(logDetails) { Debug.log("--- 3 ---"); } condition["region"] = spec; break; case 'touched': case 'pressed': case 'clicked': if(logDetails) { Debug.log("--- 4 ---"); } condition["phaseName"] = spec; break; case 'touch': case 'press': case 'click': if(logDetails) { Debug.log("--- 5 ---"); } condition["phaseName"] = spec + "ed"; break; case 'touchpad': case 'thumbstick': case 'application menu': case 'grip': case 'trigger': case 'b button': case 'a button': case 'x button': case 'y button': if(logDetails) { Debug.log("--- 6 ---"); } condition["widgetName"] = spec; break; default: if(logDetails) { Debug.log("--- 7 ---"); Debug.log("Unhandled spec string: " + spec); } break; } } // Default phaseName is "clicked" if(!condition["phaseName"]) condition["eventName"] = "clicked"; // Default eventName is "start" if(!condition["eventName"]) condition["eventName"] = "start"; if(logDetails) { Debug.dump("condition final:", condition); } return condition; } // Given an object that maps from "action name" => "trigger condition strings", // return an object that maps from "action name" => "trigger condition" public function generateActionTriggerConditions(settings: Object) { if(logDetails) { Debug.log(">>> generateActionTriggerConditions") Debug.dump("settings", settings); } var actionConditions = new Object; for(var key in settings) { actionConditions[key] = makeActionTriggerCondition(settings[key]); actionConditions[key]["name"] = key; } if(logDetails) { Debug.log("<<< generateActionTriggerConditions") } return actionConditions; } // Given a list of actions the event object sent to vrHandleInput, // return the action name that has been triggered public function triggeredAction(actionConditions: Object, event: Object) { if(logDetails) { Debug.log(">>> triggeredAction") Debug.dump("event", event); } var state = event.curState; var candidate = undefined; for(var actionName in actionConditions) { var condition = actionConditions[actionName]; if(logDetails) { Debug.dump("condition", condition); Debug.log("-- 1 --"); } var role = condition["role"] if(role && state.controllerRole != role) continue; if(logDetails) { Debug.log("-- 2 --"); } var widgetName = condition["widgetName"] if(widgetName && state.widgetName.toLowerCase() != widgetName.toLowerCase()) continue; if(logDetails) { Debug.log("-- 3 --"); } var phaseName = condition["phaseName"] if(phaseName && event.phaseName != phaseName) continue; if(logDetails) { Debug.log("-- 4 --"); } var eventName = condition["eventName"] if(eventName && eventName != event.eventName) continue; if(logDetails) { Debug.log("-- 5 --"); } var region = condition["region"] if(region && region != VRInput.axisRegion(state.axis)) continue; if(logDetails) { Debug.log("<<< triggeredAction: " + actionName) } return actionName; } if(logDetails) { Debug.log("<<< triggeredAction: no match") } return undefined; } } ================================================ FILE: src/Common/skyui/components/BottomBarMappedButton.as ================================================ import skyui.components.MappedButton; import skyui.util.GlobalFunctions; import skyui.defines.Screen; // Specialized version of a MappedButton for the BottomBar // We vertically center the button after the button is updated. // Note that we're assuming information regarding the bottombar // layout and where mapped buttons would be. // // This is not suitable for general use in other layouts. class skyui.components.BottomBarMappedButton extends MappedButton { public function update(): Void { super.update(); // Position this button so it's centered in the bottombar // We're assuming the following display tree: // bottom bar // |- bg // |- button panel // |- Mapped Button // // Note that the bg provides a stable/static dimension for the bottombar. // Since we're tweaking the layout of the bottombar programmatically, it's not a good // idea to perform the calculation with respect to the dynamic size of the bottombar since // might change if the button or text size were to ever exceed the static height of the // bottombar, then the layout calculation would be thrown off from that point on. // // To center the ourselves to the bottom bar, we need to: // ( center self with respect to the bottombar ) - (_y offset introduced by button panel) // // Also note that, sometimes, the bottombar may fall outside of the rendering area. Having // an oversized element like this makes design time tweaking a bit more straigtforward. // If we want to tweak the position at runtime, it means we can't just use the `bg` object // as a sizing reference directly. We need to figure out how much of the element is actually // visible and use that as the height of the bottombar. var targetHeight = textField._height; var bottombar = _parent._parent; var reference = bottombar.centerReference != undefined ? bottombar.centerReference : bottombar.bg; var referenceOrigin:Object = {x: 0, y:0}; reference.localToGlobal(referenceOrigin); var visibleHeight = GlobalFunctions.clamp(referenceOrigin.y + reference._height, 0, Screen.height) - referenceOrigin.y; _y = ((visibleHeight - targetHeight) / 2) - _parent._y + reference._y; } } ================================================ FILE: src/Common/skyui/components/ButtonPanel.as ================================================ class skyui.components.ButtonPanel extends MovieClip { /* PRIVATE VARIABLES */ // Number of buttons that are actually in use private var _buttonCount: Number = 0; private var _updateID: Number; /* PROPERTIES */ public var buttons: Array; public var isReversed: Boolean = false; public var buttonRenderer: String; public var maxButtons: Number = 0; public var buttonInitializer: Object; public var spacing: Number = 10; /* INITIALIZATION */ public function ButtonPanel(a_buttonRenderer: String, a_maxButtons: Number, a_buttonInitializer: Object) { buttons = []; if (a_buttonRenderer != undefined) buttonRenderer = a_buttonRenderer; if (a_maxButtons != undefined) maxButtons = a_maxButtons; if (a_buttonInitializer != undefined) buttonInitializer = a_buttonInitializer; for (var i=0; i 0; } public function hideButtons(): Void { for (var i=0; i < buttons.length; i++) buttons[i]._visible = false; } public function clearButtons(): Void { _buttonCount = 0; for (var i=0; i < buttons.length; i++) { var btn = buttons[i]; btn._visible = false; btn.label = ""; btn._x = 0; } } public function addButton(a_buttonData: Object): MovieClip { if (_buttonCount >= buttons.length) return; var btn = buttons[_buttonCount]; btn.setButtonData(a_buttonData); btn._visible = true; _buttonCount++; return btn; } public function updateButtons(a_bInstant: Boolean): Void { if (a_bInstant) doUpdateButtons(); else if (!_updateID) _updateID = setInterval(this, "doUpdateButtons", 1); } /* PRIVATE FUNCTIONS */ private function doUpdateButtons(): Void { clearInterval(_updateID); delete _updateID; var offset = 0; for (var i=0; i < buttons.length; i++) { var btn = buttons[i]; if (btn.label.length > 0 && btn._visible) { btn.update(); if (isReversed) { offset -= btn.width; btn._x = offset; offset -= spacing; } else { btn._x = offset; offset += btn.width + spacing; } } } } } ================================================ FILE: src/Common/skyui/components/MappedButton.as ================================================ import Shared.ButtonChange; import gfx.controls.Button; import skyui.defines.Input; import skyui.util.GlobalFunctions; import skyui.defines.ButtonArtNames; class skyui.components.MappedButton extends Button { /* PRIVATE VARIABLES */ private static var _arrayWrap = []; private var _platform: Number; private var _controlInfos: Array; /* STAGE ELEMENTS */ public var background: MovieClip; public var textField: TextField; /* PROPERTIES */ public function set hiddenBackground(a_flag: Boolean) { background._visible = !a_flag; } public function get hiddenBackground(): Boolean { return background._visible; } public function get width(): Number { return background._width; } public function set width(a_value: Number) { background._width = a_value; } public var buttonArt: Array; /* INITIALIZATION */ function MappedButton() { super(); _controlInfos = []; buttonArt = []; for (var i=0; this["buttonArt" + i] != undefined; i++) buttonArt.push(this["buttonArt" + i]); } function onLoad(): Void { super.onLoad(); if (_parent.onButtonLoad != undefined) _parent.onButtonLoad(this); } private function updateAfterStateChange(): Void { if (textField != null && _label != null) { textField.autoSize = "left"; textField.text = _label; textField._width = textField.getLineMetrics(0).width; } update(); dispatchEvent({type:"stateChange", state:state}); } /* PUBLIC FUNCTIONS */ public function setPlatform(a_platform: Number): Void { _platform = a_platform; if (label != null && label.length > 0) update(); } public function setButtonData(a_buttonData: Object): Void { textField.autoSize = "left"; label = a_buttonData.text; // Update textfield size - autoSize doesn't work reliably for large resolutions textField._width = textField.getLineMetrics(0).width; setMappedControls(a_buttonData.controls); } public function setMappedControls(a_controls): Void { // FIXME? a_controls is now stored directly // This means the caller may potentially change the data and mess things up. // If this becomes a problem, duplicate the incoming controls data constraints=null; _controlInfos.splice(0); // Accept either single object or array for multiple icons var controls: Array; if (a_controls instanceof Array) { controls = a_controls; } else { _arrayWrap[0] = a_controls; controls = _arrayWrap; } for (var i=0; i 0) { icon._visible = true; icon.gotoAndStop(_controlInfos[i].keyCode); // Scale up the icon up to the target height icon._scaleX = 1.0; icon._scaleY = 1.0; var scaleMult = targetHeight / icon._height; icon._scaleY = scaleMult; icon._scaleX = scaleMult; icon._x = xOffset icon._y = (_height - icon._height) / 2; xOffset += icon._width - 2; } else { icon._visible = false; } } textField._x = xOffset + 3; xOffset += textField._width + 8; background._width = xOffset; } } ================================================ FILE: src/Common/skyui/components/MaskedTextArea.as ================================================ import Shared.GlobalFunc; import gfx.core.UIComponent; import gfx.utils.Constraints; import TextField.StyleSheet; class skyui.components.MaskedTextArea extends UIComponent { /* PRIVATE VARIABLES */ private var _constraints: Constraints; private var _scrollPosition:Number = 0; private var _scrollDelta: Number = 25; private var _scrollBarAutoHide: Boolean = false; /* STAGE ELEMENTS */ private var textField: TextField; private var mask: MovieClip; private var _scrollBar:MovieClip; /* INITIALIZATION */ function MaskedTextArea() { super(); GlobalFunc.MaintainTextFormat(); } public function configUI(): Void { super.configUI(); _constraints = new Constraints(this, true); _constraints.addElement(textField, Constraints.ALL); textField.html = true; textField.verticalAutoSize = "top"; Mouse.addListener(this); initSize(); sizeIsInvalid = true; } /* PROPERTIES */ public function get scrollBar(): Object { return _scrollBar; } public function set scrollBar(a_val: Object):Void { if (_scrollBar != null) { _scrollBar.removeEventListener("scroll", this, "handleScroll"); _scrollBar.removeEventListener("change", this, "handleScroll"); _scrollBar.focusTarget = null; } _scrollBar = MovieClip(a_val); invalidate(); if (_scrollBar == null) return; if (_scrollBar.setScrollProperties != null) { _scrollBar.addEventListener("scroll", this, "handleScroll"); } else { _scrollBar.addEventListener("change", this, "handleScroll"); } _scrollBar.focusTarget = this; _scrollBar.tabEnabled = false; updateScrollBar(); } public function get scrollBarAutoHide(): Boolean { return _scrollBarAutoHide; } public function set scrollBarAutoHide(a_val: Boolean): Void { _scrollBarAutoHide = a_val; if (_scrollBar == null) return; _scrollBar.visible = (_scrollBarAutoHide)? (textField._height > __height): true; } public function get scrollPosition(): Number { return _scrollPosition; } public function set scrollPosition(a_val: Number): Void { setScrollPosition(a_val); } private function setScrollPosition(a_val: Number, a_force: Boolean): Void { var maxscroll = (textField._height - __height); a_val = Math.max(0, Math.min(maxscroll, Math.round(a_val))); if (_scrollPosition == a_val && !a_force) { return; } _scrollPosition = a_val; textField._y = -_scrollPosition; updateScrollBar(); } public function get text(): String { return textField.text; } public function set text(a_val: String): Void { textField.html = false; textField.SetText(a_val, false); setScrollPosition(0, true); } public function get styleSheet(): StyleSheet { return textField.styleSheet; } public function set styleSheet(a_val: StyleSheet): Void { textField.styleSheet = a_val; } public function get htmlText(): String { return textField.htmlText; } public function set htmlText(a_val: String): Void { textField.html = true; textField.SetText(a_val, true); textField.htmlText = a_val; setScrollPosition(0, true); } /* PRIVATE FUNCTIONS */ private function draw(): Void { if (sizeIsInvalid) { textField._width = mask._width = __width; mask._height = __height; if (_constraints != undefined) _constraints.update(__width, textField._height); //Counter-Scales text field } updateScrollBar(); } private function scrollWheel(delta:Number): Void { scrollPosition -= delta * _scrollDelta; } private function updateScrollBar(): Void { var maxscroll = (textField._height - __height); var max:Number = Math.max(0, maxscroll); if (_scrollBar.setScrollProperties != null) { _scrollBar.setScrollProperties(__height, 0, max); } else { _scrollBar.minimum = 0; _scrollBar.maximum = max; } _scrollBar.position = _scrollPosition; _scrollBar.trackScrollPageSize = 10*_scrollDelta; _scrollBar.pageScrollSize = _scrollDelta; _scrollBar.visible = (_scrollBarAutoHide)? (textField._height > __height): true; } private function handleScroll(event: Object): Void { var newPosition: Number = event.target.position; if (isNaN(newPosition)) { return; } scrollPosition = newPosition; } private function anchorPress(a_arguments: String): Void { var args: Array = a_arguments.split(","); dispatchEvent({type: args[0], args: args.slice(1)}); } } ================================================ FILE: src/Common/skyui/components/Meter.as ================================================ import skyui.util.ColorFunctions; import Shared.GlobalFunc; import flash.geom.Transform; import flash.geom.ColorTransform; import flash.geom.Matrix; class skyui.components.Meter extends MovieClip { /* CONSTANTS */ public static var FILL_DIRECTION_LEFT: String = "left"; public static var FILL_DIRECTION_RIGHT: String = "right"; public static var FILL_DIRECTION_BOTH: String = "both"; /* PRIVATE VARIABLES */ private var _originalWidth: Number; private var _originalHeight: Number; private var _originalCapWidth: Number; private var _originalCapHeight: Number; private var _originalMeterFillHolderWidth: Number; private var _meterFrameContent: MovieClip; private var _meterFillHolder: MovieClip; private var _meterFillContent: MovieClip; private var _meterFlashAnim: MovieClip; private var _meterBarAnim: MovieClip; private var _meterBar: MovieClip; private var _currentPercent: Number; private var _targetPercent: Number; private var _fillDelta: Number = 0.02; private var _emptyDelta: Number = 0.03; private var _emptyIdx: Number; private var _fullIdx: Number; private var _fillDirection: String; private var _secondaryColor: Number; private var _primaryColor: Number; private var _flashColor: Number; private var _flashColorAuto: Boolean = false; private var __width: Number; private var __height: Number; private var _initialized: Boolean = false; /* STAGE ELEMENTS */ public var meterContent: MovieClip; public var background: MovieClip; /* INITIALIZATION */ public function Meter() { super(); background._visible = meterContent.capBackground._visible = false; // Set internal dimensions to stage dimensions __width = _width; __height = _height; _meterFrameContent = meterContent.meterFrameHolder.meterFrameContent; _meterFillHolder = meterContent.meterFillHolder; _meterFillContent = _meterFillHolder.meterFillContent; _meterFlashAnim = _meterFrameContent.meterFlashAnim; _meterBarAnim = _meterFillContent.meterBarAnim; _meterBar = _meterBarAnim.meterBar; _originalWidth = background._width; _originalHeight = background._height; _originalCapWidth = meterContent.capBackground._width; _originalCapHeight = meterContent.capBackground._height; _originalMeterFillHolderWidth = _meterFillHolder._width; _meterFillHolder._x = _originalCapWidth; // Set stage dimensions to original dimensions and invalidate size _width = _originalWidth; _height = _originalHeight; } public function onLoad(): Void { invalidateSize(); invalidateFillDirection(); onEnterFrame = enterFrameHandler; _initialized = true; } /* PROPERTIES */ public function get width(): Number { return __width; } public function set width(a_width: Number): Void { if (__width == a_width) return; __width = a_width; if (_initialized) invalidateSize(); } public function get height(): Number { return background._height; } public function set height(a_height: Number): Void { if (__height == a_height) return; __height = a_height; if (_initialized) invalidateSize(); } public function setSize(a_width: Number, a_height: Number): Void { if (__width == a_width && __height == a_height) return; __width = a_width; __height = a_height; if (_initialized) invalidateSize(); } public function get color(): Number { return _primaryColor; } public function set color(a_primaryColor: Number): Void { var lightColor: Number = (a_primaryColor == undefined)? 0xFFFFFF: ColorFunctions.validHex(a_primaryColor); if (lightColor == _primaryColor) return; _primaryColor = lightColor; var darkColorHSV: Array = ColorFunctions.hexToHsv(lightColor); darkColorHSV[2] -= 40; _secondaryColor = ColorFunctions.hsvToHex(darkColorHSV); if (_initialized) invalidateColor(); } public function setColors(a_primaryColor: Number, a_secondaryColor: Number, a_flashColor: Number): Void { // Wasteful checking.. //if (a_primaryColor != undefined && _primaryColor == a_primaryColor && _secondaryColor == a_secondaryColor) // return; flashColor = a_flashColor; if (a_secondaryColor == undefined || a_secondaryColor < 0x000000) { color = a_primaryColor; return; } _primaryColor = (a_primaryColor == undefined)? 0xFFFFFF: ColorFunctions.validHex(a_primaryColor); _secondaryColor = ColorFunctions.validHex(a_secondaryColor); if (_initialized) invalidateColor(); } public function get flashColor(): Number { return _flashColor; } public function set flashColor(a_flashColor: Number): Void { var RRGGBB: Number; _flashColorAuto = false; if ((a_flashColor < 0x000000 || a_flashColor == undefined) && _primaryColor != undefined) { RRGGBB = _primaryColor; _flashColorAuto = true; } else if (a_flashColor == undefined) { RRGGBB = 0xFFFFFF; } else { RRGGBB = ColorFunctions.validHex(a_flashColor); } if (_flashColor == RRGGBB) return; _flashColor = RRGGBB; if (_initialized) invalidateFlashColor(); } public function get fillDirection(): String { return _fillDirection; } public function set fillDirection(a_fillDirection: String): Void { setFillDirection(a_fillDirection) } public function setFillDirection(a_fillDirection, a_restorePercent: Boolean): Void { var fillDirection: String = a_fillDirection.toLowerCase(); if (_fillDirection == fillDirection && !a_restorePercent) return; _fillDirection = fillDirection; if (_initialized) invalidateFillDirection(a_restorePercent); } public function get percent(): Number { return _targetPercent; } public function set percent(a_percent: Number): Void { setPercent(a_percent); } public function setPercent(a_percent: Number, a_force: Boolean): Void { _targetPercent = Math.min(1, Math.max(a_percent, 0)); if (a_force) { _currentPercent = _targetPercent; var meterFrame: Number = Math.floor(GlobalFunc.Lerp(_emptyIdx, _fullIdx, 0, 1, _currentPercent)); _meterBarAnim.gotoAndStop(meterFrame); } } public function startFlash(a_force: Boolean): Void { // meterFlashing is set on the timeline and is false once the animation has finished if (_meterFlashAnim.meterFlashing && !a_force) { return; } _meterFlashAnim.gotoAndPlay("StartFlash"); } /* PRIVATE FUNCTIONS */ private function invalidateSize(): Void { var safeWidth: Number = _originalCapWidth * 3; // Safe width is 3* size of cap var safeHeight: Number; if (__width < safeWidth) //3 times cap width is our minumum __width = safeWidth; // Safe height of meter is 80% of the max height safeHeight = ((_originalCapHeight/_originalCapWidth) * __width/2) * 0.80; if (__height > safeHeight) __height = safeHeight; background._width = __width; background._height = __height; // Calculate scaling percent of the meter based on heights var scalePercent: Number = __height/_originalHeight; // Scale the meterContent based on height so the caps AR is maintained meterContent._xscale = meterContent._yscale = scalePercent * 100; // Scale inner content // Scale meterFrameContent instead of meterFrameHolder due to scale9Grid _meterFrameContent._width = __width / scalePercent; // newWidth = oldWidth * newPercent/oldPercent /. newPercent -> 100 _meterFillHolder._xscale = ((_meterFrameContent._width - 2*_originalCapWidth)/_originalMeterFillHolderWidth) * 100; } private function invalidateFillDirection(a_restorePercent: Boolean): Void { switch(_fillDirection) { case FILL_DIRECTION_LEFT: case FILL_DIRECTION_BOTH: case FILL_DIRECTION_RIGHT: break; default: _fillDirection = FILL_DIRECTION_LEFT; } _meterFillContent.gotoAndStop(_fillDirection); drawMeterGradients(); _meterBarAnim.gotoAndStop("Full"); _fullIdx = _meterBarAnim._currentframe; _meterBarAnim.gotoAndStop("Empty"); _emptyIdx = _meterBarAnim._currentframe; if (a_restorePercent || !_initialized) setPercent(_currentPercent, true); else setPercent(0, true); // Reset to 0, assume that if fillDirection is changed, meter data provider changed } private function drawMeterGradients(): Void { // Draws the meter var w: Number = _meterBar._width; var h: Number = _meterBar._height; var meterBevel: MovieClip = _meterBar.meterBevel; var meterShine: MovieClip = _meterBar.meterShine; var colors: Array = [0xCCCCCC, 0xFFFFFF, 0x000000, 0x000000, 0x000000]; var alphas: Array = [10, 60, 0, 10, 30]; //var ratios: Array = [0, 25, 25, 140, 153, 153, 255]; var ratios: Array = [0, 115, 128, 128, 255]; var matrix: Matrix = new Matrix(); if (meterShine != undefined) return; meterShine = _meterBar.createEmptyMovieClip("meterShine", 2); meterBevel.swapDepths(1); matrix.createGradientBox(w, h, Math.PI/2); meterShine.beginGradientFill("linear", colors, alphas, ratios, matrix); meterShine.moveTo(0,0); meterShine.lineTo(w, 0); meterShine.lineTo(w, h); meterShine.lineTo(0, h); meterShine.lineTo(0, 0); meterShine.endFill(); invalidateColor(); } private function invalidateColor(): Void { var colors: Array; var alphas: Array; var ratios: Array; var w: Number = _meterBar._width; var h: Number = _meterBar._height; var meterGradient: MovieClip = _meterBar.meterGradient; var matrix: Matrix = new Matrix(); if (meterGradient != undefined) meterGradient.removeMovieClip(); meterGradient = _meterBar.createEmptyMovieClip("meterGradient", 0); switch(_fillDirection) { case FILL_DIRECTION_LEFT: colors = [_secondaryColor, _primaryColor]; alphas = [100, 100]; ratios = [0, 255]; break; case FILL_DIRECTION_BOTH: colors = [_secondaryColor, _primaryColor, _secondaryColor]; alphas = [100, 100, 100]; ratios = [0, 127, 255]; break; case FILL_DIRECTION_RIGHT: default: colors = [_primaryColor, _secondaryColor]; alphas = [100, 100]; ratios = [0, 255]; } matrix.createGradientBox(w, h); meterGradient.beginGradientFill("linear", colors, alphas, ratios, matrix); meterGradient.moveTo(0,0); meterGradient.lineTo(w, 0); meterGradient.lineTo(w, h); meterGradient.lineTo(0, h); meterGradient.lineTo(0, 0); meterGradient.endFill(); if (_flashColorAuto || !_initialized) { if (_flashColorAuto) _flashColor = _primaryColor; invalidateFlashColor(); } } private function invalidateFlashColor(): Void { var tf: Transform = new Transform(_meterFlashAnim); var colorTf: ColorTransform = new ColorTransform(); colorTf.rgb = _flashColor; tf.colorTransform = colorTf; } private function enterFrameHandler(): Void { /*if (!_initialized) { _currentPercent = _targetPercent; } else*/ if (_targetPercent == _currentPercent) { return; } if (_currentPercent < _targetPercent) { _currentPercent = _currentPercent + _fillDelta; if (_currentPercent > _targetPercent) _currentPercent = _targetPercent; } else { _currentPercent = _currentPercent - _emptyDelta; if (_currentPercent < _targetPercent) _currentPercent = _targetPercent; } _currentPercent = Math.min(1, Math.max(_currentPercent, 0)); var meterFrame: Number = Math.floor(GlobalFunc.Lerp(_emptyIdx, _fullIdx, 0, 1, _currentPercent)); _meterBarAnim.gotoAndStop(meterFrame); } } ================================================ FILE: src/Common/skyui/components/SearchWidget.as ================================================ import flash.utils.Timer; import gfx.events.EventDispatcher; import gfx.managers.FocusHandler; import gfx.ui.NavigationCode; import gfx.ui.InputDetails; import Shared.GlobalFunc; import skyui.util.ConfigManager; import skyui.util.Debug; import skyui.VRInput; class skyui.components.SearchWidget extends MovieClip { /* CONSTANTS */ private static var S_FILTER = "$FILTER"; /* PRIVATE VARIABLES */ private var _previousFocus: Object; private var _currentInput: String; private var _lastInput: String; private var _bActive: Boolean; private var _bRestoreFocus: Boolean = false; private var _bEnableAutoupdate: Boolean; private var _updateDelay: Number; private var _updateTimerId: Number; /* STAGE ELEMENTS */ public var textField: TextField; public var icon: MovieClip; /* PROPERTIES */ public var isDisabled: Boolean = false; /* INITIALIZATION */ public function SearchWidget() { super(); EventDispatcher.initialize(this); textField.onKillFocus = function(a_newFocus: Object) { _parent.endInput(); }; textField.SetText(S_FILTER); ConfigManager.registerLoadCallback(this, "onConfigLoad"); } /* PUBLIC FUNCTIONS */ // @mixin by gfx.events.EventDispatcher public var dispatchEvent: Function; public var dispatchQueue: Function; public var hasEventListener: Function; public var addEventListener: Function; public var removeEventListener: Function; public var removeAllEventListeners: Function; public var cleanUpEvents: Function; public function onConfigLoad(event): Void { var config = event.config; _bEnableAutoupdate = config.SearchBox.autoupdate.enable; _updateDelay = config.SearchBox.autoupdate.delay; } public function onPress(a_mouseIndex, a_keyboardOrMouse) { Debug.log("In onPress!"); } public function onRelease(a_mouseIndex, a_keyboardOrMouse) { //Debug.log("In onRelease!"); //setTimeout(startInput, 100); startInput(); } public function startInput(): Void { //Debug.log("SearchWidget::startInput()"); if (_bActive || isDisabled) return; //Debug.log("SearchWidget::startInput() rest"); _previousFocus = FocusHandler.instance.getFocus(0); _currentInput = _lastInput = undefined; textField.SetText(""); textField.type = "input"; textField.noTranslate = true; textField.selectable = true; Selection.setFocus(textField); Selection.setSelection(0,0); _bActive = true; // We're about to switch control over to the virtual keyboard // While the keyboard is up and running, we'll want to stop processing input // so we're not accidentally operating on something in the menu while entering text. VRInput.instance.pauseInput("all"); // Show the keyboard skse["plugins"]["skyui"].ShowVirtualKeyboard("skyui", "Search", "Item name", "", this, recvVirtualKeyboardInput); //Debug.log("sending inputStart event and entering autoupdate loop"); dispatchEvent({type: "inputStart"}); if ( _bEnableAutoupdate) { this.onEnterFrame = function() { refreshInput(); if (_currentInput != _lastInput) { _lastInput = _currentInput; if (_updateTimerId != undefined) { clearInterval(_updateTimerId); } _updateTimerId = setInterval(this, "updateInput", _updateDelay); } }; } } private function recvVirtualKeyboardInput(text:String, err:Number): Void { //Debug.log("recvVirtualKeyboardInput: ", text, err); textField.text = text; endInput(); } public function endInput(): Void { //Debug.log("SearchWidget::endInput()"); if (!_bActive) return; //Debug.log("SearchWidget::endInput() rest"); delete this.onEnterFrame; VRInput.instance.resumeInput("all"); textField.type = "dynamic"; textField.noTranslate = false; textField.selectable = false; textField.maxChars = null; var bPrevEnabled = _previousFocus.focusEnabled; _previousFocus.focusEnabled = true; Selection.setFocus(_previousFocus,0); _previousFocus.focusEnabled = bPrevEnabled; _bActive = false; //skse.AllowTextInput(false); refreshInput(); if (_currentInput != undefined) { dispatchEvent({type: "inputEnd", data: _currentInput}); } else { textField.SetText(S_FILTER); dispatchEvent({type: "inputEnd", data: ""}); } } // @GFx public function handleInput(details: InputDetails, pathToFocus: Array): Boolean { //Debug.log("search widget handle input"); Debug.dump("InputDetails", details, false, 0); if (GlobalFunc.IsKeyPressed(details)) { /* if (details.navEquivalent == NavigationCode.ENTER) { Debug.log("Ending: enter key detected"); endInput(); } else if (details.navEquivalent == NavigationCode.TAB || details.navEquivalent == NavigationCode.ESCAPE) { Debug.log("Ending: tab or escape"); clearText(); endInput(); } */ var nextClip = pathToFocus.shift(); if (nextClip.handleInput(details, pathToFocus)) return true; } return false; } /* PRIVATE FUNCTIONS */ private function clearText(): Void { textField.SetText(""); } private function refreshInput(): Void { var t = GlobalFunc.StringTrim(textField.text); if (t != undefined && t != "" && t != S_FILTER) { _currentInput = t; } else { _currentInput = undefined; } } private function updateInput(): Void { if (_updateTimerId != undefined) { clearInterval(_updateTimerId); _updateTimerId = undefined; if (_currentInput != undefined) { dispatchEvent({type: "inputChange", data: _currentInput}); } else { dispatchEvent({type: "inputChange", data: ""}); } } } } ================================================ FILE: src/Common/skyui/components/Slider.as ================================================ import gfx.ui.InputDetails; import gfx.controls.Button; import gfx.utils.Constraints; import gfx.ui.NavigationCode; class skyui.components.Slider extends gfx.controls.Slider { /* STAGE ELEMENTS */ public var leftArrow: Button; public var rightArrow: Button; /* INITIALIATZION */ function Slider() { super(); } /* PROPERTIES */ function get disabled(): Boolean { return super.disabled; } public function set disabled(a_val: Boolean): Void { leftArrow.disabled = _disabled; rightArrow.disabled = _disabled; super.disabled = a_val; } /* PUBLIC FUNCTIONS */ public function handleInput(details: InputDetails, pathToFocus: Array): Boolean { if (super.handleInput(details, pathToFocus)) return true; if (details.value == "keyDown" || details.value == "keyHold") { switch (details.navEquivalent) { case NavigationCode.PAGE_DOWN: case NavigationCode.GAMEPAD_L1: value -= Math.abs(maximum - minimum) / 10; dispatchEventAndSound({type:"change"}); return true; case NavigationCode.PAGE_UP: case NavigationCode.GAMEPAD_R1: value += Math.abs(maximum - minimum) / 10; dispatchEventAndSound({type:"change"}); return true; } } return false; } /* PRIVATE FUNCTIONS */ private function configUI(): Void { super.configUI(); leftArrow.addEventListener("click", this, "scrollLeft"); rightArrow.addEventListener("click", this, "scrollRight"); leftArrow.autoRepeat = rightArrow.autoRepeat = true; leftArrow.focusTarget = rightArrow.focusTarget = this; var r:Number = _rotation; _rotation = 0; constraints.addElement(rightArrow, Constraints.RIGHT); constraints.addElement(track, Constraints.LEFT | Constraints.RIGHT); _rotation = r; // Override left and right offsets offsetLeft = leftArrow._width + thumb._width/2; offsetRight = rightArrow._width + thumb._width/2; } private function scrollLeft(event: Object): Void { value -= _snapInterval; dispatchEventAndSound({type: "change"}); } private function scrollRight(event: Object): Void { value += _snapInterval; dispatchEventAndSound({type: "change"}); } } ================================================ FILE: src/Common/skyui/components/TabBar.as ================================================ import gfx.events.EventDispatcher; import skyui.filter.ItemSortingFilter; class skyui.components.TabBar extends MovieClip { /* CONSTANTS */ public static var LEFT_TAB = 0; public static var RIGHT_TAB = 1; /* STAGE ELEMENTS */ public var image: MovieClip; public var leftLabel: TextField; public var rightLabel: TextField; public var leftIcon: MovieClip; public var rightIcon: MovieClip; public var leftButton: MovieClip; public var rightButton: MovieClip; /* PROPERTIES */ private var _activeTab: Number; public function get activeTab(): Number { return _activeTab; } public function set activeTab(a_index: Number) { _activeTab = a_index; if (a_index == LEFT_TAB) { leftIcon._alpha = 100; leftLabel._alpha = 100; rightIcon._alpha = 50; rightLabel._alpha = 50; image.gotoAndStop("left"); } else { leftIcon._alpha = 50; leftLabel._alpha = 50; rightIcon._alpha = 100; rightLabel._alpha = 100; image.gotoAndStop("right"); } } /* INITIALIZATION */ public function TabBar() { super(); EventDispatcher.initialize(this); activeTab = LEFT_TAB; } // @override MovieClip public function onLoad(): Void { leftLabel.textAutoSize = "shrink"; rightLabel.textAutoSize = "shrink"; leftButton.onPress = function(a_mouseIndex, a_keyboardOrMouse, a_buttonIndex) { _parent.tabPress(LEFT_TAB); }; leftButton.onPressAux = function(a_mouseIndex, a_keyboardOrMouse, a_buttonIndex) { _parent.tabPress(LEFT_TAB); }; leftButton.onRollOver = function() { if (_parent._activeTab != LEFT_TAB) { _parent.leftIcon._alpha = 75; _parent.leftLabel._alpha = 75; } }; leftButton.onRollOut = function() { if (_parent._activeTab != LEFT_TAB) { _parent.leftIcon._alpha = 50; _parent.leftLabel._alpha = 50; } }; rightButton.onPress = function(a_mouseIndex, a_keyboardOrMouse, a_buttonIndex) { _parent.tabPress(RIGHT_TAB); }; rightButton.onPressAux = function(a_mouseIndex, a_keyboardOrMouse, a_buttonIndex) { _parent.tabPress(RIGHT_TAB); }; rightButton.onRollOver = function() { if (_parent._activeTab != RIGHT_TAB) { _parent.rightIcon._alpha = 75; _parent.rightLabel._alpha = 75; } }; rightButton.onRollOut = function() { if (_parent._activeTab != RIGHT_TAB) { _parent.rightIcon._alpha = 50; _parent.rightLabel._alpha = 50; } }; } /* PUBLIC FUNCTIONS */ // @mixin by gfx.events.EventDispatcher public var dispatchEvent: Function; public var dispatchQueue: Function; public var hasEventListener: Function; public var addEventListener: Function; public var removeEventListener: Function; public var removeAllEventListeners: Function; public var cleanUpEvents: Function; public function setIcons(a_leftName: String, a_rightName: String): Void { leftIcon.gotoAndStop(a_leftName); rightIcon.gotoAndStop(a_rightName); } public function setLabelText(a_leftText: String, a_rightText: String): Void { leftLabel.SetText(a_leftText.toUpperCase()); rightLabel.SetText(a_rightText.toUpperCase()); } public function tabPress(a_tabIndex: Number): Void { dispatchEvent({type:"tabPress", index:a_tabIndex}); } public function tabToggle(): Void { tabPress(_activeTab == LEFT_TAB ? RIGHT_TAB : LEFT_TAB); } } ================================================ FILE: src/Common/skyui/components/colorswatch/ColorSquare.as ================================================ import gfx.controls.Button; import flash.geom.ColorTransform; import flash.geom.Transform; import skyui.util.ColorFunctions; class skyui.components.colorswatch.ColorSquare extends Button { /* PRIVATE VARIABLES */ private var _color: Number; /* STAGE ELEMENTS */ public var pigment: MovieClip public var selector: MovieClip; public function ColorSquare() { super(); } /* PROPERTIES */ public function set color(a_color: Number): Void { _color = a_color; setColor(_color); } public function get color(): Number { return _color; } /* PRIVATE FUNCTIONS */ private function setColor(a_color: Number): Void { var ct: ColorTransform = new ColorTransform(); ct.rgb = a_color; var t: Transform = new Transform(pigment); t.colorTransform = ct; ct.rgb = ((ColorFunctions.hexToHsv(a_color)[2] < 75)? 0xFFFFFF: 0x000000); t = new Transform(selector); t.colorTransform = ct; selector._alpha = 0; } } ================================================ FILE: src/Common/skyui/components/colorswatch/ColorSwatch.as ================================================ import gfx.controls.ButtonGroup; import Shared.GlobalFunc; import gfx.managers.FocusHandler; import gfx.ui.InputDetails; import gfx.ui.NavigationCode import skyui.util.GlobalFunctions; import skyui.components.colorswatch.ColorSquare; class skyui.components.colorswatch.ColorSwatch extends MovieClip { /* STAGE ELEMENTS */ public var background: MovieClip; /* PRIVATE VARIABLES */ private var _buttonGroup: ButtonGroup; private var _highestColorDepth: Number; private var _colorCols: Number; //Calculated from colorList.length and colorRows private var _selectedColor: Number; /* INITIALIZATION */ public function ColorSwatch() { super(); if (colorList == null) { colorList = [0x990033, 0xAD0073, 0xA17700, 0x803D0D, 0xBD4F19, 0x007A87, 0x162274, 0x4F2D7F, 0x56364D, 0x618E02, 0x008542, 0x5C4836, 0x999999, 0x000000, 0xCC0033, 0xE86BA5, 0xEAAB00, 0xB88454, 0xE37222, 0x99FFFF, 0x4060AF, 0x8C6CD0, 0x8F6678, 0x9EAB05, 0x19B271, 0xAA9C8F, 0xCCCCCC, 0xFFFFFF]; } GlobalFunctions.addArrayFunctions(); _colorCols = Math.floor(colorList.length/colorRows); _buttonGroup = new ButtonGroup(); _buttonGroup.name = "colorButtons"; var row, col: Number; var colorClip: MovieClip; for (var i: Number = 0; i < colorList.length; i++) { col = i % _colorCols; row = Math.floor(i/_colorCols); colorClip = attachMovie("ColorSquare", "ColorSquare" + i, getNextHighestDepth()) colorClip._x = (col * colorSize) - col; colorClip._y = (row * colorSize) - row; colorClip._width = colorClip._height = colorSize; colorClip.color = colorList[i]; colorClip.addEventListener("select", this, "onColorClipSelect"); _buttonGroup.addButton(ColorSquare(colorClip)); } background._width = _width; background._height = _height; _highestColorDepth = ((colorClip != undefined && colorList.length > 0)? colorClip.getDepth(): getNextHighestDepth()); } /* PROPERTIES */ public var colorRows: Number = 2; public var colorSize: Number = 25; public var colorList: Array; public function set selectedColor(a_color: Number): Void { _selectedColor = a_color; attemptSelectColor(_selectedColor); } public function get selectedColor(): Number { return _selectedColor; } /* PUBLIC FUNCTIONS */ public function handleInput(a_details: InputDetails, a_pathToFocus: Array): Boolean { var handledInput: Boolean = false; if (GlobalFunc.IsKeyPressed(a_details, false)) { var currentButtonIdx: Number = _buttonGroup.indexOf(_buttonGroup.selectedButton); var maxIndex: Number = _buttonGroup.length - 1; var newIndex: Number = currentButtonIdx; var row: Number = Math.floor(currentButtonIdx/_colorCols); var col: Number = currentButtonIdx % _colorCols; if (newIndex == -1) { switch (a_details.navEquivalent) { case NavigationCode.RIGHT: case NavigationCode.DOWN: newIndex = 0; handledInput = true; break; case NavigationCode.LEFT: case NavigationCode.UP: newIndex = maxIndex; handledInput = true; break; } } else { switch (a_details.navEquivalent) { case NavigationCode.UP: if (row > 0) newIndex -= _colorCols; else newIndex += _colorCols; handledInput = true; break; case NavigationCode.DOWN: if (row < (colorRows - 1)) newIndex += _colorCols; else newIndex -= _colorCols; handledInput = true; break; // L/R doesn't wrap /* case NavigationCode.LEFT: if (newIndex != 0) newIndex -= 1; else newIndex += maxIndex; handledInput = true; break; case NavigationCode.RIGHT: if (newIndex!= maxIndex) newIndex += 1 else newIndex -= maxIndex; handledInput = true; break; */ case NavigationCode.LEFT: if (col > 0) newIndex -= 1; else newIndex += _colorCols - 1; handledInput = true; break; case NavigationCode.RIGHT: if (col < (_colorCols - 1)) newIndex += 1 else newIndex -= _colorCols - 1; handledInput = true; break; } } if (newIndex != currentButtonIdx) _buttonGroup.setSelectedButton(_buttonGroup.getButtonAt(newIndex)); } return handledInput; } /* PRIVATE FUNCTIONS */ private function onColorClipSelect(event: Object): Void { var colorClip: ColorSquare = event.target; if (colorClip.selected) { _selectedColor = colorClip.color; colorClip._x -= (colorSize * 0.5/2); colorClip._y -= (colorSize * 0.5/2); colorClip._width = colorClip._height = colorSize * 1.5; colorClip.swapDepths(_highestColorDepth); colorClip.selector._alpha = 100; } else { colorClip._x += (colorSize * 0.5/2); colorClip._y += (colorSize * 0.5/2); colorClip._width = colorClip._height = colorSize; colorClip.selector._alpha = 0; } } private function attemptSelectColor(a_color: Number): Void { var buttonIndex: Number = colorList.indexOf(a_color); var colorClip: ColorSquare; if (buttonIndex == undefined) { colorClip = ColorSquare(_buttonGroup.getButtonAt(0)); } else { colorClip = ColorSquare(_buttonGroup.getButtonAt(buttonIndex)); _buttonGroup.setSelectedButton(colorClip); } FocusHandler.instance.setFocus(colorClip, 0); } } ================================================ FILE: src/Common/skyui/components/dialog/BasicDialog.as ================================================ import gfx.events.EventDispatcher; import mx.transitions.Tween; import mx.transitions.easing.None; import mx.utils.Delegate; class skyui.components.dialog.BasicDialog extends MovieClip { /* CONSTANTS */ public static var OPEN = 0; public static var CLOSED = 1; public static var OPENING = 2; public static var CLOSING = 3; /* PRIVATE VARIABLES */ private var _dialogState: Number = -1; private var _fadeTween: Tween; /* INITIALIZATION */ public function BasicDialog() { EventDispatcher.initialize(this); Mouse.addListener(this); } /* PUBLIC FUNCTIONS */ // @mixin by EventDispatcher public var dispatchEvent: Function; public var dispatchQueue: Function; public var hasEventListener: Function; public var addEventListener: Function; public var removeEventListener: Function; public var removeAllEventListeners: Function; public var cleanUpEvents: Function; public function openDialog(): Void { setDialogState(OPENING); if (_fadeTween) { _fadeTween.stop(); delete _fadeTween; } _fadeTween = new Tween(this, "_alpha", None.easeNone, 0, 100, 0.4, true); _fadeTween.FPS = 40; _fadeTween.onMotionFinished = Delegate.create(this, fadedInFunc); } public function closeDialog(): Void { setDialogState(CLOSING); if (_fadeTween) { _fadeTween.stop(); delete _fadeTween; } _fadeTween = new Tween(this, "_alpha", None.easeNone, 100, 0, 0.4, true); _fadeTween.FPS = 40; _fadeTween.onMotionFinished = Delegate.create(this, fadedOutFunc); } public var onDialogOpening: Function; public var onDialogOpen: Function; public var onDialogClosing: Function; public var onDialogClosed: Function; /* PRIVATE FUNCTIONS */ private function setDialogState(a_newState: Number): Void { if (_dialogState == a_newState) return; _dialogState = a_newState; if (a_newState == OPENING) { if (onDialogOpening) onDialogOpening(); dispatchEvent({type: "dialogOpening"}); } else if (a_newState == OPEN) { if (onDialogOpen) onDialogOpen(); dispatchEvent({type: "dialogOpen"}); } else if (a_newState == CLOSING) { if (onDialogClosing) onDialogClosing(); dispatchEvent({type: "dialogClosing"}); } else if (a_newState == CLOSED) { if (onDialogClosed) onDialogClosed(); dispatchEvent({type: "dialogClosed"}); removeAllEventListeners(); this.removeMovieClip(); } } private function fadedInFunc() { setDialogState(BasicDialog.OPEN); } private function fadedOutFunc() { setDialogState(BasicDialog.CLOSED); } } ================================================ FILE: src/Common/skyui/components/dialog/ColumnSelectDialog.as ================================================ import gfx.io.GameDelegate; import gfx.managers.FocusHandler; import gfx.ui.NavigationCode; import gfx.ui.InputDetails; import Shared.GlobalFunc; import skyui.components.list.ButtonEntryFormatter; import skyui.components.list.ButtonList; import skyui.components.list.BasicEnumeration; import skyui.components.list.ListLayout; import skyui.components.dialog.BasicDialog; import skyui.util.DialogManager; import skyui.util.ConfigManager; class skyui.components.dialog.ColumnSelectDialog extends BasicDialog { /* STAGE ELEMENTS */ public var list: ButtonList; /* PROPERTIES */ public var layout: ListLayout; /* CONSTRUCTORS */ public function ColumnSelectDialog() { super(); } /* PUBLIC FUNCTIONS */ // Constructor is too early to do anything with the embedded list if the Movie is created with attachMovie. public function onLoad(): Void { list.listEnumeration = new BasicEnumeration(list.entryList); list.addEventListener("itemPress", this, "onColumnToggle"); layout.addEventListener("layoutChange", this, "onLayoutChange"); setColumnListData(); } public function onDialogOpening(): Void { GameDelegate.call("PlaySound",["UIMenuBladeOpenSD"]); FocusHandler.instance.setFocus(list, 0); } public function onDialogClosing(): Void { GameDelegate.call("PlaySound",["UIMenuBladeCloseSD"]); layout.removeEventListener("layoutChange", this, "onLayoutChange"); } public function onColumnToggle(event: Object): Void { var entry = event.entry; ConfigManager.setOverride("ListLayout", "columns." + entry.id + ".hidden", !entry.value, entry.value ? "false" : "true"); } public function onLayoutChange(event: Object): Void { setColumnListData(); } // @GFx public function handleInput(details: InputDetails, pathToFocus: Array): Boolean { if (GlobalFunc.IsKeyPressed(details)) { if (details.navEquivalent == NavigationCode.TAB || details.navEquivalent == NavigationCode.ESCAPE || details.navEquivalent == NavigationCode.LEFT || details.navEquivalent == NavigationCode.RIGHT) { DialogManager.close(); return true; } } var nextClip = pathToFocus.shift(); return nextClip.handleInput(details, pathToFocus); } public function onMouseDown(): Void { for (var e = Mouse.getTopMostEntity(); e != undefined; e = e._parent) if (e == this) return; DialogManager.close(); } /* PRIVATE FUNCTIONS */ private function setColumnListData() { list.clearList(); var columnDescriptors = layout.columnDescriptors; for (var i=0; i= listEnumeration.size()) _selectedIndex = listEnumeration.size() - 1; UpdateList(); if (onInvalidate) onInvalidate(); } // @override BSList // @abstract public function UpdateList(): Void { } /* PRIVATE FUNCTIONS */ private function onItemPress(a_index: Number, a_keyboardOrMouse: Number): Void { if (disableInput || disableSelection || _selectedIndex == -1) return; if (a_keyboardOrMouse == undefined) a_keyboardOrMouse = SELECT_KEYBOARD; dispatchEvent({type: "itemPress", index: _selectedIndex, entry: selectedEntry, clip: selectedClip, keyboardOrMouse: a_keyboardOrMouse}); } private function onItemPressAux(a_index: Number, a_keyboardOrMouse: Number, a_buttonIndex: Number): Void { if (disableInput || disableSelection || _selectedIndex == -1 || a_buttonIndex != 1) return; if (a_keyboardOrMouse == undefined) a_keyboardOrMouse = SELECT_KEYBOARD; dispatchEvent({type: "itemPressAux", index: _selectedIndex, entry: selectedEntry, clip: selectedClip, keyboardOrMouse: a_keyboardOrMouse}); } private function onItemRollOver(a_index: Number): Void { if (isListAnimating || disableSelection || disableInput) return; doSetSelectedIndex(a_index, SELECT_MOUSE); isMouseDrivenNav = true; } private function onItemRollOut(a_index: Number): Void { if (!isAutoUnselect) return; if (isListAnimating || disableSelection || disableInput) return; doSetSelectedIndex(-1, SELECT_MOUSE); isMouseDrivenNav = true; } private function doSetSelectedIndex(a_newIndex: Number, a_keyboardOrMouse: Number): Void { if (disableSelection || a_newIndex == _selectedIndex) return; // Selection is not contained in current entry enumeration, ignore if (a_newIndex != -1 && getListEnumIndex(a_newIndex) == undefined) return; var oldIndex = _selectedIndex; _selectedIndex = a_newIndex; if (oldIndex != -1) { var clip = _entryClipManager.getClip(_entryList[oldIndex].clipIndex); clip.setEntry(_entryList[oldIndex], listState); } if (_selectedIndex != -1) { var clip = _entryClipManager.getClip(_entryList[_selectedIndex].clipIndex); clip.setEntry(_entryList[_selectedIndex], listState); } dispatchEvent({type: "selectionChange", index: _selectedIndex, keyboardOrMouse: a_keyboardOrMouse}); } private function getClipByIndex(a_index: Number): MovieClip { return _entryClipManager.getClip(a_index); } private function setClipCount(a_count: Number) { _entryClipManager.clipCount = a_count; } private function getSelectedListEnumIndex(): Number { return listEnumeration.lookupEnumIndex(_selectedIndex); } private function getListEnumIndex(a_index: Number): Number { return listEnumeration.lookupEnumIndex(a_index); } private function getListEntryIndex(a_index: Number): Number { return listEnumeration.lookupEntryIndex(a_index); } private function getListEnumSize(): Number { return listEnumeration.size(); } private function getListEnumEntry(a_index: Number): Object { return listEnumeration.at(a_index); } private function getListEnumFirstIndex(): Number { return listEnumeration.lookupEntryIndex(0); } private function getListEnumLastIndex(): Number { return listEnumeration.lookupEntryIndex(getListEnumSize() - 1); } private function getListEnumRelativeIndex(a_offset: Number): Number { return listEnumeration.lookupEntryIndex(getSelectedListEnumIndex() + a_offset); } } ================================================ FILE: src/Common/skyui/components/list/BasicListEntry.as ================================================ import skyui.components.list.BasicList; import skyui.components.list.ListState; class skyui.components.list.BasicListEntry extends MovieClip { /* STAGE ELEMENTS */ public var background: MovieClip; /* PROPERTIES */ public var itemIndex: Number; public var isEnabled: Boolean = true; /* PUBLIC FUNCTIONS */ // @override MovieClip public function onRollOver(): Void { var list = this._parent; if (itemIndex != undefined && (isEnabled || list.canSelectDisabled)) list.onItemRollOver(itemIndex); } // @override MovieClip public function onRollOut(): Void { var list = this._parent; if (itemIndex != undefined && (isEnabled || list.canSelectDisabled)) list.onItemRollOut(itemIndex); } // @override MovieClip public function onPress(a_mouseIndex: Number, a_keyboardOrMouse: Number): Void { var list = this._parent; if (itemIndex != undefined && (isEnabled || list.canSelectDisabled)) list.onItemPress(itemIndex, a_keyboardOrMouse); } // @override MovieClip public function onPressAux(a_mouseIndex: Number, a_keyboardOrMouse: Number, a_buttonIndex: Number): Void { var list = this._parent; if (itemIndex != undefined && (isEnabled || list.canSelectDisabled)) list.onItemPressAux(itemIndex, a_keyboardOrMouse, a_buttonIndex); } // This is called after the object is added to the stage since the constructor does not accept any parameters. public function initialize(a_index: Number, a_list: BasicList): Void { // Do nothing. } // @abstract public function setEntry(a_entryObject: Object, a_state: ListState): Void {} } ================================================ FILE: src/Common/skyui/components/list/ButtonList.as ================================================ import gfx.ui.NavigationCode; import Shared.GlobalFunc; import skyui.components.list.BasicList; /* * A simple, general-purpose button list. */ class skyui.components.list.ButtonList extends BasicList { /* CONSTANTS */ public var ALIGN_LEFT = 0; public var ALIGN_RIGHT = 1; /* PROPERTIES */ private var _bAutoScale: Boolean = true; public function get autoScale(): Boolean { return _bAutoScale; } public function set autoScale(a_bAutoScale: Boolean) { _bAutoScale = a_bAutoScale; } private var _minButtonWidth: Number = 10; public function get minButtonWidth(): Number { return _minButtonWidth; } public function set minButtonWidth(a_minButtonWidth: Number) { _minButtonWidth = a_minButtonWidth; } private var _buttonWidth: Number = 0; public function get buttonWidth(): Number { return _buttonWidth; } private var _align: Number = ALIGN_RIGHT; public function set align(a_align: String) { if (align == "LEFT") _align = ALIGN_LEFT; else if (align == "RIGHT") _align = ALIGN_RIGHT; } /* INITIALIZATION */ public function ButtonList() { super(); } /* PUBLIC FUNCTIONS */ // @override BasicList public function UpdateList(): Void { if (_bSuspended) { _bRequestUpdate = true; return; } setClipCount(getListEnumSize()); var h = 0; _buttonWidth = 4; // Set entries for (var i = 0; i < getListEnumSize(); i++) { var entryClip = getClipByIndex(i); var entryItem = getListEnumEntry(i); entryClip.itemIndex = i; entryItem.clipIndex = i; entryClip.setEntry(entryItem, listState); entryClip._y = topBorder + h; entryClip._visible = true; entryClip.selectIndicator._width = 4; entryClip.background._width = 4; if (_buttonWidth < entryClip._width) _buttonWidth = entryClip._width + 4; h = h + entryClip._height; } for (var i = 0; i < getListEnumSize(); i++) { entryClip._x = (_align == ALIGN_LEFT) ? leftBorder : -(buttonWidth + rightBorder); var entryClip = getClipByIndex(i); entryClip.selectIndicator._width = _buttonWidth; entryClip.background._width = _buttonWidth; } background._width = leftBorder + _buttonWidth + rightBorder; background._height = topBorder + h + bottomBorder; background._x = (_align == ALIGN_LEFT) ? 0 : -background._width; } // @GFx public function handleInput(details, pathToFocus): Boolean { var processed = false; if (disableInput) return false; var entry = getClipByIndex(_selectedIndex); var processed = entry != undefined && entry.handleInput != undefined && entry.handleInput(details, pathToFocus.slice(1)); if (!processed && GlobalFunc.IsKeyPressed(details)) { if (details.navEquivalent == NavigationCode.UP || details.navEquivalent == NavigationCode.PAGE_UP) { moveSelectionUp(); processed = true; } else if (details.navEquivalent == NavigationCode.DOWN || details.navEquivalent == NavigationCode.PAGE_DOWN) { moveSelectionDown(); processed = true; } else if (!disableSelection && details.navEquivalent == NavigationCode.ENTER) { onItemPress(); processed = true; } } return processed; } public function moveSelectionUp(): Void { if (disableSelection) return; if (_selectedIndex == -1) { doSetSelectedIndex(getListEnumLastIndex(), SELECT_KEYBOARD); isMouseDrivenNav = false; } else if (getSelectedListEnumIndex() > 0) { doSetSelectedIndex(getListEnumRelativeIndex(-1), SELECT_KEYBOARD); isMouseDrivenNav = false; dispatchEvent({type: "listMovedUp", index: _selectedIndex, scrollChanged: true}); } } public function moveSelectionDown(): Void { if (disableSelection) return; if (_selectedIndex == -1) { doSetSelectedIndex(getListEnumFirstIndex(), SELECT_KEYBOARD); isMouseDrivenNav = false; } else if (getSelectedListEnumIndex() < getListEnumSize() - 1) { doSetSelectedIndex(getListEnumRelativeIndex(+1), SELECT_KEYBOARD); isMouseDrivenNav = false; dispatchEvent({type: "listMovedDown", index: _selectedIndex, scrollChanged: true}); } } /* PRIVATE FUNCTIONS */ // @GFx private function onMouseWheel(delta) { if (disableInput) return; for (var target = Mouse.getTopMostEntity(); target && target != undefined; target = target._parent) { if (target == this) { if (delta < 0) moveSelectionDown(); else if (delta > 0) moveSelectionUp(); } } isMouseDrivenNav = true; } } ================================================ FILE: src/Common/skyui/components/list/ButtonListEntry.as ================================================ import skyui.components.list.BasicList; import skyui.components.list.ListState; import skyui.components.list.BasicListEntry; /* * A generic entry. * Sets selectIndicator visible for the selected entry, if defined. * Sets textField to obj.text. * Forwards to label obj.state, if defined. */ class skyui.components.list.ButtonListEntry extends BasicListEntry { /* PRIVATE VARIABLES */ /* STAGE ELEMENTS */ public var activeIndicator: MovieClip; public var selectIndicator: MovieClip; public var textField: TextField; public var icon: MovieClip; /* PROPERTIES */ public static var defaultTextColor: Number = 0xffffff; public static var activeTextColor: Number = 0xffffff; public static var selectedTextColor: Number = 0xffffff; public static var disabledTextColor: Number = 0x505050; /* PUBLIC FUNCTIONS */ public function setEntry(a_entryObject: Object, a_state: ListState): Void { // Not using "enabled" directly, because we still want to be able to receive onMouseX events, // even if we chose not to process them. isEnabled = a_entryObject.enabled; var isSelected = a_entryObject == a_state.list.selectedEntry; var isActive = (a_state.activeEntry != undefined && a_entryObject == a_state.activeEntry); if (a_entryObject.state != undefined) gotoAndPlay(a_entryObject.state); if (textField != undefined) { textField.autoSize = a_entryObject.align ? a_entryObject.align : "left"; if (!a_entryObject.enabled) textField.textColor = disabledTextColor; else if (isActive) textField.textColor = activeTextColor; else if (isSelected) textField.textColor = selectedTextColor; else textField.textColor = defaultTextColor; textField.SetText(a_entryObject.text ? a_entryObject.text : " "); } if (selectIndicator != undefined) selectIndicator._visible = isSelected; if (activeIndicator != undefined) { activeIndicator._visible = isActive; activeIndicator._x = textField._x - activeIndicator._width - 5; } if (icon != undefined && a_entryObject.iconLabel != undefined) { icon.gotoAndStop(a_entryObject.iconLabel); } } } ================================================ FILE: src/Common/skyui/components/list/ColumnDescriptor.as ================================================ class skyui.components.list.ColumnDescriptor { public var identifier: String; public var longName: String; public var hidden: Boolean; public var type: Number; } ================================================ FILE: src/Common/skyui/components/list/ColumnLayoutData.as ================================================ class skyui.components.list.ColumnLayoutData { public var type: Number = -1; // Entry --------------------------------- // Position relative to the entry. public var x: Number = 0; public var y: Number = 0; public var width: Number = 0; public var height: Number = 0; // These are the names like textField0, equipIcon etc public var stageName: String; // Only defined for text fields public var entryValue: String; public var textFormat: TextFormat; public var colorAttribute: String; // support for dynamic entry coloring that overrides static textFormat // Label --------------------------------- public var labelX: Number = 0; public var labelWidth: Number = 0; public var labelArrowDown: Boolean = false; public var labelValue: String; public var labelTextFormat: TextFormat; public function clear(): Void { type = -1; x = y = width = height = labelX = labelWidth = 0; stageName = entryValue = labelValue = colorAttribute = null; textFormat = labelTextFormat = null; labelArrowDown = false; } } ================================================ FILE: src/Common/skyui/components/list/EntryClipManager.as ================================================ import skyui.components.list.BasicList; import skyui.components.list.IEntryClipBuilder; class skyui.components.list.EntryClipManager { /* PRIVATE VARIABLES */ private var _clipPool: Array; private var _list: BasicList; private var _entryRenderer: String; private var _nextIndex: Number = 0; /* PROPERTIES */ private var _clipCount: Number = -1; public function get clipCount(): Number { return _clipCount; } // Allocates the necessary number of clips in the pool, clears any existing clips for reuse. public function set clipCount(a_clipCount: Number) { _clipCount = a_clipCount; var d = a_clipCount - _clipPool.length; if (d > 0) growPool(d); for (var i=0; i<_clipPool.length; i++) { _clipPool[i]._visible = false; _clipPool[i].itemIndex = undefined; } } /* INITIALIZATION */ public function EntryClipManager(a_list: BasicList) { _list = a_list; _clipPool = []; } /* PUBLIC FUNCTIONS */ public function getClip(a_index: Number): MovieClip { if (a_index >= _clipCount) return undefined; return _clipPool[a_index]; } /* PRIVATE FUNCTIONS */ private function growPool(a_size: Number): Void { var entryRenderer = _list.entryRenderer; for (var i=0; i col.states) return; _activeColumnIndex = a_activeIndex; _activeColumnState = a_activeState; // Save as preferred state _prefData.column = col; _prefData.stateIndex = _activeColumnState; updateLayout(); } /* PRIVATE FUNCTIONS */ private function updateLayout(): Void { _layoutUpdateCount++; var maxHeight = 0; var textFieldIndex = 0; _hiddenStageNames.splice(0); _columnLayoutData.splice(0); // Set bit at position i if column is weighted var weightedFlags = 0; // Move some data from current state to root of the column so we can access single- and multi-state columns in the same manner. // So this is a merge of defaults, column root and current state. for (var i = 0, c = 0; i < _columnList.length; i++) { var col = _columnList[i]; // Skip if (col.hidden == true) continue; var columnLayoutData = new ColumnLayoutData(); _columnLayoutData[c] = columnLayoutData; // Non-active columns always use state 1 var stateData: Object; if (c == _activeColumnIndex) { stateData = col["state" + _activeColumnState]; updateSortParams(stateData); } else { stateData = col["state1"]; } columnLayoutData.type = col.type; columnLayoutData.labelArrowDown = stateData.label.arrowDown ? true : false; columnLayoutData.labelValue = stateData.label.text; columnLayoutData.entryValue = stateData.entry.text; columnLayoutData.colorAttribute = stateData.colorAttribute; c++; } // Subtract arrow tip width var weightedWidth = _entryWidth - 12; var weightSum = 0; var bEnableItemIcon = false; var bEnableEquipIcon = false; for (var i = 0, c = 0; i < _columnList.length; i++) { var col = _columnList[i]; // Skip if (col.hidden == true) continue; var columnLayoutData = _columnLayoutData[c++]; // Calc total weighted width and set weighted flags if (col.weight != undefined) { weightSum += col.weight; weightedFlags = (weightedFlags | 1) << 1; } else { weightedFlags = (weightedFlags | 0) << 1; } if (col.indent != undefined) weightedWidth -= col.indent; // Height including borders for maxHeight var curHeight = 0; switch (col.type) { // ITEM ICON + EQUIP ICON case ListLayout.COL_TYPE_ITEM_ICON: case ListLayout.COL_TYPE_EQUIP_ICON: if (col.type == ListLayout.COL_TYPE_ITEM_ICON) { columnLayoutData.stageName = "itemIcon"; bEnableItemIcon = true; } else { columnLayoutData.stageName = "equipIcon"; bEnableEquipIcon = true; } columnLayoutData.width = _columnLayoutData[i].height = col.icon.size; weightedWidth -= col.icon.size; curHeight += col.icon.size; break; // REST default: columnLayoutData.stageName = "textField" + textFieldIndex++; if (col.width != undefined) { // Width >= 1 for absolute width, < 1 for percentage width columnLayoutData.width = col.width < 1 ? (col.width * _entryWidth) : col.width; weightedWidth -= columnLayoutData.width; } else { columnLayoutData.width = 0; } if (col.height != undefined) // Height >= 1 for absolute height, < 1 for percentage height columnLayoutData.height = col.height < 1 ? (col.height * _entryWidth) : col.height; else columnLayoutData.height = 0; if (col.entry.textFormat != undefined) { var customTextFormat = new TextFormat(); // First clone default format for (var prop in _defaultEntryTextFormat) customTextFormat[prop] = _defaultEntryTextFormat[prop]; // Then override if necessary for (var prop in col.entry.textFormat) if (customTextFormat.hasOwnProperty(prop)) customTextFormat[prop] = col.entry.textFormat[prop]; columnLayoutData.textFormat = customTextFormat; } else { columnLayoutData.textFormat = _defaultEntryTextFormat; } if (col.label.textFormat != undefined) { var customTextFormat = new TextFormat(); // First clone default format for (var prop in _defaultLabelTextFormat) customTextFormat[prop] = _defaultLabelTextFormat[prop]; // Then override if necessary for (var prop in col.label.textFormat) if (customTextFormat.hasOwnProperty(prop)) customTextFormat[prop] = col.label.textFormat[prop]; columnLayoutData.labelTextFormat = customTextFormat; } else { columnLayoutData.labelTextFormat = _defaultLabelTextFormat; } } if (col.border != undefined) { weightedWidth -= col.border[LEFT] + col.border[RIGHT]; curHeight += col.border[TOP] + col.border[BOTTOM]; columnLayoutData.y = col.border[TOP]; } else { columnLayoutData.y = 0; } if (curHeight > maxHeight) maxHeight = curHeight; } // Calculate the widths if (weightSum > 0 && weightedWidth > 0 && weightedFlags != 0) { for (var i = _columnList.length-1, c = _columnLayoutData.length-1; i >= 0; i--) { var col = _columnList[i]; // Skip if (col.hidden == true) continue; var columnLayoutData = _columnLayoutData[c--]; if ((weightedFlags >>>= 1) & 1) { if (col.border != undefined) columnLayoutData.width += ((col.weight / weightSum) * weightedWidth) - col.border[LEFT] - col.border[RIGHT]; else columnLayoutData.width += (col.weight / weightSum) * weightedWidth; } } } // Set x positions based on calculated widths, and set label data var xPos = 0; for (var i=0, c=0; i<_columnList.length; i++) { var col = _columnList[i]; // Skip if (col.hidden == true) continue; var columnLayoutData = _columnLayoutData[c++]; if (col.indent != undefined) xPos += col.indent; columnLayoutData.labelX = xPos; if (col.border != undefined) { columnLayoutData.labelWidth = columnLayoutData.width + col.border[LEFT] + col.border[RIGHT]; columnLayoutData.x = xPos; xPos += col.border[LEFT]; columnLayoutData.x = xPos; xPos += col.border[RIGHT] + columnLayoutData.width; } else { columnLayoutData.labelWidth = columnLayoutData.width; columnLayoutData.x = xPos; xPos += columnLayoutData.width; } } while (textFieldIndex < MAX_TEXTFIELD_INDEX) _hiddenStageNames.push("textField" + textFieldIndex++); if (!bEnableItemIcon) _hiddenStageNames.push("itemIcon"); if (!bEnableEquipIcon) _hiddenStageNames.push("equipIcon"); _entryHeight = maxHeight; // sortChange might not always trigger an update, so we have to make sure the list is updated, // even if that means we update it twice. dispatchEvent({type: "layoutChange"}); } private function updateSortParams(stateData: Object): Void { var sortAttributes = stateData.sortAttributes; var sortOptions = stateData.sortOptions; if (!sortOptions) { _sortOptions = null; _sortAttributes = null; return; } // No attribute(s) set? Try to use entry value if (!sortAttributes) if (stateData.entry.text.charAt(0) == "@") sortAttributes = [ stateData.entry.text.slice(1) ]; if (!sortAttributes) { _sortOptions = null; _sortAttributes = null; return; } // Wrap single attribute in array if (!(sortAttributes instanceof Array)) sortAttributes = [sortAttributes]; if (!(sortOptions instanceof Array)) sortOptions = [sortOptions]; _sortOptions = sortOptions; _sortAttributes = sortAttributes; } private function restorePrefState(): Boolean { // No preference to restore yet if (!_prefData.column) return false; var listIndex = _columnList.indexOf(_prefData.column); var layoutDataIndex = toColumnLayoutDataIndex(listIndex); if (listIndex > -1 && layoutDataIndex > -1) { _activeColumnIndex = layoutDataIndex; _activeColumnState = _prefData.stateIndex; return true; } // Found no match, reset prefData and return false _prefData.column = null; _prefData.stateIndex = 1; return false; } // columnLayoutData index (no hidden columns) -> columnList index (all columns for this view) private function toColumnListIndex(a_index): Number { for (var i = 0, c = 0; i < _columnList.length; i++) { if (_columnList[i].hidden == true) continue; if (c == a_index) return i; c++; } return -1; } // columnList index (all columns for this view) -> columnLayoutData index (no hidden columns) private function toColumnLayoutDataIndex(a_index): Number { for (var i = 0, c = 0; i < _columnList.length; i++) { if (_columnList[i].hidden == true) continue; if (i == a_index) return c; c++; } return -1; } private function updateViewList(): Void { _viewList.splice(0); var viewNames = _layoutData.views; for (var i=0; i _maxScrollPosition) return; if (scrollbar != undefined) scrollbar.position = a_newPosition; else updateScrollPosition(a_newPosition); } private var _maxScrollPosition: Number = 0; public function get maxScrollPosition(): Number { return _maxScrollPosition; } private var _listHeight: Number; public function get listHeight(): Number { return _listHeight; } public function set listHeight(a_height: Number): Void { _listHeight = background._height = a_height; if (scrollbar != undefined) scrollbar.height = _listHeight; } /* INITIALIZATION */ public function ScrollingList() { super(); _listHeight = background._height - topBorder - bottomBorder; _maxListIndex = Math.floor(_listHeight / entryHeight); } /* PUBLIC FUNCTIONS */ // @override MovieClip public function onLoad(): Void { if (scrollbar != undefined) { scrollbar.position = 0; scrollbar.addEventListener("scroll", this, "onScroll"); scrollbar._y = background._x + topBorder; scrollbar.height = _listHeight; } } // @override BasicList public function setPlatform(a_platform: Number, a_bPS3Switch: Boolean): Void { super.setPlatform(a_platform,a_bPS3Switch); } // @GFx public function handleInput(details: InputDetails, pathToFocus: Array): Boolean { if (disableInput) return false; // That makes no sense, does it? var entry = getClipByIndex(selectedIndex); var bHandled = entry != undefined && entry.handleInput != undefined && entry.handleInput(details, pathToFocus.slice(1)); if (bHandled) return true; if (GlobalFunc.IsKeyPressed(details)) { if (details.navEquivalent == NavigationCode.UP || details.navEquivalent == NavigationCode.PAGE_UP) { moveSelectionUp(details.navEquivalent == NavigationCode.PAGE_UP); return true; } else if (details.navEquivalent == NavigationCode.DOWN || details.navEquivalent == NavigationCode.PAGE_DOWN) { moveSelectionDown(details.navEquivalent == NavigationCode.PAGE_DOWN); return true; } else if (!disableSelection && details.navEquivalent == NavigationCode.ENTER) { // TODO: See gfx.managers.InputDelegate.inputToNav(); stop it from converting numberpad -> navEquivalent // Fix for numberpad 0 being handled as ENTER if (details.code == 96 && _platform == PLATFORM_PC) return false; onItemPress(); return true; } } return false; } // @override BasicList public function UpdateList(): Void { if (_bSuspended) { _bRequestUpdate = true; return; } // Prepare clips setClipCount(_maxListIndex); var xStart = background._x + leftBorder; var yStart = background._y + topBorder; var h = 0; // Clear clipIndex for everything before the selected list portion for (var i = 0; i < getListEnumSize() && i < _scrollPosition ; i++) getListEnumEntry(i).clipIndex = undefined; _listIndex = 0; // Display the selected list portion of the list for (var i = _scrollPosition; i < getListEnumSize() && _listIndex < _maxListIndex; i++) { var entryClip = getClipByIndex(_listIndex); var entryItem = getListEnumEntry(i); entryClip.itemIndex = entryItem.itemIndex; entryItem.clipIndex = _listIndex; entryClip.setEntry(entryItem, listState); entryClip._x = xStart; entryClip._y = yStart + h; entryClip._visible = true; h = h + entryHeight; ++_listIndex; } // Clear clipIndex for everything after the selected list portion for (var i = _scrollPosition + _listIndex; i < getListEnumSize(); i++) getListEnumEntry(i).clipIndex = undefined; // Select entry under the cursor for mouse-driven navigation if (isMouseDrivenNav) for (var e = Mouse.getTopMostEntity(); e != undefined; e = e._parent) if (e._parent == this && e._visible && e.itemIndex != undefined) doSetSelectedIndex(e.itemIndex, SELECT_MOUSE); if (scrollUpButton != undefined) scrollUpButton._visible = _scrollPosition > 0; if (scrollDownButton != undefined) scrollDownButton._visible = _scrollPosition < _maxScrollPosition; dispatchEvent({type: "listUpdated"}); } // @override BasicList public function InvalidateData(): Void { if (_bSuspended) { _bRequestInvalidate = true; return; } for (var i = 0; i < _entryList.length; i++) { _entryList[i].itemIndex = i; _entryList[i].clipIndex = undefined; } for (var i=0; i<_dataProcessors.length; i++) _dataProcessors[i].processList(this); listEnumeration.invalidate(); if (listEnumeration.lookupEnumIndex(_selectedIndex) == null) _selectedIndex = -1; calculateMaxScrollPosition(); UpdateList(); // Restore selection if (_curClipIndex != undefined && _curClipIndex != -1 && _listIndex > 0) { if (_curClipIndex >= _listIndex) _curClipIndex = _listIndex - 1; var entryClip = getClipByIndex(_curClipIndex); doSetSelectedIndex(entryClip.itemIndex, SELECT_MOUSE); } if (onInvalidate) onInvalidate(); } public function moveSelectionUp(a_bScrollPage: Boolean): Void { if (!disableSelection && !a_bScrollPage) { if (_selectedIndex == -1) { selectDefaultIndex(false); } else if (getSelectedListEnumIndex() >= scrollDelta) { doSetSelectedIndex(getListEnumRelativeIndex(-scrollDelta), SELECT_KEYBOARD); isMouseDrivenNav = false; if (isPressOnMove) onItemPress(); } } else if (a_bScrollPage) { var t = scrollPosition - _listIndex; scrollPosition = t > 0 ? t : 0; doSetSelectedIndex(-1, SELECT_MOUSE); } else { scrollPosition = scrollPosition - scrollDelta; } } public function moveSelectionDown(a_bScrollPage: Boolean): Void { if (!disableSelection && !a_bScrollPage) { if (_selectedIndex == -1) { selectDefaultIndex(true); } else if (getSelectedListEnumIndex() < getListEnumSize() - scrollDelta) { doSetSelectedIndex(getListEnumRelativeIndex(scrollDelta), SELECT_KEYBOARD); isMouseDrivenNav = false; if (isPressOnMove) onItemPress(); } } else if (a_bScrollPage) { var t = scrollPosition + _listIndex; scrollPosition = t < _maxScrollPosition ? t : _maxScrollPosition; doSetSelectedIndex(-1, SELECT_MOUSE); } else { scrollPosition = scrollPosition + scrollDelta; } } public function selectDefaultIndex(a_bTop: Boolean): Void { if (_listIndex <= 0) return; if (a_bTop) { var firstClip = getClipByIndex(0); if (firstClip.itemIndex != undefined) doSetSelectedIndex(firstClip.itemIndex, SELECT_KEYBOARD); } else { var lastClip = getClipByIndex(_listIndex - 1); if (lastClip.itemIndex != undefined) doSetSelectedIndex(lastClip.itemIndex, SELECT_KEYBOARD); } } /* PRIVATE FUNCTIONS */ // @GFx private function onMouseWheel(a_delta: Number): Void { if (disableInput) return; for (var target = Mouse.getTopMostEntity(); target && target != undefined; target = target._parent) { if (target == this) { if (a_delta < 0) scrollPosition = scrollPosition + scrollDelta; else if (a_delta > 0) scrollPosition = scrollPosition - scrollDelta; } } isMouseDrivenNav = true; } private function onScroll(event: Object): Void { updateScrollPosition(Math.floor(event.position + 0.5)); } // @override BasicList private function doSetSelectedIndex(a_newIndex: Number, a_keyboardOrMouse: Number): Void { if (disableSelection || a_newIndex == _selectedIndex) return; // Selection is not contained in current entry enumeration, ignore if (a_newIndex != -1 && getListEnumIndex(a_newIndex) == undefined) return; var oldEntry = selectedEntry; _selectedIndex = a_newIndex; // Old entry was mapped to a clip? Then clear with setEntry now that selectedIndex has been updated if (oldEntry.clipIndex != undefined) { var clip = getClipByIndex(oldEntry.clipIndex); clip.setEntry(oldEntry, listState); } // Select valid entry if (_selectedIndex != -1) { var enumIndex = getSelectedListEnumIndex(); // New entry before visible portion, move scroll window up if (enumIndex < _scrollPosition) { scrollPosition = enumIndex; // New entry below visible portion, move scroll window down } else if (enumIndex >= _scrollPosition + _listIndex) { scrollPosition = Math.min(enumIndex - _listIndex + scrollDelta, _maxScrollPosition); // No need to change the scroll window, just select new entry } else { var clip = getClipByIndex(selectedEntry.clipIndex); clip.setEntry(selectedEntry, listState); } _curClipIndex = selectedEntry.clipIndex; // Unselect } else { _curClipIndex = -1; } dispatchEvent({type:"selectionChange", index:_selectedIndex, keyboardOrMouse:a_keyboardOrMouse}); } private function calculateMaxScrollPosition(): Void { var t = getListEnumSize() - _maxListIndex; _maxScrollPosition = (t > 0) ? t : 0; updateScrollbar(); if (_scrollPosition > _maxScrollPosition) scrollPosition = _maxScrollPosition; } private function updateScrollPosition(a_position: Number): Void { _scrollPosition = a_position; UpdateList(); } private function updateScrollbar(): Void { if (scrollbar != undefined) { scrollbar._visible = _maxScrollPosition > 0; scrollbar.setScrollProperties(_maxListIndex,0,_maxScrollPosition); } } // @override BasicList private function getClipByIndex(a_index: Number): MovieClip { if (a_index < 0 || a_index >= _maxListIndex) return undefined; return _entryClipManager.getClip(a_index); } } ================================================ FILE: src/Common/skyui/components/list/SortedListHeader.as ================================================ import gfx.events.EventDispatcher; import skyui.components.list.ListLayout; class skyui.components.list.SortedListHeader extends MovieClip { /* PRIVATE VARIABLES */ private var _columns: Array; /* STAGE ELEMENTS */ public var sortIcon: MovieClip; public var iconColumnIndicator: MovieClip; /* PROPERTIES */ private var _layout: ListLayout; public function get layout(): ListLayout { return _layout; } public function set layout(a_layout: ListLayout) { if (_layout) _layout.removeEventListener("layoutChange", this, "onLayoutChange"); _layout = a_layout; _layout.addEventListener("layoutChange", this, "onLayoutChange"); } /* INITIALIZATION */ public function SortedListHeader() { super(); _columns = new Array(); } /* PUBLIC FUNCTIONS */ public function columnPress(a_columnIndex: Number): Void { _layout.selectColumn(a_columnIndex); } /* PRIVATE FUNCTIONS */ // Hides all columns (but doesn't delete them since they can be re-used later). private function clearColumns(): Void { for (var i=0; i< _columns.length; i++) _columns[i]._visible = false; } private function addColumn(a_index: Number): MovieClip { if (a_index < 0) return undefined; var columnButton = this["Column" + a_index]; if (columnButton != undefined) { _columns[a_index] = columnButton; _columns[a_index]._visible = true; return columnButton; } // Create on-demand columnButton = attachMovie("HeaderColumn", "Column" + a_index, getNextHighestDepth()); columnButton.columnIndex = a_index; columnButton.onPress = function(a_mouseIndex, a_keyboardOrMouse, a_buttonIndex) { if (!this.columnIndex != undefined) this._parent.columnPress(this.columnIndex); }; columnButton.onPressAux = function(a_mouseIndex, a_keyboardOrMouse, a_buttonIndex) { if (!this.columnIndex != undefined) this._parent.columnPress(this.columnIndex); }; _columns[a_index] = columnButton; return columnButton; } private function onLayoutChange(event): Void { clearColumns(); var activeIndex = _layout.activeColumnIndex; for (var i = 0; i < _layout.columnCount; i++) { var columnLayoutData = _layout.columnLayoutData[i]; var btn = addColumn(i); btn.label._x = 0; btn._x = columnLayoutData.labelX; btn.label._width = columnLayoutData.labelWidth; btn.label.setTextFormat(columnLayoutData.labelTextFormat); btn.label.SetText(columnLayoutData.labelValue); if (activeIndex == i) sortIcon.gotoAndStop(columnLayoutData.labelArrowDown ? "desc" : "asc"); } positionButtons(); } // Places the buttonAreas around textfields and the sort indicator. private function positionButtons(): Void { var activeIndex = _layout.activeColumnIndex; for (var i=0; i<_columns.length; i++) { var e = _columns[i]; e.label._y = -e.label._height; e.buttonArea._x = e.label.getLineMetrics(0).x - 4; e.buttonArea._width = e.label.getLineMetrics(0).width + 8; e.buttonArea._y = e.label._y - 2; e.buttonArea._height = e.label._height + 2; if (_layout.columnLayoutData[i].type == ListLayout.COL_TYPE_ITEM_ICON) { iconColumnIndicator._x = e._x + e.buttonArea._x + e.buttonArea._width; iconColumnIndicator._y = -e._height + ((e._height - iconColumnIndicator._height) / 2); } if (activeIndex == i) { sortIcon._x = e._x + e.buttonArea._x + e.buttonArea._width; sortIcon._y = -e._height + ((e._height - sortIcon._height) / 2) - 1; iconColumnIndicator._visible = _layout.columnLayoutData[i].type != ListLayout.COL_TYPE_ITEM_ICON; } } } } ================================================ FILE: src/Common/skyui/components/list/TabularList.as ================================================ import Shared.GlobalFunc; import gfx.ui.NavigationCode; import gfx.ui.InputDetails; import skyui.defines.Input; import skyui.util.ConfigLoader; import skyui.util.GlobalFunctions; import skyui.components.list.ListLayout; import skyui.components.list.SortedListHeader; import skyui.components.list.ScrollingList; import skyui.filter.IFilter; import skyui.util.ConfigManager; class skyui.components.list.TabularList extends ScrollingList { /* PRIVATE VARIABLES */ private var _previousColumnKey: Number = -1; private var _nextColumnKey: Number = -1; private var _sortOrderKey: Number = -1; private var _columnOpRequested: Number = 0; /* STAGE ELEMENTS */ public var header: SortedListHeader; /* PROPERTIES */ private var _layout: ListLayout; public function get layout(): ListLayout { return _layout; } public function set layout(a_layout: ListLayout) { if (_layout) _layout.removeEventListener("layoutChange", this, "onLayoutChange"); _layout = a_layout; _layout.addEventListener("layoutChange", this, "onLayoutChange"); if (header) header.layout = a_layout; } /* INITIALIZATION */ public function TabularList() { super(); ConfigManager.registerLoadCallback(this, "onConfigLoad"); } /* PUBLIC FUNCTIONS */ // @GFx public function handleInput(details: InputDetails, pathToFocus: Array): Boolean { if (!disableInput && _platform != 0) { if (GlobalFunc.IsKeyPressed(details)) { // VR specific behavior // // While look at a specific category, we want to be able to both: // - switch column // - switch column sort direction // We only have swipe events to work with in VR at the moment. // We can't use the the right/left swiping motions because they cause changes to the columns. // So, we can only overload the up/down swipes. if (Shared.GlobalFunc.IsKeyPressed(details) && (details.navEquivalent == NavigationCode.UP && (selectedIndex == -1 || // Nothing is selected (just switched category) getSelectedListEnumIndex() == 0)) // Selected item is the first item in current view of the list ){ var inputWindow = 250; if(_platform == Shared.Platforms.CONTROLLER_OCULUS) { inputWindow = 400; } // Has no column operation is currently pending... if(_columnOpRequested == 0) { // Schedule an operation to be performed in the near future. var _this = this; setTimeout(function() { if(_this._columnOpRequested == 1) { _this.layout.nextColumn(); } else { _this.layout.nextActiveColumnState(); } _this._columnOpRequested = 0; }, inputWindow); } // While we're waiting for the column operation to be performed in the near future, // record the number of times the operation is requested. _columnOpRequested++; return true; } } } if (super.handleInput(details, pathToFocus)) return true; if (!disableInput && _platform != 0) { if (GlobalFunc.IsKeyPressed(details)) { if (details.skseKeycode == _previousColumnKey) { _layout.selectColumn(_layout.activeColumnIndex - 1); return true; } else if (details.skseKeycode == _nextColumnKey) { _layout.selectColumn(_layout.activeColumnIndex + 1); return true; } else if (details.skseKeycode == _sortOrderKey) { _layout.selectColumn(_layout.activeColumnIndex); return true; } } } return false; } /* PRIVATE FUNCTIONS */ private function onConfigLoad(event: Object): Void { var config = event.config; if (_platform != 0) { _previousColumnKey = config["Input"].controls.gamepad.prevColumn; _nextColumnKey = config["Input"].controls.gamepad.nextColumn; _sortOrderKey = config["Input"].controls.gamepad.sortOrder; } } private function onLayoutChange(event: Object): Void { entryHeight = _layout.entryHeight; header._x = leftBorder; _maxListIndex = Math.floor((_listHeight / entryHeight) + 0.05); if (_layout.sortAttributes && _layout.sortOptions) dispatchEvent({type:"sortChange", attributes: _layout.sortAttributes, options: _layout.sortOptions}); requestUpdate(); } } ================================================ FILE: src/Common/skyui/components/list/TabularListEntry.as ================================================ import skyui.components.list.TabularList; import skyui.components.list.ListLayout; import skyui.components.list.ListState; import skyui.components.list.ColumnLayoutData; import skyui.components.list.IEntryFormatter; import skyui.components.list.BasicListEntry; // @abstract class skyui.components.list.TabularListEntry extends BasicListEntry { /* PRIVATE VARIABLES */ private var _layoutUpdateCount: Number = -1; /* STAGE ELEMENTS */ public var selectIndicator: MovieClip; /* PUBLIC FUNCTIONS */ // @override BasicListEntry public function setEntry(a_entryObject: Object, a_state: ListState): Void { var layout: ListLayout = TabularList(a_state.list).layout; // Show select area if this is the current entry selectIndicator._visible = (a_entryObject == a_state.list.selectedEntry); var curLayoutUpdateCount = layout.layoutUpdateCount; // Has the view update sequence number changed? Then Update the columns positions etc. if (_layoutUpdateCount != curLayoutUpdateCount) { _layoutUpdateCount = curLayoutUpdateCount; setEntryLayout(a_entryObject, a_state); setSpecificEntryLayout(a_entryObject, a_state); } // The entire entry should be using the same font & size // We want to fetch the lineMetrics just once (not sure how expensive this call is) var textMetrics = undefined; // Format the actual entry contents. Do this with every upate. for (var i = 0; i < layout.columnCount; i++) { var columnLayoutData: ColumnLayoutData = layout.columnLayoutData[i]; var e = this[columnLayoutData.stageName]; if (textMetrics == undefined) textMetrics = e.getLineMetrics(0); // Substitute @variables by entryObject properties var entryValue: String = columnLayoutData.entryValue; if (entryValue != undefined) { if (entryValue.charAt(0) == "@") { var subVal = a_entryObject[entryValue.slice(1)]; e.SetText(subVal != undefined ? subVal : "-"); } else { e.SetText(entryValue); } } // Process based on column type switch (columnLayoutData.type) { case ListLayout.COL_TYPE_EQUIP_ICON : formatEquipIcon(e, a_entryObject, a_state); break; case ListLayout.COL_TYPE_ITEM_ICON : formatItemIcon(e, a_entryObject, a_state); break; case ListLayout.COL_TYPE_NAME : formatName(e, a_entryObject, a_state); break; case ListLayout.COL_TYPE_TEXT : default : formatText(e, a_entryObject, a_state); } // Process color overrides after regular formatting if (columnLayoutData.colorAttribute != undefined) { var color = a_entryObject[columnLayoutData.colorAttribute]; if (color != undefined) e.textColor = color; } // Center the text vertically, using the selectIndicator as a reference // // For some reason, text alignment is more difficult than it should be. // The idea here is to align the top of the select indicator and the TextField. // Then, we vertically center the TextField using the `ascent` height only. // // There is a small wrinkle here. For some reason, even if selectIndicator._y // and TextField._y is set to 0, they are not perfectly vertically aligned. // There is a small vertical gap which throws off this centering calculation. // By experiementation, it looks like subtracting the `descent` hight gets the // text to mostly align with the top of the indicator selector. It's still off // by a few pixels, but at least it's much better than not accounting for it. e._y = selectIndicator._y - textMetrics.descent + ((selectIndicator._height - textMetrics.ascent)/2); } } // Do any clip-specific tasks when the view was changed for this entry. // @abstract public function setSpecificEntryLayout(a_entryObject: Object, a_state: ListState): Void {} // @abstract public function formatName(a_entryField: Object, a_entryObject: Object, a_state: ListState): Void {} // @abstract public function formatEquipIcon(a_entryField: Object, a_entryObject: Object, a_state: ListState): Void {} // @abstract public function formatItemIcon(a_entryField: Object, a_entryObject: Object, a_state: ListState): Void {} // @abstract public function formatText(a_entryField: Object, a_entryObject: Object, a_state: ListState): Void {} /* PRIVATE FUNCTIONS */ private function setEntryLayout(a_entryObject: Object, a_state: ListState): Void { var layout: ListLayout = TabularList(a_state.list).layout; background._width = selectIndicator._width = layout.entryWidth; background._height = selectIndicator._height = layout.entryHeight; // Set up all visible elements in this entry for (var i=0; i 0) e._width = columnLayoutData.width; if (columnLayoutData.height > 0) e._height = columnLayoutData.height; if (e instanceof TextField) e.setTextFormat(columnLayoutData.textFormat); } // Hide any unused elements var hiddenStageNames = layout.hiddenStageNames; for (var i=0; i keycode // The keyCodes correspond directly to the animation/timeline frames in ButtonArt. class skyui.defines.ButtonArtNames { private static var _buttonNameMap = null; private static function nameMap(): Object { if(_buttonNameMap == null || _buttonNameMap == undefined) { _buttonNameMap = constructNameMap(); } return _buttonNameMap; } public static function constructNameMap(): Object { var aNameMap = { esc: 1, //1: 2, //2: 3, //3: 4, //4: 5, //5: 6, //6: 7, //7: 8, //8: 9, //9: 10, //0: 11, hyphen: 12, equal: 13, backspace: 14, tab: 15, q: 16, w: 17, e: 18, r: 19, t: 20, y: 21, u: 22, i: 23, o: 24, p: 25, bracketleft: 26, bracketright: 27, enter: 28, //l-ctrl: 29, a: 30, s: 31, d: 32, f: 33, g: 34, h: 35, j: 36, k: 37, l: 38, semicolon: 39, quotesingle: 40, tilde: 41, //l-shift: 42, backslash: 43, z: 44, x: 45, c: 46, v: 47, b: 48, n: 49, m: 50, comma: 51, period: 52, slash: 53, //r-shift: 54, numpadmult: 55, //l-alt: 56, space: 57, capslock: 58, f1: 59, f2: 60, f3: 61, f4: 62, f5: 63, f6: 64, f7: 65, f8: 66, f9: 67, f10: 68, numlock: 69, scrolllock: 70, numpad7: 71, numpad8: 72, numpad9: 73, numpadminus: 74, numpad4: 75, numpad5: 76, numpad6: 77, numpadplus: 78, numpad1: 79, numpad2: 80, numpad3: 81, numpad0: 82, numpaddec: 83, f11: 87, f12: 88, numpadenter: 156, //r-ctrl: 157, numpaddivide: 158, printsrc: 183, //r-alt: 184, pause: 197, home: 199, up: 200, pgup: 201, left: 203, right: 205, end: 207, down: 208, pgdn: 209, insert: 210, //delete: 211, // Mouse mouse1: 256, mouse2: 257, mouse3: 258, mouse4: 259, mouse5: 260, mouse6: 261, mouse7: 262, mouse8: 263, mousewheelup: 264, mousewheeldown: 265, // Controller //360_start: 270, //360_back: 271, //360_l3: 272, //360_r3: 273, //360_lb: 274, //360_rb: 275, //360_a: 276, //360_b: 277, //360_x: 278, //360_y: 279, //360_lt: 280, //360_rt: 281, // PS3 buttons = 360 buttons ps3_start: 270, ps3_back: 271, ps3_l3: 272, ps3_r3: 273, ps3_lb: 274, ps3_rb: 275, ps3_a: 276, ps3_b: 277, ps3_x: 278, ps3_y: 279, ps3_lt: 280, ps3_rt: 281 }; insertAdditionalNames(aNameMap); insertNamesStartingAtKeyCode(aNameMap, 325, [ // 325 - 329 "360_Y", "360_X", "360_Start", "360_RS", "360_RB", // 330 - 339 "360_R3", "360_LTRT", "360_LS", "360_LB", "360_LS", "360_Back", "360_B", "360_A", "MR MOTION", "MR MENU_RIGHT", // 340 - 349 "MR MENU_LEFT", "MR MENU_HOLD", "ME MENU", "trigger_Right", "trigger_LR", "trigger_Left", "trigger_Hold", "trigger", "thumb_Right_Up", "thumb_Right_UD", // 350 - 359 "thumb_Right_Right", "thumb_Right_Press", "thumb_Right_LR", "thumb_Right_Left", "thumb_Right_Down", "thumb_Right_Any", "thumb_Left_Up", "thumb_Left_UD", "thumb_Left_Right", "thumb_Left_Press", // 360 - 369 "thumb_Left_LR", "thumb_Left_Left", "thumb_Left_Down", "thumb_Left_Any", "radial_Right_Up", "radial_Right_UD", "radial_Right_Right", "radial_Right_NoCenter", "radial_Right_LR", "radial_Right_Left", // 370 - 379 "radial_Right_Down", "radial_Right_Center", "radial_Right_Any", "radial_Left_Up", "radial_Left_UD", "radial_Left_Right", "radial_Left_NoCenter", "radial_Left_LR", "radial_Left_Left", "radial_Left_Down", // 380 - 389 "radial_Left_Center", "radial_Left_Any", "radial_Either_UpDown", "radial_Either_Up", "radial_Either_NoCenter_Hold", "radial_Either_NoCenter", "radial_Either_LeftRight", "radial_Either_Down", "radial_Either_Center", "radial_Either_Any_Hold", // 390 - 399 "radial_Either_Any", "grip_Right", "grip_Left", "grip_Hold", "grip", "grab_Right", "grab_Left", "grab_Hold", "grab", "VIVE MOTION", // 400 - 409 "VIVE MENU_RIGHT", "VIVE MENU_LEFT", "VIVE MENU_HOLD", "VIVE MENU", "PS3_Y_RIGHT", "PS3_Y_LEFT", "PS3_XY_RIGHT", "PS3_XY_LEFT", "PS3_XY", "PS3_X_RIGHT", // 410 - 419 "PS3_X_LEFT", "PS3_Back", "PS3_TELEPORT", "PS3_START", "PS3_Select", "PS3_RS", "PS3_RB", "PS3_R3", "PS3_P_SWING_RIGHT", "PS3_P_SWING_LEFT", // 420 - 429 "PS3_P_SWING", "PS3_OPTIONS", "PS3_NAV_UD_RIGHT", "PS3_NAV_UD_LEFT", "PS3_NAV_UD", "PS3_NAV_RIGHT", "PS3_NAV_LR_RIGHT", "PS3_NAV_LR_LEFT", "PS3_NAV_LR", "PS3_NAV_LEFT", // 430 - 439 "PS3_NAV", "PS3_Move_Select_RIGHT", "PS3_Move_Select_LEFT", "PS3_Move_Select", "PS3_Move_RIGHT", "PS3_Move_LEFT", "PS3_Move", "PS3_MOTION_RIGHT", "PS3_MOTION_LEFT", "PS3_MOTION", // 440 - 449 "PS3_LTRT", "PS3_LS", "PS3_LBRB", "PS3_LB", "PS3_L3", "PS3_CON_RIGHT", "PS3_CON_LEFT", "PS3_B_RIGHT", "PS3_B_LEFT", "PS3_B", // 450 - 459 "PS3_AB_RIGHT", "PS3_AB_LEFT", "PS3_AB", "PS3_A_RIGHT", "PS3_A_LEFT", "PS3_A", "radial_Either_Right", "radial_Either_Left", "Action_Up", "Action_Double_Up", // 460 - 469 "Action_Left", "", "", "", "", "", "", "", "", "", // 470 - 479 "OCC MOTION", "OCC THUMB_REST", "OCC THUMB_RESET_LEFT", "OCC THUMB_REST_RIGHT", "OCC_A", "OCC_A_HOLD", "OCC_B", "OCC_B_HOLD", "OCC_X", "OCC_X_HOLD", // 480 "OCC_Y", "OCC_Y_HOLD" ]); return aNameMap; } public static function lookup(keyName: String): Number { var aNameMap = nameMap(); return aNameMap[keyName.toLowerCase()]; } private static function insertAdditionalNames(aNameMap: Object): Void { // These Button names can't be set in the object constructor since they're 'invalid' names aNameMap["1"] = 2; aNameMap["2"] = 3; aNameMap["3"] = 4; aNameMap["4"] = 5; aNameMap["5"] = 6; aNameMap["6"] = 7; aNameMap["7"] = 8; aNameMap["8"] = 9; aNameMap["9"] = 10; aNameMap["0"] = 11; aNameMap["l-ctrl"] = 29; aNameMap["l-shift"] = 42; aNameMap["r-shift"] = 54; aNameMap["l-alt"] = 56; aNameMap["r-ctrl"] = 157; aNameMap["r-alt"] = 184; aNameMap["delete"] = 211; aNameMap["360_start"] = 270; aNameMap["360_back"] = 271; aNameMap["360_l3"] = 272; aNameMap["360_r3"] = 273; aNameMap["360_lb"] = 274; aNameMap["360_rb"] = 275; aNameMap["360_a"] = 276; aNameMap["360_b"] = 277; aNameMap["360_x"] = 278; aNameMap["360_y"] = 279; aNameMap["360_lt"] = 280; aNameMap["360_rt"] = 281; aNameMap["???"] = 282; } private static function insertNamesStartingAtKeyCode(aNameMap: Object, startKeyCode: Number, namesArr: Array): Void { for(var i = 0; i < namesArr.length; i++) { aNameMap[ namesArr[i].toLowerCase() ] = i + startKeyCode; } } } ================================================ FILE: src/Common/skyui/defines/Form.as ================================================ class skyui.defines.Form { public static var TYPE_NONE: Number = 0; public static var TYPE_EFFECTSETTING: Number = 18; public static var TYPE_ENCHANTMENT: Number = 21; public static var TYPE_SPELL: Number = 22; public static var TYPE_SCROLLITEM: Number = 23; public static var TYPE_ARMOR: Number = 26; public static var TYPE_BOOK: Number = 27; public static var TYPE_INGREDIENT: Number = 30; public static var TYPE_LIGHT: Number = 31; //Torch public static var TYPE_MISC: Number = 32; public static var TYPE_WEAPON: Number = 41; public static var TYPE_AMMO: Number = 42; public static var TYPE_KEY: Number = 45; public static var TYPE_POTION: Number = 46; public static var TYPE_SOULGEM: Number = 52; public static var TYPE_SHOUT: Number = 119; /* NONE = 0, // NONE TES4, // TES4 GROUP, // GRUP GMST, // GMST KEYWORD, // KYWD BGSKEYWORD LOCATIONREF, // LCRT BGSLOCATIONREFTYPE ACTION, // AACT BGSACTION TEXTURESET, // TXST BGSTEXTURESET MENUICON, // MICN BGSMENUICON GLOBAL, // GLOB TESGLOBAL CLASS, // CLAS TESCLASS FACTION, // FACT TESFACTION HEADPART, // HDPT BGSHEADPART EYES, // EYES TESEYES RACE, // RACE TESRACE SOUND, // SOUN TESSOUND ACOUSTICSPACE, // ASPC BGSACOUSTICSPACE SKILL, // SKIL // EFFECTSETTING, // MGEF EFFECTSETTING SCRIPT, // SCPT SCRIPT LANDTEXTURE, // LTEX TESLANDTEXTURE ENCHANTMENT, // ENCH ENCHANTMENTITEM // SPELL, // SPEL SPELLITEM // SCROLLITEM, // SCRL SCROLLITEM ACTIVATOR, // ACTI TESOBJECTACTI TALKINGACTIVATOR, // TACT BGSTALKINGACTIVATOR // ARMOR, // ARMO TESOBJECTARMO // BOOK, // BOOK TESOBJECTBOOK CONTAINER, // CONT TESOBJECTCONT DOOR, // DOOR TESOBJECTDOOR // INGREDIENT, // INGR INGREDIENTITEM // LIGHT, // LIGH TESOBJECTLIGH // MISC, // TESOBJECTMISC APPARATUS, // APPA BGSAPPARATUS STATIC, // STAT TESOBJECTSTAT STATICCOLLECTION, // BGSSTATICCOLLECTION MOVABLESTATIC, // MSTT BGSMOVABLESTATIC GRASS, // GRAS TESGRASS TREE, // TREE TESOBJECTTREE FLORA, // FLOR TESFLORA FURNITURE, // FURN TESFURNITURE WEAPON, // WEAP TESOBJECTWEAP AMMO, // AMMO TESAMMO NPC, // NPC_ TESNPC LEVELEDCHARACTER, // LVLN TESLEVCHARACTER // KEY, // KEYM TESKEY // POTION, // ALCH ALCHEMYITEM IDLEMARKER, // IDLM BGSIDLEMARKER / BGSDEFAULTOBJECTMANAGER? STRANGE NOTE, // NOTE BGSNOTE CONSTRUCTIBLEOBJECT, // COBJ BGSCONSTRUCTIBLEOBJECT PROJECTILE, // PROJ BGSPROJECTILE HAZARD, // HAZD BGSHAZARD // SOULGEM, // SLGM TESSOULGEM LEVELEDITEM, // LVLI TESLEVITEM WEATHER, // WTHR TESWEATHER CLIMATE, // CLMT TESCLIMATE SPGD, // SPGD BGSSHADERPARTICLEGEOMETRYDATA REFERENCEEFFECT, // RFCT BGSREFERENCEEFFECT REGION, // REGN TESREGION NAVI, // NAVI NAVMESHINFOMAP CELL, // CELL TESOBJECTCELL REFERENCE, // REFR TESOBJECTREFR / ACTOR CHARACTER, // ACHR CHARACTER / PLAYERCHARACTER MISSILE, // PMIS MISSILEPROJECTILE ARROW, // PARW ARROWPROJECTILE GRENADE, // PGRE GRENADEPROJECTILE BEAMPROJ, // PBEA BEAMPROJECTILE FLAMEPROJ, // PFLA FLAMEPROJECTILE CONEPROJ, // PCON CONEPROJECTILE BARRIERPROJ, // PBAR BARRIERPROJECTILE PHZD, // PHZD HAZARD WORLDSPACE, // WRLD TESWORLDSPACE LAND, // LAND TESOBJECTLAND NAVM, // NAVM NAVMESH TLOD, // TLOD ? TOPIC, // DIAL TESTOPIC TOPICINFO, // INFO TESTOPICINFO QUEST, // QUST TESQUEST IDLE, // IDLE TESIDLEFORM PACKAGE, // PACK TESPACKAGE COMBATSTYLE, // CSTY TESCOMBATSTYLE LOADSCREEN, // LSCR TESLOADSCREEN LEVELEDSPELL, // LVSP TESLEVSPELL ANIO, // ANIO TESOBJECTANIO WATER, // WATR TESWATERFORM EFFECTSHADER, // EFSH TESEFFECTSHADER TOFT, // TOFT ? EXPLOSION, // EXPL BGSEXPLOSION DEBRIS, // DEBR BGSDEBRIS IMAGESPACE, // IMGS TESIMAGESPACE IMAGESPACEMOD, // IMAD TESIMAGESPACEMODIFIER LIST, // FLST BGSLISTFORM PERK, // PERK BGSPERK BODYPARTDATA, // BPTD BGSBODYPARTDATA ADDONNODE, // ADDN BGSADDONNODE ACTORVALUEINFO, // AVIF ACTORVALUEINFO CAMERASHOT, // CAMS BGSCAMERASHOT CAMERAPATH, // CPTH BGSCAMERAPATH VOICETYPE, // VTYP BGSVOICETYPE MATERIALTYPE, // MATT BGSMATERIALTYPE IMPACTDATA, // IPCT BGSIMPACTDATA IMPACTDATASET, // IPDS BGSIMPACTDATASET ARMA, // ARMA TESOBJECTARMA ENCOUNTERZONE, // ECZN BGSENCOUNTERZONE LOCATION, // LCTN BGSLOCATION MESSAGE, // MESH BGSMESSAGE RAGDOLL, // RGDL BGSRAGDOLL DOBJ, // DOBJ ? (USED FOR DEFAULT OBJECTS, CUSTOM LOADER) LIGHTINGTEMPLATE, // LGTM BGSLIGHTINGTEMPLATE MUSICTYPE, // MUSC BGSMUSICTYPE FOOTSTEP, // FSTP BGSFOOTSTEP FOOTSTEPSET, // FSTS BGSFOOTSTEPSET STORYBRANCHNODE, // SMBN BGSSTORYMANAGERBRANCHNODE STORYQUESTNODE, // SMQN BGSSTORYMANAGERQUESTNODE STORYEVENTNODE, // SMEN BGSSTORYMANAGEREVENTNODE DIALOGUEBRANCH, // DLBR BGSDIALOGUEBRANCH MUSICTRACK, // MUST BGSMUSICTRACKFORMWRAPPER DLVW, // DLVW ? WORDOFPOWER, // WOOP TESWORDOFPOWER // SHOUT, // SHOU TESSHOUT EQUIPSLOT, // EQUP BGSEQUIPSLOT RELATIONSHIP, // RELA BGSRELATIONSHIP SCENE, // SCEN BGSSCENE ASSOCIATIONTYPE, // ASTP BGSASSOCIATIONTYPE OUTFIT, // OTFT BGSOUTFIT ART, // ARTO BGSARTOBJECT MATERIAL, // MATO BGSMATERIALOBJECT MOVEMENTTYPE, // MOVT BGSMOVEMENTTYPE SOUNDDESCRIPTOR, // SNDR BGSSOUNDDESCRIPTORFORM DUALCASTDATA, // DUAL BGSDUALCASTDATA SOUNDCATEGORY, // SNCT BGSSOUNDCATEGORY SOUNDOUTPUT, // SOPM BGSSOUNDOUTPUT COLLISIONLAYER, // COLL BGSCOLLISIONLAYER COLORFORM, // CLFM BGSCOLORFORM REVERBPARAM, // REVB BGSREVERBPARAMETERS */ // baseId = (formId & 0x00FFFFFF) // Armor public static var BASEID_CLOTHESWEDDINGWREATH: Number = 0x08895A; public static var BASEID_DLC1CLOTHESVAMPIRELORDARMOR: Number = 0x011A84; // Ammo public static var BASEID_BOUNDARROW: Number = 0x10B0A7; public static var BASEID_CWARROW: Number = 0x020DDF; public static var BASEID_CWARROWSHORT: Number = 0x020F02; public static var BASEID_DAEDRICARROW: Number = 0x0139C0; public static var BASEID_DRAUGRARROW: Number = 0x034182; public static var BASEID_DUNARCHERPRATICEARROW: Number = 0x0CAB52; public static var BASEID_DUNGEIRMUNDSIGDISARROWSILLUSION: Number = 0x0E738A; public static var BASEID_DWARVENARROW: Number = 0x0139BC; public static var BASEID_DWARVENSPHEREARROW: Number = 0x07B932; public static var BASEID_DWARVENSPHEREBOLT01: Number = 0x07B935; public static var BASEID_DWARVENSPHEREBOLT02: Number = 0x10EC8C; public static var BASEID_EBONYARROW: Number = 0x0139BF; public static var BASEID_ELVENARROW: Number = 0x0139BD; public static var BASEID_FALMERARROW: Number = 0x038341; public static var BASEID_FOLLOWERIRONARROW: Number = 0x10E2DE; public static var BASEID_FORSWORNARROW: Number = 0x0CEE9E; public static var BASEID_GLASSARROW: Number = 0x0139BE; public static var BASEID_IRONARROW: Number = 0x01397D; public static var BASEID_MQ101STEELARROW: Number = 0x105EE7; public static var BASEID_NORDHEROARROW: Number = 0x0EAFDF; public static var BASEID_ORCISHARROW: Number = 0x0139BB; public static var BASEID_STEELARROW: Number = 0x01397F; public static var BASEID_TRAPDART: Number = 0x0236DD; public static var BASEID_DLC1ELVENARROWBLESSED: Number = 0x0098A1; public static var BASEID_DLC1ELVENARROWBLOOD: Number = 0x0098A0; public static var BASEID_TESTDLC1BOLT: Number = 0x00590C; public static var BASEID_DLC2DWARVENBALLISTABOLT: Number = 0x0339A1; public static var BASEID_DLC2RIEKLINGSPEARTHROWN: Number = 0x017720; // Misc public static var BASEID_LOCKPICK: Number = 0x00000A; public static var BASEID_GOLD001: Number = 0x00000F; public static var BASEID_LEATHER01: Number = 0x0DB5D2; public static var BASEID_LEATHERSTRIPS: Number = 0x0800E4; public static var BASEID_GEMAMETHYSTFLAWLESS: Number = 0x06851E; public static var BASEID_RUBYDRAGONCLAW: Number = 0x04B56C; public static var BASEID_IVORYDRAGONCLAW: Number = 0x0AB7BB; public static var BASEID_GLASSCLAW: Number = 0x07C260; public static var BASEID_EBONYCLAW: Number = 0x05AF48; public static var BASEID_EMERALDDRAGONCLAW: Number = 0x0ED417; public static var BASEID_DIAMONDCLAW: Number = 0x0AB375; public static var BASEID_IRONCLAW: Number = 0x08CDFA; public static var BASEID_CORALDRAGONCLAW: Number = 0x0B634C; public static var BASEID_E3GOLDENCLAW: Number = 0x0999E7; public static var BASEID_SAPPHIREDRAGONCLAW: Number = 0x0663D7; public static var BASEID_MS13GOLDENCLAW: Number = 0x039647; public static var BASEID_DA01AZURASSTARBROKEN: Number = 0x028AD7; // SoulGem public static var BASEID_DA01SOULGEMBLACKSTAR: Number = 0x063B29; public static var BASEID_DA01SOULGEMAZURASSTAR: Number = 0x063B27; // Weapons public static var BASEID_WEAPPICKAXE: Number = 0x0E3C16; public static var BASEID_SSDROCKSPLINTERPICKAXE: Number = 0x06A707; public static var BASEID_DUNVOLUNRUUDPICKAXE: Number = 0x1019D4; public static var BASEID_AXE01: Number = 0x02F2F4; public static var BASEID_DUNHALTEDSTREAMPOACHERSAXE: Number = 0x0AE086; // Form Ids // Sound Descriptors public static var FORMID_ITMPotionUse: Number = 0x000B6435; // EquipType public static var EQUIP_RIGHT_HAND: Number = 0x00013f42; public static var EQUIP_LEFT_HAND: Number = 0x00013f43; public static var EQUIP_EITHER_HAND: Number = 0x00013f44; public static var EQUIP_BOTH_HANDS: Number = 0x00013f45; public static var EQUIP_VOICE: Number = 0x00025bee; } ================================================ FILE: src/Common/skyui/defines/Input.as ================================================ import Shared.Platforms; import skyui.util.Debug; class skyui.defines.Input { static var DEVICE_KEYBOARD: Number = 0; static var DEVICE_MOUSE: Number = 1; static var DEVICE_GAMEPAD: Number = 2; static var CONTEXT_GAMEPLAY: Number = 0; static var CONTEXT_MENUMODE: Number = 1; static var CONTEXT_CONSOLE: Number = 2; static var CONTEXT_ITEMMENU: Number = 3; static var CONTEXT_INVENTORY: Number = 4; static var CONTEXT_DEBUGTEXT: Number = 5; static var CONTEXT_FAVORITES: Number = 6; static var CONTEXT_MAP: Number = 7; static var CONTEXT_STATS: Number = 8; static var CONTEXT_CURSOR: Number = 9; static var CONTEXT_BOOK: Number = 10; static var CONTEXT_DEBUGOVERLAY: Number = 11; static var CONTEXT_JOURNAL: Number = 12; static var CONTEXT_TFCMODE: Number = 13; static var CONTEXT_MAPDEBUG: Number = 14; static var CONTEXT_LOCKPICKING: Number = 15; static var CONTEXT_FAVOR: Number = 16; // Controlmap static var ChargeItem = {name: "ChargeItem", context: CONTEXT_INVENTORY}; static var XButton = {name: "XButton", context: CONTEXT_ITEMMENU}; static var YButton = {name: "YButton", context: CONTEXT_ITEMMENU}; static var Wait = {name: "Wait", context: CONTEXT_GAMEPLAY}; static var Jump = {name: "Jump", context: CONTEXT_GAMEPLAY}; static var Sprint = {name: "Sprint", context: CONTEXT_GAMEPLAY}; static var Shout = {name: "Shout", context: CONTEXT_GAMEPLAY}; static var Activate = {name: "Activate", context: CONTEXT_GAMEPLAY}; static var ReadyWeapon = {name: "Ready Weapon", context: CONTEXT_GAMEPLAY}; static var TogglePOV = {name: "Toggle POV", context: CONTEXT_GAMEPLAY}; static var Accept = {name: "Accept", context: CONTEXT_MENUMODE}; static var Cancel = {name: "Cancel", context: CONTEXT_MENUMODE}; static var JournalXButton = {name: "XButton", context: CONTEXT_JOURNAL}; static var JournalYButton = {name: "YButton", context: CONTEXT_JOURNAL}; // Custom static var LeftRight: Array = [ {name: "Left", context: CONTEXT_MENUMODE}, {name: "Right", context: CONTEXT_MENUMODE} ]; static var Equip: Array = [ {name: "RightEquip", context: CONTEXT_ITEMMENU}, {name: "LeftEquip", context: CONTEXT_ITEMMENU} ]; static var SortColumn = [ {keyCode: 274}, {keyCode: 275} ]; static var SortOrder = {keyCode: 272}; // Raw static var GamepadBack = {keyCode: 271}; static var Enter = {keyCode: 28}; static var Tab = {keyCode: 15}; static var Shift = {keyCode: 42}; static var Space = {keyCode: 57}; static var Alt = {keyCode: 56}; } ================================================ FILE: src/Common/skyui/defines/Inventory.as ================================================ class skyui.defines.Inventory { public static var ICT_NONE: Number = 0; public static var ICT_ARMOR: Number = 1; public static var ICT_WEAPON: Number = 2; public static var ICT_MISC: Number = 3; public static var ICT_BOOK: Number = 4; public static var ICT_FOOD: Number = 5; public static var ICT_POTION: Number = 6; public static var ICT_SPELL: Number = 7; public static var ICT_INGREDIENT: Number = 8; public static var ICT_KEY: Number = 9; public static var ICT_SHOUT: Number = 10; public static var ICT_ACTIVE_EFFECT: Number = 11; public static var ICT_SOUL_GEMS: Number = 12; public static var ICT_SPELL_DEFAULT: Number = 13; public static var ICT_LIST: Number = 14; public static var ICT_CRAFT_ENCHANTING: Number = 15; public static var ICT_HOUSE_PART: Number = 16; public static var ES_NONE: Number = 0; public static var ES_EQUIPPED: Number = 1; public static var ES_LEFT_EQUIPPED: Number = 2; public static var ES_RIGHT_EQUIPPED: Number = 3; public static var ES_BOTH_EQUIPPED: Number = 4; public static var QUANTITY_MENU_COUNT_LIMIT: Number = 5; // Category filterflags public static var FILTERFLAG_DIVIDER: Number = 0x00000000; public static var FILTERFLAG_INV_ALL: Number = 0x000003FF; // Sum of below public static var FILTERFLAG_INV_FAVORITES: Number = 0x00000001; public static var FILTERFLAG_INV_WEAPONS: Number = 0x00000002; public static var FILTERFLAG_INV_ARMOR: Number = 0x00000004; public static var FILTERFLAG_INV_POTIONS: Number = 0x00000008; public static var FILTERFLAG_INV_SCROLLS: Number = 0x00000010; public static var FILTERFLAG_INV_FOOD: Number = 0x00000020; public static var FILTERFLAG_INV_INGREDIENTS: Number = 0x00000040; public static var FILTERFLAG_INV_BOOKS: Number = 0x00000080; public static var FILTERFLAG_INV_KEYS: Number = 0x00000100; public static var FILTERFLAG_INV_MISC: Number = 0x00000200; public static var FILTERFLAG_CONTAINER_ALL: Number = 0x000FFC00; // Sum of below public static var FILTERFLAG_CONTAINER_WEAPONS: Number = 0x00000800; public static var FILTERFLAG_CONTAINER_ARMOR: Number = 0x00001000; public static var FILTERFLAG_CONTAINER_POTIONS: Number = 0x00002000; public static var FILTERFLAG_CONTAINER_SCROLLS: Number = 0x00004000; public static var FILTERFLAG_CONTAINER_FOOD: Number = 0x00008000; public static var FILTERFLAG_CONTAINER_INGREDIENTS: Number = 0x00010000; public static var FILTERFLAG_CONTAINER_BOOKS: Number = 0x00020000; public static var FILTERFLAG_CONTAINER_KEYS: Number = 0x00040000; public static var FILTERFLAG_CONTAINER_MISC: Number = 0x00080000; public static var FILTERFLAG_MAGIC_ALL: Number = -257; // 0xFFFFFEFF public static var FILTERFLAG_MAGIC_FAVORITES: Number = 0x00000001; public static var FILTERFLAG_MAGIC_ALTERATION: Number = 0x00000002; public static var FILTERFLAG_MAGIC_ILLUSION: Number = 0x00000004; public static var FILTERFLAG_MAGIC_DESTRUCTION: Number = 0x00000008; public static var FILTERFLAG_MAGIC_CONJURATION: Number = 0x00000010; public static var FILTERFLAG_MAGIC_RESTORATION: Number = 0x00000020; public static var FILTERFLAG_MAGIC_SHOUTS: Number = 0x00000040; public static var FILTERFLAG_MAGIC_POWERS: Number = 0x00000080; public static var FILTERFLAG_MAGIC_ACTIVEEFFECTS: Number = 0x00000100; public static var FILTERFLAG_ENCHANTING_ITEM: Number = 0x00000005; //5; public static var FILTERFLAG_ENCHANTING_DISENCHANT: Number = 0x0000000A; //10; public static var FILTERFLAG_ENCHANTING_ENCHANTMENT: Number = 0x00000030; //48; public static var FILTERFLAG_ENCHANTING_SOULGEM: Number = 0x00000040; //64; // incomplete, but others are irrelevant for now public static var FILTERFLAG_CRAFT_JEWELRY: Number = 0x00010000; public static var FILTERFLAG_CRAFT_FOOD: Number = 0x00020000; public static var FILTERFLAG_CRAFT_MISC: Number = 0x40000000; // Filter flags for custom categories in ConstructObject crafting public static var FILTERFLAG_CUST_CRAFT_ALL: Number = 0x0000003F; public static var FILTERFLAG_CUST_CRAFT_WEAPONS: Number = 0x00000001; public static var FILTERFLAG_CUST_CRAFT_AMMO: Number = 0x00000002; public static var FILTERFLAG_CUST_CRAFT_ARMOR: Number = 0x00000004; public static var FILTERFLAG_CUST_CRAFT_JEWELRY: Number = 0x00000008; public static var FILTERFLAG_CUST_CRAFT_FOOD: Number = 0x00000010; public static var FILTERFLAG_CUST_CRAFT_MISC: Number = 0x00000020; // Filter flags for custom categories in ConstructObject alchemy public static var FILTERFLAG_CUST_ALCH_INGREDIENTS: Number = 0x00000001; public static var FILTERFLAG_CUST_ALCH_GOOD: Number = 0x00000002; public static var FILTERFLAG_CUST_ALCH_BAD: Number = 0x00000004; public static var FILTERFLAG_CUST_ALCH_OTHER: Number = 0x00000008; } ================================================ FILE: src/Common/skyui/defines/Item.as ================================================ class skyui.defines.Item { public static var OTHER: Number = undefined; public static var POTION_HEALTH: Number = 0; public static var POTION_HEALRATE: Number = 1; public static var POTION_HEALRATEMULT: Number = 2; public static var POTION_MAGICKA: Number = 3; public static var POTION_MAGICKARATE: Number = 4; public static var POTION_MAGICKARATEMULT: Number = 5; public static var POTION_STAMINA: Number = 6; public static var POTION_STAMINARATE: Number = 7; public static var POTION_STAMINARATEMULT: Number = 8; public static var POTION_FIRERESIST: Number = 9; public static var POTION_ELECTRICRESIST: Number = 10; public static var POTION_FROSTRESIST: Number = 11; public static var POTION_POTION: Number = 12; public static var POTION_DRINK: Number = 13; public static var POTION_FOOD: Number = 14; public static var POTION_POISON: Number = 15; public static var MISC_GEM: Number = 0; public static var MISC_DRAGONCLAW: Number = 1; public static var MISC_ARTIFACT: Number = 2; public static var MISC_LEATHER: Number = 3; public static var MISC_LEATHERSTRIPS: Number = 4; public static var MISC_HIDE: Number = 5; public static var MISC_REMAINS: Number = 6; public static var MISC_INGOT: Number = 7; public static var MISC_TOOL: Number = 8; public static var MISC_CHILDRENSCLOTHES: Number = 9; public static var MISC_TOY: Number = 10; public static var MISC_FIREWOOD: Number = 11; // public static var MISC_FASTENER: Number = 12; public static var MISC_WEAPONRACK: Number = 13; public static var MISC_SHELF: Number = 14; public static var MISC_FURNITURE: Number = 15; public static var MISC_EXTERIOR: Number = 16; public static var MISC_CONTAINER: Number = 17; // public static var MISC_HOUSEPART: Number = 18; public static var MISC_CLUTTER: Number = 19; public static var MISC_LOCKPICK: Number = 20; public static var MISC_GOLD: Number = 21; public static var BOOK_SPELLTOME: Number = 0; public static var BOOK_NOTE: Number = 1; public static var BOOK_RECIPE: Number = 2; // SKSE // BOOK Flags public static var BOOKFLAG_SPELL: Number = 0x01; public static var BOOKFLAG_SKILL: Number = 0x04; public static var BOOKFLAG_READ: Number = 0x08; // BOOK bookTypes public static var BOOKTYPE_NOTE: Number = 0xFF; // ALCH Flags public static var ALCHFLAG_MANUALCALC: Number = 0x00001; public static var ALCHFLAG_FOOD: Number = 0x00002; public static var ALCHFLAG_MEDICINE: Number = 0x10000; public static var ALCHFLAG_POISON: Number = 0x20000; public static var SOULGEMSTATUS_EMPTY: Number = 0; public static var SOULGEMSTATUS_PARTIAL: Number = 1; public static var SOULGEMSTATUS_FULL: Number = 2; public static var SOULGEM_NONE: Number = 0; public static var SOULGEM_PETTY: Number = 1; public static var SOULGEM_LESSER: Number = 2; public static var SOULGEM_COMMON: Number = 3; public static var SOULGEM_GREATER: Number = 4; public static var SOULGEM_GRAND: Number = 5; public static var SOULGEM_AZURA: Number = 6; } ================================================ FILE: src/Common/skyui/defines/Magic.as ================================================ class skyui.defines.Magic { // Archetype public static var ARCHETYPE_VALUEMOD: Number = 0; public static var ARCHETYPE_SCRIPT: Number = 1; public static var ARCHETYPE_DISPEL: Number = 2; public static var ARCHETYPE_CUREDISEASE: Number = 3; public static var ARCHETYPE_ABSORB: Number = 4; public static var ARCHETYPE_DUALVALUEMOD: Number = 5; public static var ARCHETYPE_CALM: Number = 6; public static var ARCHETYPE_DEMORALIZE: Number = 7; public static var ARCHETYPE_FRENZY: Number = 8; public static var ARCHETYPE_DISARM: Number = 9; public static var ARCHETYPE_COMMANDSUMMONED: Number = 10; public static var ARCHETYPE_INVISIBILITY: Number = 11; public static var ARCHETYPE_LIGHT: Number = 12; public static var ARCHETYPE_LOCK: Number = 15; public static var ARCHETYPE_OPEN: Number = 16; public static var ARCHETYPE_BOUNDWEAPON: Number = 17; public static var ARCHETYPE_SUMMONCREATURE: Number = 18; public static var ARCHETYPE_DETECTLIFE: Number = 19; public static var ARCHETYPE_TELEKINESIS: Number = 20; public static var ARCHETYPE_PARALYSIS: Number = 21; public static var ARCHETYPE_REANIMATE: Number = 22; public static var ARCHETYPE_SOULTRAP: Number = 23; public static var ARCHETYPE_TURNUNDEAD: Number = 24; public static var ARCHETYPE_GUIDE: Number = 25; public static var ARCHETYPE_WEREWOLFFEED: Number = 26; public static var ARCHETYPE_CUREPARALYSIS: Number = 27; public static var ARCHETYPE_CUREADDICTION: Number = 28; public static var ARCHETYPE_CUREPOISON: Number = 29; public static var ARCHETYPE_CONCUSSION: Number = 30; public static var ARCHETYPE_VALUEANDPARTS: Number = 31; public static var ARCHETYPE_ACCUMULATEMAGNITUDE: Number = 32; public static var ARCHETYPE_STAGGER: Number = 33; public static var ARCHETYPE_PEAKVALUEMOD: Number = 34; public static var ARCHETYPE_CLOAK: Number = 35; public static var ARCHETYPE_WEREWOLF: Number = 36; public static var ARCHETYPE_SLOWTIME: Number = 37; public static var ARCHETYPE_RALLY: Number = 38; public static var ARCHETYPE_ENHANCEWEAPON: Number = 39; public static var ARCHETYPE_SPAWNHAZARD: Number = 40; public static var ARCHETYPE_ETHEREALIZE: Number = 41; public static var ARCHETYPE_BANISH: Number = 42; public static var ARCHETYPE_DISGUISE: Number = 44; public static var ARCHETYPE_GRABACTOR: Number = 45; public static var ARCHETYPE_VAMPIRELORD: Number = 46; // MGEF flags public static var MGEFFLAG_HOSTILE: Number = 0x00000001; public static var MGEFFLAG_RECOVER: Number = 0x00000002; public static var MGEFFLAG_DETRIMENTAL: Number = 0x00000004; public static var MGEFFLAG_NOHITEVENT: Number = 0x00000010; public static var MGEFFLAG_DISPELKEYWORDS: Number = 0x00000100; public static var MGEFFLAG_NODURATION: Number = 0x00000200; public static var MGEFFLAG_NOMAGNITUDE: Number = 0x00000400; public static var MGEFFLAG_NOAREA: Number = 0x00000800; public static var MGEFFLAG_FXPERSIST: Number = 0x00001000; public static var MGEFFLAG_GLORYVISUALS: Number = 0x00004000; public static var MGEFFLAG_HIDEINUI: Number = 0x00008000; public static var MGEFFLAG_NORECAST: Number = 0x00020000; public static var MGEFFLAG_MAGNITUDE: Number = 0x00200000; public static var MGEFFLAG_DURATION: Number = 0x00400000; public static var MGEFFLAG_PAINLESS: Number = 0x04000000; public static var MGEFFLAG_NOHITEFFECT: Number = 0x08000000; public static var MGEFFLAG_NODEATHDISPEL: Number = 0x10000000; } ================================================ FILE: src/Common/skyui/defines/Material.as ================================================ class skyui.defines.Material { public static var AETHERIUM: Number = 0; public static var ARTIFACT: Number = 1; public static var BONEMOLD: Number = 2; public static var BROTHERHOOD: Number = 3; public static var CHITIN: Number = 4; public static var CLOTHING: Number = 5; public static var DAEDRIC: Number = 6; public static var DAWNGUARD: Number = 7; public static var DRAGONBONE: Number = 8; public static var DRAGONPLATE: Number = 9; public static var DRAGONSCALE: Number = 10; public static var DRAUGR: Number = 11; public static var DRAUGRHONED: Number = 12; public static var DEATHBRAND: Number = 13; public static var DWARVEN: Number = 14; public static var EBONY: Number = 15; public static var ELVEN: Number = 16; public static var ELVENGILDED: Number = 17; public static var FALMER: Number = 18; public static var FALMERHARDENED: Number = 19; public static var FALMERHONED: Number = 20; public static var FUR: Number = 21; public static var GLASS: Number = 22; public static var HIDE: Number = 23; public static var HUNTER: Number = 24; public static var IMPERIAL: Number = 25; public static var IMPERIALSTUDDED: Number = 26; public static var IRON: Number = 27; public static var IRONBANDED: Number = 28; public static var LEATHER: Number = 29; public static var MAGIC: Number = 30; public static var MORAGTONG: Number = 31; public static var NIGHTINGALE: Number = 32; public static var NORDIC: Number = 33; public static var ORCISH: Number = 34; public static var SCALED: Number = 35; public static var SILVER: Number = 36; public static var STALHRIM: Number = 37; public static var STEEL: Number = 38; public static var STEELPLATE: Number = 39; public static var STORMCLOAK: Number = 40; public static var STUDDED: Number = 41; public static var VAMPIRE: Number = 42; public static var WOOD: Number = 43; } ================================================ FILE: src/Common/skyui/defines/Screen.as ================================================ class skyui.defines.Screen { static public var width = 1280; static public var height = 720; } ================================================ FILE: src/Common/skyui/defines/Weapon.as ================================================ class skyui.defines.Weapon { public static var ANIM_HANDTOHANDMELEE: Number = 0; public static var ANIM_ONEHANDSWORD: Number = 1; public static var ANIM_ONEHANDDAGGER: Number = 2; public static var ANIM_ONEHANDAXE: Number = 3; public static var ANIM_ONEHANDMACE: Number = 4; public static var ANIM_TWOHANDSWORD: Number = 5; public static var ANIM_TWOHANDAXE: Number = 6; public static var ANIM_BOW: Number = 7; public static var ANIM_STAFF: Number = 8; public static var ANIM_CROSSBOW: Number = 9; public static var ANIM_H2H: Number = 10; public static var ANIM_1HS: Number = 11; public static var ANIM_1HD: Number = 12; public static var ANIM_1HA: Number = 13; public static var ANIM_1HM: Number = 14; public static var ANIM_2HS: Number = 15; public static var ANIM_2HA: Number = 16; public static var ANIM_BOW2: Number = 17; public static var ANIM_STAFF2: Number = 18; public static var ANIM_CBOW: Number = 19; public static var TYPE_MELEE: Number = 0; public static var TYPE_SWORD: Number = 1; public static var TYPE_DAGGER: Number = 2; public static var TYPE_WARAXE: Number = 3; public static var TYPE_MACE: Number = 4; public static var TYPE_GREATSWORD: Number = 5; public static var TYPE_BATTLEAXE: Number = 6; public static var TYPE_WARHAMMER: Number = 7; public static var TYPE_BOW: Number = 8; public static var TYPE_CROSSBOW: Number = 9; public static var TYPE_STAFF: Number = 10; public static var TYPE_PICKAXE: Number = 11; public static var TYPE_WOODAXE: Number = 12; // AMMO public static var AMMO_ARROW: Number = 0; public static var AMMO_BOLT: Number = 1; public static var AMMOFLAG_IGNORESNORMALWEAPONRESISTANCE: Number = 0x0001; public static var AMMOFLAG_NONPLAYABLE: Number = 0x0002; public static var AMMOFLAG_NONBOLT: Number = 0x0004; } ================================================ FILE: src/Common/skyui/filter/IFilter.as ================================================ interface skyui.filter.IFilter { // Apply filter on the given array public function applyFilter(filteredList: Array): Void; } ================================================ FILE: src/Common/skyui/filter/ItemTypeFilter.as ================================================ import gfx.events.EventDispatcher; import skyui.filter.IFilter; class skyui.filter.ItemTypeFilter implements IFilter { /* PRIVATE VARIABLES */ private var _matcherFunc:Function; /* PROPERTIES */ private var _itemFilter: Number = 0xFFFFFFFF; function get itemFilter():Number { return _itemFilter; } /* INITIALIZATION */ public function ItemTypeFilter() { EventDispatcher.initialize(this); _matcherFunc = entryMatchesFilter; } /* PUBLIC FUNCTIONS */ // @mixin by gfx.events.EventDispatcher public var dispatchEvent: Function; public var dispatchQueue: Function; public var hasEventListener: Function; public var addEventListener: Function; public var removeEventListener: Function; public var removeAllEventListeners: Function; public var cleanUpEvents: Function; public function changeFilterFlag(a_newFilter:Number, a_bDoNotUpdate: Boolean): Void { if (a_bDoNotUpdate == undefined) a_bDoNotUpdate = false; _itemFilter = a_newFilter; if (!a_bDoNotUpdate) dispatchEvent({type:"filterChange"}); } public function setPartitionedFilterMode(a_bPartition: Boolean): Void { _matcherFunc = a_bPartition ? entryMatchesPartitionedFilter : entryMatchesFilter; } // @override skyui.IFilter public function applyFilter(a_filteredList: Array): Void { for (var i = 0; i < a_filteredList.length; i++) { if (!_matcherFunc(a_filteredList[i], _itemFilter)) { a_filteredList.splice(i,1); i--; } } } public function isMatch(a_entry: Object, a_flag): Boolean { return _matcherFunc(a_entry, a_flag); } /* PRIVATE FUNCTIONS */ public static function entryMatchesFilter(a_entry: Object, a_flag: Boolean): Boolean { return a_entry != undefined && (a_entry.filterFlag == undefined || (a_entry.filterFlag & a_flag) != 0); } private static function entryMatchesPartitionedFilter(a_entry: Object, a_flag: Boolean): Boolean { if (a_entry == undefined) return false; if (a_flag == 0xFFFFFFFF) return true; var flag: Number = a_entry.filterFlag; var byte0: Number = (flag & 0x000000FF); var byte1: Number = (flag & 0x0000FF00) >>> 8; var byte2: Number = (flag & 0x00FF0000) >>> 16; var byte3: Number = (flag & 0xFF000000) >>> 24; return byte0 == a_flag || byte1 == a_flag || byte2 == a_flag || byte3 == a_flag; } } ================================================ FILE: src/Common/skyui/filter/NameFilter.as ================================================ import gfx.events.EventDispatcher; import skyui.util.GlobalFunctions; class skyui.filter.NameFilter implements skyui.filter.IFilter { /* PROPERTIES */ public var nameAttribute: String = "text"; private var _filterText: String = ""; public function get filterText(): String { return _filterText; } public function set filterText(a_filterText: String) { a_filterText = a_filterText.toLowerCase(); if (a_filterText == _filterText) return; _filterText = a_filterText; dispatchEvent({type:"filterChange"}); } /* CONSTRUCTORS */ public function NameFilter() { EventDispatcher.initialize(this); } /* PUBLIC FUNCTIONS */ // @override skyui.IFilter public function applyFilter(a_filteredList:Array): Void { if (_filterText == undefined || _filterText == "") return; for (var i = 0; i < a_filteredList.length; i++) { if (!isMatch(a_filteredList[i])) { a_filteredList.splice(i,1); i--; } } } // @mixin by gfx.events.EventDispatcher public var dispatchEvent: Function; public var dispatchQueue: Function; public var hasEventListener: Function; public var addEventListener: Function; public var removeEventListener: Function; public var removeAllEventListeners: Function; public var cleanUpEvents: Function; /* PRIVATE FUNCTIONS */ private function isMatch(a_entry: Object): Boolean { var searchStr = a_entry[nameAttribute].toLowerCase(); var seekIndex = 0; var seek = false; for (var i = 0; i < searchStr.length; i++) { var charCode = GlobalFunctions.mapUnicodeChar(_filterText.charCodeAt(seekIndex)); if (searchStr.charCodeAt(i) == charCode) { if (!seek) seek = true; seekIndex++; if (seekIndex >= _filterText.length) return true; } else if (seek) { seek = false; seekIndex = 0; } } return false; } } ================================================ FILE: src/Common/skyui/filter/SortFilter.as ================================================ import gfx.events.EventDispatcher; import skyui.filter.IFilter; class skyui.filter.SortFilter implements skyui.filter.IFilter { /* PRIVATE VARIABLES */ private var _sortAttributes: Array; private var _sortOptions: Array; /* INITIALIZATION */ public function SortFilter() { EventDispatcher.initialize(this); } /* PUBLIC FUNCTIONS */ // @mixin by gfx.events.EventDispatcher public var dispatchEvent: Function; public var dispatchQueue: Function; public var hasEventListener: Function; public var addEventListener: Function; public var removeEventListener: Function; public var removeAllEventListeners: Function; public var cleanUpEvents: Function; // Change the filter attributes and options and trigger an update if necessary. public function setSortBy(a_sortAttributes: Array, a_sortOptions: Array): Void { if (_sortAttributes == a_sortAttributes && _sortOptions == a_sortOptions) return; _sortAttributes = a_sortAttributes; _sortOptions = a_sortOptions; dispatchEvent({type: "filterChange"}); } // @override skyui.IFilter public function applyFilter(a_filteredList: Array): Void { var primaryAttribute = _sortAttributes[0]; for (var i=0; i 1 dataMembers.sort(); var dataMember:String = dataMembers.join(PropertyLookup._delimiter); var valueArray:Array = new Array(); for (var i:Number = 0; i < numDataMembers; i++) { valueArray.push(a_filter[dataMembers[i]]); } var matchVal:String = valueArray.join(PropertyLookup._delimiter); return new Array(dataMember, matchVal); } private function _parseDataMemberList(a_configObject: Object): Void { dataMembers = new Object(); var dataMemberGroupObj:Object; for (var i:Number = 1; i < PropertyLookup.dataMemberLimit; i++) { var dataMemberGroup:String = "dataMember" + i; if (a_configObject[dataMemberGroup] == undefined) { // No more dataMember# to go through (they must be sequential) break; } dataMemberGroupObj = a_configObject[dataMemberGroup]; //dataMember1 etc var filter:Object = dataMemberGroupObj["filter"]; // get keyValue for formId, subType etc in dataMember# var keyValue:Array = _getPropertyValFromFilter(filter); var dataMember:String = keyValue[0]; var matchVal = keyValue[1]; // create object for this dataMember (formId etc) if it does not exist. if (dataMembers[dataMember] == undefined) { dataMembers[dataMember] = new Object(); } dataMembers[dataMember][matchVal] = dataMemberGroupObj["set"]; } } function getKeywordValues(a_keyword: String) { return keywords[a_keyword]; } function getDataMemberValues(a_dataMember: String, a_sourceValue) { return dataMembers[a_dataMember][a_sourceValue]; } function keywordMatches(a_keyword: String) { return (keywords[a_keyword] != undefined); } function dataMemberMatches(keyword:String, sourceValue) { return (dataMembers[keyword][sourceValue] != undefined); } private function _getMultSourceVal(a_object: Object, a_dataMember: String) { var dataMembers:Array = a_dataMember.split(PropertyLookup._delimiter); if (dataMembers.length <= 0) { // Shouldn't occur, just return undefined return; } else if (dataMembers.length == 1) { // only a single dataMember, simply try to get the value of it on a_object return a_object[a_dataMember] ; } // else dataMembers.length > 1 var valueArray:Array = new Array(); for (var i:Number = 0; i < dataMembers.length; i++) { if (a_object.hasOwnProperty(dataMembers[i])) { valueArray.push(a_object[dataMembers[i]]); } else { // Missing a dataMember, return undefined return; } } return valueArray.join(PropertyLookup._delimiter); } function processProperty(a_obj: Object): Void { // Check if this object passes the filter for this keyword search if (!itemFilter.passesFilter(a_obj)) return; // Set defaults for (var propertyToDefault:String in defaultValues) { if (defaultValues[propertyToDefault] != undefined) { a_obj[propertyToDefault] = defaultValues[propertyToDefault]; } } var valToSet; // Check for keywords for(var keyword in a_obj.keywords) { var keywordValues: Object = getKeywordValues(keyword); if (keywordValues != undefined) { // keyword match found for (var propertyToSet:String in keywordValues) { valToSet = keywordValues[propertyToSet]; // Don't bother setting if default value is already set if (valToSet != undefined && valToSet != defaultValues[propertyToSet]) { a_obj[propertyToSet] = valToSet; } } break; } } // Check data members last, they take precedence (for example, matching baseID) for(var dataMember in dataMembers) { //var sourceValue = a_obj[dataMember]; var sourceValue = _getMultSourceVal(a_obj, dataMember); if (sourceValue == undefined) continue; var setValues: Object = getDataMemberValues(dataMember, sourceValue); if (setValues != undefined) { // we have a match for (var propertyToSet:String in setValues){ var valToSet = setValues[propertyToSet]; if (valToSet != undefined && valToSet != defaultValues[propertyToSet]) { a_obj[propertyToSet] = valToSet; } } break; } } } } ================================================ FILE: src/Common/skyui/util/ColorFunctions.as ================================================ class skyui.util.ColorFunctions { /* CONSTANTS */ private static var RAD_TO_DEG: Number = 57.295779513082; private static var DEG_TO_RAD: Number = 0.017453292519943; private static var TWO_PI: Number = 6.2831853071796; private static var SQRT_3_OVER_2: Number = 0.86602540378444; /* PUBLIC FUNCTIONS */ // Hex public static function hexToRgb(a_RRGGBB: Number): Array { var RRGGBB: Number = validHex(a_RRGGBB); return [RRGGBB >> 0x10 & 0xFF, RRGGBB >> 0x08 & 0xFF, RRGGBB & 0xFF]; } public static function hexToHsv(a_RRGGBB: Number): Array { return rgbToHsv(hexToRgb(a_RRGGBB)); } public static function hexToHsl(a_RRGGBB: Number): Array { return rgbToHsl(hexToRgb(a_RRGGBB)); } public static function hexToStr(a_RRGGBB: Number, a_prefix: Boolean): String { var str:String = a_RRGGBB.toString(16).toUpperCase(); var padding: String = ''; for (var i: Number = str.length; i < 6; i++) { padding += '0'; } str = ((a_prefix)? "0x": "") + padding + str; return str; } public static function validHex(a_RRGGBB: Number): Number { return clampValue(a_RRGGBB, 0x000000, 0xFFFFFF); } // RGB public static function rgbToHex(a_RGB: Array): Number { var RGB: Array = a_RGB; return (RGB[0] << 0x10 ^ RGB[1] << 0x08 ^ RGB[2]); } public static function rgbToHsv(a_RGB: Array): Array { // in: [R [0-255], G [0-255], B [0-255]] // out: [H [0-360), S [0, 100], V [0, 100]] var R: Number = clampValue(a_RGB[0], 0, 255)/255; var G: Number = clampValue(a_RGB[1], 0, 255)/255; var B: Number = clampValue(a_RGB[2], 0, 255)/255; var H, S, V: Number; var M: Number = Math.max(R, Math.max(G, B)); var m: Number = Math.min(R, Math.min(G, B)); var C: Number = M - m; //H = piecewise.. var alpha: Number = (2*R - G - B)/2; var beta: Number = (G - B)*SQRT_3_OVER_2; H = Math.atan2(beta, alpha); V = M; S = ((C == 0)? 0: C/V); if (H < 0) H += TWO_PI; H *= RAD_TO_DEG; S *= 100; V *= 100; H = Math.round(H); S = Math.round(S); V = Math.round(V); return [H, S, V]; } public static function rgbToHsb(a_RGB: Array): Array { return rgbToHsv(a_RGB); } public static function rgbToHsl(a_RGB: Array): Array { // in: [R [0-255], G [0-255], B [0-255]] // out: [H [0-360), S [0, 100], L [0, 100]] var R: Number = clampValue(a_RGB[0], 0, 255)/255; var G: Number = clampValue(a_RGB[1], 0, 255)/255; var B: Number = clampValue(a_RGB[2], 0, 255)/255; var H, S, L: Number; var M: Number = Math.max(R, Math.max(G, B)); var m: Number = Math.min(R, Math.min(G, B)); var C: Number = M - m; //H = piecewise.. var alpha: Number = (2*R - G - B)/2; var beta: Number = (G - B)*SQRT_3_OVER_2; H = Math.atan2(beta, alpha); L = (M + m)/2; S = ((C == 0)? 0: C/(1 - Math.abs(2*L - 1))); if (H < 0) H += TWO_PI; H *= RAD_TO_DEG; S *= 100; L *= 100; H = Math.round(H); S = Math.round(S); L = Math.round(L); return [H, S, L]; } // HSV public static function hsvToRgb(a_HSV: Array): Array { // in: [H [0-360), S [0, 100], V [0, 100]] // out: [R [0-255], G [0-255], B [0-255]] var H: Number = loopValue(a_HSV[0], 360); var S: Number = clampValue(a_HSV[1], 0, 100)/100; var V: Number = clampValue(a_HSV[2], 0, 100)/100; var R, G, B: Number; var C = V * S; var Hdash: Number = H / 60; var sextant: Number = Math.floor(Hdash); var X: Number = C*(1 - Math.abs(Hdash % 2 - 1)); switch(sextant) { case 0: R = C; G = X; B = 0; break; case 1: R = X; G = C; B = 0; break; case 2: R = 0; G = C; B = X; break; case 3: R = 0; G = X; B = C; break; case 4: R = X; G = 0; B = C; break; case 5: R = C; G = 0; B = X; break; default: R = 0; G = 0; B = 0; break; } var m: Number = V - C; R += m; G += m; B += m; R *= 255; G *= 255; B *= 255; R = Math.round(R); G = Math.round(G); B = Math.round(B); return [R, G, B]; } public static function hsvToHex(a_HSV): Number { return rgbToHex(hsvToRgb(a_HSV)); } // HSB (alias for HSV) public static function hsbToRgb(a_HSB: Array): Array { return hsvToRgb(a_HSB); } public static function hsbToHex(a_HSB): Number { return hsvToHex(a_HSB); } // HSL public static function hslToRgb(a_HSL: Array): Array { // in: [H [0-360), S [0, 100], L [0, 100]] // out: [R [0-255], G [0-255], B [0-255]] var H: Number = loopValue(a_HSL[0], 360); var S: Number = clampValue(a_HSL[1], 0, 100)/100; var L: Number = clampValue(a_HSL[2], 0, 100)/100; var R, G, B: Number; var C = (1 - Math.abs(2*L - 1)) * S; var Hdash: Number = H / 60; var sextant: Number = Math.floor(Hdash); var X: Number = C*(1 - Math.abs(Hdash % 2 - 1)); switch(sextant) { case 0: R = C; G = X; B = 0; break; case 1: R = X; G = C; B = 0; break; case 2: R = 0; G = C; B = X; break; case 3: R = 0; G = X; B = C; break; case 4: R = X; G = 0; B = C; break; case 5: R = C; G = 0; B = X; break; default: R = 0; G = 0; B = 0; break; } var m: Number = L - C/2; R += m; G += m; B += m; R *= 255; G *= 255; B *= 255; R = Math.round(R); G = Math.round(G); B = Math.round(B); return [R, G, B]; } public static function hslToHex(a_HSL): Number { return rgbToHex(hslToRgb(a_HSL)); } /* PRIVATE FUNCTIONS */ private static function clampValue(a_val: Number, a_min: Number, a_max: Number): Number { // $ trace(clampValue(1000, 0, 100)) // > 100 // $ trace(clampValue(-1000, -50, 100)) // > -50 return Math.min(a_max, Math.max(a_min, a_val)); } private static function loopValue(a_val: Number, a_max: Number): Number { // $ trace(loopValue(360.1012, 360)) // > 0.10120000000001 // $ trace(loopValue(360, 360)) // > 0 // $ trace(loopValue(-1, 360)) // > 359 return (a_val % a_max); } } ================================================ FILE: src/Common/skyui/util/ConfigManager.as ================================================ import flash.utils.*; import gfx.events.EventDispatcher; import skyui.components.list.ListLayout; import skyui.util.GlobalFunctions; class skyui.util.ConfigManager { /* CONSTANTS */ private static var CONFIG_PATH = "skyui/config.txt"; private static var TIMEOUT = 3000; private static var LOAD_NONE = 0; private static var LOAD_FILE = 1; private static var LOAD_PAPYRUS = 2; /* PRIVATE VARIABLES */ private static var _constantTable: Object = { ASCENDING: 0, DESCENDING: Array.DESCENDING, CASEINSENSITIVE: Array.CASEINSENSITIVE, NUMERIC: Array.NUMERIC }; // Contains names of classes private static var _extConstantTableNames: Array = []; // Contains the actual classes. private static var _extConstantTables: Object = {}; private static var _eventDummy: Object; // 0: Waiting for file, 1: Waiting for override 2: Loaded private static var _loadPhase: Number = LOAD_NONE; private static var _config: Object; private static var _timeoutID: Number; /* INITIALIATZION */ private static var _initialized:Boolean = initialize(); private static function initialize(): Boolean { GlobalFunctions.addArrayFunctions(); _eventDummy = {}; EventDispatcher.initialize(_eventDummy); var lv = new LoadVars(); lv.onData = parseData; lv.load(CONFIG_PATH); return true; } /* PAPYRUS INTERFACE */ // Key/value pairs "Section$k$e$y$" / "value" public static var out_overrides = {}; public static var in_overrideKeys = []; public static function setExternalOverrideKeys() { in_overrideKeys.splice(0); for (var i = 0; i < arguments.length; i++) in_overrideKeys[i] = arguments[i]; } public static function setExternalOverrideValues() { // Received overrides before file? This can't be right. if (_loadPhase == LOAD_NONE) return; // Update happens in 2 phases. // First the keys are sent and stored, then the values are sent and immediately processed. for (var i = 0; i < arguments.length; i++) { var t = in_overrideKeys[i]; if (t && t != "") parseExternalOverride(t, arguments[i]); } if (_loadPhase != LOAD_PAPYRUS) { clearInterval(_timeoutID); delete _timeoutID; _loadPhase = LOAD_PAPYRUS; _eventDummy.dispatchEvent({type: "configLoad", config: _config}); } else { // Timeout _eventDummy.dispatchEvent({type: "configUpdate", config: _config}); } } /* PUBLIC FUNCTIONS */ public static function registerLoadCallback(a_scope: Object, a_callBack: String): Void { _eventDummy.addEventListener("configLoad", a_scope, a_callBack); } public static function registerUpdateCallback(a_scope: Object, a_callBack: String): Void { _eventDummy.addEventListener("configUpdate", a_scope, a_callBack); } public static function setConstant(a_name: String, a_value): Void { var type = typeof(a_value); if (type != "number" && type != "boolean" && type != "string") return; _constantTable[a_name] = a_value; } public static function addConstantTable(a_name: String, a_class: Function): Void { _extConstantTableNames.push(a_name); } public static function getConstant(a_name: String) { if (_constantTable[a_name] != undefined) return _constantTable[a_name]; var a: Array = a_name.split("."); if (a.length < 2) return undefined; var className: String = a[a.length - 2]; var constName: String = a[a.length - 1]; if (_extConstantTables[className][constName] != undefined) return _extConstantTables[className][constName]; return undefined; } public static function setOverride(a_section: String, a_key: String, a_value, a_valueStr: String): Void { // Allow to add new sections if (_config[a_section] == undefined) _config[a_section] = {}; var a = a_key.split("."); // Prepare key subsections var loc = _config[a_section]; var varContainer = null; if (a[0] == "vars") varContainer = loc.vars[a[1]]; for (var j=0; j $ a_key = a_key.split(".").join("$"); var ovrKey = a_section + "$" + a_key; out_overrides[ovrKey] = a_valueStr; skse.SendModEvent("SKICO_setConfigOverride", ovrKey); // If we changed the value of a var, update all recorded references. if (varContainer) { for (var i=0; i").split(","); for (var i=0; i") return new Array(); var values = GlobalFunctions.extract(a_str, "<", ">").split(","); for (var i=0; i 0) { for(var i = 0; i < _buffer.length; i++) skse.Log(_buffer[i]); _buffer.splice(0); } if(arguments[0].slice(0, 3) == "<< ") indent -= 1; for(var i = 0; i < arguments.length; i++) { var str = dateTime + " "; for(var j = 0; j < indent; j++) { str += " "; } str += arguments[i]; if (_global.skse) skse.Log(str); else if (_global.gfxPlayer) trace(str); else _buffer.push(str); } if(arguments[0].slice(0, 3) == ">> ") indent += 1; } public static function logNT(/* a_text: String , a_text2: String ... */): Void { // Flush buffer if (_global.skse && _buffer.length > 0) { for(var i = 0; i < _buffer.length; i++) skse.Log(_buffer[i]); _buffer.splice(0); } for(var i = 0; i < arguments.length; i++) { var str = arguments[i]; if (_global.skse) skse.Log(str); else if (_global.gfxPlayer) trace(str); else _buffer.push(str); } } public static function dump(a_name: String, a_obj, a_noTimestamp: Boolean, a_padLevel: Number): Void { var pad: String = ""; var padLevel: Number = (a_padLevel == undefined)? 0: a_padLevel; var logFn: Function = (a_noTimestamp)? logNT: log; for(var i = 0; i < padLevel; i++) pad += " "; if (typeof a_obj == "object" || typeof a_obj == "function" ) { logFn(pad + a_name); for (var s in a_obj) dump(s, a_obj[s], a_noTimestamp, padLevel + 1); } else if (typeof a_obj == "array") { logFn(pad + a_name); for(var j = 0; j < a_obj.length; j++) dump(j, a_obj[j], a_noTimestamp, padLevel + 1); } else { logFn(pad + a_name + ": " + a_obj); } } public static function prettyFormId(a_formId: Number, a_prefix: Boolean): String { var str:String = a_formId.toString(16).toUpperCase(); var padding: String = ""; for (var i: Number = str.length; i < 8; i++) { padding += "0"; } str = ((a_prefix)? "0x": "") + padding + str; return str; } public static function getFunctionName(a_func: Function): String { var name: String = getFunctionNameRecursive(a_func, _global); //if (!name) name = getFunctionNameRecursive(a_func, _root); return name; } public static function getFunctionNameRecursive(a_func: Function, a_root: Object): String { var func: Function = a_func; var root: Object = a_root; if (!root) return null; // Iterate over classes // Classes are function instances with a prototype for (var s: String in root) { if (root[s] instanceof Function && root[s].prototype != null) { // Found a class. // Iterate over class static members to see if there's a match for (var t: String in root[s]) if(root[s][t] == func) return (s + "." + t); // Loop over the class' prototype to look for instance methods var instance:Object = root[s].prototype; /* _global.ASSetPropFlags (target: Object, propList, ft: Number, ff: Number): Void PARAMETERS: target, the target object to be set prop flags. propList, list of property names, Array of Strings or a comma delimited String, null for all properties. ft, flag bits to be added to the target properties. ff, flag bits to be removed from target properties. RETURN: Nothing. DESCRIPTION: Flag is a 3-bits binary, bit 0x01, enumeration-protected; bit 0x02, deletion-protected; bit 0x04, write-protected. ASSetPropFlags uses the following formula to calculate the new flag from the old one: fn=fo & (~ff) | ft, where fo is the original flag, ff and ft from the parameters. */ // Save enumerable property names var enumerable: Array = new Array(); for (var t: String in instance) enumerable.push(t); // Set all properties to enumerable _global.ASSetPropFlags(instance, null, 0x00, 0x01); for (var t: String in instance) if(instance[t] == func) return (s + "." + t); // Set all properties to unenumerable _global.ASSetPropFlags(instance, null, 0x01, 0x00); // Reset all enumerable properties to enumerable _global.ASSetPropFlags(instance, enumerable, 0x00, 0x01); } } // Iterate over this package's sub packages. // Sub packages have are Object types for (var s: String in root) { if (typeof(root[s]) == "object") { var name: String = getFunctionNameRecursive(func, root[s]); if (name) return (s + "." + name); } } return null; } static public function dumpFocusPath(focusPath: Array) { Debug.dump("focusPath", focusPath); for(var i = 0; i < focusPath.length; i++) { var obj = focusPath[i]; if(obj.classname != null) Debug.log("" + i + ": " + obj.classname()); } } } ================================================ FILE: src/Common/skyui/util/DialogManager.as ================================================ import gfx.managers.FocusHandler; import gfx.events.EventDispatcher; import skyui.components.dialog.BasicDialog; class skyui.util.DialogManager { /* PRIVATE VARIABLES */ // There can only be one open dialog at a time. private static var _activeDialog: BasicDialog; private static var _previousFocus: Object; private static var _closeCallback: Function; /* PUBLIC FUNCTIONS */ public static function open(a_target: MovieClip, a_linkageID: String, a_init: Object): MovieClip { if (_activeDialog) close(); _previousFocus = FocusHandler.instance.getFocus(0); _activeDialog = BasicDialog(a_target.attachMovie(a_linkageID, "dialog", a_target.getNextHighestDepth(), a_init)); FocusHandler.instance.setFocus(_activeDialog, 0); _activeDialog.openDialog(); return _activeDialog; } public static function close(): Void { FocusHandler.instance.setFocus(_previousFocus, 0); _activeDialog.closeDialog(); _activeDialog = null; } } ================================================ FILE: src/Common/skyui/util/EffectIconMap.as ================================================ import skyui.defines.Magic; import skyui.defines.Actor; class skyui.util.EffectIconMap { private static var _archetypeMap: Array = [ null, // 0 - ARCHETYPE_VALUEMOD EMBLEM null, // 1 - ARCHETYPE_SCRIPT nn null, // 2 - ARCHETYPE_DISPEL nn null, // 3 - ARCHETYPE_CUREDISEASE nn null, // 4 - ARCHETYPE_ABSORB EMBLEM null, // 5 - ARCHETYPE_DUALVALUEMOD EMBLEM null, // 6 - ARCHETYPE_CALM nn null, // 7 - ARCHETYPE_DEMORALIZE nn null, // 8 - ARCHETYPE_FRENZY nn null, // 9 - ARCHETYPE_DISARM nn "conjure", // 10 - ARCHETYPE_COMMANDSUMMONED OK "invisibility", // 11 - ARCHETYPE_INVISIBILITY OK "light", // 12 - ARCHETYPE_LIGHT OK null, null, null, // 15 - ARCHETYPE_LOCK nn null, // 16 - ARCHETYPE_OPEN nn "bound_item", // 17 - ARCHETYPE_BOUNDWEAPON OK "conjure", // 18 - ARCHETYPE_SUMMONCREATURE OK null, // 19 - ARCHETYPE_DETECTLIFE nn null, // 20 - ARCHETYPE_TELEKINESIS nn "paralysis", // 21 - ARCHETYPE_PARALYSIS OK null, // 22 - ARCHETYPE_REANIMATE nn null, // 23 - ARCHETYPE_SOULTRAP nn null, // 24 - ARCHETYPE_TURNUNDEAD nn "clairvoyance", // 25 - ARCHETYPE_GUIDE OK null, // 26 - ARCHETYPE_WEREWOLFFEED nn null, // 27 - ARCHETYPE_CUREPARALYSIS nn null, // 28 - ARCHETYPE_CUREADDICTION nn null, // 29 - ARCHETYPE_CUREPOISON nn null, // 30 - ARCHETYPE_CONCUSSION nn null, // 31 - ARCHETYPE_VALUEANDPARTS nn null, // 32 - ARCHETYPE_ACCUMULATEMAGNITUDE nn null, // 33 - ARCHETYPE_STAGGER nn null, // 34 - ARCHETYPE_PEAKVALUEMOD EMBLEM "cloak", // 35 - ARCHETYPE_CLOAK OK "werewolf", // 36 - ARCHETYPE_WEREWOLF OK "slow_time", // 37 - ARCHETYPE_SLOWTIME OK null, // 38 - ARCHETYPE_RALLY nn "ench_weapon", // 39 - ARCHETYPE_ENHANCEWEAPON OK null, // 40 - ARCHETYPE_SPAWNHAZARD nn "ethereal", // 41 - ARCHETYPE_ETHEREALIZE OK null, // 42 - ARCHETYPE_BANISH nn null, null, // 44 - ARCHETYPE_DISGUISE nn null, // 45 - ARCHETYPE_GRABACTOR nn "vampire" // 46 - ARCHETYPE_VAMPIRELORD OK ]; private static var _avMap: Array = [ null, // 0 - AV_AGGRESSION nn null, // 1 - AV_CONFIDENCE nn null, // 2 - AV_ENERGY nn null, // 3 - AV_MORALITY nn null, // 4 - AV_MOOD nn null, // 5 - AV_ASSISTANCE nn "av_skill_weapon_1h", // 6 - AV_ONEHANDED OK "av_skill_weapon_2h", // 7 - AV_TWOHANDED OK "av_skill_archery", // 8 - AV_MARKSMAN OK "av_skill_block", // 9 - AV_BLOCK OK "av_skill_smithing", // 10 - AV_SMITHING OK "av_skill_armor_heavy", // 11 - AV_HEAVYARMOR OK "av_skill_armor_light", // 12 - AV_LIGHTARMOR OK "av_skill_pickpocket", // 13 - AV_PICKPOCKET OK "av_skill_lockpicking", // 14 - AV_LOCKPICKING OK "av_skill_sneak", // 15 - AV_SNEAK OK "av_skill_alchemy", // 16 - AV_ALCHEMY OK "av_skill_persuasion", // 17 - AV_SPEECHCRAFT OK "av_skill_alteration", // 18 - AV_ALTERATION OK "av_skill_conjuration", // 19 - AV_CONJURATION OK "av_skill_destruction", // 20 - AV_DESTRUCTION OK "av_skill_illusion", // 21 - AV_ILLUSION OK "av_skill_restoration", // 22 - AV_RESTORATION OK "av_skill_enchanting", // 23 - AV_ENCHANTING OK "av_health", // 24 - AV_HEALTH OK "av_magicka", // 25 - AV_MAGICKA OK "av_stamina", // 26 - AV_STAMINA OK "av_health_regen", // 27 - AV_HEALRATE OK "av_magicka_regen", // 28 - AV_MAGICKARATE OK "av_stamina_regen", // 29 - AV_STAMINARATE OK "av_speedmult", // 30 - AV_SPEEDMULT OK null, // 31 - AV_INVENTORYWEIGHT nn "av_carryweight", // 32 - AV_CARRYWEIGHT OK null, // 33 - AV_CRITCHANCE nn "av_skill_unarmed", // 34 - AV_MELEEDAMAGE OK "av_skill_unarmed", // 35 - AV_UNARMEDDAMAGE OK null, // 36 - AV_MASS nn null, // 37 - AV_VOICEPOINTS nn null, // 38 - AV_VOICERATE nn "av_resist_damage", // 39 - AV_DAMAGERESIST OK "av_resist_poison", // 40 - AV_POISONRESIST OK "av_resist_fire", // 41 - AV_FIRERESIST OK "av_resist_shock", // 42 - AV_ELECTRICRESIST OK "av_resist_frost", // 43 - AV_FROSTRESIST OK "av_resist_magic", // 44 - AV_MAGICRESIST OK "av_resist_disease", // 45 - AV_DISEASERESIST OK null, // 46 - AV_PERCEPTIONCONDITION nn null, // 47 - AV_ENDURANCECONDITION nn null, // 48 - AV_LEFTATTACKCONDITION nn null, // 49 - AV_RIGHTATTACKCONDITION nn null, // 50 - AV_LEFTMOBILITYCONDITION nn null, // 51 - AV_RIGHTMOBILITYCONDITION nn null, // 52 - AV_BRAINCONDITION nn "paralysis", // 53 - AV_PARALYSIS OK "invisibility", // 54 - AV_INVISIBILITY OK "av_nighteye", // 55 - AV_NIGHTEYE OK null, // 56 - AV_DETECTLIFERANGE nn "av_waterbreathing", // 57 - AV_WATERBREATHING OK "av_waterwalking", // 58 - AV_WATERWALKING OK null, // 59 - AV_IGNORECRIPPLEDLIMBS nn null, // 60 - AV_FAME nn null, // 61 - AV_INFAMY nn null, // 62 - AV_JUMPINGBONUS nn "av_ward", // 63 - AV_WARDPOWER OK null, // 64 - AV_RIGHTITEMCHARGE nn "av_armorperks", // 65 - AV_ARMORPERKS OK null, // 66 - AV_SHIELDPERKS nn null, // 67 - AV_WARDDEFLECTION nn null, // 68 - AV_VARIABLE01 nn null, // 69 - AV_VARIABLE02 nn null, // 70 - AV_VARIABLE03 nn null, // 71 - AV_VARIABLE04 nn null, // 72 - AV_VARIABLE05 nn null, // 73 - AV_VARIABLE06 nn null, // 74 - AV_VARIABLE07 nn null, // 75 - AV_VARIABLE08 nn null, // 76 - AV_VARIABLE09 nn null, // 77 - AV_VARIABLE10 nn "av_bow_speed", // 78 - AV_BOWSPEEDBONUS OK null, // 79 - AV_FAVORACTIVE nn null, // 80 - AV_FAVORSPERDAY nn null, // 81 - AV_FAVORSPERDAYTIMER nn null, // 82 - AV_LEFTITEMCHARGE nn "av_absorb", // 83 - AV_ABSORBCHANCE OK null, // 84 - AV_BLINDNESS nn "av_weapon_speed", // 85 - AV_WEAPONSPEEDMULT OK "av_skill_shout", // 86 - AV_SHOUTRECOVERYMULT OK "av_bow_stagger", // 87 - AV_BOWSTAGGERBONUS OK null, // 88 - AV_TELEKINESIS nn null, // 89 - AV_FAVORPOINTSBONUS nn null, // 90 - AV_LASTBRIBEDINTIMIDATED nn null, // 91 - AV_LASTFLATTERED nn "av_noise", // 92 - AV_MOVEMENTNOISEMULT OK null, // 93 - AV_BYPASSVENDORSTOLENCHECK nn null, // 94 - AV_BYPASSVENDORKEYWORDCHECK nn null, // 95 - AV_WAITINGFORPLAYER nn "av_skill_weapon_1h", // 96 - AV_ONEHANDEDMOD OK "av_skill_weapon_2h", // 97 - AV_TWOHANDEDMOD OK "av_skill_archery", // 98 - AV_MARKSMANMOD OK "av_skill_block", // 99 - AV_BLOCKMOD OK "av_skill_smithing", // 100 - AV_SMITHINGMOD OK "av_skill_armor_heavy", // 101 - AV_HEAVYARMORMOD OK "av_skill_armor_light", // 102 - AV_LIGHTARMORMOD OK "av_skill_pickpocket", // 103 - AV_PICKPOCKETMOD OK "av_skill_lockpicking", // 104 - AV_LOCKPICKINGMOD OK "av_skill_sneak", // 105 - AV_SNEAKMOD OK "av_skill_alchemy", // 106 - AV_ALCHEMYMOD OK "av_skill_persuasion", // 107 - AV_SPEECHCRAFTMOD OK "av_skill_alteration", // 108 - AV_ALTERATIONMOD OK "av_skill_conjuration", // 109 - AV_CONJURATIONMOD OK "av_skill_destruction", // 110 - AV_DESTRUCTIONMOD OK "av_skill_illusion", // 111 - AV_ILLUSIONMOD OK "av_skill_restoration", // 112 - AV_RESTORATIONMOD OK "av_skill_enchanting", // 113 - AV_ENCHANTINGMOD OK "av_skill_weapon_1h", // 114 - AV_ONEHANDEDSKILLADVANCE OK "av_skill_weapon_2h", // 115 - AV_TWOHANDEDSKILLADVANCE OK "av_skill_archery", // 116 - AV_MARKSMANSKILLADVANCE OK "av_skill_block", // 117 - AV_BLOCKSKILLADVANCE OK "av_skill_smithing", // 118 - AV_SMITHINGSKILLADVANCE OK "av_skill_armor_heavy", // 119 - AV_HEAVYARMORSKILLADVANCE OK "av_skill_armor_light", // 120 - AV_LIGHTARMORSKILLADVANCE OK "av_skill_pickpocket", // 121 - AV_PICKPOCKETSKILLADVANCE OK "av_skill_lockpicking", // 122 - AV_LOCKPICKINGSKILLADVANCE OK "av_skill_sneak", // 123 - AV_SNEAKSKILLADVANCE OK "av_skill_alchemy", // 124 - AV_ALCHEMYSKILLADVANCE OK "av_skill_persuasion", // 125 - AV_SPEECHCRAFTSKILLADVANCE OK "av_skill_alteration", // 126 - AV_ALTERATIONSKILLADVANCE OK "av_skill_conjuration", // 127 - AV_CONJURATIONSKILLADVANCE OK "av_skill_destruction", // 128 - AV_DESTRUCTIONSKILLADVANCE OK "av_skill_illusion", // 129 - AV_ILLUSIONSKILLADVANCE OK "av_skill_restoration", // 130 - AV_RESTORATIONSKILLADVANCE OK "av_skill_enchanting", // 131 - AV_ENCHANTINGSKILLADVANCE OK null, // 132 - AV_LEFTWEAPONSPEEDMULT OK null, // 133 - AV_DRAGONSOULS nn null, // 134 - AV_COMBATHEALTHREGENMULT nn "av_skill_weapon_1h", // 135 - AV_ONEHANDEDPOWERMOD OK "av_skill_weapon_2h", // 136 - AV_TWOHANDEDPOWERMOD OK "av_skill_archery", // 137 - AV_MARKSMANPOWERMOD OK "av_skill_block", // 138 - AV_BLOCKPOWERMOD OK "av_skill_smithing", // 139 - AV_SMITHINGPOWERMOD OK "av_skill_armor_heavy", // 140 - AV_HEAVYARMORPOWERMOD OK "av_skill_armor_light", // 141 - AV_LIGHTARMORPOWERMOD OK "av_skill_pickpocket", // 142 - AV_PICKPOCKETPOWERMOD OK "av_skill_lockpicking", // 143 - AV_LOCKPICKINGPOWERMOD OK "av_skill_sneak", // 144 - AV_SNEAKPOWERMOD OK "av_skill_alchemy", // 145 - AV_ALCHEMYPOWERMOD OK "av_skill_persuasion", // 146 - AV_SPEECHCRAFTPOWERMOD OK "av_skill_alteration", // 147 - AV_ALTERATIONPOWERMOD OK "av_skill_conjuration", // 148 - AV_CONJURATIONPOWERMOD OK "av_skill_destruction", // 149 - AV_DESTRUCTIONPOWERMOD OK "av_skill_illusion", // 150 - AV_ILLUSIONPOWERMOD OK "av_skill_restoration", // 151 - AV_RESTORATIONPOWERMOD OK "av_skill_enchanting", // 152 - AV_ENCHANTINGPOWERMOD OK null, // 153 - AV_DRAGONREND nn null, // 154 - AV_ATTACKDAMAGEMULT nn "av_health_regen", // 155 - AV_HEALRATEMULT OK "av_magicka_regen", // 156 - AV_MAGICKARATEMULT OK "av_stamina_regen", // 157 - AV_STAMINARATEMULT OK null, // 158 - AV_WEREWOLFPERKS nn null, // 159 - AV_VAMPIREPERKS nn null, // 160 - AV_GRABACTOROFFSET nn null, // 161 - AV_GRABBED nn null, // 162 - AV_DEPRECATED05 nn null // 163 - AV_REFLECTDAMAGE ]; public static function lookupIconLabel(a_effectData: Object): Object { var archetype = a_effectData.archetype; var actorValue = a_effectData.actorValue; var emblemLabel = "none"; // 1. Attempt to look up for simple archetypes var baseLabel = _archetypeMap[archetype]; // Found one, done if (baseLabel) return {baseLabel: baseLabel, emblemLabel: emblemLabel}; // 2. Archetype + ActorValue combinations // Set emblem switch (archetype) { case Magic.ARCHETYPE_VALUEMOD: case Magic.ARCHETYPE_DUALVALUEMOD: case Magic.ARCHETYPE_PEAKVALUEMOD: var isDetrimental = a_effectData.effectFlags & Magic.MGEFFLAG_DETRIMENTAL; var isRecovering = a_effectData.effectFlags & Magic.MGEFFLAG_RECOVER; if (isDetrimental) { emblemLabel = isRecovering ? "drain" : "damage"; } else { emblemLabel = isRecovering ? "fortify" : "restore"; } } // Lookup base icon baseLabel = _avMap[actorValue]; // Replace base icon for damage health with resistType icon if (actorValue == Actor.AV_HEALTH) { var resistType = a_effectData.resistType; switch (a_effectData.resistType) { case Actor.AV_FIRERESIST: baseLabel = "magic_fire"; break; case Actor.AV_FROSTRESIST: baseLabel = "magic_frost"; break; case Actor.AV_ELECTRICRESIST: baseLabel = "magic_shock"; break; } } // 3. No match? Default if (!baseLabel) baseLabel = "default_effect"; return {baseLabel: baseLabel, emblemLabel: emblemLabel}; } } ================================================ FILE: src/Common/skyui/util/GlobalFunctions.as ================================================ import skyui.defines.Input; class skyui.util.GlobalFunctions { /* PUBLIC FUNCTIONS */ public static function extract(a_str: String, a_startChar: String, a_endChar: String): String { return a_str.slice(a_str.indexOf(a_startChar) + 1,a_str.lastIndexOf(a_endChar)); } // Remove comments and leading/trailing white space public static function clean(a_str: String): String { if (a_str.indexOf(";") > 0) a_str = a_str.slice(0,a_str.indexOf(";")); var i = 0; while (a_str.charAt(i) == " " || a_str.charAt(i) == "\t") i++; var j = a_str.length - 1; while (a_str.charAt(j) == " " || a_str.charAt(j) == "\t") j--; return a_str.slice(i,j + 1); } public static function unescape(a_str: String): String { a_str = a_str.split("\\n").join("\n"); a_str = a_str.split("\\t").join("\t"); return a_str; } private static var _arrayExtended = false; public static function addArrayFunctions(): Void { if (_arrayExtended) return; _arrayExtended = true; Array.prototype.indexOf = function (a_element): Number { for (var i=0; i 0) { if (valStr.indexOf(".") == -1) valStr += "."; var t: Array = valStr.split("."); var fractLen: Number = t[1].length; while (fractLen++ < decimal) valStr += "0"; } buf += valStr; pos = end+1; } buf += a_str.slice(pos); return buf; } public static function formatNumber(a_number: Number, a_decimal: Number): String { var valStr: String = a_number.toString().toLowerCase(); var floatComponents: Array = valStr.split("e", 2); var mult = Math.pow(10, a_decimal); valStr = String((Math.round(parseFloat(floatComponents[0]) * mult) / mult)); if (a_decimal > 0) { var dotIdx: Number = valStr.indexOf(".") if (dotIdx == -1) { dotIdx = valStr.length valStr += "."; } var decLen: Number = valStr.length - (dotIdx + 1); for (var i: Number = 0; decLen + i < a_decimal; i++) valStr += "0"; } if (floatComponents[1] != undefined) valStr += "E" + floatComponents[1] return valStr; } public static function getMappedKey(a_control: String, a_context: Number, a_bGamepad: Boolean): Number { if (_global.skse == undefined) return -1; if (a_bGamepad == true) { return skse.GetMappedKey(a_control, Input.DEVICE_GAMEPAD, a_context); } else { var keyCode = skse.GetMappedKey(a_control, Input.DEVICE_KEYBOARD, a_context); if (keyCode == -1) keyCode = skse.GetMappedKey(a_control, Input.DEVICE_MOUSE, a_context); return keyCode; } } public static function hookFunction(a_scope: Object, a_memberFn: String, a_hookScope: Object, a_hookFn: String): Boolean { var memberFn: Function = a_scope[a_memberFn]; if (memberFn == null || a_scope[a_memberFn] == null) return false; a_scope[a_memberFn] = function () {memberFn.apply(a_scope, arguments); a_hookScope[a_hookFn].apply(a_hookScope, arguments);} return true; } public static function getDistance(a: MovieClip, b: MovieClip): Number { var dx = b._x - a._x; var dy = b._y - a._y; return Math.sqrt(dx*dx + dy*dy); } public static function getAngle(a: MovieClip, b: MovieClip): Number { var dx = b._x - a._x; var dy = b._y - a._y; return Math.atan2(dy, dx) * (180 / Math.PI); } static public function clamp(val:Number, min:Number, max:Number) { return Math.max(min, Math.min(max, val)) } static public function vec2Mag(vec2: Array) { if(vec2 == undefined) return undefined; var x = vec2[0]; var y = vec2[1]; return Math.sqrt(x*x + y*y); } static public function vec2Angle(vec2: Array) { return Math.atan2(vec2[1], vec2[0]) * (180 / Math.PI); } } ================================================ FILE: src/Common/skyui/util/Hash.as ================================================ class skyui.util.Hash { private static var _crc32Lookup = [ 0x00000000,0x77073096,0xEE0E612C,0x990951BA,0x076DC419,0x706AF48F,0xE963A535,0x9E6495A3, 0x0EDB8832,0x79DCB8A4,0xE0D5E91E,0x97D2D988,0x09B64C2B,0x7EB17CBD,0xE7B82D07,0x90BF1D91, 0x1DB71064,0x6AB020F2,0xF3B97148,0x84BE41DE,0x1ADAD47D,0x6DDDE4EB,0xF4D4B551,0x83D385C7, 0x136C9856,0x646BA8C0,0xFD62F97A,0x8A65C9EC,0x14015C4F,0x63066CD9,0xFA0F3D63,0x8D080DF5, 0x3B6E20C8,0x4C69105E,0xD56041E4,0xA2677172,0x3C03E4D1,0x4B04D447,0xD20D85FD,0xA50AB56B, 0x35B5A8FA,0x42B2986C,0xDBBBC9D6,0xACBCF940,0x32D86CE3,0x45DF5C75,0xDCD60DCF,0xABD13D59, 0x26D930AC,0x51DE003A,0xC8D75180,0xBFD06116,0x21B4F4B5,0x56B3C423,0xCFBA9599,0xB8BDA50F, 0x2802B89E,0x5F058808,0xC60CD9B2,0xB10BE924,0x2F6F7C87,0x58684C11,0xC1611DAB,0xB6662D3D, 0x76DC4190,0x01DB7106,0x98D220BC,0xEFD5102A,0x71B18589,0x06B6B51F,0x9FBFE4A5,0xE8B8D433, 0x7807C9A2,0x0F00F934,0x9609A88E,0xE10E9818,0x7F6A0DBB,0x086D3D2D,0x91646C97,0xE6635C01, 0x6B6B51F4,0x1C6C6162,0x856530D8,0xF262004E,0x6C0695ED,0x1B01A57B,0x8208F4C1,0xF50FC457, 0x65B0D9C6,0x12B7E950,0x8BBEB8EA,0xFCB9887C,0x62DD1DDF,0x15DA2D49,0x8CD37CF3,0xFBD44C65, 0x4DB26158,0x3AB551CE,0xA3BC0074,0xD4BB30E2,0x4ADFA541,0x3DD895D7,0xA4D1C46D,0xD3D6F4FB, 0x4369E96A,0x346ED9FC,0xAD678846,0xDA60B8D0,0x44042D73,0x33031DE5,0xAA0A4C5F,0xDD0D7CC9, 0x5005713C,0x270241AA,0xBE0B1010,0xC90C2086,0x5768B525,0x206F85B3,0xB966D409,0xCE61E49F, 0x5EDEF90E,0x29D9C998,0xB0D09822,0xC7D7A8B4,0x59B33D17,0x2EB40D81,0xB7BD5C3B,0xC0BA6CAD, 0xEDB88320,0x9ABFB3B6,0x03B6E20C,0x74B1D29A,0xEAD54739,0x9DD277AF,0x04DB2615,0x73DC1683, 0xE3630B12,0x94643B84,0x0D6D6A3E,0x7A6A5AA8,0xE40ECF0B,0x9309FF9D,0x0A00AE27,0x7D079EB1, 0xF00F9344,0x8708A3D2,0x1E01F268,0x6906C2FE,0xF762575D,0x806567CB,0x196C3671,0x6E6B06E7, 0xFED41B76,0x89D32BE0,0x10DA7A5A,0x67DD4ACC,0xF9B9DF6F,0x8EBEEFF9,0x17B7BE43,0x60B08ED5, 0xD6D6A3E8,0xA1D1937E,0x38D8C2C4,0x4FDFF252,0xD1BB67F1,0xA6BC5767,0x3FB506DD,0x48B2364B, 0xD80D2BDA,0xAF0A1B4C,0x36034AF6,0x41047A60,0xDF60EFC3,0xA867DF55,0x316E8EEF,0x4669BE79, 0xCB61B38C,0xBC66831A,0x256FD2A0,0x5268E236,0xCC0C7795,0xBB0B4703,0x220216B9,0x5505262F, 0xC5BA3BBE,0xB2BD0B28,0x2BB45A92,0x5CB36A04,0xC2D7FFA7,0xB5D0CF31,0x2CD99E8B,0x5BDEAE1D, 0x9B64C2B0,0xEC63F226,0x756AA39C,0x026D930A,0x9C0906A9,0xEB0E363F,0x72076785,0x05005713, 0x95BF4A82,0xE2B87A14,0x7BB12BAE,0x0CB61B38,0x92D28E9B,0xE5D5BE0D,0x7CDCEFB7,0x0BDBDF21, 0x86D3D2D4,0xF1D4E242,0x68DDB3F8,0x1FDA836E,0x81BE16CD,0xF6B9265B,0x6FB077E1,0x18B74777, 0x88085AE6,0xFF0F6A70,0x66063BCA,0x11010B5C,0x8F659EFF,0xF862AE69,0x616BFFD3,0x166CCF45, 0xA00AE278,0xD70DD2EE,0x4E048354,0x3903B3C2,0xA7672661,0xD06016F7,0x4969474D,0x3E6E77DB, 0xAED16A4A,0xD9D65ADC,0x40DF0B66,0x37D83BF0,0xA9BCAE53,0xDEBB9EC5,0x47B2CF7F,0x30B5FFE9, 0xBDBDF21C,0xCABAC28A,0x53B39330,0x24B4A3A6,0xBAD03605,0xCDD70693,0x54DE5729,0x23D967BF, 0xB3667A2E,0xC4614AB8,0x5D681B02,0x2A6F2B94,0xB40BBE37,0xC30C8EA1,0x5A05DF1B,0x2D02EF8D ]; public static function crc32(a_str: String, a_start: Number): Number { var result: Number = ~a_start; var n: Number = a_str.length; var c: Number; for (var i=0; i>> 8) ^ _crc32Lookup[(result & 0xFF) ^ c]; } return ~result & 0xFFFFFFFF; } } ================================================ FILE: src/Common/skyui/util/Input.as ================================================ import skyui.util.Debug; import skyui.VRInput; class skyui.util.Input { //---------------------------------------------------------------------- // Utility functions // // This is for picking the right ButtonArt given a map and a platform enum. // It expect the same format the vanilla game uses to specify keys. // This makes it relatively straighforward to port changes over. // //--------------------------------------------------------------------- static function pickButtonArt(a_platform: Number, buttonNames: Object): String { switch(VRInput.instance.controllerName) { case "vive": return buttonNames["ViveArt"]; case "knuckles": if(buttonNames["KnucklesArt"]) return buttonNames["KnucklesArt"]; else return buttonNames["OculusArt"]; } switch(a_platform) { case Shared.Platforms.CONTROLLER_PC: return buttonNames["PCArt"]; case Shared.Platforms.CONTROLLER_PCGAMEPAD: case Shared.Platforms.CONTROLLER_DURANGO: case Shared.Platforms.CONTROLLER_ORBIS: return buttonNames["XBoxArt"]; case Shared.Platforms.CONTROLLER_VIVE: case Shared.Platforms.CONTROLLER_VIVE_KNUCKLES: return buttonNames["ViveArt"]; case Shared.Platforms.CONTROLLER_ORBIS_MOVE: return buttonNames["MoveArt"]; case Shared.Platforms.CONTROLLER_OCULUS: return buttonNames["OculusArt"]; case Shared.Platforms.CONTROLLER_WINDOWS_MR: return buttonNames["WindowsMRArt"]; default: return buttonNames["XBoxArt"]; } } static function pickControls(a_platform: Number, buttonNames: Object): Object { var val = {namedKey: pickButtonArt(a_platform, buttonNames)}; return val; } // Helper function to perform rate limiting static function rateLimit(a_obj: Object, a_fieldname: String, delayTime: Number) { a_obj[a_fieldname] = true; setTimeout(function() { a_obj[a_fieldname] = false; }, delayTime); } } ================================================ FILE: src/Common/skyui/util/MarkupParser.as ================================================ import gfx.events.EventDispatcher; import mx.utils.Delegate; import TextField.StyleSheet; class skyui.util.MarkupParser { private static var _eventDummy: Object; private static var _markup: Object; public static var styleSheet: StyleSheet; /* INITIALIATZION */ private static var _initialized: Boolean = initialize(); public static function initialize(): Boolean { _markup = {}; _eventDummy = {}; EventDispatcher.initialize(_eventDummy); styleSheet = new StyleSheet(); styleSheet.setStyle("p", {color: "#FFFFFF", fontSize: "17px"}); styleSheet.setStyle(".list", {color: "#FFFFFF", fontSize: "17px", textIndent: "10px"}); styleSheet.setStyle("bullet", {color: "#FFFFFF", fontSize: "20px"}); styleSheet.setStyle("strong", {color: "#DDDDDD", fontWeight: "bold", fontFamily: "$EverywhereBoldFont"}); styleSheet.setStyle("em", {fontStyle: "italic", fontFamily: "$EverywhereFont"}); styleSheet.setStyle("underline", {textDecoration: "underline"}); styleSheet.setStyle("a:link", {color: "#FFFFFF", textDecoration: "none"}); styleSheet.setStyle("a:hover", {color: "#FFFFFF", textDecoration: "underline"}); styleSheet.setStyle("a:active", {color: "#FFFFFF", textDecoration: "underline"}); styleSheet.setStyle("h1", {color: "#FFFFFF", fontSize: "28px"}); styleSheet.setStyle("h2", {color: "#FFFFFF", fontSize: "24px"}); styleSheet.setStyle("h3", {color: "#FFFFFF", fontSize: "18px"}); styleSheet.setStyle("h4", {color: "#CCCCCC", fontSize: "16px"}); styleSheet.setStyle("h5", {color: "#CCCCCC", fontSize: "14px"}); styleSheet.setStyle("h6", {color: "#BBBBBB", fontSize: "14px"}); return true; } /* PUBLIC FUNCTIONS */ public static function registerParseCallback(a_scope: Object, a_callBack: String): Void { _eventDummy.addEventListener("dataParsed", a_scope, a_callBack); } public static function load(a_path: String): Boolean { var lv = new LoadVars(); lv.onData = Delegate.create(MarkupParser, parseData); return lv.load(a_path); } /* PRIVATE FUNCTIONS */ private static function parseData(a_data: String): Void { var lines: Array = a_data.split("\r\n"); if (lines.length == 1) lines = a_data.split("\n"); var sectionName: String; var section: Object; var line: String; var parsedLine: String; var blankLine: Boolean var inParagraph: Boolean = false; var emptyLine: Boolean = true; var lastLineIdx = lines.length - 1; for (var i = 0; i <= lastLineIdx; i++) { line = lines[i]; // Comment if (line.charAt(0) == ";") continue; // Section start if (line.charAt(0) == "[" && line.charAt(1) != "[" && line.length > 2) { sectionName = line.slice(1, line.lastIndexOf("]")).toLowerCase(); if (_markup[sectionName] == undefined) _markup[sectionName] = {lines: [], htmlText: ""}; continue; } if (sectionName == undefined && line.length < 3) continue; if (sectionName == undefined) { sectionName = "main"; _markup[sectionName] = {lines: [], htmlText: ""}; } line = htmlEscapeAndClean(line); // Empty line? emptyLine = (line.length == 0); // Header? if (!emptyLine && line.charAt(0) == "#") { var h: Number = 1; for (var j: Number = h; j < 6 && line.charAt(j) == "#"; j++) h++; if (line.charAt(h) == " ") { if (inParagraph) { _markup[sectionName].htmlText += "

"; inParagraph = false; } _markup[sectionName].htmlText += "

" + parseLine(line.slice(h + 1)) + "

"; continue; } } // List? if (!emptyLine && line.charAt(0) == "*" && line.charAt(1) == " ") { if (inParagraph) { _markup[sectionName].htmlText += "

"; inParagraph = false; } _markup[sectionName].htmlText += "

· " + parseLine(line.slice(2)) + "

"; continue; } if (!inParagraph) { if (!emptyLine) { _markup[sectionName].htmlText += "

"; _markup[sectionName].htmlText += parseLine(line); inParagraph = true; if (i == lastLineIdx) { _markup[sectionName].htmlText += "

"; inParagraph = false; } } } else { if (!emptyLine) { _markup[sectionName].htmlText += "
"; _markup[sectionName].htmlText += parseLine(line); } else { _markup[sectionName].htmlText += "

"; inParagraph = false; } } } _eventDummy.dispatchEvent({type: "dataParsed", markup: _markup}); } private static function parseLine(a_data: String): String { var parsedString = parseStyles(a_data); parsedString = parseAnchors(parsedString) return parsedString; } private static function parseStyles(a_data: String): String { var parsingString: String = ""; var parsedString: String = ""; // Bold and Italic // ***TEXT*** **Text2***** // i j k l ij k l var i: Number = -1; var j: Number = -1; var k: Number = -1; var l: Number = -1; var tokenWidth: Number = 0; while(l < a_data.length - 1) { j = i = a_data.indexOf("*", l+1); if (i == -1) { // No further tokens found parsingString += a_data.substring(l+1); break; } // Always append text before first token parsingString += a_data.substring(l+1, i); while (a_data.charAt(j+1) == "*") j++; l = k = a_data.indexOf("*", j+1); if (k == -1) { // No trailing token found, append remaining text and break parsingString += a_data.substring(i) break; } while (a_data.charAt(l+1) == "*") l++; tokenWidth = (j-i)+1; switch(tokenWidth) { case 1: parsingString += "" + a_data.substring(j+1, k) + ""; break; case 2: parsingString += "" + a_data.substring(j+1, k) + ""; break; case 3: parsingString += "" + a_data.substring(j+1, k) + ""; break; default: parsingString += a_data.substring(i, l+1) } } // Underline // _TEXT_ __Text2_____ // i j i j var m: Number = -1; var n: Number = -1; while(n < parsingString.length - 1) { m = parsingString.indexOf("_", n+1); if (m == -1) { // No further tokens found parsedString += parsingString.substring(n+1); break; } while (parsingString.charAt(m+1) == "_") m++; parsedString += parsingString.substring(n+1, m); n = parsingString.indexOf("_", m+1); if (n == -1) { parsedString += parsingString.substring(m); break; } parsedString += "" + parsingString.substring(m+1, n) + ""; } return parsedString; } private static function parseAnchors(a_data: String): String { // [[Section]] [[Section|Name]] // i k i j k var parsedString: String = ""; var anchorData: Array; var i: Number = -1; var j: Number = -2; while(j < a_data.length - 1) { i = a_data.indexOf("[[", j+2); if (i == -1) { // No further tokens found parsedString += a_data.substring(j+2); break; } // Always append text before first token parsedString += a_data.substring(j+2, i); j = a_data.indexOf("]]", i+2); if (j == -1) { parsedString += a_data.substring(i); break; } //if (j != -1) anchorData = a_data.substring(i+2, j).split("|", 2); if (anchorData.length == 2) parsedString += "" + anchorData[1] + ""; else parsedString += "" + anchorData[0] + ""; } return parsedString; } private static function htmlEscapeAndClean(a_str: String): String { // Trim leading and trailing whitespaces var i: Number = 0; while (a_str.charAt(i) == " " || a_str.charAt(i) == "\t") i++; var j: Number = a_str.length - 1; while (a_str.charAt(j) == " " || a_str.charAt(j) == "\t") j--; a_str = a_str.slice(i,j + 1); // Replace characters a_str = a_str.split("&").join("&"); a_str = a_str.split("'").join("'"); a_str = a_str.split("\"").join("""); a_str = a_str.split("<").join("<"); a_str = a_str.split(">").join(">"); a_str = a_str.split("&nbsp;").join(" "); //hack... :) return a_str; } } ================================================ FILE: src/Common/skyui/util/Translator.as ================================================ class skyui.util.Translator { /* PRIVATE VARIABLES */ private static var _translator:TextField; /* PUBLIC FUNCTIONS */ // Translate simple strings public static function translate(a_str: String): String { if (_translator == undefined) { _translator = _root.createTextField("_translator", _root.getNextHighestDepth(), 0, 0, 1, 1); _translator._visible = false; } if (a_str == "") return ""; if (a_str.charAt(0) != "$") return a_str; _translator.text = a_str; return _translator.text; } // Translate with support for substrings, i.e. "$My text, default value {$Default value}" public static function translateNested(a_str: String): String { if (a_str == "") return ""; // Quick test to decide if we can skip if (a_str.indexOf("{") == -1) return translate(a_str); // Collect substrings var subStrings: Array = []; var offset = 0; do { var startIndex = a_str.indexOf("{", offset); var endIndex = a_str.indexOf("}", offset); if (startIndex != -1 && endIndex != -1 && startIndex < endIndex) { var s = a_str.slice(startIndex+1, endIndex); subStrings.push(translate(s)); a_str = a_str.slice(0, startIndex+1) + a_str.slice(endIndex); offset = startIndex + 2; } else { break; } } while (true); // Translate the base string a_str = translate(a_str); // Split at {} and interleave with the substrings var t = a_str.split("{}"); var result = ""; var i; for (i=0; i 0); a_entryObject.infoValue = (a_entryObject.value > 0) ? (Math.round(a_entryObject.value * 100) / 100) : null; a_entryObject.infoWeight =(a_entryObject.weight > 0) ? (Math.round(a_entryObject.weight * 100) / 100) : null; a_entryObject.infoValueWeight = (a_entryObject.weight > 0 && a_entryObject.value > 0) ? (Math.round((a_entryObject.value / a_entryObject.weight) * 100) / 100) : null; switch (a_entryObject.formType) { case Form.TYPE_SCROLLITEM: a_entryObject.subTypeDisplay = Translator.translate("$Scroll"); a_entryObject.duration = (a_entryObject.duration > 0) ? (Math.round(a_entryObject.duration * 100) / 100) : null; a_entryObject.magnitude = (a_entryObject.magnitude > 0) ? (Math.round(a_entryObject.magnitude * 100) / 100) : null; break; case Form.TYPE_ARMOR: a_entryObject.infoArmor = (a_entryObject.armor > 0) ? (Math.round(a_entryObject.armor * 100) / 100) : null; processArmorClass(a_entryObject); processArmorPartMask(a_entryObject); processMaterialKeywords(a_entryObject); processArmorOther(a_entryObject); processArmorBaseId(a_entryObject); break; case Form.TYPE_BOOK: processBookType(a_entryObject); break; case Form.TYPE_INGREDIENT: a_entryObject.subTypeDisplay = Translator.translate("$Ingredient"); break; case Form.TYPE_LIGHT: a_entryObject.subTypeDisplay = Translator.translate("$Torch"); break; case Form.TYPE_MISC: processMiscType(a_entryObject); processMiscBaseId(a_entryObject); break; case Form.TYPE_WEAPON: a_entryObject.infoDamage = (a_entryObject.damage > 0) ? (Math.round(a_entryObject.damage * 100) / 100) : null; processWeaponType(a_entryObject); processMaterialKeywords(a_entryObject); processWeaponBaseId(a_entryObject); break; case Form.TYPE_AMMO: a_entryObject.infoDamage = (a_entryObject.damage > 0) ? (Math.round(a_entryObject.damage * 100) / 100) : null; processAmmoType(a_entryObject); processMaterialKeywords(a_entryObject); processAmmoBaseId(a_entryObject); break; case Form.TYPE_KEY: processKeyType(a_entryObject); break; case Form.TYPE_POTION: a_entryObject.duration = (a_entryObject.duration > 0) ? (Math.round(a_entryObject.duration * 100) / 100) : null; a_entryObject.magnitude = (a_entryObject.magnitude > 0) ? (Math.round(a_entryObject.magnitude * 100) / 100) : null; processPotionType(a_entryObject); break; case Form.TYPE_SOULGEM: processSoulGemType(a_entryObject); processSoulGemStatus(a_entryObject); processSoulGemBaseId(a_entryObject); break; } } /* PRIVATE FUNCTIONS */ private function processArmorClass(a_entryObject: Object): Void { if (a_entryObject.weightClass == Armor.WEIGHT_NONE) a_entryObject.weightClass = null; a_entryObject.weightClassDisplay = Translator.translate("$Other"); switch (a_entryObject.weightClass) { case Armor.WEIGHT_LIGHT: a_entryObject.weightClassDisplay = Translator.translate("$Light"); break; case Armor.WEIGHT_HEAVY: a_entryObject.weightClassDisplay = Translator.translate("$Heavy"); break; default: if (a_entryObject.keywords == undefined) break; if (a_entryObject.keywords["VendorItemClothing"] != undefined) { a_entryObject.weightClass = Armor.WEIGHT_CLOTHING; a_entryObject.weightClassDisplay = Translator.translate("$Clothing"); } else if (a_entryObject.keywords["VendorItemJewelry"] != undefined) { a_entryObject.weightClass = Armor.WEIGHT_JEWELRY; a_entryObject.weightClassDisplay = Translator.translate("$Jewelry"); } } } private function processMaterialKeywords(a_entryObject: Object): Void { a_entryObject.material = null; a_entryObject.materialDisplay = Translator.translate("$Other"); if (a_entryObject.keywords == undefined) return; if (a_entryObject.keywords["ArmorMaterialDaedric"] != undefined || a_entryObject.keywords["WeapMaterialDaedric"] != undefined) { a_entryObject.material = Material.DAEDRIC; a_entryObject.materialDisplay = Translator.translate("$Daedric"); } else if (a_entryObject.keywords["ArmorMaterialDragonplate"] != undefined) { a_entryObject.material = Material.DRAGONPLATE; a_entryObject.materialDisplay = Translator.translate("$Dragonplate"); } else if (a_entryObject.keywords["ArmorMaterialDragonscale"] != undefined) { a_entryObject.material = Material.DRAGONSCALE; a_entryObject.materialDisplay = Translator.translate("$Dragonscale"); } else if (a_entryObject.keywords["ArmorMaterialDwarven"] != undefined || a_entryObject.keywords["WeapMaterialDwarven"] != undefined) { a_entryObject.material = Material.DWARVEN; a_entryObject.materialDisplay = Translator.translate("$Dwarven"); } else if (a_entryObject.keywords["ArmorMaterialEbony"] != undefined || a_entryObject.keywords["WeapMaterialEbony"] != undefined) { a_entryObject.material = Material.EBONY; a_entryObject.materialDisplay = Translator.translate("$Ebony"); } else if (a_entryObject.keywords["ArmorMaterialElven"] != undefined || a_entryObject.keywords["WeapMaterialElven"] != undefined) { a_entryObject.material = Material.ELVEN; a_entryObject.materialDisplay = Translator.translate("$Elven"); } else if (a_entryObject.keywords["ArmorMaterialElvenGilded"] != undefined) { a_entryObject.material = Material.ELVENGILDED; a_entryObject.materialDisplay = Translator.translate("$Elven Gilded"); } else if (a_entryObject.keywords["ArmorMaterialGlass"] != undefined || a_entryObject.keywords["WeapMaterialGlass"] != undefined) { a_entryObject.material = Material.GLASS; a_entryObject.materialDisplay = Translator.translate("$Glass"); } else if (a_entryObject.keywords["ArmorMaterialHide"] != undefined) { a_entryObject.material = Material.HIDE; a_entryObject.materialDisplay = Translator.translate("$Hide"); } else if (a_entryObject.keywords["ArmorMaterialImperialHeavy"] != undefined || a_entryObject.keywords["ArmorMaterialImperialLight"] != undefined || a_entryObject.keywords["WeapMaterialImperial"] != undefined) { a_entryObject.material = Material.IMPERIAL; a_entryObject.materialDisplay = Translator.translate("$Imperial"); } else if (a_entryObject.keywords["ArmorMaterialImperialStudded"] != undefined) { a_entryObject.material = Material.IMPERIALSTUDDED; a_entryObject.materialDisplay = Translator.translate("$Studded"); } else if (a_entryObject.keywords["ArmorMaterialIron"] != undefined || a_entryObject.keywords["WeapMaterialIron"] != undefined) { a_entryObject.material = Material.IRON; a_entryObject.materialDisplay = Translator.translate("$Iron"); } else if (a_entryObject.keywords["ArmorMaterialIronBanded"] != undefined) { a_entryObject.material = Material.IRONBANDED; a_entryObject.materialDisplay = Translator.translate("$Iron Banded"); // Must be above leather, vampire armor has 2 material keywords } else if (a_entryObject.keywords["DLC1ArmorMaterialVampire"] != undefined) { a_entryObject.material = Material.VAMPIRE; a_entryObject.materialDisplay = Translator.translate("$Vampire"); } else if (a_entryObject.keywords["ArmorMaterialLeather"] != undefined) { a_entryObject.material = Material.LEATHER; a_entryObject.materialDisplay = Translator.translate("$Leather"); } else if (a_entryObject.keywords["ArmorMaterialOrcish"] != undefined || a_entryObject.keywords["WeapMaterialOrcish"] != undefined) { a_entryObject.material = Material.ORCISH; a_entryObject.materialDisplay = Translator.translate("$Orcish"); } else if (a_entryObject.keywords["ArmorMaterialScaled"] != undefined) { a_entryObject.material = Material.SCALED; a_entryObject.materialDisplay = Translator.translate("$Scaled"); } else if (a_entryObject.keywords["ArmorMaterialSteel"] != undefined || a_entryObject.keywords["WeapMaterialSteel"] != undefined) { a_entryObject.material = Material.STEEL; a_entryObject.materialDisplay = Translator.translate("$Steel"); } else if (a_entryObject.keywords["ArmorMaterialSteelPlate"] != undefined) { a_entryObject.material = Material.STEELPLATE; a_entryObject.materialDisplay = Translator.translate("$Steel Plate"); } else if (a_entryObject.keywords["ArmorMaterialStormcloak"] != undefined) { a_entryObject.material = Material.STORMCLOAK; a_entryObject.materialDisplay = Translator.translate("$Stormcloak"); } else if (a_entryObject.keywords["ArmorMaterialStudded"] != undefined) { a_entryObject.material = Material.STUDDED; a_entryObject.materialDisplay = Translator.translate("$Studded"); } else if (a_entryObject.keywords["DLC1ArmorMaterialDawnguard"] != undefined) { a_entryObject.material = Material.DAWNGUARD; a_entryObject.materialDisplay = Translator.translate("$Dawnguard"); } else if (a_entryObject.keywords["DLC1ArmorMaterialFalmerHardened"] != undefined || a_entryObject.keywords["DLC1ArmorMaterialFalmerHeavy"] != undefined) { a_entryObject.material = Material.FALMERHARDENED; a_entryObject.materialDisplay = Translator.translate("$Falmer Hardened"); } else if (a_entryObject.keywords["DLC1ArmorMaterialHunter"] != undefined) { a_entryObject.material = Material.HUNTER; a_entryObject.materialDisplay = Translator.translate("$Hunter"); } else if (a_entryObject.keywords["DLC1LD_CraftingMaterialAetherium"] != undefined) { a_entryObject.material = Material.AETHERIUM; a_entryObject.materialDisplay = Translator.translate("$Aetherium"); } else if (a_entryObject.keywords["DLC1WeapMaterialDragonbone"] != undefined) { a_entryObject.material = Material.DRAGONBONE; a_entryObject.materialDisplay = Translator.translate("$Dragonbone"); } else if (a_entryObject.keywords["DLC2ArmorMaterialBonemoldHeavy"] != undefined || a_entryObject.keywords["DLC2ArmorMaterialBonemoldLight"] != undefined) { a_entryObject.material = Material.BONEMOLD; a_entryObject.materialDisplay = Translator.translate("$Bonemold"); } else if (a_entryObject.keywords["DLC2ArmorMaterialChitinHeavy"] != undefined || a_entryObject.keywords["DLC2ArmorMaterialChitinLight"] != undefined) { a_entryObject.material = Material.CHITIN; a_entryObject.materialDisplay = Translator.translate("$Chitin"); } else if (a_entryObject.keywords["DLC2ArmorMaterialMoragTong"] != undefined) { a_entryObject.material = Material.MORAGTONG; a_entryObject.materialDisplay = Translator.translate("$Morag Tong"); } else if (a_entryObject.keywords["DLC2ArmorMaterialNordicHeavy"] != undefined || a_entryObject.keywords["DLC2ArmorMaterialNordicLight"] != undefined || a_entryObject.keywords["DLC2WeaponMaterialNordic"] != undefined) { a_entryObject.material = Material.NORDIC; a_entryObject.materialDisplay = Translator.translate("$Nordic"); } else if (a_entryObject.keywords["DLC2ArmorMaterialStalhrimHeavy"] != undefined || a_entryObject.keywords["DLC2ArmorMaterialStalhrimLight"] != undefined || a_entryObject.keywords["DLC2WeaponMaterialStalhrim"] != undefined) { a_entryObject.material = Material.STALHRIM; a_entryObject.materialDisplay = Translator.translate("$Stalhrim"); if (a_entryObject.keywords["DLC2dunHaknirArmor"] != undefined) { a_entryObject.material = Material.DEATHBRAND; a_entryObject.materialDisplay = Translator.translate("$Deathbrand"); } } else if (a_entryObject.keywords["WeapMaterialDraugr"] != undefined) { a_entryObject.material = Material.DRAUGR; a_entryObject.materialDisplay = Translator.translate("$Draugr"); } else if (a_entryObject.keywords["WeapMaterialDraugrHoned"] != undefined) { a_entryObject.material = Material.DRAUGRHONED; a_entryObject.materialDisplay = Translator.translate("$Draugr Honed"); } else if (a_entryObject.keywords["WeapMaterialFalmer"] != undefined) { a_entryObject.material = Material.FALMER; a_entryObject.materialDisplay = Translator.translate("$Falmer"); } else if (a_entryObject.keywords["WeapMaterialFalmerHoned"] != undefined) { a_entryObject.material = Material.FALMERHONED; a_entryObject.materialDisplay = Translator.translate("$Falmer Honed"); } else if (a_entryObject.keywords["WeapMaterialSilver"] != undefined) { a_entryObject.material = Material.SILVER; a_entryObject.materialDisplay = Translator.translate("$Silver"); } else if (a_entryObject.keywords["WeapMaterialWood"] != undefined) { a_entryObject.material = Material.WOOD; a_entryObject.materialDisplay = Translator.translate("$Wood"); } } private function processWeaponType(a_entryObject: Object): Void { a_entryObject.subType = null; a_entryObject.subTypeDisplay = Translator.translate("$Weapon"); switch (a_entryObject.weaponType) { case Weapon.ANIM_HANDTOHANDMELEE: case Weapon.ANIM_H2H: a_entryObject.subType = Weapon.TYPE_MELEE; a_entryObject.subTypeDisplay = Translator.translate("$Melee"); break; case Weapon.ANIM_ONEHANDSWORD: case Weapon.ANIM_1HS: a_entryObject.subType = Weapon.TYPE_SWORD; a_entryObject.subTypeDisplay = Translator.translate("$Sword"); break; case Weapon.ANIM_ONEHANDDAGGER: case Weapon.ANIM_1HD: a_entryObject.subType = Weapon.TYPE_DAGGER; a_entryObject.subTypeDisplay = Translator.translate("$Dagger"); break; case Weapon.ANIM_ONEHANDAXE: case Weapon.ANIM_1HA: a_entryObject.subType = Weapon.TYPE_WARAXE; a_entryObject.subTypeDisplay = Translator.translate("$War Axe"); break; case Weapon.ANIM_ONEHANDMACE: case Weapon.ANIM_1HM: a_entryObject.subType = Weapon.TYPE_MACE; a_entryObject.subTypeDisplay = Translator.translate("$Mace"); break; case Weapon.ANIM_TWOHANDSWORD: case Weapon.ANIM_2HS: a_entryObject.subType = Weapon.TYPE_GREATSWORD; a_entryObject.subTypeDisplay = Translator.translate("$Greatsword"); break; case Weapon.ANIM_TWOHANDAXE: case Weapon.ANIM_2HA: a_entryObject.subType = Weapon.TYPE_BATTLEAXE; a_entryObject.subTypeDisplay = Translator.translate("$Battleaxe"); if (a_entryObject.keywords != undefined && a_entryObject.keywords["WeapTypeWarhammer"] != undefined) { a_entryObject.subType = Weapon.TYPE_WARHAMMER; a_entryObject.subTypeDisplay = Translator.translate("$Warhammer"); } break; case Weapon.ANIM_BOW: case Weapon.ANIM_BOW2: a_entryObject.subType = Weapon.TYPE_BOW; a_entryObject.subTypeDisplay = Translator.translate("$Bow"); break; case Weapon.ANIM_STAFF: case Weapon.ANIM_STAFF2: a_entryObject.subType = Weapon.TYPE_STAFF; a_entryObject.subTypeDisplay = Translator.translate("$Staff"); break; case Weapon.ANIM_CROSSBOW: case Weapon.ANIM_CBOW: a_entryObject.subType = Weapon.TYPE_CROSSBOW; a_entryObject.subTypeDisplay = Translator.translate("$Crossbow"); break; } } private function processWeaponBaseId(a_entryObject: Object): Void { switch (a_entryObject.baseId) { case Form.BASEID_WEAPPICKAXE: case Form.BASEID_SSDROCKSPLINTERPICKAXE: case Form.BASEID_DUNVOLUNRUUDPICKAXE: a_entryObject.subType = Weapon.TYPE_PICKAXE; a_entryObject.subTypeDisplay = Translator.translate("$Pickaxe"); break; case Form.BASEID_AXE01: case Form.BASEID_DUNHALTEDSTREAMPOACHERSAXE: a_entryObject.subType = Weapon.TYPE_WOODAXE; a_entryObject.subTypeDisplay = Translator.translate("$Wood Axe"); break; } } private function processArmorPartMask(a_entryObject: Object): Void { if (a_entryObject.partMask == undefined) return; // Sets subType as the most important bitmask index. for (var i = 0; i < Armor.PARTMASK_PRECEDENCE.length; i++) { if (a_entryObject.partMask & Armor.PARTMASK_PRECEDENCE[i]) { a_entryObject.mainPartMask = Armor.PARTMASK_PRECEDENCE[i]; break; } } if (a_entryObject.mainPartMask == undefined) return; switch (a_entryObject.mainPartMask) { case Armor.PARTMASK_HEAD: a_entryObject.subType = Armor.EQUIP_HEAD; a_entryObject.subTypeDisplay = Translator.translate("$Head"); break; case Armor.PARTMASK_HAIR: a_entryObject.subType = Armor.EQUIP_HAIR; a_entryObject.subTypeDisplay = Translator.translate("$Head"); break; case Armor.PARTMASK_LONGHAIR: a_entryObject.subType = Armor.EQUIP_LONGHAIR; a_entryObject.subTypeDisplay = Translator.translate("$Head"); break; case Armor.PARTMASK_BODY: a_entryObject.subType = Armor.EQUIP_BODY; a_entryObject.subTypeDisplay = Translator.translate("$Body"); break; case Armor.PARTMASK_HANDS: a_entryObject.subType = Armor.EQUIP_HANDS; a_entryObject.subTypeDisplay = Translator.translate("$Hands"); break; case Armor.PARTMASK_FOREARMS: a_entryObject.subType = Armor.EQUIP_FOREARMS; a_entryObject.subTypeDisplay = Translator.translate("$Forearms"); break; case Armor.PARTMASK_AMULET: a_entryObject.subType = Armor.EQUIP_AMULET; a_entryObject.subTypeDisplay = Translator.translate("$Amulet"); break; case Armor.PARTMASK_RING: a_entryObject.subType = Armor.EQUIP_RING; a_entryObject.subTypeDisplay = Translator.translate("$Ring"); break; case Armor.PARTMASK_FEET: a_entryObject.subType = Armor.EQUIP_FEET; a_entryObject.subTypeDisplay = Translator.translate("$Feet"); break; case Armor.PARTMASK_CALVES: a_entryObject.subType = Armor.EQUIP_CALVES; a_entryObject.subTypeDisplay = Translator.translate("$Calves"); break; case Armor.PARTMASK_SHIELD: a_entryObject.subType = Armor.EQUIP_SHIELD; a_entryObject.subTypeDisplay = Translator.translate("$Shield"); break; case Armor.PARTMASK_CIRCLET: a_entryObject.subType = Armor.EQUIP_CIRCLET; a_entryObject.subTypeDisplay = Translator.translate("$Circlet"); break; case Armor.PARTMASK_EARS: a_entryObject.subType = Armor.EQUIP_EARS; a_entryObject.subTypeDisplay = Translator.translate("$Ears"); break; case Armor.PARTMASK_TAIL: a_entryObject.subType = Armor.EQUIP_TAIL; a_entryObject.subTypeDisplay = Translator.translate("$Tail"); break; default: a_entryObject.subType = a_entryObject.mainPartMask; break; } } private function processArmorOther(a_entryObject): Void { if (a_entryObject.weightClass != null) return; switch (a_entryObject.mainPartMask) { case Armor.PARTMASK_HEAD: case Armor.PARTMASK_HAIR: case Armor.PARTMASK_LONGHAIR: case Armor.PARTMASK_BODY: case Armor.PARTMASK_HANDS: case Armor.PARTMASK_FOREARMS: case Armor.PARTMASK_FEET: case Armor.PARTMASK_CALVES: case Armor.PARTMASK_SHIELD: case Armor.PARTMASK_TAIL: a_entryObject.weightClass = Armor.WEIGHT_CLOTHING; a_entryObject.weightClassDisplay = Translator.translate("$Clothing"); break; case Armor.PARTMASK_AMULET: case Armor.PARTMASK_RING: case Armor.PARTMASK_CIRCLET: case Armor.PARTMASK_EARS: a_entryObject.weightClass = Armor.WEIGHT_JEWELRY; a_entryObject.weightClassDisplay = Translator.translate("$Jewelry"); break; } } private function processArmorBaseId(a_entryObject: Object): Void { switch (a_entryObject.baseId) { case Form.BASEID_CLOTHESWEDDINGWREATH: a_entryObject.weightClass = Armor.WEIGHT_JEWELRY; a_entryObject.weightClassDisplay = Translator.translate("$Jewelry"); break case Form.BASEID_DLC1CLOTHESVAMPIRELORDARMOR: a_entryObject.subType = Armor.EQUIP_BODY; a_entryObject.subTypeDisplay = Translator.translate("$Body"); break; } } private function processBookType(a_entryObject: Object): Void { a_entryObject.subType = Item.OTHER; a_entryObject.subTypeDisplay = Translator.translate("$Book"); a_entryObject.isRead = ((a_entryObject.flags & Item.BOOKFLAG_READ) != 0); if (a_entryObject.bookType == Item.BOOKTYPE_NOTE) { a_entryObject.subType = Item.BOOK_NOTE; a_entryObject.subTypeDisplay = Translator.translate("$Note"); } if (a_entryObject.keywords == undefined) return; if (a_entryObject.keywords["VendorItemRecipe"] != undefined) { a_entryObject.subType = Item.BOOK_RECIPE; a_entryObject.subTypeDisplay = Translator.translate("$Recipe"); } else if (a_entryObject.keywords["VendorItemSpellTome"] != undefined) { a_entryObject.subType = Item.BOOK_SPELLTOME; a_entryObject.subTypeDisplay = Translator.translate("$Spell Tome"); } } private function processAmmoType(a_entryObject: Object): Void { if ((a_entryObject.flags & Weapon.AMMOFLAG_NONBOLT) != 0) { a_entryObject.subType = Weapon.AMMO_ARROW; a_entryObject.subTypeDisplay = Translator.translate("$Arrow"); } else { a_entryObject.subType = Weapon.AMMO_BOLT; a_entryObject.subTypeDisplay = Translator.translate("$Bolt"); } } private function processAmmoBaseId(a_entryObject: Object): Void { switch (a_entryObject.baseId) { case Form.BASEID_DAEDRICARROW: a_entryObject.material = Material.DAEDRIC; a_entryObject.materialDisplay = Translator.translate("$Daedric"); break; case Form.BASEID_EBONYARROW: a_entryObject.material = Material.EBONY; a_entryObject.materialDisplay = Translator.translate("$Ebony"); break; case Form.BASEID_GLASSARROW: a_entryObject.material = Material.GLASS; a_entryObject.materialDisplay = Translator.translate("$Glass"); break; case Form.BASEID_ELVENARROW: case Form.BASEID_DLC1ELVENARROWBLESSED: case Form.BASEID_DLC1ELVENARROWBLOOD: a_entryObject.material = Material.ELVEN; a_entryObject.materialDisplay = Translator.translate("$Elven"); break; case Form.BASEID_DWARVENARROW: case Form.BASEID_DWARVENSPHEREARROW: case Form.BASEID_DWARVENSPHEREBOLT01: case Form.BASEID_DWARVENSPHEREBOLT02: case Form.BASEID_DLC2DWARVENBALLISTABOLT: a_entryObject.material = Material.DWARVEN; a_entryObject.materialDisplay = Translator.translate("$Dwarven"); break; case Form.BASEID_ORCISHARROW: a_entryObject.material = Material.ORCISH; a_entryObject.materialDisplay = Translator.translate("$Orcish"); break; case Form.BASEID_NORDHEROARROW: a_entryObject.material = Material.NORDIC; a_entryObject.materialDisplay = Translator.translate("$Nordic"); break; case Form.BASEID_DRAUGRARROW: a_entryObject.material = Material.DRAUGR; a_entryObject.materialDisplay = Translator.translate("$Draugr"); break; case Form.BASEID_FALMERARROW: a_entryObject.material = Material.FALMER; a_entryObject.materialDisplay = Translator.translate("$Falmer"); break; case Form.BASEID_STEELARROW: case Form.BASEID_MQ101STEELARROW: a_entryObject.material = Material.STEEL; a_entryObject.materialDisplay = Translator.translate("$Steel"); break; case Form.BASEID_IRONARROW: case Form.BASEID_CWARROW: case Form.BASEID_CWARROWSHORT: case Form.BASEID_TRAPDART: case Form.BASEID_DUNARCHERPRATICEARROW: case Form.BASEID_DUNGEIRMUNDSIGDISARROWSILLUSION: case Form.BASEID_FOLLOWERIRONARROW: case Form.BASEID_TESTDLC1BOLT: a_entryObject.material = Material.IRON; a_entryObject.materialDisplay = Translator.translate("$Iron"); break; case Form.BASEID_FORSWORNARROW: a_entryObject.material = Material.HIDE; a_entryObject.materialDisplay = Translator.translate("$Forsworn"); break; case Form.BASEID_DLC2RIEKLINGSPEARTHROWN: a_entryObject.material = Material.WOOD; a_entryObject.materialDisplay = Translator.translate("$Wood"); a_entryObject.subTypeDisplay = Translator.translate("$Spear"); break; } } private function processKeyType(a_entryObject: Object): Void { a_entryObject.subTypeDisplay = Translator.translate("$Key"); if (a_entryObject.infoValue <= 0) a_entryObject.infoValue = null; if (a_entryObject.infoValue <= 0) a_entryObject.infoValue = null; } private function processPotionType(a_entryObject: Object): Void { a_entryObject.subType = Item.POTION_POTION; a_entryObject.subTypeDisplay = Translator.translate("$Potion"); if ((a_entryObject.flags & Item.ALCHFLAG_FOOD) != 0) { a_entryObject.subType = Item.POTION_FOOD; a_entryObject.subTypeDisplay = Translator.translate("$Food"); // SKSE >= 1.6.6 if (a_entryObject.useSound.formId != undefined && a_entryObject.useSound.formId == Form.FORMID_ITMPotionUse) { a_entryObject.subType = Item.POTION_DRINK; a_entryObject.subTypeDisplay = Translator.translate("$Drink"); } } else if ((a_entryObject.flags & Item.ALCHFLAG_POISON) != 0) { a_entryObject.subType = Item.POTION_POISON; a_entryObject.subTypeDisplay = Translator.translate("$Poison"); } else { switch (a_entryObject.actorValue) { case Actor.AV_HEALTH: a_entryObject.subType = Item.POTION_HEALTH; a_entryObject.subTypeDisplay = Translator.translate("$Health"); break; case Actor.AV_MAGICKA: a_entryObject.subType = Item.POTION_MAGICKA; a_entryObject.subTypeDisplay = Translator.translate("$Magicka"); break; case Actor.AV_STAMINA: a_entryObject.subType = Item.POTION_STAMINA; a_entryObject.subTypeDisplay = Translator.translate("$Stamina"); break; case Actor.AV_HEALRATE: a_entryObject.subType = Item.POTION_HEALRATE; a_entryObject.subTypeDisplay = Translator.translate("$Health"); break; case Actor.AV_MAGICKARATE: a_entryObject.subType = Item.POTION_MAGICKARATE; a_entryObject.subTypeDisplay = Translator.translate("$Magicka"); break; case Actor.AV_STAMINARATE: a_entryObject.subType = Item.POTION_STAMINARATE; a_entryObject.subTypeDisplay = Translator.translate("$Stamina"); break; case Actor.AV_HEALRATEMULT: a_entryObject.subType = Item.POTION_HEALRATEMULT; a_entryObject.subTypeDisplay = Translator.translate("$Health"); break; case Actor.AV_MAGICKARATEMULT: a_entryObject.subType = Item.POTION_MAGICKARATEMULT; a_entryObject.subTypeDisplay = Translator.translate("$Magicka"); break; case Actor.AV_STAMINARATEMULT: a_entryObject.subType = Item.POTION_STAMINARATEMULT; a_entryObject.subTypeDisplay = Translator.translate("$Stamina"); break; case Actor.AV_FIRERESIST: a_entryObject.subType = Item.POTION_FIRERESIST; break; case Actor.AV_ELECTRICRESIST: a_entryObject.subType = Item.POTION_ELECTRICRESIST; break; case Actor.AV_FROSTRESIST: a_entryObject.subType = Item.POTION_FROSTRESIST; break; } } } private function processSoulGemType(a_entryObject: Object): Void { a_entryObject.subType = Item.OTHER; a_entryObject.subTypeDisplay = Translator.translate("$Soul Gem"); // Ignores soulgems that have a size of None if (a_entryObject.gemSize != undefined && a_entryObject.gemSize != Item.SOULGEM_NONE) a_entryObject.subType = a_entryObject.gemSize; } private function processSoulGemStatus(a_entryObject: Object): Void { if (a_entryObject.gemSize == undefined || a_entryObject.soulSize == undefined || a_entryObject.soulSize == Item.SOULGEM_NONE) a_entryObject.status = Item.SOULGEMSTATUS_EMPTY; else if (a_entryObject.soulSize >= a_entryObject.gemSize) a_entryObject.status = Item.SOULGEMSTATUS_FULL; else a_entryObject.status = Item.SOULGEMSTATUS_PARTIAL; if (a_entryObject.soulSize != undefined) { switch (a_entryObject.soulSize) { case Item.SOULGEM_NONE: a_entryObject.soulSizeDisplay = "$Empty"; break; case Item.SOULGEM_PETTY: a_entryObject.soulSizeDisplay = "$Petty"; break; case Item.SOULGEM_LESSER: a_entryObject.soulSizeDisplay = "$Lesser"; break; case Item.SOULGEM_COMMON: a_entryObject.soulSizeDisplay = "$Common"; break; case Item.SOULGEM_GREATER: a_entryObject.soulSizeDisplay = "$Greater"; break; case Item.SOULGEM_GRAND: case Item.SOULGEM_AZURA: a_entryObject.soulSizeDisplay = "$Grand"; break; } } } private function processSoulGemBaseId(a_entryObject: Object): Void { switch (a_entryObject.baseId) { case Form.BASEID_DA01SOULGEMBLACKSTAR: case Form.BASEID_DA01SOULGEMAZURASSTAR: a_entryObject.subType = Item.SOULGEM_AZURA; break; } } private function processMiscType(a_entryObject: Object): Void { a_entryObject.subType = Item.OTHER; a_entryObject.subTypeDisplay = Translator.translate("$Misc"); if (a_entryObject.keywords == undefined) return; if (a_entryObject.keywords["BYOHAdoptionClothesKeyword"] != undefined) { a_entryObject.subType = Item.MISC_CHILDRENSCLOTHES; a_entryObject.subTypeDisplay = Translator.translate("$Clothing"); } else if (a_entryObject.keywords["BYOHAdoptionToyKeyword"] != undefined) { a_entryObject.subType = Item.MISC_TOY; a_entryObject.subTypeDisplay = Translator.translate("$Toy"); } else if (a_entryObject.keywords["BYOHHouseCraftingCategoryWeaponRacks"] != undefined || a_entryObject.keywords["BYOHHouseCraftingCategoryShelf"] != undefined || a_entryObject.keywords["BYOHHouseCraftingCategoryFurniture"] != undefined || a_entryObject.keywords["BYOHHouseCraftingCategoryExterior"] != undefined || a_entryObject.keywords["BYOHHouseCraftingCategoryContainers"] != undefined || a_entryObject.keywords["BYOHHouseCraftingCategoryBuilding"] != undefined || a_entryObject.keywords["BYOHHouseCraftingCategorySmithing"] != undefined) { a_entryObject.subType = Item.MISC_HOUSEPART; a_entryObject.subTypeDisplay = Translator.translate("$House Part"); } else if (a_entryObject.keywords["VendorItemDaedricArtifact"] != undefined) { a_entryObject.subType = Item.MISC_ARTIFACT; a_entryObject.subTypeDisplay = Translator.translate("$Artifact"); } else if (a_entryObject.keywords["VendorItemGem"] != undefined) { a_entryObject.subType = Item.MISC_GEM; a_entryObject.subTypeDisplay = Translator.translate("$Gem"); } else if (a_entryObject.keywords["VendorItemAnimalHide"] != undefined) { a_entryObject.subType = Item.MISC_HIDE; a_entryObject.subTypeDisplay = Translator.translate("$Hide"); } else if (a_entryObject.keywords["VendorItemTool"] != undefined) { a_entryObject.subType = Item.MISC_TOOL; a_entryObject.subTypeDisplay = Translator.translate("$Tool"); } else if (a_entryObject.keywords["VendorItemAnimalPart"] != undefined) { a_entryObject.subType = Item.MISC_REMAINS; a_entryObject.subTypeDisplay = Translator.translate("$Remains"); } else if (a_entryObject.keywords["VendorItemOreIngot"] != undefined) { a_entryObject.subType = Item.MISC_INGOT; a_entryObject.subTypeDisplay = Translator.translate("$Ingot"); } else if (a_entryObject.keywords["VendorItemClutter"] != undefined) { a_entryObject.subType = Item.MISC_CLUTTER; a_entryObject.subTypeDisplay = Translator.translate("$Clutter"); } else if (a_entryObject.keywords["VendorItemFirewood"] != undefined) { a_entryObject.subType = Item.MISC_FIREWOOD; a_entryObject.subTypeDisplay = Translator.translate("$Firewood"); } } private function processMiscBaseId(a_entryObject: Object): Void { switch (a_entryObject.baseId) { case Form.BASEID_GEMAMETHYSTFLAWLESS: a_entryObject.subType = Item.MISC_GEM; a_entryObject.subTypeDisplay = Translator.translate("$Gem"); break; case Form.BASEID_RUBYDRAGONCLAW: case Form.BASEID_IVORYDRAGONCLAW: case Form.BASEID_GLASSCLAW: case Form.BASEID_EBONYCLAW: case Form.BASEID_EMERALDDRAGONCLAW: case Form.BASEID_DIAMONDCLAW: case Form.BASEID_IRONCLAW: case Form.BASEID_CORALDRAGONCLAW: case Form.BASEID_E3GOLDENCLAW: case Form.BASEID_SAPPHIREDRAGONCLAW: case Form.BASEID_MS13GOLDENCLAW: a_entryObject.subTypeDisplay = Translator.translate("$Claw"); a_entryObject.subType = Item.MISC_DRAGONCLAW; break; case Form.BASEID_LOCKPICK: a_entryObject.subType = Item.MISC_LOCKPICK; a_entryObject.subTypeDisplay = Translator.translate("$Lockpick"); break; case Form.BASEID_GOLD001: a_entryObject.subType = Item.MISC_GOLD; a_entryObject.subTypeDisplay = Translator.translate("$Gold"); break; case Form.BASEID_LEATHER01: a_entryObject.subTypeDisplay = Translator.translate("$Leather"); a_entryObject.subType = Item.MISC_LEATHER; break; case Form.BASEID_LEATHERSTRIPS: a_entryObject.subTypeDisplay = Translator.translate("$Strips"); a_entryObject.subType = Item.MISC_LEATHERSTRIPS; break; } } private function fixSKSEExtendedObject(a_extendedObject: Object): Void { if (a_extendedObject.formType == undefined) return; switch(a_extendedObject.formType) { case Form.TYPE_SPELL: case Form.TYPE_SCROLLITEM: case Form.TYPE_INGREDIENT: case Form.TYPE_POTION: case Form.TYPE_EFFECTSETTING: // school is sent as subType if (a_extendedObject.school == undefined && a_extendedObject.subType != undefined) { a_extendedObject.school = a_extendedObject.subType; delete(a_extendedObject.subType); } // resistance is sent as magicType if (a_extendedObject.resistance == undefined && a_extendedObject.magicType != undefined) { a_extendedObject.resistance = a_extendedObject.magicType; delete(a_extendedObject.magicType); } // primaryValue is sent as actorValue /* // Ignore if (a_extendedObject.primaryValue == undefined && a_extendedObject.actorValue != undefined) { a_extendedObject.primaryValue = a_extendedObject.actorValue; delete(a_extendedObject.actorValue); } */ break; case Form.TYPE_WEAPON: // weaponType is sent as subType if (a_extendedObject.weaponType == undefined && a_extendedObject.subType != undefined) { a_extendedObject.weaponType = a_extendedObject.subType; delete(a_extendedObject.subType); } break; case Form.TYPE_BOOK: // (SKSE < 1.6.6) flags and bookType (and some padding) are sent as one UInt32 bookType if (a_extendedObject.flags == undefined && a_extendedObject.bookType != undefined) { var oldBookType: Number = a_extendedObject.bookType; a_extendedObject.bookType = (oldBookType & 0xFF00) >>> 8; a_extendedObject.flags = (oldBookType & 0x00FF); } break; default: break; } } } ================================================ FILE: src/CraftingMenu/CraftingIconSetter.as ================================================ import skyui.components.list.BasicList; import skyui.components.list.IListProcessor; import skyui.defines.Actor; import skyui.defines.Armor; import skyui.defines.Form; import skyui.defines.Item; import skyui.defines.Material; import skyui.defines.Weapon; class CraftingIconSetter implements IListProcessor { /* PRIVATE VARIABLES */ private var _noIconColors: Boolean; /* INITIALIZATION */ public function CraftingIconSetter(a_configAppearance: Object) { _noIconColors = a_configAppearance.icons.item.noColor; } /* PUBLIC FUNCTIONS */ // @override IListProcessor public function processList(a_list: BasicList): Void { var entryList: Array = a_list.entryList; for (var i: Number = 0; i < entryList.length; i++) processEntry(entryList[i]); } /* PRIVATE FUNCTIONS */ private function processEntry(a_entryObject: Object): Void { switch (a_entryObject.formType) { case Form.TYPE_SCROLLITEM: a_entryObject.iconLabel = "default_scroll"; processResist(a_entryObject); break; case Form.TYPE_ARMOR: processArmorIcon(a_entryObject); break; case Form.TYPE_BOOK: processBookIcon(a_entryObject); break; case Form.TYPE_INGREDIENT: a_entryObject.iconLabel = "default_ingredient"; break; case Form.TYPE_LIGHT: a_entryObject.iconLabel = "misc_torch"; break; case Form.TYPE_MISC: processMiscIcon(a_entryObject); break; case Form.TYPE_WEAPON: processWeaponIcon(a_entryObject); break; case Form.TYPE_AMMO: processAmmoIcon(a_entryObject); break; case Form.TYPE_KEY: a_entryObject.iconLabel = "default_key"; break; case Form.TYPE_POTION: processPotionIcon(a_entryObject); break; case Form.TYPE_SOULGEM: processSoulGemIcon(a_entryObject); break; case Form.TYPE_ENCHANTMENT: a_entryObject.iconLabel = "default_effect"; break; } if (_noIconColors && a_entryObject.iconColor != undefined) delete(a_entryObject.iconColor); } private function processResist(a_entryObject: Object): Void { if (a_entryObject.resistance == undefined || a_entryObject.resistance == Actor.AV_NONE) return; switch(a_entryObject.resistance) { case Actor.AV_FIRERESIST: a_entryObject.iconColor = 0xC73636; break; case Actor.AV_ELECTRICRESIST: a_entryObject.iconColor = 0xFFFF00; break; case Actor.AV_FROSTRESIST: a_entryObject.iconColor = 0x1FFBFF; break; } } private function processArmorIcon(a_entryObject: Object): Void { a_entryObject.iconLabel = "default_armor"; a_entryObject.iconColor = 0xEDDA87; switch (a_entryObject.weightClass) { case Armor.WEIGHT_LIGHT: processLightArmorIcon(a_entryObject); break; case Armor.WEIGHT_HEAVY: processHeavyArmorIcon(a_entryObject); break; case Armor.WEIGHT_JEWELRY: processJewelryArmorIcon(a_entryObject); break; case Armor.WEIGHT_CLOTHING: default: processClothingArmorIcon(a_entryObject); break; } } private function processLightArmorIcon(a_entryObject: Object): Void { a_entryObject.iconColor = 0x756000; switch(a_entryObject.subType) { case Armor.EQUIP_HEAD: case Armor.EQUIP_HAIR: case Armor.EQUIP_LONGHAIR: a_entryObject.iconLabel = "lightarmor_head"; break; case Armor.EQUIP_BODY: case Armor.EQUIP_TAIL: a_entryObject.iconLabel = "lightarmor_body"; break; case Armor.EQUIP_HANDS: a_entryObject.iconLabel = "lightarmor_hands"; break; case Armor.EQUIP_FOREARMS: a_entryObject.iconLabel = "lightarmor_forearms"; break; case Armor.EQUIP_FEET: a_entryObject.iconLabel = "lightarmor_feet"; break; case Armor.EQUIP_CALVES: a_entryObject.iconLabel = "lightarmor_calves"; break; case Armor.EQUIP_SHIELD: a_entryObject.iconLabel = "lightarmor_shield"; break; case Armor.EQUIP_AMULET: case Armor.EQUIP_RING: case Armor.EQUIP_CIRCLET: case Armor.EQUIP_EARS: processJewelryArmorIcon(a_entryObject); break; } } private function processHeavyArmorIcon(a_entryObject: Object): Void { a_entryObject.iconColor = 0x6B7585; switch(a_entryObject.subType) { case Armor.EQUIP_HEAD: case Armor.EQUIP_HAIR: case Armor.EQUIP_LONGHAIR: a_entryObject.iconLabel = "armor_head"; break; case Armor.EQUIP_BODY: case Armor.EQUIP_TAIL: a_entryObject.iconLabel = "armor_body"; break; case Armor.EQUIP_HANDS: a_entryObject.iconLabel = "armor_hands"; break; case Armor.EQUIP_FOREARMS: a_entryObject.iconLabel = "armor_forearms"; break; case Armor.EQUIP_FEET: a_entryObject.iconLabel = "armor_feet"; break; case Armor.EQUIP_CALVES: a_entryObject.iconLabel = "armor_calves"; break; case Armor.EQUIP_SHIELD: a_entryObject.iconLabel = "armor_shield"; break; case Armor.EQUIP_AMULET: case Armor.EQUIP_RING: case Armor.EQUIP_CIRCLET: case Armor.EQUIP_EARS: processJewelryArmorIcon(a_entryObject); break; } } private function processJewelryArmorIcon(a_entryObject: Object): Void { switch(a_entryObject.subType) { case Armor.EQUIP_AMULET: a_entryObject.iconLabel = "armor_amulet"; break; case Armor.EQUIP_RING: a_entryObject.iconLabel = "armor_ring"; break; case Armor.EQUIP_CIRCLET: a_entryObject.iconLabel = "armor_circlet"; break; case Armor.EQUIP_EARS: break; } } private function processClothingArmorIcon(a_entryObject: Object): Void { switch(a_entryObject.subType) { case Armor.EQUIP_HEAD: case Armor.EQUIP_HAIR: case Armor.EQUIP_LONGHAIR: a_entryObject.iconLabel = "clothing_head"; break; case Armor.EQUIP_BODY: case Armor.EQUIP_TAIL: a_entryObject.iconLabel = "clothing_body"; break; case Armor.EQUIP_HANDS: a_entryObject.iconLabel = "clothing_hands"; break; case Armor.EQUIP_FOREARMS: a_entryObject.iconLabel = "clothing_forearms"; break; case Armor.EQUIP_FEET: a_entryObject.iconLabel = "clothing_feet"; break; case Armor.EQUIP_CALVES: a_entryObject.iconLabel = "clothing_calves"; break; case Armor.EQUIP_SHIELD: a_entryObject.iconLabel = "clothing_shield"; break; case Armor.EQUIP_EARS: break; } } // Books private function processBookIcon(a_entryObject: Object): Void { a_entryObject.iconLabel = "default_book"; switch(a_entryObject.subType) { case Item.BOOK_RECIPE: case Item.BOOK_NOTE: a_entryObject.iconLabel = "book_note"; break; case Item.BOOK_SPELLTOME: a_entryObject.iconLabel = "book_tome"; break; } } // Weapons private function processWeaponIcon(a_entryObject: Object): Void { a_entryObject.iconLabel = "default_weapon"; a_entryObject.iconColor = 0xA4A5BF; switch(a_entryObject.subType) { case Weapon.TYPE_MELEE: break; case Weapon.TYPE_SWORD: a_entryObject.iconLabel = "weapon_sword"; break; case Weapon.TYPE_DAGGER: a_entryObject.iconLabel = "weapon_dagger"; break; case Weapon.TYPE_WARAXE: a_entryObject.iconLabel = "weapon_waraxe"; break; case Weapon.TYPE_MACE: a_entryObject.iconLabel = "weapon_mace"; break; case Weapon.TYPE_GREATSWORD: a_entryObject.iconLabel = "weapon_greatsword"; break; case Weapon.TYPE_BATTLEAXE: a_entryObject.iconLabel = "weapon_battleaxe"; break; case Weapon.TYPE_WARHAMMER: a_entryObject.iconLabel = "weapon_hammer"; break; case Weapon.TYPE_BOW: a_entryObject.iconLabel = "weapon_bow"; break; case Weapon.TYPE_STAFF: a_entryObject.iconLabel = "weapon_staff"; break; case Weapon.TYPE_CROSSBOW: a_entryObject.iconLabel = "weapon_crossbow"; break; case Weapon.TYPE_PICKAXE: a_entryObject.iconLabel = "weapon_pickaxe"; break; case Weapon.TYPE_WOODAXE: a_entryObject.iconLabel = "weapon_woodaxe"; break; } } // Ammo private function processAmmoIcon(a_entryObject: Object): Void { a_entryObject.iconLabel = "weapon_arrow"; a_entryObject.iconColor = 0xA89E8C; switch(a_entryObject.subType) { case Weapon.AMMO_ARROW: a_entryObject.iconLabel = "weapon_arrow"; break; case Weapon.AMMO_BOLT: a_entryObject.iconLabel = "weapon_bolt"; break; } } private function processPotionIcon(a_entryObject: Object): Void { a_entryObject.iconLabel = "default_potion"; switch(a_entryObject.subType) { case Item.POTION_DRINK: a_entryObject.iconLabel = "food_wine"; break; case Item.POTION_FOOD: a_entryObject.iconLabel = "default_food"; break; case Item.POTION_POISON: a_entryObject.iconLabel = "potion_poison"; a_entryObject.iconColor = 0xAD00B3; break; case Item.POTION_HEALTH: case Item.POTION_HEALRATE: case Item.POTION_HEALRATEMULT: a_entryObject.iconLabel = "potion_health"; a_entryObject.iconColor = 0xDB2E73; break; case Item.POTION_MAGICKA: case Item.POTION_MAGICKARATE: case Item.POTION_MAGICKARATEMULT: a_entryObject.iconLabel = "potion_magic"; a_entryObject.iconColor = 0x2E9FDB; break; case Item.POTION_STAMINA: case Item.POTION_STAMINARATE: case Item.POTION_STAMINARATEMULT: a_entryObject.iconLabel = "potion_stam"; a_entryObject.iconColor = 0x51DB2E; break; case Item.POTION_FIRERESIST: a_entryObject.iconLabel = "potion_fire"; a_entryObject.iconColor = 0xC73636; break; case Item.POTION_ELECTRICRESIST: a_entryObject.iconLabel = "potion_shock"; a_entryObject.iconColor = 0xEAAB00; break; case Item.POTION_FROSTRESIST: a_entryObject.iconLabel = "potion_frost"; a_entryObject.iconColor = 0x1FFBFF; break; } } private function processSoulGemIcon(a_entryObject: Object): Void { a_entryObject.iconLabel = "misc_soulgem"; a_entryObject.iconColor = 0xE3E0FF; switch(a_entryObject.subType) { case Item.SOULGEM_PETTY: a_entryObject.iconColor = 0xD7D4FF; processSoulGemStatusIcon(a_entryObject); break; case Item.SOULGEM_LESSER: a_entryObject.iconColor = 0xC0BAFF; processSoulGemStatusIcon(a_entryObject); break; case Item.SOULGEM_COMMON: a_entryObject.iconColor = 0xABA3FF; processSoulGemStatusIcon(a_entryObject); break; case Item.SOULGEM_GREATER: a_entryObject.iconColor = 0x948BFC; processGrandSoulGemIcon(a_entryObject); break; case Item.SOULGEM_GRAND: a_entryObject.iconColor = 0x7569FF; processGrandSoulGemIcon(a_entryObject); break; case Item.SOULGEM_AZURA: a_entryObject.iconColor = 0x7569FF; a_entryObject.iconLabel = "soulgem_azura"; break; } } private function processGrandSoulGemIcon(a_entryObject: Object): Void { switch(a_entryObject.status) { case Item.SOULGEMSTATUS_EMPTY: a_entryObject.iconLabel = "soulgem_grandempty"; break; case Item.SOULGEMSTATUS_FULL: a_entryObject.iconLabel = "soulgem_grandfull"; break; case Item.SOULGEMSTATUS_PARTIAL: a_entryObject.iconLabel = "soulgem_grandpartial"; break; } } private function processSoulGemStatusIcon(a_entryObject: Object): Void { switch(a_entryObject.status) { case Item.SOULGEMSTATUS_EMPTY: a_entryObject.iconLabel = "soulgem_empty"; break; case Item.SOULGEMSTATUS_FULL: a_entryObject.iconLabel = "soulgem_full"; break; case Item.SOULGEMSTATUS_PARTIAL: a_entryObject.iconLabel = "soulgem_partial"; break; } } private function processMiscIcon(a_entryObject: Object): Void { a_entryObject.iconLabel = "default_misc"; switch(a_entryObject.subType) { case Item.MISC_ARTIFACT: a_entryObject.iconLabel = "misc_artifact"; break; case Item.MISC_GEM: a_entryObject.iconLabel = "misc_gem"; a_entryObject.iconColor = 0xFFB0D1; break; case Item.MISC_HIDE: a_entryObject.iconLabel = "misc_hide"; a_entryObject.iconColor = 0xDBB36E; break; case Item.MISC_REMAINS: a_entryObject.iconLabel = "misc_remains"; break; case Item.MISC_INGOT: a_entryObject.iconLabel = "misc_ingot"; //"misc_ore" a_entryObject.iconColor = 0x828282; break; case Item.MISC_CLUTTER: a_entryObject.iconLabel = "misc_clutter"; break; case Item.MISC_FIREWOOD: a_entryObject.iconLabel = "misc_wood"; a_entryObject.iconColor = 0xA89E8C; break; case Item.MISC_DRAGONCLAW: a_entryObject.iconLabel = "misc_dragonclaw"; break; case Item.MISC_LOCKPICK: a_entryObject.iconLabel = "misc_lockpick"; break; case Item.MISC_GOLD: a_entryObject.iconLabel = "misc_gold"; a_entryObject.iconColor = 0xCCCC33; break; case Item.MISC_LEATHER: a_entryObject.iconLabel = "misc_leather"; a_entryObject.iconColor = 0xBA8D23; break; case Item.MISC_LEATHERSTRIPS: a_entryObject.iconLabel = "misc_strips"; a_entryObject.iconColor = 0xBA8D23; break; case Item.MISC_CHILDRENSCLOTHES: a_entryObject.iconColor = 0xEDDA87; a_entryObject.iconLabel = "clothing_body"; break; // Maybe use later? // ... or not. /* case Item.MISC_TOOL: break; case Item.MISC_TOY: break; case Item.MISC_HOUSEPART: break; */ } } } // skyui.util.Debug.dump(a_entryObject["text"], a_entryObject); ================================================ FILE: src/CraftingMenu/CraftingListEntry.as ================================================ import flash.geom.ColorTransform; import flash.geom.Transform; import skyui.components.list.TabularList; import skyui.components.list.TabularListEntry; import skyui.components.list.ListState; import skyui.util.ConfigManager; class CraftingListEntry extends TabularListEntry { /* CONSTANTS */ private static var STATES = ["None", "Equipped", "LeftEquip", "RightEquip", "LeftAndRightEquip"]; /* PRIVATE VARIABLES */ private var _iconLabel: String; private var _iconColor: Number; /* STAGE ELMENTS */ public var itemIcon: MovieClip; public var equipIcon: MovieClip; public var poisonIcon: MovieClip; public var stolenIcon: MovieClip; /* INITIALIZATION */ // @override TabularListEntry public function initialize(a_index: Number, a_state: ListState): Void { super.initialize(); var iconLoader = new MovieClipLoader(); iconLoader.addListener(this); iconLoader.loadClip(a_state.iconSource, itemIcon); itemIcon._visible = false; equipIcon._visible = false; for (var i = 0; this["textField" + i] != undefined; i++) this["textField" + i]._visible = false; } /* PUBLIC FUNCTIONS */ // @override TabularListEntry public function setSpecificEntryLayout(a_entryObject: Object, a_state: ListState): Void { var iconY = TabularList(a_state.list).layout.entryHeight * 0.25; var iconSize = TabularList(a_state.list).layout.entryHeight * 0.5; poisonIcon._height = poisonIcon._width = iconSize; stolenIcon._height = stolenIcon._width = iconSize; poisonIcon._y = iconY; stolenIcon._y = iconY; } // @override TabularListEntry public function formatEquipIcon(a_entryField: Object, a_entryObject: Object, a_state: ListState): Void { if (a_entryObject != undefined && a_entryObject.equipState != undefined) { a_entryField.gotoAndStop(STATES[a_entryObject.equipState]); } else { a_entryField.gotoAndStop("None"); } } // @override TabularListEntry public function formatItemIcon(a_entryField: Object, a_entryObject: Object, a_state: ListState) { _iconLabel = a_entryObject["iconLabel"] != undefined ? a_entryObject["iconLabel"] : "default_misc"; _iconColor = a_entryObject["iconColor"]; // Could return here if _iconLoaded is false a_entryField.gotoAndStop(_iconLabel); changeIconColor(MovieClip(a_entryField), _iconColor); } // @override TabularListEntry public function formatName(a_entryField: Object, a_entryObject: Object, a_state: ListState): Void { if (a_entryObject.text == undefined) { a_entryField.SetText(" "); return; } // Text var text = a_entryObject.text; if (a_entryObject.soulLVL != undefined) { text = text + " (" + a_entryObject.soulLVL + ")"; } if (a_entryObject.count > 1) { text = text + " (" + a_entryObject.count.toString() + ")"; } if (text.length > a_state.maxTextLength) { text = text.substr(0, a_state.maxTextLength - 3) + "..."; } a_entryField.autoSize = "left"; a_entryField.SetText(text); formatColor(a_entryField, a_entryObject, a_state); var iconPos = a_entryField._x + a_entryField._width + 5; // All icons have the same size var iconSpace = stolenIcon._width * 1.25; // Poisoned Icon if (a_entryObject.isPoisoned == true) { poisonIcon._x = iconPos; iconPos = iconPos + iconSpace; poisonIcon.gotoAndStop("show"); } else { poisonIcon.gotoAndStop("hide"); } // Stolen Icon if ((a_entryObject.isStolen == true || a_entryObject.isStealing == true) && a_state.showStolenIcon == true) { stolenIcon._x = iconPos; iconPos = iconPos + iconSpace; stolenIcon.gotoAndStop("show"); } else { stolenIcon.gotoAndStop("hide"); } } // @override TabularEntry public function formatText(a_entryField: Object, a_entryObject: Object, a_state: ListState): Void { formatColor(a_entryField, a_entryObject, a_state); } /* PRIVATE FUNCTIONS */ // @implements MovieClipLoader private function onLoadInit(a_icon: MovieClip): Void { a_icon.gotoAndStop(_iconLabel); changeIconColor(a_icon, _iconColor); } private function formatColor(a_entryField: Object, a_entryObject: Object, a_state: ListState): Void { // Stolen if (a_entryObject.infoIsStolen == true || a_entryObject.isStealing == true) a_entryField.textColor = a_entryObject.enabled == false ? a_state.stolenDisabledColor : a_state.stolenEnabledColor; // Default else a_entryField.textColor = a_entryObject.enabled == false ? a_state.defaultDisabledColor : a_state.defaultEnabledColor; } private function changeIconColor(a_icon: MovieClip, a_rgb: Number): Void { var element: Object; for (var e: String in a_icon) { element = a_icon[e]; if (element instanceof MovieClip) { //Note: Could check if all values of RGBA mult and .rgb are all the same then skip var ct: ColorTransform = new ColorTransform(); var tf: Transform = new Transform(MovieClip(element)); // Could return here if (a_rgb == tf.colorTransform.rgb && a_rgb != undefined) ct.rgb = (a_rgb == undefined)? 0xFFFFFF: a_rgb; tf.colorTransform = ct; // Shouldn't be necessary to recurse since we don't expect multiple clip depths for an icon //changeIconColor(element, a_rgb); } } } } ================================================ FILE: src/CraftingMenu/CraftingLists.as ================================================ import gfx.io.GameDelegate; import gfx.ui.NavigationCode; import gfx.ui.InputDetails; import gfx.events.EventDispatcher; import gfx.managers.FocusHandler; import gfx.controls.Button; import Shared.GlobalFunc; import mx.utils.Delegate; import skyui.components.SearchWidget; import skyui.components.TabBar; import skyui.components.list.FilteredEnumeration; import skyui.components.list.BasicEnumeration; import skyui.components.list.TabularList; import skyui.components.list.SortedListHeader; import skyui.filter.ItemTypeFilter; import skyui.filter.NameFilter; import skyui.filter.SortFilter; import skyui.util.ConfigManager; import skyui.util.GlobalFunctions; import skyui.util.Translator; import skyui.util.DialogManager; import skyui.util.Debug; import skyui.defines.Input; import skyui.defines.Inventory; class CraftingLists extends MovieClip { #include "../version.as" /* CONSTANTS */ static var HIDE_PANEL = 0; static var SHOW_PANEL = 1; static var TRANSITIONING_TO_HIDE_PANEL = 2; static var TRANSITIONING_TO_SHOW_PANEL = 3; static var SHORT_LIST_OFFSET = 210; /* STAGE ELEMENTS */ public var panelContainer: MovieClip; public var zoomButtonHolder: MovieClip; /* PRIVATE VARIABLES */ private var _typeFilter: ItemTypeFilter; private var _nameFilter: NameFilter; private var _sortFilter: SortFilter; private var _platform: Number; private var _currCategoryIndex: Number; private var _savedSelectionIndex: Number = -1; private var _searchKey: Number = -1; private var _sortOrderKey: Number = -1; private var _sortOrderKeyHeld: Boolean = false; private var _columnSelectDialog: MovieClip; private var _columnSelectInterval: Number; private var _subtypeName: String; private var _bFocusItemList: Boolean = true; private var _categoryChanged: Boolean; private var _categorySelections: Object; /* PROPERTIES */ public var itemList: TabularList; // @API public var CategoriesList: IconTabList; public var searchWidget: SearchWidget; public var categoryLabel: MovieClip; public var columnSelectButton: Button; private var _currentState: Number; public function get currentState() { return _currentState; } public function set currentState(a_newState: Number) { if (a_newState == SHOW_PANEL) FocusHandler.instance.setFocus(itemList,0); _currentState = a_newState; } /* INITIALIZATION */ public function CraftingLists() { super(); GlobalFunctions.addArrayFunctions(); EventDispatcher.initialize(this); gotoAndStop("NoPanels"); GameDelegate.addCallBack("SetCategoriesList", this, "SetCategoriesList"); GameDelegate.addCallBack("InvalidateListData", this, "InvalidateListData"); _typeFilter = new ItemTypeFilter(); _nameFilter = new NameFilter(); _sortFilter = new SortFilter(); categoryLabel = panelContainer.categoryLabel; CategoriesList = panelContainer.categoriesList; // Note: Re-assigned later if alchemy itemList = panelContainer.itemList; searchWidget = panelContainer.searchWidget; columnSelectButton = panelContainer.columnSelectButton; ConfigManager.registerLoadCallback(this, "onConfigLoad"); ConfigManager.registerUpdateCallback(this, "onConfigUpdate"); // Hide by default, maybe show later panelContainer.effectsList._visible = false; } /* PUBLIC FUNCTIONS */ // @mixin by gfx.events.EventDispatcher public var dispatchEvent: Function; public var dispatchQueue: Function; public var hasEventListener: Function; public var addEventListener: Function; public var removeEventListener: Function; public var removeAllEventListeners: Function; public var cleanUpEvents: Function; // @mixin by Shared.GlobalFunc public var Lock: Function; public function InitExtensions(a_subtypeName: String): Void { _subtypeName = a_subtypeName; // Alchemy uses a different layout if (_subtypeName == "Alchemy") { panelContainer.gotoAndStop("no_categories"); // Hide top icon category bar, use effects list instead CategoriesList._visible = false; CategoriesList = panelContainer.effectsList; CategoriesList._visible = true; itemList.gotoAndStop("short"); itemList.leftBorder = SHORT_LIST_OFFSET; itemList.listHeight = 560; // Support for custom categorization } else if (_subtypeName == "ConstructibleObject") { itemList.addDataProcessor(new CustomConstructDataSetter()); // Smithing doesn't need top icon categories } else if (_subtypeName == "Smithing") { panelContainer.gotoAndStop("no_categories"); CategoriesList._visible = false; itemList.listHeight = 560; } var listEnumeration = new FilteredEnumeration(itemList.entryList); listEnumeration.addFilter(_typeFilter); listEnumeration.addFilter(_nameFilter); listEnumeration.addFilter(_sortFilter); itemList.listEnumeration = listEnumeration; _typeFilter.addEventListener("filterChange", this, "onFilterChange"); _nameFilter.addEventListener("filterChange", this, "onFilterChange"); _sortFilter.addEventListener("filterChange", this, "onFilterChange"); CategoriesList.listEnumeration = new BasicEnumeration(CategoriesList.entryList); itemList.listState.maxTextLength = 80; _typeFilter.addEventListener("filterChange", this, "onFilterChange"); _nameFilter.addEventListener("filterChange", this, "onFilterChange"); _sortFilter.addEventListener("filterChange", this, "onFilterChange"); CategoriesList.addEventListener("itemPress", this, "onCategoriesItemPress"); CategoriesList.addEventListener("itemPressAux", this, "onCategoriesItemPress"); CategoriesList.addEventListener("selectionChange", this, "onCategoriesListSelectionChange"); itemList.disableInput = false; itemList.addEventListener("selectionChange", this, "onItemsListSelectionChange"); itemList.addEventListener("sortChange", this, "onSortChange"); itemList.addEventListener("itemPress", this, "onItemPress"); itemList.addEventListener("listUpdated", this, "onItemsListUpdate"); searchWidget.addEventListener("inputStart", this, "onSearchInputStart"); searchWidget.addEventListener("inputEnd", this, "onSearchInputEnd"); searchWidget.addEventListener("inputChange", this, "onSearchInputChange"); columnSelectButton.addEventListener("press", this, "onColumnSelectButtonPress"); itemList.onInvalidate = Delegate.create(this, onItemListInvalidate); CategoriesList.onUnsuspend = function() { // this == CategoriesList this.onItemPress(0, 0); // Select first category delete this.onUnsuspend; }; // Delay updates until config is ready CategoriesList.suspended = true; itemList.suspended = true; } public function showPanel(a_bPlayBladeSound: Boolean): Void { // Release itemlist for updating CategoriesList.suspended = false; itemList.suspended = false; _currentState = TRANSITIONING_TO_SHOW_PANEL; gotoAndPlay("PanelShow"); dispatchEvent({type:"categoryChange", index: CategoriesList.selectedIndex}); if (a_bPlayBladeSound != false) GameDelegate.call("PlaySound",["UIMenuBladeOpenSD"]); } public function hidePanel(): Void { _currentState = TRANSITIONING_TO_HIDE_PANEL; gotoAndPlay("PanelHide"); GameDelegate.call("PlaySound",["UIMenuBladeCloseSD"]); } public function setPlatform(a_platform: Number, a_bPS3Switch: Boolean): Void { _platform = a_platform; CategoriesList.setPlatform(a_platform,a_bPS3Switch); itemList.setPlatform(a_platform,a_bPS3Switch); } public function setPartitionedFilterMode(a_bPartitioned: Boolean): Void { _typeFilter.setPartitionedFilterMode(a_bPartitioned); } // @GFx public function handleInput(details: InputDetails, pathToFocus: Array): Boolean { if (_currentState != SHOW_PANEL) return false; if (_platform != 0) { if (details.skseKeycode == _sortOrderKey) { if (details.value == "keyDown") { _sortOrderKeyHeld = true; if (_columnSelectDialog) DialogManager.close(); else _columnSelectInterval = setInterval(this, "onColumnSelectButtonPress", 1000, {type: "timeout"}); return true; } else if (details.value == "keyUp") { _sortOrderKeyHeld = false; if (_columnSelectInterval == undefined) // keyPress handled: Key was released after the interval expired, don't process any further return true; // keyPress not handled: Clear intervals and change value to keyDown to be processed later clearInterval(_columnSelectInterval); delete(_columnSelectInterval); // Continue processing the event as a normal keyDown event details.value = "keyDown"; } else if (_sortOrderKeyHeld && details.value == "keyHold") { // Fix for opening journal menu while key is depressed // For some reason this is the only time we receive a keyHold event _sortOrderKeyHeld = false; if (_columnSelectDialog) DialogManager.close(); return true; } } if (_sortOrderKeyHeld) // Disable extra input while interval is active return true; } if (GlobalFunc.IsKeyPressed(details)) { // Search hotkey (default space) if (details.skseKeycode == _searchKey) { searchWidget.startInput(); return true; } } if (_subtypeName == "Alchemy") { if (handleAlchemyNavigation(details, pathToFocus)) return true; } else { if (CategoriesList.handleInput(details, pathToFocus)) return true; } var nextClip = pathToFocus.shift(); return nextClip.handleInput(details, pathToFocus); } private function handleAlchemyNavigation(details: InputDetails, pathToFocus: Array): Boolean { if (GlobalFunc.IsKeyPressed(details)) { if (details.navEquivalent == NavigationCode.LEFT) { if (!_bFocusItemList) return true; _savedSelectionIndex = itemList.selectedIndex; itemList.selectedIndex = -1; // Moving from Item list to Category List _bFocusItemList = false; return true; } else if (details.navEquivalent == NavigationCode.RIGHT) { if (_bFocusItemList) return true; if (_savedSelectionIndex == -1) { itemList.selectDefaultIndex(true) } else { itemList.selectedIndex = _savedSelectionIndex; } // Moving from Category list to Item List _bFocusItemList = true; return true; } // Ok thats a bit weird but whatever...: // Itemlist always has focus, but if this flag is false, categories list gets to run first. // Since both use the same nav scheme, category list wins. if (!_bFocusItemList) { if (CategoriesList.handleInput(details, pathToFocus)) { // Clear saved index _savedSelectionIndex = -1; return true; } } } return false; } public function getContentBounds():Array { var lb = panelContainer.ListBackground; return [lb._x, lb._y, lb._width, lb._height]; } public function showItemsList(): Void { // Save the previous selection in the category var prevCategory = CategoriesList.lastSelectedIndex; _categorySelections[prevCategory] = { selectedIndex: itemList.selectedIndex, scrollPosition: itemList.scrollPosition }; _currCategoryIndex = CategoriesList.selectedIndex; categoryLabel.textField.SetText(CategoriesList.selectedEntry.text.toUpperCase()); // Start with no selection itemList.selectedIndex = -1; itemList.scrollPosition = 0; if (CategoriesList.selectedEntry != undefined) { var catFlag = CategoriesList.selectedEntry.flag; // Set filter type _typeFilter.changeFilterFlag(catFlag); // Not set yet before the config is loaded itemList.layout.changeFilterFlag(catFlag); } itemList.requestUpdate(); dispatchEvent({type: "showItemsList", index: itemList.selectedIndex}); // dispatchEvent({type:"itemHighlightChange", index:itemList.selectedIndex}); itemList.disableInput = false; } // Called to initially set the category list. // @API public function SetCategoriesList(): Void { var textOffset = 0; var flagOffset = 1; var bDontHideOffset = 2; var len = 3; CategoriesList.clearList(); _categorySelections = new Array(); for (var i=0, index = 0; i < arguments.length; i = i + len, index++) { var entry = {text:arguments[i + textOffset], flag:arguments[i + flagOffset], bDontHide:arguments[i + bDontHideOffset], savedItemIndex:0, filterFlag:arguments[i + bDontHideOffset] == true ? (1) : (0)}; if (entry.flag == 0) { entry.divider = true; } entry.enabled = false; // Debug.dump("category" + i, entry); CategoriesList.entryList.push(entry); } // We have enough information to init the art now. // But the list has not been invalidated, so no clips have been loaded yet. preprocessCategoriesList(); CategoriesList.selectedIndex = 0; CategoriesList.InvalidateData(); } // Called whenever the underlying entryList data is updated (using an item, equipping etc.) // @API public function InvalidateListData(): Void { itemList.InvalidateData(); } /* PRIVATE FUNCTIONS */ private function onHideCategoriesList(event: Object): Void { itemList.listHeight = 579; } private function onConfigLoad(event: Object): Void { var config = event.config; _searchKey = config["Input"].controls.pc.search; if (_platform != 0) { _sortOrderKey = config["Input"].controls.gamepad.sortOrder; } } private function onItemListInvalidate(): Void { // Set enabled == false for empty categories if (_subtypeName != "Alchemy") { for (var i=0; i 0 ? aLineTitle + ": " : ""; var oldTextFormat: TextFormat = itemTextField.getNewTextFormat(); var newTextFormat: TextFormat = itemTextField.getNewTextFormat(); for (var i: Number = 0; i < aIngredients.length; i++) { var ingredient: Object = aIngredients[i]; newTextFormat.color = ingredient.PlayerCount < ingredient.RequiredCount ? 0x777777 : 0xFFFFFF; itemTextField.setNewTextFormat(newTextFormat); var requiredCount = ""; if (ingredient.RequiredCount > 1) { requiredCount = ingredient.RequiredCount + " "; } var itemCount: String = ""; if (abShowPlayerCount && ingredient.PlayerCount >= 1) { itemCount = " (" + ingredient.PlayerCount + ")"; } var ingredientString: String = requiredCount + ingredient.Name + itemCount + (i >= aIngredients.length - 1 ? "" : ", "); itemTextField.replaceText(itemTextField.length, itemTextField.length + 1, ingredientString); } itemTextField.setNewTextFormat(oldTextFormat); } // @API public function EditItemName(aInitialText: String, aMaxChars: Number): Void { ItemInfo.StartEditName(aInitialText, aMaxChars); } // @API public function ShowSlider(aiMaxValue: Number, aiMinValue: Number, aiCurrentValue: Number, aiSnapInterval: Number): Void { ItemInfo.ShowEnchantingSlider(aiMaxValue, aiMinValue, aiCurrentValue); ItemInfo.quantitySlider.snapping = true; ItemInfo.quantitySlider.snapInterval = aiSnapInterval; ItemInfo.quantitySlider.addEventListener("change", this, "onSliderChanged"); onSliderChanged(); } // @API public function SetSliderValue(aValue: Number): Void { ItemInfo.quantitySlider.value = aValue; } // @GFx public function handleInput(details: InputDetails, pathToFocus: Array): Boolean { // Don't process input too quickly if(_handleInputRateLimiter) { return; } skyui.util.Input.rateLimit(this, "_handleInputRateLimiter", 10); pathToFocus[0].handleInput(details, pathToFocus.slice(1)); // Always answer `true` or even `undefined`. // Answering false may cause the Scaleform player to locate another // component to focus on. return true; } public function classname(): String{ return "Class CraftingMenu"; } public function handleVRInput(event): Boolean { //Debug.dump("CraftingMenu::handleVRInput", event); var action = VRInput.instance.triggeredAction(vrActionConditions, event); if(action == "search") { InventoryLists.searchWidget.startInput(); return true; } return false; } /* PRIVATE FUNCTIONS */ private function positionFixedElements(): Void { GlobalFunc.SetLockFunction(); MovieClip(CategoryList).Lock("L"); CategoryList._x = CategoryList._x - CraftingMenu.LIST_OFFSET; MenuNameHolder.Lock("L"); MenuNameHolder._x = MenuNameHolder._x - CraftingMenu.LIST_OFFSET; MenuDescriptionHolder.Lock("TR"); var leftOffset: Number = Stage.visibleRect.x + Stage.safeRect.x; var rightOffset: Number = Stage.visibleRect.x + Stage.visibleRect.width - Stage.safeRect.x; var a = CategoryList.getContentBounds(); // 25 is hardcoded cause thats the final offset after the animation of the panel container is done var panelEdge = CategoryList._x + a[0] + a[2] + 25; MenuDescriptionHolder._x = 10 + panelEdge + ((rightOffset - panelEdge) / 2) + (MenuDescriptionHolder._width / 2); BottomBarInfo.positionElements(leftOffset, rightOffset); MovieClip(ExitMenuRect).Lock("TL"); ExitMenuRect._x = ExitMenuRect._x - (Stage.safeRect.x + 10); ExitMenuRect._y = ExitMenuRect._y - Stage.safeRect.y; } private function positionFloatingElements(): Void { var leftEdge = Stage.visibleRect.x + Stage.safeRect.x; var rightEdge = Stage.visibleRect.x + Stage.visibleRect.width - Stage.safeRect.x; var a = CategoryList.getContentBounds(); // 25 is hardcoded cause thats the final offset after the animation of the panel container is done var panelEdge = CategoryList._x + a[0] + a[2] + 25; var itemCardContainer = ItemInfo._parent; var itemcardPosition = _config.ItemInfo.itemcard; var itemCardWidth: Number; // For some reason if (ItemInfo.background != undefined) itemCardWidth = ItemInfo.background._width; else itemCardWidth = ItemInfo._width; // For some reason the container is larger than the card // Card x is at 0 so we can use the inner width without adjustment var scaleMult = (rightEdge - panelEdge) / itemCardContainer._width; // Scale down if necessary if (scaleMult < 1.0) { itemCardContainer._width *= scaleMult; itemCardContainer._height *= scaleMult; itemCardWidth *= scaleMult; } if (itemcardPosition.align == "left") { itemCardContainer._x = panelEdge + itemcardPosition.xOffset; } else if (itemcardPosition.align == "right") { itemCardContainer._x = rightEdge - itemCardWidth + itemcardPosition.xOffset; } else { itemCardContainer._x = panelEdge + itemcardPosition.xOffset + (Stage.visibleRect.x + Stage.visibleRect.width - panelEdge - itemCardWidth) / 2; } itemCardContainer._y += itemcardPosition.yOffset; MovieClip(MouseRotationRect).Lock("T"); MouseRotationRect._x = ItemInfo._parent._x; MouseRotationRect._width = ItemInfo._parent._width; MouseRotationRect._height = 0.55 * Stage.visibleRect.height; // _bItemCardPositioned = true; // Delayed fade in if positioned wasn't set /* if (_bItemCardFadedIn) { GameDelegate.call("UpdateItem3D",[true]); itemCard.FadeInCard(); }*/ } private function onConfigLoad(event: Object): Void { setConfig(event.config); CategoryList.showPanel(); } private function setConfig(a_config: Object): Void { _config = a_config; ItemList.addDataProcessor(new CraftingDataSetter()); ItemList.addDataProcessor(new CraftingIconSetter(a_config["Appearance"])); positionFloatingElements(); var itemListState = CategoryList.itemList.listState; var appearance = a_config["Appearance"]; itemListState.iconSource = appearance.icons.item.source; itemListState.showStolenIcon = appearance.icons.item.showStolen; itemListState.defaultEnabledColor = appearance.colors.text.enabled; itemListState.negativeEnabledColor = appearance.colors.negative.enabled; itemListState.stolenEnabledColor = appearance.colors.stolen.enabled; itemListState.defaultDisabledColor = appearance.colors.text.disabled; itemListState.negativeDisabledColor = appearance.colors.negative.disabled; itemListState.stolenDisabledColor = appearance.colors.stolen.disabled; var layout: ListLayout; if (_subtypeName == "EnchantConstruct") { layout = ListLayoutManager.createLayout(a_config["ListLayout"], "EnchantListLayout"); } else if (_subtypeName == "Smithing") { layout = ListLayoutManager.createLayout(a_config["ListLayout"], "SmithingListLayout"); } else if (_subtypeName == "ConstructibleObject") { layout = ListLayoutManager.createLayout(a_config["ListLayout"], "ConstructListLayout"); } else /*if (_subtypeName == "Alchemy")*/ { layout = ListLayoutManager.createLayout(a_config["ListLayout"], "AlchemyListLayout"); layout.entryWidth -= CraftingLists.SHORT_LIST_OFFSET; } ItemList.layout = layout; var previousColumnKey = a_config["Input"].controls.gamepad.prevColumn; var nextColumnKey = a_config["Input"].controls.gamepad.nextColumn; var sortOrderKey = a_config["Input"].controls.gamepad.sortOrder; _sortColumnControls = [{keyCode: previousColumnKey}, {keyCode: nextColumnKey}]; _sortOrderControls = {keyCode: sortOrderKey}; _searchKey = a_config["Input"].controls.pc.search; _searchControls = {keyCode: _searchKey}; } private function onItemListPressed(event: Object): Void { GameDelegate.call("CraftSelectedItem", [ItemList.selectedIndex]); GameDelegate.call("SetSelectedItem", [ItemList.selectedIndex]); } private function onItemSelect(event: Object): Void { GameDelegate.call("ChooseItem", [event.index]); GameDelegate.call("ShowItem3D", [event.index != -1]); UpdateButtonText(); } private function onItemHighlightChange(event: Object): Void { SetSelectedItem(event.index); FadeInfoCard(event.index == -1); UpdateButtonText(); GameDelegate.call("ShowItem3D", [event.index != -1]); } public function setupVRInput() { _VRInput = VRInput.instance; VRInput.instance.setup(); } private function onShowItemsList(event: Object): Void { setupVRInput(); if(!vrActionConditions) { vrActionConditions = VRInput.instance.getActionConditions("CraftingMenu"); if(VRInput.instance.logDetails) Debug.dump("vrActionConditions", vrActionConditions); } if (_platform == Shared.Platforms.CONTROLLER_PC || _platform == Shared.Platforms.CONTROLLER_VIVE || _platform == Shared.Platforms.CONTROLLER_OCULUS || _platform == Shared.Platforms.CONTROLLER_VIVE_KNUCKLES) { GameDelegate.call("SetSelectedCategory", [CategoryList.CategoriesList.selectedIndex]); } onItemHighlightChange(event); } private function onHideItemsList(event: Object): Void { SetSelectedItem(event.index); FadeInfoCard(true); UpdateButtonText(); GameDelegate.call("ShowItem3D", [false]); } private function onCategoryListChange(event: Object): Void { if (_platform != Shared.Platforms.CONTROLLER_PC || _platform != Shared.Platforms.CONTROLLER_VIVE || _platform != Shared.Platforms.CONTROLLER_OCULUS || _platform != Shared.Platforms.CONTROLLER_VIVE_KNUCKLES) { GameDelegate.call("SetSelectedCategory", [event.index]); } } private function onSliderChanged(event: Object): Void { GameDelegate.call("CalculateCharge", [ItemInfo.quantitySlider.value], this, "SetChargeValues"); } private function onSubMenuAction(event: Object): Void { if (event.opening == true) { ItemList.disableSelection = true; ItemList.disableInput = true; CategoryList.CategoriesList.disableSelection = true; CategoryList.CategoriesList.disableInput = true; } else if (event.opening == false) { ItemList.disableSelection = false; ItemList.disableInput = false; CategoryList.CategoriesList.disableSelection = false; CategoryList.CategoriesList.disableInput = false; } if (event.menu == "quantity") { if (event.opening) { return; } GameDelegate.call("SliderClose", [!event.canceled, event.value]); } } private function onCraftButtonPress(): Void { if (bCanCraft) { GameDelegate.call("CraftButtonPress", []); } } private function onExitButtonPress(): Void { closeMenu(); } public function closeMenu() { VRInput.instance.teardown(); GameDelegate.call("CloseMenu",[]); } private function onAuxButtonPress(): Void { GameDelegate.call("AuxButtonPress", []); } private function onEndEditItemName(event: Object): Void { ItemInfo.EndEditName(); GameDelegate.call("EndItemRename", [event.useNewName, event.newName]); } private function getItemShown(): Boolean { return ItemList.selectedIndex >= 0; } private function onMouseUp(): Void { if (ItemInfo.bEditNameMode && !ItemInfo.hitTest(_root._xmouse, _root._ymouse)) { onEndEditItemName({useNewName: false, newName: ""}); } } private function onMouseRotationStart(): Void { GameDelegate.call("StartMouseRotation", []); CategoryList.CategoriesList.disableSelection = true; ItemList.disableSelection = true; } private function onMouseRotationStop(): Void { GameDelegate.call("StopMouseRotation", []); CategoryList.CategoriesList.disableSelection = false; ItemList.disableSelection = false; } private function onItemsListInputCatcherClick(): Void { // if (CategoryList.currentState == InventoryLists.TWO_PANELS && !ItemList.disableSelection && !ItemList.disableInput) { // onItemSelect({index: ItemList.selectedIndex}); // } } private function onMouseRotationFastClick(aiMouseButton: Number): Void { if (aiMouseButton == 0) { onItemsListInputCatcherClick(); } } } ================================================ FILE: src/CraftingMenu/CustomAlchemyDataSetter.as ================================================ import skyui.util.Translator; import skyui.defines.Actor; import skyui.defines.Armor; import skyui.defines.Form; import skyui.defines.Item; import skyui.defines.Material; import skyui.defines.Weapon; import skyui.defines.Inventory; import skyui.components.list.BasicList; import skyui.components.list.IListProcessor; class CustomAlchemyDataSetter implements IListProcessor { /* INITIALIZATION */ public function CustomAlchemyDataSetter() { super(); partitionData = []; } /* PROPERTIES */ public var partitionData: Array; /* PUBLIC FUNCTIONS */ // @override IListProcessor public function processList(a_list: BasicList): Void { var entryList = a_list.entryList; // First save old filterflag and clear it for (var i = 0; i < entryList.length; i++) { var e = entryList[i]; // customFilterFlag not set yet or filterFlag changed by the game? if (e.customFilterFlag == e.filterFlag) continue; processEntry(e) } } /* PRIVATE FUNCTIONS */ private function processEntry(a_entryObject: Object): Void { // Reset data a_entryObject.goodEffects = null; a_entryObject.badEffects = null; a_entryObject.otherEffects = null; // All entries should be in there a_entryObject.customFilterFlag = Inventory.FILTERFLAG_CUST_ALCH_INGREDIENTS; for (var i = 0; i < partitionData.length; i++) { var partition = partitionData[i]; var partitionIndex = partition.index; if (! isEntryInPartition(a_entryObject.filterFlag, partitionIndex)) continue; a_entryObject.customFilterFlag |= partition.flag; switch (partition.flag) { case Inventory.FILTERFLAG_CUST_ALCH_GOOD: if (a_entryObject.goodEffects == null) a_entryObject.goodEffects = partition.text; else { a_entryObject.goodEffects += " | " + partition.text; } break; case Inventory.FILTERFLAG_CUST_ALCH_BAD: if (a_entryObject.badEffects == null) a_entryObject.badEffects = partition.text; else a_entryObject.badEffects += ", " + partition.text; break; case Inventory.FILTERFLAG_CUST_ALCH_OTHER: if (a_entryObject.otherEffects == null) a_entryObject.otherEffects = partition.text; else a_entryObject.otherEffects += ", " + partition.text; break; } } // Apply custom flag as new flag a_entryObject.filterFlag = a_entryObject.customFilterFlag; } private static function isEntryInPartition(a_filterFlag: Number, a_index: Boolean): Boolean { // Each entry can be in at most 4 partitions. // Parition indices are encoded in bytes of filterFlag. var byte0: Number = (a_filterFlag & 0x000000FF); var byte1: Number = (a_filterFlag & 0x0000FF00) >>> 8; var byte2: Number = (a_filterFlag & 0x00FF0000) >>> 16; var byte3: Number = (a_filterFlag & 0xFF000000) >>> 24; return byte0 == a_index || byte1 == a_index || byte2 == a_index || byte3 == a_index; } } ================================================ FILE: src/CraftingMenu/CustomConstructDataSetter.as ================================================ import skyui.util.Translator; import skyui.defines.Actor; import skyui.defines.Armor; import skyui.defines.Form; import skyui.defines.Item; import skyui.defines.Material; import skyui.defines.Weapon; import skyui.defines.Inventory; import skyui.components.list.BasicList; import skyui.components.list.IListProcessor; class CustomConstructDataSetter implements IListProcessor { /* INITIALIZATION */ public function CustomConstructDataSetter() { super(); } // @override IListProcessor public function processList(a_list: BasicList): Void { var entryList = a_list.entryList; for (var i = 0; i < entryList.length; i++) { var e = entryList[i]; if (e.oldFilterFlag != undefined || e.filterFlag == 0) continue; e.oldFilterFlag = e.filterFlag; processEntry(e); } } /* PUBLIC FUNCTIONS */ public function processEntry(a_entryObject: Object): Void { var bDone = false; // We can map these categories 1:1 switch (a_entryObject.oldFilterFlag) { case Inventory.FILTERFLAG_CRAFT_JEWELRY: a_entryObject.filterFlag = Inventory.FILTERFLAG_CUST_CRAFT_JEWELRY; bDone = true; break; case Inventory.FILTERFLAG_CRAFT_FOOD: a_entryObject.filterFlag = Inventory.FILTERFLAG_CUST_CRAFT_FOOD; bDone = true; break; } if (bDone) return; switch (a_entryObject.formType) { case Form.TYPE_ARMOR: a_entryObject.filterFlag = Inventory.FILTERFLAG_CUST_CRAFT_ARMOR; break; case Form.TYPE_INGREDIENT: a_entryObject.filterFlag = Inventory.FILTERFLAG_CUST_CRAFT_FOOD; break; case Form.TYPE_WEAPON: a_entryObject.filterFlag = Inventory.FILTERFLAG_CUST_CRAFT_WEAPONS; break; case Form.TYPE_AMMO: a_entryObject.filterFlag = Inventory.FILTERFLAG_CUST_CRAFT_AMMO; break; case Form.TYPE_POTION: a_entryObject.filterFlag = Inventory.FILTERFLAG_CUST_CRAFT_FOOD; break; default: a_entryObject.filterFlag = Inventory.FILTERFLAG_CUST_CRAFT_MISC; break; } } } ================================================ FILE: src/CraftingMenu/EnchantingBar.as ================================================ import gfx.events.EventDispatcher; import gfx.ui.NavigationCode; import gfx.ui.InputDetails; import gfx.controls.Button; import gfx.controls.ButtonGroup; import Shared.GlobalFunc; import skyui.components.list.EntryClipManager; import skyui.components.list.BasicEnumeration; import skyui.components.list.AlphaEntryFormatter; import skyui.components.list.BasicList; class EnchantingBar extends MovieClip { /* CONSTANTS */ /* STAGE ELEMENTS */ public var btnDisenchant: Button; public var btnItem: Button; public var btnEnchantment: Button; public var btnSoul: Button; public var vertSeparator: MovieClip; public var selectorCenter: MovieClip; public var selectorLeft: MovieClip; public var selectorRight: MovieClip; public var background: MovieClip; /* PRIVATE VARIABLES */ private var _totalWidth: Number; private var _selectorPos: Number; private var _targetSelectorPos: Number; private var _bFastSwitch: Boolean; private var _buttonGroup: ButtonGroup; /* PROPERTIES */ public var selectedIndex: Number = 0; public var disableInput: Boolean = false; /* INITIALIZATION */ public function EnchantingBar() { super(); _selectorPos = 0; _targetSelectorPos = 0; _bFastSwitch = false; _buttonGroup = new ButtonGroup("MainButtonGroup"); } public function onLoad() { btnDisenchant.group = _buttonGroup; btnItem.group = _buttonGroup; btnEnchantment.group = _buttonGroup; btnSoul.group = _buttonGroup; _buttonGroup.addEventListener("change", this, "onButtonSelect"); positionButtons(); _buttonGroup.setSelectedButton(btnDisenchant); } private function positionButtons() { _totalWidth = background._width; formatTextButton(btnItem); formatTextButton(btnEnchantment); formatTextButton(btnSoul); vertSeparator._x = 120; var borderOffset = (vertSeparator._x / 2) - (btnDisenchant._width / 2); btnDisenchant._x = borderOffset; var leftStart = vertSeparator._x + 3; var leftEnd = _totalWidth; var leftWidth = leftEnd - leftStart; var totalBtnWidth = btnItem._width + btnEnchantment._width + btnSoul._width; var spacing = (leftWidth - totalBtnWidth - (2* borderOffset)) / 2; var pos = leftStart + borderOffset; btnItem._x = pos; pos += btnItem._width + spacing; btnEnchantment._x = pos; pos += btnEnchantment._width + spacing; btnSoul._x = pos; } private static function formatTextButton(a_button: MovieClip): Void { // its not autosizing. why? :( var tf = a_button.textField; tf.autoSize = "left"; // ha. tf._width = tf.getLineMetrics(0).width + 10; a_button.background._width = tf._x + tf._width; } /* PUBLIC FUNCTIONS */ // Moves the selection left to the next element. Wraps around. public function moveSelectionLeft(): Void { var newIndex = selectedIndex - 1; if (newIndex < 0) { _bFastSwitch = true; newIndex = _buttonGroup.length - 1; } _buttonGroup.setSelectedButton(_buttonGroup.getButtonAt(newIndex)); } // Moves the selection right to the next element. Wraps around. public function moveSelectionRight(): Void { var newIndex = selectedIndex + 1; if (newIndex >= _buttonGroup.length) { _bFastSwitch = true; newIndex = 0; } _buttonGroup.setSelectedButton(_buttonGroup.getButtonAt(newIndex)); } // @GFx public function handleInput(details: InputDetails, pathToFocus: Array): Boolean { if (disableInput) return false; if (GlobalFunc.IsKeyPressed(details)) { if (details.navEquivalent == NavigationCode.LEFT) { moveSelectionLeft(); return true; } else if (details.navEquivalent == NavigationCode.RIGHT) { moveSelectionRight(); return true; } } return false; } // @override MovieClip public function onEnterFrame(): Void { super.onEnterFrame(); if (_bFastSwitch && _selectorPos != _targetSelectorPos) { _selectorPos = _targetSelectorPos; _bFastSwitch = false; refreshSelector(); } else if (_selectorPos < _targetSelectorPos) { _selectorPos = _selectorPos + (_targetSelectorPos - _selectorPos) * 0.2 + 1; refreshSelector(); if (_selectorPos > _targetSelectorPos) _selectorPos = _targetSelectorPos; } else if (_selectorPos > _targetSelectorPos) { _selectorPos = _selectorPos - (_selectorPos - _targetSelectorPos) * 0.2 - 1; refreshSelector(); if (_selectorPos < _targetSelectorPos) _selectorPos = _targetSelectorPos; } } /* PRIVATE FUNCTIONS */ private function onButtonSelect(a_event: Object): Void { var btn = a_event.item; if (btn == null) return; selectedIndex = _buttonGroup.indexOf(btn); updateSelector(); } // Note: Copy&paste from categorymenu. Could use some refactoring, but as long as it works // identically to the item menus its fine for now. private function updateSelector(): Void { if (selectedIndex == -1) { selectorCenter._visible = false; if (selectorLeft != undefined) selectorLeft._visible = false; if (selectorRight != undefined) selectorRight._visible = false; return; } var selectedButton = _buttonGroup.getButtonAt(selectedIndex) _targetSelectorPos = selectedButton._x + (selectedButton.icon._width - selectorCenter._width) / 2; selectorCenter._visible = true; selectorCenter._y = selectedButton._y + selectedButton.background._height; if (selectorLeft != undefined) { selectorLeft._visible = true; selectorLeft._x = 0; selectorLeft._y = selectorCenter._y; } if (selectorRight != undefined) { selectorRight._visible = true; selectorRight._y = selectorCenter._y; selectorRight._width = _totalWidth - selectorRight._x; } } private function refreshSelector(): Void { selectorCenter._x = _selectorPos; if (selectorLeft != undefined) selectorLeft._width = selectorCenter._x; if (selectorRight != undefined) { selectorRight._x = selectorCenter._x + selectorCenter._width; selectorRight._width = _totalWidth - selectorRight._x; } } } ================================================ FILE: src/CraftingMenu/IconTabList.as ================================================ import gfx.events.EventDispatcher; import gfx.ui.NavigationCode; import gfx.ui.InputDetails; import Shared.GlobalFunc; import skyui.components.list.EntryClipManager; import skyui.components.list.BasicEnumeration; import skyui.components.list.AlphaEntryFormatter; import skyui.components.list.BasicList; class IconTabList extends BasicList { /* CONSTANTS */ public static var LEFT_SEGMENT = 0; public static var RIGHT_SEGMENT = 1; /* STAGE ELEMENTS */ public var selectorCenter: MovieClip; public var selectorLeft: MovieClip; public var selectorRight: MovieClip; public var background: MovieClip; /* PRIVATE VARIABLES */ private var _xOffset: Number; private var _contentWidth: Number; private var _totalWidth: Number; private var _selectorPos: Number; private var _targetSelectorPos: Number; private var _bFastSwitch: Boolean; /* PROPERTIES */ // Distance from border to start icon. public var iconIndent: Number; // Size of the icon. public var iconSize: Number; // Array that contains the icon label for category at position i. // The category list uses fixed lengths/icons, so this is assigned statically. public var iconArt: Array; // Index of previous selected item public var lastSelectedIndex: Number; /* INITIALIZATION */ public function IconTabList() { super(); _selectorPos = 0; _targetSelectorPos = 0; _bFastSwitch = false; if (iconSize == undefined) iconSize = 32; } /* PUBLIC FUNCTIONS */ // Clears the list. For the category list, that's ok since the entryList isn't manipulated directly. // @override BasicList public function clearList(): Void { _entryList.splice(0); } // @override BasicList public function InvalidateData(): Void { if (_bSuspended) { _bRequestInvalidate = true; return; } listEnumeration.invalidate(); if (_selectedIndex >= listEnumeration.size()) _selectedIndex = listEnumeration.size() - 1; UpdateList(); if (onInvalidate) onInvalidate(); } // @override BasicList public function UpdateList(): Void { if (_bSuspended) { _bRequestUpdate = true; return; } var clipCount = listEnumeration.size(); setClipCount(clipCount); var cw = 0; for (var i = 0; i < clipCount; i++) { var entryClip = getClipByIndex(i); entryClip.setEntry(listEnumeration.at(i), listState); listEnumeration.at(i).clipIndex = i; entryClip.itemIndex = i; cw = cw + iconSize; } _contentWidth = cw; _totalWidth = background._width; var spacing = (_totalWidth - _contentWidth) / (clipCount + 1); var xPos = background._x + spacing; for (var i = 0; i < clipCount; i++) { var entryClip = getClipByIndex(i); entryClip._x = xPos; xPos = xPos + iconSize + spacing; entryClip._visible = true; } updateSelector(); } // Moves the selection left to the next element. Wraps around. public function moveSelectionLeft(): Void { if (disableSelection) return; var curIndex = _selectedIndex; var startIndex = _selectedIndex; lastSelectedIndex = curIndex; do { if (curIndex > 0) { curIndex--; } else { _bFastSwitch = true; curIndex = listEnumeration.size() - 1; } } while (curIndex != startIndex && listEnumeration.at(curIndex).enabled == false); onItemPress(curIndex, 0); } // Moves the selection right to the next element. Wraps around. public function moveSelectionRight(): Void { if (disableSelection) return; var curIndex = _selectedIndex; var startIndex = _selectedIndex; lastSelectedIndex = curIndex; do { if (curIndex < listEnumeration.size() - 1) { curIndex++; } else { _bFastSwitch = true; curIndex = 0; } } while (curIndex != startIndex && listEnumeration.at(curIndex).enabled == false); onItemPress(curIndex, 0); } // @GFx public function handleInput(details: InputDetails, pathToFocus: Array): Boolean { if (disableInput) return false; if (GlobalFunc.IsKeyPressed(details)) { if (details.navEquivalent == NavigationCode.LEFT) { moveSelectionLeft(); return true; } else if (details.navEquivalent == NavigationCode.RIGHT) { moveSelectionRight(); return true; } } return false; } // @override BasicList public function onEnterFrame(): Void { super.onEnterFrame(); if (_bFastSwitch && _selectorPos != _targetSelectorPos) { _selectorPos = _targetSelectorPos; _bFastSwitch = false; refreshSelector(); } else if (_selectorPos < _targetSelectorPos) { _selectorPos = _selectorPos + (_targetSelectorPos - _selectorPos) * 0.2 + 1; refreshSelector(); if (_selectorPos > _targetSelectorPos) _selectorPos = _targetSelectorPos; } else if (_selectorPos > _targetSelectorPos) { _selectorPos = _selectorPos - (_selectorPos - _targetSelectorPos) * 0.2 - 1; refreshSelector(); if (_selectorPos < _targetSelectorPos) _selectorPos = _targetSelectorPos; } } // @override BasicList public function onItemPress(a_index: Number, a_keyboardOrMouse: Number): Void { if (disableInput || disableSelection || a_index == -1) return; doSetSelectedIndex(a_index, a_keyboardOrMouse); updateSelector(); dispatchEvent({type: "itemPress", index: _selectedIndex, entry: selectedEntry, keyboardOrMouse: a_keyboardOrMouse}); } // @override BasicList private function onItemPressAux(a_index: Number, a_keyboardOrMouse: Number, a_buttonIndex: Number): Void { if (disableInput || disableSelection || a_index == -1 || a_buttonIndex != 1) return; doSetSelectedIndex(a_index, a_keyboardOrMouse); updateSelector(); dispatchEvent({type: "itemPressAux", index: _selectedIndex, entry: selectedEntry, keyboardOrMouse: a_keyboardOrMouse}); } // @override BasicList public function onItemRollOver(a_index: Number): Void { if (disableInput || disableSelection) return; isMouseDrivenNav = true; if (a_index == _selectedIndex) return; var entryClip = getClipByIndex(a_index); entryClip._alpha = 75; } // @override BasicList public function onItemRollOut(a_index: Number): Void { if (disableInput || disableSelection) return; isMouseDrivenNav = true; if (a_index == _selectedIndex) return; var entryClip = getClipByIndex(a_index); entryClip._alpha = 50; } /* PRIVATE FUNCTIONS */ private function updateSelector(): Void { if (selectorCenter == undefined) { return; } if (_selectedIndex == -1) { selectorCenter._visible = false; if (selectorLeft != undefined) selectorLeft._visible = false; if (selectorRight != undefined) selectorRight._visible = false; return; } var selectedClip = _entryClipManager.getClip(_selectedIndex); _targetSelectorPos = selectedClip._x + (selectedClip.background._width - selectorCenter._width) / 2; selectorCenter._visible = true; selectorCenter._y = selectedClip._y + selectedClip.background._height; if (selectorLeft != undefined) { selectorLeft._visible = true; selectorLeft._x = 0; selectorLeft._y = selectorCenter._y; } if (selectorRight != undefined) { selectorRight._visible = true; selectorRight._y = selectorCenter._y; selectorRight._width = _totalWidth - selectorRight._x; } } private function refreshSelector(): Void { selectorCenter._visible = true; var selectedClip = _entryClipManager.getClip(_selectedIndex); selectorCenter._x = _selectorPos; if (selectorLeft != undefined) selectorLeft._width = selectorCenter._x; if (selectorRight != undefined) { selectorRight._x = selectorCenter._x + selectorCenter._width; selectorRight._width = _totalWidth - selectorRight._x; } } } ================================================ FILE: src/CraftingMenu/IconTabListEntry.as ================================================ import skyui.components.list.ListState; import skyui.components.list.BasicListEntry; class IconTabListEntry extends BasicListEntry { /* PRIVATE VARIABLES */ private var _iconLabel: String; private var _iconSize: Number; /* STAGE ELMENTS */ public var icon: MovieClip; /* PUBLIC FUNCTIONS */ public function initialize(a_index: Number, a_state: ListState): Void { super.initialize(); _iconLabel = IconTabList(a_state.list).iconArt[a_index]; _iconSize = IconTabList(a_state.list).iconSize; icon.gotoAndStop(_iconLabel); } public function setEntry(a_entryObject: Object, a_state: ListState): Void { enabled = a_entryObject.enabled; if (a_entryObject.divider == true) { _alpha = 100; } else if (!enabled) { _alpha = 15; } else if (a_entryObject == a_state.list.selectedEntry) { _alpha = 100; } else { _alpha = 50; } } /* PRIVATE FUNCTIONS */ } ================================================ FILE: src/Enderal/ButtonGrid.as ================================================ import gfx.ui.NavigationCode; import Shared.GlobalFunc; import skyui.components.list.BasicList; class ButtonGrid extends BasicList { /* CONSTANTS */ /* PROPERTIES */ public var columnCount: Number = 1; /* INITIALIZATION */ public function ButtonGrid() { super(); } /* PUBLIC FUNCTIONS */ // @override BasicList public function UpdateList(): Void { if (_bSuspended) { _bRequestUpdate = true; return; } setClipCount(getListEnumSize()); var xOffset = leftBorder; var yOffset = topBorder; // Set entries for (var i = 0; i < getListEnumSize(); i++) { var entryClip = getClipByIndex(i); var entryItem = getListEnumEntry(i); entryClip.itemIndex = i; entryItem.clipIndex = i; entryClip.setEntry(entryItem, listState); entryClip._x = xOffset; entryClip._y = yOffset; entryClip._visible = true; if (i % columnCount == (columnCount-1)) { xOffset = leftBorder; yOffset += entryClip._height; } else { xOffset += entryClip._width; } } } // @GFx public function handleInput(details, pathToFocus): Boolean { var processed = false; if (disableInput) return false; var entry = getClipByIndex(_selectedIndex); var processed = entry != undefined && entry.handleInput != undefined && entry.handleInput(details, pathToFocus.slice(1)); if (!processed && GlobalFunc.IsKeyPressed(details)) { if (details.navEquivalent == NavigationCode.UP || details.navEquivalent == NavigationCode.PAGE_UP) { moveSelectionUp(); processed = true; } else if (details.navEquivalent == NavigationCode.DOWN || details.navEquivalent == NavigationCode.PAGE_DOWN) { moveSelectionDown(); processed = true; } else if (!disableSelection && details.navEquivalent == NavigationCode.ENTER) { onItemPress(); processed = true; } } return processed; } public function moveSelectionUp(): Void { if (disableSelection) return; if (_selectedIndex == -1) { doSetSelectedIndex(getListEnumLastIndex(), SELECT_KEYBOARD); isMouseDrivenNav = false; } else if (getSelectedListEnumIndex() > 0) { doSetSelectedIndex(getListEnumRelativeIndex(-1), SELECT_KEYBOARD); isMouseDrivenNav = false; } } public function moveSelectionDown(): Void { if (disableSelection) return; if (_selectedIndex == -1) { doSetSelectedIndex(getListEnumFirstIndex(), SELECT_KEYBOARD); isMouseDrivenNav = false; } else if (getSelectedListEnumIndex() < getListEnumSize() - 1) { doSetSelectedIndex(getListEnumRelativeIndex(+1), SELECT_KEYBOARD); isMouseDrivenNav = false; } } /* PRIVATE FUNCTIONS */ // @GFx private function onMouseWheel(delta) { if (disableInput) return; for (var target = Mouse.getTopMostEntity(); target && target != undefined; target = target._parent) { if (target == this) { if (delta < 0) moveSelectionDown(); else if (delta > 0) moveSelectionUp(); } } isMouseDrivenNav = true; } } ================================================ FILE: src/Enderal/ButtonGridEntry.as ================================================ import skyui.components.list.BasicList; import skyui.components.list.ListState; import skyui.components.list.BasicListEntry; class ButtonGridEntry extends BasicListEntry { /* PRIVATE VARIABLES */ /* STAGE ELEMENTS */ public var textField: TextField; public var icon: MovieClip; /* PROPERTIES */ /* PUBLIC FUNCTIONS */ public function setEntry(a_entryObject: Object, a_state: ListState): Void { isEnabled = true; var isSelected = a_entryObject == a_state.list.selectedEntry; gotoAndStop(isSelected ? "selected" : "normal"); textField.autoSize = a_entryObject.align ? a_entryObject.align : "left"; textField.SetText(a_entryObject.name ? a_entryObject.name : " "); icon.gotoAndStop(a_entryObject.iconLabel); } } ================================================ FILE: src/Enderal/DataLoader.as ================================================ import flash.utils.*; import mx.utils.Delegate; import gfx.events.EventDispatcher; import skyui.util.GlobalFunctions; class DataLoader { /* INITIALIATZION */ public function DataLoader() { GlobalFunctions.addArrayFunctions(); EventDispatcher.initialize(this); } /* PUBLIC FUNCTIONS */ public function loadFile(a_path: String): Void { var lv = new LoadVars(); lv.onData = Delegate.create(this, parseData); lv.load(a_path); } // @mixin by gfx.events.EventDispatcher public var dispatchEvent: Function; public var dispatchQueue: Function; public var hasEventListener: Function; public var addEventListener: Function; public var removeEventListener: Function; public var removeAllEventListeners: Function; public var cleanUpEvents: Function; /* PRIVATE FUNCTIONS */ private function parseData(a_data: Array): Void { var dataObj = {}; var lines = a_data.split("\r\n"); if (lines.length == 1) lines = a_data.split("\n"); for (var i = 0; i < lines.length; i++) { // Comment if (lines[i].charAt(0) == ";") continue; if (lines[i].length < 3) continue; // Get raw key string var key = GlobalFunctions.clean(lines[i].slice(0, lines[i].indexOf("="))); if (key == undefined) continue; // Prepare key subsections var a = key.split("."); var loc = dataObj; for (var j=0; j") return new Array(); var values = GlobalFunctions.extract(a_str, "<", ">").split(","); for (var i=0; i ; CLASSES ------------------------------------------------------- classes.myClass1.name = '$My Class 1' classes.myClass1.description = '$My Class 1 Description' classes.myClass1.iconLabel = 'my_class_1' classes.myClass1.rootSkill = mySkill1 classes.myClass2.name = '$My Class 2' classes.myClass2.description = '$My Class 2 Description' classes.myClass2.iconLabel = 'my_class_2' classes.myClass2.rootSkill = mySkill1 classes.myClass3.name = '$My Class 3' classes.myClass3.description = '$My Class 3 Description' classes.myClass3.iconLabel = 'my_class_1' classes.myClass3.rootSkill = mySkill1 classes.myClass4.name = '$My Class 4' classes.myClass4.description = '$My Class 4 Description' classes.myClass4.iconLabel = 'my_class_2' classes.myClass4.rootSkill = mySkill1 classes.myClass5.name = '$My Class 5' classes.myClass5.description = '$My Class 5 Description' classes.myClass5.iconLabel = 'my_class_1' classes.myClass5.rootSkill = mySkill1 classes.myClass6.name = '$My Class 6' classes.myClass6.description = '$My Class 6 Description' classes.myClass6.iconLabel = 'my_class_2' classes.myClass6.rootSkill = mySkill1 classes.myClass7.name = '$My Class 7' classes.myClass7.description = '$My Class 7 Description' classes.myClass7.iconLabel = 'my_class_1' classes.myClass7.rootSkill = mySkill1 classes.myClass8.name = '$My Class 8' classes.myClass8.description = '$My Class 8 Description' classes.myClass8.iconLabel = 'my_class_2' classes.myClass8.rootSkill = mySkill1 classes.myClass9.name = '$My Class 9' classes.myClass9.description = '$My Class 9 Description' classes.myClass9.iconLabel = 'my_class_1' classes.myClass9.rootSkill = mySkill1 ; SKILLS ------------------------------------------------------- skills.mySkill1.name = '$My Skill 1' skills.mySkill1.description = '$My Skill 1 Description' skills.mySkill1.iconLabel = 'my_skill_1' skills.mySkill1.children = skills.mySkill1.maxRank = 1 skills.mySkill1.position = <50, 10> skills.mySkill1.perkListID = 0x12345678 skills.mySkill2.name = '$My Skill 2' skills.mySkill2.description = '$My Skill 2 Description' skills.mySkill2.iconLabel = 'my_skill_2' skills.mySkill2.children = skills.mySkill2.maxRank = 1 skills.mySkill2.position = <30, 30> skills.mySkill2.perkListID = 0x12345678 skills.mySkill3.name = '$My Skill 3' skills.mySkill3.description = '$My Skill 3 Description' skills.mySkill3.iconLabel = 'my_skill_3' skills.mySkill3.maxRank = 1 skills.mySkill3.position = <70, 30> skills.mySkill3.perkListID = 0x12345678 skills.mySkill4.name = '$My Skill 4' skills.mySkill4.description = '$My Skill 3 Description' skills.mySkill4.iconLabel = 'my_skill_4' skills.mySkill4.maxRank = 1 skills.mySkill4.position = <50, 50> skills.mySkill4.perkListID = 0x12345678 ================================================ FILE: src/Enderal/SkillTreeEntry.as ================================================ class SkillTreeEntry extends MovieClip { /* STAGE ELEMENTS */ public var background: MovieClip; public var icon: MovieClip; public var textField: TextField; /* PROPERTIES */ public var isEnabled: Boolean = true; public var data: Object = null; /* PRIVATE VARIABLES */ /* PUBLIC FUNCTIONS */ // @override MovieClip public function onRollOver(): Void { var view = this._parent._parent; if (isEnabled) view.onSkillRollOver(this); } // @override MovieClip public function onRollOut(): Void { var view = this._parent._parent; if (isEnabled) view.onSkillRollOut(this); } // @override MovieClip public function onPress(a_mouseIndex: Number, a_keyboardOrMouse: Number): Void { var view = this._parent._parent; if ( isEnabled) view.onSkillPress(this, a_keyboardOrMouse); } // @override MovieClip public function onPressAux(a_mouseIndex: Number, a_keyboardOrMouse: Number, a_buttonIndex: Number): Void { var view = this._parent._parent; if (isEnabled) view.onSkillPressAux(this, a_keyboardOrMouse, a_buttonIndex); } public function clearData(): Void { data = null; } public function setData(a_data: Object): Void { data = a_data; invalidate(); } public function invalidate(): Void { var view = this._parent._parent; var isSelected = view.selectedClip == this; gotoAndStop(isSelected ? "normal" : "selected"); icon.gotoAndStop(data.iconLabel); textField.SetText(data.name); } } ================================================ FILE: src/Enderal/SkillTreeView.as ================================================ import gfx.ui.NavigationCode; import Shared.GlobalFunc; import skyui.util.GlobalFunctions; import gfx.events.EventDispatcher; class SkillTreeView extends MovieClip { /* CONSTANTS */ /* STAGE ELEMENTS */ public var clipPlane: MovieClip; public var edgePlane: MovieClip; public var background: MovieClip; /* PROPERTIES */ public var skillData: Object; public var entryRenderer: String; public var edgeRenderer: String; public var horizontalSpacing: Number = 75; public var verticalSpacing: Number = 75; public function get selectedClip(): SkillTreeEntry { return _selectedClip; } public function set selectedClip(a_clip: SkillTreeEntry) { if (_selectedClip == a_clip) return; var oldClip = _selectedClip; _selectedClip = a_clip; if (oldClip) oldClip.invalidate(); if (a_clip) a_clip.invalidate(); } /* PRIVATE VARIABLES */ private var _rootName: String; private var _selectedClip: SkillTreeEntry; private var _clipPool: Array; private var _edgePool: Array; /* INITIALIZATION */ public function SkillTreeView() { super(); _selectedClip = null; _rootName = null; _clipPool = []; _edgePool = []; edgePlane = this.createEmptyMovieClip("edgePlane", this.getNextHighestDepth()); clipPlane = this.createEmptyMovieClip("clipPlane", this.getNextHighestDepth()); EventDispatcher.initialize(this); } /* PUBLIC FUNCTIONS */ // @mixin by gfx.events.EventDispatcher public var dispatchEvent: Function; public var dispatchQueue: Function; public var hasEventListener: Function; public var addEventListener: Function; public var removeEventListener: Function; public var removeAllEventListeners: Function; public var cleanUpEvents: Function; public function setRootSkill(a_name: String): Void { if (a_name != _rootName) { _rootName = a_name; updateTree(); } } private function prepareClips(a_count: Number): Void { var d = a_count - _clipPool.length; // Grow pool? if (d > 0) { var nextIndex = _clipPool.length; for (var i=0; i 0) { var nextIndex = _edgePool.length; for (var i=0; i= 1.6.6 if (a_entryObject.useSound.formId != undefined && a_entryObject.useSound.formId == Form.FORMID_ITMPotionUse) { a_entryObject.subType = Item.POTION_DRINK; } } else if ((a_entryObject.flags & Item.ALCHFLAG_POISON) != 0) { a_entryObject.subType = Item.POTION_POISON; } else { switch (a_entryObject.actorValue) { case Actor.AV_HEALTH: a_entryObject.subType = Item.POTION_HEALTH; break; case Actor.AV_MAGICKA: a_entryObject.subType = Item.POTION_MAGICKA; break; case Actor.AV_STAMINA: a_entryObject.subType = Item.POTION_STAMINA; break; case Actor.AV_HEALRATE: a_entryObject.subType = Item.POTION_HEALRATE; break; case Actor.AV_MAGICKARATE: a_entryObject.subType = Item.POTION_MAGICKARATE; break; case Actor.AV_STAMINARATE: a_entryObject.subType = Item.POTION_STAMINARATE; break; case Actor.AV_HEALRATEMULT: a_entryObject.subType = Item.POTION_HEALRATEMULT; break; case Actor.AV_MAGICKARATEMULT: a_entryObject.subType = Item.POTION_MAGICKARATEMULT; break; case Actor.AV_STAMINARATEMULT: a_entryObject.subType = Item.POTION_STAMINARATEMULT; break; case Actor.AV_FIRERESIST: a_entryObject.subType = Item.POTION_FIRERESIST; break; case Actor.AV_ELECTRICRESIST: a_entryObject.subType = Item.POTION_ELECTRICRESIST; break; case Actor.AV_FROSTRESIST: a_entryObject.subType = Item.POTION_FROSTRESIST; break; } } } private function processPotionIcon(a_entryObject: Object): Void { a_entryObject.iconLabel = "default_potion"; switch(a_entryObject.subType) { case Item.POTION_DRINK: a_entryObject.iconLabel = "food_wine"; break; case Item.POTION_FOOD: a_entryObject.iconLabel = "default_food"; break; case Item.POTION_POISON: a_entryObject.iconLabel = "potion_poison"; break; case Item.POTION_HEALTH: case Item.POTION_HEALRATE: case Item.POTION_HEALRATEMULT: a_entryObject.iconLabel = "potion_health"; break; case Item.POTION_MAGICKA: case Item.POTION_MAGICKARATE: case Item.POTION_MAGICKARATEMULT: a_entryObject.iconLabel = "potion_magic"; break; case Item.POTION_STAMINA: case Item.POTION_STAMINARATE: case Item.POTION_STAMINARATEMULT: a_entryObject.iconLabel = "potion_stam"; break; case Item.POTION_FIRERESIST: a_entryObject.iconLabel = "potion_fire"; break; case Item.POTION_ELECTRICRESIST: a_entryObject.iconLabel = "potion_shock"; break; case Item.POTION_FROSTRESIST: a_entryObject.iconLabel = "potion_frost"; break; } } private function processSpellIcon(a_entryObject: Object): Void { a_entryObject.iconLabel = "default_power"; switch(a_entryObject.school) { case Actor.AV_ALTERATION: a_entryObject.iconLabel = "default_alteration"; break; case Actor.AV_CONJURATION: a_entryObject.iconLabel = "default_conjuration"; break; case Actor.AV_DESTRUCTION: a_entryObject.iconLabel = "default_destruction"; break; case Actor.AV_ILLUSION: a_entryObject.iconLabel = "default_illusion"; break; case Actor.AV_RESTORATION: a_entryObject.iconLabel = "default_restoration"; break; } } } ================================================ FILE: src/FavoritesMenu/FavoritesListEntry.as ================================================ import skyui.components.list.ScrollingList; import skyui.components.list.ListState; import skyui.components.list.BasicListEntry; import skyui.util.ConfigManager; class FavoritesListEntry extends BasicListEntry { /* CONSTANTS */ private static var STATES = ["None", "Equipped", "LeftEquip", "RightEquip", "LeftAndRightEquip"]; /* PRIVATE VARIABLES */ /* STAGE ELMENTS */ public var itemIcon: MovieClip; public var equipIcon: MovieClip; public var textField: TextField; public var selectIndicator: MovieClip; public var hotkeyIcon: MovieClip; public var mainHandIcon: MovieClip; public var offHandIcon: MovieClip; /* INITIALIZATION */ // @override BasicListEntry public function initialize(a_index: Number, a_state: ListState): Void { super.initialize(); } /* PUBLIC FUNCTIONS */ // @override BasicListEntry public function setEntry(a_entryObject: Object, a_state: ListState): Void { var isAssigned = a_entryObject == a_state.assignedEntry; var isSelected = a_entryObject == a_state.list.selectedEntry || isAssigned; var groupIndex = a_state.activeGroupIndex; var isMainHand: Boolean = groupIndex != -1 && (a_entryObject.mainHandFlag & (1 << groupIndex)) != 0; var isOffHand: Boolean = groupIndex != -1 && (a_entryObject.offHandFlag & (1 << groupIndex)) != 0; isEnabled = a_state.assignedEntry == null || isAssigned; _alpha = isEnabled ? 100 : 25; if (selectIndicator != undefined) selectIndicator._visible = isSelected; if (a_entryObject.text == undefined) { textField.SetText(" "); } else { var hotkey = a_entryObject.hotkey; if (hotkey != undefined && hotkey != -1) { if (hotkey >= 0 && hotkey <= 7) { textField.SetText(a_entryObject.text); hotkeyIcon._visible = true; hotkeyIcon.gotoAndStop(hotkey + 1); } else { textField.SetText("$HK" + hotkey); textField.SetText(textField.text + ". " + a_entryObject.text); hotkeyIcon._visible = false; } } else { textField.SetText(a_entryObject.text); hotkeyIcon._visible = false; } var maxTextLength: Number = 32; if (textField.text.length > maxTextLength) { textField.SetText(textField.text.substr(0, maxTextLength - 3) + "..."); } } // textField.textAutoSize = "shrink"; var iconLabel = a_entryObject.iconLabel != undefined ? a_entryObject.iconLabel : "default_misc"; itemIcon.gotoAndStop(iconLabel); itemIcon._alpha = isSelected ? 90 : 50; if (a_entryObject == null) equipIcon.gotoAndStop("None"); else equipIcon.gotoAndStop(STATES[a_entryObject.equipState]); var iconOffset = textField._x + textField.textWidth + 8; if (isMainHand) { mainHandIcon._x = iconOffset; iconOffset += 12; } mainHandIcon._visible = isMainHand; if (isOffHand) { offHandIcon._x = iconOffset; } offHandIcon._visible = isOffHand; } /* PRIVATE FUNCTIONS */ } ================================================ FILE: src/FavoritesMenu/FavoritesMenu.as ================================================ import Shared.GlobalFunc; import gfx.io.GameDelegate; import gfx.managers.FocusHandler; import gfx.controls.ButtonGroup; import gfx.controls.Button; import gfx.ui.InputDetails; import gfx.ui.NavigationCode; import skyui.util.GlobalFunctions; import skyui.util.Translator; import skyui.defines.Input; import skyui.defines.Form; import skyui.components.ButtonPanel; import skyui.components.MappedButton; import skyui.components.list.ScrollingList; import skyui.components.list.FilteredEnumeration; import skyui.filter.ItemTypeFilter; import skyui.filter.SortFilter; class FavoritesMenu extends MovieClip { #include "../version.as" /* CONSTANTS */ private static var ITEM_SELECT = 0; private static var GROUP_ASSIGN = 1; private static var GROUP_ASSIGN_SYNC = 2; private static var GROUP_REMOVE_SYNC = 3; private static var CLOSING = 4; private static var SAVE_EQUIP_STATE_SYNC = 5; private static var SET_ICON_SYNC = 6; /* PRIVATE VARIABLES */ private var _platform: Number; private var _typeFilter: ItemTypeFilter; private var _sortFilter: SortFilter; private var _groupDataExtender: GroupDataExtender; private var _categoryButtonGroup: ButtonGroup; private var _groupButtonGroup: ButtonGroup; private var _leftKeycode: Number = -1; private var _rightKeycode: Number = -1; private var _groupAddKey: Number = -1; private var _groupUseKey: Number = -1; private var _setIconKey: Number = -1; private var _saveEquipStateKey: Number = -1; private var _toggleFocusKey: Number = -1; private var _groupAddControls: Object; private var _groupUseControls: Object; private var _setIconControls: Object; private var _saveEquipStateControls: Object; private var _toggleFocusControls: Object; private var _state: Number; // A workaround to prevent bla blablabla private var _useMouseNavigation: Boolean = false; private var _categoryIndex: Number = 0; private var _groupIndex: Number = 0; private var _groupButtonFocused: Boolean = false; private var _groupAssignIndex: Number = -1; private var _savedIndex: Number = -1; private var _savedScrollPosition: Number = 0; private var _groupButtonsShown: Boolean = false; private var _waitingForGroupData: Boolean = true; private var _isInitialized: Boolean = false; private var _navPanelEnabled: Boolean = false; private var _fadedIn: Boolean = false; /* STAGE ELEMENTS */ public var itemList: ScrollingList; public var background: MovieClip; public var btnAll: Button; public var btnGear: Button; public var btnAid: Button; public var btnMagic: Button; public var groupButtonFader: MovieClip; public var navButton: MappedButton; public var headerText: TextField; public var navPanel: MovieClip; /* PROPERTIES */ // @API public var bPCControlsReady: Boolean = true; /* INITIALIZATION */ public function FavoritesMenu() { super(); //dbgIntvl = setInterval(this, "TestMenu", 1000); _typeFilter = new ItemTypeFilter(); _sortFilter = new SortFilter(); _categoryButtonGroup = new ButtonGroup("CategoryButtonGroup"); _groupButtonGroup = new ButtonGroup("GroupButtonGroup"); Mouse.addListener(this); } /* PAPYRUS INTERFACE */ public var leftHandItemId: Number; public var rightHandItemId: Number; public function initControls(a_navPanelEnabled: Boolean, a_groupAddKey: Number, a_groupUseKey: Number, a_setIconKey: Number, a_saveEquipStateKey: Number, a_toggleFocusKey: Number): Void { _navPanelEnabled = a_navPanelEnabled; // On PC, we need overrides from Papyrus to make sure no mouse buttons are used (handleInput doesnt catch those). // On gamepad, we can get the keys via SKSE so no need to let the user rebind it. if (_platform == 0) { _groupAddKey = a_groupAddKey; _groupUseKey = a_groupUseKey; _setIconKey = a_setIconKey; _saveEquipStateKey = a_saveEquipStateKey; _toggleFocusKey = a_toggleFocusKey; createControls(); } updateNavButtons(); } public function pushGroupItems(/* itemIds[] */): Void { for (var i=0; i= _groupButtonGroup.length) idx = 0; _groupButtonGroup.setSelectedButton(_groupButtonGroup.getButtonAt(idx)); } else if (_state == ITEM_SELECT) { if (_groupButtonFocused) { _groupIndex++; if (_groupIndex >= _groupButtonGroup.length) _groupIndex = 0; _groupButtonGroup.setSelectedButton(_groupButtonGroup.getButtonAt(_groupIndex)); } else { _categoryIndex++; if (_categoryIndex >= _categoryButtonGroup.length) _categoryIndex = 0; _categoryButtonGroup.setSelectedButton(_categoryButtonGroup.getButtonAt(_categoryIndex)); } } return true; } else if (details.skseKeycode == _groupAddKey) { if (_state == ITEM_SELECT) { if (!_groupButtonFocused) startGroupAssignment(); else startGroupRemoval(); } else if (_state == GROUP_ASSIGN) { endGroupAssignment(); } return true; } else if (_state == GROUP_ASSIGN && details.navEquivalent == NavigationCode.ENTER) { if (_groupAssignIndex != -1) applyGroupAssignment(); return true; } else if (details.skseKeycode == _groupUseKey) { if (_state == ITEM_SELECT) requestGroupUse(); return true; } else if (details.skseKeycode == _setIconKey) { if (_state == ITEM_SELECT) startSetGroupIcon(); } else if (details.skseKeycode == _saveEquipStateKey) { if (_state == ITEM_SELECT) startSaveEquipState(); } else if (details.skseKeycode == _toggleFocusKey) { if (_state == ITEM_SELECT) setGroupFocus(!_groupButtonFocused); // toggle return true; } } return true; } // @API public function get selectedIndex(): Number { return confirmSelectedEntry() ? itemList.selectedEntry.index : -1; } // @API public function setSelectedItem(a_index: Number): Void { // We use skse.Store/LoadIndices to restore the selected item on our terms return; /* for (var i = 0; i < itemList.entryList.length; i++) { if (itemList.entryList[i].index == a_index) { itemList.selectedIndex = i; //itemList.RestoreScrollPosition(i); itemList.UpdateList(); return; } }*/ } // @API public function SetPlatform(a_platform: Number, a_bPS3Switch: Boolean): Void { _platform = a_platform; var isGamepad = _platform != 0; _leftKeycode = GlobalFunctions.getMappedKey("Left", Input.CONTEXT_MENUMODE, isGamepad); _rightKeycode = GlobalFunctions.getMappedKey("Right", Input.CONTEXT_MENUMODE, isGamepad); // Set keys via SKSE for gamepad, wait for initControls for PC if (_platform != 0) { _groupAddKey = GlobalFunctions.getMappedKey("Toggle POV", Input.CONTEXT_GAMEPLAY, true); _groupUseKey = GlobalFunctions.getMappedKey("Ready Weapon", Input.CONTEXT_GAMEPLAY, true); _setIconKey = GlobalFunctions.getMappedKey("Sprint", Input.CONTEXT_GAMEPLAY, true); _saveEquipStateKey = GlobalFunctions.getMappedKey("Wait", Input.CONTEXT_GAMEPLAY, true); _toggleFocusKey = GlobalFunctions.getMappedKey("Jump", Input.CONTEXT_GAMEPLAY, true); createControls(); } navButton.setPlatform(a_platform); navPanel.row1.setPlatform(a_platform,a_bPS3Switch); navPanel.row2.setPlatform(a_platform,a_bPS3Switch); updateNavButtons(); } /* PRIVATE FUNCTIONS */ private function onFilterChange(a_event: Object): Void { if (_isInitialized) itemList.InvalidateData(); } private function onItemPress(a_event: Object): Void { if (_state != ITEM_SELECT) return; // Only handles keyboard input, mouse is done internally if (a_event.keyboardOrMouse != 0) { _useMouseNavigation = false; GameDelegate.call("ItemSelect", []); } else { _useMouseNavigation = true; } } private function onItemSelectionChange(a_event: Object): Void { GameDelegate.call("PlaySound",["UIMenuFocus"]); _useMouseNavigation = a_event.keyboardOrMouse == 0; updateNavButtons(); } private function onCategorySelect(a_event: Object): Void { var btn = a_event.item; if (btn == null) return; _categoryIndex = _categoryButtonGroup.indexOf(btn); _groupButtonFocused = false; _groupButtonGroup.setSelectedButton(null); itemList.listState.activeGroupIndex = -1; headerText.SetText(btn.text); _typeFilter.changeFilterFlag(btn.filterFlag); GameDelegate.call("PlaySound",["UIMenuBladeOpenSD"]); updateNavButtons(); } private function onGroupSelect(a_event: Object): Void { var btn = a_event.item; if (btn == null) return; var index = _groupButtonGroup.indexOf(btn); _groupButtonFocused = true; _categoryButtonGroup.setSelectedButton(null); headerText.SetText(btn.text); itemList.listState.activeGroupIndex = index; _typeFilter.changeFilterFlag(btn.filterFlag); if (_state == GROUP_ASSIGN) { if (_groupAssignIndex == index) { applyGroupAssignment(); } else { navButton.setButtonData({text: "$Confirm Group", controls: Input.Accept}); _groupAssignIndex = index; } } else { _groupIndex = index; } GameDelegate.call("PlaySound",["UIMenuBladeOpenSD"]); updateNavButtons(); } private function onFadeInCompletion(): Void { _fadedIn = true; updateNavButtons(); } private function startFadeOut(): Void { _state = CLOSING; updateNavButtons(); _parent.gotoAndPlay("startFadeOut"); GameDelegate.call("PlaySound",["UIMenuBladeCloseSD"]); } private function onFadeOutCompletion(): Void { saveIndices(); GameDelegate.call("FadeDone", [itemList.selectedIndex]); } private function onMouseDown(): Void { _useMouseNavigation = true; } private function onMouseMove(): Void { _useMouseNavigation = true; } private function startGroupAssignment(): Void { if (_waitingForGroupData) return; var selectedEntry = itemList.selectedEntry; if (selectedEntry == null) return; _state = GROUP_ASSIGN; headerText._visible = false; _groupAssignIndex = -1; var assignedEntry = itemList.selectedEntry; itemList.listState.assignedEntry = assignedEntry; assignedEntry.filterFlag |= FilterDataExtender.FILTERFLAG_GROUP_ADD; itemList.listState.restoredSelectedIndex = itemList.selectedIndex; itemList.listState.restoredScrollPosition = itemList.scrollPosition; itemList.selectedIndex = -1; itemList.disableSelection = true; itemList.requestUpdate(); navButton.visible = true; navButton.setButtonData({text: "$Select Group", controls: Input.LeftRight}); btnAll.disabled = true; btnGear.disabled = true; btnAid.disabled = true; btnMagic.disabled = true; btnAll.visible = false; btnGear.visible = false; btnAid.visible = false; btnMagic.visible = false; updateNavButtons(); } private function applyGroupAssignment(): Void { var formId: Number = itemList.listState.assignedEntry.formId; var itemId: Number = itemList.listState.assignedEntry.itemId; if (formId == null || formId == 0 || _groupAssignIndex == -1) { endGroupAssignment(); GameDelegate.call("PlaySound", ["UIMenuCancel"]); } else { // Suspend list to avoid redundant invalidate before new synced group data arrives itemList.suspended = true enableGroupButtons(false); _state = GROUP_ASSIGN_SYNC; skse.SendModEvent("SKIFM_groupAdd", String(itemId), _groupAssignIndex, formId); GameDelegate.call("PlaySound", ["UIMenuOK"]); } } private function endGroupAssignment(): Void { itemList.listState.assignedEntry.filterFlag &= ~FilterDataExtender.FILTERFLAG_GROUP_ADD; itemList.listState.assignedEntry = null; itemList.onInvalidate = function() { this.scrollPosition = this.listState.restoredScrollPosition; this.selectedIndex = this.listState.restoredSelectedIndex; delete this.onInvalidate; }; itemList.disableSelection = false; itemList.requestInvalidate(); itemList.suspended = false; _state = ITEM_SELECT; _groupAssignIndex = -1; btnAll.disabled = false; btnGear.disabled = false; btnAid.disabled = false; btnMagic.disabled = false; btnAll.visible = true; btnGear.visible = true; btnAid.visible = true; btnMagic.visible = true headerText._visible = true; navButton.visible = false; setGroupFocus(false); enableGroupButtons(true); updateNavButtons(); } private function startGroupRemoval(): Void { var itemId: Number = itemList.selectedEntry.itemId; if (_groupButtonFocused && _groupIndex >= 0) { _state = GROUP_REMOVE_SYNC; skse.SendModEvent("SKIFM_groupRemove", String(itemId), _groupIndex); GameDelegate.call("PlaySound", ["UIMenuOK"]); } } private function endGroupRemoval(): Void { _state = ITEM_SELECT; } private function requestGroupUse(): Void { if (_groupButtonFocused && _groupIndex >= 0 && itemList.listEnumeration.size() > 0) { skse.SendModEvent("SKIFM_groupUse", "", _groupIndex); startFadeOut(); } } private function startSaveEquipState(): Void { leftHandItemId = 0; rightHandItemId = 0; var n = itemList.entryList.length; for (var i=0; i= 0) { _state = SAVE_EQUIP_STATE_SYNC; skse.SendModEvent("SKIFM_saveEquipState", "", _groupIndex); GameDelegate.call("PlaySound", ["UIMenuOK"]); } } private function endSaveEquipState(): Void { _state = ITEM_SELECT; } private function startSetGroupIcon(): Void { var itemId: Number = itemList.selectedEntry.itemId; var formId: Number = itemList.selectedEntry.formId; if (_groupButtonFocused && _groupIndex >= 0 && formId) { _state = SET_ICON_SYNC; skse.SendModEvent("SKIFM_setGroupIcon", String(itemId), _groupIndex, formId); GameDelegate.call("PlaySound", ["UIMenuOK"]); } } private function endSetGroupIcon(): Void { _state = ITEM_SELECT; } private function enableGroupButtons(a_enabled: Boolean): Void { if (a_enabled && !_groupButtonsShown) { _groupButtonsShown = true; groupButtonFader.gotoAndPlay("show"); } var t = !a_enabled; for (var i=1; i<=8; i++) groupButtonFader.groupButtonHolder["btnGroup" + i].disabled = t; } private function setGroupFocus(a_focus: Boolean): Void { if (a_focus) { if (_groupButtonsShown) { _groupButtonGroup.setSelectedButton(_groupButtonGroup.getButtonAt(_groupIndex)); } } else { _categoryButtonGroup.setSelectedButton(_categoryButtonGroup.getButtonAt(_categoryIndex)); } } // Added to prevent clicks on the scrollbar from equipping/using stuff private function confirmSelectedEntry(): Boolean { // only allow item selection while in item select state if (_state != ITEM_SELECT) return false; // only confirm when using mouse if (_platform != 0 || !_useMouseNavigation) return true; for (var e = Mouse.getTopMostEntity(); e != undefined; e = e._parent) if (e.itemIndex == itemList.selectedIndex) return true; return false; } private function saveIndices(): Void { var indicesIn: Array = [_categoryIndex, _groupIndex, itemList.selectedIndex, itemList.scrollPosition]; skse.StoreIndices("SKI_FavoritesMenuState", indicesIn); } private function restoreIndices(): Void { var indicesOut: Array = []; skse.LoadIndices("SKI_FavoritesMenuState", indicesOut); if (indicesOut.length != 4) return; _categoryIndex = indicesOut[0]; _groupIndex = indicesOut[1]; itemList.listState.restoredSelectedIndex = indicesOut[2]; itemList.listState.restoredScrollPosition = indicesOut[3]; itemList.onInvalidate = function() { this.scrollPosition = this.listState.restoredScrollPosition; this.selectedIndex = this.listState.restoredSelectedIndex; delete this.onInvalidate; }; } private function updateNavButtons(): Void { if (_state != ITEM_SELECT || !_navPanelEnabled || !_fadedIn || _waitingForGroupData) { navPanel._visible = false; return; } var isListFilled = itemList.listEnumeration.size() > 0; var isEntrySelected = itemList.selectedEntry != null; navPanel._visible = true; var row1: ButtonPanel = navPanel.row1; var row2: ButtonPanel = navPanel.row2; var twoRows = false; row1.clearButtons(); row1.addButton({text: "$Toggle Focus", controls: _toggleFocusControls}); if (isEntrySelected) row1.addButton({text: _groupButtonFocused ? "$Ungroup" : "$Group", controls: _groupAddControls}); row1.updateButtons(true); row2.clearButtons(); if (_groupButtonFocused && isListFilled) { twoRows = true; row2.addButton({text: "$Group Use", controls: _groupUseControls}); row2.addButton({text: "$Save Equip State", controls: _saveEquipStateControls}); if (isEntrySelected) row2.addButton({text: "$Set Group Icon", controls: _setIconControls}); } row2.updateButtons(true); row1._x = -(row1._width / 2); row1._y = twoRows ? 10 : 35; row2._x = -(row2._width / 2); row2._y = 65; } private function createControls(): Void { _groupAddControls = {keyCode: _groupAddKey}; _groupUseControls = {keyCode: _groupUseKey}; _setIconControls = {keyCode: _setIconKey}; _saveEquipStateControls = {keyCode: _saveEquipStateKey}; _toggleFocusControls = {keyCode: _toggleFocusKey}; } } ================================================ FILE: src/FavoritesMenu/FilterDataExtender.as ================================================ import skyui.defines.Form; import skyui.components.list.BasicList; import skyui.components.list.IListProcessor; import skyui.util.Hash; class FilterDataExtender implements IListProcessor { /* CONSTANTS */ public static var FILTERFLAG_ALL = 0x0000000F; public static var FILTERFLAG_DEFAULT = 0x00000001; public static var FILTERFLAG_GEAR = 0x00000002; public static var FILTERFLAG_AID = 0x00000004; public static var FILTERFLAG_MAGIC = 0x00000008; public static var FILTERFLAG_GROUP_ADD = 0x00000010; public static var FILTERFLAG_GROUP_0 = 0x00000020; // Group N+1 = (GROUP_N << 1) | GROUP_ADD /* PRIVATE VARIABLES */ /* PROPERTIES */ /* INITIALIZATION */ public function FilterDataExtender() { } /* PUBLIC FUNCTIONS */ // @override IListProcessor public function processList(a_list: BasicList): Void { var entryList = a_list.entryList; for (var i = 0; i < entryList.length; i++) { var e = entryList[i]; if (e.skyui_itemDataProcessed) continue; e.skyui_itemDataProcessed = true; processEntry(e); } } /* PRIVATE FUNCTIONS */ private function processEntry(a_entryObject: Object): Void { // ItemID a_entryObject.itemId &= 0xFFFFFFFF; // better safe than sorry var formType = a_entryObject.formType; switch(formType) { case Form.TYPE_ARMOR: case Form.TYPE_AMMO: case Form.TYPE_WEAPON: case Form.TYPE_LIGHT: a_entryObject.filterFlag = FILTERFLAG_GEAR; break; case Form.TYPE_INGREDIENT: case Form.TYPE_POTION: a_entryObject.filterFlag = FILTERFLAG_AID; break; case Form.TYPE_SPELL: case Form.TYPE_SHOUT: case Form.TYPE_SCROLLITEM: a_entryObject.filterFlag = FILTERFLAG_MAGIC; break; case Form.TYPE_BOOK: case Form.TYPE_EFFECTSETTING: default: // This is a default flag to make sure ALL includes everything a_entryObject.filterFlag = FILTERFLAG_DEFAULT; break; } } } ================================================ FILE: src/FavoritesMenu/GroupButton.as ================================================ import gfx.controls.Button; import skyui.util.Translator; class GroupButton extends gfx.controls.Button { /* STAGE ELEMENTS */ public var groupNum: MovieClip; public var itemIcon: MovieClip; /* PROPERTIES */ public var text: String; public var iconLabel: String; private var _groupIndex: Number = 0; public function get groupIndex(): Number { return _groupIndex; } public function set groupIndex(a_index: Number) { _groupIndex = a_index; _filterFlag = (FilterDataExtender.FILTERFLAG_GROUP_0 << groupIndex) | FilterDataExtender.FILTERFLAG_GROUP_ADD; groupNum.gotoAndStop(groupIndex+1); } private var _filterFlag: Number = 0; public function get filterFlag(): Number { return _filterFlag; } /* INITIALIZATION */ public function GroupButton() { super(); text = Translator.translate("$GROUP") + " " + (groupIndex + 1); } } ================================================ FILE: src/FavoritesMenu/GroupDataExtender.as ================================================ import skyui.components.list.BasicList; import skyui.components.list.IListProcessor; class GroupDataExtender implements IListProcessor { /* CONSTANTS */ public static var GROUP_SIZE = 32; /* PRIVATE VARIABLES */ private var _itemIdMap: Object; private var _groupButtons: Array; private var _invalidItems: Array; /* PROPERTIES */ public var groupData: Array; public var mainHandData: Array; public var offHandData: Array; public var iconData: Array; /* INITIALIZATION */ public function GroupDataExtender(a_groupButtons: Array) { groupData = []; mainHandData = []; offHandData = []; iconData = []; _itemIdMap = {}; _invalidItems = []; _groupButtons = a_groupButtons; } /* PUBLIC FUNCTIONS */ // @override IListProcessor public function processList(a_list: BasicList): Void { var groupCount = int(groupData.length / GROUP_SIZE); var clearFlag = 0; for (var c=0; centry, clear group filter flags for (var i = 0; i < entryList.length; i++) { var e = entryList[i]; e.filterFlag &= ~clearFlag; e.mainHandFlag = 0; e.offHandFlag = 0; if (e.itemId != undefined) _itemIdMap[e.itemId] = e; } processGroupData(); processMainHandData(); processOffHandData(); processIconData(); } /* PRIVATE FUNCTIONS */ private function processGroupData(): Void { // Set filterFlags for group membership var c = 0; var curFilterFlag = FilterDataExtender.FILTERFLAG_GROUP_0; for (var i=0; i 0 ? GlobalFunc.Lerp(25, 75, 0, 100, _hungerPerc) : 0; var thirstAlpha = _thirstPerc > 0 ? GlobalFunc.Lerp(25, 75, 0, 100, _thirstPerc) : 0; var fatigueAlpha = _fatiguePerc > 0 ? GlobalFunc.Lerp(25, 75, 0, 100, _fatiguePerc) : 0; var axis1 = _orientation == "vertical" ? "_x" : "_y"; var axis2 = _orientation != "vertical" ? "_x" : "_y"; // 1. position icons _hungerIcon[axis1] = 0; _thirstIcon[axis1] = 0; _fatigueIcon[axis1] = 0; var offset = 0; _visibleIconCount = 0; if (hungerAlpha > 0) { _hungerIcon[axis2] = offset; offset += _iconSize; _hungerIcon.gotoAndStop(_hungerLevel+1); _visibleIconCount++; } else { _hungerIcon[axis2] = 0; } _hungerIcon._alpha = hungerAlpha; if (thirstAlpha > 0) { _thirstIcon[axis2] = offset; offset += _iconSize; _thirstIcon.gotoAndStop(_thirstLevel+1); _visibleIconCount++; } else { _thirstIcon[axis2] = 0; } _thirstIcon._alpha = thirstAlpha; if (fatigueAlpha > 0) { _fatigueIcon[axis2] = offset; offset += _iconSize; _fatigueIcon.gotoAndStop(_fatigueLevel+1); _visibleIconCount++; } else { _fatigueIcon[axis2] = 0; } _fatigueIcon._alpha = fatigueAlpha; invalidateSize(); } } ================================================ FILE: src/HUDWidgets/skyui/widgets/WidgetBase.as ================================================ import skyui.util.Tween; import Shared.GlobalFunc; class skyui.widgets.WidgetBase extends MovieClip { /* CONSTANTS */ private static var MODES: Array = ["All", "Favor", "MovementDisabled", "Swimming", "WarHorseMode", "HorseMode", "InventoryMode", "BookMode", "DialogueMode", "StealthMode", "SleepWaitMode", "BarterMode", "TweenMode", "WorldMapMode", "JournalMode", "CartMode", "VATSPlayback"]; private static var MODEMAP: Object = { all: "All", favor: "Favor", movementdisabled: "MovementDisabled", swimming: "Swimming", warhorsemode: "WarHorseMode", horsemode: "HorseMode", inventorymode: "InventoryMode", bookmode: "BookMode", dialoguemode: "DialogueMode", stealthmode: "StealthMode", sleepwaitmode: "SleepWaitMode", bartermode: "BarterMode", tweenmode: "TweenMode", worldmapmode: "WorldMapMode", journalmode: "JournalMode", cartmode: "CartMode", vatsplayback: "VATSPlayback" }; //private static var CROSSHAIR_MODES: Array = ["All", "Favor", "DialogueMode", "StealthMode", "Swimming", "HorseMode", "WarHorseMode"]; private static var ANCHOR_LEFT: String = "left"; private static var ANCHOR_RIGHT: String = "right"; private static var ANCHOR_CENTER: String = "center"; private static var ANCHOR_TOP: String = "top"; private static var ANCHOR_BOTTOM: String = "bottom"; /* PRIVATE VARIABLES */ private var _rootPath: String = ""; private var _hudMetrics: Object; private var _clientInfo: Object; private var _widgetID: String; private var _widgetHolder: MovieClip; private var __x: Number = 0; private var __y: Number = 0; private var _vAnchor: String = "top"; private var _hAnchor: String = "left"; /* INITIALIZATION */ public function WidgetBase() { _clientInfo = {}; _widgetHolder = _parent; _widgetID = _widgetHolder._name; // Allows for preview in Flash Player if (_global.gfxPlayer) _global.gfxExtensions = true; else _widgetHolder._visible = false; } /* PUBLIC FUNCTIONS */ public function setRootPath(a_path: String): Void { _rootPath = a_path; } public function setHudMetrics(a_hudMetrics: Object): Void { _hudMetrics = a_hudMetrics; } // @Papyrus public function setClientInfo(a_clientString: String): Void { var widget = this; var clientInfo: Object = new Object(); //[ScriptName ] var lBrackIdx: Number = 0; var lInequIdx: Number = a_clientString.indexOf("<"); var lParenIdx: Number = a_clientString.indexOf("("); var rParenIdx: Number = a_clientString.indexOf(")"); clientInfo["scriptName"] = a_clientString.slice(lBrackIdx + 1, lInequIdx - 1); clientInfo["formName"] = a_clientString.slice(lInequIdx + 1, lParenIdx - 1); clientInfo["formID"] = a_clientString.slice(lParenIdx + 1, rParenIdx); widget.clientInfo = clientInfo; } // @Papyrus public function setModes(/* a_visibleMode0: String, a_visibleMode1: String, ... */): Void { var numValidModes: Number = 0; // Clear all modes for (var i=0; i -_hudMetrics.hMin // 1280 -> _hudMetrics.hMax _x = GlobalFunc.Lerp(-_hudMetrics.hMin, _hudMetrics.hMax, 0, 1280, __x); // 0 -> -_hudMetrics.vMin // 720 -> _hudMetrics.vMax _y = GlobalFunc.Lerp(-_hudMetrics.vMin, _hudMetrics.vMax, 0, 720, __y); } } ================================================ FILE: src/HUDWidgets/skyui/widgets/activeeffects/ActiveEffect.as ================================================ import gfx.events.EventDispatcher; import skyui.util.EffectIconMap; import Shared.GlobalFunc; import mx.utils.Delegate; import skyui.util.Tween; class skyui.widgets.activeeffects.ActiveEffect extends MovieClip { /* CONSTANTS */ private static var METER_WIDTH: Number = 15; private static var METER_PADDING: Number = 5; /* PRIVATE VARIABLES */ private var _meter: MovieClip; private var _meterEmptyIdx: Number; private var _meterFullIdx: Number; // Icon private var _iconLoader: MovieClipLoader; private var _icon: MovieClip; private var _iconHolder: MovieClip; private var _iconBaseLabel: String; private var _iconEmblemLabel: String; /* STAGE ELEMENTS */ private var content: MovieClip; private var background: MovieClip; /* PUBLIC VARIABLES */ public var marker: Number; // initObject public var index: Number; public var effectData: Object; public var iconLocation: String; public var effectBaseSize: Number; public var effectSpacing: Number; public var effectFadeInDuration: Number; public var effectFadeOutDuration: Number; public var effectMoveDuration: Number; public var hAnchor: String; public var vAnchor: String; public var orientation: String; /* INITIALIZATION */ public function ActiveEffect() { super(); EventDispatcher.initialize(this); _iconLoader = new MovieClipLoader(); _iconLoader.addListener(this); _iconHolder = content.iconContent; _icon = _iconHolder.createEmptyMovieClip("icon", _iconHolder.getNextHighestDepth()); _icon.noIconLoaded = true; // Is removed when MovieClipLoader loads a clip _width = _height = effectBaseSize; // Force position var p = determinePosition(index); _x = p[0]; _y = p[1]; background._alpha = 0; _iconHolder.iconBackground._alpha = 0; initEffect(); updateEffect(effectData); this._alpha = 0; Tween.LinearTween(this, "_alpha", 0, 100, effectFadeInDuration, null); } /* PUBLIC FUNCTIONS */ // @mixin by gfx.events.EventDispatcher public var dispatchEvent: Function; public var dispatchQueue: Function; public var hasEventListener: Function; public var addEventListener: Function; public var removeEventListener: Function; public var removeAllEventListeners: Function; public var cleanUpEvents: Function; public function updateEffect(a_effectData: Object): Void { effectData = a_effectData; updateMeter(); } public function updatePosition(a_newIndex: Number): Void { index = a_newIndex; var p = determinePosition(index); Tween.LinearTween(this, "_x", this._x, p[0], effectMoveDuration, null); Tween.LinearTween(this, "_y", this._y, p[1], effectMoveDuration, null); } public function remove(a_immediate: Boolean): Void { if (a_immediate == true) { _alpha = 0; dispatchEvent({type: "effectRemoved"}); return; } Tween.LinearTween(this, "_alpha", 100, 0, effectFadeOutDuration, Delegate.create(this, function() {dispatchEvent({type: "effectRemoved"})})); } /* PRIVATE FUNCTIONS */ private function initEffect(): Void { var iconData = EffectIconMap.lookupIconLabel(effectData); _iconBaseLabel = iconData.baseLabel; _iconEmblemLabel = iconData.emblemLabel; if (_iconBaseLabel == "default_effect" || _iconBaseLabel == undefined || _iconBaseLabel == "") { skyui.util.Debug.log("[SkyUI Active Effects]: Missing icon"); for (var s: String in effectData) skyui.util.Debug.log("\t\t" + s + ": " + effectData[s]); } _iconHolder._width = _iconHolder._height = (background._width - METER_PADDING - METER_WIDTH); _iconHolder._y = (background._height - _iconHolder._height) / 2; if (effectData.duration - effectData.elapsed > 1) initMeter(); _iconLoader.loadClip(iconLocation, _icon); } private function initMeter(): Void { _meter = content.attachMovie("SimpleMeter", "meter", content.getNextHighestDepth(), {_x: (background._width - METER_WIDTH), _y: _iconHolder._y, _width: METER_WIDTH, _height: _iconHolder._height}); _meter.background._alpha = 50; _meter.gotoAndStop("Empty"); _meterEmptyIdx = _meter._currentframe; _meter.gotoAndStop("Full"); _meterFullIdx = _meter._currentframe; } private function updateMeter(): Void { if (_meter == undefined) // Constant effects, no timer (e.g. Healing) return; var newPercent: Number = (100 * (effectData.duration - effectData.elapsed)) / effectData.duration; newPercent = Math.min(100, Math.max(newPercent, 0)); var meterFrame: Number = Math.floor(GlobalFunc.Lerp(_meterEmptyIdx, _meterFullIdx, 0, 100, newPercent)); _meter.gotoAndStop(meterFrame); } private function onLoadInit(a_mc: MovieClip): Void { // Fix for spamming effects causing MovieClipLoader to do strainge things // (a_mc === _icon) == true, but a_mc.noIconLoaded == undefined whereas _icon.noIconLoaded == true; if (_icon.noIconLoaded == true) { remove(true); return; } _icon._x = 0; _icon._y = 0; // TODO, make it scale w/ icon size. All the icons we use are 128*128 so it doesn't matter _icon._width = _icon._height = _iconHolder.iconBackground._width; _icon.baseIcon.gotoAndStop(_iconBaseLabel); _icon.emblemIcon.gotoAndStop(_iconEmblemLabel); updateEffect(effectData); } private function onLoadError(a_mc: MovieClip, a_errorCode: String): Void { var errorTextField: TextField = _iconHolder.createTextField("ErrorTextField", _icon.getNextHighestDepth(), 0, 0, _iconHolder.iconBackground._width, _iconHolder.iconBackground._height); errorTextField.verticalAlign = "center"; errorTextField.textAutoSize = "fit"; errorTextField.multiLine = true; var tf: TextFormat = new TextFormat(); tf.align = "center"; tf.color = 0xFFFFFF; tf.indent = 20; tf.font = "$EverywhereBoldFont"; errorTextField.setNewTextFormat(tf); errorTextField.text = "No Icon\nSource"; } private function determinePosition(a_index: Number): Array { var newX: Number = 0; var newY: Number = 0; // Orientation is the orientation of the EffectsGroups if (orientation == "vertical") { // Orientation vertical means that the ActiveEffect is in a column, so the next effect needs to be added either above, or below if (vAnchor == "bottom") { // Widget is anchored vertically to the bottom of the stage, so need to add next ActiveEffect above newY = -(index * (effectBaseSize + effectSpacing)); } else { newY = +(index * (effectBaseSize + effectSpacing)); } } else { // Orientation horizontal means that the ActiveEffect is in a row, so the next effect needs to be added either to the left, or right if (hAnchor == "right") { // Widget is anchored horizontally to the right of the stage, so need to add next ActiveEffect to the left newX = -(index * (effectBaseSize + effectSpacing)); } else { newX = +(index * (effectBaseSize + effectSpacing)); } } return [newX, newY]; } private function parseTime(a_s: Number): String { var s: Number = Math.floor(a_s); var m: Number = 0; var h: Number = 0; var d: Number = 0; if (s >= 60) { m = Math.floor(s / 60); s = s % 60; } if (m >= 60) { h = Math.floor(m / 60); m = m % 60; } if (h >= 24) { d = Math.floor(h / 24); h = h % 24; } return ((d != 0 ? (d + "d ") : "") + (h != 0 || d ? (h + "h ") : "") + (m != 0 || d || h ? (m + "m ") : "") + (s + "s")); } } ================================================ FILE: src/HUDWidgets/skyui/widgets/activeeffects/ActiveEffectsGroup.as ================================================ import gfx.events.EventDispatcher; import mx.utils.Delegate; import skyui.util.Tween; class skyui.widgets.activeeffects.ActiveEffectsGroup extends MovieClip { /* PRIVATE VARIABLES */ private var _effectsArray: Array /* PUBLIC VARIABLES */ // initObject public var index: Number; public var iconLocation: String; public var effectBaseSize: Number; public var effectSpacing: Number; public var effectFadeInDuration: Number; public var effectFadeOutDuration: Number; public var effectMoveDuration: Number; public var hAnchor: String; public var vAnchor: String; public var orientation: String; /* INITIALIZATION */ public function ActiveEffectsGroup() { super(); EventDispatcher.initialize(this); _effectsArray = new Array(); var p = determinePosition(index); _x = p[0]; _y = p[1]; } /* PUBLIC FUNCTIONS */ // @mixin by gfx.events.EventDispatcher public var dispatchEvent: Function; public var dispatchQueue: Function; public var hasEventListener: Function; public var addEventListener: Function; public var removeEventListener: Function; public var removeAllEventListeners: Function; public var cleanUpEvents: Function; /* PROPERTIES */ public function get length(): Number { return _effectsArray.length; } /* PUBLIC FUNCTIONS */ public function addEffect(a_effectData: Object): MovieClip { var effectIdx = _effectsArray.length; var initObject = { index: _effectsArray.length, effectData: a_effectData, iconLocation: iconLocation, effectBaseSize: effectBaseSize, effectSpacing: effectSpacing, effectFadeInDuration: effectFadeInDuration, effectFadeOutDuration: effectFadeOutDuration, effectMoveDuration: effectMoveDuration, hAnchor: hAnchor, vAnchor: vAnchor, orientation: orientation }; var effectClip = attachMovie("ActiveEffect", a_effectData.id, getNextHighestDepth(), initObject); effectClip.addEventListener("effectRemoved", this, "onEffectRemoved"); _effectsArray.push(effectClip); return effectClip; } public function updatePosition(a_newIndex: Number): Void { index = a_newIndex; var p = determinePosition(index); Tween.LinearTween(this, "_x", this._x, p[0], effectMoveDuration, null); Tween.LinearTween(this, "_y", this._y, p[1], effectMoveDuration, null); } /* PRIVATE FUNCTIONS */ private function onEffectRemoved(event: Object): Void { var removedEffectClip: MovieClip = event.target; var effectIdx: Number = removedEffectClip.index; _effectsArray.splice(effectIdx, 1); removedEffectClip.removeMovieClip(); if (_effectsArray.length > 0){ var effectClip: MovieClip; for (var i: Number = effectIdx; i < _effectsArray.length; i++) { effectClip = _effectsArray[i]; effectClip.updatePosition(i); } } else { // If the group had a background, for example, we'd call // this.remove() // which would fade out the group then, onComplete, call // dispatchEvent({type: "groupRemoved"}); dispatchEvent({type: "groupRemoved"}); } } private function determinePosition(a_index: Number): Array { var newX: Number = 0; var newY: Number = 0; // Orientation is the orientation of the EffectsGroups if (orientation == "vertical") { // Orientation vertical means that the EffectsGroup acts as a column, so the next group needs to be added either to the left, or right if (hAnchor == "right") { // Widget is anchored horizontally to the right of the stage, so need to add next EffectsGroup to the left newX = -(effectSpacing + index * (effectBaseSize + effectSpacing)); } else { newX = +(effectSpacing + index * (effectBaseSize + effectSpacing)); } } else { // Orientation horizontal means that the EffectsGroup acts as a row, so the next group needs to be added either above, or below if (vAnchor == "bottom") { // Widget is anchored vertically to the bottom of the stage, so need to add next EffectsGroup above newY = -(effectSpacing + index * (effectBaseSize + effectSpacing)); } else { newY = +(effectSpacing + index * (effectBaseSize + effectSpacing)); } } return [newX, newY]; } // Not needed, see onEffectRemoved(); /* private function remove(): Void { Tween.LinearTween(this, "_alpha", 100, 0, effectFadeOutDuration, Delegate.create(this, function() {dispatchEvent({type: "groupRemoved"})})); } */ } ================================================ FILE: src/HUDWidgets/skyui/widgets/activeeffects/ActiveEffectsWidget.as ================================================ import skyui.widgets.WidgetBase; import skyui.widgets.activeeffects.ActiveEffectsGroup; import skyui.widgets.activeeffects.ActiveEffect; import skyui.defines.Magic; import gfx.events.EventDispatcher; class skyui.widgets.activeeffects.ActiveEffectsWidget extends WidgetBase { /* CONSTANTS */ private static var EFFECT_SPACING: Number = 5.00; private static var EFFECT_FADE_IN_DURATION: Number = 0.25; private static var EFFECT_FADE_OUT_DURATION: Number = 0.75; private static var EFFECT_MOVE_DURATION: Number = 1.00; private static var ICON_SOURCE: String = "skyui/icons_effect_psychosteve.swf"; // config private var _effectBaseSize: Number; // "small" = 32.0, "medium" = 48.0, "large" = 64.0, Default: "medium" private var _groupEffectCount: Number; private var _orientation: String; /* PRIVATE VARIABLES */ // Phases between 0 and 1 during update intervals private var _marker: Number = 1; private var _sortFlag: Boolean = true; private var _effectsHash: Object; private var _effectsGroups: Array; private var _intervalId: Number; private var _updateInterval: Number = 150; private var _enabled: Boolean; private var _minTimeLeft: Number = 180; /* PUBLIC VARIABLES */ // Passed from SKSE public var effectDataArray: Array; public function ActiveEffectsWidget() { super(); EventDispatcher.initialize(this); _effectsHash = new Object(); _effectsGroups = new Array(); effectDataArray = new Array(); } /* PUBLIC FUNCTIONS */ // @mixin by gfx.events.EventDispatcher public var dispatchEvent: Function; public var dispatchQueue: Function; public var hasEventListener: Function; public var addEventListener: Function; public var removeEventListener: Function; public var removeAllEventListeners: Function; public var cleanUpEvents: Function; // @overrides WidgetBase public function getWidth(): Number { return _effectBaseSize; } // @overrides WidgetBase public function getHeight(): Number { return _effectBaseSize; } // @Papyrus public function initNumbers(a_enabled: Boolean, a_effectSize: Number, a_groupEffectCount: Number, a_minTimeLeft: Number): Void { _enabled = a_enabled; _effectBaseSize = a_effectSize; _groupEffectCount = a_groupEffectCount; _minTimeLeft = a_minTimeLeft; } // @Papyrus public function initStrings(a_orientation: String): Void { _orientation = a_orientation.toLowerCase(); } // @Papyrus public function initCommit(): Void { invalidateSize(); if (_enabled) drawEffects(); } // @Papyrus public function setEffectSize(a_effectBaseSize: Number): Void { _effectBaseSize = a_effectBaseSize; invalidateSize(); invalidateEffects(); } // @Papyrus public function setGroupEffectCount(a_groupEffectCount: Number): Void { _groupEffectCount = a_groupEffectCount; invalidateEffects(); } // @Papyrus public function setEnabled(a_enabled: Boolean): Void { _enabled = a_enabled; if (_enabled) { eraseEffects(); drawEffects(); } else { eraseEffects(); } } // @Papyrus public function setOrientation(a_orientation: String): Void { _orientation = a_orientation.toLowerCase(); invalidateEffects(); } // @Papyrus public function setMinTimeLeft(a_seconds: Number): Void { _minTimeLeft = a_seconds; } /* PRIVATE FUNCTIONS */ // @override WidgetBase private function updatePosition(): Void { super.updatePosition(); invalidateEffects(); } private function onIntervalUpdate(): Void { effectDataArray.splice(0); skse.RequestActivePlayerEffects(effectDataArray); if (_sortFlag) { // Make sure oldest effects are at the top effectDataArray.sortOn("elapsed", Array.DESCENDING | Array.NUMERIC); _sortFlag = false; } for (var i=0; i < effectDataArray.length; i++) { var effectData = effectDataArray[i]; // Ignore if time left is > minimum, i.e. for blessings that last several hours if (_minTimeLeft != 0 && _minTimeLeft < (effectData.duration - effectData.elapsed)) continue; var effectClip: ActiveEffect = _effectsHash[effectData.id]; if (!effectClip) { // New Effect var effectsGroup = getFreeEffectsGroup(); effectClip = effectsGroup.addEffect(effectData); _effectsHash[effectData.id] = effectClip; } else { // Existing Effect effectClip.updateEffect(effectData); } effectClip.marker = _marker; } for (var s: String in _effectsHash) { var effectClip = _effectsHash[s]; if (effectClip.marker != _marker) { effectClip.remove(); delete(_effectsHash[s]); } } _marker = 1 - _marker; } private function getFreeEffectsGroup(): MovieClip { // Existing group has free slots? for (var i=0; i < _effectsGroups.length; i++) { var group = _effectsGroups[i]; if (group.length < _groupEffectCount) return group; } // No free slots, create new group var newGroupIdx = _effectsGroups.length; var initObject = { index: newGroupIdx, iconLocation: _rootPath + ICON_SOURCE, effectBaseSize: _effectBaseSize, effectSpacing: EFFECT_SPACING, effectFadeInDuration: EFFECT_FADE_IN_DURATION, effectFadeOutDuration: EFFECT_FADE_OUT_DURATION, effectMoveDuration: EFFECT_MOVE_DURATION, hAnchor: _hAnchor, vAnchor: _vAnchor, orientation: _orientation }; // Name needs to be unique so append getNextHighestDepth() to the name var newGroup = attachMovie("ActiveEffectsGroup", "effectsGroup" + getNextHighestDepth(), getNextHighestDepth(), initObject); newGroup.addEventListener("groupRemoved", this, "onGroupRemoved"); _effectsGroups.push(newGroup); return newGroup; } // Called from ActiveEffectsGroup public function onGroupRemoved(event: Object): Void { var removedGroup: MovieClip = event.target; var groupIdx: Number = removedGroup.index; _effectsGroups.splice(groupIdx, 1); removedGroup.removeMovieClip(); var effectsGroup: MovieClip; for (var i: Number = groupIdx; i < _effectsGroups.length; i++) { effectsGroup = _effectsGroups[i]; effectsGroup.updatePosition(i); //Sets new index } } private function invalidateEffects(): Void { if (!_enabled) return; eraseEffects(); // Logic here to check if in the right HUD Mode, avoid unnecessary updates? drawEffects(); } private function eraseEffects(): Void { clearInterval(_intervalId); var effectsGroup: MovieClip; for (var i: Number = 0; i < _effectsGroups.length; i++) { effectsGroup = _effectsGroups[i]; effectsGroup.removeMovieClip(); } _effectsHash = new Object(); _effectsGroups = new Array(); } private function drawEffects(): Void { clearInterval(_intervalId); _sortFlag = true; _intervalId = setInterval(this, "onIntervalUpdate", _updateInterval); } } ================================================ FILE: src/HUDWidgets/skyui/widgets/arrowcount/ArrowCountWidget.as ================================================ import skyui.widgets.WidgetBase; class skyui.widgets.arrowcount.ArrowCountWidget extends WidgetBase { /* STAGE ELEMENTS */ public var countText: TextField; /* INITIALIZATION */ public function ArrowCountWidget() { super(); _visible = false; countText.text = "0"; } /* PUBLIC FUNCTIONS */ // @overrides WidgetBase public function getWidth(): Number { return _width; } // @overrides WidgetBase public function getHeight(): Number { return _height; } // @Papyrus public function setVisible(a_visible: Boolean): Void { _visible = a_visible; } // @Papyrus public function setCount(a_count: Number): Void { countText.text = String(a_count); } } ================================================ FILE: src/HUDWidgets/skyui/widgets/meter/MeterWidget.as ================================================ import skyui.widgets.WidgetBase; import skyui.components.Meter; class skyui.widgets.meter.MeterWidget extends WidgetBase { /* PRIVATE VARIABLES */ private var _initialized: Boolean = false; private var __width; private var __height; /* STAGE ELEMENTS */ public var meter: Meter; /* INITIALIZATION */ public function MeterWidget() { super(); meter._visible = false; } // @papyrus public function initNumbers(a_width: Number, a_height: Number, a_lightColor: Number, a_darkColor: Number, a_flashColor: Number, a_percent: Number, a_fillSpeed: Number, a_emptySpeed: Number): Void { setSize(a_width, a_height); setColors(a_lightColor, a_darkColor); setFlashColor(a_flashColor); setPercent(a_percent, true); //a_fillSpeed; //a_emptySpeed; } // @papyrus public function initStrings(a_fillDirection: String): Void { meter.setFillDirection(a_fillDirection, true); //Reset fill Direction and force percentage back } // @papyrus public function initCommit(): Void { meter._visible = true; _initialized = true; } // @papyrus public function setWidth(a_width: Number): Void { meter.width = a_width; __width = meter.width; invalidateSize(); } // @papyrus public function setHeight(a_height: Number): Void { meter.height = a_height; __height = meter.height; invalidateSize(); } // @papyrus public function setSize(a_width: Number, a_height: Number): Void { meter.setSize(a_width, a_height); __width = meter.width; __height = meter.height; invalidateSize(); } // @papyrus public function setColor(a_lightColor: Number): Void { meter.color = a_lightColor; } // @papyrus public function setColors(a_lightColor: Number, a_darkColor: Number, a_flashColor: Number): Void { meter.setColors(a_lightColor, a_darkColor); } // @papyrus public function setFlashColor(a_flashColor: Number): Void { meter.flashColor = a_flashColor; } // @papyrus public function setFillDirection(a_fillDirection: String): Void { meter.fillDirection = a_fillDirection; } // @papyrus public function setPercent(a_percent: Number, a_force: Boolean): Void { meter.setPercent(a_percent, a_force); } // @papyrus public function startFlash(a_force: Boolean): Void { meter.startFlash(a_force); } /* PRIVATE FUNCTIONS */ // @Overrides WidgetBase private function getWidth(): Number { return __width; } // @Overrides WidgetBase private function getHeight(): Number { return __height; } } ================================================ FILE: src/HUDWidgets/skyui/widgets/minimap/MiniMapWidget.as ================================================ import gfx.io.GameDelegate; import skyui.widgets.WidgetBase; import skyui.util.GlobalFunctions; class skyui.widgets.minimap.MiniMapWidget extends WidgetBase { /* PRIVATE VARIABLES */ private var _initialized: Boolean = false; private var _enabled: Boolean = false; /* STAGE ELEMENTS */ var playerMarker: MovieClip /* INITIALIZATION */ public function MeterWidget() { super(); } // @papyrus public function initNumbers(a_enabled: Boolean): Void { _enabled = a_enabled; } // @papyrus public function initCommit(): Void { installHooks(); _initialized = true; } // @Papyrus public function setEnabled(a_enabled: Boolean): Void { _enabled = a_enabled; } // @papyrus public function setWidth(a_width: Number): Void { _width = a_width; invalidateSize(); } // @papyrus public function setHeight(a_height: Number): Void { _height = a_height; invalidateSize(); } // @papyrus public function setSize(a_width: Number, a_height: Number): Void { _width = a_width; _height = a_height; invalidateSize(); } /* PRIVATE FUNCTIONS */ private function installHooks(): Void { if (GlobalFunctions.hookFunction(_root.HUDMovieBaseInstance, "SetCompassAngle", this, "setAngle")) skyui.util.Debug.log("Hooked _root.HUDMovieBaseInstance.SetCompassAngle()"); else skyui.util.Debug.log("Could not hook _root.HUDMovieBaseInstance.SetCompassAngle()"); } private function setAngle(a_playerAngle: Number, a_compassAngle: Number, a_showCompass: Boolean) { if (!_enabled) return; playerMarker._rotation = a_playerAngle; } } ================================================ FILE: src/HUDWidgets/skyui/widgets/status/StatusWidget.as ================================================ import skyui.widgets.WidgetBase; import Shared.GlobalFunc; import flash.geom.Transform; import flash.geom.ColorTransform; import flash.geom.Matrix; class skyui.widgets.status.StatusWidget extends WidgetBase { /* CONSTANTS */ public static var ALIGN_LEFT: String = "left"; public static var ALIGN_RIGHT: String = "right"; public static var ALIGN_CENTER: String = "center"; public static var ALIGN_BORDER: String = "border"; public static var FILL_LEFT: String = "left"; public static var FILL_RIGHT: String = "right"; public static var FILL_CENTER: String = "center"; /* PRIVATE VARIABLES */ public var _labelTextField: TextField; public var _valueTextField: TextField; public var _icon: MovieClip; public var _meter: MovieClip; public var _meterFrameContent: MovieClip; public var _meterFillContent: MovieClip; public var _meterFlashAnim: MovieClip; public var _meterBarAnim: MovieClip; public var _meterBar: MovieClip; private var _iconLoader: MovieClipLoader; // Widget data private var _widgetWidth: Number; private var _labelText: String; private var _labelTextFont: String; private var _labelTextColor: Number; private var _labelTextAlpha: Number; private var _labelTextSize: Number; private var _valueText: String; private var _valueTextFont: String; private var _valueTextColor: Number; private var _valueTextAlpha: Number; private var _valueTextSize: Number; private var _paddingTop: Number; private var _paddingRight: Number; private var _paddingBottom: Number; private var _paddingLeft: Number; private var _borderColor: Number; private var _borderAlpha: Number; private var _borderRounded: Boolean; private var _borderWidth: Number; private var _backgroundColor: Number; private var _backgroundAlpha: Number; private var _iconSource: String; private var _iconName: String; private var _iconSize: Number; private var _iconColor: Number; private var _iconAlpha: Number; private var _iconSpacing: Number; private var _textAlign: String; private var _iconAlign: String; private var _meterCurrentPercent: Number; private var _meterTargetPercent: Number; private var _meterEmptyIdx: Number; private var _meterFullIdx: Number; private var _meterSpacing: Number; private var _meterScale: Number; private var _meterFillMode: String; private var _meterFillSpeed: Number; private var _meterEmptySpeed: Number; private var _meterColorA: Number; private var _meterColorB: Number; private var _meterAlpha: Number; private var _meterFlashColor: Number; private var _iconLoaded: Boolean; /* STAGE ELEMENTS */ public var border: MovieClip; public var background: MovieClip; public var content: MovieClip; /* INITIALIZATION */ public function StatusWidget() { super(); _labelTextField = content.labelTextField; _valueTextField = content.valueTextField; _icon = content.icon; _meter = content.meterContent; _meterFrameContent = _meter.meterFrameHolder.meterFrameContent _meterFillContent = _meter.meterFillHolder.meterFillContent; _meterFlashAnim = _meterFrameContent.meterFlashAnim; _meterBarAnim = _meterFillContent.meterBarAnim; _meterBar = _meterBarAnim.meterBar; _labelTextField.autoSize = "left"; _labelTextField.textAutoSize = "none"; _labelTextField.text = ""; _valueTextField.autoSize = "left"; _valueTextField.textAutoSize = "none"; _valueTextField.text = ""; _meter._visible = false; _iconLoader = new MovieClipLoader(); _iconLoader.addListener(this); _iconLoaded = false; } // @override WidgetBase public function onLoad(): Void { super.onLoad(); // For testing in flash /*initNumbers(200, 0x0099000, 100, 5, 0xFF00FF, 100, 1, 5, 5, 5, 5, 0x00FFFF, 48, 0x00FFFF, 22, 20, 0x0F55F0, 100, 5, 5, 50, 0x003300, 0x339966, 50, 0x009900); initStrings("$EverywhereFont", "$EverywhereFont", "Lab", "Val", ALIGN_BORDER, "../skyui/skyui_icons_psychosteve.swf", "weapon_sword", ALIGN_RIGHT, FILL_CENTER); initCommit(); setInterval(this, "testFunc", 1000);//*/ } // @override MovieClipLoader public function onLoadInit(a_icon: MovieClip): Void { _iconLoaded = true; updateIcon(); updateBackgroundSize(); updateElementPositions(); } // @override MovieClipLoader public function onLoadError(a_icon:MovieClip, a_errorCode: String): Void { // TODO skse.SendModEvent("SKIWF_widgetError", "IconLoadFailure", Number(_widgetID)); //"WidgetID: " + _widgetID + " IconLoadError: " + a_errorCode + " (" + _iconSource + ")"); unloadIcon(); } var st: Number = 0; private function testFunc() { st++; trace(st) if (st == 1) { setMeterPercent(0) setWidth(100); setLabelText(""); } else if (st == 2) { setWidth(300); startMeterFlash(); setMeterFillMode("center"); setIconSource("") } else if (st == 3) { setBackgroundColor(0xFF0000); setValueTextColor(0x00FFFF); setLabelTextColor(0xFF00FF); } else if (st == 4) { setBackgroundAlpha(25); setIconSource("../skyui/skyui_icons_psychosteve.swf"); } else if (st == 5) { setBorderColor(0xFFFF00); } else if (st == 6) { setBorderWidth(10); } else if (st == 7) { setBorderAlpha(25); } else if (st == 8) { setBorderRounded(false); } else if (st == 9) { setLabelText("Test Label"); } else if (st == 10) { setValueText("Test Value"); } else if (st == 11) { setLabelTextFont("$EverywhereMediumFont"); setValueTextFont("$EverywhereMediumFont"); setLabelTextSize(26); setValueTextSize(36); } else if (st == 12) { setValueTextColor(0x00FF00); setLabelTextColor(0x00FFFF); } else if (st == 13) { setTextAlign(ALIGN_LEFT); } else if (st == 14) { setTextAlign(ALIGN_RIGHT); } else if (st == 15) { setTextAlign(ALIGN_CENTER); } else if (st == 16) { setTextAlign(ALIGN_BORDER); } else if (st == 17) { setTexts("Test Labelsss", "Tost"); setIconName("weapon_bow"); setLabelTextSize(22); setValueTextSize(22); } else if (st == 18) { setIconSize(64); } else if (st == 19) { setIconAlign(ALIGN_LEFT); st = 12; } } /* PAPYRUS INTERFACE */ // @Papyrus public function initNumbers(a_widgetWidth: Number, a_backgroundColor: Number, a_backgroundAlpha: Number, a_borderWidth: Number, a_borderColor: Number, a_borderAlpha: Number, a_borderRounded: Boolean, a_paddingTop: Number, a_paddingRight: Number, a_paddingBottom: Number, a_paddingLeft: Number, a_labelTextColor: Number, a_labelTextSize: Number, a_valueTextColor: Number, a_valueTextSize: Number, a_iconSize: Number, a_iconColor: Number, a_iconAlpha: Number, a_iconSpacing: Number, a_meterScale: Number, a_meterColorA: Number, a_meterColorB: Number, a_meterAlpha: Number, a_meterSpacing: Number, a_meterFlashColor: Number): Void { _widgetWidth = a_widgetWidth; setBackgroundColor(a_backgroundColor); setBackgroundAlpha(a_backgroundAlpha); _borderWidth = a_borderWidth; _borderColor = a_borderColor; _borderAlpha = a_borderAlpha; _borderRounded = a_borderRounded; _paddingTop = a_paddingTop; _paddingRight = a_paddingRight; _paddingBottom = a_paddingBottom; _paddingLeft = a_paddingLeft; setLabelTextColor(a_labelTextColor); _labelTextSize = a_labelTextSize; setValueTextColor(a_valueTextColor); _valueTextSize = a_valueTextSize; _iconSize = a_iconSize; _iconColor = a_iconColor; _iconAlpha = a_iconAlpha; _iconSpacing = a_iconSpacing; _meterScale = a_meterScale; _meterColorA = a_meterColorA; _meterColorB = a_meterColorB; _meterAlpha = a_meterAlpha; _meterSpacing = a_meterSpacing; _meterFlashColor = a_meterFlashColor; } // @Papyrus public function initStrings(a_labelText: String, a_labelTextFont: String, a_valueText: String, a_valueTextFont: String, a_textAlign: String, a_iconSource: String, a_iconName: String, a_iconAlign: String, a_meterFillMode: String): Void { _labelTextField.text = _labelText = a_labelText; _labelTextFont = a_labelTextFont; _valueTextField.text = _valueText = a_valueText; _valueTextFont = a_valueTextFont; _textAlign = a_textAlign.toLowerCase(); _iconSource = a_iconSource; _iconName = a_iconName; _iconAlign = a_iconAlign.toLowerCase(); _meterFillMode = a_meterFillMode.toLowerCase(); } // @Papyrus public function initCommit(): Void { loadIcon(); updateLabelTextFormat(); updateValueTextFormat(); updateMeterFillMode(); updateBackgroundSize(); updateElementPositions(); onEnterFrame = updateMeter; } // @Papyrus public function setWidth(a_val: Number): Void { if (_widgetWidth == a_val) return; _widgetWidth = a_val; updateBackgroundSize(); updateElementPositions(); } // @Papyrus public function setBackgroundColor(a_val: Number): Void { if (_backgroundColor == a_val) return; _backgroundColor = a_val; var tf: Transform = new Transform(background); var colorTf: ColorTransform = new ColorTransform(); colorTf.rgb = _backgroundColor; tf.colorTransform = colorTf; } // @Papyrus public function setBackgroundAlpha(a_val: Number): Void { if (_backgroundAlpha == a_val) return; background._alpha = _backgroundAlpha = a_val; } // @Papyrus public function setBorderWidth(a_val: Number): Void { if (_borderWidth == a_val && border) return; _borderWidth = a_val; redrawBorder(); } // @Papyrus public function setBorderColor(a_val: Number): Void { if (_borderColor == a_val && border) return; _borderColor = a_val; if (border) { var tf: Transform = new Transform(border); var colorTf: ColorTransform = new ColorTransform(); colorTf.rgb = _borderColor; tf.colorTransform = colorTf; } else { redrawBorder(); } } // @Papyrus public function setBorderAlpha(a_val: Number): Void { if (_borderAlpha == a_val && border) return; _borderAlpha = a_val; if (border) border._alpha = a_val; else redrawBorder(); } // @Papyrus public function setBorderRounded(a_val: Boolean): Void { if (_borderRounded == a_val && border) return; _borderRounded = a_val; redrawBorder(); } // @Papyrus public function setLabelTextColor(a_val: Number): Void { if (_labelTextColor == a_val) return; _labelTextColor = _valueTextField.textColor = a_val; } // @Papyrus public function setLabelTextSize(a_val: Number): Void { if(_labelTextSize == a_val) return; _labelTextSize = a_val; updateLabelTextFormat(); updateBackgroundSize(); updateElementPositions(); } // @Papyrus public function setValueTextColor(a_val: Number): Void { if(_valueTextColor == a_val) return; _valueTextColor = _valueTextField.textColor = a_val; updateValueTextFormat(); } // @Papyrus public function setValueTextSize(a_val: Number): Void { if(_valueTextSize == a_val) return _valueTextSize = a_val; updateValueTextFormat(); updateBackgroundSize(); updateElementPositions(); } // @Papyrus public function setIconSize(a_val: Number): Void { if (_iconSize == a_val) return; _iconSize = a_val; updateIcon(); updateBackgroundSize(); updateElementPositions(); } // @Papyrus public function setIconColor(a_val: Number): Void { if (_iconColor == a_val) return; _iconColor = a_val; updateIcon(); } // @Papyrus public function setIconAlpha(a_val: Number): Void { if (_iconAlpha == a_val) return; _iconAlpha = a_val; updateIcon(); } // @Papyrus public function setIconSpacing(a_val: Number): Void { if (_iconSpacing == a_val) return; _iconSpacing = a_val; updateElementPositions(); } // @Papyrus public function setMeterScale(a_meterScale: Number): Void { if (_meterScale == a_meterScale) return; _meterScale = a_meterScale; updateBackgroundSize(); updateElementPositions(); } // @Papyrus public function setMeterAlpha(a_meterAlpha: Number): Void { if (_meterAlpha == a_meterAlpha) return; _meter._alpha = _meterAlpha = a_meterAlpha; } // @Papyrus public function setMeterSpacing(a_meterSpacing: Number): Void { if (_meterSpacing == a_meterSpacing) return; _meterSpacing = a_meterSpacing; updateBackgroundSize(); updateElementPositions(); } // @Papyrus public function setMeterFlashColor(a_meterFlashColor: Number): Void { if (_meterFlashColor == a_meterFlashColor) return; _meterFlashColor = a_meterFlashColor; updateMeterFlashColor(); } // @Papyrus public function setLabelText(a_val: String): Void { if (_labelText == a_val) return _labelTextField.text = _labelText = a_val; updateBackgroundSize(); updateElementPositions(); } // @Papyrus public function setLabelTextFont(a_val: String): Void { if (_labelTextFont == a_val) return; _labelTextFont = a_val; updateLabelTextFormat(); updateBackgroundSize(); updateElementPositions(); } // @Papyrus public function setValueText(a_val: String): Void { if(_valueText == a_val) return; _valueTextField.text = _valueText = a_val; updateBackgroundSize(); updateElementPositions(); } // @Papyrus public function setValueTextFont(a_val: String): Void { if(_valueTextFont == a_val) return; _valueTextFont = a_val; updateValueTextFormat(); updateBackgroundSize(); updateElementPositions(); } // @Papyrus public function setTextAlign(a_val: String): Void { if (_textAlign == a_val.toLowerCase()) return; _textAlign = a_val.toLowerCase(); updateElementPositions(); } // @Papyrus public function setIconSource(a_iconSource: String, a_initIconName: String): Void { if (_iconSource == a_iconSource) return; _iconSource = a_iconSource; if (a_initIconName) _iconName = a_initIconName; if (_iconSource == "") unloadIcon(); else loadIcon(); } // @Papyrus public function setIconName(a_iconName: String): Void { if (_iconName == a_iconName) return; _iconName = a_iconName; updateIcon(); } // @Papyrus public function setIconAlign(a_val: String): Void { if (_iconAlign == a_val.toLowerCase()) return; _iconAlign = a_val.toLowerCase(); updateElementPositions(); } // @Papyrus public function setMeterFillMode(a_meterFillMode: String): Void { if (_meterFillMode == a_meterFillMode.toLowerCase()) return; _meterFillMode = a_meterFillMode.toLowerCase(); updateMeterFillMode(); } // @Papyrus public function setPadding(a_paddingTop: Number, a_paddingRight: Number, a_paddingBottom: Number, a_paddingLeft: Number): Void { if (_paddingTop == a_paddingTop && _paddingRight == a_paddingRight && _paddingBottom == a_paddingBottom && _paddingLeft == a_paddingLeft) return; _paddingTop = a_paddingTop; _paddingBottom = a_paddingBottom; _paddingRight = a_paddingRight; _paddingLeft = a_paddingLeft; updateBackgroundSize(); updateElementPositions(); } // @Papyrus public function setTexts(a_labelText: String, a_valueText: String): Void { if(_labelText == a_labelText && _valueText == a_valueText) return; _labelTextField.text = _labelText = a_labelText; _valueTextField.text = _valueText = a_valueText; updateBackgroundSize(); updateElementPositions(); } // @Papyrus public function setMeterColors(a_meterColorA: Number, a_meterColorB: Number): Void { if (_meterColorA == a_meterColorA && _meterColorB == a_meterColorB) return; _meterColorA = a_meterColorA; _meterColorB = a_meterColorB; drawMeterGradient(); } // @Papyrus public function setMeterPercent(a_percent: Number, a_force: Boolean): Void { _meterTargetPercent = Math.min(100, Math.max(a_percent, 0)); if (a_force) { _meterCurrentPercent = _meterTargetPercent; var meterFrame: Number = Math.floor(GlobalFunc.Lerp(_meterEmptyIdx, _meterFullIdx, 0, 100, _meterCurrentPercent)); _meterBarAnim.gotoAndStop(meterFrame); } } // @Papyrus public function startMeterFlash(a_force: Boolean): Void { if (_meterFlashAnim.meterFlashing && !a_force) // Set on the timeline return; _meterFlashAnim.gotoAndPlay("StartFlash"); } /* PRIVATE FUNCTIONS */ private function updateLabelTextFormat(): Void { var tf: TextFormat = _labelTextField.getTextFormat(); tf.font = _labelTextFont; tf.size = _labelTextSize; _labelTextField.setTextFormat(tf); _labelTextField.setNewTextFormat(tf); } private function updateValueTextFormat(): Void { var tf: TextFormat = _valueTextField.getTextFormat(); tf.font = _valueTextFont; tf.size = _valueTextSize; _valueTextField.setTextFormat(tf); _valueTextField.setNewTextFormat(tf); } private function updateBackgroundSize(): Void { var labelTextFieldHeight: Number = (_labelText != "") ? _labelTextField._height : 0; var valueTextFieldHeight: Number = (_valueText != "") ? _valueTextField._height : 0; var iconSize: Number = (_iconLoaded) ? _iconSize : 0; var maxIconTextHeight: Number = Math.max(labelTextFieldHeight, Math.max(valueTextFieldHeight, iconSize)); var meterHeight: Number = (_meterScale > 0) ? (_meterFrameContent._height * _meterScale/100) : 0; var meterSpacing: Number = (_meterScale > 0 && maxIconTextHeight > 0) ? _meterSpacing : 0; var h: Number = _paddingTop + _paddingBottom + maxIconTextHeight + meterSpacing + meterHeight; if (h == background._height && _widgetWidth == background._width && border != undefined) return; background._height = h; background._width = _widgetWidth; redrawBorder(); } private function loadIcon(): Void { _iconLoader.loadClip(_iconSource, _icon); } private function unloadIcon(): Void { _iconLoader.unloadClip(_icon); _iconLoaded = false; updateBackgroundSize(); updateElementPositions(); } private function updateIcon(): Void { var tf: Transform = new Transform(_icon); var colorTf: ColorTransform = new ColorTransform(); colorTf.rgb = _iconColor; tf.colorTransform = colorTf; _icon._alpha = _iconAlpha; _icon._width = _icon._height = _iconSize; if (_iconName == "") _icon.gotoAndStop(0); else _icon.gotoAndStop(_iconName); } private function updateElementPositions(): Void { _labelTextField.autoSize = "left"; _labelTextField.textAutoSize = "none"; _valueTextField.autoSize = "left"; _valueTextField.textAutoSize = "none"; var iconSize: Number = (_iconLoaded) ? _iconSize : 0; var iconSpacing: Number = (_iconLoaded) ? _iconSpacing : 0; var meterSpacing: Number = (_meterScale > 0) ? _meterSpacing : 0; var meterHeight: Number = (_meterScale > 0) ? (_meterFrameContent._height * _meterScale/100) : 0; var meterWidth: Number = _widgetWidth - _paddingLeft - _paddingRight; var availableHeight: Number = background._height - _paddingTop - _paddingBottom - meterSpacing - meterHeight; var availableWidth: Number = _widgetWidth - _paddingLeft - _paddingRight - iconSize - iconSpacing; var textWidth: Number = _labelTextField._width + _valueTextField._width; var textStart: Number = (_iconAlign == ALIGN_RIGHT) ? _paddingLeft : (_paddingLeft + iconSize + iconSpacing); var textEnd: Number = (_iconAlign == ALIGN_RIGHT) ? (_widgetWidth - _paddingRight - iconSize - iconSpacing) : (_widgetWidth - _paddingRight); // Case 1: There's more available than required space if (availableWidth >= textWidth) { if (_textAlign == ALIGN_LEFT) { _labelTextField._x = textStart; _valueTextField._x = _labelTextField._x + _labelTextField._width; } else if (_textAlign == ALIGN_RIGHT) { _valueTextField._x = textEnd - _valueTextField._width; _labelTextField._x = _valueTextField._x - _labelTextField._width; } else if (_textAlign == ALIGN_CENTER) { _labelTextField._x = textStart + ((availableWidth - textWidth) / 2); _valueTextField._x = _labelTextField._x + _labelTextField._width; } else { _labelTextField._x = textStart; _valueTextField._x = textEnd - _paddingRight - _valueTextField._width; } // Case 2: Text fields have to be shrunk to fit in available space. // No need for alignment because there's no free space. } else { _labelTextField.autoSize = "none"; _labelTextField.textAutoSize = "shrink"; _valueTextField.autoSize = "none"; _valueTextField.textAutoSize = "shrink"; _labelTextField._width = availableWidth * (_labelTextField._width / textWidth); _valueTextField._width = availableWidth * (_valueTextField._width / textWidth); _labelTextField._x = textStart; _valueTextField._x = _labelTextField._x + _labelTextField._width; } _labelTextField._y = _paddingTop + (availableHeight - _labelTextField._height - 4)/2 _valueTextField._y = _paddingTop + (availableHeight - _valueTextField._height - 4)/2 _icon._x = (_iconAlign == ALIGN_RIGHT) ? (textEnd + iconSpacing) : _paddingLeft; _icon._y = _paddingTop + (availableHeight - iconSize)/2 if (_meterScale <= 0) { _meter._visible = false return; } _meter._visible = true; _meter._x = _paddingLeft; _meter._y = background._height - meterHeight - _paddingBottom; _meter._xscale = _meter._yscale = _meterScale; var newMeterWidth: Number = meterWidth * 100/_meterScale; _meterFrameContent._width = newMeterWidth; _meterFillContent._xscale = (newMeterWidth - (33.25 + 33.25)) / 366.4 * 100; } private function redrawBorder(): Void { if (border != undefined) border.removeMovieClip(); createEmptyMovieClip("border", getNextHighestDepth()); if (_borderWidth == 0) return; var d: Number = _borderWidth / 2; var left: Number = background._x - d; var top: Number = background._y - d; var right: Number = background._width + d; var bottom: Number = background._height + d; border.lineStyle(_borderWidth, _borderColor, 100, true, "normal", _borderRounded ? "round" : "square", _borderRounded ? "round" : "miter"); border.moveTo(left, top); border.lineTo(right, top); border.lineTo(right, bottom); border.lineTo(left, bottom); border.lineTo(left, top); border._alpha = _borderAlpha; } private function initMeter(): Void { // Draws the meter var w: Number = _meterBar._width; var h: Number = _meterBar._height; var meterBevel: MovieClip = _meterBar.meterBevel; var meterShine: MovieClip = _meterBar.meterShine; var colors: Array = [0xCCCCCC, 0xFFFFFF, 0x000000, 0x000000, 0x000000]; var alphas: Array = [10, 60, 0, 10, 30]; //var ratios: Array = [0, 25, 25, 140, 153, 153, 255]; var ratios: Array = [0, 115, 128, 128, 255]; var matrix: Matrix = new Matrix(); if (meterShine != undefined) return; meterShine = _meterBar.createEmptyMovieClip("meterShine", 2); meterBevel.swapDepths(1); matrix.createGradientBox(w, h, Math.PI/2); meterShine.beginGradientFill("linear", colors, alphas, ratios, matrix); meterShine.moveTo(0,0); meterShine.lineTo(w, 0); meterShine.lineTo(w, h); meterShine.lineTo(0, h); meterShine.lineTo(0, 0); meterShine.endFill(); _meter._alpha = _meterAlpha; updateMeterFlashColor(); } private function updateMeterFillMode(): Void { switch(_meterFillMode) { case FILL_LEFT: case FILL_CENTER: case FILL_RIGHT: break; default: _meterFillMode = FILL_RIGHT; } _meterFillContent.gotoAndStop(_meterFillMode); initMeter(); _meterCurrentPercent = 100; _meterTargetPercent = 100; _meterBarAnim.gotoAndStop("Empty"); _meterEmptyIdx = _meterBarAnim._currentframe; _meterBarAnim.gotoAndStop("Full"); _meterFullIdx = _meterBarAnim._currentframe; _meterFillSpeed = 2; _meterEmptySpeed = 3; drawMeterGradient(); } private function drawMeterGradient(): Void { var colors: Array; var alphas: Array; var ratios: Array; var w: Number = _meterBar._width; var h: Number = _meterBar._height; var meterGradient: MovieClip = _meterBar.meterGradient; var matrix: Matrix = new Matrix(); if (meterGradient != undefined) meterGradient.removeMovieClip(); meterGradient = _meterBar.createEmptyMovieClip("meterGradient", 0); switch(_meterFillMode) { case FILL_LEFT: colors = [_meterColorB, _meterColorA]; alphas = [100, 100]; ratios = [0, 255]; break; case FILL_CENTER: colors = [_meterColorA, _meterColorB, _meterColorA]; alphas = [100, 100, 100]; ratios = [0, 127, 255]; break; case FILL_RIGHT: default: colors = [_meterColorA, _meterColorB]; alphas = [100, 100]; ratios = [0, 255]; } matrix.createGradientBox(w, h); meterGradient.beginGradientFill("linear", colors, alphas, ratios, matrix); meterGradient.moveTo(0,0); meterGradient.lineTo(w, 0); meterGradient.lineTo(w, h); meterGradient.lineTo(0, h); meterGradient.lineTo(0, 0); meterGradient.endFill(); } private function updateMeterFlashColor(): Void { var tf: Transform = new Transform(_meterFlashAnim); var colorTf: ColorTransform = new ColorTransform(); colorTf.rgb = _meterFlashColor; tf.colorTransform = colorTf; } private function updateMeter(): Void { if (_meterTargetPercent == _meterCurrentPercent) return; if (_meterCurrentPercent < _meterTargetPercent) { _meterCurrentPercent = _meterCurrentPercent + _meterFillSpeed; if (_meterCurrentPercent > _meterTargetPercent) _meterCurrentPercent = _meterTargetPercent; } else { _meterCurrentPercent = _meterCurrentPercent - _meterEmptySpeed; if (_meterCurrentPercent < _meterTargetPercent) _meterCurrentPercent = _meterTargetPercent; } _meterCurrentPercent = Math.min(100, Math.max(_meterCurrentPercent, 0)); var meterFrame: Number = Math.floor(GlobalFunc.Lerp(_meterEmptyIdx, _meterFullIdx, 0, 100, _meterCurrentPercent)); _meterBarAnim.gotoAndStop(meterFrame); } } ================================================ FILE: src/ItemMenus/BarterDataSetter.as ================================================ class BarterDataSetter extends InventoryDataSetter { /* PRIVATE VARIABLES */ private var _barterBuyMult: Number; private var _barterSellMult: Number; /* INITIALIZATION */ public function BarterDataSetter(a_barterBuyMult: Number, a_barterSellMult: Number) { super(); _barterBuyMult = (a_barterBuyMult == undefined) ? 1.0 : a_barterBuyMult; _barterSellMult = (a_barterSellMult == undefined) ? 1.0 : a_barterSellMult; } /* PUBLIC FUNCTIONS */ // @override InventoryDataSetter public function processEntry(a_entryObject: Object, a_itemInfo: Object): Void { // Apply multipliers to itemInfo value, then process the entry if (a_entryObject.filterFlag < 1024) { a_itemInfo.value = a_itemInfo.value * _barterSellMult; } else { a_itemInfo.value = Math.max((a_itemInfo.value * _barterBuyMult), 1); } a_itemInfo.value = Math.floor(a_itemInfo.value + 0.5); super.processEntry(a_entryObject, a_itemInfo); } public function updateBarterMultipliers(a_barterBuyMult: Number, a_barterSellMult: Number): Void { // Not used (yet/ever) // see BarterMenu.doTransaction _barterBuyMult = (a_barterBuyMult == undefined) ? 1.0 : a_barterBuyMult; _barterSellMult = (a_barterSellMult == undefined) ? 1.0 : a_barterSellMult; } } ================================================ FILE: src/ItemMenus/BarterMenu.as ================================================ import gfx.io.GameDelegate; import gfx.ui.NavigationCode; import gfx.ui.InputDetails; import skyui.components.list.ListLayoutManager; import skyui.components.list.TabularList; import skyui.components.list.ListLayout; import skyui.props.PropertyDataExtender; import skyui.defines.Input; import skyui.defines.Inventory; import skyui.VRInput; import skyui.util.Debug; class BarterMenu extends ItemMenu { #include "../version.as" /* PRIVATE VARIABLES */ private var _buyMult: Number = 1; private var _sellMult: Number = 1; private var _confirmAmount: Number = 0; private var _playerGold: Number = 0; private var _vendorGold: Number = 0; private var _categoryListIconArt: Array; private var _tabBarIconArt: Array; /* PROPERTIES */ // @override ItemMenu public var bEnableTabs: Boolean = true; private var _handleInputRateLimiter: Boolean; private var _tabSwitchRateLimiter: Boolean; private var vrActionConditions = undefined; /* INITIALIZATION */ public function BarterMenu() { super(); _categoryListIconArt = ["inv_all", "inv_weapons", "inv_armor", "inv_potions", "inv_scrolls", "inv_food", "inv_ingredients", "inv_books", "inv_keys", "inv_misc"]; _tabBarIconArt = ["buy", "sell"]; } /* PUBLIC FUNCTIONS */ public function InitExtensions(): Void { super.InitExtensions(); GameDelegate.addCallBack("SetBarterMultipliers", this, "SetBarterMultipliers"); itemCard.addEventListener("messageConfirm",this,"onTransactionConfirm"); itemCard.addEventListener("sliderChange",this,"onQuantitySliderChange"); inventoryLists.tabBarIconArt = _tabBarIconArt; // Initialize menu-specific list components var categoryList: CategoryList = inventoryLists.categoryList; categoryList.iconArt = _categoryListIconArt; // We need access to the categoryList to figure out if want to // show the new icon or not inventoryLists.itemList.listState.categoryList = categoryList; } // @override ItemMenu public function setConfig(a_config: Object): Void { super.setConfig(a_config); var itemList: TabularList = inventoryLists.itemList; itemList.addDataProcessor(new BarterDataSetter(_buyMult, _sellMult)); itemList.addDataProcessor(new InventoryIconSetter(a_config["Appearance"])); itemList.addDataProcessor(new PropertyDataExtender(a_config["Appearance"], a_config["Properties"], "itemProperties", "itemIcons", "itemCompoundProperties")); var layout: ListLayout = ListLayoutManager.createLayout(a_config["ListLayout"], "ItemListLayout"); itemList.layout = layout; // Not 100% happy with doing this here, but has to do for now. if (inventoryLists.categoryList.selectedEntry) layout.changeFilterFlag(inventoryLists.categoryList.selectedEntry.flag); inventoryLists.itemList.listState.layout = layout; } // @GFx public function handleInput(details: InputDetails, pathToFocus: Array): Boolean { if(_handleInputRateLimiter) return true; skyui.util.Input.rateLimit(this, "_handleInputRateLimiter", 10); // If the item card is in focus, don't capture right/left events. // The item card is likely waiting for quantity slider input. var bShouldCaptureInput = (pathToFocus[0] != itemCard); // Is the user asking a tab switch? if (bShouldCaptureInput && Shared.GlobalFunc.IsKeyPressed(details) && details.navEquivalent == NavigationCode.LEFT && inventoryLists.categoryList.selectionAtBeginningOfSegment()) { // Rate limit tab switching so the user won't accidentally tab switch multiple times if(!_tabSwitchRateLimiter) { inventoryLists.toggleTab(); skyui.util.Input.rateLimit(this, "_tabSwitchRateLimiter", 1000/3); } return true; } return super.handleInput(details, pathToFocus); } public function handleVRInput(event): Boolean { //Debug.dump("BarterMenu::handleVRInput", event); if (!bFadedIn) return; var action = VRInput.instance.triggeredAction(vrActionConditions, event); if(action == "search") { inventoryLists.searchWidget.startInput(); return true; } return false; } private function onExitButtonPress(): Void { closeMenu() } // @API public function SetBarterMultipliers(a_buyMult: Number, a_sellMult: Number): Void { _buyMult = a_buyMult; _sellMult = a_sellMult; } // @API public function ShowRawDealWarning(a_warning: String): Void { itemCard.ShowConfirmMessage(a_warning); } // @override ItemMenu public function UpdateItemCardInfo(a_updateObj: Object): Void { if (isViewingVendorItems()) { a_updateObj.value = a_updateObj.value * _buyMult; a_updateObj.value = Math.max(a_updateObj.value, 1); } else { a_updateObj.value = a_updateObj.value * _sellMult; } a_updateObj.value = Math.floor(a_updateObj.value + 0.5); itemCard.itemInfo = a_updateObj; bottomBar.updateBarterPerItemInfo(a_updateObj); } // @override ItemMenu public function UpdatePlayerInfo(a_playerGold: Number, a_vendorGold: Number, a_vendorName: String, a_playerUpdateObj: Object): Void { _vendorGold = a_vendorGold; _playerGold = a_playerGold; bottomBar.updateBarterInfo(a_playerUpdateObj, itemCard.itemInfo, a_playerGold, a_vendorGold, a_vendorName); } /* PRIVATE FUNCTIONS */ // @override ItemMenu private function onShowItemsList(event: Object): Void { setupVRInput(); if(!vrActionConditions) { vrActionConditions = VRInput.instance.getActionConditions("BarterMenu"); if(VRInput.instance.logDetails) Debug.dump("vrActionConditions", vrActionConditions); } inventoryLists.showItemsList(); //super.onShowItemsList(event); } // @override ItemMenu private function onItemHighlightChange(event: Object): Void { if (event.index != -1) updateBottomBar(true); super.onItemHighlightChange(event); } // @override ItemMenu private function onHideItemsList(event: Object): Void { super.onHideItemsList(event); bottomBar.updateBarterPerItemInfo({type:Inventory.ICT_NONE}); updateBottomBar(false); } private function onQuantitySliderChange(event: Object): Void { var price = itemCard.itemInfo.value * event.value; if (isViewingVendorItems()) { price = price * -1; } bottomBar.updateBarterPriceInfo(_playerGold, _vendorGold, itemCard.itemInfo, price); } // @override ItemMenu private function onQuantityMenuSelect(event: Object): Void { var price = event.amount * itemCard.itemInfo.value; if (price > _vendorGold && !isViewingVendorItems()) { _confirmAmount = event.amount; GameDelegate.call("GetRawDealWarningString", [price], this, "ShowRawDealWarning"); bottomBar.updateBarterPriceInfo(_playerGold, _vendorGold, itemCard.itemInfo, price); return; } doTransaction(event.amount); } // @override ItemMenu private function onItemCardSubMenuAction(event: Object): Void { super.onItemCardSubMenuAction(event); if (event.menu == "quantity") { if (event.opening) { onQuantitySliderChange({value:itemCard.itemInfo.count}); return; } bottomBar.updateBarterPriceInfo(_playerGold, _vendorGold); } } private function onTransactionConfirm(): Void { doTransaction(_confirmAmount); _confirmAmount = 0; } private function doTransaction(a_amount: Number): Void { GameDelegate.call("ItemSelect",[a_amount, itemCard.itemInfo.value, isViewingVendorItems()]); // Update barter multipliers // Update itemList => dataProcessor => BarterDataSetter updateBarterMultipliers // Update itemCardInfo GameDelegate.call("RequestItemCardInfo",[], this, "UpdateItemCardInfo"); } private function isViewingVendorItems(): Boolean { return inventoryLists.categoryList.activeSegment == 0; } // @override ItemMenu private function updateBottomBar(a_bSelected: Boolean): Void { navPanel.clearButtons(); if (a_bSelected) { var activateControls = skyui.util.Input.pickControls(_platform, {PCArt:"E",XBoxArt:"360_A",PS3Art:"PS3_A",ViveArt:"trigger",MoveArt:"PS3_MOVE",OculusArt:"trigger",WindowsMRArt:"trigger"}); navPanel.addButton({text: (isViewingVendorItems() ? "$Buy" : "$Sell"), controls: activateControls}); } else { // navPanel.addButton({text: "$Exit", controls: _cancelControls}); // navPanel.addButton({text: "$Search", controls: _searchControls}); if (_platform != 0) { navPanel.addButton({text: "$Column", controls: {namedKey: "Action_Up"}}); navPanel.addButton({text: "$Order", controls: {namedKey: "Action_Double_Up"}}); } navPanel.addButton({text: "$Switch Tab", controls: {namedKey: "Action_Left"}}); } navPanel.addButton({ text: "$Search", controls: skyui.util.Input.pickControls(_platform, {PCArt: "Space", ViveArt: "radial_Either_Down", MoveArt: "PS3_X", OculusArt: "OCC THUMB_REST", WindowsMRArt: "OCC THUMB_REST", KnucklesArt: "OCC THUMB_REST"})}); navPanel.updateButtons(true); } } ================================================ FILE: src/ItemMenus/BottomBar.as ================================================ import gfx.io.GameDelegate; import Components.Meter; import skyui.components.ButtonPanel; import skyui.defines.Inventory; class BottomBar extends MovieClip { #include "../version.as" /* PRIVATE VARIABLES */ private var _lastItemType: Number; private var _healthMeter: Meter; private var _magickaMeter: Meter; private var _staminaMeter: Meter; private var _levelMeter: Meter; private var _playerInfoObj: Object; /* STAGE ELEMENTS */ public var playerInfoCard: MovieClip; /* PROPERTIES */ public var buttonPanel: ButtonPanel; /* INITIALIZATION */ public function BottomBar() { super(); _lastItemType = Inventory.ICT_NONE; _healthMeter = new Meter(playerInfoCard.HealthRect.MeterInstance.Meter_mc); _magickaMeter = new Meter(playerInfoCard.MagickaRect.MeterInstance.Meter_mc); _staminaMeter = new Meter(playerInfoCard.StaminaRect.MeterInstance.Meter_mc); _levelMeter = new Meter(playerInfoCard.LevelMeterInstance.Meter_mc); } /* PUBLIC FUNCTIONS */ public function positionElements(a_leftOffset: Number, a_rightOffset: Number): Void { buttonPanel._x = a_leftOffset; buttonPanel.updateButtons(true); playerInfoCard._x = a_rightOffset - playerInfoCard._width; } public function showPlayerInfo(): Void { playerInfoCard._alpha = 100; } public function hidePlayerInfo(): Void { playerInfoCard._alpha = 0; } // @API public function UpdatePlayerInfo(a_playerUpdateObj: Object, a_itemUpdateObj: Object): Void { _playerInfoObj = a_playerUpdateObj; updatePerItemInfo(a_itemUpdateObj); } public function updatePerItemInfo(a_itemUpdateObj: Object): Void { var infoCard = playerInfoCard; var itemType: Number = a_itemUpdateObj.type; var bHasWeightandValue = true; if (itemType == undefined) { itemType = _lastItemType; if (a_itemUpdateObj == undefined) a_itemUpdateObj = {type: _lastItemType}; } else { _lastItemType = itemType; } if (_playerInfoObj != undefined && a_itemUpdateObj != undefined) { switch(itemType) { case Inventory.ICT_ARMOR: infoCard.gotoAndStop("Armor"); var strArmor: String = Math.floor(_playerInfoObj.armor).toString(); if (a_itemUpdateObj.armorChange != undefined) { var iArmorDelta = Math.round(a_itemUpdateObj.armorChange); if (iArmorDelta > 0) strArmor = strArmor + " (+" + iArmorDelta.toString() + ")"; else if (iArmorDelta < 0) strArmor = strArmor + " (" + iArmorDelta.toString() + ")"; } infoCard.ArmorRatingValue.textAutoSize = "shrink"; infoCard.ArmorRatingValue.html = true; infoCard.ArmorRatingValue.SetText(strArmor, true); break; case Inventory.ICT_WEAPON: infoCard.gotoAndStop("Weapon"); var strDamage: String = Math.floor(_playerInfoObj.damage).toString(); if (a_itemUpdateObj.damageChange != undefined) { var iDamageDelta = Math.round(a_itemUpdateObj.damageChange); if (iDamageDelta > 0) strDamage = strDamage + " (+" + iDamageDelta.toString() + ")"; else if (iDamageDelta < 0) strDamage = strDamage + " (" + iDamageDelta.toString() + ")"; } infoCard.DamageValue.textAutoSize = "shrink"; infoCard.DamageValue.html = true; infoCard.DamageValue.SetText(strDamage, true); break; case Inventory.ICT_POTION: case Inventory.ICT_FOOD: var EF_HEALTH: Number = 0; var EF_MAGICKA: Number = 1; var EF_STAMINA: Number = 2; if (a_itemUpdateObj.potionType == EF_MAGICKA) infoCard.gotoAndStop("MagickaPotion"); else if (a_itemUpdateObj.potionType == EF_STAMINA) infoCard.gotoAndStop("StaminaPotion"); else if (a_itemUpdateObj.potionType == EF_HEALTH) infoCard.gotoAndStop("HealthPotion"); break; case Inventory.ICT_SPELL_DEFAULT: case Inventory.ICT_ACTIVE_EFFECT: infoCard.gotoAndStop("Magic"); bHasWeightandValue = false; break; case Inventory.ICT_SPELL: infoCard.gotoAndStop("MagicSkill"); if (a_itemUpdateObj.magicSchoolName != undefined) updateSkillBar(a_itemUpdateObj.magicSchoolName, a_itemUpdateObj.magicSchoolLevel, a_itemUpdateObj.magicSchoolPct); bHasWeightandValue = false; break; case Inventory.ICT_SHOUT: infoCard.gotoAndStop("Shout"); infoCard.DragonSoulTextInstance.SetText(_playerInfoObj.dragonSoulText); bHasWeightandValue = false; break; case Inventory.ICT_BOOK: case Inventory.ICT_INGREDIENT: case Inventory.ICT_MISC: case Inventory.ICT_KEY: default: infoCard.gotoAndStop("Default"); } if (bHasWeightandValue) { infoCard.CarryWeightValue.textAutoSize = "shrink"; infoCard.CarryWeightValue.SetText(Math.ceil(_playerInfoObj.encumbrance) + "/" + Math.floor(_playerInfoObj.maxEncumbrance)); infoCard.PlayerGoldValue.textAutoSize = "shrink"; infoCard.PlayerGoldValue.SetText(_playerInfoObj.gold.toString()); infoCard.PlayerGoldLabel._x = infoCard.PlayerGoldValue._x + infoCard.PlayerGoldValue.getLineMetrics(0).x - infoCard.PlayerGoldLabel._width; infoCard.CarryWeightValue._x = infoCard.PlayerGoldLabel._x + infoCard.PlayerGoldLabel.getLineMetrics(0).x - infoCard.CarryWeightValue._width - 5; infoCard.CarryWeightLabel._x = infoCard.CarryWeightValue._x + infoCard.CarryWeightValue.getLineMetrics(0).x - infoCard.CarryWeightLabel._width; if (itemType === Inventory.ICT_ARMOR) { infoCard.ArmorRatingValue._x = infoCard.CarryWeightLabel._x + infoCard.CarryWeightLabel.getLineMetrics(0).x - infoCard.ArmorRatingValue._width - 5; infoCard.ArmorRatingLabel._x = infoCard.ArmorRatingValue._x + infoCard.ArmorRatingValue.getLineMetrics(0).x - infoCard.ArmorRatingLabel._width; } else if (itemType === Inventory.ICT_WEAPON) { infoCard.DamageValue._x = infoCard.CarryWeightLabel._x + infoCard.CarryWeightLabel.getLineMetrics(0).x - infoCard.DamageValue._width - 5; infoCard.DamageLabel._x = infoCard.DamageValue._x + infoCard.DamageValue.getLineMetrics(0).x - infoCard.DamageLabel._width; } } updateStatMeter(infoCard.HealthRect, _healthMeter, _playerInfoObj.health, _playerInfoObj.maxHealth, _playerInfoObj.healthColor); updateStatMeter(infoCard.MagickaRect, _magickaMeter, _playerInfoObj.magicka, _playerInfoObj.maxMagicka, _playerInfoObj.magickaColor); updateStatMeter(infoCard.StaminaRect, _staminaMeter, _playerInfoObj.stamina, _playerInfoObj.maxStamina, _playerInfoObj.staminaColor); } } // @API public function UpdateCraftingInfo(a_skillName: String, a_levelStart: Number, a_levelPercent: Number): Void { playerInfoCard.gotoAndStop("Crafting"); updateSkillBar(a_skillName, a_levelStart, a_levelPercent); } public function updateBarterInfo(a_playerUpdateObj: Object, a_itemUpdateObj: Object, a_playerGold: Number, a_vendorGold: Number, a_vendorName: String): Void { _playerInfoObj = a_playerUpdateObj; var infoCard = playerInfoCard; infoCard.gotoAndStop("Barter"); infoCard.CarryWeightValue.textAutoSize = "shrink"; infoCard.CarryWeightValue.SetText(Math.ceil(_playerInfoObj.encumbrance) + "/" + Math.floor(_playerInfoObj.maxEncumbrance)); infoCard.VendorGoldLabel.textAutoSize = "shrink"; if (a_vendorName != undefined) { infoCard.VendorGoldLabel.SetText("$Gold"); infoCard.VendorGoldLabel.SetText(a_vendorName + " " + infoCard.VendorGoldLabel.text); } updateBarterPriceInfo(a_playerGold, a_vendorGold, a_itemUpdateObj); } public function updateBarterPriceInfo(a_playerGold: Number, a_vendorGold: Number, a_itemUpdateObj: Object, a_goldDelta: Number): Void { var infoCard = playerInfoCard; infoCard.PlayerGoldValue.textAutoSize = "shrink"; if (a_goldDelta == undefined) { infoCard.PlayerGoldValue.SetText(a_playerGold.toString(), true); } else if (a_goldDelta >= 0) { infoCard.PlayerGoldValue.SetText(a_playerGold.toString() + " (+" + a_goldDelta.toString() + ")", true); } else { infoCard.PlayerGoldValue.SetText(a_playerGold.toString() + " (" + a_goldDelta.toString() + ")", true); } infoCard.VendorGoldValue.textAutoSize = "shrink"; infoCard.VendorGoldValue.SetText(a_vendorGold.toString()); infoCard.VendorGoldLabel._x = infoCard.VendorGoldValue._x + infoCard.VendorGoldValue.getLineMetrics(0).x - infoCard.VendorGoldLabel._width; infoCard.PlayerGoldValue._x = infoCard.VendorGoldLabel._x + infoCard.VendorGoldLabel.getLineMetrics(0).x - infoCard.PlayerGoldValue._width - 10; infoCard.PlayerGoldLabel._x = infoCard.PlayerGoldValue._x + infoCard.PlayerGoldValue.getLineMetrics(0).x - infoCard.PlayerGoldLabel._width; infoCard.CarryWeightValue._x = infoCard.PlayerGoldLabel._x + infoCard.PlayerGoldLabel.getLineMetrics(0).x - infoCard.CarryWeightValue._width - 5; infoCard.CarryWeightLabel._x = infoCard.CarryWeightValue._x + infoCard.CarryWeightValue.getLineMetrics(0).x - infoCard.CarryWeightLabel._width; updateBarterPerItemInfo(a_itemUpdateObj); } public function updateBarterPerItemInfo(a_itemUpdateObj: Object): Void { var infoCard = playerInfoCard; var itemType: Number = a_itemUpdateObj.type; if (itemType == undefined) { itemType = _lastItemType; if (a_itemUpdateObj == undefined) a_itemUpdateObj = {type: _lastItemType}; } else { _lastItemType = itemType; } if (a_itemUpdateObj != undefined) { var itemType: Number = a_itemUpdateObj.type; switch(itemType) { case Inventory.ICT_ARMOR: infoCard.gotoAndStop("Barter_Armor"); var strArmor: String = Math.floor(_playerInfoObj.armor).toString(); if (a_itemUpdateObj.armorChange != undefined) { var iArmorDelta: Number = Math.round(a_itemUpdateObj.armorChange); if (iArmorDelta > 0) strArmor = strArmor + " (+" + iArmorDelta.toString() + ")"; else if (iArmorDelta < 0) strArmor = strArmor + " (" + iArmorDelta.toString() + ")"; } infoCard.ArmorRatingValue.textAutoSize = "shrink"; infoCard.ArmorRatingValue.html = true; infoCard.ArmorRatingValue.SetText(strArmor, true); infoCard.ArmorRatingValue._x = infoCard.CarryWeightLabel._x + infoCard.CarryWeightLabel.getLineMetrics(0).x - infoCard.ArmorRatingValue._width - 5; infoCard.ArmorRatingLabel._x = infoCard.ArmorRatingValue._x + infoCard.ArmorRatingValue.getLineMetrics(0).x - infoCard.ArmorRatingLabel._width; break; case Inventory.ICT_WEAPON: infoCard.gotoAndStop("Barter_Weapon"); var strDamage: String = Math.floor(_playerInfoObj.damage).toString(); if (a_itemUpdateObj.damageChange != undefined) { var iDamageDelta: Number = Math.round(a_itemUpdateObj.damageChange); if (iDamageDelta > 0) strDamage = strDamage + " (+" + iDamageDelta.toString() + ")"; else if (iDamageDelta < 0) strDamage = strDamage + " (" + iDamageDelta.toString() + ")"; } infoCard.DamageValue.textAutoSize = "shrink"; infoCard.DamageValue.html = true; infoCard.DamageValue.SetText(strDamage, true); infoCard.DamageValue._x = infoCard.CarryWeightLabel._x + infoCard.CarryWeightLabel.getLineMetrics(0).x - infoCard.DamageValue._width - 5; infoCard.DamageLabel._x = infoCard.DamageValue._x + infoCard.DamageValue.getLineMetrics(0).x - infoCard.DamageLabel._width; break; default: infoCard.gotoAndStop("Barter"); } } } public function setGiftInfo(a_favorPoints: Number): Void { playerInfoCard.gotoAndStop("Gift"); } public function setPlatform(a_platform: Number, a_bPS3Switch: Boolean): Void { buttonPanel.setPlatform(a_platform, a_bPS3Switch); } function GoToDefaultFrame() { // TODO! Check if the MC actually have a "default" defined playerInfoCard.gotoAndStop("Default"); } /* PRIVATE FUNCTIONS */ private function updateStatMeter(a_meterRect: MovieClip, a_meterObj: Meter, a_currValue: Number, a_maxValue: Number, a_colorStr: String): Void { if (a_colorStr == undefined) a_colorStr = "#FFFFFF"; if (a_meterRect._alpha > 0) { if (a_meterRect.MeterText != undefined) { a_meterRect.MeterText.textAutoSize = "shrink"; a_meterRect.MeterText.html = true; a_meterRect.MeterText.SetText("" + Math.floor(a_currValue) + "/" + Math.floor(a_maxValue) + "", true); } a_meterRect.MeterInstance.gotoAndStop("Pause"); a_meterObj.SetPercent(a_currValue / a_maxValue * 100); } } private function updateSkillBar(a_skillName: String, a_levelStart: Number, a_levelPercent: Number): Void { var infoCard = playerInfoCard; infoCard.SkillLevelLabel.SetText(a_skillName); infoCard.SkillLevelCurrent.SetText(a_levelStart); infoCard.SkillLevelNext.SetText(a_levelStart + 1); infoCard.LevelMeterInstance.gotoAndStop("Pause"); _levelMeter.SetPercent(a_levelPercent); } } ================================================ FILE: src/ItemMenus/CategoryList.as ================================================ import gfx.events.EventDispatcher; import gfx.ui.NavigationCode; import gfx.ui.InputDetails; import Shared.GlobalFunc; import skyui.components.list.EntryClipManager; import skyui.components.list.BasicEnumeration; import skyui.components.list.AlphaEntryFormatter; import skyui.components.list.BasicList; class CategoryList extends BasicList { /* CONSTANTS */ public static var LEFT_SEGMENT = 0; public static var RIGHT_SEGMENT = 1; /* STAGE ELEMENTS */ public var selectorCenter: MovieClip; public var selectorLeft: MovieClip; public var selectorRight: MovieClip; public var background: MovieClip; /* PRIVATE VARIABLES */ private var _xOffset: Number; private var _contentWidth: Number; private var _totalWidth: Number; private var _selectorPos: Number; private var _targetSelectorPos: Number; private var _bFastSwitch: Boolean; private var _segmentOffset: Number; private var _segmentLength: Number; /* PROPERTIES */ // Distance from border to start icon. public var iconIndent: Number; // Size of the icon. public var iconSize: Number; // Array that contains the icon label for category at position i. // The category list uses fixed lengths/icons, so this is assigned statically. public var iconArt: Array; // For segmented lists, this is in the index of the divider that seperates player and container/vendor inventory. public var dividerIndex: Number; // The active segment for divided lists (left or right). private var _activeSegment: Number; // Index of previous selected item public var lastSelectedIndex: Number; public function set activeSegment(a_segment: Number) { if (a_segment == _activeSegment) return; _activeSegment = a_segment; calculateSegmentParams(); if (a_segment == LEFT_SEGMENT && _selectedIndex > dividerIndex) doSetSelectedIndex(_selectedIndex - dividerIndex - 1, SELECT_MOUSE); else if (a_segment == RIGHT_SEGMENT && _selectedIndex < dividerIndex) doSetSelectedIndex(_selectedIndex + dividerIndex + 1, SELECT_MOUSE); UpdateList(); } public function get activeSegment(): Number { return _activeSegment; } public function selectionAtBeginningOfSegment(): Boolean { if(selectedIndex == 0) return true; if(dividerIndex != -1 && selectedIndex == dividerIndex + 1) return true; return false; } public function selectionAtEndOfSegment(): Boolean { if(selectedIndex == entryList.length) return true; if(dividerIndex != -1 && selectedIndex == dividerIndex - 1) return true; return false; } /* INITIALIZATION */ public function CategoryList() { super(); _selectorPos = 0; _targetSelectorPos = 0; _bFastSwitch = false; _activeSegment = LEFT_SEGMENT; dividerIndex = -1; _segmentOffset = 0; _segmentLength = 0; if (iconSize == undefined) iconSize = 32; } /* PUBLIC FUNCTIONS */ // Clears the list. For the category list, that's ok since the entryList isn't manipulated directly. // @override BasicList public function clearList(): Void { dividerIndex = -1; _entryList.splice(0); } // @override BasicList public function InvalidateData(): Void { if (_bSuspended) { _bRequestInvalidate = true; return; } listEnumeration.invalidate(); calculateSegmentParams(); if (_selectedIndex >= listEnumeration.size()) _selectedIndex = listEnumeration.size() - 1; UpdateList(); if (onInvalidate) onInvalidate(); } // @override BasicList public function UpdateList(): Void { if (_bSuspended) { _bRequestUpdate = true; return; } setClipCount(_segmentLength); var cw = 0; for (var i = 0; i < _segmentLength; i++) { var entryClip = getClipByIndex(i); entryClip.setEntry(listEnumeration.at(i + _segmentOffset), listState); entryClip.background._width = entryClip.background._height = iconSize; listEnumeration.at(i + _segmentOffset).clipIndex = i; entryClip.itemIndex = i + _segmentOffset; cw = cw + iconSize; } _contentWidth = cw; _totalWidth = background._width; var spacing = (_totalWidth - _contentWidth) / (_segmentLength + 1); var xPos = background._x + spacing; for (var i = 0; i < _segmentLength; i++) { var entryClip = getClipByIndex(i); entryClip._x = xPos; xPos = xPos + iconSize + spacing; entryClip._visible = true; } updateSelector(); } // Moves the selection left to the next element. Wraps around. public function moveSelectionLeft(): Void { if (disableSelection) return; var curIndex = _selectedIndex; var startIndex = _selectedIndex; lastSelectedIndex = curIndex; do { if (curIndex > _segmentOffset) { curIndex--; } else { _bFastSwitch = true; curIndex = _segmentOffset + _segmentLength - 1; } } while (curIndex != startIndex && listEnumeration.at(curIndex).filterFlag == 0 && !listEnumeration.at(curIndex).bDontHide); onItemPress(curIndex, 0); } // Moves the selection right to the next element. Wraps around. public function moveSelectionRight(): Void { if (disableSelection) return; var curIndex = _selectedIndex; var startIndex = _selectedIndex; lastSelectedIndex = curIndex; do { if (curIndex < _segmentOffset + _segmentLength - 1) { curIndex++; } else { _bFastSwitch = true; curIndex = _segmentOffset; } } while (curIndex != startIndex && listEnumeration.at(curIndex).filterFlag == 0 && !listEnumeration.at(curIndex).bDontHide); onItemPress(curIndex, 0); } // @GFx public function handleInput(details: InputDetails, pathToFocus: Array): Boolean { if (disableInput) return false; if (GlobalFunc.IsKeyPressed(details)) { if (details.navEquivalent == NavigationCode.LEFT) { moveSelectionLeft(); return true; } else if (details.navEquivalent == NavigationCode.RIGHT) { moveSelectionRight(); return true; } } return false; } // @override BasicList public function onEnterFrame(): Void { super.onEnterFrame(); if (_bFastSwitch && _selectorPos != _targetSelectorPos) { _selectorPos = _targetSelectorPos; _bFastSwitch = false; refreshSelector(); } else if (_selectorPos < _targetSelectorPos) { _selectorPos = _selectorPos + (_targetSelectorPos - _selectorPos) * 0.2 + 1; refreshSelector(); if (_selectorPos > _targetSelectorPos) _selectorPos = _targetSelectorPos; } else if (_selectorPos > _targetSelectorPos) { _selectorPos = _selectorPos - (_selectorPos - _targetSelectorPos) * 0.2 - 1; refreshSelector(); if (_selectorPos < _targetSelectorPos) _selectorPos = _targetSelectorPos; } } // @override BasicList public function onItemPress(a_index: Number, a_keyboardOrMouse: Number): Void { if (disableInput || disableSelection || a_index == -1) return; doSetSelectedIndex(a_index, a_keyboardOrMouse); updateSelector(); dispatchEvent({type: "itemPress", index: _selectedIndex, entry: selectedEntry, keyboardOrMouse: a_keyboardOrMouse}); } // @override BasicList private function onItemPressAux(a_index: Number, a_keyboardOrMouse: Number, a_buttonIndex: Number): Void { if (disableInput || disableSelection || a_index == -1 || a_buttonIndex != 1) return; doSetSelectedIndex(a_index, a_keyboardOrMouse); updateSelector(); dispatchEvent({type: "itemPressAux", index: _selectedIndex, entry: selectedEntry, keyboardOrMouse: a_keyboardOrMouse}); } // @override BasicList public function onItemRollOver(a_index: Number): Void { if (disableInput || disableSelection) return; isMouseDrivenNav = true; if (a_index == _selectedIndex) return; var entryClip = getClipByIndex(a_index); entryClip._alpha = 75; } // @override BasicList public function onItemRollOut(a_index: Number): Void { if (disableInput || disableSelection) return; isMouseDrivenNav = true; if (a_index == _selectedIndex) return; var entryClip = getClipByIndex(a_index); entryClip._alpha = 50; } /* PRIVATE FUNCTIONS */ private function calculateSegmentParams(): Void { // Divided if (dividerIndex != undefined && dividerIndex != -1) { if (_activeSegment == LEFT_SEGMENT) { _segmentOffset = 0; _segmentLength = dividerIndex; } else { _segmentOffset = dividerIndex + 1; _segmentLength = listEnumeration.size() - _segmentOffset; } // Default for non-divided lists } else { _segmentOffset = 0; _segmentLength = listEnumeration.size(); } } private function updateSelector(): Void { if (selectorCenter == undefined) { return; } if (_selectedIndex == -1) { selectorCenter._visible = false; if (selectorLeft != undefined) selectorLeft._visible = false; if (selectorRight != undefined) selectorRight._visible = false; return; } var selectedClip = _entryClipManager.getClip(_selectedIndex - _segmentOffset); _targetSelectorPos = selectedClip._x + (selectedClip.background._width - selectorCenter._width) / 2; selectorCenter._visible = true; selectorCenter._y = selectedClip._y + selectedClip.background._height; if (selectorLeft != undefined) { selectorLeft._visible = true; selectorLeft._x = 0; selectorLeft._y = selectorCenter._y; } if (selectorRight != undefined) { selectorRight._visible = true; selectorRight._y = selectorCenter._y; selectorRight._width = _totalWidth - selectorRight._x; } } private function refreshSelector(): Void { selectorCenter._visible = true; var selectedClip = _entryClipManager.getClip(_selectedIndex - _segmentOffset); selectorCenter._x = _selectorPos; if (selectorLeft != undefined) selectorLeft._width = selectorCenter._x; if (selectorRight != undefined) { selectorRight._x = selectorCenter._x + selectorCenter._width; selectorRight._width = _totalWidth - selectorRight._x; } } } ================================================ FILE: src/ItemMenus/CategoryListEntry.as ================================================ import skyui.components.list.ListState; import skyui.components.list.BasicListEntry; class CategoryListEntry extends BasicListEntry { /* PRIVATE VARIABLES */ private var _iconLabel: String; private var _iconSize: Number; /* STAGE ELMENTS */ public var icon: MovieClip; /* PUBLIC FUNCTIONS */ public function initialize(a_index: Number, a_state: ListState): Void { super.initialize(); var iconLoader = new MovieClipLoader(); iconLoader.addListener(this); _iconLabel = CategoryList(a_state.list).iconArt[a_index]; _iconSize = CategoryList(a_state.list).iconSize; iconLoader.loadClip(a_state.iconSource, icon); } public function setEntry(a_entryObject: Object, a_state: ListState): Void { if (a_entryObject.filterFlag == 0 && !a_entryObject.bDontHide) { _alpha = 15; enabled = false; } else if (a_entryObject == a_state.list.selectedEntry) { _alpha = 100; enabled = true; } else { _alpha = 50; enabled = true; } } /* PRIVATE FUNCTIONS */ // @implements MovieClipLoader private function onLoadInit(a_mc: MovieClip): Void { if (a_mc.background != undefined) { // If the icon set has a background, scale the icon until background size would = icon size a_mc._xscale = a_mc._yscale = (_iconSize/a_mc.background._width)*100; } else { a_mc._width = a_mc._height = _iconSize; } a_mc.gotoAndStop(_iconLabel); } } ================================================ FILE: src/ItemMenus/ContainerMenu.as ================================================ import gfx.io.GameDelegate; import gfx.ui.NavigationCode; import gfx.ui.InputDetails; import skyui.util.Translator; import skyui.util.GlobalFunctions; import skyui.components.list.ListLayoutManager; import skyui.components.list.TabularList; import skyui.components.list.ListLayout; import skyui.props.PropertyDataExtender; import skyui.defines.Input; import skyui.defines.Inventory; import skyui.defines.Item; import skyui.util.Debug; import skyui.VRInput; class ContainerMenu extends ItemMenu { #include "../version.as" /* CONSTANTS */ private static var NULL_HAND: Number = -1; private static var RIGHT_HAND: Number = 0; private static var LEFT_HAND: Number = 1; /* PRIVATE VARIABLES */ private var _bEquipMode: Boolean = false; private var _equipHand: Number; private var _equipModeKey: Number; private var _equipModeControls: Object; private var _tabBarIconArt: Array; private var _pauseInputHandling: Boolean; private var _pauseTabSwitch: Boolean; private var _columnOpRequested: Number; private var vrActionConditions = undefined; /* PROPERTIES */ // @API public var bNPCMode: Boolean = false; // @override ItemMenu public var bEnableTabs: Boolean = true; /* INITIALIZATION */ public function ContainerMenu() { super(); _tabBarIconArt = ["take", "give"]; _pauseInputHandling = false; _columnOpRequested = 0; } /* PUBLIC FUNCTIONS */ public function InitExtensions(): Void { super.InitExtensions(); inventoryLists.tabBarIconArt = _tabBarIconArt; // Initialize menu-specific list components inventoryLists.categoryList.iconArt = ["inv_all", "inv_weapons", "inv_armor", "inv_potions", "inv_scrolls", "inv_food", "inv_ingredients", "inv_books", "inv_keys", "inv_misc"]; GameDelegate.addCallBack("AttemptEquip", this, "AttemptEquip"); GameDelegate.addCallBack("AttemptTake",this,"AttemptTake"); GameDelegate.addCallBack("AttemptTakeAll",this,"AttemptTakeAll"); GameDelegate.addCallBack("AttemptStore",this,"AttemptStore"); GameDelegate.addCallBack("AttemptTakeAndEquip",this,"AttemptTakeAndEquip"); GameDelegate.addCallBack("Vanilla_AttemptEquip",this,"Vanilla_AttemptEquip"); GameDelegate.addCallBack("Vanilla_XButtonPress",this,"Vanilla_XButtonPress"); itemCardFadeHolder.StealTextInstance._visible = false; // We need access to the categoryList to figure out if want to // show the new icon or not inventoryLists.itemList.listState.categoryList = inventoryLists.categoryList; } // @override ItemMenu public function setConfig(a_config: Object): Void { super.setConfig(a_config); var itemList: TabularList = inventoryLists.itemList; itemList.addDataProcessor(new InventoryDataSetter()); itemList.addDataProcessor(new InventoryIconSetter(a_config["Appearance"])); itemList.addDataProcessor(new PropertyDataExtender(a_config["Appearance"], a_config["Properties"], "itemProperties", "itemIcons", "itemCompoundProperties")); var layout: ListLayout = ListLayoutManager.createLayout(a_config["ListLayout"], "ItemListLayout"); itemList.layout = layout; // Not 100% happy with doing this here, but has to do for now. if (inventoryLists.categoryList.selectedEntry) layout.changeFilterFlag(inventoryLists.categoryList.selectedEntry.flag); _equipModeKey = a_config["Input"].controls.pc.equipMode; _equipModeControls = {keyCode: _equipModeKey}; inventoryLists.itemList.listState.layout = layout; } // @API public function ShowItemsList(): Void { // Not necessary anymore. Now handled in onShowItemsList for consistency reasons. //inventoryLists.showItemsList(); } // @GFx public function handleInput(details: InputDetails, pathToFocus: Array): Boolean { // Rate limit input handling // For some reason, VR trackpad swipe events seem to be sent in duplictes? // This means if we're using the trackpad to enable some kind of toggling logic, // the toggle would always cancel itself out. To get around this, we... // // Limit processing of these events to something reasonable. if(_pauseInputHandling) return true; skyui.util.Input.rateLimit(this, "_pauseInputHandling", 10); // VR specific behavior // // Currently, we're not getting a whole lot of keycodes from the game. We cannot // hookup additional keypresses to UI behavior arbitrarily. However, we can continue // to make use of NavigationCode.LEFT and RIGHT. // // The original SkyUI category list allows the player to wrap around the list. Here, // we alter the behavior so that... // // If we've reached the beginning the category list and the player is still asking to // navigate left, switch active segment instead. var bShouldCaptureInput = (pathToFocus[0] != itemCard); if (bShouldCaptureInput && Shared.GlobalFunc.IsKeyPressed(details) && details.navEquivalent == NavigationCode.LEFT && inventoryLists.categoryList.selectionAtBeginningOfSegment()) { // Only actually toggle the tab if we're not being rate limited if(!_pauseTabSwitch) { inventoryLists.toggleTab(); // Rate limit tab switching to 3 times a second skyui.util.Input.rateLimit(this, "_pauseTabSwitch", 1000/3); } return true; } super.handleInput(details,pathToFocus); if (shouldProcessItemsListInput(false)) { if ((_platform == Shared.Platforms.CONTROLLER_PC || _platform == Shared.Platforms.CONTROLLER_VIVE || _platform == Shared.Platforms.CONTROLLER_OCULUS || _platform == Shared.Platforms.CONTROLLER_WINDOWS_MR) && details.skseKeycode == _equipModeKey && inventoryLists.itemList.selectedIndex != -1) { _bEquipMode = details.value != "keyUp"; updateBottomBar(true); } } return true; } public function classname(): String{ return "Class ContainerMenu"; } public function handleVRInput(event): Boolean { //Debug.dump("ContainerMenu::handleVRInput", event); if (!bFadedIn) return; var action = VRInput.instance.triggeredAction(vrActionConditions, event); if(action == "search") { inventoryLists.searchWidget.startInput(); return true; } return false; } // @override ItemMenu public function UpdateItemCardInfo(a_updateObj: Object): Void { super.UpdateItemCardInfo(a_updateObj); updateBottomBar(true); if (a_updateObj.pickpocketChance != undefined) { itemCardFadeHolder.StealTextInstance._visible = true; itemCardFadeHolder.StealTextInstance.PercentTextInstance.html = true; itemCardFadeHolder.StealTextInstance.PercentTextInstance.htmlText = "" + a_updateObj.pickpocketChance + "%" + (isViewingContainer() ? Translator.translate("$ TO STEAL") : Translator.translate("$ TO PLACE")); } else { itemCardFadeHolder.StealTextInstance._visible = false; } } // @API public function AttemptEquip(a_slot: Number, a_bCheckOverList: Boolean): Void { // Function not present in VR interface file } // @API public function SetPlatform(a_platform: Number, a_bPS3Switch: Boolean): Void { super.SetPlatform(a_platform,a_bPS3Switch); _bEquipMode = (a_platform != 0); } // @API public function Vanilla_AttemptEquip(a_slot: Number, a_bCheckOverList: Boolean): Void { var bCheckOverList = a_bCheckOverList == undefined ? true : a_bCheckOverList; if (!shouldProcessItemsListInput(bCheckOverList) || !confirmSelectedEntry()) return; if (_platform == Shared.Platforms.CONTROLLER_PC || _platform == Shared.Platforms.CONTROLLER_VIVE || _platform == Shared.Platforms.CONTROLLER_OCULUS || _platform == Shared.Platforms.CONTROLLER_WINDOWS_MR) { if (_bEquipMode) startItemEquip(a_slot); else startItemTransfer(); } else { startItemEquip(a_slot); } } // @API function AttemptTake(abCheckOverList) { var bCheckOverList = abCheckOverList == undefined ? true : abCheckOverList; if(shouldProcessItemsListInput(bCheckOverList)) startItemTransfer(); } // @API function AttemptTakeAndEquip(aiSlot, abCheckOverList) { var bCheckOverList = abCheckOverList == undefined?true:abCheckOverList; if(shouldProcessItemsListInput(bCheckOverList)) startItemEquip(aiSlot); } // @API function AttemptTakeAll() { if(isViewingContainer() && !bNPCMode) GameDelegate.call("TakeAllItems",[]); } // @API function AttemptStore() { if(!isViewingContainer()) startItemTransfer(); } // @API public function Vanilla_XButtonPress(): Void { // If we are zoomed into an item, do nothing if (!bFadedIn) return; if (isViewingContainer() && !bNPCMode) GameDelegate.call("TakeAllItems",[]); // TODO! Is this really required? // Present in SE and VR but not in SkyUI. // Maybe skyui already takes care of this case elsewhere? else if (!isViewingContainer()) startItemTransfer(); } /* PRIVATE FUNCTIONS */ private function onItemSelect(event: Object): Void { if (event.keyboardOrMouse != 0) { if (_platform == 0 && _bEquipMode) startItemEquip(ContainerMenu.NULL_HAND); else startItemTransfer(); } } private function onItemCardSubMenuAction(event: Object): Void { super.onItemCardSubMenuAction(event); if (event.menu == "quantity") GameDelegate.call("QuantitySliderOpen", [event.opening]); } // @override ItemMenu private function onItemHighlightChange(event: Object): Void { if (event.index != -1) updateBottomBar(true); super.onItemHighlightChange(event); } // @override ItemMenu private function onShowItemsList(event: Object): Void { // For some unknown reason, OnShow() does not get called for the container menu. // setupVRInput(); if(!vrActionConditions) { vrActionConditions = VRInput.instance.getActionConditions("ContainerMenu"); if(VRInput.instance.logDetails) Debug.dump("vrActionConditions", vrActionConditions); } inventoryLists.showItemsList(); } // @override ItemMenu private function onHideItemsList(event: Object): Void { super.onHideItemsList(event); bottomBar.updatePerItemInfo({type:Inventory.ICT_NONE}); updateBottomBar(false); } private function onMouseRotationFastClick(a_mouseButton:Number): Void { GameDelegate.call("CheckForMouseEquip",[a_mouseButton],this,"AttemptEquip"); } private function onQuantityMenuSelect(event: Object): Void { if (_equipHand != undefined) { GameDelegate.call("EquipItem",[_equipHand, event.amount]); if (!checkBook(inventoryLists.itemList.selectedEntry)) checkPoison(inventoryLists.itemList.selectedEntry); _equipHand = undefined; return; } if (inventoryLists.itemList.selectedEntry.enabled) { GameDelegate.call("ItemTransfer",[event.amount, isViewingContainer()]); return; } GameDelegate.call("DisabledItemSelect",[]); } // @override ItemMenu private function updateBottomBar(a_bSelected: Boolean): Void { navPanel.clearButtons(); var equipControl = skyui.util.Input.pickControls(_platform, {PCArt:"M1M2",XBoxArt:"360_LTRT",PS3Art:"PS3_LTRT",ViveArt:"trigger_LR",MoveArt:"PS3_A",OculusArt:"trigger_LR",WindowsMRArt:"trigger_LR"}); var takeAllControl = skyui.util.Input.pickControls(_platform, {PCArt:"R",XBoxArt:"360_X",PS3Art:"PS3_X",ViveArt:"radial_Either_Left",MoveArt:"PS3_B",OculusArt:"OCC_Y",WindowsMRArt:"radial_Either_Left"}); var activateControl = skyui.util.Input.pickControls(_platform, {PCArt:"E",XBoxArt:"360_A",PS3Art:"PS3_A",ViveArt:"radial_Either_Center",MoveArt:"PS3_MOVE",OculusArt:"OCC_A",WindowsMRArt:"radial_Either_Center"}); var favoriteControl = skyui.util.Input.pickControls(_platform, {PCArt:"F",XBoxArt:"360_Y",PS3Art:"PS3_Y",ViveArt:"radial_Either_Right",MoveArt:"PS3_Y",OculusArt:"OCC_B",WindowsMRArt:"radial_Either_Right"}); // Setup the main action button var equipArt = {PCArt:"M1M2", XBoxArt:"360_LTRT", PS3Art:"PS3_LTRT", ViveArt: "trigger_LR", MoveArt:"PS3_MOVE", OculusArt: "trigger_LR", WindowsMRArt: "trigger_LR"}; var useItemArt = {PCArt:"E",XBoxArt:"360_A",PS3Art:"PS3_A",ViveArt:"trigger",MoveArt:"PS3_MOVE",OculusArt:"trigger",WindowsMRArt:"trigger"}; var actionText = undefined; var actionArt = undefined; switch(itemCard.itemInfo.type) { case Inventory.ICT_BOOK: actionText = "$Read"; actionArt = useItemArt; break; case Inventory.ICT_POTION: actionText = "$Use"; actionArt = useItemArt; break; case Inventory.ICT_FOOD: case Inventory.ICT_INGREDIENT: actionText = "$Eat"; actionArt = useItemArt; break; case Inventory.ICT_ARMOR: case Inventory.ICT_WEAPON: actionText = "$Equip"; actionArt = equipArt; break; } if (actionArt != undefined) navPanel.addButton({text: actionText, controls: skyui.util.Input.pickControls(_platform, actionArt)}); if (a_bSelected && inventoryLists.itemList.selectedIndex != -1 && inventoryLists.currentState == InventoryLists.SHOW_PANEL) { if (isViewingContainer()) { navPanel.addButton({text: "$Take", controls: activateControl}); if (!bNPCMode) navPanel.addButton({text: "$Take All", controls: takeAllControl}); } else { navPanel.addButton({text: bNPCMode ? "$Give" : "$Store", controls: activateControl}); navPanel.addButton({text: itemCard.itemInfo.favorite ? "$Unfavorite" : "$Favorite", controls: favoriteControl}); } // if (!_bEquipMode) // navPanel.addButton({text: "$Equip Mode", controls: _equipModeControls}); } else { // navPanel.addButton({text: "$Exit", controls: _cancelControls}); if (_platform != 0) { navPanel.addButton({text: "$Column", controls: {namedKey: "Action_Up"}}); navPanel.addButton({text: "$Order", controls: {namedKey: "Action_Double_Up"}}); } navPanel.addButton({text: "$Switch Tab", controls: {namedKey: "Action_Left"}}); if (isViewingContainer() && !bNPCMode) navPanel.addButton({text: "$Take All", controls: takeAllControl}); } navPanel.addButton({ text: "$Search", controls: skyui.util.Input.pickControls(_platform, {PCArt: "Space", ViveArt: "radial_Either_Down", MoveArt: "PS3_X", OculusArt: "OCC THUMB_REST", WindowsMRArt: "OCC THUMB_REST", KnucklesArt: "OCC THUMB_REST"})}); navPanel.updateButtons(true); } private function startItemTransfer(): Void { if (inventoryLists.itemList.selectedEntry.enabled) { // Don't remove. This is so if an item weighs nothing, it takes the whole stack // Gold, for example. if (itemCard.itemInfo.weight == 0 && isViewingContainer()) { onQuantityMenuSelect({amount:inventoryLists.itemList.selectedEntry.count}); return; } if (_quantityMinCount < 1 || (inventoryLists.itemList.selectedEntry.count < _quantityMinCount)) { onQuantityMenuSelect({amount:1}); } else { itemCard.ShowQuantityMenu(inventoryLists.itemList.selectedEntry.count); } } } private function startItemEquip(a_equipHand: Number): Void { if (isViewingContainer()) { _equipHand = a_equipHand; startItemTransfer(); return; } GameDelegate.call("EquipItem",[a_equipHand]); if (!checkBook(inventoryLists.itemList.selectedEntry)) checkPoison(inventoryLists.itemList.selectedEntry); } private function isViewingContainer(): Boolean { return (inventoryLists.categoryList.activeSegment == 0); } /* This method is only used in ContainerMenu. If you attempt to use a poison in Container menu a dialog box is presented to ask whether you want to poison the equipped weapon If you release the _equipModeKey while the diaolog is present, the keyUp event for this key is not received by ContainerMenu, so _bEquipMode remains true meaning that the bottom bar buttons are incorrect */ private function checkPoison(a_entryObject: Object): Boolean { if (a_entryObject.type != Inventory.ICT_POTION || _global.skse == null) return false; if (a_entryObject.subType != Item.POTION_POISON) return false; // force equip mode to false. // Use this until we can detect if a specific keyCode is depressed // _bEquipMode = skse.IsKeyDown(_equipModeKey) _bEquipMode = false; return true; } } ================================================ FILE: src/ItemMenus/GiftMenu.as ================================================ import gfx.io.GameDelegate; import skyui.components.list.ListLayoutManager; import skyui.components.list.TabularList; import skyui.components.list.ListLayout; import skyui.props.PropertyDataExtender; import skyui.defines.Input; import skyui.defines.Inventory; import skyui.util.Debug; import skyui.VRInput; class GiftMenu extends ItemMenu { #include "../version.as" /* PRIVATE VARIABLES */ private var _bGivingGifts: Boolean = true; private var _categoryListIconArt: Array; private var vrActionConditions = undefined; /* INITIALIZATION */ public function GiftMenu() { super(); _categoryListIconArt = ["inv_all", "inv_weapons", "inv_armor", "inv_potions", "inv_scrolls", "inv_food", "inv_ingredients", "inv_books", "inv_keys", "inv_misc"]; } /* PUBLIC FUNCTIONS */ public function InitExtensions(): Void { super.InitExtensions(); GameDelegate.addCallBack("SetMenuInfo", this, "SetMenuInfo"); // Initialize menu-specific list components var categoryList: CategoryList = inventoryLists.categoryList; categoryList.iconArt = _categoryListIconArt; } // @override ItemMenu public function setConfig(a_config: Object): Void { super.setConfig(a_config); var itemList: TabularList = inventoryLists.itemList; itemList.addDataProcessor(new InventoryDataSetter()); itemList.addDataProcessor(new InventoryIconSetter(a_config["Appearance"])); itemList.addDataProcessor(new PropertyDataExtender(a_config["Appearance"], a_config["Properties"], "itemProperties", "itemIcons", "itemCompoundProperties")); var layout: ListLayout = ListLayoutManager.createLayout(a_config["ListLayout"], "ItemListLayout"); itemList.layout = layout; // Not 100% happy with doing this here, but has to do for now. if (inventoryLists.categoryList.selectedEntry) layout.changeFilterFlag(inventoryLists.categoryList.selectedEntry.flag); } // @API public function ShowItemsList(): Void { // Not necessary anymore. Now handled in onShowItemsList for consistency reasons. //inventoryLists.showItemsList(); } // @API public function SetMenuInfo(a_bGivingGifts: Boolean, a_bUseFavorPoints: Boolean): Void { _bGivingGifts = a_bGivingGifts; if (!a_bUseFavorPoints) bottomBar.hidePlayerInfo(); } // @override ItemMenu public function UpdatePlayerInfo(a_favorPoints: Number): Void { bottomBar.setGiftInfo(a_favorPoints); } /* PRIVATE FUNCTIONS */ // @override ItemMenu private function onShowItemsList(event: Object): Void { setupVRInput(); if(!vrActionConditions) { vrActionConditions = VRInput.instance.getActionConditions("GiftMenu"); if(VRInput.instance.logDetails) Debug.dump("vrActionConditions", vrActionConditions); } // Force select of first category because RestoreIndices isn't called for GiftMenu // TODO: Do this in the correct place, i.e. InventoryLists.SetCategoriesList(); var categoryList: CategoryList = inventoryLists.categoryList; categoryList.selectedIndex = 0; categoryList.entryList[0].text = "$ALL"; categoryList.InvalidateData(); inventoryLists.showItemsList(); } // @override ItemMenu private function onHideItemsList(event: Object): Void { super.onHideItemsList(event); bottomBar.updatePerItemInfo({type:Inventory.ICT_NONE}); updateBottomBar(false); } private function onItemHighlightChange(event: Object): Void { super.onItemHighlightChange(event); if (event.index != -1) updateBottomBar(true); } // @override ItemMenu private function onItemCardSubMenuAction(event: Object): Void { super.onItemCardSubMenuAction(event); if (event.menu == "quantity") GameDelegate.call("QuantitySliderOpen", [event.opening]); } // @override ItemMenu private function updateBottomBar(a_bSelected: Boolean): Void { navPanel.clearButtons(); var activateControls = skyui.util.Input.pickControls(_platform, {PCArt:"E",XBoxArt:"360_A",PS3Art:"PS3_A",ViveArt:"trigger",MoveArt:"PS3_MOVE",OculusArt:"trigger",WindowsMRArt:"trigger"}); if (a_bSelected) { navPanel.addButton({text: (_bGivingGifts ? "$Give" : "$Take"), controls: activateControls}); } else { navPanel.addButton({text: "$Exit", controls: _cancelControls}); navPanel.addButton({text: "$Search", controls: _searchControls}); if (_platform != 0) { navPanel.addButton({text: "$Column", controls: {namedKey: "Action_Up"}}); navPanel.addButton({text: "$Order", controls: {namedKey: "Action_Double_Up"}}); } } navPanel.addButton({ text: "$Search", controls: skyui.util.Input.pickControls(_platform, {PCArt: "Space", ViveArt: "radial_Either_Down", MoveArt: "PS3_X", OculusArt: "OCC THUMB_REST", WindowsMRArt: "OCC THUMB_REST", KnucklesArt: "OCC THUMB_REST"})}); navPanel.updateButtons(true); } public function handleVRInput(event): Boolean { //Debug.dump("GiftMenu::handleVRInput", event); if (!bFadedIn) return; var action = VRInput.instance.triggeredAction(vrActionConditions, event); if(action == "search") { inventoryLists.searchWidget.startInput(); return true; } return false; } } ================================================ FILE: src/ItemMenus/InventoryDataSetter.as ================================================ import skyui.util.Translator; import skyui.defines.Actor; import skyui.defines.Armor; import skyui.defines.Form; import skyui.defines.Item; import skyui.defines.Material; import skyui.defines.Weapon; import skyui.defines.Inventory; class InventoryDataSetter extends ItemcardDataExtender { /* INITIALIZATION */ public function InventoryDataSetter() { super(); } /* PUBLIC FUNCTIONS */ // @override ItemcardDataExtender public function processEntry(a_entryObject: Object, a_itemInfo: Object): Void { a_entryObject.baseId = a_entryObject.formId & 0x00FFFFFF; a_entryObject.type = a_itemInfo.type; a_entryObject.isEquipped = (a_entryObject.equipState > 0); a_entryObject.isStolen = (a_itemInfo.stolen == true); a_entryObject.infoValue = (a_itemInfo.value > 0) ? (Math.round(a_itemInfo.value * 100) / 100) : null; a_entryObject.infoWeight =(a_itemInfo.weight > 0) ? (Math.round(a_itemInfo.weight * 100) / 100) : null; a_entryObject.infoValueWeight = (a_itemInfo.weight > 0 && a_itemInfo.value > 0) ? Math.round(a_itemInfo.value / a_itemInfo.weight) : null; switch (a_entryObject.formType) { case Form.TYPE_SCROLLITEM: a_entryObject.subTypeDisplay = Translator.translate("$Scroll"); a_entryObject.duration = (a_entryObject.duration > 0) ? (Math.round(a_entryObject.duration * 100) / 100) : null; a_entryObject.magnitude = (a_entryObject.magnitude > 0) ? (Math.round(a_entryObject.magnitude * 100) / 100) : null; break; case Form.TYPE_ARMOR: a_entryObject.isEnchanted = (a_itemInfo.effects != ""); a_entryObject.infoArmor = (a_itemInfo.armor > 0) ? (Math.round(a_itemInfo.armor * 100) / 100) : null; processArmorClass(a_entryObject); processArmorPartMask(a_entryObject); processMaterialKeywords(a_entryObject); processArmorOther(a_entryObject); processArmorBaseId(a_entryObject); break; case Form.TYPE_BOOK: processBookType(a_entryObject); break; case Form.TYPE_INGREDIENT: a_entryObject.subTypeDisplay = Translator.translate("$Ingredient"); break; case Form.TYPE_LIGHT: a_entryObject.subTypeDisplay = Translator.translate("$Torch"); break; case Form.TYPE_MISC: processMiscType(a_entryObject); processMiscBaseId(a_entryObject); break; case Form.TYPE_WEAPON: a_entryObject.isEnchanted = (a_itemInfo.effects != ""); a_entryObject.isPoisoned = (a_itemInfo.poisoned == true); a_entryObject.infoDamage = (a_itemInfo.damage > 0) ? (Math.round(a_itemInfo.damage * 100) / 100) : null; processWeaponType(a_entryObject); processMaterialKeywords(a_entryObject); processWeaponBaseId(a_entryObject); break; case Form.TYPE_AMMO: a_entryObject.isEnchanted = (a_itemInfo.effects != ""); a_entryObject.infoDamage = (a_itemInfo.damage > 0) ? (Math.round(a_itemInfo.damage * 100) / 100) : null; processAmmoType(a_entryObject); processMaterialKeywords(a_entryObject); processAmmoBaseId(a_entryObject); break; case Form.TYPE_KEY: processKeyType(a_entryObject); break; case Form.TYPE_POTION: a_entryObject.duration = (a_entryObject.duration > 0) ? (Math.round(a_entryObject.duration * 100) / 100) : null; a_entryObject.magnitude = (a_entryObject.magnitude > 0) ? (Math.round(a_entryObject.magnitude * 100) / 100) : null; processPotionType(a_entryObject); break; case Form.TYPE_SOULGEM: processSoulGemType(a_entryObject); processSoulGemStatus(a_entryObject); processSoulGemBaseId(a_entryObject); break; } } /* PRIVATE FUNCTIONS */ private function processArmorClass(a_entryObject: Object): Void { if (a_entryObject.weightClass == Armor.WEIGHT_NONE) a_entryObject.weightClass = null; a_entryObject.weightClassDisplay = Translator.translate("$Other"); switch (a_entryObject.weightClass) { case Armor.WEIGHT_LIGHT: a_entryObject.weightClassDisplay = Translator.translate("$Light"); break; case Armor.WEIGHT_HEAVY: a_entryObject.weightClassDisplay = Translator.translate("$Heavy"); break; default: if (a_entryObject.keywords == undefined) break; if (a_entryObject.keywords["VendorItemClothing"] != undefined) { a_entryObject.weightClass = Armor.WEIGHT_CLOTHING; a_entryObject.weightClassDisplay = Translator.translate("$Clothing"); } else if (a_entryObject.keywords["VendorItemJewelry"] != undefined) { a_entryObject.weightClass = Armor.WEIGHT_JEWELRY; a_entryObject.weightClassDisplay = Translator.translate("$Jewelry"); } } } private function processMaterialKeywords(a_entryObject: Object): Void { a_entryObject.material = null; a_entryObject.materialDisplay = Translator.translate("$Other"); if (a_entryObject.keywords == undefined) return; if (a_entryObject.keywords["ArmorMaterialDaedric"] != undefined || a_entryObject.keywords["WeapMaterialDaedric"] != undefined) { a_entryObject.material = Material.DAEDRIC; a_entryObject.materialDisplay = Translator.translate("$Daedric"); } else if (a_entryObject.keywords["ArmorMaterialDragonplate"] != undefined) { a_entryObject.material = Material.DRAGONPLATE; a_entryObject.materialDisplay = Translator.translate("$Dragonplate"); } else if (a_entryObject.keywords["ArmorMaterialDragonscale"] != undefined) { a_entryObject.material = Material.DRAGONSCALE; a_entryObject.materialDisplay = Translator.translate("$Dragonscale"); } else if (a_entryObject.keywords["ArmorMaterialDwarven"] != undefined || a_entryObject.keywords["WeapMaterialDwarven"] != undefined) { a_entryObject.material = Material.DWARVEN; a_entryObject.materialDisplay = Translator.translate("$Dwarven"); } else if (a_entryObject.keywords["ArmorMaterialEbony"] != undefined || a_entryObject.keywords["WeapMaterialEbony"] != undefined) { a_entryObject.material = Material.EBONY; a_entryObject.materialDisplay = Translator.translate("$Ebony"); } else if (a_entryObject.keywords["ArmorMaterialElven"] != undefined || a_entryObject.keywords["WeapMaterialElven"] != undefined) { a_entryObject.material = Material.ELVEN; a_entryObject.materialDisplay = Translator.translate("$Elven"); } else if (a_entryObject.keywords["ArmorMaterialElvenGilded"] != undefined) { a_entryObject.material = Material.ELVENGILDED; a_entryObject.materialDisplay = Translator.translate("$Elven Gilded"); } else if (a_entryObject.keywords["ArmorMaterialGlass"] != undefined || a_entryObject.keywords["WeapMaterialGlass"] != undefined) { a_entryObject.material = Material.GLASS; a_entryObject.materialDisplay = Translator.translate("$Glass"); } else if (a_entryObject.keywords["ArmorMaterialHide"] != undefined) { a_entryObject.material = Material.HIDE; a_entryObject.materialDisplay = Translator.translate("$Hide"); } else if (a_entryObject.keywords["ArmorMaterialImperialHeavy"] != undefined || a_entryObject.keywords["ArmorMaterialImperialLight"] != undefined || a_entryObject.keywords["WeapMaterialImperial"] != undefined) { a_entryObject.material = Material.IMPERIAL; a_entryObject.materialDisplay = Translator.translate("$Imperial"); } else if (a_entryObject.keywords["ArmorMaterialImperialStudded"] != undefined) { a_entryObject.material = Material.IMPERIALSTUDDED; a_entryObject.materialDisplay = Translator.translate("$Studded"); } else if (a_entryObject.keywords["ArmorMaterialIron"] != undefined || a_entryObject.keywords["WeapMaterialIron"] != undefined) { a_entryObject.material = Material.IRON; a_entryObject.materialDisplay = Translator.translate("$Iron"); } else if (a_entryObject.keywords["ArmorMaterialIronBanded"] != undefined) { a_entryObject.material = Material.IRONBANDED; a_entryObject.materialDisplay = Translator.translate("$Iron Banded"); // Must be above leather, vampire armor has 2 material keywords } else if (a_entryObject.keywords["DLC1ArmorMaterialVampire"] != undefined) { a_entryObject.material = Material.VAMPIRE; a_entryObject.materialDisplay = Translator.translate("$Vampire"); } else if (a_entryObject.keywords["ArmorMaterialLeather"] != undefined) { a_entryObject.material = Material.LEATHER; a_entryObject.materialDisplay = Translator.translate("$Leather"); } else if (a_entryObject.keywords["ArmorMaterialOrcish"] != undefined || a_entryObject.keywords["WeapMaterialOrcish"] != undefined) { a_entryObject.material = Material.ORCISH; a_entryObject.materialDisplay = Translator.translate("$Orcish"); } else if (a_entryObject.keywords["ArmorMaterialScaled"] != undefined) { a_entryObject.material = Material.SCALED; a_entryObject.materialDisplay = Translator.translate("$Scaled"); } else if (a_entryObject.keywords["ArmorMaterialSteel"] != undefined || a_entryObject.keywords["WeapMaterialSteel"] != undefined) { a_entryObject.material = Material.STEEL; a_entryObject.materialDisplay = Translator.translate("$Steel"); } else if (a_entryObject.keywords["ArmorMaterialSteelPlate"] != undefined) { a_entryObject.material = Material.STEELPLATE; a_entryObject.materialDisplay = Translator.translate("$Steel Plate"); } else if (a_entryObject.keywords["ArmorMaterialStormcloak"] != undefined) { a_entryObject.material = Material.STORMCLOAK; a_entryObject.materialDisplay = Translator.translate("$Stormcloak"); } else if (a_entryObject.keywords["ArmorMaterialStudded"] != undefined) { a_entryObject.material = Material.STUDDED; a_entryObject.materialDisplay = Translator.translate("$Studded"); } else if (a_entryObject.keywords["DLC1ArmorMaterialDawnguard"] != undefined) { a_entryObject.material = Material.DAWNGUARD; a_entryObject.materialDisplay = Translator.translate("$Dawnguard"); } else if (a_entryObject.keywords["DLC1ArmorMaterialFalmerHardened"] != undefined || a_entryObject.keywords["DLC1ArmorMaterialFalmerHeavy"] != undefined) { a_entryObject.material = Material.FALMERHARDENED; a_entryObject.materialDisplay = Translator.translate("$Falmer Hardened"); } else if (a_entryObject.keywords["DLC1ArmorMaterialHunter"] != undefined) { a_entryObject.material = Material.HUNTER; a_entryObject.materialDisplay = Translator.translate("$Hunter"); } else if (a_entryObject.keywords["DLC1LD_CraftingMaterialAetherium"] != undefined) { a_entryObject.material = Material.AETHERIUM; a_entryObject.materialDisplay = Translator.translate("$Aetherium"); } else if (a_entryObject.keywords["DLC1WeapMaterialDragonbone"] != undefined) { a_entryObject.material = Material.DRAGONBONE; a_entryObject.materialDisplay = Translator.translate("$Dragonbone"); } else if (a_entryObject.keywords["DLC2ArmorMaterialBonemoldHeavy"] != undefined || a_entryObject.keywords["DLC2ArmorMaterialBonemoldLight"] != undefined) { a_entryObject.material = Material.BONEMOLD; a_entryObject.materialDisplay = Translator.translate("$Bonemold"); } else if (a_entryObject.keywords["DLC2ArmorMaterialChitinHeavy"] != undefined || a_entryObject.keywords["DLC2ArmorMaterialChitinLight"] != undefined) { a_entryObject.material = Material.CHITIN; a_entryObject.materialDisplay = Translator.translate("$Chitin"); } else if (a_entryObject.keywords["DLC2ArmorMaterialMoragTong"] != undefined) { a_entryObject.material = Material.MORAGTONG; a_entryObject.materialDisplay = Translator.translate("$Morag Tong"); } else if (a_entryObject.keywords["DLC2ArmorMaterialNordicHeavy"] != undefined || a_entryObject.keywords["DLC2ArmorMaterialNordicLight"] != undefined || a_entryObject.keywords["DLC2WeaponMaterialNordic"] != undefined) { a_entryObject.material = Material.NORDIC; a_entryObject.materialDisplay = Translator.translate("$Nordic"); } else if (a_entryObject.keywords["DLC2ArmorMaterialStalhrimHeavy"] != undefined || a_entryObject.keywords["DLC2ArmorMaterialStalhrimLight"] != undefined || a_entryObject.keywords["DLC2WeaponMaterialStalhrim"] != undefined) { a_entryObject.material = Material.STALHRIM; a_entryObject.materialDisplay = Translator.translate("$Stalhrim"); if (a_entryObject.keywords["DLC2dunHaknirArmor"] != undefined) { a_entryObject.material = Material.DEATHBRAND; a_entryObject.materialDisplay = Translator.translate("$Deathbrand"); } } else if (a_entryObject.keywords["WeapMaterialDraugr"] != undefined) { a_entryObject.material = Material.DRAUGR; a_entryObject.materialDisplay = Translator.translate("$Draugr"); } else if (a_entryObject.keywords["WeapMaterialDraugrHoned"] != undefined) { a_entryObject.material = Material.DRAUGRHONED; a_entryObject.materialDisplay = Translator.translate("$Draugr Honed"); } else if (a_entryObject.keywords["WeapMaterialFalmer"] != undefined) { a_entryObject.material = Material.FALMER; a_entryObject.materialDisplay = Translator.translate("$Falmer"); } else if (a_entryObject.keywords["WeapMaterialFalmerHoned"] != undefined) { a_entryObject.material = Material.FALMERHONED; a_entryObject.materialDisplay = Translator.translate("$Falmer Honed"); } else if (a_entryObject.keywords["WeapMaterialSilver"] != undefined) { a_entryObject.material = Material.SILVER; a_entryObject.materialDisplay = Translator.translate("$Silver"); } else if (a_entryObject.keywords["WeapMaterialWood"] != undefined) { a_entryObject.material = Material.WOOD; a_entryObject.materialDisplay = Translator.translate("$Wood"); } } private function processWeaponType(a_entryObject: Object): Void { a_entryObject.subType = null; a_entryObject.subTypeDisplay = Translator.translate("$Weapon"); switch (a_entryObject.weaponType) { case Weapon.ANIM_HANDTOHANDMELEE: case Weapon.ANIM_H2H: a_entryObject.subType = Weapon.TYPE_MELEE; a_entryObject.subTypeDisplay = Translator.translate("$Melee"); break; case Weapon.ANIM_ONEHANDSWORD: case Weapon.ANIM_1HS: a_entryObject.subType = Weapon.TYPE_SWORD; a_entryObject.subTypeDisplay = Translator.translate("$Sword"); break; case Weapon.ANIM_ONEHANDDAGGER: case Weapon.ANIM_1HD: a_entryObject.subType = Weapon.TYPE_DAGGER; a_entryObject.subTypeDisplay = Translator.translate("$Dagger"); break; case Weapon.ANIM_ONEHANDAXE: case Weapon.ANIM_1HA: a_entryObject.subType = Weapon.TYPE_WARAXE; a_entryObject.subTypeDisplay = Translator.translate("$War Axe"); break; case Weapon.ANIM_ONEHANDMACE: case Weapon.ANIM_1HM: a_entryObject.subType = Weapon.TYPE_MACE; a_entryObject.subTypeDisplay = Translator.translate("$Mace"); break; case Weapon.ANIM_TWOHANDSWORD: case Weapon.ANIM_2HS: a_entryObject.subType = Weapon.TYPE_GREATSWORD; a_entryObject.subTypeDisplay = Translator.translate("$Greatsword"); break; case Weapon.ANIM_TWOHANDAXE: case Weapon.ANIM_2HA: a_entryObject.subType = Weapon.TYPE_BATTLEAXE; a_entryObject.subTypeDisplay = Translator.translate("$Battleaxe"); if (a_entryObject.keywords != undefined && a_entryObject.keywords["WeapTypeWarhammer"] != undefined) { a_entryObject.subType = Weapon.TYPE_WARHAMMER; a_entryObject.subTypeDisplay = Translator.translate("$Warhammer"); } break; case Weapon.ANIM_BOW: case Weapon.ANIM_BOW2: a_entryObject.subType = Weapon.TYPE_BOW; a_entryObject.subTypeDisplay = Translator.translate("$Bow"); break; case Weapon.ANIM_STAFF: case Weapon.ANIM_STAFF2: a_entryObject.subType = Weapon.TYPE_STAFF; a_entryObject.subTypeDisplay = Translator.translate("$Staff"); break; case Weapon.ANIM_CROSSBOW: case Weapon.ANIM_CBOW: a_entryObject.subType = Weapon.TYPE_CROSSBOW; a_entryObject.subTypeDisplay = Translator.translate("$Crossbow"); break; } } private function processWeaponBaseId(a_entryObject: Object): Void { switch (a_entryObject.baseId) { case Form.BASEID_WEAPPICKAXE: case Form.BASEID_SSDROCKSPLINTERPICKAXE: case Form.BASEID_DUNVOLUNRUUDPICKAXE: a_entryObject.subType = Weapon.TYPE_PICKAXE; a_entryObject.subTypeDisplay = Translator.translate("$Pickaxe"); break; case Form.BASEID_AXE01: case Form.BASEID_DUNHALTEDSTREAMPOACHERSAXE: a_entryObject.subType = Weapon.TYPE_WOODAXE; a_entryObject.subTypeDisplay = Translator.translate("$Wood Axe"); break; } } private function processArmorPartMask(a_entryObject: Object): Void { if (a_entryObject.partMask == undefined) return; // Sets subType as the most important bitmask index. for (var i = 0; i < Armor.PARTMASK_PRECEDENCE.length; i++) { if (a_entryObject.partMask & Armor.PARTMASK_PRECEDENCE[i]) { a_entryObject.mainPartMask = Armor.PARTMASK_PRECEDENCE[i]; break; } } if (a_entryObject.mainPartMask == undefined) return; switch (a_entryObject.mainPartMask) { case Armor.PARTMASK_HEAD: a_entryObject.subType = Armor.EQUIP_HEAD; a_entryObject.subTypeDisplay = Translator.translate("$Head"); break; case Armor.PARTMASK_HAIR: a_entryObject.subType = Armor.EQUIP_HAIR; a_entryObject.subTypeDisplay = Translator.translate("$Head"); break; case Armor.PARTMASK_LONGHAIR: a_entryObject.subType = Armor.EQUIP_LONGHAIR; a_entryObject.subTypeDisplay = Translator.translate("$Head"); break; case Armor.PARTMASK_BODY: a_entryObject.subType = Armor.EQUIP_BODY; a_entryObject.subTypeDisplay = Translator.translate("$Body"); break; case Armor.PARTMASK_HANDS: a_entryObject.subType = Armor.EQUIP_HANDS; a_entryObject.subTypeDisplay = Translator.translate("$Hands"); break; case Armor.PARTMASK_FOREARMS: a_entryObject.subType = Armor.EQUIP_FOREARMS; a_entryObject.subTypeDisplay = Translator.translate("$Forearms"); break; case Armor.PARTMASK_AMULET: a_entryObject.subType = Armor.EQUIP_AMULET; a_entryObject.subTypeDisplay = Translator.translate("$Amulet"); break; case Armor.PARTMASK_RING: a_entryObject.subType = Armor.EQUIP_RING; a_entryObject.subTypeDisplay = Translator.translate("$Ring"); break; case Armor.PARTMASK_FEET: a_entryObject.subType = Armor.EQUIP_FEET; a_entryObject.subTypeDisplay = Translator.translate("$Feet"); break; case Armor.PARTMASK_CALVES: a_entryObject.subType = Armor.EQUIP_CALVES; a_entryObject.subTypeDisplay = Translator.translate("$Calves"); break; case Armor.PARTMASK_SHIELD: a_entryObject.subType = Armor.EQUIP_SHIELD; a_entryObject.subTypeDisplay = Translator.translate("$Shield"); break; case Armor.PARTMASK_CIRCLET: a_entryObject.subType = Armor.EQUIP_CIRCLET; a_entryObject.subTypeDisplay = Translator.translate("$Circlet"); break; case Armor.PARTMASK_EARS: a_entryObject.subType = Armor.EQUIP_EARS; a_entryObject.subTypeDisplay = Translator.translate("$Ears"); break; case Armor.PARTMASK_TAIL: a_entryObject.subType = Armor.EQUIP_TAIL; a_entryObject.subTypeDisplay = Translator.translate("$Tail"); break; default: a_entryObject.subType = a_entryObject.mainPartMask; break; } } private function processArmorOther(a_entryObject): Void { if (a_entryObject.weightClass != null) return; switch (a_entryObject.mainPartMask) { case Armor.PARTMASK_HEAD: case Armor.PARTMASK_HAIR: case Armor.PARTMASK_LONGHAIR: case Armor.PARTMASK_BODY: case Armor.PARTMASK_HANDS: case Armor.PARTMASK_FOREARMS: case Armor.PARTMASK_FEET: case Armor.PARTMASK_CALVES: case Armor.PARTMASK_SHIELD: case Armor.PARTMASK_TAIL: a_entryObject.weightClass = Armor.WEIGHT_CLOTHING; a_entryObject.weightClassDisplay = Translator.translate("$Clothing"); break; case Armor.PARTMASK_AMULET: case Armor.PARTMASK_RING: case Armor.PARTMASK_CIRCLET: case Armor.PARTMASK_EARS: a_entryObject.weightClass = Armor.WEIGHT_JEWELRY; a_entryObject.weightClassDisplay = Translator.translate("$Jewelry"); break; } } private function processArmorBaseId(a_entryObject: Object): Void { switch (a_entryObject.baseId) { case Form.BASEID_CLOTHESWEDDINGWREATH: a_entryObject.weightClass = Armor.WEIGHT_JEWELRY; a_entryObject.weightClassDisplay = Translator.translate("$Jewelry"); break case Form.BASEID_DLC1CLOTHESVAMPIRELORDARMOR: a_entryObject.subType = Armor.EQUIP_BODY; a_entryObject.subTypeDisplay = Translator.translate("$Body"); break; } } private function processBookType(a_entryObject: Object): Void { a_entryObject.subType = Item.OTHER; a_entryObject.subTypeDisplay = Translator.translate("$Book"); a_entryObject.isRead = ((a_entryObject.flags & Item.BOOKFLAG_READ) != 0); if (a_entryObject.bookType == Item.BOOKTYPE_NOTE) { a_entryObject.subType = Item.BOOK_NOTE; a_entryObject.subTypeDisplay = Translator.translate("$Note"); } if (a_entryObject.keywords == undefined) return; if (a_entryObject.keywords["VendorItemRecipe"] != undefined) { a_entryObject.subType = Item.BOOK_RECIPE; a_entryObject.subTypeDisplay = Translator.translate("$Recipe"); } else if (a_entryObject.keywords["VendorItemSpellTome"] != undefined) { a_entryObject.subType = Item.BOOK_SPELLTOME; a_entryObject.subTypeDisplay = Translator.translate("$Spell Tome"); } } // Mirrors logic in SKSE private function isBolt(a_entryObject: Object): Boolean { return (a_entryObject.flags & Weapon.AMMOFLAG_NONBOLT) == 0; } private function processAmmoType(a_entryObject: Object): Void { if (!isBolt(a_entryObject)) { a_entryObject.subType = Weapon.AMMO_ARROW; a_entryObject.subTypeDisplay = Translator.translate("$Arrow"); } else { a_entryObject.subType = Weapon.AMMO_BOLT; a_entryObject.subTypeDisplay = Translator.translate("$Bolt"); } } private function processAmmoBaseId(a_entryObject: Object): Void { switch (a_entryObject.baseId) { case Form.BASEID_DAEDRICARROW: a_entryObject.material = Material.DAEDRIC; a_entryObject.materialDisplay = Translator.translate("$Daedric"); break; case Form.BASEID_EBONYARROW: a_entryObject.material = Material.EBONY; a_entryObject.materialDisplay = Translator.translate("$Ebony"); break; case Form.BASEID_GLASSARROW: a_entryObject.material = Material.GLASS; a_entryObject.materialDisplay = Translator.translate("$Glass"); break; case Form.BASEID_ELVENARROW: case Form.BASEID_DLC1ELVENARROWBLESSED: case Form.BASEID_DLC1ELVENARROWBLOOD: a_entryObject.material = Material.ELVEN; a_entryObject.materialDisplay = Translator.translate("$Elven"); break; case Form.BASEID_DWARVENARROW: case Form.BASEID_DWARVENSPHEREARROW: case Form.BASEID_DWARVENSPHEREBOLT01: case Form.BASEID_DWARVENSPHEREBOLT02: case Form.BASEID_DLC2DWARVENBALLISTABOLT: a_entryObject.material = Material.DWARVEN; a_entryObject.materialDisplay = Translator.translate("$Dwarven"); break; case Form.BASEID_ORCISHARROW: a_entryObject.material = Material.ORCISH; a_entryObject.materialDisplay = Translator.translate("$Orcish"); break; case Form.BASEID_NORDHEROARROW: a_entryObject.material = Material.NORDIC; a_entryObject.materialDisplay = Translator.translate("$Nordic"); break; case Form.BASEID_DRAUGRARROW: a_entryObject.material = Material.DRAUGR; a_entryObject.materialDisplay = Translator.translate("$Draugr"); break; case Form.BASEID_FALMERARROW: a_entryObject.material = Material.FALMER; a_entryObject.materialDisplay = Translator.translate("$Falmer"); break; case Form.BASEID_STEELARROW: case Form.BASEID_MQ101STEELARROW: a_entryObject.material = Material.STEEL; a_entryObject.materialDisplay = Translator.translate("$Steel"); break; case Form.BASEID_IRONARROW: case Form.BASEID_CWARROW: case Form.BASEID_CWARROWSHORT: case Form.BASEID_TRAPDART: case Form.BASEID_DUNARCHERPRATICEARROW: case Form.BASEID_DUNGEIRMUNDSIGDISARROWSILLUSION: case Form.BASEID_FOLLOWERIRONARROW: case Form.BASEID_TESTDLC1BOLT: a_entryObject.material = Material.IRON; a_entryObject.materialDisplay = Translator.translate("$Iron"); break; case Form.BASEID_FORSWORNARROW: a_entryObject.material = Material.HIDE; a_entryObject.materialDisplay = Translator.translate("$Forsworn"); break; case Form.BASEID_DLC2RIEKLINGSPEARTHROWN: a_entryObject.material = Material.WOOD; a_entryObject.materialDisplay = Translator.translate("$Wood"); a_entryObject.subTypeDisplay = Translator.translate("$Spear"); break; } } private function processKeyType(a_entryObject: Object): Void { a_entryObject.subTypeDisplay = Translator.translate("$Key"); if (a_entryObject.infoValue <= 0) a_entryObject.infoValue = null; if (a_entryObject.infoValue <= 0) a_entryObject.infoValue = null; } private function processPotionType(a_entryObject: Object): Void { a_entryObject.subType = Item.POTION_POTION; a_entryObject.subTypeDisplay = Translator.translate("$Potion"); if ((a_entryObject.flags & Item.ALCHFLAG_FOOD) != 0) { a_entryObject.subType = Item.POTION_FOOD; a_entryObject.subTypeDisplay = Translator.translate("$Food"); // SKSE >= 1.6.6 if (a_entryObject.useSound.formId != undefined && a_entryObject.useSound.formId == Form.FORMID_ITMPotionUse) { a_entryObject.subType = Item.POTION_DRINK; a_entryObject.subTypeDisplay = Translator.translate("$Drink"); } } else if ((a_entryObject.flags & Item.ALCHFLAG_POISON) != 0) { a_entryObject.subType = Item.POTION_POISON; a_entryObject.subTypeDisplay = Translator.translate("$Poison"); } else { switch (a_entryObject.actorValue) { case Actor.AV_HEALTH: a_entryObject.subType = Item.POTION_HEALTH; a_entryObject.subTypeDisplay = Translator.translate("$Health"); break; case Actor.AV_MAGICKA: a_entryObject.subType = Item.POTION_MAGICKA; a_entryObject.subTypeDisplay = Translator.translate("$Magicka"); break; case Actor.AV_STAMINA: a_entryObject.subType = Item.POTION_STAMINA; a_entryObject.subTypeDisplay = Translator.translate("$Stamina"); break; case Actor.AV_HEALRATE: a_entryObject.subType = Item.POTION_HEALRATE; a_entryObject.subTypeDisplay = Translator.translate("$Health"); break; case Actor.AV_MAGICKARATE: a_entryObject.subType = Item.POTION_MAGICKARATE; a_entryObject.subTypeDisplay = Translator.translate("$Magicka"); break; case Actor.AV_STAMINARATE: a_entryObject.subType = Item.POTION_STAMINARATE; a_entryObject.subTypeDisplay = Translator.translate("$Stamina"); break; case Actor.AV_HEALRATEMULT: a_entryObject.subType = Item.POTION_HEALRATEMULT; a_entryObject.subTypeDisplay = Translator.translate("$Health"); break; case Actor.AV_MAGICKARATEMULT: a_entryObject.subType = Item.POTION_MAGICKARATEMULT; a_entryObject.subTypeDisplay = Translator.translate("$Magicka"); break; case Actor.AV_STAMINARATEMULT: a_entryObject.subType = Item.POTION_STAMINARATEMULT; a_entryObject.subTypeDisplay = Translator.translate("$Stamina"); break; case Actor.AV_FIRERESIST: a_entryObject.subType = Item.POTION_FIRERESIST; break; case Actor.AV_ELECTRICRESIST: a_entryObject.subType = Item.POTION_ELECTRICRESIST; break; case Actor.AV_FROSTRESIST: a_entryObject.subType = Item.POTION_FROSTRESIST; break; } } } private function processSoulGemType(a_entryObject: Object): Void { a_entryObject.subType = Item.OTHER; a_entryObject.subTypeDisplay = Translator.translate("$Soul Gem"); // Ignores soulgems that have a size of None if (a_entryObject.gemSize != undefined && a_entryObject.gemSize != Item.SOULGEM_NONE) a_entryObject.subType = a_entryObject.gemSize; } private function processSoulGemStatus(a_entryObject: Object): Void { if (a_entryObject.gemSize == undefined || a_entryObject.soulSize == undefined || a_entryObject.soulSize == Item.SOULGEM_NONE) a_entryObject.status = Item.SOULGEMSTATUS_EMPTY; else if (a_entryObject.soulSize >= a_entryObject.gemSize) a_entryObject.status = Item.SOULGEMSTATUS_FULL; else a_entryObject.status = Item.SOULGEMSTATUS_PARTIAL; } private function processSoulGemBaseId(a_entryObject: Object): Void { switch (a_entryObject.baseId) { case Form.BASEID_DA01SOULGEMBLACKSTAR: case Form.BASEID_DA01SOULGEMAZURASSTAR: a_entryObject.subType = Item.SOULGEM_AZURA; break; } } private function processMiscType(a_entryObject: Object): Void { a_entryObject.subType = Item.OTHER; a_entryObject.subTypeDisplay = Translator.translate("$Misc"); if (a_entryObject.keywords == undefined) return; if (a_entryObject.keywords["BYOHAdoptionClothesKeyword"] != undefined) { a_entryObject.subType = Item.MISC_CHILDRENSCLOTHES; a_entryObject.subTypeDisplay = Translator.translate("$Clothing"); } else if (a_entryObject.keywords["BYOHAdoptionToyKeyword"] != undefined) { a_entryObject.subType = Item.MISC_TOY; a_entryObject.subTypeDisplay = Translator.translate("$Toy"); } else if (a_entryObject.keywords["BYOHHouseCraftingCategoryWeaponRacks"] != undefined || a_entryObject.keywords["BYOHHouseCraftingCategoryShelf"] != undefined || a_entryObject.keywords["BYOHHouseCraftingCategoryFurniture"] != undefined || a_entryObject.keywords["BYOHHouseCraftingCategoryExterior"] != undefined || a_entryObject.keywords["BYOHHouseCraftingCategoryContainers"] != undefined || a_entryObject.keywords["BYOHHouseCraftingCategoryBuilding"] != undefined || a_entryObject.keywords["BYOHHouseCraftingCategorySmithing"] != undefined) { a_entryObject.subType = Item.MISC_HOUSEPART; a_entryObject.subTypeDisplay = Translator.translate("$House Part"); } else if (a_entryObject.keywords["VendorItemDaedricArtifact"] != undefined) { a_entryObject.subType = Item.MISC_ARTIFACT; a_entryObject.subTypeDisplay = Translator.translate("$Artifact"); } else if (a_entryObject.keywords["VendorItemGem"] != undefined) { a_entryObject.subType = Item.MISC_GEM; a_entryObject.subTypeDisplay = Translator.translate("$Gem"); } else if (a_entryObject.keywords["VendorItemAnimalHide"] != undefined) { a_entryObject.subType = Item.MISC_HIDE; a_entryObject.subTypeDisplay = Translator.translate("$Hide"); } else if (a_entryObject.keywords["VendorItemTool"] != undefined) { a_entryObject.subType = Item.MISC_TOOL; a_entryObject.subTypeDisplay = Translator.translate("$Tool"); } else if (a_entryObject.keywords["VendorItemAnimalPart"] != undefined) { a_entryObject.subType = Item.MISC_REMAINS; a_entryObject.subTypeDisplay = Translator.translate("$Remains"); } else if (a_entryObject.keywords["VendorItemOreIngot"] != undefined) { a_entryObject.subType = Item.MISC_INGOT; a_entryObject.subTypeDisplay = Translator.translate("$Ingot"); } else if (a_entryObject.keywords["VendorItemClutter"] != undefined) { a_entryObject.subType = Item.MISC_CLUTTER; a_entryObject.subTypeDisplay = Translator.translate("$Clutter"); } else if (a_entryObject.keywords["VendorItemFirewood"] != undefined) { a_entryObject.subType = Item.MISC_FIREWOOD; a_entryObject.subTypeDisplay = Translator.translate("$Firewood"); } } private function processMiscBaseId(a_entryObject: Object): Void { switch (a_entryObject.baseId) { case Form.BASEID_GEMAMETHYSTFLAWLESS: a_entryObject.subType = Item.MISC_GEM; a_entryObject.subTypeDisplay = Translator.translate("$Gem"); break; case Form.BASEID_RUBYDRAGONCLAW: case Form.BASEID_IVORYDRAGONCLAW: case Form.BASEID_GLASSCLAW: case Form.BASEID_EBONYCLAW: case Form.BASEID_EMERALDDRAGONCLAW: case Form.BASEID_DIAMONDCLAW: case Form.BASEID_IRONCLAW: case Form.BASEID_CORALDRAGONCLAW: case Form.BASEID_E3GOLDENCLAW: case Form.BASEID_SAPPHIREDRAGONCLAW: case Form.BASEID_MS13GOLDENCLAW: a_entryObject.subTypeDisplay = Translator.translate("$Claw"); a_entryObject.subType = Item.MISC_DRAGONCLAW; break; case Form.BASEID_LOCKPICK: a_entryObject.subType = Item.MISC_LOCKPICK; a_entryObject.subTypeDisplay = Translator.translate("$Lockpick"); break; case Form.BASEID_GOLD001: a_entryObject.subType = Item.MISC_GOLD; a_entryObject.subTypeDisplay = Translator.translate("$Gold"); break; case Form.BASEID_LEATHER01: a_entryObject.subTypeDisplay = Translator.translate("$Leather"); a_entryObject.subType = Item.MISC_LEATHER; break; case Form.BASEID_LEATHERSTRIPS: a_entryObject.subTypeDisplay = Translator.translate("$Strips"); a_entryObject.subType = Item.MISC_LEATHERSTRIPS; break; } } } ================================================ FILE: src/ItemMenus/InventoryIconSetter.as ================================================ import skyui.components.list.BasicList; import skyui.components.list.IListProcessor; import skyui.defines.Actor; import skyui.defines.Armor; import skyui.defines.Form; import skyui.defines.Item; import skyui.defines.Material; import skyui.defines.Weapon; class InventoryIconSetter implements IListProcessor { /* PRIVATE VARIABLES */ private var _noIconColors: Boolean; /* INITIALIZATION */ public function InventoryIconSetter(a_configAppearance: Object) { _noIconColors = a_configAppearance.icons.item.noColor; } /* PUBLIC FUNCTIONS */ // @override IListProcessor public function processList(a_list: BasicList): Void { var entryList: Array = a_list.entryList; for (var i: Number = 0; i < entryList.length; i++) processEntry(entryList[i]); } /* PRIVATE FUNCTIONS */ private function processEntry(a_entryObject: Object): Void { switch (a_entryObject.formType) { case Form.TYPE_SCROLLITEM: a_entryObject.iconLabel = "default_scroll"; processResist(a_entryObject); break; case Form.TYPE_ARMOR: processArmorIcon(a_entryObject); break; case Form.TYPE_BOOK: processBookIcon(a_entryObject); break; case Form.TYPE_INGREDIENT: a_entryObject.iconLabel = "default_ingredient"; break; case Form.TYPE_LIGHT: a_entryObject.iconLabel = "misc_torch"; break; case Form.TYPE_MISC: processMiscIcon(a_entryObject); break; case Form.TYPE_WEAPON: processWeaponIcon(a_entryObject); break; case Form.TYPE_AMMO: processAmmoIcon(a_entryObject); break; case Form.TYPE_KEY: a_entryObject.iconLabel = "default_key"; break; case Form.TYPE_POTION: processPotionIcon(a_entryObject); break; case Form.TYPE_SOULGEM: processSoulGemIcon(a_entryObject); break; } if (_noIconColors && a_entryObject.iconColor != undefined) delete(a_entryObject.iconColor); } private function processResist(a_entryObject: Object): Void { if (a_entryObject.resistance == undefined || a_entryObject.resistance == Actor.AV_NONE) return; switch(a_entryObject.resistance) { case Actor.AV_FIRERESIST: a_entryObject.iconColor = 0xC73636; break; case Actor.AV_ELECTRICRESIST: a_entryObject.iconColor = 0xFFFF00; break; case Actor.AV_FROSTRESIST: a_entryObject.iconColor = 0x1FFBFF; break; } } private function processArmorIcon(a_entryObject: Object): Void { a_entryObject.iconLabel = "default_armor"; a_entryObject.iconColor = 0xEDDA87; switch (a_entryObject.weightClass) { case Armor.WEIGHT_LIGHT: processLightArmorIcon(a_entryObject); break; case Armor.WEIGHT_HEAVY: processHeavyArmorIcon(a_entryObject); break; case Armor.WEIGHT_JEWELRY: processJewelryArmorIcon(a_entryObject); break; case Armor.WEIGHT_CLOTHING: default: processClothingArmorIcon(a_entryObject); break; } } private function processLightArmorIcon(a_entryObject: Object): Void { a_entryObject.iconColor = 0x756000; switch(a_entryObject.subType) { case Armor.EQUIP_HEAD: case Armor.EQUIP_HAIR: case Armor.EQUIP_LONGHAIR: a_entryObject.iconLabel = "lightarmor_head"; break; case Armor.EQUIP_BODY: case Armor.EQUIP_TAIL: a_entryObject.iconLabel = "lightarmor_body"; break; case Armor.EQUIP_HANDS: a_entryObject.iconLabel = "lightarmor_hands"; break; case Armor.EQUIP_FOREARMS: a_entryObject.iconLabel = "lightarmor_forearms"; break; case Armor.EQUIP_FEET: a_entryObject.iconLabel = "lightarmor_feet"; break; case Armor.EQUIP_CALVES: a_entryObject.iconLabel = "lightarmor_calves"; break; case Armor.EQUIP_SHIELD: a_entryObject.iconLabel = "lightarmor_shield"; break; case Armor.EQUIP_AMULET: case Armor.EQUIP_RING: case Armor.EQUIP_CIRCLET: case Armor.EQUIP_EARS: processJewelryArmorIcon(a_entryObject); break; } } private function processHeavyArmorIcon(a_entryObject: Object): Void { a_entryObject.iconColor = 0x6B7585; switch(a_entryObject.subType) { case Armor.EQUIP_HEAD: case Armor.EQUIP_HAIR: case Armor.EQUIP_LONGHAIR: a_entryObject.iconLabel = "armor_head"; break; case Armor.EQUIP_BODY: case Armor.EQUIP_TAIL: a_entryObject.iconLabel = "armor_body"; break; case Armor.EQUIP_HANDS: a_entryObject.iconLabel = "armor_hands"; break; case Armor.EQUIP_FOREARMS: a_entryObject.iconLabel = "armor_forearms"; break; case Armor.EQUIP_FEET: a_entryObject.iconLabel = "armor_feet"; break; case Armor.EQUIP_CALVES: a_entryObject.iconLabel = "armor_calves"; break; case Armor.EQUIP_SHIELD: a_entryObject.iconLabel = "armor_shield"; break; case Armor.EQUIP_AMULET: case Armor.EQUIP_RING: case Armor.EQUIP_CIRCLET: case Armor.EQUIP_EARS: processJewelryArmorIcon(a_entryObject); break; } } private function processJewelryArmorIcon(a_entryObject: Object): Void { switch(a_entryObject.subType) { case Armor.EQUIP_AMULET: a_entryObject.iconLabel = "armor_amulet"; break; case Armor.EQUIP_RING: a_entryObject.iconLabel = "armor_ring"; break; case Armor.EQUIP_CIRCLET: a_entryObject.iconLabel = "armor_circlet"; break; case Armor.EQUIP_EARS: break; } } private function processClothingArmorIcon(a_entryObject: Object): Void { switch(a_entryObject.subType) { case Armor.EQUIP_HEAD: case Armor.EQUIP_HAIR: case Armor.EQUIP_LONGHAIR: a_entryObject.iconLabel = "clothing_head"; break; case Armor.EQUIP_BODY: case Armor.EQUIP_TAIL: a_entryObject.iconLabel = "clothing_body"; break; case Armor.EQUIP_HANDS: a_entryObject.iconLabel = "clothing_hands"; break; case Armor.EQUIP_FOREARMS: a_entryObject.iconLabel = "clothing_forearms"; break; case Armor.EQUIP_FEET: a_entryObject.iconLabel = "clothing_feet"; break; case Armor.EQUIP_CALVES: a_entryObject.iconLabel = "clothing_calves"; break; case Armor.EQUIP_SHIELD: a_entryObject.iconLabel = "clothing_shield"; break; case Armor.EQUIP_EARS: break; } } // Books private function processBookIcon(a_entryObject: Object): Void { a_entryObject.iconLabel = "default_book"; switch(a_entryObject.subType) { case Item.BOOK_RECIPE: case Item.BOOK_NOTE: a_entryObject.iconLabel = "book_note"; break; case Item.BOOK_SPELLTOME: a_entryObject.iconLabel = "book_tome"; break; } } // Weapons private function processWeaponIcon(a_entryObject: Object): Void { a_entryObject.iconLabel = "default_weapon"; a_entryObject.iconColor = 0xA4A5BF; switch(a_entryObject.subType) { case Weapon.TYPE_MELEE: break; case Weapon.TYPE_SWORD: a_entryObject.iconLabel = "weapon_sword"; break; case Weapon.TYPE_DAGGER: a_entryObject.iconLabel = "weapon_dagger"; break; case Weapon.TYPE_WARAXE: a_entryObject.iconLabel = "weapon_waraxe"; break; case Weapon.TYPE_MACE: a_entryObject.iconLabel = "weapon_mace"; break; case Weapon.TYPE_GREATSWORD: a_entryObject.iconLabel = "weapon_greatsword"; break; case Weapon.TYPE_BATTLEAXE: a_entryObject.iconLabel = "weapon_battleaxe"; break; case Weapon.TYPE_WARHAMMER: a_entryObject.iconLabel = "weapon_hammer"; break; case Weapon.TYPE_BOW: a_entryObject.iconLabel = "weapon_bow"; break; case Weapon.TYPE_STAFF: a_entryObject.iconLabel = "weapon_staff"; break; case Weapon.TYPE_CROSSBOW: a_entryObject.iconLabel = "weapon_crossbow"; break; case Weapon.TYPE_PICKAXE: a_entryObject.iconLabel = "weapon_pickaxe"; break; case Weapon.TYPE_WOODAXE: a_entryObject.iconLabel = "weapon_woodaxe"; break; } } // Ammo private function processAmmoIcon(a_entryObject: Object): Void { a_entryObject.iconLabel = "weapon_arrow"; a_entryObject.iconColor = 0xA89E8C; switch(a_entryObject.subType) { case Weapon.AMMO_ARROW: a_entryObject.iconLabel = "weapon_arrow"; break; case Weapon.AMMO_BOLT: a_entryObject.iconLabel = "weapon_bolt"; break; } } private function processPotionIcon(a_entryObject: Object): Void { a_entryObject.iconLabel = "default_potion"; switch(a_entryObject.subType) { case Item.POTION_DRINK: a_entryObject.iconLabel = "food_wine"; break; case Item.POTION_FOOD: a_entryObject.iconLabel = "default_food"; break; case Item.POTION_POISON: a_entryObject.iconLabel = "potion_poison"; a_entryObject.iconColor = 0xAD00B3; break; case Item.POTION_HEALTH: case Item.POTION_HEALRATE: case Item.POTION_HEALRATEMULT: a_entryObject.iconLabel = "potion_health"; a_entryObject.iconColor = 0xDB2E73; break; case Item.POTION_MAGICKA: case Item.POTION_MAGICKARATE: case Item.POTION_MAGICKARATEMULT: a_entryObject.iconLabel = "potion_magic"; a_entryObject.iconColor = 0x2E9FDB; break; case Item.POTION_STAMINA: case Item.POTION_STAMINARATE: case Item.POTION_STAMINARATEMULT: a_entryObject.iconLabel = "potion_stam"; a_entryObject.iconColor = 0x51DB2E; break; case Item.POTION_FIRERESIST: a_entryObject.iconLabel = "potion_fire"; a_entryObject.iconColor = 0xC73636; break; case Item.POTION_ELECTRICRESIST: a_entryObject.iconLabel = "potion_shock"; a_entryObject.iconColor = 0xEAAB00; break; case Item.POTION_FROSTRESIST: a_entryObject.iconLabel = "potion_frost"; a_entryObject.iconColor = 0x1FFBFF; break; } } private function processSoulGemIcon(a_entryObject: Object): Void { a_entryObject.iconLabel = "misc_soulgem"; a_entryObject.iconColor = 0xE3E0FF; switch(a_entryObject.subType) { case Item.SOULGEM_PETTY: a_entryObject.iconColor = 0xD7D4FF; processSoulGemStatusIcon(a_entryObject); break; case Item.SOULGEM_LESSER: a_entryObject.iconColor = 0xC0BAFF; processSoulGemStatusIcon(a_entryObject); break; case Item.SOULGEM_COMMON: a_entryObject.iconColor = 0xABA3FF; processSoulGemStatusIcon(a_entryObject); break; case Item.SOULGEM_GREATER: a_entryObject.iconColor = 0x948BFC; processGrandSoulGemIcon(a_entryObject); break; case Item.SOULGEM_GRAND: a_entryObject.iconColor = 0x7569FF; processGrandSoulGemIcon(a_entryObject); break; case Item.SOULGEM_AZURA: a_entryObject.iconColor = 0x7569FF; a_entryObject.iconLabel = "soulgem_azura"; break; } } private function processGrandSoulGemIcon(a_entryObject: Object): Void { switch(a_entryObject.status) { case Item.SOULGEMSTATUS_EMPTY: a_entryObject.iconLabel = "soulgem_grandempty"; break; case Item.SOULGEMSTATUS_FULL: a_entryObject.iconLabel = "soulgem_grandfull"; break; case Item.SOULGEMSTATUS_PARTIAL: a_entryObject.iconLabel = "soulgem_grandpartial"; break; } } private function processSoulGemStatusIcon(a_entryObject: Object): Void { switch(a_entryObject.status) { case Item.SOULGEMSTATUS_EMPTY: a_entryObject.iconLabel = "soulgem_empty"; break; case Item.SOULGEMSTATUS_FULL: a_entryObject.iconLabel = "soulgem_full"; break; case Item.SOULGEMSTATUS_PARTIAL: a_entryObject.iconLabel = "soulgem_partial"; break; } } private function processMiscIcon(a_entryObject: Object): Void { a_entryObject.iconLabel = "default_misc"; switch(a_entryObject.subType) { case Item.MISC_ARTIFACT: a_entryObject.iconLabel = "misc_artifact"; break; case Item.MISC_GEM: a_entryObject.iconLabel = "misc_gem"; a_entryObject.iconColor = 0xFFB0D1; break; case Item.MISC_HIDE: a_entryObject.iconLabel = "misc_hide"; a_entryObject.iconColor = 0xDBB36E; break; case Item.MISC_REMAINS: a_entryObject.iconLabel = "misc_remains"; break; case Item.MISC_INGOT: a_entryObject.iconLabel = "misc_ingot"; //"misc_ore" a_entryObject.iconColor = 0x828282; break; case Item.MISC_CLUTTER: a_entryObject.iconLabel = "misc_clutter"; break; case Item.MISC_FIREWOOD: a_entryObject.iconLabel = "misc_wood"; a_entryObject.iconColor = 0xA89E8C; break; case Item.MISC_DRAGONCLAW: a_entryObject.iconLabel = "misc_dragonclaw"; break; case Item.MISC_LOCKPICK: a_entryObject.iconLabel = "misc_lockpick"; break; case Item.MISC_GOLD: a_entryObject.iconLabel = "misc_gold"; a_entryObject.iconColor = 0xCCCC33; break; case Item.MISC_LEATHER: a_entryObject.iconLabel = "misc_leather"; a_entryObject.iconColor = 0xBA8D23; break; case Item.MISC_LEATHERSTRIPS: a_entryObject.iconLabel = "misc_strips"; a_entryObject.iconColor = 0xBA8D23; break; case Item.MISC_CHILDRENSCLOTHES: a_entryObject.iconColor = 0xEDDA87; a_entryObject.iconLabel = "clothing_body"; break; // Maybe use later? // ... or not. /* case Item.MISC_TOOL: break; case Item.MISC_TOY: break; case Item.MISC_HOUSEPART: break; */ } } } // skyui.util.Debug.dump(a_entryObject["text"], a_entryObject); ================================================ FILE: src/ItemMenus/InventoryListEntry.as ================================================ import flash.geom.ColorTransform; import flash.geom.Transform; import skyui.components.list.TabularList; import skyui.components.list.TabularListEntry; import skyui.components.list.ListState; import skyui.util.ConfigManager; import skyui.util.Debug; class InventoryListEntry extends TabularListEntry { /* CONSTANTS */ private static var STATES = ["None", "Equipped", "LeftEquip", "RightEquip", "LeftAndRightEquip"]; /* PRIVATE VARIABLES */ private var _iconLabel: String; private var _iconColor: Number; /* STAGE ELMENTS */ public var itemIcon: MovieClip; public var equipIcon: MovieClip; public var bestIcon: MovieClip; public var favoriteIcon: MovieClip; public var poisonIcon: MovieClip; public var stolenIcon: MovieClip; public var enchIcon: MovieClip; public var readIcon: MovieClip; public var newItemIndicator: MovieClip; /* INITIALIZATION */ // @override TabularListEntry public function initialize(a_index: Number, a_state: ListState): Void { super.initialize(); var iconLoader = new MovieClipLoader(); iconLoader.addListener(this); iconLoader.loadClip(a_state.iconSource, itemIcon); itemIcon._visible = false; equipIcon._visible = false; for (var i = 0; this["textField" + i] != undefined; i++) this["textField" + i]._visible = false; } /* PUBLIC FUNCTIONS */ // @override TabularListEntry public function setSpecificEntryLayout(a_entryObject: Object, a_state: ListState): Void { var iconY = TabularList(a_state.list).layout.entryHeight * 0.25; var iconSize = TabularList(a_state.list).layout.entryHeight * 0.5; bestIcon._height = bestIcon._width = iconSize; favoriteIcon._height = favoriteIcon._width = iconSize; poisonIcon._height = poisonIcon._width = iconSize; stolenIcon._height = stolenIcon._width = iconSize; enchIcon._height = enchIcon._width = iconSize; readIcon._height = readIcon._width = iconSize; bestIcon._y = iconY; favoriteIcon._y = iconY; poisonIcon._y = iconY; stolenIcon._y = iconY; enchIcon._y = iconY; readIcon._y = iconY; } // @override TabularListEntry public function formatEquipIcon(a_entryField: Object, a_entryObject: Object, a_state: ListState): Void { if (a_entryObject != undefined && a_entryObject.equipState != undefined) { a_entryField.gotoAndStop(STATES[a_entryObject.equipState]); } else { a_entryField.gotoAndStop("None"); } } // @override TabularListEntry public function formatItemIcon(a_entryField: Object, a_entryObject: Object, a_state: ListState) { _iconLabel = a_entryObject["iconLabel"] != undefined ? a_entryObject["iconLabel"] : "default_misc"; _iconColor = a_entryObject["iconColor"]; // Could return here if _iconLoaded is false a_entryField.gotoAndStop(_iconLabel); changeIconColor(MovieClip(a_entryField), _iconColor); } // @override TabularListEntry public function formatName(a_entryField: Object, a_entryObject: Object, a_state: ListState): Void { if (a_entryObject.text == undefined) { a_entryField.SetText(" "); return; } // Text var text = a_entryObject.text; if (a_entryObject.soulLVL != undefined) { text = text + " (" + a_entryObject.soulLVL + ")"; } if (a_entryObject.count > 1) { text = text + " (" + a_entryObject.count.toString() + ")"; } if (text.length > a_state.maxTextLength) { text = text.substr(0, a_state.maxTextLength - 3) + "..."; } a_entryField.autoSize = "left"; a_entryField.SetText(text); formatColor(a_entryField, a_entryObject, a_state); // BestInClass icon var iconPos = a_entryField._x + a_entryField._width + 5; // All icons have the same size var iconSpace = bestIcon._width * 1.25; // FIXME!!! Need a better to figure out if we're actually looking at the player's inventory. // Presumably, the player container is always shown as the "right" segment. var shouldShowNewIndicator = false if(a_state.categoryList) { if (a_state.categoryList.activeSegment == CategoryList.RIGHT_SEGMENT && a_entryObject.newItem == true) { shouldShowNewIndicator = true } } else if (a_entryObject.newItem == true) { shouldShowNewIndicator = true } newItemIndicator._visible = shouldShowNewIndicator; newItemIndicator._height = this._height - 2.5; if (a_entryObject.bestInClass == true) { bestIcon._x = iconPos; iconPos = iconPos + iconSpace; bestIcon.gotoAndStop("show"); } else { bestIcon.gotoAndStop("hide"); } // Fav icon if (a_entryObject.favorite == true) { favoriteIcon._x = iconPos; iconPos = iconPos + iconSpace; favoriteIcon.gotoAndStop("show"); } else { favoriteIcon.gotoAndStop("hide"); } // Poisoned Icon if (a_entryObject.isPoisoned == true) { poisonIcon._x = iconPos; iconPos = iconPos + iconSpace; poisonIcon.gotoAndStop("show"); } else { poisonIcon.gotoAndStop("hide"); } // Stolen Icon if ((a_entryObject.isStolen == true || a_entryObject.isStealing == true) && a_state.showStolenIcon == true) { stolenIcon._x = iconPos; iconPos = iconPos + iconSpace; stolenIcon.gotoAndStop("show"); } else { stolenIcon.gotoAndStop("hide"); } // Enchanted Icon if (a_entryObject.isEnchanted == true) { enchIcon._x = iconPos; iconPos = iconPos + iconSpace; enchIcon.gotoAndStop("show"); } else { enchIcon.gotoAndStop("hide"); } // Enchanted Icon if (a_entryObject.isRead == true) { readIcon._x = iconPos; iconPos = iconPos + iconSpace; readIcon.gotoAndStop("show"); } else { readIcon.gotoAndStop("hide"); } } // @override TabularEntry public function formatText(a_entryField: Object, a_entryObject: Object, a_state: ListState): Void { formatColor(a_entryField, a_entryObject, a_state); } /* PRIVATE FUNCTIONS */ // @implements MovieClipLoader private function onLoadInit(a_icon: MovieClip): Void { a_icon.gotoAndStop(_iconLabel); changeIconColor(a_icon, _iconColor); } private function formatColor(a_entryField: Object, a_entryObject: Object, a_state: ListState): Void { // Negative Effect if (a_entryObject.negativeEffect == true) a_entryField.textColor = a_entryObject.enabled == false ? a_state.negativeDisabledColor : a_state.negativeEnabledColor; // Stolen else if (a_entryObject.infoIsStolen == true || a_entryObject.isStealing == true) a_entryField.textColor = a_entryObject.enabled == false ? a_state.stolenDisabledColor : a_state.stolenEnabledColor; // Default else a_entryField.textColor = a_entryObject.enabled == false ? a_state.defaultDisabledColor : a_state.defaultEnabledColor; } private function changeIconColor(a_icon: MovieClip, a_rgb: Number): Void { var element: Object; for (var e: String in a_icon) { element = a_icon[e]; if (element instanceof MovieClip) { //Note: Could check if all values of RGBA mult and .rgb are all the same then skip var ct: ColorTransform = new ColorTransform(); var tf: Transform = new Transform(MovieClip(element)); // Could return here if (a_rgb == tf.colorTransform.rgb && a_rgb != undefined) ct.rgb = (a_rgb == undefined)? 0xFFFFFF: a_rgb; tf.colorTransform = ct; // Shouldn't be necessary to recurse since we don't expect multiple clip depths for an icon //changeIconColor(element, a_rgb); } } } } ================================================ FILE: src/ItemMenus/InventoryLists.as ================================================ import gfx.io.GameDelegate; import gfx.ui.NavigationCode; import gfx.ui.InputDetails; import gfx.events.EventDispatcher; import gfx.managers.FocusHandler; import gfx.controls.Button; import Shared.GlobalFunc; import skyui.components.SearchWidget; import skyui.components.TabBar; import skyui.components.list.FilteredEnumeration; import skyui.components.list.BasicEnumeration; import skyui.components.list.TabularList; import skyui.components.list.SortedListHeader; import skyui.filter.ItemTypeFilter; import skyui.filter.NameFilter; import skyui.filter.SortFilter; import skyui.util.ConfigManager; import skyui.util.GlobalFunctions; import skyui.util.Translator; import skyui.util.DialogManager; import skyui.util.Debug; import skyui.defines.Input; class InventoryLists extends MovieClip { #include "../version.as" /* CONSTANTS */ static var HIDE_PANEL = 0; static var SHOW_PANEL = 1; static var TRANSITIONING_TO_HIDE_PANEL = 2; static var TRANSITIONING_TO_SHOW_PANEL = 3; /* STAGE ELEMENTS */ public var panelContainer: MovieClip; public var zoomButtonHolder: MovieClip; /* PRIVATE VARIABLES */ private var _typeFilter: ItemTypeFilter; private var _nameFilter: NameFilter; private var _sortFilter: SortFilter; private var _platform: Number; private var _currCategoryIndex: Number; private var _savedSelectionIndex: Number = -1; private var _searchKey: Number = -1; private var _switchTabKey: Number = -1; private var _sortOrderKey: Number = -1; private var _sortOrderKeyHeld: Boolean = false; private var _bTabbed = false; private var _leftTabText: String; private var _rightTabText: String; private var _columnSelectDialog: MovieClip; private var _columnSelectInterval: Number; private var _categoryChanged: Boolean; private var _categorySelections: Object; /* PROPERTIES */ public var itemList: TabularList; public var categoryList: CategoryList; public var tabBar: TabBar; public var searchWidget: SearchWidget; public var categoryLabel: MovieClip; public var columnSelectButton: Button; private var _currentState: Number; public function get currentState() { return _currentState; } public function set currentState(a_newState: Number) { if (a_newState == SHOW_PANEL) FocusHandler.instance.setFocus(itemList,0); _currentState = a_newState; } private var _tabBarIconArt: Array; public function set tabBarIconArt(a_iconArt: Array) { _tabBarIconArt = a_iconArt; if (tabBar) tabBar.setIcons(_tabBarIconArt[0], _tabBarIconArt[1]); } public function get tabBarIconArt(): Array { return _tabBarIconArt; } /* INITIALIZATION */ public function InventoryLists() { super(); GlobalFunctions.addArrayFunctions(); EventDispatcher.initialize(this); gotoAndStop("NoPanels"); GameDelegate.addCallBack("SetCategoriesList", this, "SetCategoriesList"); GameDelegate.addCallBack("InvalidateListData", this, "InvalidateListData"); _typeFilter = new ItemTypeFilter(); _nameFilter = new NameFilter(); _sortFilter = new SortFilter(); categoryList = panelContainer.categoryList; categoryLabel = panelContainer.categoryLabel; itemList = panelContainer.itemList; searchWidget = panelContainer.searchWidget; columnSelectButton = panelContainer.columnSelectButton; ConfigManager.registerLoadCallback(this, "onConfigLoad"); ConfigManager.registerUpdateCallback(this, "onConfigUpdate"); } private function onLoad(): Void { categoryList.listEnumeration = new BasicEnumeration(categoryList.entryList); var listEnumeration = new FilteredEnumeration(itemList.entryList); listEnumeration.addFilter(_typeFilter); listEnumeration.addFilter(_nameFilter); listEnumeration.addFilter(_sortFilter); itemList.listEnumeration = listEnumeration; // data processors are initialized by the top-level menu since they differ in each case itemList.listState.maxTextLength = 80; _typeFilter.addEventListener("filterChange", this, "onFilterChange"); _nameFilter.addEventListener("filterChange", this, "onFilterChange"); _sortFilter.addEventListener("filterChange", this, "onFilterChange"); categoryList.addEventListener("itemPress", this, "onCategoriesItemPress"); categoryList.addEventListener("itemPressAux", this, "onCategoriesItemPress"); categoryList.addEventListener("selectionChange", this, "onCategoriesListSelectionChange"); itemList.disableInput = false; itemList.addEventListener("selectionChange", this, "onItemsListSelectionChange"); itemList.addEventListener("sortChange", this, "onSortChange"); itemList.addEventListener("listUpdated", this, "onItemsListUpdate"); searchWidget.addEventListener("inputStart", this, "onSearchInputStart"); searchWidget.addEventListener("inputEnd", this, "onSearchInputEnd"); searchWidget.addEventListener("inputChange", this, "onSearchInputChange"); columnSelectButton.addEventListener("press", this, "onColumnSelectButtonPress"); } /* PUBLIC FUNCTIONS */ // @mixin by gfx.events.EventDispatcher public var dispatchEvent: Function; public var dispatchQueue: Function; public var hasEventListener: Function; public var addEventListener: Function; public var removeEventListener: Function; public var removeAllEventListeners: Function; public var cleanUpEvents: Function; // @mixin by Shared.GlobalFunc public var Lock: Function; public function InitExtensions(): Void { // Delay updates until config is ready categoryList.suspended = true; itemList.suspended = true; } public function showPanel(a_bPlayBladeSound: Boolean): Void { // Release itemlist for updating categoryList.suspended = false; itemList.suspended = false; _currentState = TRANSITIONING_TO_SHOW_PANEL; gotoAndPlay("PanelShow"); dispatchEvent({type:"categoryChange", index:categoryList.selectedIndex}); if (a_bPlayBladeSound != false) GameDelegate.call("PlaySound",["UIMenuBladeOpenSD"]); } public function hidePanel(): Void { _currentState = TRANSITIONING_TO_HIDE_PANEL; gotoAndPlay("PanelHide"); GameDelegate.call("PlaySound",["UIMenuBladeCloseSD"]); } public function enableTabBar(): Void { _bTabbed = true; panelContainer.gotoAndPlay("tabbed"); itemList.listHeight = 480; } public function setPlatform(a_platform: Number, a_bPS3Switch: Boolean): Void { _platform = a_platform; categoryList.setPlatform(a_platform,a_bPS3Switch); itemList.setPlatform(a_platform,a_bPS3Switch); } public function classname(): String { return "Class InventoryLists"; } // @GFx public function handleInput(details: InputDetails, pathToFocus: Array): Boolean { if (_currentState != SHOW_PANEL) return false; if (_platform != 0) { if (details.skseKeycode == _sortOrderKey) { if (details.value == "keyDown") { _sortOrderKeyHeld = true; if (_columnSelectDialog) DialogManager.close(); else _columnSelectInterval = setInterval(this, "onColumnSelectButtonPress", 1000, {type: "timeout"}); return true; } else if (details.value == "keyUp") { _sortOrderKeyHeld = false; if (_columnSelectInterval == undefined) // keyPress handled: Key was released after the interval expired, don't process any further return true; // keyPress not handled: Clear intervals and change value to keyDown to be processed later clearInterval(_columnSelectInterval); delete(_columnSelectInterval); // Continue processing the event as a normal keyDown event details.value = "keyDown"; } else if (_sortOrderKeyHeld && details.value == "keyHold") { // Fix for opening journal menu while key is depressed // For some reason this is the only time we receive a keyHold event _sortOrderKeyHeld = false; if (_columnSelectDialog) DialogManager.close(); return true; } } if (_sortOrderKeyHeld) // Disable extra input while interval is active return true; } if (GlobalFunc.IsKeyPressed(details)) { // Search hotkey (default space) /* if (details.skseKeycode == _searchKey) { searchWidget.startInput(); return true; } */ /* if (details.navEquivalent == "down") { Debug.log("InventoryLists triggering search start"); searchWidget.startInput(); return true; } */ // Toggle tab (default ALT) if (tabBar != undefined && details.skseKeycode == _switchTabKey) { tabBar.tabToggle(); return true; } } if (categoryList.handleInput(details, pathToFocus)) return true; var nextClip = pathToFocus.shift(); return nextClip.handleInput(details, pathToFocus); } public function getContentBounds():Array { var lb = panelContainer.ListBackground; return [lb._x, lb._y, lb._width, lb._height]; } public function showItemsList(): Void { // Save the previous selection in the category var prevCategory = categoryList.lastSelectedIndex; _categorySelections[prevCategory] = { selectedIndex: itemList.selectedIndex, scrollPosition: itemList.scrollPosition }; _currCategoryIndex = categoryList.selectedIndex; categoryLabel.textField.SetText(categoryList.selectedEntry.text); // Start with no selection itemList.selectedIndex = -1; itemList.scrollPosition = 0; if (categoryList.selectedEntry != undefined) { // Set filter type _typeFilter.changeFilterFlag(categoryList.selectedEntry.flag); // Not set yet before the config is loaded itemList.layout.changeFilterFlag(categoryList.selectedEntry.flag); } itemList.requestUpdate(); dispatchEvent({type:"itemHighlightChange", index:itemList.selectedIndex}); itemList.disableInput = false; } // Called to initially set the category list. // @API public function SetCategoriesList(): Void { var textOffset = 0; var flagOffset = 1; var bDontHideOffset = 2; var len = 3; categoryList.clearList(); _categorySelections = new Array(); for (var i = 0, index = 0; i < arguments.length; i = i + len, index++) { var entry = {text:arguments[i + textOffset], flag:arguments[i + flagOffset], bDontHide:arguments[i + bDontHideOffset], savedItemIndex:0, filterFlag:arguments[i + bDontHideOffset] == true ? (1) : (0)}; categoryList.entryList.push(entry); if (entry.flag == 0) categoryList.dividerIndex = index; _categorySelections.push(undefined); } // Initialize tabbar labels and replace text of segment heads (name -> ALL) if (_bTabbed) { // Restore 0 as default index for tabbed lists categoryList.selectedIndex = 0; _leftTabText = categoryList.entryList[0].text; _rightTabText = categoryList.entryList[categoryList.dividerIndex + 1].text categoryList.entryList[0].text = categoryList.entryList[categoryList.dividerIndex + 1].text = "$ALL"; } categoryList.InvalidateData(); } // Called whenever the underlying entryList data is updated (using an item, equipping etc.) // @API public function InvalidateListData(): Void { var flag = categoryList.selectedEntry.flag; for (var i = 0; i < categoryList.entryList.length; i++) categoryList.entryList[i].filterFlag = categoryList.entryList[i].bDontHide ? 1 : 0; itemList.InvalidateData(); // Set filter flag = 1 for non-empty categories with bDontHideOffset=false for (var i = 0; i < itemList.entryList.length; i++) { for (var j = 0; j < categoryList.entryList.length; ++j) { if (categoryList.entryList[j].filterFlag != 0) continue; if (itemList.entryList[i].filterFlag & categoryList.entryList[j].flag) categoryList.entryList[j].filterFlag = 1; } } categoryList.UpdateList(); if (flag != categoryList.selectedEntry.flag) { // Triggers an update if filter flag changed _typeFilter.itemFilter = categoryList.selectedEntry.flag; dispatchEvent({type:"categoryChange", index:categoryList.selectedIndex}); } // This is called when an ItemCard list closes(ex. ShowSoulGemList) to refresh ItemCard data if (itemList.selectedIndex == -1) dispatchEvent({type:"showItemsList", index: -1}); else dispatchEvent({type:"itemHighlightChange", index:itemList.selectedIndex}); } /* PRIVATE FUNCTIONS */ private function onConfigLoad(event: Object): Void { var config = event.config; _searchKey = config["Input"].controls.pc.search; if (_platform == 0) _switchTabKey = config["Input"].controls.pc.switchTab; else { _switchTabKey = config["Input"].controls.gamepad.switchTab; _sortOrderKey = config["Input"].controls.gamepad.sortOrder; } } private function onFilterChange(): Void { itemList.requestInvalidate(); } private function onTabBarLoad(): Void { tabBar = panelContainer.tabBar; tabBar.setIcons(_tabBarIconArt[0], _tabBarIconArt[1]); tabBar.addEventListener("tabPress", this, "onTabPress"); if (categoryList.dividerIndex != -1) tabBar.setLabelText(_leftTabText, _rightTabText); } private function onColumnSelectButtonPress(event: Object): Void { if (event.type == "timeout") { clearInterval(_columnSelectInterval); delete(_columnSelectInterval); } if (_columnSelectDialog) { DialogManager.close(); return; } openColumnSelectDialog(); } public function openColumnSelectDialog(): Void { // Don't do anything if the dialog is already opened if (_columnSelectDialog) { return; } // Setup and open the dialog _savedSelectionIndex = itemList.selectedIndex; itemList.selectedIndex = -1; categoryList.disableSelection = categoryList.disableInput = true; itemList.disableSelection = itemList.disableInput = true; searchWidget.isDisabled = true; _columnSelectDialog = DialogManager.open(panelContainer, "ColumnSelectDialog", {_x: 554, _y: 35, layout: itemList.layout}); _columnSelectDialog.addEventListener("dialogClosed", this, "onColumnSelectDialogClosed"); } private function onColumnSelectDialogClosed(event: Object): Void { categoryList.disableSelection = categoryList.disableInput = false; itemList.disableSelection = itemList.disableInput = false; searchWidget.isDisabled = false; itemList.selectedIndex = _savedSelectionIndex; } private function onConfigUpdate(event: Object): Void { itemList.layout.refresh(); } private function onCategoriesItemPress(): Void { showItemsList(); } public function toggleTab(): Void { var newTab = tabBar.activeTab == TabBar.LEFT_TAB ? TabBar.RIGHT_TAB : TabBar.LEFT_TAB; switchTab(newTab); } public function switchTab(newTab: Number): Void { if (categoryList.disableSelection || categoryList.disableInput || itemList.disableSelection || itemList.disableInput) return; if (newTab == TabBar.LEFT_TAB) { tabBar.activeTab = TabBar.LEFT_TAB; categoryList.activeSegment = CategoryList.LEFT_SEGMENT; } else if (newTab == TabBar.RIGHT_TAB) { tabBar.activeTab = TabBar.RIGHT_TAB; categoryList.activeSegment = CategoryList.RIGHT_SEGMENT; } GameDelegate.call("PlaySound",["UIMenuBladeOpenSD"]); showItemsList(); } private function onTabPress(event: Object): Void { switchTab(event.index); } private function onCategoriesListSelectionChange(event: Object): Void { _categoryChanged = true; dispatchEvent({type:"categoryChange", index:event.index}); if (event.index != -1) GameDelegate.call("PlaySound",["UIMenuFocus"]); } private function onItemsListSelectionChange(event: Object): Void { dispatchEvent({type:"itemHighlightChange", index:event.index}); if (event.index != -1) GameDelegate.call("PlaySound",["UIMenuFocus"]); } private function onSortChange(event: Object): Void { _sortFilter.setSortBy(event.attributes, event.options); } private function onItemsListUpdate(): Void { if(!_categoryChanged) return; // The items list was just updated because the selected // category changed. // Restore the selected item and scroll position settings. // This is needed because it's quite easy to accidentally // switch catetory by accdient while using the VR trackpad. // In these case, we want to be able to return to the previous // category and retain our position in the list. If the scroll // position always returned to the top of the list, this makes // navigating large inventory lists very difficult. // If we can find a previously saved selection setting for this // category, restore it now. var savedSelection = _categorySelections[_currCategoryIndex]; if(savedSelection != undefined) { itemList.selectedIndex = savedSelection.selectedIndex; itemList.scrollPosition = savedSelection.scrollPosition; } else { itemList.selectedIndex = -1; itemList.scrollPosition = 0; } _categoryChanged = false; } private function onSearchInputStart(event: Object): Void { categoryList.disableSelection = categoryList.disableInput = true; itemList.disableSelection = itemList.disableInput = true _nameFilter.filterText = ""; } private function onSearchInputChange(event: Object) { _nameFilter.filterText = event.data; } private function onSearchInputEnd(event: Object) { categoryList.disableSelection = categoryList.disableInput = false; itemList.disableSelection = itemList.disableInput = false; _nameFilter.filterText = event.data; } } ================================================ FILE: src/ItemMenus/InventoryMenu.as ================================================ import gfx.io.GameDelegate; import Shared.GlobalFunc; import gfx.ui.NavigationCode; import gfx.ui.InputDetails; import skyui.components.list.ListLayoutManager; import skyui.components.list.TabularList; import skyui.components.list.ListLayout; import skyui.props.PropertyDataExtender; import skyui.defines.Inventory; import skyui.defines.Input; import skyui.util.Debug; import skyui.VRInput; class InventoryMenu extends ItemMenu { #include "../version.as" /* PRIVATE VARIABLES */ private var _bMenuClosing: Boolean = false; private var _bSwitchMenus: Boolean = false; private var _categoryListIconArt: Array; /* PROPERTIES */ // @GFx public var bPCControlsReady: Boolean = true; /* INITIALIZATION */ public function InventoryMenu() { super(); _categoryListIconArt = ["cat_favorites", "inv_all", "inv_weapons", "inv_armor", "inv_potions", "inv_scrolls", "inv_food", "inv_ingredients", "inv_books", "inv_keys", "inv_misc"]; GameDelegate.addCallBack("AttemptEquip", this, "AttemptEquip"); GameDelegate.addCallBack("DropItem", this, "DropItem"); GameDelegate.addCallBack("AttemptChargeItem", this, "AttemptChargeItem"); GameDelegate.addCallBack("ItemRotating", this, "ItemRotating"); } private var vrActionConditions = undefined; public function OnShow() { super.OnShow(); if(!vrActionConditions) { vrActionConditions = VRInput.instance.getActionConditions("InventoryMenu"); if(VRInput.instance.logDetails) Debug.dump("vrActionConditions", vrActionConditions); } _bMenuClosing = false; // TODO! Cleanup these lines ported from SkyrimVR //this.iLastItemType = InventoryDefines.ICT_NONE; //bottomBar._lastItemType = Inventory.ICT_NONE; //ResetItemCard(); //itemCard.bFadedIn = false; //itemCard._visible = false; //inventoryLists.showItemsList(); if(!this.bFadedIn) { inventoryLists.showPanel(false); itemCard.FadeInCard(); ToggleMenuFade(); } //bottomBar.GoToDefaultFrame(); //bottomBar.buttonPanel.hideButtons(); } /* PUBLIC FUNCTIONS */ // @override ItemMenu public function InitExtensions(): Void { super.InitExtensions(); GlobalFunc.AddReverseFunctions(); inventoryLists.zoomButtonHolder.gotoAndStop(1); // Initialize menu-specific list components var categoryList: CategoryList = inventoryLists.categoryList; categoryList.iconArt = _categoryListIconArt; itemCard.addEventListener("itemPress", this, "onItemCardListPress"); } // @override ItemMenu public function closeMenu(): Void { var list = inventoryLists.itemList.listEnumeration; for(var i = 0; i < list.size(); i++) { var item = list.at(i); if(item.newItem) { var skyui_funcs = skse["plugins"]["skyui"]; if(skyui_funcs) { skyui_funcs.FormDB_RemoveField(item.formId, "skyui/newItem"); } } } super.closeMenu(); } // @override ItemMenu public function setConfig(a_config: Object): Void { super.setConfig(a_config); var itemList: TabularList = inventoryLists.itemList; itemList.addDataProcessor(new InventoryDataSetter()); itemList.addDataProcessor(new InventoryIconSetter(a_config["Appearance"])); itemList.addDataProcessor(new PropertyDataExtender(a_config["Appearance"], a_config["Properties"], "itemProperties", "itemIcons", "itemCompoundProperties")); var layout: ListLayout = ListLayoutManager.createLayout(a_config["ListLayout"], "ItemListLayout"); itemList.layout = layout; // Not 100% happy with doing this here, but has to do for now. if (inventoryLists.categoryList.selectedEntry) layout.changeFilterFlag(inventoryLists.categoryList.selectedEntry.flag); inventoryLists.itemList.listState.layout = layout; } // @GFx public function handleInput(details: InputDetails, pathToFocus: Array): Boolean { if (!bFadedIn) return true; var nextClip = pathToFocus.shift(); if (nextClip.handleInput(details, pathToFocus)) return true; if (GlobalFunc.IsKeyPressed(details)) { if (details.navEquivalent == NavigationCode.TAB || details.navEquivalent == NavigationCode.SHIFT_TAB ) { startMenuFade(); GameDelegate.call("CloseTweenMenu", []); } else if (!inventoryLists.itemList.disableInput) { // Gamepad back || ALT (default) || 'P' if (details.skseKeycode == _switchTabKey || details.control == "Quick Magic") openMagicMenu(true); } } return true; } public function classname(): String{ return "Class Inventorymenu"; } public function handleVRInput(event): Boolean { //Debug.dump("InventoryMenu::handleVRInput", event); if (!bFadedIn) return; var action = VRInput.instance.triggeredAction(vrActionConditions, event); if(action == "search") { inventoryLists.searchWidget.startInput(); return true; } return false; } // @API public function AttemptEquip(a_slot: Number, a_bCheckOverList: Boolean): Void { var bCheckOverList = a_bCheckOverList != undefined ? a_bCheckOverList : true; if (shouldProcessItemsListInput(bCheckOverList) && confirmSelectedEntry()) { GameDelegate.call("ItemSelect", [a_slot]); checkBook(inventoryLists.itemList.selectedEntry); } } // @API public function DropItem(): Void { if (shouldProcessItemsListInput(false) && inventoryLists.itemList.selectedEntry != undefined) { if (_quantityMinCount < 1 || (inventoryLists.itemList.selectedEntry.count < _quantityMinCount)) onQuantityMenuSelect({amount:1}); else itemCard.ShowQuantityMenu(inventoryLists.itemList.selectedEntry.count); } } // @API public function AttemptChargeItem(): Void { if (inventoryLists.itemList.selectedIndex == -1) return; if (shouldProcessItemsListInput(false) && itemCard.itemInfo.charge != undefined && itemCard.itemInfo.charge < 100) GameDelegate.call("ShowSoulGemList", []); } // @override ItemMenu public function SetPlatform(a_platform: Number, a_bPS3Switch: Boolean): Void { inventoryLists.zoomButtonHolder.gotoAndStop(1); inventoryLists.zoomButtonHolder.ZoomButton._visible = a_platform != 0; inventoryLists.zoomButtonHolder.ZoomButton.SetPlatform(a_platform, a_bPS3Switch); super.SetPlatform(a_platform, a_bPS3Switch); } // @API public function ItemRotating(): Void { inventoryLists.zoomButtonHolder.PlayForward(inventoryLists.zoomButtonHolder._currentframe); } /* PRIVATE FUNCTIONS */ // @override ItemMenu private function onExitMenuRectClick(): Void { startMenuFade(); GameDelegate.call("ShowTweenMenu", []); } private function onFadeCompletion(): Void { if (!_bMenuClosing) return; closeMenu(); if (_bSwitchMenus) { GameDelegate.call("CloseTweenMenu",[]); skse.OpenMenu("MagicMenu"); } } // @override ItemMenu private function onShowItemsList(event: Object): Void { super.onShowItemsList(event); if (event.index != -1) { updateBottomBar(true); GameDelegate.call("SetShowingItemsList",[1]); } } public function logAllItems() { var itemList = inventoryLists.itemList; var entryList: Array = itemList.entryList; for (var i: Number = 0; i < entryList.length; i++) { var obj = entryList[i]; Debug.dump("inv item", obj); } } private function onItemHighlightChange(event: Object): Void { super.onItemHighlightChange(event); if (event.index != -1) updateBottomBar(true); } // @override ItemMenu private function onHideItemsList(event: Object): Void { super.onHideItemsList(event); bottomBar.updatePerItemInfo({type:Inventory.ICT_NONE}); updateBottomBar(false); GameDelegate.call("SetShowingItemsList",[0]); } // @override ItemMenu private function onItemSelect(event: Object): Void { if (event.entry.enabled && event.keyboardOrMouse != 0) { GameDelegate.call("ItemSelect", []); checkBook(event.entry); } } // @override ItemMenu private function onQuantityMenuSelect(event: Object): Void { GameDelegate.call("ItemDrop", [event.amount]); // Bug Fix: ItemCard does not update when attempting to drop quest items through the quantity menu // so let's request an update even though it may be redundant. GameDelegate.call("RequestItemCardInfo", [], this, "UpdateItemCardInfo"); } private function onMouseRotationFastClick(aiMouseButton: Number): Void { GameDelegate.call("CheckForMouseEquip", [aiMouseButton], this, "AttemptEquip"); } private function onItemCardListPress(event: Object): Void { GameDelegate.call("ItemCardListCallback", [event.index]); } // @override ItemMenu private function onItemCardSubMenuAction(event: Object): Void { super.onItemCardSubMenuAction(event); GameDelegate.call("QuantitySliderOpen", [event.opening]); if (event.menu == "list") { if (event.opening == true) { navPanel.clearButtons(); navPanel.addButton({text: "$Select", controls: _acceptControls}); navPanel.addButton({text: "$Cancel", controls: _cancelControls}); navPanel.updateButtons(true); } else { GameDelegate.call("RequestItemCardInfo", [], this, "UpdateItemCardInfo"); updateBottomBar(true); } } } private function openMagicMenu(a_bFade: Boolean): Void { if (a_bFade) { _bSwitchMenus = true; startMenuFade(); } else { saveIndices(); closeMenu(); GameDelegate.call("CloseTweenMenu",[]); skse.OpenMenu("MagicMenu"); } } private function startMenuFade(): Void { inventoryLists.hidePanel(); itemCard.FadeOutCard(); //onHideItemsList({}); ToggleMenuFade(); saveIndices(); _bMenuClosing = true; } // @override ItemMenu private function updateBottomBar(a_bSelected: Boolean): Void { navPanel.clearButtons(); if (a_bSelected) { // Setup the main action button var equipArt = {PCArt:"M1M2", XBoxArt:"360_LTRT", PS3Art:"PS3_LTRT", ViveArt: "trigger_LR", MoveArt:"PS3_MOVE", OculusArt: "trigger_LR", WindowsMRArt: "trigger_LR"}; var useItemArt = {PCArt:"E",XBoxArt:"360_A",PS3Art:"PS3_A",ViveArt:"trigger",MoveArt:"PS3_MOVE",OculusArt:"trigger",WindowsMRArt:"trigger"}; var actionText = undefined; var actionArt = undefined; switch(itemCard.itemInfo.type) { case Inventory.ICT_BOOK: actionText = "$Read"; actionArt = useItemArt; break; case Inventory.ICT_POTION: actionText = "$Use"; actionArt = useItemArt; break; case Inventory.ICT_FOOD: case Inventory.ICT_INGREDIENT: actionText = "$Eat"; actionArt = useItemArt; break; case Inventory.ICT_ARMOR: case Inventory.ICT_WEAPON: actionText = "$Equip"; actionArt = equipArt; break; } if (actionArt != undefined) navPanel.addButton({text: actionText, controls: skyui.util.Input.pickControls(_platform, actionArt)}); navPanel.addButton({ text: "$Drop", controls: skyui.util.Input.pickControls(_platform, {PCArt:"R", XBoxArt: "360_X", PS3Art: "PS3_X", ViveArt: "radial_Either_Up", MoveArt: "PS3_A", OculusArt: "OCC_X", WindowsMRArt: "radial_Either_Up"}) }); // Add the Favorite/Unfavorite button var favoriteControl = skyui.util.Input.pickControls(_platform, {PCArt:"F", XBoxArt:"360_Y", PS3Art:"PS3_Y", ViveArt:"radial_Either_Right", MoveArt:"PS3_Y", OculusArt:"OCC_B", WindowsMRArt:"radial_Either_Right"}); if (inventoryLists.itemList.selectedEntry.filterFlag & inventoryLists.categoryList.entryList[0].flag != 0) navPanel.addButton({text: "$Unfavorite", controls: favoriteControl}); else navPanel.addButton({text: "$Favorite", controls: favoriteControl}); if (itemCard.itemInfo.charge != undefined && itemCard.itemInfo.charge < 100) { navPanel.addButton({ text: "$Charge", controls: skyui.util.Input.pickControls(_platform, {PCArt: "T", XBoxArt: "360_RB", PS3Art: "PS3_RB", ViveArt: "radial_Either_Left", MoveArt: "PS3_X", OculusArt: "OCC_Y", WindowsMRArt: "radial_Either_Left"}) }); } } else { // navPanel.addButton({text: "$Exit", controls: _cancelControls}); // navPanel.addButton({text: "$Search", controls: _searchControls}); if (_platform != 0) { navPanel.addButton({text: "$Column", controls: {namedKey: "Action_Up"}}); navPanel.addButton({text: "$Order", controls: {namedKey: "Action_Double_Up"}}); } // navPanel.addButton({text: "$Magic", controls: _switchControls}); } navPanel.addButton({ text: "$Search", controls: skyui.util.Input.pickControls(_platform, {PCArt: "Space", ViveArt: "radial_Either_Down", MoveArt: "PS3_X", OculusArt: "OCC THUMB_REST", WindowsMRArt: "OCC THUMB_REST", KnucklesArt: "OCC THUMB_REST"})}); navPanel.updateButtons(true); } } ================================================ FILE: src/ItemMenus/ItemCard.as ================================================ import gfx.events.EventDispatcher; import gfx.ui.NavigationCode; import gfx.managers.FocusHandler; import gfx.ui.InputDetails; import gfx.io.GameDelegate; import Components.DeltaMeter; import Shared.GlobalFunc; import skyui.defines.Inventory; import skyui.util.Debug; class ItemCard extends MovieClip { #include "../version.as" var ActiveEffectTimeValue: TextField; var ApparelArmorValue: TextField; var ApparelEnchantedLabel: TextField; var BookDescriptionLabel: TextField; var EnchantmentLabel: TextField; var ItemName: TextField; var ItemText: TextField; var ItemValueText: TextField; var ItemWeightText: TextField; var MagicCostLabel: TextField; var MagicCostPerSec: TextField; var MagicCostTimeLabel: TextField; var MagicCostTimeValue: TextField; var MagicCostValue: TextField; var MagicEffectsLabel: TextField; var MessageText: TextField; var PotionsLabel: TextField; var SecsText: TextField; var ShoutCostValue: TextField; var ShoutEffectsLabel: TextField; var SkillLevelText: TextField; var SkillTextInstance: TextField; var SliderValueText: TextField; var SoulLevel: TextField; var StolenTextInstance: TextField; var TotalChargesValue: TextField; var WeaponDamageValue: TextField; var WeaponEnchantedLabel: TextField; var ButtonRect: MovieClip; var ButtonRect_mc: MovieClip; var CardList_mc: MovieClip; var ChargeMeter_Default: MovieClip; var ChargeMeter_Enchantment: MovieClip; var ChargeMeter_SoulGem: MovieClip; var ChargeMeter_Weapon: MovieClip; var EnchantingSlider_mc: MovieClip; var Enchanting_Background: MovieClip; var Enchanting_Slim_Background: MovieClip; var ItemList: MovieClip; var ListChargeMeter: MovieClip; var PoisonInstance: MovieClip; var PrevFocus: MovieClip; var QuantitySlider_mc: MovieClip; var WeaponChargeMeter: MovieClip; var InputHandler: Function; var dispatchEvent: Function; var ItemCardMeters: Object; var LastUpdateObj: Object; var _bEditNameMode: Boolean; var bFadedIn: Boolean; //var LastShoutObj: Object; function ItemCard() { super(); GlobalFunc.MaintainTextFormat(); GlobalFunc.AddReverseFunctions(); EventDispatcher.initialize(this); QuantitySlider_mc = QuantitySlider_mc; ButtonRect_mc = ButtonRect; ItemList = CardList_mc.List_mc; SetupItemName(); bFadedIn = false; InputHandler = undefined; _bEditNameMode = false; } function shoutWordPronunciation(word: String): String { word = GlobalFunc.StringReplaceAll(word, "1", "aa"); word = GlobalFunc.StringReplaceAll(word, "2", "ei"); word = GlobalFunc.StringReplaceAll(word, "3", "ii"); word = GlobalFunc.StringReplaceAll(word, "4", "ah"); word = GlobalFunc.StringReplaceAll(word, "6", "ur"); word = GlobalFunc.StringReplaceAll(word, "7", "ir"); word = GlobalFunc.StringReplaceAll(word, "8", "oo"); word = GlobalFunc.StringReplaceAll(word, "9", "ey"); return word.charAt(0).toUpperCase() + word.slice(1); } function get bEditNameMode(): Boolean { return _bEditNameMode; } function GetItemName(): TextField { return ItemName; } function SetupItemName(aName: String): Void { ItemName = ItemText.ItemTextField; if (aName != undefined) { ItemName.textAutoSize = "shrink"; ItemName.SetText(aName, true); ItemName.selectable = false; } } function onLoad(): Void { QuantitySlider_mc.addEventListener("change", this, "onSliderChange"); ButtonRect_mc.AcceptMouseButton.addEventListener("click", this, "onAcceptMouseClick"); ButtonRect_mc.CancelMouseButton.addEventListener("click", this, "onCancelMouseClick"); ButtonRect_mc.AcceptMouseButton.SetPlatform(0, false); ButtonRect_mc.CancelMouseButton.SetPlatform(0, false); } function SetPlatform(aiPlatform: Number, abPS3Switch: Boolean): Void { // TODO!!! Clean out both *GamepadButton and *MouseButton // We're now using MappedButton instead of CrossplatformButton ButtonRect_mc.AcceptGamepadButton._visible = false; ButtonRect_mc.CancelGamepadButton._visible = false; ButtonRect_mc.AcceptMouseButton._visible = false; ButtonRect_mc.CancelMouseButton._visible = false; var acceptControls = skyui.util.Input.pickControls(aiPlatform, {PCArt:"Enter",XBoxArt:"360_A",PS3Art:"PS3_A",ViveArt:"trigger",MoveArt:"PS3_MOVE",OculusArt:"trigger",WindowsMRArt:"trigger"}) var cancelControls = skyui.util.Input.pickControls(aiPlatform, {PCArt:"Esc", XBoxArt:"360_B", PS3Art:"PS3_B", ViveArt:"grip", MoveArt:"PS3_B", OculusArt:"grab", WindowsMRArt:"grab"}); ButtonRect_mc.AcceptButton.setButtonData({text: "$Yes", controls: acceptControls}); ButtonRect_mc.CancelButton.setButtonData({text: "$No", controls: cancelControls}); ItemList.SetPlatform(aiPlatform, abPS3Switch); } function onAcceptMouseClick(): Void { if (ButtonRect_mc._alpha == 100 && ButtonRect_mc.AcceptMouseButton._visible == true && InputHandler != undefined) { var inputEnterObj: Object = {value: "keyDown", navEquivalent: NavigationCode.ENTER}; InputHandler(inputEnterObj); } } function onCancelMouseClick(): Void { if (ButtonRect_mc._alpha == 100 && ButtonRect_mc.CancelMouseButton._visible == true && InputHandler != undefined) { var inputTabObj: Object = {value: "keyDown", navEquivalent: NavigationCode.TAB}; InputHandler(inputTabObj); } } function FadeInCard(): Void { if (bFadedIn) return; _visible = true; _parent.gotoAndPlay("fadeIn"); bFadedIn = true; } function FadeOutCard(): Void { if (bFadedIn) { _parent.gotoAndPlay("fadeOut"); bFadedIn = false; } } function get quantitySlider(): MovieClip { return QuantitySlider_mc; } function get weaponChargeMeter(): DeltaMeter { return ItemCardMeters[Inventory.ICT_WEAPON]; } function get itemInfo(): Object { return LastUpdateObj; } function set itemInfo(aUpdateObj: Object): Void { ItemCardMeters = new Array(); var strItemNameHtml: String = ItemName == undefined ? "" : ItemName.htmlText; var _iItemType: Number = aUpdateObj.type; switch (_iItemType) { case Inventory.ICT_ARMOR: if (aUpdateObj.effects.length == 0) gotoAndStop("Apparel_reg"); else gotoAndStop("Apparel_Enchanted"); ApparelArmorValue.textAutoSize = "shrink"; ApparelArmorValue.SetText(aUpdateObj.armor); ApparelEnchantedLabel.textAutoSize = "shrink"; ApparelEnchantedLabel.SetText(aUpdateObj.effects, true); SkillTextInstance.SetText(aUpdateObj.skillText); break; case Inventory.ICT_WEAPON: if (aUpdateObj.effects.length == 0) { gotoAndStop("Weapons_reg"); } else { gotoAndStop("Weapons_Enchanted"); if (ItemCardMeters[Inventory.ICT_WEAPON] == undefined) ItemCardMeters[Inventory.ICT_WEAPON] = new DeltaMeter(WeaponChargeMeter.MeterInstance); if (aUpdateObj.usedCharge != undefined && aUpdateObj.charge != undefined) { ItemCardMeters[Inventory.ICT_WEAPON].SetPercent(aUpdateObj.usedCharge); ItemCardMeters[Inventory.ICT_WEAPON].SetDeltaPercent(aUpdateObj.charge); WeaponChargeMeter._visible = true; } else { WeaponChargeMeter._visible = false; } } var strIsPoisoned: String = aUpdateObj.poisoned == true ? "On" : "Off"; PoisonInstance.gotoAndStop(strIsPoisoned); WeaponDamageValue.SetText(aUpdateObj.damage); WeaponEnchantedLabel.textAutoSize = "shrink"; WeaponEnchantedLabel.SetText(aUpdateObj.effects, true); break; case Inventory.ICT_BOOK: if (aUpdateObj.description != undefined && aUpdateObj.description != "") { gotoAndStop("Books_Description"); BookDescriptionLabel.SetText(aUpdateObj.description); } else { gotoAndStop("Books_reg"); } break; case Inventory.ICT_POTION: gotoAndStop("Potions_reg"); PotionsLabel.textAutoSize = "shrink"; PotionsLabel.SetText(aUpdateObj.effects, true); SkillTextInstance.SetText(aUpdateObj.skillName == undefined ? "" : aUpdateObj.skillName); break; case Inventory.ICT_FOOD: gotoAndStop("Potions_reg"); PotionsLabel.textAutoSize = "shrink"; PotionsLabel.SetText(aUpdateObj.effects, true); SkillTextInstance.SetText(aUpdateObj.skillName == undefined ? "" : aUpdateObj.skillName); break; case Inventory.ICT_SPELL_DEFAULT: gotoAndStop("Power_reg"); MagicEffectsLabel.SetText(aUpdateObj.effects, true); MagicEffectsLabel.textAutoSize = "shrink"; if (aUpdateObj.spellCost <= 0) { MagicCostValue._alpha = 0; MagicCostTimeValue._alpha = 0; MagicCostLabel._alpha = 0; MagicCostTimeLabel._alpha = 0; MagicCostPerSec._alpha = 0; } else { MagicCostValue._alpha = 100; MagicCostLabel._alpha = 100; MagicCostValue.SetText(aUpdateObj.spellCost.toString()); } break; case Inventory.ICT_SPELL: var bCastTime: Boolean = aUpdateObj.castTime == 0; if (bCastTime) gotoAndStop("Magic_time_label"); else gotoAndStop("Magic_reg"); SkillLevelText.SetText(aUpdateObj.castLevel.toString()); MagicEffectsLabel.SetText(aUpdateObj.effects, true); MagicEffectsLabel.textAutoSize = "shrink"; MagicCostValue.textAutoSize = "shrink"; MagicCostTimeValue.textAutoSize = "shrink"; if (bCastTime) MagicCostTimeValue.SetText(aUpdateObj.spellCost.toString()); else MagicCostValue.SetText(aUpdateObj.spellCost.toString()); break; case Inventory.ICT_INGREDIENT: gotoAndStop("Ingredients_reg"); for (var i: Number = 0; i < 4; i++) { this["EffectLabel" + i].textAutoSize = "shrink"; if (aUpdateObj["itemEffect" + i] != undefined && aUpdateObj["itemEffect" + i] != "") { this["EffectLabel" + i].textColor = 0xFFFFFF; this["EffectLabel" + i].SetText(aUpdateObj["itemEffect" + i]); } else if (i < aUpdateObj.numItemEffects) { this["EffectLabel" + i].textColor = 0x999999; this["EffectLabel" + i].SetText("$UNKNOWN"); } else { this["EffectLabel" + i].SetText(""); } } break; case Inventory.ICT_MISC: gotoAndStop("Misc_reg"); break; case Inventory.ICT_SHOUT: gotoAndStop("Shouts_reg"); var iLastWord: Number = 0; for (var i: Number = 0; i < 3; i++) { if (aUpdateObj["word" + i] != undefined && aUpdateObj["word" + i] != "" && aUpdateObj["unlocked" + i] == true) iLastWord = i; } for (var i: Number = 0; i < 3; i++) { var strDragonWord: String = aUpdateObj["dragonWord" + i] == undefined ? "" : aUpdateObj["dragonWord" + i]; var strWord: String = aUpdateObj["word" + i] == undefined ? "" : aUpdateObj["word" + i]; var bWordKnown: Boolean = aUpdateObj["unlocked" + i] == true; var textInstance = this["ShoutTextInstance" + i]; textInstance.ShoutPronunciation.ShoutWordsLabel.textAutoSize = "shrink"; textInstance.DragonShoutLabelInstance.ShoutWordsLabel.textAutoSize = "shrink"; textInstance.ShoutLabelInstance.ShoutWordsLabelTranslation.textAutoSize = "shrink"; textInstance.ShoutPronunciation.ShoutWordsLabel.SetText(shoutWordPronunciation(strDragonWord)); textInstance.DragonShoutLabelInstance.ShoutWordsLabel.SetText(strDragonWord.toUpperCase()); textInstance.ShoutLabelInstance.ShoutWordsLabelTranslation.SetText(strWord); // If the player just learned a word, kick off the Learn animation if (bWordKnown && i == iLastWord && LastUpdateObj.soulSpent == true) { textInstance.gotoAndPlay("Learn"); // If the word is known, kick off the Translate animation to show the // pronunciation } else if (bWordKnown) { textInstance.gotoAndPlay("Translate"); // Otherwise, just display the word as is } else { textInstance.gotoAndStop("Unlocked"); } } ShoutEffectsLabel.SetText(aUpdateObj.effects, true); ShoutCostValue.SetText(aUpdateObj.spellCost.toString()); break; case Inventory.ICT_ACTIVE_EFFECT: gotoAndStop("ActiveEffects"); MagicEffectsLabel.html = true; MagicEffectsLabel.SetText(aUpdateObj.effects, true); MagicEffectsLabel.textAutoSize = "shrink"; if (aUpdateObj.timeRemaining > 0) { var iEffectTimeRemaining: Number = Math.floor(aUpdateObj.timeRemaining); ActiveEffectTimeValue._alpha = 100; SecsText._alpha = 100; if (iEffectTimeRemaining >= 3600) { iEffectTimeRemaining = Math.floor(iEffectTimeRemaining / 3600); ActiveEffectTimeValue.SetText(iEffectTimeRemaining.toString()); if (iEffectTimeRemaining == 1) SecsText.SetText("$hour"); else SecsText.SetText("$hours"); } else if (iEffectTimeRemaining >= 60) { iEffectTimeRemaining = Math.floor(iEffectTimeRemaining / 60); ActiveEffectTimeValue.SetText(iEffectTimeRemaining.toString()); if (iEffectTimeRemaining == 1) SecsText.SetText("$min"); else SecsText.SetText("$mins"); } else { ActiveEffectTimeValue.SetText(iEffectTimeRemaining.toString()); if (iEffectTimeRemaining == 1) SecsText.SetText("$sec"); else SecsText.SetText("$secs"); } } else { ActiveEffectTimeValue._alpha = 0; SecsText._alpha = 0; } break; case Inventory.ICT_SOUL_GEMS: gotoAndStop("SoulGem"); SoulLevel.SetText(aUpdateObj.soulLVL); break; case Inventory.ICT_LIST: gotoAndStop("Item_list"); if (aUpdateObj.listItems != undefined) { ItemList.entryList = aUpdateObj.listItems; ItemList.InvalidateData(); ItemCardMeters[Inventory.ICT_LIST] = new DeltaMeter(ListChargeMeter.MeterInstance); ItemCardMeters[Inventory.ICT_LIST].SetPercent(aUpdateObj.currentCharge); ItemCardMeters[Inventory.ICT_LIST].SetDeltaPercent(aUpdateObj.currentCharge + ItemList.selectedEntry.chargeAdded); OpenListMenu(); } break; case Inventory.ICT_CRAFT_ENCHANTING: case Inventory.ICT_HOUSE_PART: if (aUpdateObj.type == Inventory.ICT_HOUSE_PART) { gotoAndStop("Magic_short"); if (aUpdateObj.effects == undefined) MagicEffectsLabel.SetText("", true); else MagicEffectsLabel.SetText(aUpdateObj.effects, true); } else if (aUpdateObj.sliderShown == true) { gotoAndStop("Craft_Enchanting"); ItemCardMeters[Inventory.ICT_WEAPON] = new DeltaMeter(ChargeMeter_Default.MeterInstance); if (aUpdateObj.totalCharges != undefined && aUpdateObj.totalCharges != 0) TotalChargesValue.SetText(aUpdateObj.totalCharges); } else if (aUpdateObj.damage == undefined) { if (aUpdateObj.armor == undefined) { if (aUpdateObj.soulLVL == undefined) { if (QuantitySlider_mc._alpha == 0) { gotoAndStop("Craft_Enchanting_Enchantment"); ItemCardMeters[Inventory.ICT_WEAPON] = new DeltaMeter(ChargeMeter_Enchantment.MeterInstance); } } else { gotoAndStop("Craft_Enchanting_SoulGem"); ItemCardMeters[Inventory.ICT_WEAPON] = new DeltaMeter(ChargeMeter_SoulGem.MeterInstance); SoulLevel.SetText(aUpdateObj.soulLVL); } } else { gotoAndStop("Craft_Enchanting_Armor"); ApparelArmorValue.SetText(aUpdateObj.armor); SkillTextInstance.SetText(aUpdateObj.skillText); } } else { gotoAndStop("Craft_Enchanting_Weapon"); ItemCardMeters[Inventory.ICT_WEAPON] = new DeltaMeter(ChargeMeter_Weapon.MeterInstance); WeaponDamageValue.SetText(aUpdateObj.damage); } if (aUpdateObj.usedCharge == 0 && aUpdateObj.totalCharges == 0) ItemCardMeters[Inventory.ICT_WEAPON].DeltaMeterMovieClip._parent._parent._alpha = 0; else if (aUpdateObj.usedCharge != undefined) ItemCardMeters[Inventory.ICT_WEAPON].SetPercent(aUpdateObj.usedCharge); if (aUpdateObj.effects != undefined && aUpdateObj.effects.length > 0) { if (EnchantmentLabel != undefined) EnchantmentLabel.SetText(aUpdateObj.effects, true); EnchantmentLabel.textAutoSize = "shrink"; WeaponChargeMeter._alpha = 100; Enchanting_Background._alpha = 60; Enchanting_Slim_Background._alpha = 0; } else { if (EnchantmentLabel != undefined) EnchantmentLabel.SetText("", true); WeaponChargeMeter._alpha = 0; Enchanting_Slim_Background._alpha = 60; Enchanting_Background._alpha = 0; } break; case Inventory.ICT_KEY: case Inventory.ICT_NONE: default: gotoAndStop("Empty"); } SetupItemName(strItemNameHtml); if (aUpdateObj.name != undefined) { var strItemName: String = aUpdateObj.count != undefined && aUpdateObj.count > 1 ? aUpdateObj.name + " (" + aUpdateObj.count + ")" : aUpdateObj.name; ItemText.ItemTextField.SetText(_bEditNameMode || aUpdateObj.upperCaseName == false ? strItemName : strItemName.toUpperCase(), false); ItemText.ItemTextField.textColor = aUpdateObj.negativeEffect == true ? 0xFF0000 : 0xFFFFFF; } ItemValueText.textAutoSize = "shrink"; ItemWeightText.textAutoSize = "shrink"; if (aUpdateObj.value != undefined && ItemValueText != undefined) ItemValueText.SetText(aUpdateObj.value.toString()); if (aUpdateObj.weight != undefined && ItemWeightText != undefined) ItemWeightText.SetText(RoundDecimal(aUpdateObj.weight, 2).toString()); StolenTextInstance._visible = aUpdateObj.stolen == true; LastUpdateObj = aUpdateObj; } function RoundDecimal(aNumber: Number, aPrecision: Number): Number { var significantFigures = Math.pow(10, aPrecision); return Math.round(significantFigures * aNumber) / significantFigures; } function PrepareInputElements(aActiveClip: MovieClip): Void { var iQuantitySlider_yOffset = 92; var iCardList_yOffset = 98; var iEnchantingSlider_yOffset = 147.3; var iButtonRect_iOffset = 130; var iButtonRect_iOffsetEnchanting = 166; switch (aActiveClip) { case EnchantingSlider_mc: QuantitySlider_mc._y = -100; ButtonRect._y = iButtonRect_iOffsetEnchanting; EnchantingSlider_mc._y = iEnchantingSlider_yOffset; CardList_mc._y = -100; QuantitySlider_mc._alpha = 0; ButtonRect._alpha = 100; EnchantingSlider_mc._alpha = 100; CardList_mc._alpha = 0; break; case QuantitySlider_mc: QuantitySlider_mc._y = iQuantitySlider_yOffset; ButtonRect._y = iButtonRect_iOffset; EnchantingSlider_mc._y = -100; CardList_mc._y = -100; QuantitySlider_mc._alpha = 100; ButtonRect._alpha = 100; EnchantingSlider_mc._alpha = 0; CardList_mc._alpha = 0; break; case CardList_mc: QuantitySlider_mc._y = -100; ButtonRect._y = -100; EnchantingSlider_mc._y = -100; CardList_mc._y = iCardList_yOffset; QuantitySlider_mc._alpha = 0; ButtonRect._alpha = 0; EnchantingSlider_mc._alpha = 0; CardList_mc._alpha = 100; break; case ButtonRect: QuantitySlider_mc._y = -100; ButtonRect._y = iButtonRect_iOffset; EnchantingSlider_mc._y = -100; CardList_mc._y = -100; QuantitySlider_mc._alpha = 0; ButtonRect._alpha = 100; EnchantingSlider_mc._alpha = 0; CardList_mc._alpha = 0; break; } } function ShowEnchantingSlider(aiMaxValue: Number, aiMinValue: Number, aiCurrentValue: Number): Void { gotoAndStop("Craft_Enchanting"); QuantitySlider_mc = EnchantingSlider_mc; QuantitySlider_mc.addEventListener("change", this, "onSliderChange"); PrepareInputElements(EnchantingSlider_mc); QuantitySlider_mc.maximum = aiMaxValue; QuantitySlider_mc.minimum = aiMinValue; QuantitySlider_mc.value = aiCurrentValue; PrevFocus = FocusHandler.instance.getFocus(0); FocusHandler.instance.setFocus(QuantitySlider_mc, 0); InputHandler = HandleQuantityMenuInput; dispatchEvent({type: "subMenuAction", opening: true, menu: "quantity"}); } function ShowQuantityMenu(aiMaxAmount: Number): Void { gotoAndStop("Quantity"); PrepareInputElements(QuantitySlider_mc); QuantitySlider_mc.maximum = aiMaxAmount; QuantitySlider_mc.value = aiMaxAmount; SliderValueText.textAutoSize = "shrink"; SliderValueText.SetText(Math.floor(QuantitySlider_mc.value).toString()); PrevFocus = FocusHandler.instance.getFocus(0); FocusHandler.instance.setFocus(QuantitySlider_mc, 0); InputHandler = HandleQuantityMenuInput; dispatchEvent({type: "subMenuAction", opening: true, menu: "quantity"}); } function HideQuantityMenu(abCanceled: Boolean): Void { FocusHandler.instance.setFocus(PrevFocus, 0); QuantitySlider_mc._alpha = 0; ButtonRect_mc._alpha = 0; InputHandler = undefined; dispatchEvent({type: "subMenuAction", opening: false, canceled: abCanceled, menu: "quantity"}); } function OpenListMenu(): Void { PrevFocus = FocusHandler.instance.getFocus(0); FocusHandler.instance.setFocus(ItemList, 0); ItemList._visible = true; ItemList.addEventListener("itemPress", this, "onListItemPress"); ItemList.addEventListener("listMovedUp", this, "onListSelectionChange"); ItemList.addEventListener("listMovedDown", this, "onListSelectionChange"); ItemList.addEventListener("selectionChange", this, "onListMouseSelectionChange"); PrepareInputElements(CardList_mc); ListChargeMeter._alpha = 100; InputHandler = HandleListMenuInput; dispatchEvent({type: "subMenuAction", opening: true, menu: "list"}); } function HideListMenu(): Void { FocusHandler.instance.setFocus(PrevFocus, 0); ListChargeMeter._alpha = 0; CardList_mc._alpha = 0; ItemCardMeters[Inventory.ICT_LIST] = undefined; InputHandler = undefined; ItemList._visible = true; dispatchEvent({type: "subMenuAction", opening: false, menu: "list"}); } function ShowConfirmMessage(astrMessage: String): Void { gotoAndStop("ConfirmMessage"); PrepareInputElements(ButtonRect_mc); var messageArray: Array = astrMessage.split("\r\n"); var strMessageText = messageArray.join("\n"); MessageText.SetText(strMessageText); PrevFocus = FocusHandler.instance.getFocus(0); FocusHandler.instance.setFocus(this, 0); InputHandler = HandleConfirmMessageInput; dispatchEvent({type: "subMenuAction", opening: true, menu: "message"}); } function HideConfirmMessage(): Void { FocusHandler.instance.setFocus(PrevFocus, 0); ButtonRect_mc._alpha = 0; InputHandler = undefined; dispatchEvent({type: "subMenuAction", opening: false, menu: "message"}); } function StartEditName(aInitialText: String, aiMaxChars: Number): Void { if (Selection.getFocus() != ItemName) { PrevFocus = FocusHandler.instance.getFocus(0); if (aInitialText != undefined) ItemName.SetText(aInitialText); ItemName.type = "input"; ItemName.noTranslate = true; ItemName.selectable = true; ItemName.maxChars = aiMaxChars == undefined ? null : aiMaxChars; Selection.setFocus(ItemName, 0); Selection.setSelection(0, 0); InputHandler = HandleEditNameInput; dispatchEvent({type: "subMenuAction", opening: true, menu: "editName"}); _bEditNameMode = true; } } function EndEditName(): Void { ItemName.type = "dynamic"; ItemName.noTranslate = false; ItemName.selectable = false; ItemName.maxChars = null; var bPreviousFocusEnabled: Boolean = PrevFocus.focusEnabled; PrevFocus.focusEnabled = true; Selection.setFocus(PrevFocus, 0); PrevFocus.focusEnabled = bPreviousFocusEnabled; InputHandler = undefined; dispatchEvent({type: "subMenuAction", opening: false, menu: "editName"}); _bEditNameMode = false; } function handleInput(details: InputDetails, pathToFocus: Array): Boolean { var bHandledInput: Boolean = false; if (pathToFocus.length > 0 && pathToFocus[0].handleInput != undefined) pathToFocus[0].handleInput(details, pathToFocus.slice(1)); if (InputHandler != undefined) bHandledInput = InputHandler(details); return bHandledInput; } function HandleQuantityMenuInput(details: Object): Boolean { var bValidKeyPressed: Boolean = false; if (GlobalFunc.IsKeyPressed(details)) if (details.navEquivalent == NavigationCode.ENTER) { HideQuantityMenu(false); if (QuantitySlider_mc.value > 0) dispatchEvent({type: "quantitySelect", amount: Math.floor(QuantitySlider_mc.value)}); else itemInfo = LastUpdateObj; bValidKeyPressed = true; } else if (details.navEquivalent == NavigationCode.TAB) { HideQuantityMenu(true); itemInfo = LastUpdateObj; bValidKeyPressed = true; } return bValidKeyPressed; } function HandleListMenuInput(details: Object): Boolean { var bValidKeyPressed: Boolean = false; if (GlobalFunc.IsKeyPressed(details) && details.navEquivalent == NavigationCode.TAB) { HideListMenu(); bValidKeyPressed = true; } return bValidKeyPressed; } function HandleConfirmMessageInput(details: Object): Boolean { var bValidKeyPressed: Boolean = false; if (GlobalFunc.IsKeyPressed(details)) { if (details.navEquivalent == NavigationCode.ENTER) { HideConfirmMessage(); dispatchEvent({type: "messageConfirm"}); bValidKeyPressed = true; } else if (details.navEquivalent == NavigationCode.TAB) { HideConfirmMessage(); dispatchEvent({type: "messageCancel"}); itemInfo = LastUpdateObj; bValidKeyPressed = true; } } return bValidKeyPressed; } function HandleEditNameInput(details: Object): Boolean { Selection.setFocus(ItemName, 0); if (GlobalFunc.IsKeyPressed(details)) { if (details.navEquivalent == NavigationCode.ENTER && details.code != 32) dispatchEvent({type: "endEditItemName", useNewName: true, newName: ItemName.text}); else if (details.navEquivalent == NavigationCode.TAB) dispatchEvent({type: "endEditItemName", useNewName: false, newName: ""}); } return true; } function onSliderChange(): Void { var currentValue_tf: TextField = EnchantingSlider_mc._alpha <= 0 ? SliderValueText : TotalChargesValue; var iCurrentValue: Number = Number(currentValue_tf.text); var iNewValue: Number = Math.floor(QuantitySlider_mc.value); if (iCurrentValue != iNewValue) { currentValue_tf.SetText(iNewValue.toString()); GameDelegate.call("PlaySound", ["UIMenuPrevNext"]); dispatchEvent({type: "sliderChange", value: iNewValue}); } } function onListItemPress(event: Object): Void { dispatchEvent(event); HideListMenu(); } function onListMouseSelectionChange(event: Object): Void { if (event.keyboardOrMouse == 0) onListSelectionChange(event); } function onListSelectionChange(event: Object): Void { ItemCardMeters[Inventory.ICT_LIST].SetDeltaPercent(ItemList.selectedEntry.chargeAdded + LastUpdateObj.currentCharge); } } ================================================ FILE: src/ItemMenus/ItemMenu.as ================================================ import gfx.io.GameDelegate; import Shared.GlobalFunc; import gfx.ui.NavigationCode; import gfx.ui.InputDetails; import skyui.defines.Input; import skyui.util.GlobalFunctions; import skyui.util.ConfigManager; import skyui.components.ButtonPanel; import skyui.defines.Inventory; import skyui.defines.Item; import skyui.util.Debug; import skyui.VRInput; class ItemMenu extends MovieClip { /* PRIVATE VARIABLES */ private var _platform: Number; private var _bItemCardFadedIn: Boolean = false; private var _bItemCardPositioned: Boolean = false; private var _quantityMinCount: Number = 5; private var _config: Object; private var _bPlayBladeSound: Boolean; private var _searchKey: Number; private var _switchTabKey: Number; private var _acceptControls: Object; private var _cancelControls: Object; private var _searchControls: Object; private var _switchControls: Object; private var _sortColumnControls: Array; private var _sortOrderControls: Object; private var _VRInput: VRInput; /* STAGE ELEMENTS */ public var inventoryLists: InventoryLists; public var itemCardFadeHolder: MovieClip; public var bottomBar: BottomBar; public var mouseRotationRect: MovieClip; public var exitMenuRect: MovieClip; /* PROPERTIES */ public var itemCard: MovieClip; public var navPanel: ButtonPanel; public var bEnableTabs: Boolean = false; // @GFx public var bPCControlsReady: Boolean = true; public var bFadedIn: Boolean = true; /* INITIALIZATION */ public function ItemMenu() { super(); itemCard = itemCardFadeHolder.ItemCard_mc; navPanel = bottomBar.buttonPanel; Mouse.addListener(this); ConfigManager.registerLoadCallback(this, "onConfigLoad"); bFadedIn = true; _bItemCardFadedIn = false; } public function setupVRInput() { _VRInput = VRInput.instance; VRInput.instance.setup(); } public function OnShow() { setupVRInput(); } /* PUBLIC FUNCTIONS */ // @API public function InitExtensions(a_bPlayBladeSound): Void { skse.ExtendData(true); skse.ForceContainerCategorization(true); _bPlayBladeSound = a_bPlayBladeSound inventoryLists.InitExtensions(); if (bEnableTabs) inventoryLists.enableTabBar(); GameDelegate.addCallBack("UpdatePlayerInfo",this,"UpdatePlayerInfo"); GameDelegate.addCallBack("UpdateItemCardInfo",this,"UpdateItemCardInfo"); GameDelegate.addCallBack("ToggleMenuFade",this,"ToggleMenuFade"); GameDelegate.addCallBack("RestoreIndices",this,"RestoreIndices"); inventoryLists.addEventListener("categoryChange",this,"onCategoryChange"); inventoryLists.addEventListener("itemHighlightChange",this,"onItemHighlightChange"); inventoryLists.addEventListener("showItemsList",this,"onShowItemsList"); inventoryLists.addEventListener("hideItemsList",this,"onHideItemsList"); inventoryLists.itemList.addEventListener("itemPress", this ,"onItemSelect"); itemCard.addEventListener("quantitySelect",this,"onQuantityMenuSelect"); itemCard.addEventListener("subMenuAction",this,"onItemCardSubMenuAction"); positionFixedElements(); itemCard._visible = false; navPanel.hideButtons(); exitMenuRect.onMouseDown = function() { if (_parent.bFadedIn == true && Mouse.getTopMostEntity() == this) _parent.onExitMenuRectClick(); }; } public function setConfig(a_config: Object): Void { _config = a_config; positionFloatingElements(); var itemListState = inventoryLists.itemList.listState; var categoryListState = inventoryLists.categoryList.listState; var appearance = a_config["Appearance"]; categoryListState.iconSource = appearance.icons.category.source; itemListState.iconSource = appearance.icons.item.source; itemListState.showStolenIcon = appearance.icons.item.showStolen; itemListState.defaultEnabledColor = appearance.colors.text.enabled; itemListState.negativeEnabledColor = appearance.colors.negative.enabled; itemListState.stolenEnabledColor = appearance.colors.stolen.enabled; itemListState.defaultDisabledColor = appearance.colors.text.disabled; itemListState.negativeDisabledColor = appearance.colors.negative.disabled; itemListState.stolenDisabledColor = appearance.colors.stolen.disabled; _quantityMinCount = a_config["ItemList"].quantityMenu.minCount; if (_platform == 0) { _switchTabKey = a_config["Input"].controls.pc.switchTab; } else { _switchTabKey = a_config["Input"].controls.gamepad.switchTab; var previousColumnKey = a_config["Input"].controls.gamepad.prevColumn; var nextColumnKey = a_config["Input"].controls.gamepad.nextColumn; var sortOrderKey = a_config["Input"].controls.gamepad.sortOrder; _sortColumnControls = [{keyCode: previousColumnKey}, {keyCode: nextColumnKey}]; _sortOrderControls = {keyCode: sortOrderKey}; } _switchControls = {keyCode: _switchTabKey}; _searchKey = a_config["Input"].controls.pc.search; _searchControls = {keyCode: _searchKey}; updateBottomBar(false); } // @API public function SetPlatform(a_platform: Number, a_bPS3Switch: Boolean): Void { VRInput.instance.updatePlatform(a_platform); _platform = a_platform; if (a_platform == 0) { _acceptControls = Input.Enter; _cancelControls = Input.Tab; // Defaults _switchControls = Input.Alt; } else { _acceptControls = Input.Accept; _cancelControls = Input.Cancel; // Defaults _switchControls = Input.GamepadBack; _sortColumnControls = Input.SortColumn; _sortOrderControls = Input.SortOrder; } // Defaults _searchControls = Input.Space; inventoryLists.setPlatform(a_platform,a_bPS3Switch); itemCard.SetPlatform(a_platform,a_bPS3Switch); bottomBar.setPlatform(a_platform,a_bPS3Switch); } // @API public function GetInventoryItemList(): MovieClip { return inventoryLists.itemList; } // @GFx public function handleInput(details: InputDetails, pathToFocus: Array): Boolean { if (!bFadedIn) return true; var nextClip = pathToFocus.shift(); if (nextClip.handleInput(details, pathToFocus)) return true; if (GlobalFunc.IsKeyPressed(details) && (details.navEquivalent == NavigationCode.TAB || details.navEquivalent == NavigationCode.SHIFT_TAB)) closeMenu(); return true; } public function closeMenu() { //Debug.log(">>> ItemMenu::CloseMenu"); VRInput.instance.teardown(); GameDelegate.call("CloseMenu",[]); //Debug.log("<<< ItemMenu::CloseMenu"); } // @API public function UpdatePlayerInfo(aUpdateObj: Object): Void { bottomBar.UpdatePlayerInfo(aUpdateObj,itemCard.itemInfo); } // @API public function UpdateItemCardInfo(aUpdateObj: Object): Void { itemCard.itemInfo = aUpdateObj; bottomBar.updatePerItemInfo(aUpdateObj); } // @API public function ToggleMenuFade(): Void { if (bFadedIn) { _parent.gotoAndPlay("fadeOut"); bFadedIn = false; inventoryLists.itemList.disableSelection = true; inventoryLists.itemList.disableInput = true; inventoryLists.categoryList.disableSelection = true; inventoryLists.categoryList.disableInput = true; } else { _parent.gotoAndPlay("fadeIn"); } } // @API public function SetFadedIn(): Void { bFadedIn = true; inventoryLists.itemList.disableSelection = false; inventoryLists.itemList.disableInput = false; inventoryLists.categoryList.disableSelection = false; inventoryLists.categoryList.disableInput = false; } // @API public function RestoreIndices(): Void { var categoryList = inventoryLists.categoryList; var itemList = inventoryLists.itemList; if (arguments[0] != undefined && arguments[0] != -1 && arguments.length == 5) { categoryList.listState.restoredItem = arguments[0]; categoryList.onUnsuspend = function() { this.onItemPress(this.listState.restoredItem, 0); delete this.onUnsuspend; }; itemList.listState.restoredScrollPosition = arguments[2]; itemList.listState.restoredSelectedIndex = arguments[1]; itemList.listState.restoredActiveColumnIndex = arguments[3]; itemList.listState.restoredActiveColumnState = arguments[4]; itemList.onUnsuspend = function() { this.onInvalidate = function() { this.scrollPosition = this.listState.restoredScrollPosition; this.selectedIndex = this.listState.restoredSelectedIndex; delete this.onInvalidate; }; this.layout.restoreColumnState(this.listState.restoredActiveColumnIndex, this.listState.restoredActiveColumnState); delete this.onUnsuspend; }; } else { categoryList.onUnsuspend = function() { this.onItemPress(1, 0); // ALL delete this.onUnsuspend; }; } } /* PRIVATE FUNCTIONS */ public function onItemCardSubMenuAction(event: Object): Void { if (event.opening == true) { inventoryLists.itemList.disableSelection = true; inventoryLists.itemList.disableInput = true; inventoryLists.categoryList.disableSelection = true; inventoryLists.categoryList.disableInput = true; } else if (event.opening == false) { inventoryLists.itemList.disableSelection = false; inventoryLists.itemList.disableInput = false; inventoryLists.categoryList.disableSelection = false; inventoryLists.categoryList.disableInput = false; } } private function onConfigLoad(event: Object): Void { setConfig(event.config); inventoryLists.showPanel(_bPlayBladeSound); } private function onMouseWheel(delta: Number): Void { for (var e = Mouse.getTopMostEntity(); e != undefined; e = e._parent) { if (e == mouseRotationRect && shouldProcessItemsListInput(false) || !bFadedIn && delta == -1) { GameDelegate.call("ZoomItemModel",[delta]); break; } } } private function onExitMenuRectClick(): Void { closeMenu(); } private function onCategoryChange(event: Object): Void { } private function ResetItemCard(aiItemInfo) { itemCard.itemInfo = aiItemInfo; bottomBar.updateBarterPerItemInfo(aiItemInfo); } private function onItemHighlightChange(event: Object): Void { if (event.index != -1) { if (!_bItemCardFadedIn) { _bItemCardFadedIn = true; if (_bItemCardPositioned) itemCard.FadeInCard(); } if (_bItemCardPositioned) GameDelegate.call("UpdateItem3D",[true]); GameDelegate.call("RequestItemCardInfo",[], this, "UpdateItemCardInfo"); } else { if (!bFadedIn) resetMenu(); if (_bItemCardFadedIn) { _bItemCardFadedIn = false; onHideItemsList(); } } } private function onShowItemsList(event: Object): Void { onItemHighlightChange(event); } private function onHideItemsList(event: Object): Void { GameDelegate.call("UpdateItem3D",[false]); itemCard.FadeOutCard(); } private function onItemSelect(event: Object): Void { if (event.entry.enabled) { if (_quantityMinCount < 1 || (event.entry.count < _quantityMinCount)) onQuantityMenuSelect({amount:1}); else itemCard.ShowQuantityMenu(event.entry.count); } else { GameDelegate.call("DisabledItemSelect",[]); } } private function onQuantityMenuSelect(event: Object): Void { GameDelegate.call("ItemSelect",[event.amount]); } private function onMouseRotationStart(): Void { GameDelegate.call("StartMouseRotation",[]); inventoryLists.categoryList.disableSelection = true; inventoryLists.itemList.disableSelection = true; } private function onMouseRotationStop(): Void { GameDelegate.call("StopMouseRotation",[]); inventoryLists.categoryList.disableSelection = false; inventoryLists.itemList.disableSelection = false; } private function onMouseRotationFastClick(): Void { if (shouldProcessItemsListInput(false)) onItemSelect({entry:inventoryLists.itemList.selectedEntry, keyboardOrMouse:0}); } private function saveIndices(): Void { var a = new Array(); // Save selected category, selected item and relative scroll position a.push(inventoryLists.categoryList.selectedIndex); a.push(inventoryLists.itemList.selectedIndex); a.push(inventoryLists.itemList.scrollPosition); a.push(inventoryLists.itemList.layout.activeColumnIndex); a.push(inventoryLists.itemList.layout.activeColumnState); GameDelegate.call("SaveIndices", [a]); } private function positionFixedElements(): Void { GlobalFunc.SetLockFunction(); inventoryLists.Lock("L"); inventoryLists._x = inventoryLists._x - 20; var leftEdge = Stage.visibleRect.x + Stage.safeRect.x; var rightEdge = Stage.visibleRect.x + Stage.visibleRect.width - Stage.safeRect.x; bottomBar.positionElements(leftEdge, rightEdge); MovieClip(exitMenuRect).Lock("TL"); exitMenuRect._x = exitMenuRect._x - Stage.safeRect.x; exitMenuRect._y = exitMenuRect._y - Stage.safeRect.y; } private function positionFloatingElements(): Void { var leftEdge = Stage.visibleRect.x + Stage.safeRect.x; var rightEdge = Stage.visibleRect.x + Stage.visibleRect.width - Stage.safeRect.x; var a = inventoryLists.getContentBounds(); // 25 is hardcoded cause thats the final offset after the animation of the panel container is done var panelEdge = inventoryLists._x + a[0] + a[2] + 25; var itemCardContainer = itemCard._parent; var itemcardPosition = _config.ItemInfo.itemcard; var itemiconPosition = _config.ItemInfo.itemicon; var scaleMult = (rightEdge - panelEdge) / itemCardContainer._width; // Scale down if necessary if (scaleMult < 1.0) { itemCardContainer._width *= scaleMult; itemCardContainer._height *= scaleMult; itemiconPosition.scale *= scaleMult; } if (itemcardPosition.align == "left") itemCardContainer._x = panelEdge + leftEdge + itemcardPosition.xOffset; else if (itemcardPosition.align == "right") itemCardContainer._x = rightEdge - itemCardContainer._width + itemcardPosition.xOffset; else itemCardContainer._x = panelEdge + itemcardPosition.xOffset + (Stage.visibleRect.x + Stage.visibleRect.width - panelEdge - itemCardContainer._width) / 2; itemCardContainer._y = itemCardContainer._y + itemcardPosition.yOffset; if (mouseRotationRect != undefined) { MovieClip(mouseRotationRect).Lock("T"); mouseRotationRect._x = itemCard._parent._x; mouseRotationRect._width = itemCardContainer._width; mouseRotationRect._height = 0.55 * Stage.visibleRect.height; } _bItemCardPositioned = true; // Delayed fade in if positioned wasn't set if (_bItemCardFadedIn) { GameDelegate.call("UpdateItem3D",[true]); itemCard.FadeInCard(); } } private function shouldProcessItemsListInput(abCheckIfOverRect: Boolean): Boolean { var process = bFadedIn == true && inventoryLists.currentState == InventoryLists.SHOW_PANEL && inventoryLists.itemList.itemCount > 0 && !inventoryLists.itemList.disableSelection && !inventoryLists.itemList.disableInput; if (process && _platform == Shared.Platforms.CONTROLLER_PC && abCheckIfOverRect) { var e = Mouse.getTopMostEntity(); var found = false; while (!found && e != undefined) { if (e == inventoryLists.itemList) found = true; e = e._parent; } process = process && found; } return process; } // Added to prevent clicks on the scrollbar from equipping/using stuff private function confirmSelectedEntry(): Boolean { // only confirm when using mouse if (_platform != 0) return true; for (var e = Mouse.getTopMostEntity(); e != undefined; e = e._parent) if (e.itemIndex == inventoryLists.itemList.selectedIndex) return true; return false; } /* This method is only used for the InventoryMenu Favorites Category. It prevents a lockup when unfavoriting the last item from favorites list by resetting the menu. */ private function resetMenu(): Void { // FIXME? This crashes SkyrimVR // When opening the inventory a second time without having an item selected for some reason. //saveIndices(); //closemenu(); //skse.OpenMenu("Inventory Menu"); } /* This method is only used in InventoryMenu and ContainerMenu. It it allows determination of read books. Item list isn't re-sent when you activate a book, unlike other items, so the flags don't get updated. If the item is a book, we apply the book read flag and invalidate locally */ private function checkBook(a_entryObject: Object): Boolean { if (a_entryObject.type != Inventory.ICT_BOOK || _global.skse == null) return false; a_entryObject.flags |= Item.BOOKFLAG_READ; a_entryObject.skyui_itemDataProcessed = false; inventoryLists.itemList.requestInvalidate(); return true; } private function getEquipButtonData(a_itemType: Number, a_bAlwaysEquip: Boolean): Object { var btnData = {}; var useControls = Input.Activate; var equipControls = Input.Equip; switch (a_itemType) { case Inventory.ICT_ARMOR : btnData.text = "$Equip"; btnData.controls = a_bAlwaysEquip ? equipControls : useControls; break; case Inventory.ICT_BOOK : btnData.text = "$Read"; btnData.controls = a_bAlwaysEquip ? equipControls : useControls; break; case Inventory.ICT_FOOD : case Inventory.ICT_INGREDIENT : btnData.text = "$Eat"; btnData.controls = a_bAlwaysEquip ? equipControls : useControls; break; case Inventory.ICT_WEAPON : btnData.text = "$Equip"; btnData.controls = equipControls; break; default : btnData.text = "$Use"; btnData.controls = a_bAlwaysEquip ? equipControls : useControls; } return btnData; } private function updateBottomBar(a_bSelected: Boolean): Void {} } ================================================ FILE: src/ItemMenus/ItemcardDataExtender.as ================================================ import gfx.io.GameDelegate; import skyui.defines.Form; import skyui.components.list.BasicList; import skyui.components.list.IListProcessor; // @abstract class ItemcardDataExtender implements IListProcessor { /* PRIVATE VARIABLES */ private var _itemInfo: Object; private var _requestItemInfo: Function; /* INITIALIZATION */ public function ItemcardDataExtender() { _requestItemInfo = function(a_target: Object, a_index: Number): Void { var oldIndex = this._selectedIndex; this._selectedIndex = a_index; GameDelegate.call("RequestItemCardInfo", [], a_target, "updateItemInfo"); this._selectedIndex = oldIndex; }; } /* PUBLIC FUNCTIONS */ public function updateItemInfo(a_updateObj: Object): Void { _itemInfo = a_updateObj; } // @override IListProcessor public function processList(a_list: BasicList): Void { var entryList = a_list.entryList; for (var i = 0; i < entryList.length; i++) { var e = entryList[i]; if (e.skyui_itemDataProcessed || e.filterFlag == 0) continue; e.skyui_itemDataProcessed = true; // Fix wrong property names fixSKSEExtendedObject(e); // Hack to retrieve itemcard info _requestItemInfo.apply(a_list, [this, i]); processEntry(e, _itemInfo); } } /* PRIVATE FUNCTIONS */ // @abstract private function processEntry(a_entryObject: Object, a_itemInfo: Object): Void {} private function fixSKSEExtendedObject(a_extendedObject: Object): Void { if (a_extendedObject.formType == undefined) return; switch(a_extendedObject.formType) { case Form.TYPE_SPELL: case Form.TYPE_SCROLLITEM: case Form.TYPE_INGREDIENT: case Form.TYPE_POTION: case Form.TYPE_EFFECTSETTING: // school is sent as subType if (a_extendedObject.school == undefined && a_extendedObject.subType != undefined) { a_extendedObject.school = a_extendedObject.subType; delete(a_extendedObject.subType); } // resistance is sent as magicType if (a_extendedObject.resistance == undefined && a_extendedObject.magicType != undefined) { a_extendedObject.resistance = a_extendedObject.magicType; delete(a_extendedObject.magicType); } // primaryValue is sent as actorValue /* // Ignore if (a_extendedObject.primaryValue == undefined && a_extendedObject.actorValue != undefined) { a_extendedObject.primaryValue = a_extendedObject.actorValue; delete(a_extendedObject.actorValue); } */ break; case Form.TYPE_WEAPON: // weaponType is sent as subType if (a_extendedObject.weaponType == undefined && a_extendedObject.subType != undefined) { a_extendedObject.weaponType = a_extendedObject.subType; delete(a_extendedObject.subType); } break; case Form.TYPE_BOOK: // (SKSE < 1.6.6) flags and bookType (and some padding) are sent as one UInt32 bookType if (a_extendedObject.flags == undefined && a_extendedObject.bookType != undefined) { var oldBookType: Number = a_extendedObject.bookType; a_extendedObject.bookType = (oldBookType & 0xFF00) >>> 8; a_extendedObject.flags = (oldBookType & 0x00FF); } break; default: break; } } } ================================================ FILE: src/ItemMenus/MagicDataSetter.as ================================================ import skyui.defines.Inventory; class MagicDataSetter extends ItemcardDataExtender { /* PRIVATE VARIABLES */ private var _defaultEnabledColor: Number; private var _defaultDisabledColor: Number; /* INITIALIZATION */ public function MagicDataSetter(a_configAppearance: Object) { super(); _defaultEnabledColor = a_configAppearance.colors.text.enabled; _defaultDisabledColor = a_configAppearance.colors.text.disabled; } /* PUBLIC FUNCTIONS */ // @override ItemcardDataExtender public function processEntry(a_entryObject: Object, a_itemInfo: Object): Void { a_entryObject.baseId = a_entryObject.formId & 0x00FFFFFF; a_entryObject.type = a_itemInfo.type; switch (a_entryObject.type) { // Shout case Inventory.ICT_SHOUT: var recharge: Array = a_itemInfo.spellCost.split(" , "); if (a_itemInfo.word0) { a_entryObject.word0 = a_itemInfo.word0 + " (" + recharge[0] + ")"; a_entryObject.word0Recharge = recharge[0]; a_entryObject.word0Color = a_itemInfo.unlocked0 ? _defaultEnabledColor : _defaultDisabledColor; } if (a_itemInfo.word1) { a_entryObject.word1 = a_itemInfo.word1 + " (" + recharge[1] + ")"; a_entryObject.word1Recharge = recharge[1]; a_entryObject.word1Color = a_itemInfo.unlocked1 ? _defaultEnabledColor : _defaultDisabledColor; } if (a_itemInfo.word2) { a_entryObject.word2 = a_itemInfo.word2 + " (" + recharge[2] + ")"; a_entryObject.word2Recharge = recharge[2]; a_entryObject.word2Color = a_itemInfo.unlocked2 ? _defaultEnabledColor : _defaultDisabledColor; } break; // Active effect case Inventory.ICT_ACTIVE_EFFECT: if (a_itemInfo.timeRemaining != undefined && a_itemInfo.timeRemaining > 0) { var s: Number = Math.round(a_itemInfo.timeRemaining); var m: Number = 0; var h: Number = 0; var d: Number = 0; if (s >= 60) { m = Math.floor(s / 60); s = s % 60; } if (m >= 60) { h = Math.floor(m / 60); m = m % 60; } if (h >= 24) { d = Math.floor(h / 24); h = h % 24; } a_entryObject.timeRemainingDisplay = (d != 0 ? (d + "d ") : "") + (h != 0 || d ? (h + "h ") : "") + (m != 0 || d || h ? (m + "m ") : "") + (s + "s"); } break; // Spell case Inventory.ICT_SPELL: a_entryObject.infoCastLevel = a_itemInfo.castLevel; a_entryObject.infoSchoolName = a_itemInfo.magicSchoolName; // 0 -> "-" a_entryObject.duration = (a_entryObject.duration > 0) ? (Math.round(a_entryObject.duration * 100) / 100) : null; a_entryObject.magnitude = (a_entryObject.magnitude > 0) ? (Math.round(a_entryObject.magnitude * 100) / 100) : null; var spellCost = a_itemInfo.spellCost; a_entryObject.infoSpellCost = spellCost; if (spellCost != 0 && a_itemInfo.castTime == 0) a_entryObject.spellCostDisplay = spellCost + "/s"; else a_entryObject.spellCostDisplay = spellCost; break; //Power case Inventory.ICT_SPELL_DEFAULT: default: a_entryObject.skillLevel = null; // Sent by SKSE, we don't want it for powers a_entryObject.infoSpellCost = a_itemInfo.spellCost; // For lesser powers break; } } } ================================================ FILE: src/ItemMenus/MagicIconSetter.as ================================================ import skyui.components.list.BasicList; import skyui.components.list.IListProcessor; import skyui.defines.Actor; import skyui.defines.Magic; import skyui.defines.Inventory; class MagicIconSetter implements IListProcessor { /* PRIVATE VARIABLES */ private var _noIconColors: Boolean; /* INITIALIZATION */ public function MagicIconSetter(a_configAppearance: Object) { _noIconColors = a_configAppearance.icons.item.noColor; } /* PUBLIC FUNCTIONS */ // @override IListProcessor public function processList(a_list: BasicList): Void { var entryList: Array = a_list.entryList; for (var i: Number = 0; i < entryList.length; i++) processEntry(entryList[i]); } /* PRIVATE FUNCTIONS */ private function processEntry(a_entryObject: Object): Void { switch (a_entryObject.type) { case Inventory.ICT_SPELL: processSpellIcon(a_entryObject); break; case Inventory.ICT_SHOUT: a_entryObject.iconLabel = "default_shout"; break; case Inventory.ICT_ACTIVE_EFFECT: a_entryObject.iconLabel = "default_effect"; break; case Inventory.ICT_SPELL_DEFAULT: a_entryObject.iconLabel = "default_power"; break; default: break; } if (_noIconColors && a_entryObject.iconColor != undefined) delete(a_entryObject.iconColor); } private function processSpellIcon(a_entryObject: Object): Void { a_entryObject.iconLabel = "default_power"; // fire rune, actorValue = Health, school = Destruction, resistance = Fire, effectFlags = hostile+detrimental switch(a_entryObject.school) { case Actor.AV_ALTERATION: a_entryObject.iconLabel = "default_alteration"; break; case Actor.AV_CONJURATION: a_entryObject.iconLabel = "default_conjuration"; break; case Actor.AV_DESTRUCTION: a_entryObject.iconLabel = "default_destruction"; processResist(a_entryObject); break; case Actor.AV_ILLUSION: a_entryObject.iconLabel = "default_illusion"; break; case Actor.AV_RESTORATION: a_entryObject.iconLabel = "default_restoration"; break; } } private function processResist(a_entryObject: Object): Void { if (a_entryObject.resistance == undefined || a_entryObject.resistance == Actor.AV_NONE) return; switch(a_entryObject.resistance) { case Actor.AV_FIRERESIST: a_entryObject.iconLabel = "magic_fire"; a_entryObject.iconColor = 0xC73636; break; case Actor.AV_ELECTRICRESIST: a_entryObject.iconLabel = "magic_shock"; a_entryObject.iconColor = 0xEAAB00; break; case Actor.AV_FROSTRESIST: a_entryObject.iconLabel = "magic_frost"; a_entryObject.iconColor = 0x1FFBFF; break; } } } ================================================ FILE: src/ItemMenus/MagicMenu.as ================================================ import Shared.GlobalFunc; import gfx.io.GameDelegate; import gfx.ui.NavigationCode; import gfx.ui.InputDetails; import skyui.components.list.ListLayoutManager; import skyui.components.list.TabularList; import skyui.components.list.ListLayout; import skyui.props.PropertyDataExtender; import skyui.defines.Input; import skyui.defines.Inventory; import skyui.util.Debug; import skyui.VRInput; class MagicMenu extends ItemMenu { #include "../version.as" /* PRIVATE VARIABLES */ private var _hideButtonFlag: Number = 0; private var _bMenuClosing: Boolean = false; private var _bSwitchMenus: Boolean = false; private var _categoryListIconArt: Array; /* PROPERTIES */ public var hideButtonFlag: Number; /* INITIALIZATION */ public function MagicMenu() { super(); _categoryListIconArt = ["cat_favorites", "mag_all", "mag_alteration", "mag_illusion", "mag_destruction", "mag_conjuration", "mag_restoration", "mag_shouts", "mag_powers", "mag_activeeffects"]; } private var vrActionConditions = undefined; public function OnShow() { super.OnShow(); if(!vrActionConditions) { vrActionConditions = VRInput.instance.getActionConditions("MagicMenu"); if(VRInput.instance.logDetails) Debug.dump("vrActionConditions", vrActionConditions); } _bMenuClosing = false; //iLastItemType = InventoryDefines.ICT_NONE; //bottomBar.iLastItemType = Inventory.ICT_NONE; /* ResetItemCard({type:Inventory.ICT_SPELL_DEFAULT}); */ /* itemCard.bFadedIn = false; */ /* itemCard._visible = false; */ if(!bFadedIn) { inventoryLists.showPanel(false); this.ToggleMenuFade(); } /* bottomBar.GoToDefaultFrame(); */ /* bottomBar.HideButtons(); */ } /* PUBLIC FUNCTIONS */ public function InitExtensions(): Void { super.InitExtensions(); GameDelegate.addCallBack("DragonSoulSpent", this, "DragonSoulSpent"); GameDelegate.addCallBack("AttemptEquip", this , "AttemptEquip"); bottomBar.updatePerItemInfo({type:Inventory.ICT_SPELL_DEFAULT}); // Initialize menu-specific list components var categoryList: CategoryList = inventoryLists.categoryList; categoryList.iconArt = _categoryListIconArt; // SkyrimVR moves some variables from the "Interface" section to the "VRUI" section. // Originally, SkyUI patched these positions in papyrus scripts to line up with the new UI. // It does seem to make sense for this kind of patching to be done from the UI itself though. var itemPosXSettingName = "fMagic3DItemPosX:VRUI"; skse.SetINISetting(itemPosXSettingName, skse.GetINISetting(itemPosXSettingName) - 37); } // @override ItemMenu public function setConfig(a_config: Object): Void { super.setConfig(a_config); var itemList: TabularList = inventoryLists.itemList; itemList.addDataProcessor(new MagicDataSetter(a_config["Appearance"])); itemList.addDataProcessor(new MagicIconSetter(a_config["Appearance"])); itemList.addDataProcessor(new PropertyDataExtender(a_config["Appearance"], a_config["Properties"], "magicProperties", "magicIcons", "magicCompoundProperties")); var layout: ListLayout = ListLayoutManager.createLayout(a_config["ListLayout"], "MagicListLayout"); itemList.layout = layout; // Not 100% happy with doing this here, but has to do for now. if (inventoryLists.categoryList.selectedEntry) layout.changeFilterFlag(inventoryLists.categoryList.selectedEntry.flag); } // @GFx public function handleInput(details: InputDetails, pathToFocus: Array): Boolean { if (!bFadedIn) return true; var nextClip = pathToFocus.shift(); if (nextClip.handleInput(details, pathToFocus)) return true; if (GlobalFunc.IsKeyPressed(details)) { if (details.navEquivalent == NavigationCode.TAB || details.navEquivalent == NavigationCode.SHIFT_TAB ) { startMenuFade(); GameDelegate.call("CloseTweenMenu",[]); } else if (!inventoryLists.itemList.disableInput) { // Gamepad back || ALT (default) || 'I' if (details.skseKeycode == _switchTabKey || details.control == "Quick Inventory") openInventoryMenu(true); } } return true; } public function classname(): String{ return "Class MagicMenu"; } public function handleVRInput(event): Boolean { if (!bFadedIn) return; var action = VRInput.instance.triggeredAction(vrActionConditions, event); if(action == "search") { inventoryLists.searchWidget.startInput(); return true; } return false; } // @API public function DragonSoulSpent(): Void { itemCard.itemInfo.soulSpent = true; updateBottomBar(); } // @API public function AttemptEquip(a_slot: Number): Void { if (shouldProcessItemsListInput(true) && confirmSelectedEntry()) GameDelegate.call("ItemSelect",[a_slot]); } /* PRIVATE FUNCTIONS */ // @override ItemMenu private function onItemSelect(event: Object): Void { //Vanilla bugfix if (event.keyboardOrMouse != 0) { if (event.entry.enabled) GameDelegate.call("ItemSelect",[]); else GameDelegate.call("ShowShoutFail",[]); } } // @override ItemMenu private function onExitMenuRectClick(): Void { startMenuFade(); GameDelegate.call("ShowTweenMenu",[]); } private function onFadeCompletion(): Void { if (!_bMenuClosing) return; closeMenu(); if (_bSwitchMenus) { GameDelegate.call("CloseTweenMenu",[]); skse.OpenMenu("InventoryMenu"); } } // @override ItemMenu private function onShowItemsList(event: Object): Void { super.onShowItemsList(event); if (event.index != -1) updateBottomBar(true); } // @override ItemMenu private function onItemHighlightChange(event: Object) { super.onItemHighlightChange(event); if (event.index != -1) updateBottomBar(true); } // @override ItemMenu private function onHideItemsList(event: Object): Void { super.onHideItemsList(event); bottomBar.updatePerItemInfo({type:Inventory.ICT_SPELL_DEFAULT}); updateBottomBar(false); } private function openInventoryMenu(a_bFade: Boolean): Void { if (a_bFade) { _bSwitchMenus = true; startMenuFade(); } else { saveIndices(); closeMenu(); GameDelegate.call("CloseTweenMenu",[]); skse.OpenMenu("InventoryMenu"); } } // @override ItemMenu private function updateBottomBar(a_bSelected: Boolean): Void { navPanel.clearButtons(); var activateControls = skyui.util.Input.pickControls(_platform, {PCArt:"E",XBoxArt:"360_A",PS3Art:"PS3_A",ViveArt:"trigger",MoveArt:"PS3_MOVE",OculusArt:"trigger",WindowsMRArt:"trigger"}); var exitControls = skyui.util.Input.pickControls(_platform, {PCArt:"Tab",XBoxArt:"360_B",PS3Art:"PS3_B",ViveArt:"grip",MoveArt:"PS3_B",OculusArt:"grab",WindowsMRArt:"grab"}); var favoriteControls = skyui.util.Input.pickControls(_platform, {PCArt:"F",XBoxArt:"360_Y",PS3Art:"PS3_Y",ViveArt:"radial_Either_Right",MoveArt:"PS3_Y",OculusArt:"OCC_B",WindowsMRArt:"radial_Either_Right"}); var unlockControls = skyui.util.Input.pickControls(_platform, {PCArt:"R",XBoxArt:"360_X",PS3Art:"PS3_X",ViveArt:"radial_Either_Left",MoveArt:"PS3_X",OculusArt:"OCC_Y",WindowsMRArt:"radial_Either_Left"}); if (a_bSelected && (inventoryLists.itemList.selectedEntry.filterFlag & Inventory.FILTERFLAG_MAGIC_ACTIVEEFFECTS) == 0) { navPanel.addButton({text: "$Equip", controls: activateControls}); if (inventoryLists.itemList.selectedEntry.filterFlag & inventoryLists.categoryList.entryList[0].flag != 0) navPanel.addButton({text: "$Unfavorite", controls: favoriteControls}); else navPanel.addButton({text: "$Favorite", controls: favoriteControls}); if (itemCard.itemInfo.showUnlocked) navPanel.addButton({text: "$Unlock", controls: unlockControls}); } else { // navPanel.addButton({text: "$Exit", controls: _cancelControls}); if (_platform != 0) { navPanel.addButton({text: "$Column", controls: {namedKey: "Action_Up"}}); navPanel.addButton({text: "$Order", controls: {namedKey: "Action_Double_Up"}}); } // navPanel.addButton({text: "$Inventory", controls: _switchControls}); } navPanel.addButton({ text: "$Search", controls: skyui.util.Input.pickControls(_platform, {PCArt: "Space", ViveArt: "radial_Either_Down", MoveArt: "PS3_X", OculusArt: "OCC_X", WindowsMRArt: "radial_Either_Down", KnucklesArt: "OCC THUMB_REST"})}); navPanel.updateButtons(true); } private function startMenuFade(): Void { inventoryLists.hidePanel(); ToggleMenuFade(); saveIndices(); _bMenuClosing = true; } } ================================================ FILE: src/MapMenu/Map/LocalMap.as ================================================ import gfx.io.GameDelegate; import Map.MapMenu; import Map.LocationFinder; class Map.LocalMap extends MovieClip { /* CONSTANTS */ private static var STATE_HIDDEN = 0; private static var STATE_LOCALMAP = 1; private static var STATE_FINDLOCATION = 2; /* PRIVATE VARIABLES */ private var _mapImageLoader: MovieClipLoader; private var _bUpdated: Boolean = false; private var _bottomBar: MovieClip; // The local map has to manage visiblity of the location finder as well. private var _locationFinder: LocationFinder; private var _bShow: Boolean = false; private var _state: Number = STATE_HIDDEN; private var _bRequestFindLoc: Boolean = false; /* STAGE ELEMENTS */ public var LocalMapHolder_mc: MovieClip; public var LocationTextClip: MovieClip; public var ClearedText: TextField; /* PROPERTIES */ // @API public var IconDisplay: MapMenu; public var TextureHolder: MovieClip; public var LocationDescription: TextField; public var ClearedDescription: TextField; private var _textureWidth: Number = 800; function get TextureWidth(): Number { return _textureWidth; } private var _textureHeight: Number = 450; function get TextureHeight(): Number { return _textureHeight; } /* INITIALIZATION */ public function LocalMap() { super(); IconDisplay = new MapMenu(this); _mapImageLoader = new MovieClipLoader(); _mapImageLoader.addListener(this); LocationDescription = LocationTextClip.LocationText; LocationDescription.noTranslate = true; LocationTextClip.swapDepths(3); ClearedDescription = ClearedText; ClearedDescription.noTranslate = true; TextureHolder = LocalMapHolder_mc; } /* PUBLIC FUNCTIONS */ // @API public function InitMap(): Void { if (!_bUpdated) { _mapImageLoader.loadClip("img://Local_Map", TextureHolder); _bUpdated = true; } updateLocalMapExtends(true); } // @API public function Show(a_bShow: Boolean): Void { _bShow = a_bShow; if (a_bShow) { if (_bRequestFindLoc) setState(STATE_FINDLOCATION); else setState(STATE_LOCALMAP); } else { setState(STATE_HIDDEN); } _bRequestFindLoc = false; } // @API public function SetTitle(a_name: String, a_cleared: String): Void { LocationDescription.text = a_name == undefined ? "" : a_name; ClearedDescription.text = a_cleared == undefined ? "" : "(" + a_cleared + ")"; } public function showLocationFinder(): Void { // Local map mode if (_state == STATE_LOCALMAP) { setState(STATE_FINDLOCATION); // World map mode - delay state update for Show() } else if (_state == STATE_HIDDEN) { _bRequestFindLoc = true; GameDelegate.call("ToggleMapCallback", []); } // Ignore if state == STATE_FINDLOCATION already } public function setBottomBar(a_bottomBar: MovieClip): Void { _bottomBar = a_bottomBar; } public function setLocationFinder(a_locationFinder: LocationFinder): Void { _locationFinder = a_locationFinder; } /* PRIVATE FUNCTIONS */ private function onLoadInit(a_targetClip: MovieClip): Void { a_targetClip._width = _textureWidth; a_targetClip._height = _textureHeight; } private function setState(a_newState: Number): Void { var oldState = _state; var buttonPanel = _bottomBar.buttonPanel; if (a_newState == STATE_LOCALMAP) { updateLocalMapExtends(true); _parent.gotoAndPlay("fadeIn"); _parent._visible = true; buttonPanel.button0.label = "$World Map"; buttonPanel.button2.visible = true; buttonPanel.button3.visible = true; if (!buttonPanel.button4.disabled) buttonPanel.button4.visible = true; buttonPanel.button5.visible = false; buttonPanel.button6.visible = false; } else if (a_newState == STATE_FINDLOCATION) { updateLocalMapExtends(false); if (oldState == STATE_LOCALMAP) { _parent.gotoAndPlay("fadeOut"); _parent._visible = true; } else { _parent._visible = false; } _locationFinder.show(); buttonPanel.button0.label = "$World Map"; buttonPanel.button2.visible = false; buttonPanel.button3.visible = false; buttonPanel.button4.visible = false; buttonPanel.button5.visible = false; buttonPanel.button6.visible = true; } else if (a_newState == STATE_HIDDEN) { if (oldState == STATE_LOCALMAP) { _parent.gotoAndPlay("fadeOut"); } else if (oldState == STATE_FINDLOCATION) { _locationFinder.hide(); } _parent._visible = true; buttonPanel.button0.label = "$Local Map"; buttonPanel.button2.visible = true; buttonPanel.button3.visible = true; if (!buttonPanel.button4.disabled) buttonPanel.button4.visible = true; buttonPanel.button5.visible = true; buttonPanel.button6.visible = false; } buttonPanel.updateButtons(true); // Label length changed _state = a_newState; } private function updateLocalMapExtends(a_bEnabled: Boolean): Void { if (a_bEnabled) { var textureTopLeft: Object = {x: _x, y: _y}; var textureBottomRight: Object = {x: _x + _textureWidth, y: _y + _textureHeight}; _parent.localToGlobal(textureTopLeft); _parent.localToGlobal(textureBottomRight); GameDelegate.call("SetLocalMapExtents", [textureTopLeft.x, textureTopLeft.y, textureBottomRight.x, textureBottomRight.y]); } else { GameDelegate.call("SetLocalMapExtents", [0, 0, 0, 0]); } } } ================================================ FILE: src/MapMenu/Map/LocationFinder.as ================================================ import flash.geom.ColorTransform; import flash.geom.Transform; import skyui.components.list.FilteredEnumeration; import skyui.components.list.ScrollingList; import skyui.components.SearchWidget; import skyui.filter.NameFilter; import skyui.filter.SortFilter; import skyui.defines.Input; import gfx.ui.NavigationCode; import gfx.ui.InputDetails; import Shared.GlobalFunc; import gfx.managers.FocusHandler; import gfx.managers.InputDelegate; class Map.LocationFinder extends MovieClip { /* CONSTANTS */ public static var TYPE_RANGE: Number = 60; /* PRIVATE VARIABLES */ private var _foundMarker: MovieClip; private var _nameFilter: NameFilter; private var _sortFilter: SortFilter; private var _bShown: Boolean = false; /* STAGE ELEMENTS */ public var list: ScrollingList; public var searchWidget: SearchWidget; public var loadIcon: MovieClip; /* INITIALIZATION */ public function LocationFinder() { super(); _nameFilter = new NameFilter(); _nameFilter.nameAttribute = "_label"; _sortFilter = new SortFilter(); _sortFilter.setSortBy(["_label"], [Array.CASEINSENSITIVE]); } // @override MovieClip private function onLoad(): Void { var e = new FilteredEnumeration(list.entryList); e.addFilter(_nameFilter); e.addFilter(_sortFilter); list.listEnumeration = e; _nameFilter.addEventListener("filterChange", this, "onNameFilterChange"); list.addEventListener("itemPress", this, "onLocationListPress"); searchWidget.addEventListener("inputStart", this, "onSearchInputStart"); searchWidget.addEventListener("inputEnd", this, "onSearchInputEnd"); searchWidget.addEventListener("inputChange", this, "onSearchInputChange"); setLoading(false); hide(true); } private function onNameFilterChange(a_event: Object): Void { list.requestInvalidate(); } /* PUBLIC FUNCTIONS */ public function setLoading(a_bLoading: Boolean): Void { if (a_bLoading) { loadIcon._visible = true; loadIcon.gotoAndPlay(0); list._visible = false; } else { loadIcon._visible = false; loadIcon.stop(); list._visible = true; } } public function show(): Void { FocusHandler.instance.setFocus(list,0); _bShown = true; _parent.gotoAndPlay("fadeIn"); searchWidget.isDisabled = false; list.disableInput = list.disableSelection = false; list.selectedIndex = -1; clearFoundMarker(); } public function hide(a_bInstant: Boolean): Void { _bShown = false; if (a_bInstant) _parent.gotoAndStop("hide"); else _parent.gotoAndPlay("fadeOut"); searchWidget.isDisabled = true; list.disableInput = list.disableSelection = true; } // @GFx public function handleInput(details: InputDetails, pathToFocus: Array): Boolean { if (_bShown) { if (GlobalFunc.IsKeyPressed(details)) { // Search hotkey (default space) if (details.skseKeycode == 57) { searchWidget.startInput(); return true; } } } var nextClip = pathToFocus.shift(); return nextClip.handleInput(details, pathToFocus); } /* PRIVATE FUNCTIONS */ private function onLocationListPress(a_event: Object): Void { var entry = a_event.entry; if (entry == null) return; setFoundMarker(entry); skse.ShowOnMap(entry.index); // hide will be called from local map menu as soon as its state changes } private function clearFoundMarker(): Void { if (_foundMarker) { _foundMarker.removeMovieClip(); _foundMarker = null; } } private function setFoundMarker(a_marker: MovieClip): Void { clearFoundMarker(); if (a_marker.IconClip != null) { var depth = a_marker.IconClip.getNextHighestDepth(); _foundMarker = a_marker.IconClip.attachMovie("FoundMarker", "foundIcon", depth); } } private function onSearchInputStart(event: Object): Void { list.disableInput = list.disableSelection = true; InputDelegate.instance.enableControlFixup(false); _nameFilter.filterText = ""; } private function onSearchInputChange(event: Object) { _nameFilter.filterText = event.data; } private function onSearchInputEnd(event: Object) { list.disableInput = list.disableSelection = false; InputDelegate.instance.enableControlFixup(true); _nameFilter.filterText = event.data; } } ================================================ FILE: src/MapMenu/Map/LocationListEntry.as ================================================ import skyui.components.list.ScrollingList; import skyui.components.list.ListState; import skyui.components.list.BasicListEntry; import skyui.util.ConfigManager; import skyui.util.GlobalFunctions; // Entry objects are the actual markers class Map.LocationListEntry extends BasicListEntry { /* STAGE ELMENTS */ public var selectIndicator: MovieClip; public var icon: MovieClip; public var textField: TextField; /* PROPERTIES */ public function get width(): Number { return background._width; } public function set width(a_val: Number) { background._width = a_val; selectIndicator._width = a_val; } /* PUBLIC FUNCTIONS */ public function setEntry(a_entryObject: Object, a_state: ListState): Void { var entryWidth = background._width; var isSelected = a_entryObject == a_state.list.selectedEntry; selectIndicator._visible = isSelected; icon.gotoAndStop(a_entryObject.iconFrame); if (icon._width > icon._height) { icon._height *= 30 / icon._width; icon._width = 30; } else { icon._width *= 30 / icon._height; icon._height = 30; } textField.SetText(a_entryObject.label); } } ================================================ FILE: src/MapMenu/Map/MapMarker.as ================================================ import gfx.io.GameDelegate; import mx.utils.Delegate; import skyui.util.Tween; class Map.MapMarker extends gfx.controls.Button { /* CONSTANTS */ private static var ICON_MAP: Array = [ "EmptyMarker", "CityMarker", "TownMarker", "SettlementMarker", "CaveMarker", "CampMarker", "FortMarker", "NordicRuinMarker", "DwemerMarker", "ShipwreckMarker", "GroveMarker", "LandmarkMarker", "DragonlairMarker", "FarmMarker", "WoodMillMarker", "MineMarker", "ImperialCampMarker", "StormcloakCampMarker", "DoomstoneMarker", "WheatMillMarker", "SmelterMarker", "StableMarker", "ImperialTowerMarker", "ClearingMarker", "PassMarker", "AltarMarker", "RockMarker", "LighthouseMarker", "OrcStrongholdMarker", "GiantCampMarker", "ShackMarker", "NordicTowerMarker", "NordicDwellingMarker", "DocksMarker", "ShrineMarker", "RiftenCastleMarker", "RiftenCapitolMarker", "WindhelmCastleMarker", "WindhelmCapitolMarker", "WhiterunCastleMarker", "WhiterunCapitolMarker", "SolitudeCastleMarker", "SolitudeCapitolMarker", "MarkarthCastleMarker", "MarkarthCapitolMarker", "WinterholdCastleMarker", "WinterholdCapitolMarker", "MorthalCastleMarker", "MorthalCapitolMarker", "FalkreathCastleMarker", "FalkreathCapitolMarker", "DawnstarCastleMarker", "DawnstarCapitolMarker", "DLC02MiraakTempleMarker", "DLC02RavenRockMarker", "DLC02StandingStonesMarker", "DLC02TelvanniTowerMarker", "DLC02ToSkyrimMarker", "DLC02ToSolstheimMarker", "DLC02CastleKarstaagMarker", "", "DoorMarker", "QuestTargetMarker", "QuestTargetDoorMarker", "MultipleQuestTargetMarker", "PlayerSetMarker", "YouAreHereMarker" ]; private static var UNDISCOVERED_OFFSET: Number = 80; private static var MARKER_BASE_SIZE: Number = 30; private static var MARKER_SCALE_MAX: Number = 150; private static var MARKER_ALPHA_MIN: Number = 60; private static var TWEEN_TIME: Number = 0.2; /* STAGE ELEMENTS */ public var IconClip: MovieClip; public var HitArea: MovieClip; /* STATIC VARIABLES */ public static var topDepth: Number = 0; /* PROPERTIES */ public var index: Number = -1; private var _fadingIn: Boolean = false; public function get FadingIn(): Boolean { return _fadingIn; } public function set FadingIn(value: Boolean): Void { if (value != _fadingIn) { _fadingIn = value; if (_fadingIn) { _visible = true; gotoAndPlay("fade_in"); } } } private var _fadingOut: Boolean = false; public function get FadingOut(): Boolean { return _fadingOut; } public function set FadingOut(value: Boolean): Void { if (value != _fadingOut) { _fadingOut = value; if (_fadingOut) { gotoAndPlay("fade_out"); } } } public var iconFrame: Number = 1; // initObject public var markerType: Number; public var isUndiscovered: Boolean; /* PRIVATE VARIABLES */ private var _iconName: String = ""; private var _markerSize: Number; /* INITIALIZATION */ public function MapMarker() { super(); hitArea = HitArea; disableFocus = true; _markerSize = MARKER_BASE_SIZE; _iconName = ICON_MAP[markerType]; iconFrame = (_iconName == null) ? 0 : markerType; iconFrame += ((isUndiscovered == true) ? UNDISCOVERED_OFFSET : 0) + 1; // Frame numbers start at 1 } public function configUI(): Void { super.configUI(); onRollOver = function () {}; onRollOut = function () {}; var iconHolder: MovieClip = IconClip.iconHolder; var icon: MovieClip = iconHolder.icon; iconHolder.background._visible = false; icon.gotoAndStop(iconFrame); IconClip._alpha = MARKER_ALPHA_MIN; switch (_iconName) { case "MineMarker": case "SmelterMarker": case "StableMarker": case "CampMarker": case "CaveMarker": case "GiantCampMarker": case "GroveMarker": case "SettlementMarker": case "ShackMarker": case "AltarMarker": case "ClearingMarker": case "FarmMarker": case "NordicDwellingMarker": case "WheatMillMarker": case "WoodMillMarker": _markerSize -= _markerSize/3; break; case "DoorMarker": IconClip._alpha = 100; break; case "YouAreHereMarker": case "QuestTargetMarker": case "MultipleQuestTargetMarker": IconClip.gotoAndPlay("StartBlink"); case "CityMarker": case "TownMarker": case "RiftenCapitolMarker": case "WindhelmCapitolMarker": case "WhiterunCapitolMarker": case "SolitudeCapitolMarker": case "MarkarthCapitolMarker": case "WinterholdCapitolMarker": case "MorthalCapitolMarker": case "FalkreathCapitolMarker": case "DawnstarCapitolMarker": case "PlayerSetMarker": _markerSize += _markerSize/3; break; case "QuestTargetDoorMarker": IconClip.gotoAndPlay("StartBlink"); _markerSize += 2*_markerSize/3; break; case "EmptyMarker": IconClip._alpha = 0; break; } // Scale the icons to fit _markerSize square without overflow if (icon._width > icon._height) { icon._height *= _markerSize / icon._width; icon._width = _markerSize; } else { icon._width *= _markerSize / icon._height; icon._height = _markerSize; } } /* PUBLIC FUNCTIONS */ // @override gfx.controls.Button public function setState(a_state: String): Void { if (_fadingOut || _fadingIn) return; super.setState(a_state); switch (_iconName) { case "QuestTargetMarker": case "QuestTargetDoorMarker": case "MultipleQuestTargetMarker": case "YouAreHereMarker": break; case "PlayerSetMarker": case "DoorMarker": default: if (_iconName != "PlayerSetMarker") { if (a_state == "over") { Tween.LinearTween(IconClip, "_xscale", 100, MARKER_SCALE_MAX, TWEEN_TIME, null); Tween.LinearTween(IconClip, "_yscale", 100, MARKER_SCALE_MAX, TWEEN_TIME, null); } else { Tween.LinearTween(IconClip, "_xscale", MARKER_SCALE_MAX, 100, TWEEN_TIME, null); Tween.LinearTween(IconClip, "_yscale", MARKER_SCALE_MAX, 100, TWEEN_TIME, null); } } if (_iconName != "DoorMarker") { if (a_state == "over") { Tween.LinearTween(IconClip, "_alpha", MARKER_ALPHA_MIN, 100, TWEEN_TIME, null); } else { Tween.LinearTween(IconClip, "_alpha", 100, MARKER_ALPHA_MIN, TWEEN_TIME, null); } } } } public function MarkerRollOver(): Boolean { if (IconClip.foundIcon) { Tween.LinearTween(IconClip.foundIcon, "_alpha", 100, 0, TWEEN_TIME, Delegate.create(IconClip.foundIcon, removeMovieClip)); } var overState: Boolean = false; setState("over"); overState = state == "over"; if (overState) { var topInstance: MovieClip = _parent.getInstanceAtDepth(Map.MapMarker.topDepth); if (topInstance != null) topInstance.swapDepths(Map.MapMarker(topInstance).index); swapDepths(Map.MapMarker.topDepth); GameDelegate.call("PlaySound", ["UIMapRollover"]); } return overState; } public function MarkerRollOut(): Void { setState("out"); } public function MarkerClick(): Void { GameDelegate.call("MarkerClick", [index]); } } ================================================ FILE: src/MapMenu/Map/MapMenu.as ================================================ import gfx.io.GameDelegate; import gfx.ui.NavigationCode; import gfx.ui.InputDetails; import gfx.managers.FocusHandler; import gfx.managers.InputDelegate; import Map.LocalMap; import Map.LocationFinder; import Shared.ButtonChange; import Shared.GlobalFunc; import skyui.components.ButtonPanel; import skyui.components.MappedButton; import skyui.defines.Input; /* A few comments: * The map menu set up somewhat complicated. There's a lot of @API, so changing that was not an option. * The top-level clip contains 3 main components, and the bottombar. Root +-- MapMenu (aka WorldMap. this class) +-- LocalMap +-- LocationFinder (new) +-- BottomBar * To prevent WSAD etc from zooming while the location finder is active, we have to enter a fake local map mode. * LocalMap handles the overall state of the menu: worldmap(aka hidden), localmap, locationfinder * To open the LocationFinder, we send a request to localmap, which prepares the fake mode, then shows the location finder. * For handleInput, MapMenu acts as the root. * The bottombar changes happen in LocalMap when the mode is changed. * To detect E as NavEquivalent.ENTER, we have to enable a custom fixup in InputDelegate. * To receive mouse wheel input for the scrolling list, we need skse.EnableMapMenuMouseWheel(true). * Oh, and the localmap reuses this class somehow for its IconView... */ class Map.MapMenu { #include "../../version.as" /* CONSTANTS */ private static var REFRESH_SHOW: Number = 0; private static var REFRESH_X: Number = 1; private static var REFRESH_Y: Number = 2; private static var REFRESH_ROTATION: Number = 3; private static var REFRESH_STRIDE: Number = 4; private static var CREATE_NAME: Number = 0; private static var CREATE_ICONTYPE: Number = 1; private static var CREATE_UNDISCOVERED: Number = 2; private static var CREATE_STRIDE: Number = 3; private static var MARKER_CREATE_PER_FRAME: Number = 10; /* PRIVATE VARIABLES */ private var _markerList: Array; private var _bottomBar: MovieClip; private var _nextCreateIndex: Number = -1; private var _mapWidth: Number = 0; private var _mapHeight: Number = 0; private var _mapMovie: MovieClip; private var _markerDescriptionHolder: MovieClip; private var _markerContainer: MovieClip; private var _selectedMarker: MovieClip; private var _platform: Number; private var _localMapButton: MovieClip; private var _journalButton: MovieClip; private var _playerLocButton: MovieClip; private var _findLocButton: MovieClip; private var _searchButton: MovieClip; private var _locationFinder: LocationFinder; private var _localMapControls: Object; private var _journalControls: Object; private var _zoomControls: Object; private var _playerLocControls: Object; private var _setDestControls: Object; private var _findLocControls: Object; /* STAGE ELEMENTS */ public var locationFinderFader: MovieClip; public var localMapFader: MovieClip; /* PROPERTIES */ // @API public var LocalMapMenu: MovieClip; // @API public var MarkerDescriptionObj: MovieClip; // @API public var PlayerLocationMarkerType: Number; // @API public var MarkerData: Array; // @API public var YouAreHereMarker: MovieClip; // @GFx public var bPCControlsReady: Boolean = true; /* INITIALIZATION */ public function MapMenu(a_mapMovie: MovieClip) { _mapMovie = a_mapMovie == undefined ? _root : a_mapMovie; _markerContainer = _mapMovie.createEmptyMovieClip("MarkerClips", 1); _markerList = new Array(); _nextCreateIndex = -1; LocalMapMenu = _mapMovie.localMapFader.MapClip; _locationFinder = _mapMovie.locationFinderFader.locationFinder; _bottomBar = _root.bottomBar; if (LocalMapMenu != undefined) { LocalMapMenu.setBottomBar(_bottomBar); LocalMapMenu.setLocationFinder(_locationFinder); Mouse.addListener(this); FocusHandler.instance.setFocus(this,0); } _markerDescriptionHolder = _mapMovie.attachMovie("DescriptionHolder", "markerDescriptionHolder", _mapMovie.getNextHighestDepth()); _markerDescriptionHolder._visible = false; _markerDescriptionHolder.hitTestDisable = true; MarkerDescriptionObj = _markerDescriptionHolder.Description; Stage.addListener(this); initialize(); } public function InitExtensions(): Void { skse.EnableMapMenuMouseWheel(true); } private function initialize(): Void { onResize(); if (_bottomBar != undefined) _bottomBar.swapDepths(4); if (_mapMovie.localMapFader != undefined) { _mapMovie.localMapFader.swapDepths(3); _mapMovie.localMapFader.gotoAndStop("hide"); } if (_mapMovie.locationFinderFader != undefined) { _mapMovie.locationFinderFader.swapDepths(6); } GameDelegate.addCallBack("RefreshMarkers", this, "RefreshMarkers"); GameDelegate.addCallBack("SetSelectedMarker", this, "SetSelectedMarker"); GameDelegate.addCallBack("ClickSelectedMarker", this, "ClickSelectedMarker"); GameDelegate.addCallBack("SetDateString", this, "SetDateString"); GameDelegate.addCallBack("ShowJournal", this, "ShowJournal"); } /* PUBLIC FUNCTIONS */ // @API public function SetNumMarkers(a_numMarkers: Number): Void { if (_markerContainer != null) { _markerContainer.removeMovieClip(); _markerContainer = _mapMovie.createEmptyMovieClip("MarkerClips", 1); onResize(); } delete _markerList; _markerList = new Array(a_numMarkers); Map.MapMarker.topDepth = a_numMarkers; _nextCreateIndex = 0; SetSelectedMarker(-1); _locationFinder.list.clearList(); _locationFinder.setLoading(true); } // @API public function GetCreatingMarkers(): Boolean { return _nextCreateIndex != -1; } // @API public function CreateMarkers(): Void { if (_nextCreateIndex == -1 || _markerContainer == null) return; var i = 0; var idx = _nextCreateIndex * CREATE_STRIDE; var markersLen = _markerList.length; var dataLen = MarkerData.length; while (_nextCreateIndex < markersLen && idx < dataLen && i < MARKER_CREATE_PER_FRAME) { var markerType = MarkerData[idx + CREATE_ICONTYPE]; var markerName = MarkerData[idx + CREATE_NAME]; var isUndiscovered = MarkerData[idx + CREATE_UNDISCOVERED]; var mapMarker: MovieClip = _markerContainer.attachMovie("MapMarker", "Marker" + _nextCreateIndex, _nextCreateIndex, {markerType: markerType, isUndiscovered: isUndiscovered}); _markerList[_nextCreateIndex] = mapMarker; if (markerType == PlayerLocationMarkerType) { YouAreHereMarker = mapMarker.IconClip; } mapMarker.index = _nextCreateIndex; mapMarker.label = markerName; mapMarker.visible = false; // Adding the markers directly so we don't have to create data obidxects. // NOTE: Make sure internal entry properties (mappedIndex etc) dont conflict with marker properties if (0 < markerType && markerType < Map.LocationFinder.TYPE_RANGE) { _locationFinder.list.entryList.push(mapMarker); } i++; _nextCreateIndex++; idx += CREATE_STRIDE; } _locationFinder.list.InvalidateData(); if (_nextCreateIndex >= markersLen) { _locationFinder.setLoading(false); _nextCreateIndex = -1; } } // @API public function RefreshMarkers(): Void { var i: Number = 0; var idx: Number = 0; var markersLen: Number = _markerList.length; var dataLen: Number = MarkerData.length; while (i < markersLen && idx < dataLen) { var marker: MovieClip = _markerList[i]; marker._visible = MarkerData[idx + REFRESH_SHOW]; if (marker._visible) { marker._x = MarkerData[idx + REFRESH_X] * _mapWidth; marker._y = MarkerData[idx + REFRESH_Y] * _mapHeight; marker._rotation = MarkerData[idx + REFRESH_ROTATION]; } i++; idx += REFRESH_STRIDE; } if (_selectedMarker != undefined) { _markerDescriptionHolder._x = _selectedMarker._x + _markerContainer._x; _markerDescriptionHolder._y = _selectedMarker._y + _markerContainer._y; } } // @API public function SetSelectedMarker(a_selectedMarkerIndex: Number): Void { var marker: MovieClip = a_selectedMarkerIndex < 0 ? null : _markerList[a_selectedMarkerIndex]; if (marker == _selectedMarker) return; if (_selectedMarker != null) { _selectedMarker.MarkerRollOut(); _selectedMarker = null; _markerDescriptionHolder.gotoAndPlay("Hide"); } if (marker != null && !_bottomBar.hitTest(_root._xmouse, _root._ymouse) && marker.visible && marker.MarkerRollOver()) { _selectedMarker = marker; _markerDescriptionHolder._visible = true; _markerDescriptionHolder.gotoAndPlay("Show"); return; } _selectedMarker = null; } // @API public function ClickSelectedMarker(): Void { if (_selectedMarker != undefined) { _selectedMarker.MarkerClick(); } } // @API public function SetPlatform(a_platform: Number, a_bPS3Switch: Boolean): Void { if (a_platform == ButtonChange.PLATFORM_PC) { _localMapControls = {keyCode: 38}; // L _journalControls = {name: "Journal", context: Input.CONTEXT_GAMEPLAY}; _zoomControls = {keyCode: 283}; // special: mouse wheel _playerLocControls = {keyCode: 18}; // E _setDestControls = {keyCode: 256}; // Mouse1 _findLocControls = {keyCode: 33}; // F } else { _localMapControls = {keyCode: 278}; // X _journalControls = {keyCode: 270}; // START _zoomControls = [ // LT/RT {keyCode: 280}, {keyCode: 281} ]; _playerLocControls = {keyCode: 279}; // Y _setDestControls = {keyCode: 276}; // A _findLocControls = {keyCode: 273}; // RS } if (_bottomBar != undefined) { _bottomBar.buttonPanel.setPlatform(a_platform, a_bPS3Switch); createButtons(a_platform != ButtonChange.PLATFORM_PC); } InputDelegate.instance.isGamepad = a_platform != ButtonChange.PLATFORM_PC; InputDelegate.instance.enableControlFixup(true); _platform = a_platform; } // @API public function SetDateString(a_strDate: String): Void { _bottomBar.DateText.SetText(a_strDate); } // @API public function ShowJournal(a_bShow: Boolean): Void { if (_bottomBar != undefined) { _bottomBar._visible = !a_bShow; } } // @API public function SetCurrentLocationEnabled(a_bEnabled: Boolean): Void { if (_bottomBar != undefined && _platform == ButtonChange.PLATFORM_PC) { _bottomBar.PlayerLocButton.disabled = !a_bEnabled; } } // @GFx public function handleInput(details: InputDetails, pathToFocus: Array): Boolean { var nextClip = pathToFocus.shift(); if (nextClip.handleInput(details, pathToFocus)) return true; // Find Location - F if (_platform == ButtonChange.PLATFORM_PC) { if (GlobalFunc.IsKeyPressed(details) && (details.skseKeycode == 33)) { LocalMapMenu.showLocationFinder(); } } return false; } /* PRIVATE FUNCTIONS */ private function OnLocalButtonClick(): Void { GameDelegate.call("ToggleMapCallback", []); } private function OnJournalButtonClick(): Void { GameDelegate.call("OpenJournalCallback", []); } private function OnPlayerLocButtonClick(): Void { GameDelegate.call("CurrentLocationCallback", []); } private function OnFindLocButtonClick(): Void { LocalMapMenu.showLocationFinder(); } private function onMouseDown(): Void { if (_bottomBar.hitTest(_root._xmouse, _root._ymouse)) return; GameDelegate.call("ClickCallback", []); } private function onResize(): Void { _mapWidth = Stage.visibleRect.right - Stage.visibleRect.left; _mapHeight = Stage.visibleRect.bottom - Stage.visibleRect.top; if (_mapMovie == _root) { _markerContainer._x = Stage.visibleRect.left; _markerContainer._y = Stage.visibleRect.top; } else { var localMap: LocalMap = LocalMap(_mapMovie); if (localMap != undefined) { _mapWidth = localMap.TextureWidth; _mapHeight = localMap.TextureHeight; } } GlobalFunc.SetLockFunction(); _bottomBar.Lock("B"); } private function createButtons(a_bGamepad: Boolean): Void { var buttonPanel: ButtonPanel = _bottomBar.buttonPanel; buttonPanel.clearButtons(); _localMapButton = buttonPanel.addButton({text: "$Local Map", controls: _localMapControls}); // 0 _journalButton = buttonPanel.addButton({text: "$Journal", controls: _journalControls}); // 1 buttonPanel.addButton({text: "$Zoom", controls: _zoomControls}); // 2 _playerLocButton = buttonPanel.addButton({text: "$Current Location", controls: _playerLocControls}); // 3 _findLocButton = buttonPanel.addButton({text: "$Find Location", controls: _findLocControls}); // 4 buttonPanel.addButton({text: "$Set Destination", controls: _setDestControls}); // 5 _searchButton = buttonPanel.addButton({text: "$Search", controls: Input.Space}); // 6 _localMapButton.addEventListener("click", this, "OnLocalButtonClick"); _journalButton.addEventListener("click", this, "OnJournalButtonClick"); _playerLocButton.addEventListener("click", this, "OnPlayerLocButtonClick"); _findLocButton.addEventListener("click", this, "OnFindLocButtonClick"); _localMapButton.disabled = a_bGamepad; _journalButton.disabled = a_bGamepad; _playerLocButton.disabled = a_bGamepad; _findLocButton.disabled = a_bGamepad; _findLocButton.visible = !a_bGamepad; _searchButton.visible = false; buttonPanel.updateButtons(true); } } ================================================ FILE: src/MapMenu/Map/MarkerDescription.as ================================================ import gfx.io.GameDelegate; class Map.MarkerDescription extends MovieClip { var DescriptionList: Array; var LineItem0: MovieClip; var Title: TextField; /* INITIALIZATION */ public function MarkerDescription() { super(); Title = Title; Title.autoSize = "left"; DescriptionList = new Array(); DescriptionList.push(LineItem0); DescriptionList[0]._visible = false; } function SetDescription(aTitle: String, aLineItems: Array): Void { Title.text = aTitle == undefined ? "" : aTitle; var totalHeight: Number = Title.text.length <= 0 ? 0 : Title._height; for (var i: Number = 0; i < aLineItems.length; i++) { if (i >= DescriptionList.length) { DescriptionList.push(attachMovie("DescriptionLineItem", "LineItem" + i, getNextHighestDepth())); DescriptionList[i]._x = DescriptionList[0]._x; DescriptionList[i]._y = DescriptionList[0]._y; } DescriptionList[i]._visible = true; var item: TextField = DescriptionList[i].Item; var value: TextField = DescriptionList[i].Value; var itemString: String = aLineItems[i].Item; item.autoSize = "left"; item.text = itemString != undefined && itemString.length > 0 ? itemString + ": " : ""; value.autoSize = "left"; value.text = aLineItems[i].Value == undefined ? "" : aLineItems[i].Value; value._x = item._x + item._width; totalHeight = totalHeight + DescriptionList[i]._height; } for (var i: Number = aLineItems.length; i < DescriptionList.length; i++) { DescriptionList[i]._visible = false; } var yOffset: Number = (0 - totalHeight) / 2; Title._y = yOffset; yOffset = yOffset + (Title.text.length <= 0 ? 0 : Title._height); for (var i: Number = 0; i < DescriptionList.length; i++) { DescriptionList[i]._y = yOffset; yOffset = yOffset + DescriptionList[i]._height; } } function OnShowFinish() { GameDelegate.call("PlaySound", ["UIMapRolloverFlyout"]); } } ================================================ FILE: src/MessageBox/MessageBox.as ================================================ import gfx.io.GameDelegate; import gfx.controls.Button; class MessageBox extends MovieClip { /* CONSTANTS */ private static var WIDTH_MARGIN: Number = 20; private static var HEIGHT_MARGIN: Number = 30; private static var MESSAGE_TO_BUTTON_SPACER: Number = 10; private static var SELECTION_INDICATOR_WIDTH: Number = 25; /* PRIVATE VARIABLES */ private var _buttonContainer: MovieClip; private var _defaultTextFormat: TextFormat; private var _buttons: Array; /* STAGE ELEMENTS */ public var messageText: TextField; public var divider: MovieClip; public var background: MovieClip; /* INITIALIZATION */ public function MessageBox() { super(); messageText.noTranslate = true; _buttons = new Array(); _buttonContainer = undefined; _defaultTextFormat = messageText.getTextFormat(); Key.addListener(this); GameDelegate.addCallBack("setMessageText", this, "SetMessage"); GameDelegate.addCallBack("setButtons", this, "setupButtons"); } /* PUBLIC FUNCTIONS */ // @API public function setupButtons(): Void { if (_buttonContainer != null) { _buttonContainer.removeMovieClip(); _buttonContainer = null; } _buttons.length = 0; // This truncates the array to 0 var controllerOrConsole: Boolean = arguments[0]; if (arguments.length > 1) { _buttonContainer = createEmptyMovieClip("Buttons", getNextHighestDepth()); var buttonXOffset: Number = 0; for (var i: Number = 1; i < arguments.length; i++) { if (arguments[i] == " ") continue; var buttonIdx: Number = i - 1; var button: Button = Button(_buttonContainer.attachMovie("MessageBoxButton", "Button" + buttonIdx, _buttonContainer.getNextHighestDepth())); var buttonText: TextField = button.ButtonText; buttonText.autoSize = "center"; buttonText.verticalAlign = "center"; buttonText.verticalAutoSize = "center"; buttonText.html = true; buttonText.SetText(arguments[i], true); button.SelectionIndicatorHolder.SelectionIndicator._width = buttonText._width + MessageBox.SELECTION_INDICATOR_WIDTH; button.SelectionIndicatorHolder.SelectionIndicator._y = buttonText._y + buttonText._height / 2; button._x = buttonXOffset + button._width / 2; buttonXOffset = buttonXOffset + (button._width + MessageBox.SELECTION_INDICATOR_WIDTH); _buttons.push(button); } initButtons(); resetDimensions(); if (controllerOrConsole) { Selection.setFocus(_buttons[0]); } } } // @API public function SetPlatform(a_platform: Number, a_bPS3Switch: Boolean): Void { if (a_platform != 0 && _buttons.length > 0) { Selection.setFocus(_buttons[0]); } } // @API public function SetMessage(aText: String, abHTML: Boolean): Void { messageText.autoSize = "center"; messageText.setTextFormat(_defaultTextFormat); messageText.setNewTextFormat(_defaultTextFormat); messageText.html = abHTML; if (abHTML) messageText.htmlText = aText; else messageText.SetText(aText); resetDimensions(); processMessage(aText); } /* PRIVATE FUNCTIONS */ private function initButtons(): Void { for (var i: Number = 0; i < _buttons.length; i++) { _buttons[i].handlePress = function () {}; _buttons[i].addEventListener("press", clickCallback); _buttons[i].addEventListener("focusIn", focusCallback); _buttons[i].ButtonText.noTranslate = true; } } private function resetDimensions(): Void { positionElements(); var parentBounds: Object = getBounds(_parent); var i: Number = Stage.height * 0.85 - parentBounds.yMax; if (i < 0) { messageText.autoSize = false; var extraHeight: Number = i * 100 / _yscale; messageText._height = messageText._height + extraHeight; positionElements(); } } private function positionElements(): Void { var maxLineWidth: Number = 0; for (var i: Number = 0; i < messageText.numLines; i++) maxLineWidth = Math.max(maxLineWidth, messageText.getLineMetrics(i).width); var buttonContainerWidth = 0; var buttonContainerHeight = 0; if (_buttonContainer != undefined) { buttonContainerWidth = _buttonContainer._width; buttonContainerHeight = _buttonContainer._height; } background._width = Math.max(maxLineWidth + 60, buttonContainerWidth + MessageBox.WIDTH_MARGIN * 2); background._height = messageText._height + buttonContainerHeight + MessageBox.HEIGHT_MARGIN * 2 + MessageBox.MESSAGE_TO_BUTTON_SPACER; messageText._y = (0 - background._height) / 2 + MessageBox.HEIGHT_MARGIN; _buttonContainer._y = background._height / 2 - MessageBox.HEIGHT_MARGIN - _buttonContainer._height / 2; _buttonContainer._x = (0 - _buttonContainer._width) / 2; divider._width = background._width - MessageBox.WIDTH_MARGIN * 2; divider._y = _buttonContainer._y - _buttonContainer._height / 2 - MessageBox.MESSAGE_TO_BUTTON_SPACER / 2; } private function clickCallback(aEvent: Object): Void { GameDelegate.call("buttonPress", [Number(aEvent.target._name.substr(-1))]); } private function focusCallback(aEvent: Object): Void { GameDelegate.call("PlaySound", ["UIMenuFocus"]); } private function onKeyDown(): Void { if (Key.getCode() == 89 && _buttons[0].ButtonText.text == "Yes") { GameDelegate.call("buttonPress", [0]); return; } if (Key.getCode() == 78 && _buttons[1].ButtonText.text == "No") { GameDelegate.call("buttonPress", [1]); return; } if (Key.getCode() == 65 && _buttons[2].ButtonText.text == "Yes to All") { GameDelegate.call("buttonPress", [2]); } } private function processMessage(a_text: String): Void { if (a_text.slice(0,2) != "$$" || a_text.slice(a_text.length-2, a_text.length) != "$$") return; var command = a_text.slice(2, a_text.length-2); var key = command.slice(0, command.indexOf("=")); if (key == null) return; var val = command.slice(command.indexOf("=") + 1); if (val == null) return; if (key.toLowerCase() == "loadmovie") { var oldMenu = _root.MessageMenu; oldMenu._visible = false; oldMenu.enabled = false; var newMenu = _root.createEmptyMovieClip("menuContainer", _root.getNextHighestDepth()); skse.Log("Loading " + val); newMenu.loadMovie(val); } } } ================================================ FILE: src/ModConfigPanel/ColorDialog.as ================================================ import skyui.components.colorswatch.ColorSwatch; import skyui.util.DialogManager; import gfx.managers.FocusHandler; import gfx.ui.NavigationCode; import Shared.GlobalFunc; import skyui.defines.Input; class ColorDialog extends OptionDialog { /* PRIVATE VARIABLES */ private var _acceptButton: MovieClip; private var _defaultButton: MovieClip; private var _cancelButton: MovieClip; private var _defaultControls: Object; /* STAGE ELEMENTS */ public var colorSwatch: ColorSwatch; /* PROPERTIES */ public var currentColor: Number; public var defaultColor: Number; /* INITIALIZATION */ public function ColorDialog() { super(); } /* PUBLIC FUNCTIONS */ // @override OptionDialog private function initButtons(): Void { var acceptControls: Object; var cancelControls: Object; if (platform == 0) { acceptControls = Input.Enter; _defaultControls = Input.ReadyWeapon; cancelControls = Input.Tab; } else { acceptControls = Input.Accept; _defaultControls = Input.YButton; cancelControls = Input.Cancel; } leftButtonPanel.clearButtons(); var defaultButton = leftButtonPanel.addButton({text: "$Default", controls: _defaultControls}); defaultButton.addEventListener("press", this, "onDefaultPress"); leftButtonPanel.updateButtons(); rightButtonPanel.clearButtons(); var cancelButton = rightButtonPanel.addButton({text: "$Cancel", controls: cancelControls}); cancelButton.addEventListener("press", this, "onCancelPress"); var acceptButton = rightButtonPanel.addButton({text: "$Accept", controls: acceptControls}); acceptButton.addEventListener("press", this, "onAcceptPress"); rightButtonPanel.updateButtons(); } // @override OptionDialog public function initContent(): Void { colorSwatch._x = -colorSwatch._width/2; colorSwatch._y = -colorSwatch._height/2; colorSwatch.selectedColor = currentColor; FocusHandler.instance.setFocus(colorSwatch, 0); } // @GFx public function handleInput(details, pathToFocus): Boolean { var nextClip = pathToFocus.shift(); if (nextClip.handleInput(details, pathToFocus)) return true; if (GlobalFunc.IsKeyPressed(details, false)) { if (details.navEquivalent == NavigationCode.TAB) { onCancelPress(); return true; } else if (details.navEquivalent == NavigationCode.ENTER) { onAcceptPress(); return true; } else if (details.control == _defaultControls.name) { onDefaultPress(); return true; } } // Don't forward to higher level return true; } /* PRIVATE FUNCTIONS */ private function onAcceptPress(): Void { skse.SendModEvent("SKICP_colorAccepted", null, colorSwatch.selectedColor); DialogManager.close(); } private function onDefaultPress(): Void { colorSwatch.selectedColor = defaultColor; } private function onCancelPress(): Void { skse.SendModEvent("SKICP_dialogCanceled"); DialogManager.close(); } } ================================================ FILE: src/ModConfigPanel/ConfigPanel.as ================================================ import gfx.managers.FocusHandler; import gfx.ui.InputDetails; import gfx.io.GameDelegate; import gfx.ui.NavigationCode; import Shared.GlobalFunc; import skyui.components.list.BasicEnumeration; import skyui.components.list.ScrollingList; import skyui.components.ButtonPanel; import skyui.util.DialogManager; import skyui.util.GlobalFunctions; import skyui.util.Translator; import skyui.defines.Input; import skyui.util.Tween; class ConfigPanel extends MovieClip { #include "../version.as" /* CONSTANTS */ private static var READY = 0; private static var WAIT_FOR_OPTION_DATA = 1; private static var WAIT_FOR_SLIDER_DATA = 2; private static var WAIT_FOR_MENU_DATA = 3; private static var WAIT_FOR_COLOR_DATA = 4; private static var WAIT_FOR_SELECT = 5; private static var WAIT_FOR_DEFAULT = 6; private static var DIALOG = 7; private static var FOCUS_MODLIST = 0; private static var FOCUS_OPTIONS = 1; /* PRIVATE VARIABLES */ private var _platform: Number; // Quest_Journal_mc private var _parentMenu: MovieClip; private var _buttonPanelL: ButtonPanel; private var _buttonPanelR: ButtonPanel; private var _bottomBarStartY: Number; private var _modListPanel: ModListPanel; private var _modList: ScrollingList; private var _subList: ScrollingList; private var _optionsList: MultiColumnScrollingList; private var _customContent: MovieClip; private var _customContentX: Number = 0; private var _customContentY: Number = 0; private var _state: Number; private var _focus: Number; private var _optionFlagsBuffer: Array; private var _optionTextBuffer: Array; private var _optionStrValueBuffer: Array; private var _optionNumValueBuffer: Array; private var _titleText: String = ""; private var _infoText: String = ""; private var _dialogTitleText: String = ""; private var _highlightIndex: Number = -1; private var _highlightIntervalID: Number; private var _menuDialogOptions: Array; private var _sliderDialogFormatString: String = ""; private var _currentRemapOption: Number = -1; private var _bRemapMode: Boolean = false; private var _remapDelayID: Number; private var _acceptControls: Object; private var _cancelControls: Object; private var _defaultControls: Object; private var _unmapControls: Object; private var _bDefaultEnabled: Boolean = false; private var _bRequestPageReset: Boolean = false; /* STAGE ELEMENTS */ public var contentHolder: MovieClip; public var titlebar: MovieClip; public var bottomBar: MovieClip; /* INITIALIATZION */ public function ConfigPanel() { // A bit hackish but w/e _parentMenu = _root.QuestJournalFader.Menu_mc; _modListPanel = contentHolder.modListPanel; _modList = _modListPanel.modListFader.list; _subList = _modListPanel.subListFader.list; _optionsList = contentHolder.optionsPanel.optionsList; _buttonPanelL = bottomBar.buttonPanelL; _buttonPanelR = bottomBar.buttonPanelR; _state = READY; _optionFlagsBuffer = []; _optionTextBuffer = []; _optionStrValueBuffer = []; _optionNumValueBuffer = []; _menuDialogOptions = []; contentHolder.infoPanel.textField.verticalAutoSize = "top"; } // @override MovieClip private function onLoad() { super.onLoad(); _modList.listEnumeration = new BasicEnumeration(_modList.entryList); _subList.listEnumeration = new BasicEnumeration(_subList.entryList); _optionsList.listEnumeration = new BasicEnumeration(_optionsList.entryList); _modList.addEventListener("itemPress", this, "onModListPress"); _modList.addEventListener("selectionChange", this, "onModListChange"); _subList.addEventListener("itemPress", this, "onSubListPress"); _subList.addEventListener("selectionChange", this, "onSubListChange"); _optionsList.addEventListener("itemPress", this, "onOptionPress"); _optionsList.addEventListener("selectionChange", this, "onOptionChange"); _modListPanel.addEventListener("modListEnter", this, "onModListEnter"); _modListPanel.addEventListener("modListExit", this, "onModListExit"); _modListPanel.addEventListener("subListEnter", this, "onSubListEnter"); _modListPanel.addEventListener("subListExit", this, "onSubListExit"); _optionsList._visible = false; } /* PAPYRUS INTERFACE */ // Holds last selected key public var selectedKeyCode = -1; public function unlock(): Void { _state = READY; // Execute depending forced reset when ready if (_bRequestPageReset) { _bRequestPageReset = false; var entry = _subList.listState.activeEntry; selectPage(entry); return; } } public function setModNames(/* names */): Void { _modList.clearList(); _modList.listState.savedIndex = null; for (var i=0; i>> 8) & 0xFF; _optionsList.entryList.push({optionType: optionType, text: _optionTextBuffer[i], strValue: _optionStrValueBuffer[i], numValue: _optionNumValueBuffer[i], flags: flags}); } // Pad uneven option count with empty option keyboard selection area is symmetrical if ((_optionsList.entryList.length % 2) != 0) _optionsList.entryList.push({optionType: OptionsListEntry.OPTION_EMPTY}); _optionsList.InvalidateData(); _optionsList.selectedIndex = -1; _optionFlagsBuffer.splice(0); _optionTextBuffer.splice(0); _optionStrValueBuffer.splice(0); _optionNumValueBuffer.splice(0); applyTitleText(); _highlightIndex = -1; clearInterval(_highlightIntervalID); _infoText = ""; applyInfoText(); } // Direct access to option data public var optionCursorIndex = -1; public function get optionCursor(): Object { return _optionsList.entryList[optionCursorIndex]; } public function invalidateOptionData(): Void { _optionsList.InvalidateData(); } public function setOptionFlags(/* values */): Void { var index = arguments[0]; var flags = arguments[1]; _optionsList.entryList[index].flags = flags; } public function forcePageReset(): Void { _bRequestPageReset = true; } public function showMessageDialog(a_text: String, a_acceptLabel: String, a_cancelLabel: String): Void { // Don't open it while READY cause we should always be waiting for something. if (_state == READY) { skse.SendModEvent("SKICP_messageDialogClosed", null, 0); return; } // This is a special dialog. It doesn't result in Papyrus event when closed but instead the // thread opening is supposed to sleep and wait until it's closed again (behaving like Message.Show()). // It keeps _state set to whatever it was. var initObj = { _x: 719, _y: 265, platform: _platform, messageText: a_text, acceptLabel: a_acceptLabel, cancelLabel: a_cancelLabel }; var dialog = DialogManager.open(this, "MessageDialog", initObj); dialog.addEventListener("dialogClosing", this, "onMessageDialogClosing"); dimOut(); } /* PUBLIC FUNCTIONS */ public function initExtensions(): Void { bottomBar.Lock("B"); _bottomBarStartY = bottomBar._y; showWelcomeScreen(); } public function setPlatform(a_platform: Number, a_bPS3Switch: Boolean): Void { _platform = a_platform; if (a_platform == 0) { _acceptControls = Input.Enter; _cancelControls = Input.Tab; _defaultControls = Input.ReadyWeapon; _unmapControls = Input.JournalYButton; } else { _acceptControls = Input.Accept; _cancelControls = Input.Cancel; _defaultControls = Input.JournalXButton; _unmapControls = Input.JournalYButton; } _buttonPanelL.setPlatform(a_platform, a_bPS3Switch); _buttonPanelR.setPlatform(a_platform, a_bPS3Switch); updateModListButtons(false); } public function startPage(): Void { GameDelegate.call("PlaySound", ["UIMenuOK"]); _parent.gotoAndPlay("fadeIn"); changeFocus(FOCUS_MODLIST); showWelcomeScreen(); } public function endPage(): Void { GameDelegate.call("PlaySound", ["UIMenuCancel"]); _parent.gotoAndPlay("fadeOut"); } // @GFx public function handleInput(details: InputDetails, pathToFocus: Array): Boolean { if (_bRemapMode) return true; if (GlobalFunc.IsKeyPressed(details)) { if (_focus == FOCUS_OPTIONS) { var valid = !_optionsList.disableInput && _optionsList.selectedIndex % 2 == 0 && _subList.entryList.length > 0 && _subList._visible; if (valid && details.navEquivalent == NavigationCode.LEFT) { changeFocus(FOCUS_MODLIST); _optionsList.listState.savedIndex = _optionsList.selectedIndex; _optionsList.selectedIndex = -1; var restored = _subList.listState.savedIndex; _subList.selectedIndex = (restored > -1) ? restored : ((_subList.listState.activeEntry.itemIndex > -1) ? _subList.listState.activeEntry.itemIndex : 0); return true; } } else if (_focus == FOCUS_MODLIST) { var valid = !_subList.disableInput && _optionsList.entryList.length > 0 && _optionsList._visible; if (valid && details.navEquivalent == NavigationCode.RIGHT) { changeFocus(FOCUS_OPTIONS); _subList.listState.savedIndex = _subList.selectedIndex; _subList.selectedIndex = -1; var restored = _optionsList.listState.savedIndex; _optionsList.selectedIndex = (restored > -1) ? restored : 0; return true; } } } var nextClip = pathToFocus.shift(); if (nextClip && nextClip.handleInput(details, pathToFocus)) return true; if (GlobalFunc.IsKeyPressed(details, false)) { if (details.navEquivalent == NavigationCode.TAB) { if (_modListPanel.isSublistActive()) { changeFocus(FOCUS_MODLIST); _modListPanel.showList(); } else if (_modListPanel.isListActive()) { _parentMenu.ConfigPanelClose(); } return true; } else if (details.control == _defaultControls.name) { requestDefaults(); return true; } else if (details.control == _unmapControls.name) { requestUnmap(); return true; } } // Don't forward to higher level return true; } /* PRIVATE FUNCTIONS */ private function requestDefaults(): Void { if (_state != READY) return; var index = _optionsList.selectedIndex; if (index == -1) return; if (_optionsList.selectedEntry.flags & OptionsListEntry.FLAG_DISABLED) return _state = WAIT_FOR_DEFAULT; skse.SendModEvent("SKICP_optionDefaulted", null, index); } private function requestUnmap(): Void { if (_state != READY) return; var index = _optionsList.selectedIndex; if (index == -1) return; if (_optionsList.selectedEntry.flags & (OptionsListEntry.FLAG_DISABLED | OptionsListEntry.FLAG_HIDDEN)) return if (!(_optionsList.selectedEntry.flags & OptionsListEntry.FLAG_WITH_UNMAP)) return selectedKeyCode = -1; _state = WAIT_FOR_SELECT; skse.SendModEvent("SKICP_keymapChanged", null, index); } private function onModListEnter(event: Object): Void { showWelcomeScreen(); } private function onModListExit(event: Object): Void { } private function onSubListEnter(event: Object): Void { } private function onSubListExit(event: Object): Void { _optionsList.clearList(); _optionsList.InvalidateData(); unloadCustomContent(); } private function onModListPress(a_event: Object): Void { selectMod(a_event.entry); } private function onModListChange(a_event: Object): Void { if (a_event.index != -1) changeFocus(FOCUS_MODLIST); updateModListButtons(false); } private function onSubListPress(a_event: Object): Void { selectPage(a_event.entry); } private function onSubListChange(a_event: Object): Void { if (a_event.index != -1) changeFocus(FOCUS_MODLIST); updateModListButtons(true); } private function onOptionPress(a_event: Object): Void { selectOption(a_event.index); } private function onOptionChange(a_event: Object): Void { if (a_event.index != -1) changeFocus(FOCUS_OPTIONS); initHighlightOption(a_event.index); updateOptionButtons(); } private function onOptionChangeDialogClosing(event: Object): Void { dimIn(); } private function onMessageDialogClosing(event: Object): Void { dimIn(); } private function onOptionChangeDialogClosed(event: Object): Void { } private function selectMod(a_entry: Object): Void { if (_state != READY) return; _subList.listState.activeEntry = null; _subList.clearList(); _subList.InvalidateData(); _optionsList.clearList(); _optionsList.InvalidateData(); unloadCustomContent(); _state = WAIT_FOR_OPTION_DATA; skse.SendModEvent("SKICP_modSelected", null, a_entry.modIndex); _modListPanel.showSublist(); } private function selectPage(a_entry: Object): Void { if (_state != READY) return; if (a_entry != null) { _subList.listState.activeEntry = a_entry; _subList.UpdateList(); // Send name as well so mod doesn't have to look it up by index later _state = WAIT_FOR_OPTION_DATA; skse.SendModEvent("SKICP_pageSelected", a_entry.pageName, a_entry.pageIndex); // Special case for ForcePageReset without any pages } else { _state = WAIT_FOR_OPTION_DATA; skse.SendModEvent("SKICP_pageSelected", "", -1); } } private function selectOption(a_index: Number): Void { if (_state != READY) return; var e = _optionsList.selectedEntry; if (e == undefined) return; if (e.flags & OptionsListEntry.FLAG_DISABLED) return switch (e.optionType) { case OptionsListEntry.OPTION_EMPTY: case OptionsListEntry.OPTION_HEADER: break; case OptionsListEntry.OPTION_TEXT: case OptionsListEntry.OPTION_TOGGLE: _state = WAIT_FOR_SELECT; skse.SendModEvent("SKICP_optionSelected", null, a_index); break; case OptionsListEntry.OPTION_SLIDER: _dialogTitleText = e.text; _sliderDialogFormatString = e.strValue; _state = WAIT_FOR_SLIDER_DATA; skse.SendModEvent("SKICP_sliderSelected", null, a_index); break; case OptionsListEntry.OPTION_MENU: _dialogTitleText = e.text; _state = WAIT_FOR_MENU_DATA; skse.SendModEvent("SKICP_menuSelected", null, a_index); break; case OptionsListEntry.OPTION_COLOR: _dialogTitleText = e.text; _state = WAIT_FOR_COLOR_DATA; skse.SendModEvent("SKICP_colorSelected", null, a_index); break; case OptionsListEntry.OPTION_KEYMAP: if (!_bRemapMode) { _currentRemapOption = a_index; initRemapMode(); } break; } } private function initRemapMode(): Void { dimOut(); var dialog = DialogManager.open(this, "KeymapDialog", {_x: 719, _y: 240}); dialog.background._width = dialog.textField.textWidth + 100; _bRemapMode = true; skse.StartRemapMode(this); } // @SKSE private function EndRemapMode(a_keyCode: Number): Void { selectedKeyCode = a_keyCode; _state = WAIT_FOR_SELECT; skse.SendModEvent("SKICP_keymapChanged", null, _currentRemapOption); _remapDelayID = setInterval(this, "clearRemap", 200); DialogManager.close(); dimIn(); } private function clearRemap(): Void { clearInterval(_remapDelayID); delete _remapDelayID; _bRemapMode = false; _currentRemapOption = -1; } private function initHighlightOption(a_index: Number): Void { if (_state != READY) return; // Same option? if (a_index == _highlightIndex) return; _highlightIndex = a_index; clearInterval(_highlightIntervalID); _highlightIntervalID = setInterval(this, "doHighlightOption", 200, a_index); } private function doHighlightOption(a_index: Number): Void { clearInterval(_highlightIntervalID); delete _highlightIntervalID; skse.SendModEvent("SKICP_optionHighlighted", null, a_index); } private function applyTitleText(): Void { titlebar.textField.text = _titleText; var w = titlebar.textField.textWidth + 100; if (w < 300) w = 300; titlebar.background._width = w; } private function applyInfoText(): Void { var t = contentHolder.infoPanel; t.textField.text = GlobalFunctions.unescape(_infoText); if (_infoText != "") { var h = t.textField.textHeight + 22; t.background._height = h; } else { t.background._height = 32; } } private function changeFocus(a_focus: Number): Void { _focus = a_focus; FocusHandler.instance.setFocus(a_focus == FOCUS_OPTIONS ? _optionsList : _modListPanel, 0); } private function dimOut(): Void { GameDelegate.call("PlaySound",["UIMenuBladeOpenSD"]); _optionsList.disableSelection = _optionsList.disableInput = true; _modListPanel.isDisabled = true; Tween.LinearTween(bottomBar, "_alpha", 100, 0, 0.5, null); Tween.LinearTween(bottomBar, "_y", _bottomBarStartY, _bottomBarStartY+50, 0.5, null); Tween.LinearTween(contentHolder, "_alpha", 100, 75, 0.5, null); } private function dimIn(): Void { GameDelegate.call("PlaySound",["UIMenuBladeCloseSD"]); _optionsList.disableSelection = _optionsList.disableInput = false; _modListPanel.isDisabled = false; Tween.LinearTween(bottomBar, "_alpha", 0, 100, 0.5, null); Tween.LinearTween(bottomBar, "_y", _bottomBarStartY+50, _bottomBarStartY, 0.5, null); Tween.LinearTween(contentHolder, "_alpha", 75, 100, 0.5, null); } private function showWelcomeScreen(): Void { setCustomContentParams(150, 50); loadCustomContent("skyui/mcm_splash.swf"); setTitleText("$MOD CONFIGURATION"); setInfoText(""); } private function updateModListButtons(a_bSubList: Boolean): Void { var entry = _modListPanel.selectedEntry; _buttonPanelL.clearButtons(); if (entry != null) _buttonPanelL.addButton({text: "$Select", controls: _acceptControls}); _buttonPanelL.updateButtons(true); _buttonPanelR.clearButtons(); _buttonPanelR.addButton({text: a_bSubList? "$Back" : "$Exit", controls: _cancelControls}); _buttonPanelR.updateButtons(true); } private function updateOptionButtons(): Void { var entry = _optionsList.selectedEntry; _buttonPanelL.clearButtons(); if (entry != null && !(entry.flags & (OptionsListEntry.FLAG_DISABLED | OptionsListEntry.FLAG_HIDDEN))) { var type = entry.optionType; switch (type) { case OptionsListEntry.OPTION_EMPTY: case OptionsListEntry.OPTION_HEADER: break; case OptionsListEntry.OPTION_TOGGLE: _buttonPanelL.addButton({text: "$Toggle", controls: _acceptControls}); break; case OptionsListEntry.OPTION_TEXT: _buttonPanelL.addButton({text: "$Select", controls: _acceptControls}); break; case OptionsListEntry.OPTION_SLIDER: _buttonPanelL.addButton({text: "$Open Slider", controls: _acceptControls}); break; case OptionsListEntry.OPTION_MENU: _buttonPanelL.addButton({text: "$Open Menu", controls: _acceptControls}); break; case OptionsListEntry.OPTION_COLOR: _buttonPanelL.addButton({text: "$Pick Color", controls: _acceptControls}); break; case OptionsListEntry.OPTION_KEYMAP: _buttonPanelL.addButton({text: "$Remap", controls: _acceptControls}); if (entry.flags & OptionsListEntry.FLAG_WITH_UNMAP) _buttonPanelL.addButton({text: "$Unmap", controls: _unmapControls}); break; } if (type != OptionsListEntry.OPTION_EMPTY && type != OptionsListEntry.OPTION_HEADER) { _buttonPanelL.addButton({text: "$Default", controls: _defaultControls}); _bDefaultEnabled = true; } else { _bDefaultEnabled = false; } } else { _bDefaultEnabled = false; } _buttonPanelL.updateButtons(true); _buttonPanelR.clearButtons(); _buttonPanelR.addButton({text: "$Back", controls: _cancelControls}); _buttonPanelR.updateButtons(true); } } ================================================ FILE: src/ModConfigPanel/MenuDialog.as ================================================ import skyui.components.list.BasicEnumeration; import skyui.components.list.ScrollingList; import skyui.util.DialogManager; import gfx.managers.FocusHandler; import gfx.ui.NavigationCode; import Shared.GlobalFunc; import skyui.defines.Input; class MenuDialog extends OptionDialog { /* PRIVATE VARIABLES */ private var _defaultControls: Object; private var _closeControls: Object; /* STAGE ELEMENTS */ public var menuList: ScrollingList; /* PROPERTIES */ public var menuOptions: Array; public var menuStartIndex: Number; public var menuDefaultIndex: Number; /* INITIALIZATION */ public function MenuDialog() { super(); } /* PUBLIC FUNCTIONS */ // @override OptionDialog public function initButtons(): Void { if (platform == 0) { _defaultControls = Input.ReadyWeapon; _closeControls = Input.Tab; } else { _defaultControls = Input.YButton; _closeControls = Input.Cancel; } leftButtonPanel.clearButtons(); var defaultButton = leftButtonPanel.addButton({text: "$Default", controls: _defaultControls}); defaultButton.addEventListener("press", this, "onDefaultPress"); leftButtonPanel.updateButtons(); rightButtonPanel.clearButtons(); var closeButton = rightButtonPanel.addButton({text: "$Exit", controls: _closeControls}); closeButton.addEventListener("press", this, "onExitPress"); rightButtonPanel.updateButtons(); } // @override OptionDialog public function initContent(): Void { menuList.addEventListener("itemPress", this, "onMenuListPress"); menuList.listEnumeration = new BasicEnumeration(menuList.entryList); for (var i=0; i -1) ? restored : 0; if (modListFader.getDepth() < subListFader.getDepth()) modListFader.swapDepths(subListFader); dispatchEvent({type: "modListEnter"}); break; case SUBLIST_ACTIVE: subListFader.gotoAndStop("show"); _subList.disableInput = false; _subList.disableSelection = false; _subList.selectedIndex = -1; if (subListFader.getDepth() < modListFader.getDepth()) subListFader.swapDepths(modListFader); decorTitle.onPress = function(): Void { if (!_parent.isDisabled) _parent.showList(); }; dispatchEvent({type: "subListEnter"}); break; case TRANSITION_TO_SUBLIST: _titleText = _modList.selectedEntry.text; decorTitle._y = _modList.selectedClip._y; hideDecorTitle(false); decorTitle.gotoAndPlay("fadeIn"); decorTitle.textHolder.textField.text = _titleText; modListFader.gotoAndPlay("fadeOut"); _modList.listState.savedIndex = _modList.selectedIndex; _modList.disableInput = true; _modList.disableSelection = true; sublistIndicator._visible = false; dispatchEvent({type: "modListExit"}); break; case TRANSITION_TO_LIST: decorTitle.gotoAndPlay("fadeOut"); subListFader.gotoAndPlay("fadeOut"); delete decorTitle.onPress; _subList.disableInput = true; _subList.disableSelection = true; dispatchEvent({type: "subListExit"}); break; default: return; } _state = a_state; } private function onAnimFinish(a_animID: Number): Void { switch (a_animID) { case ANIM_DECORTITLE_FADE_IN: // Should happen at the same time as ANIM_LIST_FADE_OUT, we just need to handle one of them. var tween = new Tween(decorTitle, "_y", Strong.easeOut, decorTitle._y, _modList._x + _modList.topBorder, 0.75, true); tween.FPS = 60; tween.onMotionFinished = Delegate.create(this, decorMotionFinishedFunc); tween.onMotionChanged = Delegate.create(this, decorMotionUpdateFunc); break; case ANIM_DECORTITLE_TWEEN: subListFader.gotoAndPlay("fadeIn"); break; case ANIM_SUBLIST_FADE_IN: setState(SUBLIST_ACTIVE); break; case ANIM_SUBLIST_FADE_OUT: // Should happen at the same time as ANIM_DECORTITLE_FADE_OUT, we just need to handle one of them. modListFader.gotoAndPlay("fadeIn"); hideDecorTitle(true); break; case ANIM_LIST_FADE_IN: setState(LIST_ACTIVE); break; } } private function onSubListPress(a_event: Object): Void { } private function decorMotionFinishedFunc(): Void { onAnimFinish(ANIM_DECORTITLE_TWEEN); } private function decorMotionUpdateFunc(): Void { decorTop._y = _modList._y; decorTop._height = decorTitle._y - decorTop._y ; decorBottom._y = decorTitle._y + decorTitle._height; decorBottom._height = decorBottom._y - _modList._height; } private function hideDecorTitle(a_hide: Boolean): Void { if (a_hide) { decorTop._visible = true; decorTop._y = _modList._y; decorTop._height = _modList._height; decorTitle._visible = false; decorBottom._visible = false; } else { decorTitle._visible = true; decorTop._visible = true; decorTop._y = _modList._y; decorTop._height = decorTitle._y - decorTop._y ; decorBottom._visible = true; decorBottom._y = decorTitle._y + decorTitle._height; decorBottom._height = decorBottom._y - _modList._height; } } } ================================================ FILE: src/ModConfigPanel/MultiColumnScrollBar.as ================================================ import gfx.controls.ScrollBar; class MultiColumnScrollBar extends ScrollBar { private var _scrollDelta = 1; private var _trackScrollPageSize = 1; public function MultiColumnScrollBar() { super(); } public function get trackScrollPageSize(): Number { return _trackScrollPageSize; } public function set trackScrollPageSize(a_val: Number): Void { _trackScrollPageSize = Math.ceil(a_val / _scrollDelta) * _scrollDelta; } public function get scrollDelta(): Number { return _scrollDelta; } public function set scrollDelta(a_val: Number): Void { _scrollDelta = a_val; _trackScrollPageSize = Math.ceil(_trackScrollPageSize / a_val) * a_val; } public function get position(): Number { return _position; } public function set position(a_val: Number): Void { a_val -= (a_val % _scrollDelta); super.position = a_val; } private function scrollWheel(a_delta: Number): Void { position -= (a_delta * _trackScrollPageSize); } private function scrollUp(): Void { position -= _scrollDelta; } private function scrollDown(): Void { position += _scrollDelta; } } ================================================ FILE: src/ModConfigPanel/MultiColumnScrollingList.as ================================================ import skyui.components.list.ScrollingList; import gfx.ui.NavigationCode; import gfx.ui.InputDetails; import Shared.GlobalFunc; class MultiColumnScrollingList extends ScrollingList { /* PRIVATE VARIABLES */ private var _separators: Array; /* PROPERTIES */ public var columnSpacing: Number = 0; public var separatorRenderer: String; private var _columnCount: Number = 1; public function get columnCount(): Number { return _columnCount; } public function set columnCount(a_value: Number) { _columnCount = a_value; refreshSeparators(); } /* INITIALIZATION */ public function MultiColumnScrollingList() { super(); scrollDelta = columnCount; _maxListIndex *= columnCount; if (_separators == null) _separators = []; } public function onLoad(): Void { super.onLoad(); if(scrollbar != undefined) { scrollbar.scrollDelta = scrollDelta; } } /* PUBLIC FUNCTIONS */ // @override ScrollingList public function UpdateList(): Void { // Prepare clips setClipCount(_maxListIndex); var xStart = background._x + leftBorder; var yStart = background._y + topBorder; var h = 0; var w = 0; var lastColumnIndex = columnCount - 1; var columnWidth = (background._width - leftBorder - rightBorder - (columnCount-1) * columnSpacing) / columnCount; // Clear clipIndex for everything before the selected list part for (var i = 0; i < getListEnumSize() && i < _scrollPosition ; i++) getListEnumEntry(i).clipIndex = undefined; _listIndex = 0; // Display the selected part of the list for (var i = _scrollPosition; i < getListEnumSize() && _listIndex < _maxListIndex; i++) { var entryClip = getClipByIndex(_listIndex); var entryItem = getListEnumEntry(i); entryClip.itemIndex = entryItem.itemIndex; entryItem.clipIndex = _listIndex; entryClip.width = columnWidth; entryClip.setEntry(entryItem, listState); entryClip._x = xStart + w; entryClip._y = yStart + h; entryClip._visible = true; if (i % columnCount == lastColumnIndex) { w = 0; h = h + entryHeight; } else { w = w + columnWidth + columnSpacing; } ++_listIndex; } // Clear clipIndex for everything after the selected list part for (var i = _scrollPosition + _listIndex; i < getListEnumSize(); i++) getListEnumEntry(i).clipIndex = undefined; // Select entry under the cursor for mouse-driven navigation if (isMouseDrivenNav) for (var e = Mouse.getTopMostEntity(); e != undefined; e = e._parent) if (e._parent == this && e._visible && e.itemIndex != undefined) doSetSelectedIndex(e.itemIndex, SELECT_MOUSE); var bShowSeparators = _listIndex > 0; for (var i=0; i<_separators.length; i++) _separators[i]._visible = bShowSeparators; } // @GFx public function handleInput(details: InputDetails, pathToFocus: Array): Boolean { if (disableInput) return false; if (super.handleInput(details, pathToFocus)) return true; if (GlobalFunc.IsKeyPressed(details)) { if (details.navEquivalent == NavigationCode.LEFT) { moveSelectionLeft(); return true; } else if (details.navEquivalent == NavigationCode.RIGHT) { moveSelectionRight(); return true; } } return false; } public function moveSelectionLeft(): Void { if (disableSelection) return; if (_selectedIndex == -1) { selectDefaultIndex(false); } else if ((getSelectedListEnumIndex() % columnCount) > 0) { doSetSelectedIndex(getListEnumRelativeIndex(-1), SELECT_KEYBOARD); isMouseDrivenNav = false; } } public function moveSelectionRight(): Void { if (disableSelection) return; if (_selectedIndex == -1) { selectDefaultIndex(false); } else if ((getSelectedListEnumIndex() % columnCount) < (columnCount - 1)) { doSetSelectedIndex(getListEnumRelativeIndex(1), SELECT_KEYBOARD); isMouseDrivenNav = false; } } /* PRIVATE FUNCTIONS */ private function refreshSeparators() { if (_separators == null) _separators = []; while (_separators.length > 0) { var e = _separators.pop(); e.removeMovieClip(); } // Create separators if (!separatorRenderer) return; var columnWidth = (background._width - leftBorder - rightBorder - (columnCount-1) * columnSpacing) / columnCount; var t = background._x + leftBorder; var d = columnSpacing/2; for (var i=0; i < columnCount-1; i++) { var e = attachMovie(separatorRenderer, separatorRenderer + i, getNextHighestDepth()); t += columnWidth + d; e._x = t; e._y = background._y; e._height = background._height; e._alpha = 50; _separators.push(e); t += d; } } } ================================================ FILE: src/ModConfigPanel/OptionDialog.as ================================================ import skyui.components.dialog.BasicDialog; import skyui.components.ButtonPanel; import skyui.util.Translator; import gfx.io.GameDelegate; import gfx.ui.NavigationCode; import Shared.GlobalFunc; // @abstract class OptionDialog extends BasicDialog { /* PRIVATE VARIABLES */ private var _updateButtonID: Number; /* STAGE ELEMENTS */ public var background: MovieClip; public var leftButtonPanel: ButtonPanel; public var rightButtonPanel: ButtonPanel; public var titleTextField: TextField; /* PROPERTIES */ public var platform: Number; public var titleText: String; /* INITIALIZATION */ public function OptionDialog() { super(); } // @override MovieClip private function onLoad(): Void { leftButtonPanel.setPlatform(platform, false); rightButtonPanel.setPlatform(platform, false); initButtons(); titleTextField.textAutoSize = "shrink"; titleText = Translator.translate(titleText); titleTextField.SetText(titleText.toUpperCase()); initContent(); } /* PUBLIC FUNCTIONS */ // @abstract public function initButtons(): Void {} // @abstract public function initContent(): Void {} } ================================================ FILE: src/ModConfigPanel/OptionsListEntry.as ================================================ import skyui.components.list.ScrollingList; import skyui.components.list.ListState; import skyui.components.list.BasicListEntry; import skyui.util.ConfigManager; import skyui.util.GlobalFunctions; import skyui.util.Translator; class OptionsListEntry extends BasicListEntry { /* CONSTANTS */ // 1 byte public static var OPTION_EMPTY = 0x00; public static var OPTION_HEADER = 0x01; public static var OPTION_TEXT = 0x02; public static var OPTION_TOGGLE = 0x03; public static var OPTION_SLIDER = 0x04; public static var OPTION_MENU = 0x05; public static var OPTION_COLOR = 0x06; public static var OPTION_KEYMAP = 0x07; // 1 byte public static var FLAG_DISABLED = 0x01; public static var FLAG_HIDDEN = 0x02; public static var FLAG_WITH_UNMAP = 0x04; public static var ALPHA_SELECTED = 100; public static var ALPHA_ACTIVE = 75; public static var ALPHA_ENABLED = 100; public static var ALPHA_DISABLED = 50; /* STAGE ELMENTS */ public var selectIndicator: MovieClip; public var labelTextField: TextField; public var valueTextField: TextField; public var headerDecor: MovieClip; public var sliderIcon: MovieClip; public var menuIcon: MovieClip; public var toggleIcon: MovieClip; public var colorIcon: MovieClip; public var buttonArt: MovieClip; /* PROPERTIES */ public function get width(): Number { return background._width; } public function set width(a_val: Number) { background._width = a_val; selectIndicator._width = a_val; } /* PUBLIC FUNCTIONS */ public function initialize(a_index: Number, a_list: ScrollingList): Void { gotoAndStop("empty"); } public function setEntry(a_entryObject: Object, a_state: ListState): Void { var entryWidth = background._width; var isSelected = a_entryObject == a_state.list.selectedEntry; var flags = a_entryObject.flags; var isEnabled = !(flags & (FLAG_DISABLED | FLAG_HIDDEN)); selectIndicator._visible = isSelected; _alpha = isEnabled ? ALPHA_ENABLED : ALPHA_DISABLED; // If entry is hidden, treat like empty option var optionType = a_entryObject.optionType; if (flags & FLAG_HIDDEN) optionType = OPTION_EMPTY; switch (optionType) { case OPTION_HEADER: enabled = false; gotoAndStop("header"); labelTextField._width = entryWidth; labelTextField.SetText(a_entryObject.text, true); labelTextField._alpha = 100; headerDecor._x = labelTextField.getLineMetrics(0).width + 10; headerDecor._width = entryWidth - headerDecor._x; break; case OPTION_TEXT: enabled = isEnabled; gotoAndStop("text"); labelTextField._width = entryWidth; labelTextField.SetText(a_entryObject.text, true); labelTextField._alpha = isSelected ? ALPHA_SELECTED : ALPHA_ACTIVE; valueTextField._width = entryWidth; valueTextField.SetText(Translator.translateNested(a_entryObject.strValue).toUpperCase(), true); break; case OPTION_TOGGLE: enabled = isEnabled; gotoAndStop("toggle"); labelTextField._width = entryWidth; labelTextField.SetText(a_entryObject.text, true); labelTextField._alpha = isSelected ? ALPHA_SELECTED : ALPHA_ACTIVE; toggleIcon._x = entryWidth - toggleIcon._width; toggleIcon.gotoAndStop(a_entryObject.numValue? "on" : "off"); break; case OPTION_SLIDER: enabled = isEnabled; gotoAndStop("slider"); labelTextField._width = entryWidth; labelTextField.SetText(a_entryObject.text, true); labelTextField._alpha = isSelected ? ALPHA_SELECTED : ALPHA_ACTIVE; valueTextField._width = entryWidth; valueTextField.SetText(GlobalFunctions.formatString(Translator.translate(a_entryObject.strValue), a_entryObject.numValue).toUpperCase(), true); sliderIcon._x = valueTextField.getLineMetrics(0).x - sliderIcon._width; break; case OPTION_MENU: enabled = isEnabled; gotoAndStop("menu"); labelTextField._width = entryWidth; labelTextField.SetText(a_entryObject.text, true); labelTextField._alpha = isSelected ? ALPHA_SELECTED : ALPHA_ACTIVE; valueTextField._width = entryWidth; valueTextField.SetText(Translator.translateNested(a_entryObject.strValue).toUpperCase(), true); menuIcon._x = valueTextField.getLineMetrics(0).x - menuIcon._width; break; case OPTION_COLOR: enabled = isEnabled; gotoAndStop("color"); labelTextField._width = entryWidth; labelTextField.SetText(a_entryObject.text, true); labelTextField._alpha = isSelected ? ALPHA_SELECTED : ALPHA_ACTIVE; colorIcon._x = entryWidth - colorIcon._width; var color: Color = new Color(colorIcon.pigment); color.setRGB(a_entryObject.numValue); break; case OPTION_KEYMAP: enabled = isEnabled; gotoAndStop("keymap"); labelTextField._width = entryWidth; labelTextField.SetText(a_entryObject.text, true); labelTextField._alpha = isSelected ? ALPHA_SELECTED : ALPHA_ACTIVE; var keyCode = a_entryObject.numValue; if (keyCode == -1) keyCode = 282; // "???" buttonArt.gotoAndStop(keyCode); buttonArt._x = entryWidth - buttonArt._width; break; case OPTION_EMPTY: default: enabled = false; gotoAndStop("empty"); } } } ================================================ FILE: src/ModConfigPanel/ParticleEmitter.as ================================================ class ParticleEmitter extends MovieClip { /* Stage Elements */ private var _particleHolder: MovieClip; /* Component Definitions */ public var particleLinkageName: String; public var particleFrameLabel: String; public var particleScaleFactor: Number; public var maxParticles: Number; public var effectBuffer: Number; /* Private Variables */ private var _effectWidth: Number; private var _effectHeight: Number; private var _particles: Array; /* Interface */ public function set width(a_val: Number): Void { _width = a_val; _effectWidth = a_val * 100/_particleHolder._xscale; } public function get width(): Number { return _width; } public function set height(a_val: Number): Void { _height = a_val; _effectHeight = a_val * 100/_particleHolder._yscale; } public function get height(): Number { return _height; } public function set visible(a_val: Boolean): Void { _particleHolder._visible = a_val; } public function get visible(): Boolean { return _particleHolder._visible; } public function set alpha(a_val: Number): Void { _particleHolder._alpha = a_val; } public function get alpha(): Number { return _particleHolder._alpha; } public function set xscale(a_val: Number): Void { _particleHolder._xscale = a_val; _width = _effectWidth * a_val/100; } public function get xscale(): Number { return _particleHolder._xscale; } public function set yscale(a_val: Number): Void { _particleHolder._yscale = a_val; _height *= a_val/100; } public function get yscale(): Number { return _particleHolder._yscale; } public function ParticleEmitter() { // The ParticleEmitter MovieClip(this) is actually a mask, the real magic bappens in _particleHolder _visible = false; _effectWidth = _width; _effectHeight = _height; var particleHolderName: String = "_particleHolder"; while (_parent[particleHolderName] != undefined) particleHolderName = "_" + particleHolderName; _particleHolder = _parent.createEmptyMovieClip(particleHolderName, _parent.getNextHighestDepth()); _particleHolder.swapDepths(this); //Swap depths so the _particleHolder is on the correct "layer" _particleHolder.setMask(this); _particles = new Array(); } private function setParticleFrameLabel(a_frameLabel: String): Void { particleFrameLabel = a_frameLabel; for (var i: Number = 0; i < _particles.length; i++) { if (_particles[i].frameLabel == particleFrameLabel) continue; _particles[i].frameLabel = particleFrameLabel; _particles[i].gotoAndStop(particleFrameLabel); } } private function addParticle(a_particleInitFunc: Function, a_forceAdd: Boolean): MovieClip { if (_particles.length >= maxParticles && !a_forceAdd) return undefined; var initFunc: Function = a_particleInitFunc || initParticle; var particle: MovieClip = _particleHolder.attachMovie(particleLinkageName, "particle" + _particles.length, _particleHolder.getNextHighestDepth()); particle.frameLabel = particleFrameLabel; particle.gotoAndStop(particleFrameLabel); particle = initFunc(particle); _particles.push(particle); return particle; } private function initParticle(a_particle: MovieClip): MovieClip { var particle: MovieClip = a_particle; particle._visible = false; return particle; } } ================================================ FILE: src/ModConfigPanel/SkyUISplash.as ================================================ class SkyUISplash extends MovieClip { #include "../version.as" /* STAGE ELEMENTS */ public var versionText: TextField; public function SkyUISplash() { } // @override MovieClip private function onLoad(): Void { super.onLoad(); versionText.text = ("v" + SKYUI_VERSION_STRING); } } ================================================ FILE: src/ModConfigPanel/SliderDialog.as ================================================ import skyui.util.DialogManager; import skyui.util.GlobalFunctions; import skyui.util.Translator; import gfx.managers.FocusHandler; import gfx.ui.NavigationCode; import Shared.GlobalFunc; import skyui.defines.Input; class SliderDialog extends OptionDialog { /* PRIVATE VARIABLES */ private var _acceptControls: Object; private var _defaultControls: Object; private var _cancelControls: Object; /* STAGE ELEMENTS */ public var sliderPanel: MovieClip; /* PROPERTIES */ public var sliderValue: Number; public var sliderDefault: Number; public var sliderMax: Number; public var sliderMin: Number; public var sliderInterval: Number; public var sliderFormatString: String; /* INITIALIZATION */ public function SliderDialog() { super(); } /* PUBLIC FUNCTIONS */ // @override OptionDialog public function initButtons(): Void { if (platform == 0) { _acceptControls = Input.Enter; _defaultControls = Input.ReadyWeapon; _cancelControls = Input.Tab; } else { _acceptControls = Input.Accept; _defaultControls = Input.YButton; _cancelControls = Input.Cancel; } leftButtonPanel.clearButtons(); var defaultButton = leftButtonPanel.addButton({text: "$Default", controls: _defaultControls}); defaultButton.addEventListener("press", this, "onDefaultPress"); leftButtonPanel.updateButtons(); rightButtonPanel.clearButtons(); var cancelButton = rightButtonPanel.addButton({text: "$Cancel", controls: _cancelControls}); cancelButton.addEventListener("press", this, "onCancelPress"); var acceptButton = rightButtonPanel.addButton({text: "$Accept", controls: _acceptControls}); acceptButton.addEventListener("press", this, "onAcceptPress"); rightButtonPanel.updateButtons(); } // @override OptionDialog public function initContent(): Void { sliderPanel.slider.maximum = sliderMax; sliderPanel.slider.minimum = sliderMin; sliderPanel.slider.liveDragging = true; sliderPanel.slider.snapInterval = sliderInterval; sliderPanel.slider.snapping = true; sliderPanel.slider.value = sliderValue; sliderFormatString = Translator.translate(sliderFormatString); updateValueText(); sliderPanel.slider.addEventListener("change", this, "onValueChange"); FocusHandler.instance.setFocus(sliderPanel.slider, 0); } // @GFx public function handleInput(details, pathToFocus): Boolean { var nextClip = pathToFocus.shift(); if (nextClip.handleInput(details, pathToFocus)) return true; if (GlobalFunc.IsKeyPressed(details, false)) { if (details.navEquivalent == NavigationCode.TAB) { onCancelPress(); return true; } else if (details.navEquivalent == NavigationCode.ENTER) { onAcceptPress(); return true; } else if (details.control == _defaultControls.name) { onDefaultPress(); return true; } } // Don't forward to higher level return true; } /* PRIVATE FUNCTIONS */ private function onValueChange(event: Object): Void { sliderValue = event.target.value; updateValueText(); } private function onAcceptPress(): Void { skse.SendModEvent("SKICP_sliderAccepted", null, sliderValue); DialogManager.close(); } private function onDefaultPress(): Void { sliderValue = sliderPanel.slider.value = sliderDefault; updateValueText(); } private function onCancelPress(): Void { skse.SendModEvent("SKICP_dialogCanceled"); DialogManager.close(); } private function updateValueText(): Void { var t = sliderFormatString ? GlobalFunctions.formatString(sliderFormatString, sliderValue) : Math.round(sliderValue * 100) / 100; sliderPanel.valueTextField.SetText(t); } } ================================================ FILE: src/ModConfigPanel/SnowEffect.as ================================================ import mx.utils.Delegate; import skyui.util.Tween; class SnowEffect extends ParticleEmitter { /* Public Variables */ public var minWindSpeed: Number = 0; public var maxWindSpeed: Number = 400; public var initialWindSpeed: Number = 0; public var particleRotationFactor:Number = 1; /* Private Variables */ private var _framesPerSpawn: Number = 5; private var _windSpeed: Number; private var __currentFrame: Number = 0; private var _nextSpawn: Number = __currentFrame + _framesPerSpawn; private var _windInterval: Number; public function SnowEffect() { super(); _windSpeed = initialWindSpeed; windLoop(); onEnterFrame = emitter; } // @Override ParticleEmitter private function initParticle(a_particle: MovieClip): MovieClip { var particle: MovieClip = a_particle; particle._alpha = 100; //todo particle._x = Math.random()*(_effectWidth + 2*effectBuffer) - effectBuffer; particle._y = Math.random()*(_effectHeight - effectBuffer) - _effectHeight; particle._xscale = particle._yscale = (Math.max(0.5, Math.random())*particleScaleFactor)*100; xLoop(particle); yLoop(particle); return particle; } private function emitter(): Void { if (__currentFrame >= _nextSpawn) { // set to >= to support for non integer _framePerSpawn ? if (addParticle() == undefined) { delete onEnterFrame; return; } if (_particles.length % 100 == 0 && _particles.length < maxParticles) particleScaleFactor += 0.15; // Increase size if (_particles.length % 20 == 0 && _framesPerSpawn > 1) _framesPerSpawn--; // Speed up _nextSpawn += _framesPerSpawn; } __currentFrame++; } private function windLoop(): Void { var time: Number = Math.random()*3+1; var nextSpeed: Number = Math.random()*(2*maxWindSpeed-minWindSpeed)-(minWindSpeed+maxWindSpeed); var nextWind: Number = Math.random()*(2)+1; Tween.LinearTween(this, "_windSpeed", this._windSpeed, nextSpeed, time, null); if (_windInterval != undefined) { clearInterval(_windInterval); delete(_windInterval); } _windInterval = setInterval(this, "windLoop", nextWind); } private function xLoop(a_particle: MovieClip): Void { if (a_particle._x > _effectWidth + effectBuffer) a_particle._x = Math.random() * -effectBuffer; else if (a_particle._x < -effectBuffer) a_particle._x = _effectWidth + Math.random() * effectBuffer; var onCompleteFn: Function = Delegate.create(this, function() {xLoop(a_particle)}); var duration: Number = Math.random()*2+1; // Quad.easeInOut Tween.LinearTween(a_particle, "_x", a_particle._x, a_particle._x+(Math.random()*80-40+_windSpeed)*(a_particle._xscale/100), duration, onCompleteFn); Tween.LinearTween(a_particle, "_rotation", a_particle._rotation, Math.random()*particleRotationFactor*600, duration, null); } private function yLoop(a_particle: MovieClip): Void { if (a_particle._y > _effectHeight + effectBuffer) { a_particle._y = Math.random() * -effectBuffer; if (Math.floor(4096*Math.random()) == 0 && _particles.length > 375) a_particle.gotoAndStop("snow2"); else if (a_particle.frameLabel != particleFrameLabel) a_particle.gotoAndStop(particleFrameLabel); } else if (a_particle._y < -effectBuffer) { a_particle._y = _effectHeight + Math.random() * effectBuffer; } var onCompleteFn: Function = Delegate.create(this, function() {yLoop(a_particle)}); var duration: Number = Math.random()*2+1; // Linear.easeInOut Tween.LinearTween(a_particle, "_y", a_particle._y, a_particle._y+(Math.random()*7+30)*(a_particle._xscale/100)*3, duration, onCompleteFn); } } ================================================ FILE: src/ModConfigPanel/TextLoader.as ================================================ import gfx.core.UIComponent; import gfx.utils.Constraints; import gfx.controls.ScrollBar; import skyui.util.MarkupParser; import skyui.components.MaskedTextArea; import TextField.StyleSheet; class TextLoader extends UIComponent { /* PRIVATE VARIABLES */ private var _constraints: Constraints; private var _markup: Object; /* STAGE ELEMENTS */ public var titleText: TextField; public var maskedTextArea: MaskedTextArea; public var scrollBar: ScrollBar; /* INITIALIZATION */ function TextLoader() { super(); } public function configUI(): Void { super.configUI(); MarkupParser.registerParseCallback(this, "onDataParsed"); _constraints = new Constraints(this, false); _constraints.addElement(maskedTextArea, Constraints.ALL); _constraints.addElement(scrollBar, Constraints.TOP | Constraints.BOTTOM | Constraints.RIGHT); maskedTextArea.scrollBar = scrollBar; maskedTextArea.scrollBarAutoHide = false; maskedTextArea.styleSheet = MarkupParser.styleSheet; maskedTextArea.addEventListener("changeSection", this, "onChangeSection") } /* PRIVATE FUNCTIONS */ private function draw(): Void { super.draw(); if (_constraints != undefined) _constraints.update(_width, _height); load("demoText.txt"); } private function onDataParsed(a_event: Object): Void { _markup = a_event.markup; maskedTextArea.htmlText = _markup["main"].htmlText; } private function onChangeSection(a_event: Object): Void { var newSection: Object = _markup[a_event.args[0].toLowerCase()]; if (newSection != undefined) maskedTextArea.htmlText = newSection.htmlText; } /* PUBLIC FUNCTIONS */ public function load(a_path): Boolean { return MarkupParser.load(a_path); } } ================================================ FILE: src/PauseMenu/InputMappingArt.as ================================================ import Shared.GlobalFunc; import skyui.defines.ButtonArtNames; class InputMappingArt extends MovieClip { /* PRIVATE VARIABLES */ private var _keyCodes: Array; /* STAGE ELEMENTS */ public var background: MovieClip; public var textField: TextField; /* PROPERTIES */ public function set hiddenBackground(a_flag: Boolean) { background._visible = !a_flag; } public function get hiddenBackground(): Boolean { return background._visible; } public function get width(): Number { return background._width; } public function set width(a_value: Number) { background._width = a_value; } public var buttonArt: Array; /* INITIALIZATION */ function MappedButton() { super(); GlobalFunc.MaintainTextFormat(); } public function onLoad(): Void { buttonArt = []; _keyCodes = []; textField.textAutoSize = "shrink"; textField._visible = false; background._visible = false; for (var i=0; this["buttonArt" + i] != undefined; i++) { this["buttonArt" + i]._visible = false; buttonArt.push(this["buttonArt" + i]); } } /* PUBLIC FUNCTIONS */ public function setButtonName(a_buttonName: String): Void { textField._visible = false; var keyCodes = ButtonArtNames.lookup(a_buttonName); if (keyCodes instanceof Array) _keyCodes = keyCodes; else _keyCodes = [keyCodes]; if (_keyCodes[0] == null) { for (var i: Number = 0; i < buttonArt.length; i++) buttonArt[i]._visible = false; textField.SetText(a_buttonName); textField._width = textField.getLineMetrics(0).width; textField._visible = true; background._width = textField._width; return; } var xOffset: Number = 0; for (var i: Number = 0; i < buttonArt.length; i++) { var icon: MovieClip = buttonArt[i]; if (_keyCodes[i] > 0) { icon._visible = true; icon.gotoAndStop(_keyCodes[i]); icon._x = xOffset; icon._y = 0; //(0 - icon._height) / 2; // Center it xOffset += icon._width; } else { icon._visible = false; } } background._width = xOffset; } } ================================================ FILE: src/PauseMenu/InputMappingList.as ================================================ class InputMappingList extends Shared.BSScrollingList { var GetClipByIndex; function InputMappingList() { super(); } function GetEntryHeight(aiEntryIndex: Number): Number { var entry: MovieClip = GetClipByIndex(0); return entry._height; } function SetEntry(aEntryClip: MovieClip, aEntryObject: Object): Void { var buttonArt: InputMappingArt = aEntryClip.buttonArt; var label: MovieClip = aEntryClip.textField; buttonArt._alpha = aEntryObject == selectedEntry ? 100 : 30; label._alpha = aEntryObject == selectedEntry ? 100 : 30; label.textAutoSize = "shrink"; buttonArt.setButtonName(aEntryObject.buttonName); label.SetText("$" + aEntryObject.text); } } ================================================ FILE: src/PauseMenu/JournalBottomBar.as ================================================ import Components.CrossPlatformButtons; import Components.Meter; import gfx.io.GameDelegate; import skyui.components.ButtonPanel; import skyui.defines.Input; class JournalBottomBar extends MovieClip { /*var Button1_mc: CrossPlatformButtons; var Button2_mc: CrossPlatformButtons;*/ var ButtonRect: MovieClip; var DateText: TextField; var LevelMeter_mc: Meter; public var LevelMeterRect: MovieClip; public var buttonPanel: ButtonPanel; public var deleteButton: MovieClip; public function JournalBottomBar() { super(); } public function InitBar(): Void { LevelMeter_mc = new Meter(LevelMeterRect.LevelProgressBar); GameDelegate.call("RequestPlayerInfo", [], this, "SetPlayerInfo"); } public function SetPlayerInfo(): Void { DateText.SetText(arguments[0]); LevelMeterRect.LevelNumberLabel.textAutoSize = "shrink"; LevelMeterRect.LevelNumberLabel.SetText(arguments[1]); LevelMeter_mc.SetPercent(arguments[2]); } public function setPlatform(a_platform: Number, a_bPS3Switch: Boolean): Void { buttonPanel.setPlatform(a_platform, a_bPS3Switch); } } ================================================ FILE: src/PauseMenu/JournalSaveLoadList.as ================================================ import gfx.controls.ScrollBar; import gfx.io.GameDelegate; class JournalSaveLoadList extends Shared.BSScrollingList { var ListScrollbar: ScrollBar; var iMaxScrollPosition: Number; function JournalSaveLoadList() { super(); } function SetEntry(aEntryClip: MovieClip, aEntryObject: Object): Void { super.SetEntry(aEntryClip, aEntryObject); if (aEntryObject.fileNum == undefined) { aEntryClip.SaveNumber.SetText(" "); } else if (aEntryObject.fileNum < 10) { aEntryClip.SaveNumber.SetText("00" + aEntryObject.fileNum); } else if (aEntryObject.fileNum < 100) { aEntryClip.SaveNumber.SetText("0" + aEntryObject.fileNum); } else { aEntryClip.SaveNumber.SetText(aEntryObject.fileNum); } if (ListScrollbar != undefined) { aEntryClip._x = iMaxScrollPosition <= 0 ? 0 : 25; } } function moveSelectionUp(): Void { super.moveSelectionUp(); GameDelegate.call("PlaySound", ["UIMenuFocus"]); } function moveSelectionDown(): Void { super.moveSelectionDown(); GameDelegate.call("PlaySound", ["UIMenuFocus"]); } } ================================================ FILE: src/PauseMenu/ObjectiveScrollingList.as ================================================ class ObjectiveScrollingList extends Shared.BSScrollingList { var SetEntryText: Function; function ObjectiveScrollingList() { super(); } function SetEntry(aEntryClip: MovieClip, aEntryObject: Object): Void { if (aEntryObject.text == undefined) { aEntryClip.gotoAndStop("None"); } else { var slabelName: String = ""; if (aEntryObject.active) { slabelName = slabelName + "Active"; } else if (aEntryObject.completed) { slabelName = slabelName + "Completed"; } else if (aEntryObject.failed) { slabelName = slabelName + "Failed"; } else { slabelName = slabelName + "Normal"; } if (aEntryObject == selectedEntry) { slabelName = slabelName + "Selected"; } aEntryClip.gotoAndStop(slabelName); } SetEntryText(aEntryClip, aEntryObject); } } ================================================ FILE: src/PauseMenu/OptionsList.as ================================================ class OptionsList extends Shared.BSScrollingList { var EntriesA: Array; var GetClipByIndex: Function; var bAllowValueOverwrite: Boolean; function OptionsList() { super(); bAllowValueOverwrite = false; } function GetEntryHeight(aiEntryIndex: Number): Number { var entry: MovieClip = GetClipByIndex(0); return entry._height; } function onValueChange(aiItemIndex: Number, aiNewValue: Number): Void { if (aiItemIndex != undefined) { EntriesA[aiItemIndex].value = aiNewValue; } } function SetEntry(aEntryClip: MovieClip, aEntryObject: Object): Void { if (aEntryClip != undefined) { aEntryClip.selected = aEntryObject == selectedEntry; if (bAllowValueOverwrite || aEntryClip.ID != aEntryObject.ID) { aEntryClip.movieType = aEntryObject.movieType; if (aEntryObject.options != undefined) { aEntryClip.SetOptionStepperOptions(aEntryObject.options); } aEntryClip.ID = aEntryObject.ID; aEntryClip.value = aEntryObject.value; aEntryClip.requiresRestart = aEntryObject.requiresRestart; aEntryClip.text = aEntryObject.text; } } } } ================================================ FILE: src/PauseMenu/QuestCenteredList.as ================================================ class QuestCenteredList extends Shared.CenteredScrollingList { function QuestCenteredList() { super(); } function SetEntryText(aEntryClip: MovieClip, aEntryObject: Object): Void { super.SetEntryText(aEntryClip, aEntryObject); if (aEntryClip.textField != undefined) { aEntryClip.textField.textColor = aEntryObject.completed == true ? 0x606060 : 0xFFFFFF; } if (aEntryClip.EquipIcon != undefined) { if (aEntryObject != undefined && aEntryObject.active) { aEntryClip.EquipIcon.gotoAndStop("Equipped"); return; } aEntryClip.EquipIcon.gotoAndStop("None"); } } } ================================================ FILE: src/PauseMenu/Quest_Journal.as ================================================ import gfx.controls.RadioButton; import gfx.controls.ButtonGroup; import gfx.io.GameDelegate; import gfx.ui.InputDetails; import Shared.GlobalFunc; import gfx.ui.NavigationCode; import gfx.managers.FocusHandler; import skyui.components.ButtonPanel; import skyui.defines.ButtonArtNames; import skyui.util.Debug; import skyui.VRInput; import skyui.util.GlobalFunctions; class Quest_Journal extends MovieClip { #include "../version.as" var bTabsDisabled: Boolean; var iCurrentTab: Number; var BottomBar: MovieClip; var BottomBar_mc: MovieClip; var TextPanel: MovieClip; var showInputReadout: Boolean; var PageArray: Array; public var previousTabButton: MovieClip; public var nextTabButton: MovieClip; var TopmostPage: MovieClip; var QuestsFader: MovieClip; var StatsFader: MovieClip; var SystemFader: MovieClip; var QuestsTab: RadioButton; var StatsTab: RadioButton; var SystemTab: RadioButton; var TabButtonGroup: ButtonGroup; var ConfigPanel: MovieClip; var _VRInput: VRInput; public static var PAGE_QUEST: Number = 0; public static var PAGE_STATS: Number = 1; public static var PAGE_SYSTEM: Number = 2; public static var QUESTS_TAB: Number = 0; public static var STATS_TAB: Number = 1; public static var SETTINGS_TAB: Number = 2; function Quest_Journal() { super(); BottomBar_mc = BottomBar; PageArray = new Array(QuestsFader.Page_mc, StatsFader.Page_mc, SystemFader.Page_mc); TopmostPage = QuestsFader; bTabsDisabled = false; iCurrentTab = Quest_Journal.PAGE_QUEST; } function InitExtensions() { GlobalFunc.SetLockFunction(); ConfigPanel = _root.ConfigPanelFader.configPanel; QuestsTab.disableFocus = true; StatsTab.disableFocus = true; SystemTab.disableFocus = true; TabButtonGroup = ButtonGroup(QuestsTab.group); TabButtonGroup.addEventListener("itemClick", this, "onTabClick"); TabButtonGroup.addEventListener("change", this, "onTabChange"); GameDelegate.addCallBack("RestoreSavedSettings", this, "RestoreSavedSettings"); GameDelegate.addCallBack("onRightStickInput", this, "onRightStickInput"); GameDelegate.addCallBack("HideMenu", this, "DoHideMenu"); GameDelegate.addCallBack("ShowMenu", this, "DoShowMenu"); GameDelegate.addCallBack("StartCloseMenu", this, "CloseMenu"); GameDelegate.addCallBack("OnShow", this, "OnShow"); GameDelegate.call("ShouldShowMod", [], this, "SetShowMod"); BottomBar_mc.InitBar(); ConfigPanel.initExtensions(); } function OnShow(): Void { var vrtools = skse["plugins"]["vrinput"]; if(vrtools != undefined) { //vrtools.ShutoffButtonEventsToGame(true); } else { Debug.log("SkyrimVRTools plugin not available"); } showInputReadout = skse["plugins"]["skyui"].IniGetBool("Settings/showInputReadout"); if(!showInputReadout) TextPanel._visible = false; else { // For whatever reason, Scaleform API requires an object to be somewhere // on the stage to be able to send inputs via a registered callback. // By adding it here, VRInput should start receiving and button updates // and start pumping out button events. _VRInput = VRInput.instance; VRInput.instance.setup(); } QuestsTab.disableFocus = true; StatsTab.disableFocus = true; SystemTab.disableFocus = true; QuestsTab.disabled = false; StatsTab.disabled = false; SystemTab.disabled = false; BottomBar_mc.InitBar(); var pageCursor = 0; while(pageCursor <= Quest_Journal.PAGE_SYSTEM) { var page = PageArray[pageCursor]; Shared.Macros.BSASSERT(page != null && page != undefined,"Unable to open page " + pageCursor); Shared.Macros.BSASSERT(page.OnShow != null && page.OnShow != undefined,"page does not have OnShow function"); page.OnShow(); if(pageCursor == iCurrentTab) { page.startPage(); } pageCursor = pageCursor + 1; } if(TopmostPage != null && TopmostPage != undefined) { TopmostPage.gotoAndPlay("fadeIn"); } } function SetShowMod(): Void { PageArray[Quest_Journal.PAGE_SYSTEM].SetShowMod(arguments[0]); } function RestoreSavedSettings(aiSavedTab: Number, abTabsDisabled: Boolean): Void { // For some reason, the game will ask for the tab to be set to 0 (PAGE_QUEST) // *every* time after 'OnShow' is called. // This means the player will always be sent to the Quest page when the // quest_journal menu is brought up. // Strangely, the vanilla VR interface does not suffer from this problem. if(aiSavedTab != 0) iCurrentTab = Math.min(Math.max(aiSavedTab, 0), TabButtonGroup.length - 1); bTabsDisabled = abTabsDisabled; if (bTabsDisabled) { iCurrentTab = TabButtonGroup.length - 1; QuestsTab.disabled = true; StatsTab.disabled = true; } SwitchPageToFront(iCurrentTab, true); TabButtonGroup.setSelectedButton(TabButtonGroup.getButtonAt(iCurrentTab)); } function SwitchPageToFront(aiTab: Number, abForceFade: Boolean): Void { if (TopmostPage != PageArray[iCurrentTab]._parent) { TopmostPage.gotoAndStop("hide"); PageArray[iCurrentTab]._parent.swapDepths(TopmostPage); TopmostPage = PageArray[iCurrentTab]._parent; } TopmostPage.gotoAndPlay(abForceFade ? "ForceFade" : "fadeIn"); BottomBar_mc.LevelMeterRect._visible = iCurrentTab != 0; } function classname():String { return "class Quest_Journal" } function handleVRButtonUpdate(update) { if(!showInputReadout) return; //Debug.dump("update", update); var stateString = VRInput.instance.controllerStateString(update); Debug.log("stateString: " + stateString); if(stateString.length != 0) { TextPanel.TextArea.SetText(stateString); } else { TextPanel.TextArea.SetText(update.timestamp.toString()); } } function handleInput(details: InputDetails, pathToFocus: Array): Boolean { var bHandledInput: Boolean = false; if (pathToFocus != undefined && pathToFocus.length > 0) { bHandledInput = pathToFocus[0].handleInput(details, pathToFocus.slice(1)); } if (!bHandledInput && GlobalFunc.IsKeyPressed(details, false)) { var triggerLeft = NavigationCode.GAMEPAD_L2; var triggerRight = NavigationCode.GAMEPAD_R2; if(PageArray[Quest_Journal.PAGE_SYSTEM].GetIsRemoteDevice()) { triggerLeft = NavigationCode.GAMEPAD_L1; triggerRight = NavigationCode.GAMEPAD_R1; } if (details.navEquivalent === NavigationCode.TAB) { CloseMenu(); } else if (details.navEquivalent === triggerLeft) { if (!bTabsDisabled) { PageArray[iCurrentTab].endPage(); iCurrentTab = iCurrentTab + (details.navEquivalent == triggerLeft ? -1 : 1); if (iCurrentTab == -1) { iCurrentTab = TabButtonGroup.length - 1; } if (iCurrentTab == TabButtonGroup.length) { iCurrentTab = 0; } SwitchPageToFront(iCurrentTab, false); TabButtonGroup.setSelectedButton(TabButtonGroup.getButtonAt(iCurrentTab)); } } else if (details.navEquivalent === triggerRight) { if (!bTabsDisabled) { PageArray[iCurrentTab].endPage(); iCurrentTab = iCurrentTab + (details.navEquivalent == triggerLeft ? -1 : 1); if (iCurrentTab == -1) { iCurrentTab = TabButtonGroup.length - 1; } if (iCurrentTab == TabButtonGroup.length) { iCurrentTab = 0; } SwitchPageToFront(iCurrentTab, false); TabButtonGroup.setSelectedButton(TabButtonGroup.getButtonAt(iCurrentTab)); } } } return true; } function CloseMenu(abForceClose: Boolean): Void { //Debug.log(">>> Quest_Journal::CloseMenu"); var vrtools = skse["plugins"]["vrinput"]; if(vrtools != undefined) { //vrtools.ShutoffButtonEventsToGame(false); } VRInput.instance.teardown(); if (abForceClose != true) { GameDelegate.call("PlaySound", ["UIJournalClose"]); } GameDelegate.call("CloseMenu", [iCurrentTab, QuestsFader.Page_mc.selectedQuestID, QuestsFader.Page_mc.selectedQuestInstance]); //Debug.log("<<< Quest_Journal::CloseMenu"); } function onTabClick(event: Object): Void { if (bTabsDisabled) { return; } var iOldTab: Number = iCurrentTab; if (event.item == QuestsTab) { iCurrentTab = 0; } else if (event.item == StatsTab) { iCurrentTab = 1; } else if (event.item == SystemTab) { iCurrentTab = 2; } if (iOldTab != iCurrentTab) { PageArray[iOldTab].endPage(); // Moved SwitchPageToFront to within this statement // if you click the same tab it won't reload it SwitchPageToFront(iCurrentTab, false); // Bugfix for vanilla } } function onTabChange(event: Object): Void { event.item.gotoAndPlay("selecting"); PageArray[iCurrentTab].startPage(); GameDelegate.call("PlaySound", ["UIJournalTabsSD"]); } function onRightStickInput(afX: Number, afY: Number): Void { if (PageArray[iCurrentTab].onRightStickInput != undefined) { PageArray[iCurrentTab].onRightStickInput(afX, afY); } } function SetPlatform(aiPlatform: Number, abPS3Switch: Boolean): Void { VRInput.instance.updatePlatform(aiPlatform); // Not sure if these are the correct mapping for next/prev tab var nextTabArt = ButtonArtNames.lookup(skyui.util.Input.pickButtonArt(aiPlatform, {ViveArt:"radial_Either_Right", MoveArt:"PS3_Y",OculusArt:"OCC_B", WindowsMRArt:"radial_Either_Right"})); var prevTabArt = ButtonArtNames.lookup(skyui.util.Input.pickButtonArt(aiPlatform, {ViveArt:"radial_Either_Left", MoveArt:"PS3_X", OculusArt:"OCC_Y", WindowsMRArt:"radial_Either_Left"})); // If we can't find the right button art by name, provide some defaults if (nextTabArt == undefined) nextTabArt = 281; // RT if (prevTabArt == undefined) prevTabArt = 280; // LT if (aiPlatform == 0) { previousTabButton._visible = nextTabButton._visible = false; } else { previousTabButton._visible = nextTabButton._visible = true; previousTabButton.gotoAndStop(prevTabArt); nextTabButton.gotoAndStop(nextTabArt); } for (var i: String in PageArray) { if (PageArray[i].SetPlatform != undefined) { PageArray[i].SetPlatform(aiPlatform, abPS3Switch); } } BottomBar_mc.setPlatform(aiPlatform, abPS3Switch); ConfigPanel.setPlatform(aiPlatform, abPS3Switch); } function DoHideMenu(): Void { _parent.gotoAndPlay("fadeOut"); } function DoShowMenu(): Void { _parent.gotoAndPlay("fadeIn"); } function DisableTabs(abEnable: Boolean): Void { QuestsTab.disabled = abEnable; StatsTab.disabled = abEnable; SystemTab.disabled = abEnable; } function ConfigPanelOpen(): Void { DisableTabs(true); SystemFader.Page_mc.endPage(); DoHideMenu(); _root.ConfigPanelFader.swapDepths(_root.QuestJournalFader); FocusHandler.instance.setFocus(ConfigPanel, 0); ConfigPanel.startPage(); } function ConfigPanelClose(): Void { ConfigPanel.endPage(); _root.QuestJournalFader.swapDepths(_root.ConfigPanelFader); FocusHandler.instance.setFocus(this, 0); DoShowMenu(); SystemFader.Page_mc.startPage(); DisableTabs(false); } } ================================================ FILE: src/PauseMenu/QuestsPage.as ================================================ import Components.CrossPlatformButtons; import gfx.io.GameDelegate; import gfx.ui.InputDetails; import Shared.GlobalFunc; import gfx.ui.NavigationCode; import gfx.managers.FocusHandler; class QuestsPage extends MovieClip { var DescriptionText: TextField; var Divider: MovieClip; var NoQuestsText: TextField; var ObjectiveList: Object; var ObjectivesHeader: MovieClip; var QuestTitleText: TextField; var TitleList: MovieClip; var TitleList_mc: MovieClip; var bAllowShowOnMap: Boolean; var bHasMiscQuests: Boolean; var bUpdated: Boolean; var iPlatform: Number; var objectiveList: Object; var objectivesHeader: MovieClip; var questDescriptionText: TextField; var questTitleEndpieces: MovieClip; var questTitleText: TextField; private var _showOnMapButton: MovieClip; private var _toggleActiveButton: MovieClip; private var _bottomBar: MovieClip; private var _toggleActiveControls: Object; private var _showOnMapControls: Object; private var _deleteControls: Object; function QuestsPage() { super(); TitleList = TitleList_mc.List_mc; DescriptionText = questDescriptionText; QuestTitleText = questTitleText; ObjectiveList = objectiveList; ObjectivesHeader = objectivesHeader; bHasMiscQuests = false; bUpdated = false; _bottomBar = _parent._parent.BottomBar_mc; } function OnShow() { bUpdated = false; bHasMiscQuests = false; TitleList.entryList = new Array(); TitleList.InvalidateData(); } function onLoad() { QuestTitleText.SetText(" "); DescriptionText.SetText(" "); DescriptionText.verticalAutoSize = "top"; QuestTitleText.textAutoSize = "shrink"; TitleList.addEventListener("itemPress", this, "onTitleListSelect"); TitleList.addEventListener("listMovedUp", this, "onTitleListMoveUp"); TitleList.addEventListener("listMovedDown", this, "onTitleListMoveDown"); TitleList.addEventListener("selectionChange", this, "onTitleListMouseSelectionChange"); TitleList.disableInput = true; // Bugfix for vanilla ObjectiveList.addEventListener("itemPress", this, "onObjectiveListSelect"); ObjectiveList.addEventListener("selectionChange", this, "onObjectiveListHighlight"); } function startPage() { TitleList.disableInput = false; // Bugfix for vanilla if (!bUpdated) { //ShowOnMapButton = _parent._parent._bottomBar.Button2_mc; GameDelegate.call("RequestQuestsData", [TitleList], this, "onQuestsDataComplete"); //_toggleActiveButton = _parent._parent._bottomBar.Button1_mc; bUpdated = true; } _bottomBar.buttonPanel.clearButtons(); _toggleActiveButton = _bottomBar.buttonPanel.addButton({text: "$Toggle Active", controls: _toggleActiveControls}); if (bAllowShowOnMap) _showOnMapButton = _bottomBar.buttonPanel.addButton({text: "$Show on Map", controls: _showOnMapControls}); _bottomBar.buttonPanel.updateButtons(true); switchFocusToTitles(); } function endPage() { _showOnMapButton._alpha = 100; _toggleActiveButton._alpha = 100; _bottomBar.buttonPanel.clearButtons(); TitleList.disableInput = true; // Bugfix for vanilla } function get selectedQuestID(): Number { return TitleList.entryList.length <= 0 ? undefined : TitleList.centeredEntry.formID; } function get selectedQuestInstance(): Number { return TitleList.entryList.length <= 0 ? undefined : TitleList.centeredEntry.instance; } function handleInput(details: InputDetails, pathToFocus: Array): Boolean { var bhandledInput: Boolean = false; if (GlobalFunc.IsKeyPressed(details)) { if ((details.navEquivalent == NavigationCode.GAMEPAD_X || details.code == 77) && bAllowShowOnMap) { onShowMap(); bhandledInput = true; } else if (TitleList.entryList.length > 0) { if (details.navEquivalent == NavigationCode.LEFT && FocusHandler.instance.getFocus(0) != TitleList) { switchFocusToTitles(); bhandledInput = true; } else if (details.navEquivalent == NavigationCode.RIGHT && FocusHandler.instance.getFocus(0) != ObjectiveList) { switchFocusToObjectives(); bhandledInput = true; } } } if (!bhandledInput && pathToFocus != undefined && pathToFocus.length > 0) { bhandledInput = pathToFocus[0].handleInput(details, pathToFocus.slice(1)); } return bhandledInput; } function onShowMap() { var quest: Object = undefined; if (ObjectiveList.selectedEntry != undefined && ObjectiveList.selectedEntry.questTargetID != undefined) { quest = ObjectiveList.selectedEntry; } else { quest = ObjectiveList.entryList[0]; } if (quest != undefined && quest.questTargetID != undefined) { _parent._parent.CloseMenu(); GameDelegate.call("ShowTargetOnMap", [quest.questTargetID]); } else { GameDelegate.call("PlaySound", ["UIMenuCancel"]); } } private function isViewingMiscObjectives(): Boolean { return bHasMiscQuests && TitleList.selectedEntry.formID == 0; } function onTitleListSelect(): Void { if (TitleList.selectedEntry != undefined && !TitleList.selectedEntry.completed) { if (!isViewingMiscObjectives()) { GameDelegate.call("ToggleQuestActiveStatus", [TitleList.selectedEntry.formID, TitleList.selectedEntry.instance], this, "onToggleQuestActive"); return; } TitleList.selectedEntry.active = !TitleList.selectedEntry.active; GameDelegate.call("ToggleShowMiscObjectives", [TitleList.selectedEntry.active]); TitleList.UpdateList(); } } function onObjectiveListSelect(): Void { if (isViewingMiscObjectives()) { GameDelegate.call("ToggleQuestActiveStatus", [ObjectiveList.selectedEntry.formID, ObjectiveList.selectedEntry.instance], this, "onToggleQuestActive"); } } private function switchFocusToTitles(): Void { FocusHandler.instance.setFocus(TitleList, 0); Divider.gotoAndStop("Right"); _toggleActiveButton._alpha = 100; ObjectiveList.selectedIndex = -1; if (iPlatform != Shared.Platforms.CONTROLLER_PC && iPlatform != Shared.Platforms.CONTROLLER_VIVE && iPlatform != Shared.Platforms.CONTROLLER_OCULUS && iPlatform != Shared.Platforms.CONTROLLER_WINDOWS_MR) { ObjectiveList.disableSelection = true; } updateShowOnMapButtonAlpha(0); } private function switchFocusToObjectives(): Void { FocusHandler.instance.setFocus(ObjectiveList, 0); Divider.gotoAndStop("Left"); _toggleActiveButton._alpha = isViewingMiscObjectives() ? 100 : 50; if (iPlatform != Shared.Platforms.CONTROLLER_PC && iPlatform != Shared.Platforms.CONTROLLER_VIVE && iPlatform != Shared.Platforms.CONTROLLER_OCULUS && iPlatform != Shared.Platforms.CONTROLLER_WINDOWS_MR) { ObjectiveList.disableSelection = false; } ObjectiveList.selectedIndex = 0; updateShowOnMapButtonAlpha(0); } private function onObjectiveListHighlight(event): Void { updateShowOnMapButtonAlpha(event.index); } private function updateShowOnMapButtonAlpha(a_entryIdx: Number): Void { var alpha: Number = 50; if (bAllowShowOnMap && (a_entryIdx >= 0 && ObjectiveList.entryList[a_entryIdx].questTargetID != undefined) || (ObjectiveList.entryList.length > 0 && ObjectiveList.entryList[0].questTargetID != undefined)) { alpha = 100; } _toggleActiveButton._alpha = ((!TitleList.selectedEntry.completed) ? 100 : 50); _showOnMapButton._alpha = alpha; } private function onToggleQuestActive(a_bnewActiveStatus: Number): Void { if (isViewingMiscObjectives()) { var iformID: Number = ObjectiveList.selectedEntry.formID; var iinstance: Number = ObjectiveList.selectedEntry.instance; for (var i: String in ObjectiveList.entryList) { if (ObjectiveList.entryList[i].formID == iformID && ObjectiveList.entryList[i].instance == iinstance) { ObjectiveList.entryList[i].active = a_bnewActiveStatus; } } ObjectiveList.UpdateList(); } else { TitleList.selectedEntry.active = a_bnewActiveStatus; TitleList.UpdateList(); } if (a_bnewActiveStatus) { GameDelegate.call("PlaySound", ["UIQuestActive"]); return; } GameDelegate.call("PlaySound", ["UIQuestInactive"]); } private function onQuestsDataComplete(auiSavedFormID: Number, auiSavedInstance: Number, abAddMiscQuest: Boolean, abMiscQuestActive: Boolean, abAllowShowOnMap: Boolean): Void { bAllowShowOnMap = abAllowShowOnMap; if (abAddMiscQuest) { TitleList.entryList.push({text: "$MISCELLANEOUS", formID: 0, instance: 0, active: abMiscQuestActive, completed: false, type: 0}); bHasMiscQuests = true; } var itimeCompleted: Number = undefined; var bCompleted = false; var bUncompleted = false; for (var i: Number = 0; i < TitleList.entryList.length; i++) { if (TitleList.entryList[i].formID == 0) { // Is a misc quest TitleList.entryList[i].timeIndex = Number.MAX_VALUE; } else { TitleList.entryList[i].timeIndex = i; } if (TitleList.entryList[i].completed) { if (itimeCompleted == undefined) { itimeCompleted = TitleList.entryList[i].timeIndex - 0.5; } bCompleted = true; } else { bUncompleted = true; } } if (itimeCompleted != undefined && bCompleted && bUncompleted) { // i.e. at least one completed and one uncompleted quest in the list TitleList.entryList.push({divider: true, completed: true, timeIndex: itimeCompleted}); } TitleList.entryList.sort(completedQuestSort); var isavedIndex: Number = 0; for (var i: Number = 0; i < TitleList.entryList.length; i++) { if (TitleList.entryList[i].text != undefined) { TitleList.entryList[i].text = TitleList.entryList[i].text.toUpperCase(); } if (TitleList.entryList[i].formID == auiSavedFormID && TitleList.entryList[i].instance == auiSavedInstance) { isavedIndex = i; } } TitleList.InvalidateData(); TitleList.RestoreScrollPosition(isavedIndex, true); TitleList.UpdateList(); onQuestHighlight(); } function completedQuestSort(aObj1: Object, aObj2: Object): Number { if (!aObj1.completed && aObj2.completed) { return -1; } if (aObj1.completed && !aObj2.completed) { return 1; } if (aObj1.timeIndex < aObj2.timeIndex) { return -1; } if (aObj1.timeIndex > aObj2.timeIndex) { return 1; } return 0; } function onQuestHighlight(): Void { if (TitleList.entryList.length > 0) { var aCategories: Array = ["Misc", "Main", "MagesGuild", "ThievesGuild", "DarkBrotherhood", "Companion", "Favor", "Daedric", "Misc", "CivilWar", "DLC01", "DLC02"]; QuestTitleText.SetText(TitleList.selectedEntry.text); if (TitleList.selectedEntry.objectives == undefined) { GameDelegate.call("RequestObjectivesData", []); } ObjectiveList.entryList = TitleList.selectedEntry.objectives; SetDescriptionText(); questTitleEndpieces.gotoAndStop(aCategories[TitleList.selectedEntry.type]); questTitleEndpieces._visible = true; ObjectivesHeader._visible = !isViewingMiscObjectives(); ObjectiveList.selectedIndex = -1; ObjectiveList.scrollPosition = 0; if (iPlatform != Shared.Platforms.CONTROLLER_PC && iPlatform != Shared.Platforms.CONTROLLER_VIVE && iPlatform != Shared.Platforms.CONTROLLER_OCULUS && iPlatform != Shared.Platforms.CONTROLLER_WINDOWS_MR) { ObjectiveList.disableSelection = true; } updateShowOnMapButtonAlpha(0); } else { NoQuestsText.SetText("No Active Quests"); DescriptionText.SetText(" "); QuestTitleText.SetText(" "); ObjectiveList.ClearList(); questTitleEndpieces._visible = false; ObjectivesHeader._visible = false; } UpdateButtonVisiblity(); ObjectiveList.InvalidateData(); } function UpdateButtonVisiblity(): Void { var bActive = TitleList.entryList.length > 0 && TitleList.selectedEntry != null; _toggleActiveButton._visible = bActive && !TitleList.selectedEntry.completed; _showOnMapButton._visible = bActive && !TitleList.selectedEntry.completed && bAllowShowOnMap; } function SetDescriptionText(): Void { var iHeaderyOffset: Number = 25; var iObjectiveyOffset: Number = 10; var iObjectiveBorderMaxy: Number = 470; var iObjectiveBorderMiny: Number = 40; DescriptionText.SetText(TitleList.selectedEntry.description); var oCharBoundaries: Object = DescriptionText.getCharBoundaries(DescriptionText.getLineOffset(DescriptionText.numLines - 1)); ObjectivesHeader._y = DescriptionText._y + oCharBoundaries.bottom + iHeaderyOffset; if (isViewingMiscObjectives()) { ObjectiveList._y = DescriptionText._y; } else { ObjectiveList._y = ObjectivesHeader._y + ObjectivesHeader._height + iObjectiveyOffset; } ObjectiveList.border._height = Math.max(iObjectiveBorderMaxy - ObjectiveList._y, iObjectiveBorderMiny); ObjectiveList.scrollbar.height = ObjectiveList.border._height - 20; } function onTitleListMoveUp(event: Object): Void { onQuestHighlight(); GameDelegate.call("PlaySound", ["UIMenuFocus"]); if (event.scrollChanged == true) { TitleList._parent.gotoAndPlay("moveUp"); } } function onTitleListMoveDown(event: Object): Void { onQuestHighlight(); GameDelegate.call("PlaySound", ["UIMenuFocus"]); if (event.scrollChanged == true) { TitleList._parent.gotoAndPlay("moveDown"); } } function onTitleListMouseSelectionChange(event: Object): Void { if (event.keyboardOrMouse == 0 && event.index != -1) { onQuestHighlight(); GameDelegate.call("PlaySound", ["UIMenuFocus"]); } } function onRightStickInput(afX: Number, afY: Number): Void { if (afY < 0) { ObjectiveList.moveSelectionDown(); return; } ObjectiveList.moveSelectionUp(); } function SetPlatform(a_platform: Number, a_bPS3Switch: Boolean): Void { _toggleActiveControls = skyui.util.Input.pickControls(a_platform, {PCArt:"Enter",XBoxArt:"360_A",PS3Art:"PS3_A",ViveArt:"trigger",MoveArt:"PS3_MOVE",OculusArt:"trigger",WindowsMRArt:"trigger"}); _showOnMapControls = skyui.util.Input.pickControls(a_platform, {PCArt:"M",XBoxArt:"360_X",PS3Art:"PS3_X",ViveArt:"radial_Either_Up",MoveArt:"PS3_A",OculusArt:"OCC_A",WindowsMRArt:"radial_Either_Up"}); iPlatform = a_platform; TitleList.SetPlatform(a_platform, a_bPS3Switch); ObjectiveList.SetPlatform(a_platform, a_bPS3Switch); } } ================================================ FILE: src/PauseMenu/SettingsOptionItem.as ================================================ import gfx.controls.OptionStepper; import gfx.controls.ScrollBar; import Shared.GlobalFunc; import gfx.ui.InputDetails; import gfx.ui.NavigationCode; import gfx.io.GameDelegate; class SettingsOptionItem extends MovieClip { var CheckBox_mc: MovieClip; var OptionStepper_mc: MovieClip; var ScrollBar_mc: MovieClip; var bSendChangeEvent: Boolean; var checkBox: MovieClip; var iID: Number; var iMovieType: Number; var optionStepper: OptionStepper; var scrollBar: ScrollBar; var textField: TextField; var pScope = null; var sFunction: String = ""; var bRequiresRestart: Boolean = false; function SettingsOptionItem() { super(); Mouse.addListener(this); ScrollBar_mc = scrollBar; OptionStepper_mc = optionStepper; CheckBox_mc = checkBox; bSendChangeEvent = true; textField.textAutoSize = "shrink"; } function SetOnChangeCallback(apScope, asFunction) { pScope = apScope; sFunction = asFunction; } function onLoad(): Void { ScrollBar_mc.setScrollProperties(0.7, 0, 20); ScrollBar_mc.addEventListener("scroll", this, "onScroll"); OptionStepper_mc.addEventListener("change", this, "onStepperChange"); bSendChangeEvent = true; } function get movieType(): Number { return iMovieType; } function set movieType(aiMovieType: Number): Void { iMovieType = aiMovieType; ScrollBar_mc.disabled = true; ScrollBar_mc.visible = false; OptionStepper_mc.disabled = true; OptionStepper_mc.visible = false; CheckBox_mc._visible = false; switch (iMovieType) { case 0: ScrollBar_mc.disabled = false; ScrollBar_mc.visible = true; break; case 1: OptionStepper_mc.disabled = false; OptionStepper_mc.visible = true; break; case 2: CheckBox_mc._visible = true; break; } } function get ID(): Number { return iID; } function set ID(aiNewValue: Number): Void { iID = aiNewValue; } function get value(): Number { var iFrameValue: Number = undefined; switch (iMovieType) { case 0: iFrameValue = ScrollBar_mc.position / 20; break; case 1: iFrameValue = OptionStepper_mc.selectedIndex; break; case 2: iFrameValue = CheckBox_mc._currentframe - 1; break; } return iFrameValue; } function set value(afNewValue: Number): Void { switch (iMovieType) { case 0: bSendChangeEvent = false; ScrollBar_mc.position = afNewValue * 20; bSendChangeEvent = true; break; case 1: bSendChangeEvent = false; OptionStepper_mc.selectedIndex = afNewValue; bSendChangeEvent = true; break; case 2: CheckBox_mc.gotoAndStop(afNewValue + 1); break; } } function get text(): String { return textField.text; } function set text(astrNew: String): Void { textField.SetText(astrNew); } function get selected(): Boolean { return textField._alpha == 100; } function set selected(abSelected: Boolean): Void { textField._alpha = abSelected ? 100 : 30; ScrollBar_mc._alpha = abSelected ? 100 : 30; OptionStepper_mc._alpha = abSelected ? 100 : 30; CheckBox_mc._alpha = abSelected ? 100 : 30; } function get requiresRestart() { return bRequiresRestart; } function set requiresRestart(abRequiresRestart) { bRequiresRestart = abRequiresRestart; } function handleInput(details: InputDetails, pathToFocus: Array): Boolean { var bhandledInput: Boolean = false; if (GlobalFunc.IsKeyPressed(details)) { switch (iMovieType) { case 0: if (details.navEquivalent == NavigationCode.LEFT) { ScrollBar_mc.position = ScrollBar_mc.position - 1; bhandledInput = true; } else if (details.navEquivalent == NavigationCode.RIGHT) { ScrollBar_mc.position = ScrollBar_mc.position + 1; bhandledInput = true; } break; case 1: if (details.navEquivalent == NavigationCode.LEFT || details.navEquivalent == NavigationCode.RIGHT) { bhandledInput = OptionStepper_mc.handleInput(details, pathToFocus); } else if (details.navEquivalent == NavigationCode.ENTER) { OptionStepper_mc.ToggleNextOrAround(); bhandledInput = true; } break; case 2: if (details.navEquivalent == gfx.ui.NavigationCode.ENTER) { ToggleCheckbox(); bhandledInput = true; } break; } } return bhandledInput; } function SetOptionStepperOptions(aOptions: Object): Void { bSendChangeEvent = false; OptionStepper_mc.dataProvider = aOptions; bSendChangeEvent = true; } function onMousePress(): Void { var TopMostEntity_mc: Object = Mouse.getTopMostEntity(); switch (iMovieType) { case 0: if (TopMostEntity_mc == ScrollBar_mc.thumb) { ScrollBar_mc.thumb.onPress(); } else if (TopMostEntity_mc._parent == ScrollBar_mc.upArrow) { ScrollBar_mc.upArrow.onPress(); } else if (TopMostEntity_mc._parent == ScrollBar_mc.downArrow) { ScrollBar_mc.downArrow.onPress(); } else if (TopMostEntity_mc == ScrollBar_mc.track) { ScrollBar_mc.track.onPress(); } break; case 1: if (TopMostEntity_mc == OptionStepper_mc.nextBtn || TopMostEntity_mc == OptionStepper_mc.textField) { OptionStepper_mc.nextBtn.onPress(); } else if (TopMostEntity_mc == OptionStepper_mc.prevBtn) { OptionStepper_mc.prevBtn.onPress(); } break; } } function onRelease(): Void { var TopMostEntity_mc: Object = Mouse.getTopMostEntity(); switch (iMovieType) { case 0: if (TopMostEntity_mc == ScrollBar_mc.thumb) { ScrollBar_mc.thumb.onRelease(); } else if (TopMostEntity_mc._parent == ScrollBar_mc.upArrow) { ScrollBar_mc.upArrow.onRelease(); } else if (TopMostEntity_mc._parent == ScrollBar_mc.downArrow) { ScrollBar_mc.downArrow.onRelease(); } else if (TopMostEntity_mc == ScrollBar_mc.track) { ScrollBar_mc.track.onRelease(); } break; case 1: if (TopMostEntity_mc == OptionStepper_mc.nextBtn || TopMostEntity_mc == OptionStepper_mc.textField) { OptionStepper_mc.nextBtn.onRelease(); } else if (TopMostEntity_mc == OptionStepper_mc.prevBtn) { OptionStepper_mc.prevBtn.onRelease(); } break; case 2: if (TopMostEntity_mc._parent == CheckBox_mc) { ToggleCheckbox(); } break; } } function ToggleCheckbox(): Void { if (CheckBox_mc._currentframe == 1) { CheckBox_mc.gotoAndStop(2); } else if (CheckBox_mc._currentframe == 2) { CheckBox_mc.gotoAndStop(1); } DoOptionChange(); } function onStepperChange(event: Object): Void { if (bSendChangeEvent) { DoOptionChange(); } ProcessOnChangeCallback(); } function onScroll(event: Object): Void { if (bSendChangeEvent) { DoOptionChange(); } ProcessOnChangeCallback(); } function DoOptionChange(): Void { GameDelegate.call("OptionChange", [ID, value], requiresRestart); GameDelegate.call("PlaySound", ["UIMenuPrevNext"]); _parent.onValueChange(MovieClip(this).itemIndex, value); ProcessOnChangeCallback(); } function ProcessOnChangeCallback() { if(pScope != null && pScope != undefined && sFunction != null && sFunction != undefined) { pScope[sFunction].apply(pScope, [this]); } } } ================================================ FILE: src/PauseMenu/StatsList.as ================================================ import gfx.controls.ScrollBar; class StatsList extends Shared.BSScrollingList { var scrollbar: ScrollBar; function StatsList() { super(); scrollbar.focusTarget = this; } function SetEntryText(aEntryClip: MovieClip, aEntryObject: Object): Void { super.SetEntryText(aEntryClip, aEntryObject); aEntryClip.valueText.textAutoSize = "shrink"; if (aEntryObject.text != undefined) { aEntryClip.valueText.SetText(aEntryObject.value.toString()); return; } aEntryClip.valueText.SetText(" "); } } ================================================ FILE: src/PauseMenu/StatsPage.as ================================================ import gfx.managers.FocusHandler; import gfx.io.GameDelegate; import gfx.ui.InputDetails; import Shared.GlobalFunc; import gfx.ui.NavigationCode; class StatsPage extends MovieClip { var CategoryList: MovieClip; var CategoryList_mc: MovieClip; var StatsList_mc: MovieClip; var _StatsList: MovieClip; var bUpdated: Boolean; var iPlatform: Number; var Divider: MovieClip; function StatsPage() { super(); CategoryList = CategoryList_mc.List_mc; _StatsList = StatsList_mc; bUpdated = false; } function OnShow(): Void { bUpdated = false; var STAT_ENTRYLISTINDEX = 2; var STAT_STRIDE = 4; var cursor = 0; while(cursor < arguments.length) { CategoryList.entryList[arguments[cursor + STAT_ENTRYLISTINDEX]].stats.length = 0; cursor = cursor + STAT_STRIDE; } CategoryList.entryList.length = 0; CategoryList.InvalidateData(); onLoad(); } function onLoad(): Void { CategoryList.entryList.push({text: "$GENERAL", stats: new Array(), savedHighlight: 0}); CategoryList.entryList.push({text: "$QUEST", stats: new Array(), savedHighlight: 0}); CategoryList.entryList.push({text: "$COMBAT", stats: new Array(), savedHighlight: 0}); CategoryList.entryList.push({text: "$MAGIC", stats: new Array(), savedHighlight: 0}); CategoryList.entryList.push({text: "$CRAFTING", stats: new Array(), savedHighlight: 0}); CategoryList.entryList.push({text: "$CRIME", stats: new Array(), savedHighlight: 0}); CategoryList.InvalidateData(); CategoryList.addEventListener("listMovedUp", this, "onCategoryListMoveUp"); CategoryList.addEventListener("listMovedDown", this, "onCategoryListMoveDown"); CategoryList.addEventListener("selectionChange", this, "onCategoryListMouseSelectionChange"); CategoryList.disableInput = true; // Bugfix for vanilla _StatsList.disableSelection = false; } function startPage(): Void { CategoryList.disableInput = false; // Bugfix for vanilla FocusHandler.instance.setFocus(CategoryList, 0); if (bUpdated) { return; } GameDelegate.call("updateStats", [], this, "PopulateStatsList"); bUpdated = true; } function endPage(): Void { CategoryList.disableInput = true; // Bugfix for vanilla } function PopulateStatsList(): Void { var STAT_TEXT = 0; var STAT_VALUE = 1; var STAT_ENTRYLISTINDEX = 2; var STAT_UNKNOWN = 3; var STAT_STRIDE = 4; for (var i: Number = 0; i < arguments.length; i += STAT_STRIDE) { var stat: Object = {text: "$" + arguments[i + STAT_TEXT], value: arguments[i + STAT_VALUE]}; CategoryList.entryList[arguments[i + STAT_ENTRYLISTINDEX]].stats.push(stat); } onCategoryHighlight(); } function onCategoryHighlight(): Void { var stats: Array = CategoryList.selectedEntry.stats; _StatsList.ClearList(); _StatsList.scrollPosition = 0; for(var i: Number = 0; i < stats.length; i++) { _StatsList.entryList.push(stats[i]); } _StatsList.InvalidateData(); } function onCategoryListMoveUp(event: Object): Void { onCategoryHighlight(); GameDelegate.call("PlaySound", ["UIMenuFocus"]); if (event.scrollChanged == true) { CategoryList._parent.gotoAndPlay("moveUp"); } } function onCategoryListMoveDown(event: Object): Void { onCategoryHighlight(); GameDelegate.call("PlaySound", ["UIMenuFocus"]); if (event.scrollChanged == true) { CategoryList._parent.gotoAndPlay("moveDown"); } } function onCategoryListMouseSelectionChange(event: Object): Void { if (event.keyboardOrMouse == 0 && event.index != -1) { onCategoryHighlight(); GameDelegate.call("PlaySound", ["UIMenuFocus"]); } } function onRightStickInput(afX: Number, afY: Number): Void { if (afY < 0) { _StatsList.moveSelectionDown(); return; } _StatsList.moveSelectionUp(); } function SetPlatform(aiPlatform: Number, abPS3Switch: Boolean): Void { CategoryList.SetPlatform(aiPlatform, abPS3Switch); _StatsList.SetPlatform(aiPlatform, abPS3Switch); iPlatform = aiPlatform; } function handleInput(details: InputDetails, pathToFocus: Array): Boolean { var bhandledInput: Boolean = false; if (GlobalFunc.IsKeyPressed(details)) { if (_StatsList.entryList.length > 0) { if (details.navEquivalent == NavigationCode.LEFT && FocusHandler.instance.getFocus(0) != CategoryList) { switchFocusToCategoryList(); bhandledInput = true; } else if (details.navEquivalent == NavigationCode.RIGHT && FocusHandler.instance.getFocus(0) != _StatsList) { switchFocusToStatsList(); bhandledInput = true; } else if (details.navEquivalent == NavigationCode.DOWN && FocusHandler.instance.getFocus(0) == _StatsList) { // Scroll down if the user has the stat list select and hits "down" _StatsList.scrollPosition = _StatsList.scrollPosition + 1; } else if (details.navEquivalent == NavigationCode.UP && FocusHandler.instance.getFocus(0) == _StatsList) { // Scroll up if the user has the stat list select and hits "up" _StatsList.scrollPosition = _StatsList.scrollPosition - 1; } } } // Let other widgets try handling the event if (!bhandledInput && pathToFocus != undefined && pathToFocus.length > 0) { bhandledInput = pathToFocus[0].handleInput(details, pathToFocus.slice(1)); } return bhandledInput; } private function switchFocusToStatsList(): Void { FocusHandler.instance.setFocus(_StatsList, 0); Divider.gotoAndStop("Left"); } private function switchFocusToCategoryList(): Void { FocusHandler.instance.setFocus(CategoryList, 0); Divider.gotoAndStop("Right"); } } ================================================ FILE: src/PauseMenu/SystemPage.as ================================================ import Shared.ButtonTextArtHolder; import gfx.io.GameDelegate; import gfx.ui.InputDetails; import Shared.GlobalFunc; import gfx.ui.NavigationCode; import gfx.managers.FocusHandler; import skyui.defines.Input; import skyui.VRInput; import skyui.util.Debug; class SystemPage extends MovieClip { public static var MAIN_STATE: Number = 0; public static var SAVE_LOAD_STATE: Number = 1; public static var SAVE_LOAD_CONFIRM_STATE: Number = 2; public static var SETTINGS_CATEGORY_STATE: Number = 3; public static var OPTIONS_LISTS_STATE: Number = 4; public static var DEFAULT_SETTINGS_CONFIRM_STATE: Number = 5; public static var INPUT_MAPPING_STATE: Number = 6; public static var QUIT_CONFIRM_STATE: Number = 7; public static var PC_QUIT_LIST_STATE: Number = 8; public static var PC_QUIT_CONFIRM_STATE: Number = 9; public static var DELETE_SAVE_CONFIRM_STATE: Number = 10; public static var HELP_LIST_STATE: Number = 11; public static var HELP_TEXT_STATE: Number = 12; public static var TRANSITIONING: Number = 13; public static var CHARACTER_LOAD_STATE: Number = 14; public static var CHARACTER_SELECTION_STATE: Number = 15; public static var MOD_MANAGER_BUTTON_INDEX: Number = 3; public static var CONTROLS_BUTTON_INDEX: Number = 5 var HelpButtonHolder: ButtonTextArtHolder; var BottomBar_mc: MovieClip; var CategoryList: MovieClip; var CategoryList_mc: MovieClip; var ConfirmPanel: MovieClip; var HelpList: MovieClip; var HelpListPanel: MovieClip; var HelpTextPanel: MovieClip; var InputMappingPanel: MovieClip; var MappingList: MovieClip; var OptionsListsPanel: MovieClip; var PCQuitList: MovieClip; var PCQuitPanel: MovieClip; var PanelRect: MovieClip; var SaveLoadListHolder: MovieClip; var SaveLoadPanel: MovieClip; var SettingsList: MovieClip; var SettingsPanel: MovieClip; var SystemDivider: MovieClip; var TopmostPanel: MovieClip; var ConfirmTextField: TextField; var ErrorText: TextField; var HelpText: TextField; var HelpTitleText: TextField; var VersionText: TextField; var bMenuClosing: Boolean; var bRemapMode: Boolean; var bSavingSettings: Boolean; var bSettingsChanged: Boolean; var bUpdated: Boolean; var bShowKinectTunerButton: Boolean; var iCurrentState: Number; var iDebounceRemapModeID: Number; var iHideErrorTextID: Number; var iPlatform: Number; var iSaveDelayTimerID: Number; var iSavingSettingsTimerID: Number; var bDefaultButtonVisible: Boolean; var bIsRemoteDevice: Boolean; private var _saveDisabledList: Array; private var _deleteControls: Object; private var _defaultControls: Object; private var _kinectControls: Object; private var _acceptControls: Object; private var _cancelControls: Object; private var _characterSelectionControls: Object; private var _acceptButton: MovieClip; private var _cancelButton: MovieClip; private var _skyrimVersion: Number; private var _skyrimVersionMinor: Number; private var _skyrimVersionBuild: Number; private var _showModMenu: Boolean; private var _showControlsMenu: Boolean; private var _deleteButton: Object; private var pageWasEnded: Boolean = true; private var iTurnModeID: Number = undefined; private var bJustRefreshedSettings: Boolean = false; function SystemPage() { super(); CategoryList = CategoryList_mc.List_mc; SaveLoadListHolder = SaveLoadPanel; SettingsList = SettingsPanel.List_mc; MappingList = InputMappingPanel.List_mc; PCQuitList = PCQuitPanel.List_mc; HelpList = HelpListPanel.List_mc; HelpText = HelpTextPanel.HelpTextHolder.HelpText; HelpButtonHolder = HelpTextPanel.HelpTextHolder.ButtonArtHolder; HelpTitleText = HelpTextPanel.HelpTextHolder.TitleText; ConfirmTextField = ConfirmPanel.ConfirmText.textField; TopmostPanel = PanelRect; bUpdated = false; bRemapMode = false; bSettingsChanged = false; bMenuClosing = false; bSavingSettings = false; bShowKinectTunerButton = false; iPlatform = 0; bDefaultButtonVisible = false; _showModMenu = false; _showControlsMenu = false; } function GetIsRemoteDevice() { return bIsRemoteDevice; } function OnShow(): Void { if(pageWasEnded == false) { endPage(); } bMenuClosing = false; bUpdated = false; bRemapMode = false; bSettingsChanged = false; bSavingSettings = false; bShowKinectTunerButton = false; bDefaultButtonVisible = false; // Reset all panels and their animations (?) var cursor = SystemPage.SAVE_LOAD_STATE; while(cursor <= SystemPage.CHARACTER_SELECTION_STATE) { GetPanelForState(cursor).gotoAndStop(1); cursor++; } SystemDivider.gotoAndStop("Right"); HideErrorText(); GameDelegate.call("ShouldShowMod", [], this, "SetShowMod"); if(Shared.Platforms.IsUsingWands(iPlatform)) { _showControlsMenu = false; } else { _showControlsMenu = true; } /* CategoryList.clearList(); */ CategoryList.entryList = new Array(); CategoryList.entryList.push({text: "$QUICKSAVE"}); CategoryList.entryList.push({text: "$SAVE"}); CategoryList.entryList.push({text: "$LOAD"}); CategoryList.entryList.push({text: "$SETTINGS"}); CategoryList.entryList.push({text: "$MOD CONFIGURATION"}); if(_showModMenu) { CategoryList.entryList.push({text:"$MOD MANAGER"}); } if(_showControlsMenu) { CategoryList.entryList.push({text: "$CONTROLS"}); } CategoryList.entryList.push({text: "$HELP"}); CategoryList.entryList.push({text: "$QUIT"}); CategoryList.InvalidateData(); ConfirmPanel.handleInput = function () { return false; }; if(HelpList.entryList.length != 0) { HelpList.entryList = new Array(); } } static function IsOrbis(aiPlatform) { return aiPlatform == Shared.Platforms.CONTROLLER_ORBIS || aiPlatform == Shared.Platforms.CONTROLLER_ORBIS_MOVE; } function onLoad() { OnShow(); SaveLoadListHolder.addEventListener("saveGameSelected", this, "ConfirmSaveGame"); SaveLoadListHolder.addEventListener("loadGameSelected", this, "ConfirmLoadGame"); SaveLoadListHolder.addEventListener("saveListCharactersPopulated", this, "OnSaveListCharactersOpenSuccess"); SaveLoadListHolder.addEventListener("saveListPopulated", this, "OnSaveListOpenSuccess"); SaveLoadListHolder.addEventListener("saveListOnBatchAdded", this, "OnSaveListBatchAdded"); SaveLoadListHolder.addEventListener("OnCharacterSelected", this, "OnCharacterSelected"); GameDelegate.addCallBack("OnSaveDataEventSaveSUCCESS", this, "OnSaveDataEventSaveSUCCESS"); GameDelegate.addCallBack("OnSaveDataEventSaveCANCEL", this, "OnSaveDataEventSaveCANCEL"); GameDelegate.addCallBack("OnSaveDataEventLoadCANCEL", this, "OnSaveDataEventLoadCANCEL"); SaveLoadListHolder.addEventListener("saveHighlighted", this, "onSaveHighlight"); SaveLoadListHolder.List_mc.addEventListener("listPress", this, "onSaveLoadListPress"); CategoryList.addEventListener("itemPress", this,"onCategoryButtonPress"); CategoryList.addEventListener("listPress", this,"onCategoryListPress"); CategoryList.addEventListener("listMovedUp", this,"onCategoryListMoveUp"); CategoryList.addEventListener("listMovedDown", this,"onCategoryListMoveDown"); CategoryList.addEventListener("selectionChange", this,"onCategoryListMouseSelectionChange"); this.CategoryList.disableInput = true; SettingsList.entryList = [{text: "$Gameplay"}, {text: "$Display"}, {text: "$Audio"}, {text: "$VR"}, {text: "$VR Performance"}]; SettingsList.InvalidateData(); SettingsList.addEventListener("itemPress", this, "onSettingsCategoryPress"); SettingsList.disableInput = true; InputMappingPanel.List_mc.addEventListener("itemPress", this, "onInputMappingPress"); GameDelegate.addCallBack("FinishRemapMode", this, "onFinishRemapMode"); GameDelegate.addCallBack("SettingsSaved", this, "onSettingsSaved"); GameDelegate.addCallBack("RefreshSystemButtons", this, "RefreshSystemButtons"); PCQuitList.entryList = [{text: "$Main Menu"}, {text: "$Desktop"}]; PCQuitList.UpdateList(); PCQuitList.addEventListener("itemPress", this, "onPCQuitButtonPress"); HelpList.addEventListener("itemPress", this, "onHelpItemPress"); HelpList.disableInput = true; HelpTitleText.textAutoSize = "shrink"; BottomBar_mc = _parent._parent.BottomBar_mc; GameDelegate.addCallBack("BackOutFromLoadGame", this, "BackOutFromLoadGame"); GameDelegate.addCallBack("SetRemoteDevice", this, "SetRemoteDevice"); GameDelegate.addCallBack("UpdatePermissions", this, "UpdatePermissions"); GameDelegate.addCallBack("ConfirmDeleteSave", this, "ConfirmDeleteSave"); GameDelegate.addCallBack("StartDefaultSettingsConfirmState", this, "StartDefaultSettingsConfirmState"); GameDelegate.addCallBack("UpdateVRPerformanceValues", this, "UpdateVRPerformanceValues"); } function SetShowMod(bshow) { _showModMenu = bshow; } function startPage(): Void { pageWasEnded = false; CategoryList.disableInput = false; // Bugfix for vanilla if (!bUpdated) { currentState = SystemPage.MAIN_STATE; GameDelegate.call("SetVersionText", [VersionText]); var versionArr: Array = VersionText.text.split("."); // "1.8.151.0.7" without SKSE, "1.8.151.0.7 (SKSE 1.6.9 rel 37)" with _skyrimVersion = versionArr[0]; _skyrimVersionMinor = versionArr[1]; _skyrimVersionBuild = versionArr[2]; GameDelegate.call("ShouldShowKinectTunerOption", [], this, "SetShouldShowKinectTunerOption"); UpdatePermissions(); bUpdated = true; } else { UpdateStateFocus(iCurrentState); } } function endPage(): Void { BottomBar_mc.buttonPanel.clearButtons(); CategoryList.disableInput = true; // Bugfix for vanilla pageWasEnded = true; } function get currentState(): Number { return iCurrentState; } function set currentState(aiNewState: Number): Void { if(aiNewState == undefined) return; if(aiNewState == SystemPage.MAIN_STATE) { SaveLoadListHolder.isShowingCharacterList = false; } else if (aiNewState == SystemPage.SAVE_LOAD_STATE && this.SaveLoadListHolder.isShowingCharacterList) { aiNewState = SystemPage.CHARACTER_SELECTION_STATE; } var Panel_mc: MovieClip = GetPanelForState(aiNewState); iCurrentState = aiNewState; if (Panel_mc != TopmostPanel) { Panel_mc.swapDepths(TopmostPanel); TopmostPanel = Panel_mc; } UpdateStateFocus(aiNewState); GameDelegate.call("SetJournalMenuState", [aiNewState]); } function OnSaveDataEventSaveSUCCESS() { if(SystemPage.IsOrbis(iPlatform)) { this.bMenuClosing = true; this.EndState(); } } function OnSaveDataEventSaveCANCEL() { if(SystemPage.IsOrbis(iPlatform)) { this.HideErrorText(); this.EndState(); this.StartState(SystemPage.SAVE_LOAD_STATE); } } function OnSaveDataEventLoadCANCEL() { this.StartState(SystemPage.CHARACTER_SELECTION_STATE); } public function handleInput(details: InputDetails, pathToFocus: Array): Boolean { var bhandledInput: Boolean = false; if (bRemapMode || bMenuClosing || bSavingSettings || iCurrentState == SystemPage.TRANSITIONING) { bhandledInput = true; } else if (GlobalFunc.IsKeyPressed(details, iCurrentState != SystemPage.INPUT_MAPPING_STATE)) { if (iCurrentState != SystemPage.OPTIONS_LISTS_STATE) { if (details.navEquivalent == NavigationCode.RIGHT && iCurrentState == SystemPage.MAIN_STATE) { details.navEquivalent = NavigationCode.ENTER; } else if (details.navEquivalent == NavigationCode.LEFT && iCurrentState != SystemPage.MAIN_STATE) { details.navEquivalent = NavigationCode.TAB; } } if ((details.navEquivalent == NavigationCode.GAMEPAD_L2 || details.navEquivalent == gfx.ui.NavigationCode.GAMEPAD_R2) && isConfirming()) { bhandledInput = true; } else if ((details.navEquivalent == NavigationCode.GAMEPAD_X || details.code == 88) && iCurrentState == SystemPage.SAVE_LOAD_STATE) { if(SystemPage.IsOrbis(iPlatform)) { gfx.io.GameDelegate.call("ORBISDeleteSave",[]); } else { ConfirmDeleteSave(); } bhandledInput = true; } else if ((details.navEquivalent == gfx.ui.NavigationCode.GAMEPAD_Y || details.code == 84) && iCurrentState == SystemPage.SAVE_LOAD_STATE && !SaveLoadListHolder.isSaving) { StartState(SystemPage.CHARACTER_LOAD_STATE); bhandledInput = true; } else if ((details.navEquivalent == NavigationCode.GAMEPAD_Y || details.code == 84) && (iCurrentState == SystemPage.OPTIONS_LISTS_STATE || iCurrentState == SystemPage.INPUT_MAPPING_STATE)) { StartDefaultSettingsConfirmState(); bhandledInput = true; } else if (bShowKinectTunerButton && details.navEquivalent == NavigationCode.GAMEPAD_R1 && iCurrentState == SystemPage.OPTIONS_LISTS_STATE) { GameDelegate.call("OpenKinectTuner", []); bhandledInput = true; } else if (!pathToFocus[0].handleInput(details, pathToFocus.slice(1))) { if (details.navEquivalent == NavigationCode.ENTER) { bhandledInput = onAcceptPress(); } else if (details.navEquivalent == NavigationCode.TAB) { bhandledInput = onCancelPress(); } } } return bhandledInput; } function onAcceptPress(): Boolean { var bAcceptPressed: Boolean = true; switch (iCurrentState) { case SystemPage.CHARACTER_SELECTION_STATE: GameDelegate.call("PlaySound",["UIMenuOK"]); GameDelegate.call("CharacterSelected",[SaveLoadListHolder.selectedIndex]); break; case SystemPage.SAVE_LOAD_CONFIRM_STATE: case SystemPage.TRANSITIONING: if (SaveLoadListHolder.List_mc.disableSelection) { GameDelegate.call("PlaySound", ["UIMenuOK"]); if(SystemPage.IsOrbis(iPlatform)) { if(this.SaveLoadListHolder.isSaving) { this.iSaveDelayTimerID = setInterval(this,"DoSaveGame",1); } else { gfx.io.GameDelegate.call("LoadGame",[this.SaveLoadListHolder.selectedIndex]); } } else { bMenuClosing = true; if (SaveLoadListHolder.isSaving) { ConfirmPanel._visible = false; if (iPlatform > 1) { ErrorText.SetText("$Saving content. Please don\'t turn off your console."); } else { ErrorText.SetText("$Saving..."); } iSaveDelayTimerID = setInterval(this, "DoSaveGame", 1); } else { GameDelegate.call("LoadGame", [SaveLoadListHolder.selectedIndex]); } } } break; case SystemPage.QUIT_CONFIRM_STATE: // Have skyui dll release any GFxValues it's holding before actually quitting Debug.log(">>> Quest_Journal SystemPage.QUIT_CONFIRM_STATE"); VRInput.instance.teardown(); GameDelegate.call("PlaySound", ["UIMenuOK"]); GameDelegate.call("QuitToMainMenu", []); bMenuClosing = true; Debug.log("<<< Quest_Journal SystemPage.QUIT_CONFIRM_STATE"); break; case SystemPage.PC_QUIT_CONFIRM_STATE: if (PCQuitList.selectedIndex == 0) { GameDelegate.call("QuitToMainMenu", []); bMenuClosing = true; } else if (PCQuitList.selectedIndex == 1) { GameDelegate.call("QuitToDesktop", []); } break; case SystemPage.DELETE_SAVE_CONFIRM_STATE: SaveLoadListHolder.DeleteSelectedSave(); if (SaveLoadListHolder.numSaves == 0) { GetPanelForState(SystemPage.SAVE_LOAD_STATE).gotoAndStop(1); GetPanelForState(SystemPage.DELETE_SAVE_CONFIRM_STATE).gotoAndStop(1); currentState = SystemPage.MAIN_STATE; SystemDivider.gotoAndStop("Right"); } else { EndState(); } break; case SystemPage.DEFAULT_SETTINGS_CONFIRM_STATE: GameDelegate.call("PlaySound", ["UIMenuOK"]); if (ConfirmPanel.returnState == SystemPage.OPTIONS_LISTS_STATE) { ResetSettingsToDefaults(); } else if (ConfirmPanel.returnState == SystemPage.INPUT_MAPPING_STATE) { ResetControlsToDefaults(); } EndState(); break; default: bAcceptPressed = false; break; } return bAcceptPressed; } function onCancelPress(): Boolean { var bCancelPressed: Boolean = true; switch (iCurrentState) { case SystemPage.CHARACTER_LOAD_STATE: case SystemPage.CHARACTER_SELECTION_STATE: case SystemPage.SAVE_LOAD_STATE: SaveLoadListHolder.ForceStopLoading(); case SystemPage.PC_QUIT_LIST_STATE: case SystemPage.HELP_LIST_STATE: case SystemPage.SAVE_LOAD_CONFIRM_STATE: case SystemPage.QUIT_CONFIRM_STATE: case SystemPage.DEFAULT_SETTINGS_CONFIRM_STATE: case SystemPage.PC_QUIT_CONFIRM_STATE: case SystemPage.DELETE_SAVE_CONFIRM_STATE: GameDelegate.call("PlaySound", ["UIMenuCancel"]); EndState(); break; case SystemPage.HELP_TEXT_STATE: GameDelegate.call("PlaySound", ["UIMenuCancel"]); EndState(); StartState(SystemPage.HELP_LIST_STATE); HelpListPanel.bCloseToMainState = true; break; case SystemPage.OPTIONS_LISTS_STATE: GameDelegate.call("PlaySound", ["UIMenuCancel"]); EndState(); StartState(SystemPage.SETTINGS_CATEGORY_STATE); SettingsPanel.bCloseToMainState = true; break; case SystemPage.INPUT_MAPPING_STATE: case SystemPage.SETTINGS_CATEGORY_STATE: GameDelegate.call("PlaySound", ["UIMenuCancel"]); if (bSettingsChanged) { ErrorText.SetText("$Saving..."); bSavingSettings = true; if (iCurrentState == SystemPage.INPUT_MAPPING_STATE) { iSavingSettingsTimerID = setInterval(this, "SaveControls", 1000); } else if (iCurrentState == SystemPage.SETTINGS_CATEGORY_STATE) { iSavingSettingsTimerID = setInterval(this, "SaveSettings", 1000); } } else { onSettingsSaved(); } break; default: bCancelPressed = false; break; } return bCancelPressed; } function isConfirming(): Boolean { return iCurrentState == SystemPage.SAVE_LOAD_CONFIRM_STATE || iCurrentState == SystemPage.QUIT_CONFIRM_STATE || iCurrentState == SystemPage.PC_QUIT_CONFIRM_STATE || iCurrentState == SystemPage.DELETE_SAVE_CONFIRM_STATE || iCurrentState == SystemPage.DEFAULT_SETTINGS_CONFIRM_STATE; } function onAcceptMousePress(): Void { if (isConfirming()) { onAcceptPress(); } } function onCancelMousePress(): Void { if (isConfirming()) { onCancelPress(); } } function StartDefaultSettingsConfirmState(): Void { if(iCurrentState == SystemPage.OPTIONS_LISTS_STATE || iCurrentState == SystemPage.INPUT_MAPPING_STATE) { ConfirmTextField.SetText("$Reset settings to default values?"); StartState(SystemPage.DEFAULT_SETTINGS_CONFIRM_STATE); } } function onCategoryButtonPress(event: Object): Void { if (event.entry.disabled) { GameDelegate.call("PlaySound", ["UIMenuCancel"]); return; } if (iCurrentState == SystemPage.MAIN_STATE) { var categoryName = CategoryList.entryList[event.index].text; switch (categoryName) { case "$QUICKSAVE": GameDelegate.call("PlaySound", ["UIMenuOK"]); GameDelegate.call("QuickSave", []); break; case "$SAVE": GameDelegate.call("UseCurrentCharacterFilter",[]); SaveLoadListHolder.isSaving = true; if (SystemPage.IsOrbis(iPlatform)) { SaveLoadListHolder.PopulateEmptySaveList(); } else { GameDelegate.call("SAVE",[SaveLoadListHolder.List_mc.entryList, SaveLoadListHolder.batchSize]); } break; case "$LOAD": SaveLoadListHolder.isSaving = false; GameDelegate.call("LOAD", [SaveLoadListHolder.List_mc.entryList, SaveLoadListHolder.batchSize]); break; case "$MOD MANAGER": gfx.io.GameDelegate.call("ModManager",[]); break; case "$SETTINGS": StartState(SystemPage.SETTINGS_CATEGORY_STATE); GameDelegate.call("PlaySound", ["UIMenuOK"]); break; case "$MOD CONFIGURATION": _root.QuestJournalFader.Menu_mc.ConfigPanelOpen(); break; case "$CONTROLS": if (MappingList.entryList.length == 0) requestInputMappings(); StartState(SystemPage.INPUT_MAPPING_STATE); GameDelegate.call("PlaySound", ["UIMenuOK"]); break; case "$HELP": if (HelpList.entryList.length == 0) { GameDelegate.call("PopulateHelpTopics", [HelpList.entryList]); HelpList.entryList.sort(doABCSort); HelpList.InvalidateData(); } if (HelpList.entryList.length == 0) { GameDelegate.call("PlaySound", ["UIMenuCancel"]); } else { StartState(SystemPage.HELP_LIST_STATE); GameDelegate.call("PlaySound", ["UIMenuOK"]); } break; case "$QUIT": GameDelegate.call("PlaySound", ["UIMenuOK"]); GameDelegate.call("RequestIsOnPC", [], this, "populateQuitList"); break; default: GameDelegate.call("PlaySound", ["UIMenuCancel"]); break; } } } function onCategoryListPress(event: Object): Void { if (!bRemapMode && !bMenuClosing && !bSavingSettings && iCurrentState != SystemPage.TRANSITIONING) { onCancelPress(); CategoryList.disableSelection = false; CategoryList.UpdateList(); CategoryList.disableSelection = true; } } function doABCSort(aObj1: Object, aObj2: Object): Number { if(aObj1.text.indexOf("VR ") >= 0 && aObj2.text.indexOf("VR ") >= 0) { if(aObj1.text < aObj2.text) { return -1; } if(aObj1.text > aObj2.text) { return 1; } } if(aObj1.text.indexOf("VR ") >= 0) { return -1; } if(aObj2.text.indexOf("VR ") >= 0) { return 1; } if (aObj1.text < aObj2.text) { return -1; } if (aObj1.text > aObj2.text) { return 1; } return 0; } function onCategoryListMoveUp(event: Object): Void { GameDelegate.call("PlaySound", ["UIMenuFocus"]); if (event.scrollChanged == true) { CategoryList._parent.gotoAndPlay("moveUp"); } } function onCategoryListMoveDown(event: Object): Void { GameDelegate.call("PlaySound", ["UIMenuFocus"]); if (event.scrollChanged == true) { CategoryList._parent.gotoAndPlay("moveDown"); } } function onCategoryListMouseSelectionChange(event: Object): Void { if (event.keyboardOrMouse == 0 && event.index != -1) { GameDelegate.call("PlaySound", ["UIMenuFocus"]); } } function OnCharacterSelected() { if(!SystemPage.IsOrbis(iPlatform)) { StartState(SystemPage.SAVE_LOAD_STATE); } } function OnSaveListCharactersOpenSuccess() { if(this.SaveLoadListHolder.numSaves > 0) { GameDelegate.call("PlaySound",["UIMenuOK"]); StartState(SystemPage.CHARACTER_SELECTION_STATE); } else { GameDelegate.call("PlaySound",["UIMenuCancel"]); } } function OnSaveListOpenSuccess(): Void { if (SaveLoadListHolder.numSaves > 0) { GameDelegate.call("PlaySound", ["UIMenuOK"]); StartState(SystemPage.SAVE_LOAD_STATE); } else { StartState(SystemPage.CHARACTER_LOAD_STATE); } } function OnSaveListBatchAdded() { } function ConfirmSaveGame(event: Object): Void { SaveLoadListHolder.List_mc.disableSelection = true; if (iCurrentState == SystemPage.SAVE_LOAD_STATE) { if (event.index == 0) { iCurrentState = SystemPage.SAVE_LOAD_CONFIRM_STATE; onAcceptPress(); } else { ConfirmTextField.SetText("$Save over this game?"); StartState(SystemPage.SAVE_LOAD_CONFIRM_STATE); GameDelegate.call("PlaySound", ["UIMenuOK"]); } } } function DoSaveGame(): Void { clearInterval(iSaveDelayTimerID); GameDelegate.call("SaveGame", [SaveLoadListHolder.selectedIndex]); if(!SystemPage.IsOrbis(iPlatform)) { _parent._parent.CloseMenu(); } } function onSaveHighlight(event: Object): Void { if (iCurrentState == SystemPage.SAVE_LOAD_STATE && !SaveLoadListHolder.isShowingCharacterList) { if (_deleteButton != null) { _deleteButton._alpha = ((event.index == -1) ? 50 : 100); } if (iPlatform == Shared.Platforms.CONTROLLER_PC) GameDelegate.call("PlaySound", ["UIMenuFocus"]); } } function onSaveLoadListPress(): Void { onAcceptPress(); } function ConfirmLoadGame(event: Object): Void { SaveLoadListHolder.List_mc.disableSelection = true; if (iCurrentState == SystemPage.SAVE_LOAD_STATE) { ConfirmTextField.SetText("$Load this game? All unsaved progress will be lost."); StartState(SystemPage.SAVE_LOAD_CONFIRM_STATE); GameDelegate.call("PlaySound", ["UIMenuOK"]); } } function ConfirmDeleteSave(): Void { if (!SaveLoadListHolder.isSaving || SaveLoadListHolder.selectedIndex != 0) { SaveLoadListHolder.List_mc.disableSelection = true; if (iCurrentState == SystemPage.SAVE_LOAD_STATE) { ConfirmTextField.SetText("$Delete this save?"); StartState(SystemPage.DELETE_SAVE_CONFIRM_STATE); } } } function onSettingsCategoryPress(): Void { var List_mc: MovieClip = OptionsListsPanel.OptionsLists.List_mc; switch (SettingsList.selectedIndex) { case 0: List_mc.entryList = [ {text: "$Invert Y", movieType: 2}, {text: "$Look Sensitivity", movieType: 0}, {text: "$Vibration", movieType: 2}, {text: "$360 Controller", movieType: 2}, {text: "$Difficulty", movieType: 1, options: ["$Very Easy", "$Easy", "$Normal", "$Hard", "$Very Hard", "$Legendary"]}, {text: "$Show Floating Markers", movieType: 2}, {text: "$Save on Rest", movieType: 2}, {text: "$Save on Wait", movieType: 2}, {text: "$Save on Travel", movieType: 2}, {text: "$Save on Pause", movieType: 1, options: ["$5 Mins", "$10 Mins", "$15 Mins", "$30 Mins", "$45 Mins", "$60 Mins", "$Disabled"]}, {text: "$Use Kinect Commands", movieType: 2}]; GameDelegate.call("RequestGameplayOptions", [List_mc.entryList]); break; case 1: List_mc.entryList = [ {text: "$Brightness", movieType: 0}, {text: "$HUD Opacity", movieType: 0}, {text: "$Actor Fade", movieType: 0}, {text: "$Item Fade", movieType: 0}, {text: "$Object Fade", movieType: 0}, {text: "$Grass Fade", movieType: 0}, {text: "$Shadow Fade", movieType: 0}, {text: "$Light Fade", movieType: 0}, {text: "$Specularity Fade", movieType: 0}, {text: "$Tree LOD Fade", movieType: 0}, {text: "$Crosshair", movieType: 2}, {text: "$Dialogue Subtitles", movieType: 2}, {text: "$General Subtitles", movieType: 2}]; GameDelegate.call("RequestDisplayOptions", [List_mc.entryList]); break; case 2: List_mc.entryList = [{text: "$Master", movieType: 0}]; GameDelegate.call("RequestAudioOptions", [List_mc.entryList]); for (var i: String in List_mc.entryList) List_mc.entryList[i].movieType = 0; break; case 3: List_mc.entryList = [ {text:"$Turning Mode",movieType:1,options:["$Snap","$Smooth"]}, {text:"$Snap Transition",movieType:1,options:["$Gradual","$Instant"]}, {text:"$Angle Snap Amount",movieType:0}, {text:"$Rotation Speed",movieType:0}, {text:"$Movement Mode",movieType:1,options:["$Teleportation","$Direct Movement"]}, {text:"$Direct Movement Mode",movieType:1,options:["$HMD Relative","$Wand Relative"]}, {text:"$Compass Position",movieType:1,options:["$Compass Low","$Compass High","$Compass Off"]}, {text:"$Main Hand",movieType:1,options:["$Right","$Left"]}, {text:"$Show Hands While Sheathed",movieType:2}, {text:"$Height",movieType:0}, {text:"$Movement Speed",movieType:0}, {text:"$Crosshair",movieType:2}, {text:"$Physical Sneaking",movieType:2}, {text:"$Realistic Swimming",movieType:2}, {text:"$Realistic Shield Grip",movieType:2}, {text:"$Realistic Bow",movieType:2}, {text:"$FOV Filter While Turning",movieType:2}, {text:"$FOV Filter While Moving",movieType:2}, {text:"$FOV Filter Strength",movieType:0}]; GameDelegate.call("RequestVROptions", [List_mc.entryList]); break; case 4: GameDelegate.call("RequestVRPerformanceOptions", [List_mc.entryList]); break; } for (var i: Number = 0; i < List_mc.entryList.length; ){ if (List_mc.entryList[i].ID == undefined) { List_mc.entryList.splice(i, 1); } else { i++; } } if (iPlatform != Shared.Platforms.CONTROLLER_PC) { List_mc.selectedIndex = 0; } List_mc.bAllowValueOverwrite = true; List_mc.InvalidateData(); List_mc.bAllowValueOverwrite = false; SettingsPanel.bCloseToMainState = false; EndState(); StartState(SystemPage.OPTIONS_LISTS_STATE); GameDelegate.call("PlaySound", ["UIMenuOK"]); bSettingsChanged = true; GameDelegate.call("RequestTurnModeID", [], this, "SetTurningModeID"); var i = 0; var item = List_mc["Entry" + i]; while(item != undefined) { item.SetOnChangedCAllback(this, "OnOptionValueChanged"); i++; item = List_mc["Entry" + i]; } } function SetTurningModeID(afID) { iTurnModeID = afID; } function OnOptionValueChanged(aObject) { if(aObject.ID == this.iTurnModeID) { GameDelegate.call("GetGradualSpeedData", [], this, "UpdateGradualSpeed"); } } function UpdateGradualSpeed(afValue, afDefaultValue, afGradualSpeedID) { if(SettingsList.selectedIndex == 3) { var List_mc: MovieClip = OptionsListsPanel.OptionsLists.List_mc; if(List_mc != null && List_mc != undefined) { var i = 0; while(i < List_mc.entryList.length) { if(List_mc.entryList[i].ID == afGradualSpeedID) { List_mc.entryList[i].value = afValue; List_mc.entryList[i].defaultVal = afDefaultValue; if(List_mc.entryList[i].clipIndex != undefined) { List_mc["Entry" + List_mc.entryList[i].clipIndex].value = afValue; } return; } i++; } } } } function UpdateVRPerformanceValues() { bJustRefreshedSettings = true; if(SettingsList.selectedIndex == 4) { var List_mc: MovieClip = OptionsListsPanel.OptionsLists.List_mc; if(List_mc != null && List_mc != undefined) { // Grab the value of the performance options var optionValues = new Array(); GameDelegate.call("RequestVRPerformanceOptions", [optionValues]); // Go through each item in the entry list var i = 0; while(i < List_mc.entryList.length) { var optionIdx = -1; var j = 0; // Try to find a matching entry in the optionsValues array while(j < optionValues.length) { if(optionValues[j].ID == List_mc.entryList[i].ID) { optionIdx = j; break; } j++ } // If a matching entry is found, copy the current value into List_mc if(optionIdx >= 0) { List_mc.entryList[i].value = optionValues[optionIdx].value; List_mc.entryList[i].defaultVal = optionValues[optionIdx].defaultVal; } i++; } List_mc.bAllowVAlueOverwrite = true; List_mc.UpdateList(); List_mc.bAllowVAlueOverwrite = false; } } } function ResetSettingsToDefaults(): Void { var List_mc: MovieClip = OptionsListsPanel.OptionsLists.List_mc; for (var i: String in List_mc.entryList) { if (List_mc.entryList[i].defaultVal != undefined) { List_mc.entryList[i].value = List_mc.entryList[i].defaultVal; GameDelegate.call("OptionChange", [List_mc.entryList[i].ID, List_mc.entryList[i].value]); } } GameDelegate.call("OnresetToDefault", []); List_mc.bAllowValueOverwrite = true; List_mc.UpdateList(); List_mc.bAllowValueOverwrite = false; } function onInputMappingPress(event: Object): Void { if (bRemapMode == false && iCurrentState == SystemPage.INPUT_MAPPING_STATE) { MappingList.disableSelection = true; bRemapMode = true; ErrorText.SetText("$Press a button to map to this action."); GameDelegate.call("PlaySound", ["UIMenuPrevNext"]); GameDelegate.call("StartRemapMode", [event.entry.text, MappingList.entryList]); } } function onFinishRemapMode(abSuccess: Boolean): Void { if (abSuccess) { HideErrorText(); MappingList.entryList.sort(inputMappingSort); MappingList.UpdateList(); bSettingsChanged = true; GameDelegate.call("PlaySound", ["UIMenuFocus"]); } else { ErrorText.SetText("$That button is reserved."); GameDelegate.call("PlaySound", ["UIMenuCancel"]); iHideErrorTextID = setInterval(this, "HideErrorText", 1000); } MappingList.disableSelection = false; iDebounceRemapModeID = setInterval(this, "ClearRemapMode", 200); } private function inputMappingSort(a_obj1: Object, a_obj2: Object): Number { if (a_obj1.sortIndex < a_obj2.sortIndex) { return -1; } if (a_obj1.sortIndex > a_obj2.sortIndex) { return 1; } return 0; } function HideErrorText(): Void { if (iHideErrorTextID != undefined) { clearInterval(iHideErrorTextID); } ErrorText.SetText(" "); } function ClearRemapMode(): Void { if (iDebounceRemapModeID != undefined) { clearInterval(iDebounceRemapModeID); delete(iDebounceRemapModeID); } bRemapMode = false; } function ResetControlsToDefaults(): Void { GameDelegate.call("ResetControlsToDefaults", [MappingList.entryList]); requestInputMappings(true); bSettingsChanged = true; } function onHelpItemPress(): Void { GameDelegate.call("RequestHelpText", [HelpList.selectedEntry.index, HelpTitleText, HelpText]); HelpText.text = Shared.ExtractPlatformText.Extract(HelpText.text, iPlatform); ApplyHelpTextButtonArt(); HelpListPanel.bCloseToMainState = false; EndState(); StartState(SystemPage.HELP_TEXT_STATE); } function ApplyHelpTextButtonArt(): Void { var strTextWithButtons: String = HelpButtonHolder.CreateButtonArtCustomSize(HelpText.textField, 32); if (strTextWithButtons != undefined) HelpText.htmlText = strTextWithButtons; } function populateQuitList(abOnPC: Boolean): Void { if (abOnPC) { if (iPlatform != Shared.Platforms.CONTROLLER_PC) { PCQuitList.selectedIndex = 0; } StartState(SystemPage.PC_QUIT_LIST_STATE); return; } ConfirmTextField.textAutoSize = "shrink"; ConfirmTextField.SetText("$Quit to main menu? Any unsaved progress will be lost."); StartState(SystemPage.QUIT_CONFIRM_STATE); } function onPCQuitButtonPress(event: Object): Void { if (iCurrentState == SystemPage.PC_QUIT_LIST_STATE) { PCQuitList.disableSelection = true; if (event.index == 0) { ConfirmTextField.textAutoSize = "shrink"; ConfirmTextField.SetText("$Quit to main menu? Any unsaved progress will be lost."); } else if (event.index == 1) { ConfirmTextField.textAutoSize = "shrink"; ConfirmTextField.SetText("$Quit to desktop? Any unsaved progress will be lost."); } StartState(SystemPage.PC_QUIT_CONFIRM_STATE); } } function SaveControls(): Void { clearInterval(iSavingSettingsTimerID); GameDelegate.call("SaveControls", []); } function SaveSettings(): Void { clearInterval(iSavingSettingsTimerID); GameDelegate.call("SaveSettings", []); } function onSettingsSaved(): Void { bSavingSettings = false; bSettingsChanged = false; ErrorText.SetText(" "); EndState(); } function RefreshSystemButtons() { var params = new Array(); var i = 0; while(i < CategoryList.entryList.length) { if( i != CategoryList.entryList.length - 2) { params.push(CategoryList.entryList[i]); } i++; } params.push(true); GameDelegate.call("SetSaveDisabled", params) CategoryList.UpdateList(); } function StartState(aiState: Number): Void { BottomBar_mc.buttonPanel.clearButtons(); switch (aiState) { case SystemPage.CHARACTER_LOAD_STATE: SaveLoadListHolder.isShowingCharacterList = true; SystemDivider.gotoAndStop("Left"); GameDelegate.call("PopulateCharacterList", [SaveLoadListHolder.List_mc.entryList, SaveLoadListHolder.batchSize]); break; case SystemPage.CHARACTER_SELECTION_STATE: BottomBar_mc.buttonPanel.addButton({text:"$Cancel", controls: _cancelControls}); break; case SystemPage.SAVE_LOAD_STATE: SaveLoadListHolder.isShowingCharacterList = false; SystemDivider.gotoAndStop("Left"); _deleteButton = BottomBar_mc.buttonPanel.addButton({text: "$Delete", controls: _deleteControls}); // X or 360_X if(SaveLoadListHolder.isSaving == false) { BottomBar_mc.buttonPanel.addButton({text:"$CharacterSelection",controls: _characterSelectionControls}); } BottomBar_mc.buttonPanel.addButton({text:"$Cancel",controls:this._cancelControls}); BottomBar_mc.buttonPanel.updateButtons(true); break; case SystemPage.INPUT_MAPPING_STATE: SystemDivider.gotoAndStop("Left"); if(bIsRemoteDevice) { bDefaultButtonVisible = false; } else { BottomBar_mc.buttonPanel.addButton({text:"$Defaults", controls: _defaultControls}); bDefaultButtonVisible = true; } BottomBar_mc.buttonPanel.addButton({text:"$Cancel", controls: _cancelControls}); BottomBar_mc.buttonPanel.updateButtons(true); break; case SystemPage.OPTIONS_LISTS_STATE: BottomBar_mc.buttonPanel.addButton({text: "$Defaults", controls: _defaultControls}); // T or 360_Y if (aiState == SystemPage.OPTIONS_LISTS_STATE && bShowKinectTunerButton && iPlatform == 2 && SettingsList.selectedIndex == 0) BottomBar_mc.buttonPanel.addButton({text: "$Kinect Tuner", controls: _kinectControls}); // K or RB BottomBar_mc.buttonPanel.addButton({text:"$Cancel",controls:this._cancelControls}); BottomBar_mc.buttonPanel.updateButtons(true); break; case SystemPage.HELP_TEXT_STATE: case SystemPage.HELP_LIST_STATE: case SystemPage.SETTINGS_CATEGORY_STATE: BottomBar_mc.buttonPanel.addButton({text:"$Cancel", controls:_cancelControls}); BottomBar_mc.buttonPanel.updateButtons(true); SystemDivider.gotoAndStop("Left"); break; case SystemPage.SAVE_LOAD_CONFIRM_STATE: case SystemPage.QUIT_CONFIRM_STATE: case SystemPage.PC_QUIT_CONFIRM_STATE: case SystemPage.DELETE_SAVE_CONFIRM_STATE: case SystemPage.DEFAULT_SETTINGS_CONFIRM_STATE: ConfirmPanel.confirmType = aiState; ConfirmPanel.returnState = iCurrentState; break; } iCurrentState = SystemPage.TRANSITIONING; GetPanelForState(aiState).gotoAndPlay("start"); } function EndState(): Void { BottomBar_mc.buttonPanel.clearButtons(); switch (iCurrentState) { case SystemPage.CHARACTER_LOAD_STATE: case SystemPage.CHARACTER_SELECTION_STATE: case SystemPage.SAVE_LOAD_STATE: case SystemPage.INPUT_MAPPING_STATE: case SystemPage.HELP_TEXT_STATE: if(!SystemPage.IsOrbis(iPlatform)) { SystemDivider.gotoAndStop("Right"); } break; case SystemPage.OPTIONS_LISTS_STATE: break; case SystemPage.HELP_LIST_STATE: HelpList.disableInput = true; if (HelpListPanel.bCloseToMainState != false) { SystemDivider.gotoAndStop("Right"); } break; case SystemPage.SETTINGS_CATEGORY_STATE: SettingsList.disableInput = true; if (SettingsPanel.bCloseToMainState != false) { SystemDivider.gotoAndStop("Right"); } break; case SystemPage.PC_QUIT_LIST_STATE: SystemDivider.gotoAndStop("Right"); break; } if (iCurrentState != SystemPage.MAIN_STATE) { GetPanelForState(iCurrentState).gotoAndPlay("end"); iCurrentState = SystemPage.TRANSITIONING; } } function GetPanelForState(aiState: Number): MovieClip { switch (aiState) { case SystemPage.MAIN_STATE: return PanelRect; case SystemPage.SETTINGS_CATEGORY_STATE: return SettingsPanel; case SystemPage.OPTIONS_LISTS_STATE: return OptionsListsPanel; case SystemPage.INPUT_MAPPING_STATE: return InputMappingPanel; case SystemPage.CHARACTER_LOAD_STATE: case SystemPage.CHARACTER_SELECTION_STATE: case SystemPage.SAVE_LOAD_STATE: return SaveLoadPanel; case SystemPage.SAVE_LOAD_CONFIRM_STATE: case SystemPage.PC_QUIT_CONFIRM_STATE: case SystemPage.QUIT_CONFIRM_STATE: case SystemPage.DELETE_SAVE_CONFIRM_STATE: case SystemPage.DEFAULT_SETTINGS_CONFIRM_STATE: return ConfirmPanel; case SystemPage.PC_QUIT_LIST_STATE: return PCQuitPanel; case SystemPage.HELP_LIST_STATE: return HelpListPanel; case SystemPage.HELP_TEXT_STATE: return HelpTextPanel; } } function UpdateStateFocus(aiNewState: Number): Void { CategoryList.disableSelection = aiNewState != SystemPage.MAIN_STATE; switch (aiNewState) { case SystemPage.MAIN_STATE: FocusHandler.instance.setFocus(CategoryList, 0); break; case SystemPage.SETTINGS_CATEGORY_STATE: SettingsList.disableInput = false; FocusHandler.instance.setFocus(SettingsList, 0); break; case SystemPage.OPTIONS_LISTS_STATE: FocusHandler.instance.setFocus(OptionsListsPanel.OptionsLists.List_mc, 0); break; case SystemPage.INPUT_MAPPING_STATE: FocusHandler.instance.setFocus(MappingList, 0); break; case SystemPage.SAVE_LOAD_STATE: case SystemPage.CHARACTER_LOAD_STATE: case SystemPage.CHARACTER_SELECTION_STATE: FocusHandler.instance.setFocus(SaveLoadListHolder.List_mc, 0); SaveLoadListHolder.List_mc.disableSelection = false; break; case SystemPage.SAVE_LOAD_CONFIRM_STATE: case SystemPage.QUIT_CONFIRM_STATE: case SystemPage.PC_QUIT_CONFIRM_STATE: case SystemPage.DELETE_SAVE_CONFIRM_STATE: case SystemPage.DEFAULT_SETTINGS_CONFIRM_STATE: ConfirmPanel._visible = true; FocusHandler.instance.setFocus(ConfirmPanel, 0); break; case SystemPage.PC_QUIT_LIST_STATE: FocusHandler.instance.setFocus(PCQuitList, 0); PCQuitList.disableSelection = false; break; case SystemPage.HELP_LIST_STATE: HelpList.disableInput = false; FocusHandler.instance.setFocus(HelpList, 0); break; case SystemPage.HELP_TEXT_STATE: FocusHandler.instance.setFocus(HelpText, 0); break; } } function Exists(apObject) { return apObject != null && apObject != undefined; } function SetPlatform(a_platform: Number, a_bPS3Switch: Boolean): Void { if(bJustRefreshedSettings) { bJustRefreshedSettings = false; return; } BottomBar_mc.SetPlatform(a_platform, a_bPS3Switch); CategoryList.SetPlatform(a_platform, a_bPS3Switch); // Setup the buttons by platform _deleteControls = skyui.util.Input.pickControls(a_platform, {PCArt:"X", XBoxArt:"360_X", PS3Art:"PS3_X", ViveArt:"radial_Either_Right", MoveArt:"PS3_A", OculusArt:"OCC_A", WindowsMRArt:"radial_Either_Right"}); _defaultControls = skyui.util.Input.pickControls(a_platform, {PCArt: "T", XBoxArt: "360_Y"}); _kinectControls = skyui.util.Input.pickControls(a_platform, {PCArt:"K", XBoxArt:"360_RB"}); _acceptControls = skyui.util.Input.pickControls(a_platform, {PCArt:"Enter", XBoxArt:"360_A", ViveArt:"trigger", MoveArt:"trigger",OculusArt: "trigger", WindowsMRArt:"trigger"}); _cancelControls = skyui.util.Input.pickControls(a_platform, {PCArt:"Esc", XBoxArt:"360_B", PS3Art:"PS3_B", ViveArt:"grip", MoveArt:"PS3_B", OculusArt:"grab", WindowsMRArt:"grab"}); _characterSelectionControls = skyui.util.Input.pickControls(a_platform, {PCArt:"T", XBoxArt:"360_Y", PS3Art:"PS3_Y", ViveArt:"radial_Either_Left", MoveArt:"PS3_A", OculusArt:"OCC_A", WindowsMRArt:"radial_Either_Left"}); if (a_platform != Shared.Platforms.CONTROLLER_PC) { SettingsList.selectedIndex = 0; PCQuitList.selectedIndex = 0; HelpList.selectedIndex = 0; MappingList.selectedIndex = 0; } ConfirmPanel.buttonPanel.clearButtons(); _acceptButton = ConfirmPanel.buttonPanel.addButton({text: "$Yes", controls: _acceptControls}); _acceptButton.addEventListener("click", this, "onAcceptMousePress"); _cancelButton = ConfirmPanel.buttonPanel.addButton({text: "$No", controls: _cancelControls}); _cancelButton.addEventListener("click", this, "onCancelMousePress"); ConfirmPanel.buttonPanel.updateButtons(true); iPlatform = a_platform; SaveLoadListHolder.platform = a_platform; requestInputMappings(); } function BackOutFromLoadGame(): Void { bMenuClosing = false; onCancelPress(); } function SetShouldShowKinectTunerOption(abFlag: Boolean): Void { bShowKinectTunerButton = abFlag == true; } function SetRemoteDevice(abISRemoteDevice) { bIsRemoteDevice = abISRemoteDevice; if(bIsRemoteDevice) { MappingList.entryList.clear(); } } // It's not very clear what this function is supposed to do. // This is a refactoring of what ships with SE, VR, and Skyui swfs. // Instead of handling all possible permutations of the various settings that may // affect the menu entry order, this simply puts together the correct list of // items to send at runtime. function UpdatePermissions() { var itemsList = CategoryList.entryList; var itemsToSend = new Array(); // Which entries do we want to send? var matchList = ["$QUICKSAVE", "$SAVE", "$LOAD", "$SETTINGS", "$MOD MANAGER", "$CONTROLS", "$QUIT"]; // Locate all entries specified by the matchList for(var itemIdx = 0; itemIdx < itemsList.length; itemIdx++) { var item = itemsList[itemIdx]; for(var matchIdx in matchList) { if(matchList[matchIdx] == item.text) { itemsToSend.push(item); } } } // Send the data to the engine for... something... GameDelegate.call("SetSaveDisabled", itemsToSend); // Make sure the help item is not disabled for(var itemIdx in itemsList) { if("$HELP" == itemsList[itemIdx].text) { item[itemIdx].disabled = false; } } CategoryList.UpdateList(); } private function requestInputMappings(a_updateOnly: Boolean): Void { MappingList.entryList.splice(0); GameDelegate.call("RequestInputMappings", [MappingList.entryList]); MappingList.entryList.sort(inputMappingSort); if (a_updateOnly) MappingList.UpdateList(); else MappingList.InvalidateData(); } } ================================================ FILE: src/PauseMenu/quest_journal/DOMDocument.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/ButtonArt.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/ButtonBG.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/ButtonPanel.xml ================================================ ]]> ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/DialogButton.xml ================================================ TEXT TEXT TEXT ]]> ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/Divider.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/Graphic/ButtonBG Shape.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/InputMappingArt.xml ================================================ TEXT ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/InputMappingArtBG.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/JournalBottomBarCenterReference.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MappedButton.xml ================================================ TEXT ]]> ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/ButtonArtBackground.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/ConfigPanelFader.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/ConfirmPanel.xml ================================================ ]]> ]]> ]]> ]]> ]]> ]]> ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/ConfirmText.xml ================================================ $Load this game? All unsaved progress will be lost. ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/EquipIcon.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/HelpList.xml ================================================ ]]> ]]> ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/HelpListEntry.xml ================================================ HELP TOPIC HELP TOPIC ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/HelpListPanel.xml ================================================ ]]> ]]> ]]> ]]> ]]> ]]> ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/HelpTextButtonArtHolder.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/HelpTextHolder.xml ================================================ HELP TOPIC ]]> ]]> ]]> ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/HelpTextPanel.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/InputMappingList.xml ================================================ ]]> ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/InputMappingListEntry.xml ================================================ Label ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/InputMappingListScrollArrow.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/InputMappingPanel.xml ================================================ ]]> ]]> ]]> ]]> ]]> ]]> ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/JournalBackground.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/JournalBottomBar.xml ================================================ Time, Date, Year ]]> ]]> ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/JournalTab.xml ================================================ BUTTON TEXT BUTTON TEXT BUTTON TEXT ]]> ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/JournalTabEnd.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/LevelMeterRect.xml ================================================ 10 $LEVEL ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/LevelProgressBar.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/MeterBar.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/MeterBarBackground.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/MeterBarColor.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/MeterMask.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/ObjectiveListItem.xml ================================================ Objective Text Objective Text Objective Text Objective Text Objective Text Objective Text Objective Text Objective Text ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/ObjectiveScrollingList.xml ================================================ ]]> ]]> ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/ObjectivesHeader.xml ================================================ $OBJECTIVES ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/OptionStepperArrowBtn.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/OptionsLists.xml ================================================ ]]> ]]> ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/OptionsListsList.xml ================================================ ]]> ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/OptionsListsListEntry.xml ================================================ ]]> ]]> ]]> ]]> Label ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/OptionsListsPanel.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/PCQuitList.xml ================================================ ]]> ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/PCQuitListEntry.xml ================================================ Label Label ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/PCQuitPanel.xml ================================================ ]]> ]]> ]]> ]]> ]]> ]]> ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/PlayerInfoText.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/QuestJournalBase.xml ================================================ ]]> ]]> ]]> ]]> ]]> ]]> ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/QuestJournalFader.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/QuestTitleEndpieces.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/QuestTitleHolder.xml ================================================ ]]> ]]> ]]> ]]> ]]> ]]> ]]> ]]> ]]> ]]> ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/QuestTitleList.xml ================================================ ]]> ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/QuestTitleListEntry.xml ================================================ QUEST TEXT ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/QuestTitleListEntryCentered.xml ================================================ SELECTED QUEST ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/QuestTitleListEntryDivider.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/QuestsFader.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/QuestsPage.xml ================================================ Quest description text. TITLE ]]> ]]> ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/SaveLoadList.xml ================================================ ]]> ]]> ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/SaveLoadListEntry.xml ================================================ 000 000 Place Name Place Name ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/SaveLoadPanel.xml ================================================ ]]> ]]> ]]> ]]> ]]> ]]> ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/ScreenshotHolder.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/ScrollableText.xml ================================================ Help text goes here! ]]> ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/SettingsCheckBox.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/SettingsCheckBoxBackground.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/SettingsCheckBoxCheck.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/SettingsList.xml ================================================ ]]> ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/SettingsListEntry.xml ================================================ CATEGORY CATEGORY ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/SettingsOptionStepper.xml ================================================ OPTION ]]> ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/SettingsPanel.xml ================================================ ]]> ]]> ]]> ]]> ]]> ]]> ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/StatsCategoryListEntry.xml ================================================ CATEGORY ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/StatsCategoryListEntryCentered.xml ================================================ CATEGORY ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/StatsCategoryListHolder.xml ================================================ ]]> ]]> ]]> ]]> ]]> ]]> ]]> ]]> ]]> ]]> ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/StatsCategoryListList.xml ================================================ ]]> ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/StatsFader.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/StatsList.xml ================================================ ]]> ]]> ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/StatsListEntry.xml ================================================ VALUE Category Name ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/StatsPage.xml ================================================ ]]> ]]> ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/SystemCategoriesList.xml ================================================ ]]> ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/SystemCategoriesListEntry.xml ================================================ CATEGORY ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/SystemCategoriesListEntryCentered.xml ================================================ SELECTED CATEGORY ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/SystemCategoryList.xml ================================================ ]]> ]]> ]]> ]]> ]]> ]]> ]]> ]]> ]]> ]]> ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/SystemFader.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/MovieClips/SystemPage.xml ================================================ <version> ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/Shapes/BackgroundRect.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/Shapes/Endpieces_DLC01.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/Shapes/Endpieces_DLC02.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/Shapes/MeterBackground.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/Shapes/Shape 122.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/Shapes/Shape 398.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/Shapes/Shape 400.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/Shapes/Shape 407.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/Shapes/Shape 409.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/Shapes/Shape 411.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/Shapes/Shape 414.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/Shapes/Shape 417.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/Shapes/Shape 432.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/Shapes/Shape 433.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/Shapes/Shape 435.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/Shapes/Shape 439.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/Shapes/Shape 440.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/Shapes/Shape 441.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/Shapes/Shape 442.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/Shapes/Shape 443.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/Shapes/Shape 444.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/Shapes/Shape 445.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/Shapes/Shape 446.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/Shapes/Shape 447.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/Shapes/Shape 468.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/Shapes/Shape 493.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/Shapes/Shape 499.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/Shapes/Shape 505.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/Shapes/Shape 507.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/Shapes/Shape 541.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/Shapes/Shape 548.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/Shapes/Shape 552.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/Shapes/Shape 556.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/Shapes/Shape 558.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/Shapes/Shape 560.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/Shapes/Shape 562.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/Shapes/Shape 569.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/Shapes/Shape 571.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/Shapes/Shape 573.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/Shapes/Shape 575.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/Shapes/Shape 577.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/TextArea.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/scrollBar.xml ================================================ ]]> ]]> ]]> ]]> ]]> ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/scrollBarAssets/scrollBarGraphics/scrollBarOption_thumb_shape.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/scrollBarAssets/scrollBarGraphics/scrollBar_cap_shape.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/scrollBarAssets/scrollBarGraphics/scrollBar_thumb_shape.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/scrollBarAssets/scrollBarGraphics/scrollBar_track_shape.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/scrollBarAssets/scrollBarOption_thumb.xml ================================================ ]]> ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/scrollBarAssets/scrollBar_downArrow.xml ================================================ ]]> ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/scrollBarAssets/scrollBar_thumb.xml ================================================ ]]> ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/scrollBarAssets/scrollBar_track.xml ================================================ ]]> ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/scrollBarAssets/scrollBar_upArrow.xml ================================================ ]]> ================================================ FILE: src/PauseMenu/quest_journal/LIBRARY/scrollBarOption.xml ================================================ ]]> ]]> ]]> ]]> ]]> ================================================ FILE: src/PauseMenu/quest_journal/META-INF/metadata.xml ================================================ Adobe Flash CS4 Professional 2011-12-12T12:48:35Z 2021-10-30T15:01:56+08:00 2021-10-30T15:01:56+08:00 application/vnd.adobe.fla xmp.iid:E307A1A1EBC5E811BD99E8D9DEB06D6C xmp.did:86B470DFAE24E1118A1BB716BAE455BA xmp.did:86B470DFAE24E1118A1BB716BAE455BA xmp.did:94C3E5734A39EC11BF58C9ACE5BFC4EF xmp.iid:96C3E5734A39EC11BF58C9ACE5BFC4EF xmp.did:86B470DFAE24E1118A1BB716BAE455BA saved xmp.iid:86B470DFAE24E1118A1BB716BAE455BA 2011-12-12T12:56:07Z Adobe Flash CS4 Professional / created xmp.iid:05BD622883B5E8119DB9A3102D19C3D5 2011-12-12T12:48:35Z Adobe Flash Professional CS6 - build 481 created xmp.iid:6731F41887B5E8119DB9A3102D19C3D5 2011-12-12T12:48:35Z Adobe Flash Professional CS6 - build 481 created xmp.iid:1A0E510B1AC3E811A10D972EADDA1FE9 2011-12-12T12:48:35Z Adobe Flash Professional CS6 - build 481 created xmp.iid:A3EC38F82BC3E811A10D972EADDA1FE9 2011-12-12T12:48:35Z Adobe Flash Professional CS6 - build 481 created xmp.iid:F64EA5A9A0C3E811A10D972EADDA1FE9 2011-12-12T12:48:35Z Adobe Flash Professional CS6 - build 481 created xmp.iid:E307A1A1EBC5E811BD99E8D9DEB06D6C 2011-12-12T12:48:35Z Adobe Flash Professional CS6 - build 481 created xmp.iid:94C3E5734A39EC11BF58C9ACE5BFC4EF 2011-12-12T12:48:35Z Adobe Flash Professional CS6 - build 481 created xmp.iid:96C3E5734A39EC11BF58C9ACE5BFC4EF 2011-12-12T12:48:35Z Adobe Flash Professional CS6 - build 481 ================================================ FILE: src/PauseMenu/quest_journal/MobileSettings.xml ================================================ ================================================ FILE: src/PauseMenu/quest_journal/PublishSettings.xml ================================================ 0 1 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 0 ../../build/quest_journal.swf quest_journal.exe quest_journal.app quest_journal.html quest_journal.gif quest_journal.jpg quest_journal.png quest_journal.mov quest_journal.smil ../../build/quest_journal.swc 0 12,0,0,0;11,2,0,0;11,1,0,0;10,3,0,0;10,2,153,0;10,1,52,0;9,0,124,0;8,0,24,0;7,0,14,0;6,0,79,0;5,0,58,0;4,0,32,0;3,0,8,0;2,0,1,12;1,0,0,1; 1 1 quest_journal.xfl_content.html quest_journal.xfl_alternate.html 0 1280 720 0 0 1 0 0 1 1 4 0 0 1 0 C:\Users\odie\AppData\Local\Adobe\Flash CS6\en_US\Configuration\HTML\Default.html 1 0 0 0 80 0 0 7 0 7 0 15 FlashPlayer11.2 2 1 ../Common;../CLIK;.;$(LocalData)/Classes CONFIG::FLASH_AUTHORING="true"; 0 1 0 1 0 0 0 0 0 4 0 AS3 1 1 0 15 0 0 4 rsl wrap $(AppConfig)/ActionScript 3.0/rsls/loader_animation.swf $(AppConfig)/ActionScript 3.0/libs merge $(AppConfig)/ActionScript 3.0/libs/11.0/textLayout.swc rsl http://fpdownload.adobe.com/pub/swz/tlf/2.0.0.232/textLayout_2.0.0.232.swz http://fpdownload.adobe.com/pub/swz/crossdomain.xml textLayout_2.0.0.232.swz $(AppConfig)/ActionScript 3.0/libs/11.0/textLayout.swc http://fpdownload.adobe.com/pub/swz/tlf/2.0.0.232/textLayout_2.0.0.232.swz http://fpdownload.adobe.com/pub/swz/crossdomain.xml textLayout_2.0.0.232.swz 1280 720 0 4718592 0 80 1 1 0 1 0 0 100000 1 1 0 0 0 0 0 0 1 1280 720 0 1 1 0 1 0 1 0 0 128 255 1280 720 1 0 0 1 0 0 1 24-bit with Alpha 255 1280 720 1 0 00000000 0 0 0 0 1 ================================================ FILE: src/PauseMenu/quest_journal/quest_journal.xfl ================================================ PROXY-CS5 ================================================ FILE: src/Resources/buttonArt/DOMDocument.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/ButtonArt.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/ButtonArtBackgrounds/BackgroundBig.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/ButtonArtBackgrounds/BackgroundLarge.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/ButtonArtBackgrounds/BackgroundLeft.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/ButtonArtBackgrounds/BackgroundMedium.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/ButtonArtBackgrounds/BackgroundRight.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/ButtonArtBackgrounds/BackgroundRound.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/ButtonArtBackgrounds/BackgroundSmall.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Controller/360/Back.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Controller/360/LB.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Controller/360/LS.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Controller/360/LSPress.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Controller/360/LT.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Controller/360/RB.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Controller/360/RS.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Controller/360/RSPress.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Controller/360/RT.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Controller/PS3/Circle.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Controller/PS3/L1.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Controller/PS3/L2.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Controller/PS3/L3.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Controller/PS3/PS3X.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Controller/PS3/R1.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Controller/PS3/R2.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Controller/PS3/R3.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Controller/PS3/Select.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Controller/PS3/Square.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Controller/PS3/Triangle.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Controller/Start.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/FunctionKeys/Alt.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/FunctionKeys/Backspace.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/FunctionKeys/BackspaceWithArrow.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/FunctionKeys/Caps.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/FunctionKeys/Ctrl.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/FunctionKeys/Del.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/FunctionKeys/End.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/FunctionKeys/Enter.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/FunctionKeys/EnterWithArrow.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/FunctionKeys/Esc.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/FunctionKeys/F1.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/FunctionKeys/F10.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/FunctionKeys/F11.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/FunctionKeys/F12.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/FunctionKeys/F2.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/FunctionKeys/F3.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/FunctionKeys/F4.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/FunctionKeys/F5.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/FunctionKeys/F6.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/FunctionKeys/F7.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/FunctionKeys/F8.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/FunctionKeys/F9.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/FunctionKeys/Home.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/FunctionKeys/Ins.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/FunctionKeys/LAlt.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/FunctionKeys/LCtrl.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/FunctionKeys/NumLck.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/FunctionKeys/Pause.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/FunctionKeys/PgDn.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/FunctionKeys/PgUp.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/FunctionKeys/PrtSc.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/FunctionKeys/RAlt.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/FunctionKeys/RCtrl.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/FunctionKeys/ScrLck.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/FunctionKeys/Shift.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/FunctionKeys/ShiftWithArrow.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/FunctionKeys/Space.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/FunctionKeys/Tab.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Letters/A.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Letters/B.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Letters/C.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Letters/D.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Letters/E.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Letters/F.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Letters/G.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Letters/H.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Letters/I.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Letters/J.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Letters/K.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Letters/L.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Letters/M.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Letters/N.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Letters/O.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Letters/P.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Letters/Q.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Letters/R.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Letters/S.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Letters/T.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Letters/U.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Letters/V.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Letters/W.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Letters/X.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Letters/Y.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Letters/Z.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Mouse/MouseButtons/M1.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Mouse/MouseButtons/M2.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Mouse/MouseButtons/M3.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Mouse/MouseButtons/M4.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Mouse/MouseButtons/M5.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Mouse/MouseButtons/M6.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Mouse/MouseButtons/M7.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Mouse/MouseButtons/M8.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Mouse/MouseMove.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Mouse/MouseWheel/MouseWheel.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Mouse/MouseWheel/MouseWheelDown.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Mouse/MouseWheel/MouseWheelUp.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Action_Double_Up.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Action_Up.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Action_Up_Arrow.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/OCC BUTTON BASE CIRCLE.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/OCC BUTTON BASE SQUARE.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/OCC BUTTON MOD BASE 1.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/OCC BUTTON MOD BASE 2.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/OCC BUTTON MOD BASE 3.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/OCC BUTTON MOD BASE 4.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/OCC CONTROLLER MC.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/OCC CONTROLLER.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/OCC MOTION.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/OCC THUM REST RIGHT BASE.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/OCC THUMB REST BASE.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/OCC THUMB REST LEFT BASE.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/OCC THUMB_REST.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/OCC THUMB_REST_LEFT.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/OCC THUMB_REST_RIGHT.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/OCC_A.xml ================================================ A A ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/OCC_A_HOLD.xml ================================================ Hold Hold ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/OCC_B.xml ================================================ B B ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/OCC_B_HOLD.xml ================================================ Hold Hold ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/OCC_X.xml ================================================ X X ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/OCC_X_HOLD.xml ================================================ Hold Hold ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/OCC_Y.xml ================================================ Y Y ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/OCC_Y_HOLD.xml ================================================ Hold Hold ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 163.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 164.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 170.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 171.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 258.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 259.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 260.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 261.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 262.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 264.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 266.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 267.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 268.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 270.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 271.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 272.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 273.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 274.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 275.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 276.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 277.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 278.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 279.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 280.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 281.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 282.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 284.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 285.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 286.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 287.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 288.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 289.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 290.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 291.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 292.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 293.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 294.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 295.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 296.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 297.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 298.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 299.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 302.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 304.xml ================================================ Hold Hold ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 305.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 306.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 307.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 308.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 309.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 310.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 311.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 312.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 313.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 314.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 315.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 316.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 318.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 319.xml ================================================ Hold Hold ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 320.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 321.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 322.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 323.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 324.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 325.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 326.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 327.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 328.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 329.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 330.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 331.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 332.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 333.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 334.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 335.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 336.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 337.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 338.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 339.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 340.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 341.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 342.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 343.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 344.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 345.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 346.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 347.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 348.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 349.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 350.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 351.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 352.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 353.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 354.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 355.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 356.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 357.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 358.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 359.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 36.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 360.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 361.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 362.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 363.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 364.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 365.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 366.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 367.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 368.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 369.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 370.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 371.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 372.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 373.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 374.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 375.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 376.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 377.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 378.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 379.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 380.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 381.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 382.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 383.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 384.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 385.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 386.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 387.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 388.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 389.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 390.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 391.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 392.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 393.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 394.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 395.xml ================================================ Hold Hold ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 396.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 397.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 398.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 399.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 400.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 401.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 402.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 403.xml ================================================ Hold Hold ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 404.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 406.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 407.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 409.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 412.xml ================================================ Grip Grip ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 413.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 414.xml ================================================ Grip Grip ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 415.xml ================================================ Grip Grip Hold Hold ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 417.xml ================================================ Grip Grip ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 420.xml ================================================ Grab Grab ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 421.xml ================================================ Grab Grab ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 422.xml ================================================ Grab Grab Hold Hold ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 423.xml ================================================ Grab Grab ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 424.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 425.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 426.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 427.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 428.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 429.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 430.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 431.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 432.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 433.xml ================================================ Hold Hold ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 434.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 435.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 436.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 437.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 438.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 439.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 440.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 441.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 442.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 443.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 445.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 446.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 447.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 448.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 449.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 451.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 452.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 453.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 454.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 455.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 457.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 458.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 459.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 460.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 462.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 465.xml ================================================ C C ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 466.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 467.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 468.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 469.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 470.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 471.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 472.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 473.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 474.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 475.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 476.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 477.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 478.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 479.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 480.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 481.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 482.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 483.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 484.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 485.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 486.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 487.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 488.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 489.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 490.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 491.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 492.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 493.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 494.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 495.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 496.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 497.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 498.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 499.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 500.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 501.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 502.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 503.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 504.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 505.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 506.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 507.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 508.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 509.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 510.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 511.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 512.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 513.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 514.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 515.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 516.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 517.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 518.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 519.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 520.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 521.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 522.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 523.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 524.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 525.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 526.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 527.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 528.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 529.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 530.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 531.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 532.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 533.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 534.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 535.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 536.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 537.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 538.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 539.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 540.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 541.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 543.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 544.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 545.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 546.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 547.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 548.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 549.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 550.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 551.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 552.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 553.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Named Icons/Symbol 555.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/NumberPad/NP0.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/NumberPad/NP1.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/NumberPad/NP2.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/NumberPad/NP3.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/NumberPad/NP4.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/NumberPad/NP5.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/NumberPad/NP6.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/NumberPad/NP7.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/NumberPad/NP8.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/NumberPad/NP9.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/NumberPad/NPAsterisk.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/NumberPad/NPEnter.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/NumberPad/NPForwardSlash.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/NumberPad/NPMinus.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/NumberPad/NPPeriod.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/NumberPad/NPPlus.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Numbers/0.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Numbers/1.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Numbers/2.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Numbers/3.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Numbers/4.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Numbers/5.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Numbers/6.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Numbers/7.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Numbers/8.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Numbers/9.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Symbols/Amersand.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Symbols/Arrow.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Symbols/Asterisk.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Symbols/At.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Symbols/BackSlash.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Symbols/BrokenBar.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Symbols/Caret.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Symbols/Colon.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Symbols/Comma.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Symbols/Dollar Sign.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Symbols/Equals.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Symbols/Exclamation.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Symbols/ForwardSlash.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Symbols/Grave.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Symbols/GreaterThan.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Symbols/LeftCurlyBracket.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Symbols/LeftParenthesis.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Symbols/LeftSquareBracket.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Symbols/LessThan.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Symbols/Minus.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Symbols/Negation.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Symbols/Number.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Symbols/Percent.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Symbols/Period.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Symbols/Plus Original.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Symbols/Plus.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Symbols/Pound.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Symbols/Question.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Symbols/Quotation.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Symbols/RightCurlyBracket.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Symbols/RightParenthesis.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Symbols/RightSquareBracket.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Symbols/SemiColon.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Symbols/SingleQuote.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Symbols/Tilde.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Symbols/Underscore.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Symbols/Unknown.xml ================================================ ================================================ FILE: src/Resources/buttonArt/LIBRARY/Symbols/VerticalBar.xml ================================================ ================================================ FILE: src/Resources/buttonArt/META-INF/metadata.xml ================================================ Adobe Flash CS4 Professional 2012-07-28T23:24:59+01:00 2021-11-10T22:16:41+08:00 2021-11-10T22:16:41+08:00 application/vnd.adobe.fla xmp.iid:651B82C62F42EC119843FECE3E3F8DD6 xmp.did:F216964DEFD8E111AD4AF18A9CE578B4 xmp.did:F216964DEFD8E111AD4AF18A9CE578B4 xmp.did:48EE966A3042EC119843FECE3E3F8DD6 xmp.iid:48EE966A3042EC119843FECE3E3F8DD6 xmp.did:F216964DEFD8E111AD4AF18A9CE578B4 created xmp.iid:F216964DEFD8E111AD4AF18A9CE578B4 2012-07-28T23:25:16+01:00 Adobe Flash CS4 Professional created xmp.iid:224A94E383B6E81191FEDF04AA088F4B 2012-07-28T23:24:59+01:00 Adobe Flash Professional CS6 - build 481 created xmp.iid:7129409B99B6E811ADBA847149D102AF 2012-07-28T23:24:59+01:00 Adobe Flash Professional CS6 - build 481 created xmp.iid:6444DFC80CB7E811ABE4CA8355120988 2012-07-28T23:24:59+01:00 Adobe Flash Professional CS6 - build 481 created xmp.iid:0AD9144C31C1E811A10D972EADDA1FE9 2012-07-28T23:24:59+01:00 Adobe Flash Professional CS6 - build 481 created xmp.iid:BEDFC9FC82C5E811BD99E8D9DEB06D6C 2012-07-28T23:24:59+01:00 Adobe Flash Professional CS6 - build 481 created xmp.iid:651B82C62F42EC119843FECE3E3F8DD6 2012-07-28T23:24:59+01:00 Adobe Flash Professional CS6 - build 481 saved xmp.iid:48EE966A3042EC119843FECE3E3F8DD6 2021-11-10T22:16:41+08:00 Adobe Flash Professional CS6 - build 481 / ================================================ FILE: src/Resources/buttonArt/MobileSettings.xml ================================================ ================================================ FILE: src/Resources/buttonArt/PublishSettings.xml ================================================ 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 ..\..\build\skyui\buttonArt.swf buttonArt.exe buttonArt.app buttonArt.html buttonArts.gif buttonArt.jpg buttonArt.png buttonArt.mov buttonArt.smil ..\..\build\skyui\buttonArt.swc 0 10,0,2,0;12,0,0,0;11,2,0,0;11,1,0,0;10,3,0,0;10,2,153,0;10,1,52,0;9,0,124,0;8,0,24,0;7,0,14,0;6,0,79,0;5,0,58,0;4,0,32,0;3,0,8,0;2,0,1,12;1,0,0,1; 1 1 buttonArt.xfl_content.html buttonArt.xfl_alternate.html 0 550 400 0 0 1 0 0 1 1 4 0 0 1 0 C:\Users\Owner\AppData\Local\Adobe\Flash CS4\en\Configuration\HTML\Default.html 1 0 0 0 80 0 0 7 0 7 0 15 FlashPlayer11.2 2 1 $(LocalData)\Classes . CONFIG::FLASH_AUTHORING="true"; 0 1 0 1 0 0 0 0 2 4 4096 AS3 1 1 0 15 1 0 4102 rsl wrap $(AppConfig)/ActionScript 3.0/rsls/loader_animation.swf $(AppConfig)/ActionScript 3.0/libs merge . external $(AppConfig)/ActionScript 3.0/libs/11.0/textLayout.swc rsl http://fpdownload.adobe.com/pub/swz/tlf/2.0.0.232/textLayout_2.0.0.232.swz http://fpdownload.adobe.com/pub/swz/crossdomain.xml textLayout_2.0.0.232.swz $(AppConfig)/ActionScript 3.0/libs/11.0/textLayout.swc http://fpdownload.adobe.com/pub/swz/tlf/2.0.0.232/textLayout_2.0.0.232.swz http://fpdownload.adobe.com/pub/swz/crossdomain.xml textLayout_2.0.0.232.swz 550 400 0 4718592 0 80 1 1 0 1 0 0 100000 1 1 0 0 0 0 0 0 1 550 400 0 1 1 1 0 1 0 0 128 255 550 400 1 0 0 1 0 0 1 24-bit with Alpha 255 550 400 1 0 00000000 0 0 0 0 1 ================================================ FILE: src/Resources/buttonArt/buttonArt.xfl ================================================ PROXY-CS5 ================================================ FILE: src/version.as ================================================ // History // // Release Index // 3.0-alpha4 1 // 3.0-alpha5 2 // 3.0-alpha6 3 // 3.0-beta1 4 // 3.0-beta2 5 // 3.0-beta3 6 // 3.0 7 // 3.1 8 // 3.2 9 // 3.3 10 // 3.4 11 // 4.0-beta1 12 // 4.0-beta2 13 // 4.0-beta3 14 // 4.0 15 // 4.1 16 public static var SKYUI_RELEASE_IDX: Number = 2018; public static var SKYUI_VERSION_MAJOR: Number = 5; public static var SKYUI_VERSION_MINOR: Number = 2; public static var SKYUI_VERSION_STRING: String = (SKYUI_VERSION_MAJOR + "." + SKYUI_VERSION_MINOR + " SE"); //public static var SKYUI_VERSION_ALPHA: Number = 7; //public static var SKYUI_VERSION_STRING: String = (SKYUI_VERSION_MAJOR + "." + SKYUI_VERSION_MINOR + "-alpha" + SKYUI_VERSION_ALPHA); //public static var SKYUI_VERSION_BETA: Number = 3; //public static var SKYUI_VERSION_STRING: String = (SKYUI_VERSION_MAJOR + "." + SKYUI_VERSION_MINOR + "-beta" + SKYUI_VERSION_BETA);