Skip to content

Commit

Permalink
Clean up rotation tab UI
Browse files Browse the repository at this point in the history
  • Loading branch information
jimmyt857 committed Jul 4, 2023
1 parent 17741fe commit aa17435
Show file tree
Hide file tree
Showing 9 changed files with 178 additions and 48 deletions.
113 changes: 93 additions & 20 deletions ui/core/components/individual_sim_ui/rotation_tab.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,22 @@
import { IndividualSimUI } from "../../individual_sim_ui";
import { IndividualSimUI, InputSection } from "../../individual_sim_ui";
import {
Consumes,
Cooldowns,
Debuffs,
IndividualBuffs,
PartyBuffs,
Profession,
RaidBuffs,
Spec,
Stat
} from "../../proto/common";
import { ActionId } from "../../proto_utils/action_id";
import { EventID, TypedEvent } from "../../typed_event";
import { getEnumValues } from "../../utils";
import { Player } from "../../player";

import { ContentBlock } from "../content_block";
import { SimTab } from "../sim_tab";
import { NumberPicker } from "../number_picker";
import { BooleanPicker } from "../boolean_picker";
import { EnumPicker } from "../enum_picker";
import { Input } from "../input";
import { MultiIconPicker } from "../multi_icon_picker";
import { IconPickerConfig } from "../icon_picker";
import { TypedIconPickerConfig } from "../input_helpers";
import { ItemSwapPicker } from "../item_swap_picker";
import { CooldownsPicker } from "./cooldowns_picker";
import { CustomRotationPicker } from "./custom_rotation_picker";

import * as IconInputs from '../icon_inputs.js';
import * as Tooltips from '../../constants/tooltips.js';

import { APLRotationPicker } from "./apl_rotation_picker";

Expand All @@ -47,26 +41,45 @@ export class RotationTab extends SimTab {
this.contentContainer.appendChild(this.rightPanel);

this.buildTabContent();

this.updateSections();
this.simUI.player.rotationChangeEmitter.on(() => this.updateSections());
}

protected buildTabContent() {
this.buildHeader();
this.buildContent();
this.buildRotationSettings();
this.buildCooldownSettings();
}

private updateSections() {
if (this.simUI.player.aplRotation.enabled) {
this.rootElem.classList.add('rotation-type-apl');
this.rootElem.classList.remove('rotation-type-legacy');
} else {
this.rootElem.classList.remove('rotation-type-apl');
this.rootElem.classList.add('rotation-type-legacy');
}
}

private buildHeader() {
const header = document.createElement('div');
header.classList.add('rotation-tab-header');
this.leftPanel.appendChild(header);

new BooleanPicker(header, this.simUI.player, {
label: 'Use APL Rotation',
labelTooltip: 'Enables the APL Rotation options.',
new EnumPicker(header, this.simUI.player, {
label: 'Rotation Type',
labelTooltip: 'Whether to use the legacy rotation options, or the new APL rotation options.',
inline: true,
values: [
{value: 0, name: 'Legacy'},
{value: 1, name: 'APL'},
],
changedEvent: (player: Player<any>) => player.rotationChangeEmitter,
getValue: (player: Player<any>) => player.aplRotation.enabled,
setValue: (eventID: EventID, player: Player<any>, newValue: boolean) => {
player.aplRotation.enabled = newValue;
getValue: (player: Player<any>) => Number(player.aplRotation.enabled),
setValue: (eventID: EventID, player: Player<any>, newValue: number) => {
player.aplRotation.enabled = !!newValue;
player.rotationChangeEmitter.emit(eventID);
},
});
Expand All @@ -79,4 +92,64 @@ export class RotationTab extends SimTab {

new APLRotationPicker(content, this.simUI, this.simUI.player);
}

private buildRotationSettings() {
const contentBlock = new ContentBlock(this.leftPanel, 'rotation-settings', {
header: {title: 'Rotation'}
});

const rotationIconGroup = Input.newGroupContainer();
rotationIconGroup.classList.add('rotation-icon-group', 'icon-group');
contentBlock.bodyElement.appendChild(rotationIconGroup);

if (this.simUI.individualConfig.rotationIconInputs?.length) {
this.configureIconSection(
rotationIconGroup,
this.simUI.individualConfig.rotationIconInputs.map(iconInput => IconInputs.buildIconInput(rotationIconGroup, this.simUI.player, iconInput)),
true
);
}

this.configureInputSection(contentBlock.bodyElement, this.simUI.individualConfig.rotationInputs);

contentBlock.bodyElement.querySelectorAll('.input-root').forEach(elem => {
elem.classList.add('input-inline');
})
}

private buildCooldownSettings() {
const contentBlock = new ContentBlock(this.leftPanel, 'cooldown-settings', {
header: {title: 'Cooldowns', tooltip: Tooltips.COOLDOWNS_SECTION}
});

new CooldownsPicker(contentBlock.bodyElement, this.simUI.player);
}

private configureInputSection(sectionElem: HTMLElement, sectionConfig: InputSection) {
sectionConfig.inputs.forEach(inputConfig => {
if (inputConfig.type == 'number') {
new NumberPicker(sectionElem, this.simUI.player, inputConfig);
} else if (inputConfig.type == 'boolean') {
new BooleanPicker(sectionElem, this.simUI.player, {...inputConfig, ...{cssScheme: this.simUI.cssScheme}});
} else if (inputConfig.type == 'enum') {
new EnumPicker(sectionElem, this.simUI.player, inputConfig);
} else if (inputConfig.type == 'customRotation') {
new CustomRotationPicker(sectionElem, this.simUI, this.simUI.player, inputConfig);
} else if (inputConfig.type == 'itemSwap'){
new ItemSwapPicker(sectionElem, this.simUI, this.simUI.player, inputConfig)
}
});
}

private configureIconSection(sectionElem: HTMLElement, iconPickers: Array<any>, adjustColumns?: boolean) {
if (iconPickers.length == 0) {
sectionElem.classList.add('hide');
} else if (adjustColumns) {
if (iconPickers.length <= 4) {
sectionElem.style.gridTemplateColumns = `repeat(${iconPickers.length}, 1fr)`;
} else if (iconPickers.length > 4 && iconPickers.length < 8) {
sectionElem.style.gridTemplateColumns = `repeat(${Math.ceil(iconPickers.length / 2)}, 1fr)`;
}
}
}
}
12 changes: 9 additions & 3 deletions ui/core/components/individual_sim_ui/settings_tab.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { SavedEncounter, SavedSettings } from "../../proto/ui";
import { EventID, TypedEvent } from "../../typed_event";
import { getEnumValues } from "../../utils";
import { Player } from "../../player";
import { aplLaunchStatuses, LaunchStatus } from '../../launched_sims';

import { ContentBlock } from "../content_block";
import { EncounterPicker } from '../encounter_picker.js';
Expand Down Expand Up @@ -81,12 +82,16 @@ export class SettingsTab extends SimTab {
this.buildEncounterSettings();
}

this.buildRotationSettings();
if (aplLaunchStatuses[this.simUI.player.spec] == LaunchStatus.Unlaunched) {
this.buildRotationSettings();
}

this.buildPlayerSettings();
this.buildCustomSettingsSections();
this.buildConsumesSection();
this.buildCooldownSettings();
if (aplLaunchStatuses[this.simUI.player.spec] == LaunchStatus.Unlaunched) {
this.buildCooldownSettings();
}
this.buildOtherSettings();

if (!this.simUI.isWithinRaidSim) {
Expand Down Expand Up @@ -132,7 +137,8 @@ export class SettingsTab extends SimTab {
}

private buildPlayerSettings() {
const contentBlock = new ContentBlock(this.column2, 'player-settings', {
const column = aplLaunchStatuses[this.simUI.player.spec] == LaunchStatus.Unlaunched ? this.column2 : this.column1;
const contentBlock = new ContentBlock(column, 'player-settings', {
header: {title: 'Player'}
});

Expand Down
2 changes: 2 additions & 0 deletions ui/core/components/input_helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ function makeWrappedBooleanInput<SpecType extends Spec, ModObject>(config: Wrapp
setValue: (eventID: EventID, player: Player<SpecType>, newValue: boolean) => config.setValue(eventID, getModObject(player), newValue),
enableWhen: config.enableWhen ? (player: Player<SpecType>) => config.enableWhen!(getModObject(player)) : undefined,
showWhen: config.showWhen ? (player: Player<SpecType>) => config.showWhen!(getModObject(player)) : undefined,
extraCssClasses: config.extraCssClasses,
}
}
export interface PlayerBooleanInputConfig<SpecType extends Spec, Message> extends BasePlayerConfig<SpecType, boolean> {
Expand Down Expand Up @@ -118,6 +119,7 @@ function makeWrappedNumberInput<SpecType extends Spec, ModObject>(config: Wrappe
setValue: (eventID: EventID, player: Player<SpecType>, newValue: number) => config.setValue(eventID, getModObject(player), newValue),
enableWhen: config.enableWhen ? (player: Player<SpecType>) => config.enableWhen!(getModObject(player)) : undefined,
showWhen: config.showWhen ? (player: Player<SpecType>) => config.showWhen!(getModObject(player)) : undefined,
extraCssClasses: config.extraCssClasses,
}
}
export interface PlayerNumberInputConfig<SpecType extends Spec, Message> extends BasePlayerConfig<SpecType, number> {
Expand Down
7 changes: 5 additions & 2 deletions ui/core/individual_sim_ui.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { simLaunchStatuses } from './launched_sims';
import { aplLaunchStatuses, LaunchStatus, simLaunchStatuses } from './launched_sims';
import { Player } from './player';
import { SimUI, SimWarning } from './sim_ui';
import { EventID, TypedEvent } from './typed_event';
Expand Down Expand Up @@ -187,6 +187,7 @@ export abstract class IndividualSimUI<SpecType extends Spec> extends SimUI {
spec: player.spec,
knownIssues: config.knownIssues,
launchStatus: simLaunchStatuses[player.spec],
noticeText: aplLaunchStatuses[player.spec] == LaunchStatus.Alpha || aplLaunchStatuses[player.spec] == LaunchStatus.Beta ? 'Rotation settings have been moved to the \'Rotation\' tab, where experimental APL options are also available. Try them out!' : undefined,
});
this.rootElem.classList.add('individual-sim-ui');
this.player = player;
Expand Down Expand Up @@ -277,7 +278,9 @@ export abstract class IndividualSimUI<SpecType extends Spec> extends SimUI {
this.bt = this.addBulkTab();
this.addSettingsTab();
this.addTalentsTab();
//this.addRotationTab();
if (aplLaunchStatuses[this.player.spec] != LaunchStatus.Unlaunched) {
this.addRotationTab();
}

if (!this.isWithinRaidSim) {
this.addDetailedResultsTab();
Expand Down
25 changes: 25 additions & 0 deletions ui/core/launched_sims.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,31 @@ export const simLaunchStatuses: Record<Spec, LaunchStatus> = {
[Spec.SpecTankDeathknight]: LaunchStatus.Launched,
};

// Alpha and Beta show an info notice at the top of the page.
export const aplLaunchStatuses: Record<Spec, LaunchStatus> = {
[Spec.SpecBalanceDruid]: LaunchStatus.Unlaunched,
[Spec.SpecFeralDruid]: LaunchStatus.Unlaunched,
[Spec.SpecFeralTankDruid]: LaunchStatus.Unlaunched,
[Spec.SpecRestorationDruid]: LaunchStatus.Unlaunched,
[Spec.SpecElementalShaman]: LaunchStatus.Unlaunched,
[Spec.SpecEnhancementShaman]: LaunchStatus.Unlaunched,
[Spec.SpecRestorationShaman]: LaunchStatus.Unlaunched,
[Spec.SpecHunter]: LaunchStatus.Unlaunched,
[Spec.SpecMage]: LaunchStatus.Unlaunched,
[Spec.SpecRogue]: LaunchStatus.Unlaunched,
[Spec.SpecHolyPaladin]: LaunchStatus.Unlaunched,
[Spec.SpecProtectionPaladin]: LaunchStatus.Unlaunched,
[Spec.SpecRetributionPaladin]: LaunchStatus.Unlaunched,
[Spec.SpecHealingPriest]: LaunchStatus.Unlaunched,
[Spec.SpecShadowPriest]: LaunchStatus.Unlaunched,
[Spec.SpecSmitePriest]: LaunchStatus.Unlaunched,
[Spec.SpecWarlock]: LaunchStatus.Unlaunched,
[Spec.SpecWarrior]: LaunchStatus.Unlaunched,
[Spec.SpecProtectionWarrior]: LaunchStatus.Unlaunched,
[Spec.SpecDeathknight]: LaunchStatus.Unlaunched,
[Spec.SpecTankDeathknight]: LaunchStatus.Unlaunched,
};

// Meme specs are excluded from title drop-down menu.
export const memeSpecs: Array<Spec> = [
Spec.SpecSmitePriest,
Expand Down
36 changes: 16 additions & 20 deletions ui/core/sim_ui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import { SimTab } from './components/sim_tab.js';
import { BaseModal } from './components/base_modal.js';

const URLMAXLEN = 2048;
const noticeText = '';
const globalKnownIssues = [
'Wowhead tooltips may not correctly display Tier 8 set bonuses when combining 10 and 25 player tier pieces.'
]
Expand All @@ -33,6 +32,7 @@ export interface SimUIConfig {
spec: Spec | null,
launchStatus: LaunchStatus,
knownIssues?: Array<string>,
noticeText?: string,
}

// Shared UI for all individual sims and the raid sim.
Expand Down Expand Up @@ -60,7 +60,21 @@ export abstract class SimUI extends Component {
this.cssClass = config.cssClass;
this.cssScheme = config.cssScheme;
this.isWithinRaidSim = this.rootElem.closest('.within-raid-sim') != null;
this.rootElem.innerHTML = simHTML;
this.rootElem.innerHTML = `
<div class="sim-root">
<div class="sim-bg"></div>
${config.noticeText ? `<div class="notices-banner alert border-bottom mb-0 text-center">${config.noticeText}</div>` : ''}
<aside class="sim-sidebar">
<div class="sim-title"></div>
<div class="sim-sidebar-content">
<div class="sim-sidebar-actions within-raid-sim-hide"></div>
<div class="sim-sidebar-results within-raid-sim-hide"></div>
<div class="sim-sidebar-footer"></div>
</div>
</aside>
<div class="sim-content container-fluid"></div>
</div>
`;
this.simContentContainer = this.rootElem.querySelector('.sim-content') as HTMLElement;
this.simHeader = new SimHeader(this.simContentContainer, this);
this.simMain = document.createElement('main');
Expand Down Expand Up @@ -328,21 +342,3 @@ class CrashModal extends BaseModal {
this.body.querySelector('textarea')?.appendChild(text);
}
}

const simHTML = `
<div class="sim-root">
<div class="sim-bg"></div>
${noticeText ? `<div class="notices-banner alert border-bottom mb-0 text-center">${noticeText}</div>` : ''}
<aside class="sim-sidebar">
<div class="sim-title"></div>
<div class="sim-sidebar-content">
<div class="sim-sidebar-actions within-raid-sim-hide"></div>
<div class="sim-sidebar-results within-raid-sim-hide"></div>
<div class="sim-sidebar-footer"></div>
</div>
</aside>
<div class="sim-content container-fluid">
</div>
</section>
</div>
`;
5 changes: 3 additions & 2 deletions ui/hunter/inputs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,11 @@ export const HunterRotationConfig = {
showWhen: (player: Player<Spec.SpecHunter>) => player.getRotation().type != RotationType.Custom,
}),
InputHelpers.makeRotationNumberInput<Spec.SpecHunter>({
extraCssClasses: ['used-in-apl'],
fieldName: 'timeToTrapWeaveMs',
label: 'Weave Time',
labelTooltip: 'Amount of time, in milliseconds, between when you start moving towards the boss and when you re-engage your ranged autos.',
enableWhen: (player: Player<Spec.SpecHunter>) => (player.getRotation().type != RotationType.Custom && player.getRotation().trapWeave) || (player.getRotation().type == RotationType.Custom && player.getRotation().customRotation?.spells.some(spell => spell.spell == SpellOption.ExplosiveTrap) || false),
labelTooltip: 'Amount of time for Explosive Trap, in milliseconds, between when you start moving towards the boss and when you re-engage your ranged autos.',
enableWhen: (player: Player<Spec.SpecHunter>) => player.aplRotation.enabled || (player.getRotation().type != RotationType.Custom && player.getRotation().trapWeave) || (player.getRotation().type == RotationType.Custom && player.getRotation().customRotation?.spells.some(spell => spell.spell == SpellOption.ExplosiveTrap) || false),
}),
InputHelpers.makeRotationNumberInput<Spec.SpecHunter>({
fieldName: 'steadyShotMaxDelay',
Expand Down
5 changes: 5 additions & 0 deletions ui/scss/core/components/_enum_picker.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.input-inline {
.enum-picker-selector {
width: auto;
}
}
21 changes: 20 additions & 1 deletion ui/scss/core/components/individual_sim_ui/_rotation_tab.scss
Original file line number Diff line number Diff line change
@@ -1,3 +1,22 @@
@use "sass:map";

@import "./apl_rotation_picker";
@import "./apl_rotation_picker";

.rotation-tab-left {
flex-direction: column;
}

.rotation-type-legacy {
.rotation-tab-main {
display: none;
}
}
.rotation-type-apl {
.cooldown-settings {
display: none;
}

.rotation-settings .input-root:not(.used-in-apl) {
display: none;
}
}

0 comments on commit aa17435

Please sign in to comment.