Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New stat tier editor #9992

Merged
merged 15 commits into from
Oct 30, 2023
1 change: 1 addition & 0 deletions .stylelintrc
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"at-rule-no-unknown": null,
"scss/at-rule-no-unknown": true,
"media-feature-name-no-unknown": null,
"selector-not-notation": null,
"selector-pseudo-class-no-unknown": [true, { "ignorePseudoClasses": ["horizontal", "global"] }],
"hue-degree-notation": "number",
"selector-id-pattern": "(^[a-z][a-zA-Z0-9]+$|^([a-z][a-z0-9]*)(-[a-z0-9]+)*$)",
Expand Down
2 changes: 2 additions & 0 deletions config/feature-flags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ export function makeFeatureFlags(env: { release: boolean; beta: boolean; dev: bo
customStatWeights: false,
// Allow for non-default visual themes
themePicker: true,
// New LO stat picker
statConstraintEditor: !env.release,
};
}

Expand Down
6 changes: 5 additions & 1 deletion config/i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -631,7 +631,11 @@
"MaxTier": "Max {{tier}}",
"UnableToAddAllMods": "Unable to add all mods.",
"UnableToAddAllModsBody": "There weren't enough mod slots available to fit {{mods}}.",
"UnlockItem": "Unpin Item"
"UnlockItem": "Unpin Item",
"IncreaseStatPriority": "Increase stat priority",
"DecreaseStatPriority": "Decrease stat priority",
"IgnoreStat": "If unchecked, Loadout Optimizer will pretend this stat doesn't exist when building sets",
"TierSelect": "Select minimum stat tier"
},
"Loadouts": {
"Abilities": "Abilities",
Expand Down
4 changes: 2 additions & 2 deletions src/app/dim-ui/Dropdown.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Placement } from '@popperjs/core';
import { kebabIcon, moveDownIcon } from 'app/shell/icons';
import { expandDownIcon, kebabIcon } from 'app/shell/icons';
import AppIcon from 'app/shell/icons/AppIcon';
import clsx from 'clsx';
import { useSelect } from 'downshift';
Expand Down Expand Up @@ -91,7 +91,7 @@ export default function Dropdown({
<AppIcon icon={kebabIcon} />
) : (
<>
{children} <AppIcon icon={moveDownIcon} className={styles.arrow} />
{children} <AppIcon icon={expandDownIcon} className={styles.arrow} />
</>
)}
</button>
Expand Down
4 changes: 4 additions & 0 deletions src/app/dim-ui/PressTip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,10 @@ export function PressTip(props: Props) {

// Fires on both pointerenter and pointerdown - does double duty for handling both hover tips and press tips
const hover = useCallback((e: React.PointerEvent) => {
if (e.type === 'pointerenter' && e.buttons !== 0) {
// Ignore hover events when the mouse is down
return;
}
e.preventDefault();
// If we're already hovering, don't start hovering again
if (
Expand Down
4 changes: 2 additions & 2 deletions src/app/dim-ui/Select.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { moveDownIcon, moveUpIcon } from 'app/shell/icons';
import { expandDownIcon, expandUpIcon } from 'app/shell/icons';
import AppIcon from 'app/shell/icons/AppIcon';
import clsx from 'clsx';
import { useSelect } from 'downshift';
Expand Down Expand Up @@ -131,7 +131,7 @@ export default function Select<T>({
{children ?? (
<>
{selectedItem.content}{' '}
<AppIcon icon={isOpen ? moveUpIcon : moveDownIcon} className={styles.arrow} />
<AppIcon icon={isOpen ? expandUpIcon : expandDownIcon} className={styles.arrow} />
</>
)}
</button>
Expand Down
4 changes: 4 additions & 0 deletions src/app/loadout-builder/LoadoutBuilder.m.scss
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@
}
}

.wide {
--page-with-menu-menu-width: 320px;
}

.toolbar {
display: flex;
flex-flow: row wrap;
Expand Down
1 change: 1 addition & 0 deletions src/app/loadout-builder/LoadoutBuilder.m.scss.d.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 25 additions & 7 deletions src/app/loadout-builder/LoadoutBuilder.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import { querySelector, useIsPhonePortrait } from 'app/shell/selectors';
import { emptyObject } from 'app/utils/empty';
import { isClassCompatible, itemCanBeEquippedBy } from 'app/utils/item-utils';
import { DestinyClass } from 'bungie-api-ts/destiny2';
import clsx from 'clsx';
import { PlugCategoryHashes } from 'data/d2/generated-enums';
import { deepEqual } from 'fast-equals';
import { Dispatch, memo, useCallback, useEffect, useMemo, useRef } from 'react';
Expand All @@ -54,6 +55,7 @@ import {
LoadoutOptimizerPinnedItems,
loMenuSection,
} from './filter/LoadoutOptimizerMenuItems';
import StatConstraintEditor from './filter/StatConstraintEditor';
import TierSelect from './filter/TierSelect';
import CompareLoadoutsDrawer from './generated-sets/CompareLoadoutsDrawer';
import GeneratedSets from './generated-sets/GeneratedSets';
Expand All @@ -68,6 +70,7 @@ import {
LockableBucketHashes,
loDefaultArmorEnergyRules,
} from './types';
import useEquippedHashes from './useEquippedHashes';

/**
* The Loadout Optimizer screen
Expand Down Expand Up @@ -288,6 +291,8 @@ export default memo(function LoadoutBuilder({
const handleAutoStatModsChanged = (autoStatMods: boolean) =>
lbDispatch({ type: 'autoStatModsChanged', autoStatMods });

const equippedHashes = useEquippedHashes(loadout.parameters!, subclass);

// I don't think this can actually happen?
if (!selectedStore) {
return null;
Expand All @@ -303,11 +308,20 @@ export default memo(function LoadoutBuilder({
</div>
)}
<UndoRedoControls canRedo={canRedo} canUndo={canUndo} lbDispatch={lbDispatch} />
<TierSelect
resolvedStatConstraints={resolvedStatConstraints}
statRangesFiltered={result?.statRangesFiltered}
lbDispatch={lbDispatch}
/>
{$featureFlags.statConstraintEditor ? (
<StatConstraintEditor
resolvedStatConstraints={resolvedStatConstraints}
statRangesFiltered={result?.statRangesFiltered}
lbDispatch={lbDispatch}
equippedHashes={equippedHashes}
/>
) : (
<TierSelect
resolvedStatConstraints={resolvedStatConstraints}
statRangesFiltered={result?.statRangesFiltered}
lbDispatch={lbDispatch}
/>
)}
<EnergyOptions assumeArmorMasterwork={assumeArmorMasterwork} lbDispatch={lbDispatch} />
<div className={loMenuSection}>
<CheckButton
Expand Down Expand Up @@ -383,9 +397,13 @@ export default memo(function LoadoutBuilder({
</>
);

// TODO: replace character select with horizontal choice?

return (
<PageWithMenu className={styles.page}>
<PageWithMenu.Menu className={styles.menuContent}>
<PageWithMenu.Menu
className={clsx(styles.menuContent, { [styles.wide]: $featureFlags.statConstraintEditor })}
>
<CharacterSelect
selectedStore={selectedStore}
stores={stores}
Expand Down Expand Up @@ -444,7 +462,6 @@ export default memo(function LoadoutBuilder({
<GeneratedSets
loadout={loadout}
sets={sortedSets}
subclass={subclass}
lockedMods={result.mods}
pinnedItems={pinnedItems}
selectedStore={selectedStore}
Expand All @@ -455,6 +472,7 @@ export default memo(function LoadoutBuilder({
armorEnergyRules={result.armorEnergyRules}
autoStatMods={autoStatMods}
isEditingExistingLoadout={isEditingExistingLoadout}
equippedHashes={equippedHashes}
/>
) : (
!processing && (
Expand Down
122 changes: 122 additions & 0 deletions src/app/loadout-builder/filter/StatConstraintEditor.m.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
@use '../../variables' as *;

.iconStat {
display: inline-block;
height: 17px;
width: 17px;
}

.grip {
opacity: 0.5;
font-size: 10px;
padding-left: 10px;
align-self: stretch;
composes: flexRow from '../../dim-ui/common.m.scss';
align-items: center;
}

.ignored {
opacity: 0.4;
}

.row {
display: grid;
grid-template-columns: 1fr min-content;
grid-template-areas:
'name buttons'
'bar bar';
gap: 4px 4px;
margin-bottom: 2px;
background-color: black;
align-items: center;
padding: 4px 4px 4px 0;

> * {
white-space: nowrap;
}
}

.name {
grid-area: name;
composes: flexRow from '../../dim-ui/common.m.scss';
align-items: center;
gap: 2px;
}

.label {
display: flex;
flex-direction: row;
align-items: center;
white-space: nowrap;
gap: 2px;
text-overflow: ellipsis;
overflow: hidden;
align-self: stretch;
width: 100%;
}

.statBar {
grid-area: bar;
composes: flexRow from '../../dim-ui/common.m.scss';
margin-left: 4px;
gap: 2px;
}

.statBarSegment {
composes: flexRow from '../../dim-ui/common.m.scss';
flex: 1;
background-color: var(--theme-button-bg);
color: var(--theme-button-text);
font-size: 12px;
height: 24px;
box-sizing: border-box;

/* stylelint-disable-next-line no-descending-specificity */
> * {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
width: 100%;
}

&:hover {
outline: 1px solid var(--theme-accent-primary);
}
}

// Tiers that can't be reached given the currently selected minimums
.maxed:not(.locked):not(.selectedStatBar) {
color: #666;
background-color: rgba(255, 255, 255, 0.1);
}

.selectedStatBar {
background-color: var(--theme-accent-primary);
color: var(--theme-text-invert);
}

.buttons {
composes: flexRow from '../../dim-ui/common.m.scss';
}

.rowControl {
composes: resetButton from '../../dim-ui/common.m.scss';
padding: 4px 6px;
opacity: 0.9;

&.ignored,
&:disabled {
opacity: 0.9;
color: #555;
}

&:hover,
&:focus-visible {
color: var(--theme-accent-primary);
}
}

.dragging {
outline: 1px solid var(--theme-accent-primary);
}
20 changes: 20 additions & 0 deletions src/app/loadout-builder/filter/StatConstraintEditor.m.scss.d.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading