diff --git a/packages/panorama-types/types/api.d.ts b/packages/panorama-types/types/api.d.ts index 9367fcd..f13a82b 100644 --- a/packages/panorama-types/types/api.d.ts +++ b/packages/panorama-types/types/api.d.ts @@ -29,6 +29,20 @@ declare namespace GameEvents { : InferCustomGameEventType; } +declare namespace PanoramaEvents { + type PanoramaEventName = keyof PanoramaEvent; + type InferPanoramaEventParams = T extends PanoramaEventName + ? PanoramaEvent[T] extends (...args: infer P) => void + ? P | [PanelBase, ...P] + : TUntyped + : TUntyped; + type InferPanoramaCallback = T extends PanoramaEventName + ? PanoramaEvent[T] extends (...args: infer P) => void + ? (...args: P) => void + : (...args: any[]) => void + : (...args: any[]) => void; +} + interface CDOTA_PanoramaScript_GameEvents { /** * Subscribe to a game event. @@ -1972,10 +1986,16 @@ interface DollarStatic { GetContextPanel(): Panel; Schedule(time: number, callback: () => void): ScheduleID; CancelScheduled(scheduledEvent: ScheduleID): void; - DispatchEvent(event: string, panelID?: string, ...args: any[]): void; - DispatchEvent(event: string, panel: PanelBase, ...args: any[]): void; - DispatchEventAsync(delay: number, event: string, panelID?: string, ...args: any[]): void; - DispatchEventAsync(delay: number, event: string, panel: PanelBase, ...args: any[]): void; + + DispatchEvent( + eventName: E extends PanoramaEvents.PanoramaEventName ? E : string, + ...args: PanoramaEvents.InferPanoramaEventParams + ): void; + DispatchEventAsync( + eventName: E extends PanoramaEvents.PanoramaEventName ? E : string, + ...args: PanoramaEvents.InferPanoramaEventParams + ): void; + Language(): string; /** * Localize a string. Optionally accepts Quantity, Precision, and Panel arguments. @@ -1986,18 +2006,16 @@ interface DollarStatic { * @deprecated */ LocalizePlural(token: string, value: number, parent?: PanelBase): string; - RegisterEventHandler( - event: 'DragStart', - parent: PanelBase, - handler: (panelID: string, settings: DragSettings) => boolean, - ): void; - RegisterEventHandler( - event: 'DragEnd' | 'DragDrop' | 'DragEnter' | 'DragLeave', - parent: PanelBase, - handler: (panelID: string, dragged: Panel) => boolean, + + RegisterEventHandler( + eventName: E extends PanoramaEvents.PanoramaEventName ? E : string, + panel: PanelBase | string, + callback: PanoramaEvents.InferPanoramaCallback, ): void; - RegisterEventHandler(event: string, parent: PanelBase, handler: (...args: any[]) => void): void; - RegisterForUnhandledEvent(event: string, handler: (...args: any[]) => void): UnhandledEventListenerID; + RegisterForUnhandledEvent( + eventName: E extends PanoramaEvents.PanoramaEventName ? E : string, + callback: PanoramaEvents.InferPanoramaCallback, + ): UnhandledEventListenerID; UnregisterForUnhandledEvent(event: string, handle: UnhandledEventListenerID): void; Each(list: T[], callback: (item: T, index: number) => void): void; Each(map: { [key: string]: T }, callback: (value: T, key: string) => void): void; diff --git a/packages/panorama-types/types/common.d.ts b/packages/panorama-types/types/common.d.ts index 326c65f..1dc726f 100644 --- a/packages/panorama-types/types/common.d.ts +++ b/packages/panorama-types/types/common.d.ts @@ -2,6 +2,7 @@ /// /// /// +/// /// type EntityIndex = number & { _entityIndex: never }; diff --git a/packages/panorama-types/types/panorama-events.d.ts b/packages/panorama-types/types/panorama-events.d.ts new file mode 100644 index 0000000..ea936ff --- /dev/null +++ b/packages/panorama-types/types/panorama-events.d.ts @@ -0,0 +1,359 @@ +/** + * Events provided by Valve's document: https://developer.valvesoftware.com/wiki/Dota_2_Workshop_Tools/Panorama/Events + */ +declare interface PanoramaEvent { + /** Add a CSS class to a panel. */ + AddStyle(className: string): void; + + /** Add a CSS class to a panel after a specified delay. */ + AddStyleAfterDelay(className: string, preDelay: number): void; + + /** Add a CSS class to all children of this panel. */ + AddStyleToEachChild(className: string): void; + + /** Add a class for a specified duration, with optional pre-delay; clears existing timers when called with same class. */ + AddTimedStyle(className: string, duration: number, preDelay: number): void; + + /** Fire another event after a delay (in seconds, the event is provided in string and parsed by javascript engine). */ + AsyncEvent(delay: number, event: string): void; + + /** Tip to display, panel to attach to (default 'DefaultTipAttachment') */ + DOTADisplayDashboardTip(str: string, panelName?: string): void; + + /** Hide the ability tooltip */ + DOTAHideAbilityTooltip(): void; + + /** Hide the buff tooltip */ + DOTAHideBuffTooltip(): void; + + /** Hide the dropped item tooltip */ + DOTAHideDroppedItemTooltip(): void; + + /** Hide the econ item tooltip. */ + DOTAHideEconItemTooltip(): void; + + /** Hide the profile card / battle cup tooltip. */ + DOTAHideProfileCardBattleCupTooltip(): void; + + /** Hide the profile card tooltip. */ + DOTAHideProfileCardTooltip(panel: PanelBase): void; + + /** Hide the rank tier tooltip. */ + DOTAHideRankTierTooltip(): void; + + /** Hide the rune tooltip. */ + DOTAHideRuneTooltip(): void; + + /** Hide the text tooltip. */ + DOTAHideTextTooltip(): void; + + /** Hide the ti10 event game tooltip. */ + DOTAHideTI10EventGameTooltip(): void; + + /** Hide the title image text tooltip. */ + DOTAHideTitleImageTextTooltip(): void; + + /** Hide the title text tooltip. */ + DOTAHideTitleTextTooltip(): void; + + /** Show tooltip for an item in the entityIndex NPC's inventory. */ + DOTAShowAbilityInventoryItemTooltip(entityIndex: EntityIndex, inventorySlot: number): void; + + /** Show tooltip for an item in the entityIndex NPC's shop. */ + DOTAShowAbilityShopItemTooltip( + panel: PanelBase, + abilityName: string, + guideName: string, + entityIndex: EntityIndex, + ): void; + + /** Show an ability tooltip. */ + DOTAShowAbilityTooltip(abilityName: string): void; + + /** Show an ability tooltip. Level information comes from the entity specified by the entityIndex. */ + DOTAShowAbilityTooltipForEntityIndex(abilityName: string, entityIndex: EntityIndex): void; + + /** Show an ability tooltip annotated with a particular guide's info. */ + DOTAShowAbilityTooltipForGuide(abilityName: string, guideName: string): void; + + /** Show an ability tooltip for the specified hero. */ + DOTAShowAbilityTooltipForHero(abilityName: string, heroid: EntityIndex, bOnEnemy: boolean): void; + + /** Show an ability tooltip for a specific level. */ + DOTAShowAbilityTooltipForLevel(abilityName: string, level: number): void; + + /** Show a buff tooltip for the specified entityIndex + buff serial. */ + DOTAShowBuffTooltip(entityIndex: EntityIndex, buffSerial: BuffID, bOnEnemy: boolean): void; + + /** Show the econ item tooltip for a given item, style, and hero. Use 0 for the default style, and -1 for the default hero. */ + DOTAShowEconItemTooltip(itemDef: string, styleIndex: number, heroID: number): void; + + /** Show the battle cup portion of the user's profile card, if it exists */ + DOTAShowProfileCardBattleCupTooltip(steamID: number): void; + + /** Show a user's profile card. Use pro name determines whether to use their professional team name if applicable. */ + DOTAShowProfileCardTooltip(steamID: number, useProName: boolean): void; + + /** Show the rank tier tooltip for a user */ + DOTAShowRankTierTooltip(steamID: number): void; + + /** Show a rune tooltip in the X Y location for the rune type */ + DOTAShowRuneTooltip(X: number, Y: number, RuneType: number): void; + + /** Show a tooltip with the given text. */ + DOTAShowTextTooltip(text: string): void; + + /** Show a tooltip with the given text. Also apply a CSS class named "style" to allow custom styling. */ + DOTAShowTextTooltipStyled(text: string, style: string): void; + + /** Show a tooltip with the given title, image, and text. */ + DOTAShowTitleImageTextTooltip(title: string, imagePath: string, text: string): void; + + /** Show a tooltip with the given title, image, and text. Also apply a CSS class named "style" to allow custom styling. */ + DOTAShowTitleImageTextTooltipStyled( + panel: PanelBase, + title: string, + imagePath: string, + text: string, + style: string, + ): void; + + /** Show a tooltip with the given title and text. */ + DOTAShowTitleTextTooltip(title: string, text: string): void; + + /** Show a tooltip with the given title and text. Also apply a CSS class named "style" to allow custom styling. */ + DOTAShowTitleTextTooltipStyled(title: string, text: string, style: string): void; + + /** Drop focus entirely from the window containing this panel. */ + DropInputFocus(): void; + + /** Fire another event if this panel has a given class. */ + IfHasClassEvent(className: string, event: string): void; + + /** Fire another event if this panel is hovered over. */ + IfHoverOtherEvent(otherPanelID: string, event: string): void; + + /** Fire another event if this panel does not have a given class. */ + IfNotHasClassEvent(className: string, event: string): void; + + /** Fire another event if this panel is not hovered over. */ + IfNotHoverOtherEvent(otherPanelID: string, event: string): void; + + /** Move down from the panel. By default, this will change the focus position, but other panel types may implement this differently. */ + MovePanelDown(repeatCount: number): void; + + /** Move left from the panel. By default, this will change the focus position, but other panel types may implement this differently. */ + MovePanelLeft(repeatCount: number): void; + + /** Move right from the panel. By default, this will change the focus position, but other panel types may implement this differently. */ + MovePanelRight(repeatCount: number): void; + + /** Move up from the panel. By default, this will change the focus position, but other panel types may implement this differently. */ + MovePanelUp(repeatCount: number): void; + + /** Scroll the panel down by one page. */ + PageDown(): void; + + /** Scroll the panel left by one page. */ + PageLeft(): void; + + /** Scroll the panel right by one page. */ + PageRight(): void; + + /** Scroll the panel up by one page. */ + PageUp(): void; + + /** Scroll the panel down by one page. */ + PagePanelDown(panel: PanelBase): void; + + /** Scroll the panel left by one page. */ + PagePanelLeft(panel: PanelBase): void; + + /** Scroll the panel right by one page. */ + PagePanelRight(panel: PanelBase): void; + + /** Scroll the panel up by one page. */ + PagePanelUp(panel: PanelBase): void; + + /** Remove a CSS class from a panel. */ + RemoveStyle(className: string): void; + + /** Remove a CSS class from a panel after a specified delay. */ + RemoveStyleAfterDelay(className: string, preDelay: number): void; + + /** Remove a CSS class from all children of this panel. */ + RemoveStyleFromEachChild(className: string): void; + + /** Scroll the panel down by one line. */ + ScrollDown(): void; + + /** Scroll the panel left by one line. */ + ScrollLeft(): void; + + /** Scroll the panel right by one line. */ + ScrollRight(): void; + + /** Scroll the panel up by one line. */ + ScrollUp(): void; + + /** Scroll the panel down by one line. */ + ScrollPanelDown(panel: PanelBase): void; + + /** Scroll the panel left by one line. */ + ScrollPanelLeft(panel: PanelBase): void; + + /** Scroll the panel right by one line. */ + ScrollPanelRight(panel: PanelBase): void; + + /** Scroll the panel up by one line. */ + ScrollPanelUp(panel: PanelBase): void; + + /** Scroll this panel to the bottom. */ + ScrollToBottom(): void; + + /** Scroll this panel to the top. */ + ScrollToTop(): void; + + /** Set whether any child panels are :selected. */ + SetChildPanelsSelected(selected: boolean): void; + + /** Set focus to this panel. */ + SetInputFocus(panel: PanelBase): void; + + /** Sets whether the given panel is enabled */ + SetPanelEnabled(enabled: boolean): void; + + /** Set whether this panel is :selected. */ + SetPanelSelected(selected: boolean): void; + + /** Switch which class the panel has for a given attribute slot. Allows easily changing between multiple states. */ + SwitchStyle(slot: string, className: string): void; + + /** Toggle whether this panel is :selected. */ + TogglePanelSelected(panel: PanelBase): void; + + /** Toggle whether a panel has the given CSS class. */ + ToggleStyle(className: string): void; + + /** Remove then immediately add back a CSS class from a panel. Useful to re-trigger events like animations or sound effects. */ + TriggerStyle(className: string): void; +} + +/** + * Dota Panorama Events collect in DotA2 xml files + */ +declare interface PanoramaEvent { + DOTAScenePanelSceneLoaded(panel: PanelBase): void; + DOTAScenePanelSceneUnloaded(panel: PanelBase): void; + DOTAScenePanelCameraLerpFinished(panel: PanelBase): void; + DOTAScenePanelSetRotationSpeed(speed: number): void; + DOTASceneFireEntityInput( + panel: PanelBase, + entityName: string, + eventName: string, + eventParam: string | number, + ): void; + DOTAScenePanelSimulateWorld(num: number): void; + DOTAScenePanelEntityClicked(entityName: string): void; + DOTAScenePanelEntityMouseOver(entityName: string): void; + DOTAScenePanelEntityMouseOut(entityName: string): void; + DOTASceneSetCameraEntity(entityName: string, delay: number): void; + DOTAScenePanelResetRotation(): void; + DOTAGlobalSceneFireEntityInput(entityName: string, eventName: string, eventParam: string | number): void; + DOTAGlobalSceneSetCameraEntity(sceneId: string, entityName: string, delay: number): void; + DOTAGlobalSceneSetRootEntity(sceneId: string, entityName: string): void; + DOTAScenePanelDumpState(): void; + DOTAShowReferencePage(xmlPath: string): void; + DOTAShowReferencePageStyled(xmlPath: string, styleClass: string): void; + DOTAHUDShopOpened(shopType: DOTA_SHOP_TYPE, opened: boolean): void; + DOTAHUDToggleShop(): void; + DOTAShopCancelSearch(): void; + DOTAHUDToggleScoreboard(): void; + DOTAHUDShowScoreboard(): void; + DOTAHUDHideScoreboard(): void; + DOTAShowHomePage(): void; +} + +/** + * UNDOCUMENTED BUT USEFUL EVENTS + */ +declare interface PanoramaEvent { + /** Dismiss all context menus */ + DismissAllContextMenus(): void; + + /** Built in browser goto the provided url. (will return to the dashboard) */ + BrowserGoToURL(url: string): void; + + /** Open your default browser and goto url. */ + ExternalBrowserGoToURL(url: string): void; + + /** Show custom layout parameters tooltip, layout is the xml file, the parameters are contacted with & symbol. */ + UIShowCustomLayoutParametersTooltip(toolipId: string, xmlFile: string, parameters: string): void; + + /** Hide custom layout parameters tooltip. */ + UIHideCustomLayoutParametersTooltip(toolipId: string): void; + + /** Show custom layout tooltip, layout is the xml file. */ + UIShowCustomLayoutTooltip(toolipId: string, xmlFile: string): void; + + /** Hide custom layout tooltip */ + UIHideCustomLayoutTooltip(toolipId: string): void; + + UIHideCustomLayoutTooltip(toolipId: string): void; + + UIShowCustomLayoutPopup(id: string, xmlPath: string): void; + + UIShowTextTooltip(text: string): void; + + UIShowTextTooltip(text: string): void; + + UIHideTextTooltip(): void; + + /** Click the disconnect icon */ + DOTAHUDGameDisconnect(): void; + + /** Show the match details screen for the provided match id. */ + DOTAShowMatchDetails(matchId: number): void; + + /** Play a sound effect. */ + PlaySoundEffect(sound: string): void; + + /** Popup button is clicked */ + UIPopupButtonClicked(panel: PanelBase): void; + + /** Fire a game event clientside? */ + FireCustomGameEvent_Str(eventName: string, data: string | number): void; + + /** display the damage armor tooltip */ + DOTAHUDShowDamageArmorTooltip(): void; + + /** hide the damage armor tooltip */ + DOTAHUDHideDamageArmorTooltip(): void; + + /** Show gold tooltip */ + DOTAHUDShowGoldTooltip(): void; + + /** Hide gold tooltip */ + DOTAHUDHideGoldTooltip(): void; + + /** Buff icon is clicked */ + DOTAHUDBuffClicked(): void; + + /** Go back to dashboard */ + DOTAHUDShowDashboard(): void; + + /** Show the settings popup panel */ + DOTAShowSettingsPopup(): void; + + /** Show the dropped item tooltip */ + DOTAShowDroppedItemTooltip(x: number, y: number, abilityName: string, playerId: PlayerID, unknown: boolean): void; + + /** + * Drag events + */ + DragStart(panel: PanelBase, settings: DragSettings): void; + DragEnter(panel: PanelBase, displayPanel: PanelBase): void; + DragLeave(panel: PanelBase, displayPanel: PanelBase): void; + DragDrop(panel: PanelBase, displayPanel: PanelBase): void; + DragEnd(panel: PanelBase, displayPanel: PanelBase): void; +} diff --git a/test/panorama/panorama-events.ts b/test/panorama/panorama-events.ts new file mode 100644 index 0000000..67fc177 --- /dev/null +++ b/test/panorama/panorama-events.ts @@ -0,0 +1,53 @@ +/** + * The following code segments require correct parameters to be provided, + * as they are frequently used and the parameters are already predefined in panorama-events.d.ts. + */ +$.DispatchEvent('BrowserGoToURL', 'test'); +$.DispatchEvent('AddStyle', $('#test'), 'test_class'); +$.DispatchEvent('DOTAGlobalSceneSetCameraEntity', 'ModelBackground', 'dashboard_cam', 4); +$.DispatchEvent('PlaySoundEffect', 'playercard.card_to_dust'); +$.DispatchEvent('PlaySoundEffect', $.GetContextPanel(), 'playercard.card_to_dust'); + +// @ts-expect-error +$.DispatchEvent('AddStyle', $('#test')); +// @ts-expect-error +$.DispatchEvent('DOTAGlobalSceneSetCameraEntity', 'ModelBackground', 'dashboard_cam', '4'); + +/** + * The following code are syntactically legal + * since certain parameters may not be covered by standard validations + * programmers must explicitly validate parameter correctness themselves. + */ +$.DispatchEvent('DOTASetCurrentDashboardPageFullscreen', true); +$.DispatchEvent('UnknownEvent', 'test'); + +/** + * Test of register event handlers + */ +$.RegisterEventHandler('DragStart', $('#test'), (panelId, settings) => {}); +$.RegisterEventHandler('DragStart', $('#test'), () => {}); +// @ts-expect-error +$.RegisterEventHandler('DragStart', $('#test'), (panelId, settings, badParam) => {}); + +$.RegisterEventHandler('UnknownEvent', $('#test'), () => {}); + +$.RegisterForUnhandledEvent('DOTAHUDBuffClicked', () => {}); +// @ts-expect-error +$.RegisterForUnhandledEvent('DOTAHUDBuffClicked', (panel) => {}); + +// users can define their own events and parameters. +declare global { + interface PanoramaEvent { + TestCustomEvent(panel: PanelBase, text: string): void; + } +} + +$.DispatchEvent('TestCustomEvent', $('#test'), 'some string'); +// @ts-expect-error +$.DispatchEvent('TestCustomEvent', $('#test'), 2); +// @ts-expect-error +$.DispatchEvent('TestCustomEvent', $('#test'), 2); +// @ts-expect-error +$.DispatchEvent('TestCustomEvent', $('#test'), 'string', 2); + +export {};