Start wardrobe

This commit is contained in:
Bill 2021-07-21 17:53:36 -04:00
parent 5449012069
commit 5d091bebb3
7 changed files with 125 additions and 14 deletions

View File

@ -1,4 +1,5 @@
.nitro-card-grid { .nitro-card-grid {
width: 100%;
.row-cols-3 { .row-cols-3 {

View File

@ -6,13 +6,13 @@ import { NitroCardGridItemViewProps } from './NitroCardGridItemView.types';
export const NitroCardGridItemView: FC<NitroCardGridItemViewProps> = props => export const NitroCardGridItemView: FC<NitroCardGridItemViewProps> = props =>
{ {
const { itemImage = undefined, itemColor = undefined, itemActive = false, itemCount = 1, itemUnique = false, itemUniqueNumber = 0, itemUnseen = false, className = '', style = {}, children = null, ...rest } = props; const { itemImage = undefined, itemColor = undefined, itemActive = false, itemCount = 1, itemUnique = false, itemUniqueNumber = 0, itemUnseen = false, columns = undefined, className = '', style = {}, children = null, ...rest } = props;
const { theme = NitroCardGridThemes.THEME_DEFAULT } = useNitroCardGridContext(); const { theme = NitroCardGridThemes.THEME_DEFAULT } = useNitroCardGridContext();
const imageUrl = `url(${ itemImage })`; const imageUrl = `url(${ itemImage })`;
return ( return (
<div className="col pb-1 grid-item-container"> <div className={ `${ columns === undefined ? 'col' : ('col-' + columns) } pb-1 grid-item-container` }>
<div className={ `grid-item ${ theme } cursor-pointer${ itemActive ? ' active' : '' }${ itemUnique ? ' unique-item' : '' }${ itemUnseen ? ' unseen' : ''}${ (itemImage === null ? ' icon loading-icon': '')} ${ className || '' }` } style={ itemImage ? { ...style, backgroundImage: imageUrl } : (itemColor ? { ...style, backgroundColor: itemColor } : style) } { ...rest }> <div className={ `grid-item ${ theme } cursor-pointer${ itemActive ? ' active' : '' }${ itemUnique ? ' unique-item' : '' }${ itemUnseen ? ' unseen' : ''}${ (itemImage === null ? ' icon loading-icon': '')} ${ className || '' }` } style={ itemImage ? { ...style, backgroundImage: imageUrl } : (itemColor ? { ...style, backgroundColor: itemColor } : style) } { ...rest }>
{ (itemCount > 1) && { (itemCount > 1) &&
<span className="position-absolute badge border bg-danger px-1 rounded-circle">{ itemCount }</span> } <span className="position-absolute badge border bg-danger px-1 rounded-circle">{ itemCount }</span> }

View File

@ -9,4 +9,5 @@ export interface NitroCardGridItemViewProps extends DetailsHTMLAttributes<HTMLDi
itemUnique?: boolean; itemUnique?: boolean;
itemUniqueNumber?: number; itemUniqueNumber?: number;
itemUnseen?: boolean; itemUnseen?: boolean;
columns?: number;
} }

View File

@ -79,4 +79,12 @@
transform: scale(2); transform: scale(2);
} }
} }
.wardrobe-grid {
.grid-item-container {
height: 100% !important;
max-height: 100% !important;
}
}
} }

View File

@ -1,4 +1,4 @@
import { AvatarDirectionAngle, AvatarEditorFigureCategory, FigureSetIdsMessageEvent, UserFigureComposer } from 'nitro-renderer'; import { AvatarDirectionAngle, AvatarEditorFigureCategory, FigureSetIdsMessageEvent, UserFigureComposer, UserWardrobePageComposer, UserWardrobePageEvent } from 'nitro-renderer';
import { FC, useCallback, useEffect, useState } from 'react'; import { FC, useCallback, useEffect, useState } from 'react';
import { GetSessionDataManager } from '../../api'; import { GetSessionDataManager } from '../../api';
import { AvatarEditorEvent } from '../../events/avatar-editor'; import { AvatarEditorEvent } from '../../events/avatar-editor';
@ -16,9 +16,11 @@ import { LegModel } from './common/LegModel';
import { TorsoModel } from './common/TorsoModel'; import { TorsoModel } from './common/TorsoModel';
import { AvatarEditorFigurePreviewView } from './views/figure-preview/AvatarEditorFigurePreviewView'; import { AvatarEditorFigurePreviewView } from './views/figure-preview/AvatarEditorFigurePreviewView';
import { AvatarEditorModelView } from './views/model/AvatarEditorModelView'; import { AvatarEditorModelView } from './views/model/AvatarEditorModelView';
import { AvatarEditorWardrobeView } from './views/wardrobe/AvatarEditorWardrobeView';
const DEFAULT_MALE_FIGURE: string = 'hr-100.hd-180-7.ch-215-66.lg-270-79.sh-305-62.ha-1002-70.wa-2007'; const DEFAULT_MALE_FIGURE: string = 'hr-100.hd-180-7.ch-215-66.lg-270-79.sh-305-62.ha-1002-70.wa-2007';
const DEFAULT_FEMALE_FIGURE: string = 'hr-515-33.hd-600-1.ch-635-70.lg-716-66-62.sh-735-68'; const DEFAULT_FEMALE_FIGURE: string = 'hr-515-33.hd-600-1.ch-635-70.lg-716-66-62.sh-735-68';
const MAX_SAVED_FIGURES: number = 10;
export const AvatarEditorView: FC<AvatarEditorViewProps> = props => export const AvatarEditorView: FC<AvatarEditorViewProps> = props =>
{ {
@ -29,6 +31,8 @@ export const AvatarEditorView: FC<AvatarEditorViewProps> = props =>
const [ activeCategory, setActiveCategory ] = useState<IAvatarEditorCategoryModel>(null); const [ activeCategory, setActiveCategory ] = useState<IAvatarEditorCategoryModel>(null);
const [ figureSetIds, setFigureSetIds ] = useState<number[]>([]); const [ figureSetIds, setFigureSetIds ] = useState<number[]>([]);
const [ boundFurnitureNames, setBoundFurnitureNames ] = useState<string[]>([]); const [ boundFurnitureNames, setBoundFurnitureNames ] = useState<string[]>([]);
const [ savedFigures, setSavedFigures ] = useState<[ string, string ][]>(new Array(MAX_SAVED_FIGURES));
const [ isWardrobeVisible, setIsWardrobeVisible ] = useState(false);
const [ lastFigure, setLastFigure ] = useState<string>(null); const [ lastFigure, setLastFigure ] = useState<string>(null);
const [ lastGender, setLastGender ] = useState<string>(null); const [ lastGender, setLastGender ] = useState<string>(null);
const [ needsReset, setNeedsReset ] = useState(false); const [ needsReset, setNeedsReset ] = useState(false);
@ -62,6 +66,32 @@ export const AvatarEditorView: FC<AvatarEditorViewProps> = props =>
useUiEvent(AvatarEditorEvent.HIDE_EDITOR, onAvatarEditorEvent); useUiEvent(AvatarEditorEvent.HIDE_EDITOR, onAvatarEditorEvent);
useUiEvent(AvatarEditorEvent.TOGGLE_EDITOR, onAvatarEditorEvent); useUiEvent(AvatarEditorEvent.TOGGLE_EDITOR, onAvatarEditorEvent);
const onFigureSetIdsMessageEvent = useCallback((event: FigureSetIdsMessageEvent) =>
{
const parser = event.getParser();
setFigureSetIds(parser.figureSetIds);
setBoundFurnitureNames(parser.boundsFurnitureNames);
}, []);
CreateMessageHook(FigureSetIdsMessageEvent, onFigureSetIdsMessageEvent);
const onUserWardrobePageEvent = useCallback((event: UserWardrobePageEvent) =>
{
const parser = event.getParser();
const savedFigures: [ string, string ][] = new Array(MAX_SAVED_FIGURES);
for(const value of parser.looks.values())
{
console.log(value);
}
setSavedFigures(savedFigures)
}, []);
CreateMessageHook(UserWardrobePageEvent, onUserWardrobePageEvent);
const selectCategory = useCallback((name: string) => const selectCategory = useCallback((name: string) =>
{ {
if(!categories) return; if(!categories) return;
@ -157,17 +187,20 @@ export const AvatarEditorView: FC<AvatarEditorViewProps> = props =>
setFigureData(figures.get(gender)); setFigureData(figures.get(gender));
}, [ figures ]); }, [ figures ]);
const onFigureSetIdsMessageEvent = useCallback((event: FigureSetIdsMessageEvent) => useEffect(() =>
{ {
const parser = event.getParser(); if(!isWardrobeVisible) return;
setFigureSetIds(parser.figureSetIds); setActiveCategory(null);
setBoundFurnitureNames(parser.boundsFurnitureNames); SendMessageHook(new UserWardrobePageComposer());
}, [ isWardrobeVisible ]);
resetCategories(); useEffect(() =>
}, [ resetCategories ]); {
if(!activeCategory) return;
CreateMessageHook(FigureSetIdsMessageEvent, onFigureSetIdsMessageEvent); setIsWardrobeVisible(false);
}, [ activeCategory ]);
useEffect(() => useEffect(() =>
{ {
@ -192,12 +225,14 @@ export const AvatarEditorView: FC<AvatarEditorViewProps> = props =>
AvatarEditorUtilities.FIGURE_SET_IDS = figureSetIds; AvatarEditorUtilities.FIGURE_SET_IDS = figureSetIds;
AvatarEditorUtilities.BOUND_FURNITURE_NAMES = boundFurnitureNames; AvatarEditorUtilities.BOUND_FURNITURE_NAMES = boundFurnitureNames;
resetCategories();
return () => return () =>
{ {
AvatarEditorUtilities.FIGURE_SET_IDS = null; AvatarEditorUtilities.FIGURE_SET_IDS = null;
AvatarEditorUtilities.BOUND_FURNITURE_NAMES = null; AvatarEditorUtilities.BOUND_FURNITURE_NAMES = null;
} }
}, [ figureSetIds, boundFurnitureNames ]); }, [ figureSetIds, boundFurnitureNames, resetCategories ]);
useEffect(() => useEffect(() =>
{ {
@ -227,19 +262,25 @@ export const AvatarEditorView: FC<AvatarEditorViewProps> = props =>
<NitroCardView className="nitro-avatar-editor"> <NitroCardView className="nitro-avatar-editor">
<NitroCardHeaderView headerText={ LocalizeText('avatareditor.title') } onCloseClick={ event => setIsVisible(false) } /> <NitroCardHeaderView headerText={ LocalizeText('avatareditor.title') } onCloseClick={ event => setIsVisible(false) } />
<NitroCardTabsView> <NitroCardTabsView>
{ categories && (categories.size > 0) && activeCategory && Array.from(categories.keys()).map(category => { categories && (categories.size > 0) && Array.from(categories.keys()).map(category =>
{ {
const isActive = (activeCategory && (activeCategory.name === category));
return ( return (
<NitroCardTabsItemView key={ category } isActive={ (activeCategory.name === category) } onClick={ event => selectCategory(category) }> <NitroCardTabsItemView key={ category } isActive={ isActive } onClick={ event => selectCategory(category) }>
{ LocalizeText(`avatareditor.category.${ category }`) } { LocalizeText(`avatareditor.category.${ category }`) }
</NitroCardTabsItemView> </NitroCardTabsItemView>
); );
})} })}
<NitroCardTabsItemView isActive={ isWardrobeVisible } onClick={ event => setIsWardrobeVisible(true) }>
{ LocalizeText(`avatareditor.category.wardrobe`) }
</NitroCardTabsItemView>
</NitroCardTabsView> </NitroCardTabsView>
<NitroCardContentView> <NitroCardContentView>
<div className="row h-100"> <div className="row h-100">
<div className="col-9 d-flex flex-column h-100"> <div className="col-9 d-flex flex-column h-100">
{ activeCategory && <AvatarEditorModelView model={ activeCategory } gender={ figureData.gender } setGender={ setGender } /> } { (activeCategory && !isWardrobeVisible) && <AvatarEditorModelView model={ activeCategory } gender={ figureData.gender } setGender={ setGender } /> }
{ isWardrobeVisible && <AvatarEditorWardrobeView figures={ savedFigures } /> }
</div> </div>
<div className="col-3 d-flex flex-column h-100"> <div className="col-3 d-flex flex-column h-100">
<div className="figure-preview-container"> <div className="figure-preview-container">

View File

@ -0,0 +1,56 @@
import { FC, useMemo } from 'react';
import { NitroCardGridItemView } from '../../../../layout/card/grid/item/NitroCardGridItemView';
import { NitroCardGridView } from '../../../../layout/card/grid/NitroCardGridView';
import { NitroCardGridThemes } from '../../../../layout/card/grid/NitroCardGridView.types';
import { AvatarImageView } from '../../../shared/avatar-image/AvatarImageView';
import { AvatarEditorWardrobeViewProps } from './AvatarEditorWardrobeView.types';
export const AvatarEditorWardrobeView: FC<AvatarEditorWardrobeViewProps> = props =>
{
const { figures = [] } = props;
const savedFigures = useMemo(() =>
{
if(!figures) return [];
let i = 0;
const items: JSX.Element[] = [];
while(i < figures.length)
{
const figure = figures[i];
let figureString = null;
let gender = null;
if(figure)
{
figureString = (figure[0] || null);
gender = (figure[1] || null);
}
items.push(
<NitroCardGridItemView key={ i } columns={ 2 }>
<AvatarImageView figure={ figureString } gender={ gender } />
</NitroCardGridItemView>
);
i++
}
return items;
}, [ figures ]);
console.log(figures.length);
return (
<div className="row h-100">
<div className="col-12 d-flex h-100">
<NitroCardGridView className="wardrobe-grid" columns={ 12 } theme={ NitroCardGridThemes.THEME_DEFAULT }>
{ savedFigures }
</NitroCardGridView>
</div>
</div>
);
}

View File

@ -0,0 +1,4 @@
export interface AvatarEditorWardrobeViewProps
{
figures: [ string, string ][];
}