More updates

This commit is contained in:
Bill 2021-07-21 05:31:36 -04:00
parent 918d2eb6bd
commit 8f883bc761
8 changed files with 98 additions and 74 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 229 B

View File

@ -329,6 +329,12 @@
} }
} }
&.sellable-icon {
background-image: url('../images/avatareditor/sellable-icon.png');
width: 17px;
height: 15px;
}
&.chatstyles-icon { &.chatstyles-icon {
background-image: url('../images/chat/styles-icon.png'); background-image: url('../images/chat/styles-icon.png');
width: 17px; width: 17px;

View File

@ -43,22 +43,6 @@ ul {
pointer-events: none; pointer-events: none;
} }
.t-0 {
top: 0 !important;
}
.b-0 {
bottom: 0 !important;
}
.l-0 {
left: 0 !important;
}
.r-0 {
right: 0 !important;
}
.filter-none { .filter-none {
filter: unset !important; filter: unset !important;
} }

View File

@ -1,8 +1,8 @@
import { AvatarDirectionAngle, AvatarEditorFigureCategory, UserFigureComposer } from 'nitro-renderer'; import { AvatarDirectionAngle, AvatarEditorFigureCategory, FigureSetIdsMessageEvent, UserFigureComposer } 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';
import { SendMessageHook } from '../../hooks'; import { CreateMessageHook, SendMessageHook } from '../../hooks';
import { useUiEvent } from '../../hooks/events/ui/ui-event'; import { useUiEvent } from '../../hooks/events/ui/ui-event';
import { NitroCardContentView, NitroCardHeaderView, NitroCardTabsItemView, NitroCardTabsView, NitroCardView } from '../../layout'; import { NitroCardContentView, NitroCardHeaderView, NitroCardTabsItemView, NitroCardTabsView, NitroCardView } from '../../layout';
import { LocalizeText } from '../../utils/LocalizeText'; import { LocalizeText } from '../../utils/LocalizeText';
@ -27,11 +27,41 @@ export const AvatarEditorView: FC<AvatarEditorViewProps> = props =>
const [ figureData, setFigureData ] = useState<FigureData>(null); const [ figureData, setFigureData ] = useState<FigureData>(null);
const [ categories, setCategories ] = useState<Map<string, IAvatarEditorCategoryModel>>(null); const [ categories, setCategories ] = useState<Map<string, IAvatarEditorCategoryModel>>(null);
const [ activeCategory, setActiveCategory ] = useState<IAvatarEditorCategoryModel>(null); const [ activeCategory, setActiveCategory ] = useState<IAvatarEditorCategoryModel>(null);
const [ figureSetIds, setFigureSetIds ] = useState<number[]>([]);
const [ boundFurnitureNames, setBoundFurnitureNames ] = useState<string[]>([]);
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);
const [ isInitalized, setIsInitalized ] = useState(false); const [ isInitalized, setIsInitalized ] = useState(false);
const onAvatarEditorEvent = useCallback((event: AvatarEditorEvent) =>
{
switch(event.type)
{
case AvatarEditorEvent.SHOW_EDITOR:
setIsVisible(true);
setNeedsReset(true);
return;
case AvatarEditorEvent.HIDE_EDITOR:
setIsVisible(false);
return;
case AvatarEditorEvent.TOGGLE_EDITOR:
setIsVisible(prevValue =>
{
const flag = !prevValue;
if(flag) setNeedsReset(true);
return flag;
});
return;
}
}, []);
useUiEvent(AvatarEditorEvent.SHOW_EDITOR, onAvatarEditorEvent);
useUiEvent(AvatarEditorEvent.HIDE_EDITOR, onAvatarEditorEvent);
useUiEvent(AvatarEditorEvent.TOGGLE_EDITOR, onAvatarEditorEvent);
const selectCategory = useCallback((name: string) => const selectCategory = useCallback((name: string) =>
{ {
if(!categories) return; if(!categories) return;
@ -87,34 +117,6 @@ export const AvatarEditorView: FC<AvatarEditorViewProps> = props =>
} }
}, [ figures, figureData ]); }, [ figures, figureData ]);
const onAvatarEditorEvent = useCallback((event: AvatarEditorEvent) =>
{
switch(event.type)
{
case AvatarEditorEvent.SHOW_EDITOR:
setIsVisible(true);
setNeedsReset(true);
return;
case AvatarEditorEvent.HIDE_EDITOR:
setIsVisible(false);
return;
case AvatarEditorEvent.TOGGLE_EDITOR:
setIsVisible(prevValue =>
{
const flag = !prevValue;
if(flag) setNeedsReset(true);
return flag;
});
return;
}
}, []);
useUiEvent(AvatarEditorEvent.SHOW_EDITOR, onAvatarEditorEvent);
useUiEvent(AvatarEditorEvent.HIDE_EDITOR, onAvatarEditorEvent);
useUiEvent(AvatarEditorEvent.TOGGLE_EDITOR, onAvatarEditorEvent);
const clearFigure = useCallback(() => const clearFigure = useCallback(() =>
{ {
loadAvatarInEditor(figureData.getFigureStringWithFace(0, false), figureData.gender, false); loadAvatarInEditor(figureData.getFigureStringWithFace(0, false), figureData.gender, false);
@ -145,6 +147,7 @@ export const AvatarEditorView: FC<AvatarEditorViewProps> = props =>
const saveFigure = useCallback(() => const saveFigure = useCallback(() =>
{ {
SendMessageHook(new UserFigureComposer(figureData.gender, figureData.getFigureString())); SendMessageHook(new UserFigureComposer(figureData.gender, figureData.getFigureString()));
setIsVisible(false);
}, [ figureData ]); }, [ figureData ]);
const setGender = useCallback((gender: string) => const setGender = useCallback((gender: string) =>
@ -154,6 +157,18 @@ export const AvatarEditorView: FC<AvatarEditorViewProps> = props =>
setFigureData(figures.get(gender)); setFigureData(figures.get(gender));
}, [ figures ]); }, [ figures ]);
const onFigureSetIdsMessageEvent = useCallback((event: FigureSetIdsMessageEvent) =>
{
const parser = event.getParser();
setFigureSetIds(parser.figureSetIds);
setBoundFurnitureNames(parser.boundsFurnitureNames);
resetCategories();
}, [ resetCategories ]);
CreateMessageHook(FigureSetIdsMessageEvent, onFigureSetIdsMessageEvent);
useEffect(() => useEffect(() =>
{ {
if(!categories) return; if(!categories) return;
@ -172,6 +187,18 @@ export const AvatarEditorView: FC<AvatarEditorViewProps> = props =>
return () => AvatarEditorUtilities.CURRENT_FIGURE = null; return () => AvatarEditorUtilities.CURRENT_FIGURE = null;
}, [ figureData, resetCategories ]); }, [ figureData, resetCategories ]);
useEffect(() =>
{
AvatarEditorUtilities.FIGURE_SET_IDS = figureSetIds;
AvatarEditorUtilities.BOUND_FURNITURE_NAMES = boundFurnitureNames;
return () =>
{
AvatarEditorUtilities.FIGURE_SET_IDS = null;
AvatarEditorUtilities.BOUND_FURNITURE_NAMES = null;
}
}, [ figureSetIds, boundFurnitureNames ]);
useEffect(() => useEffect(() =>
{ {
if(!isVisible) return; if(!isVisible) return;
@ -194,7 +221,7 @@ export const AvatarEditorView: FC<AvatarEditorViewProps> = props =>
setNeedsReset(false); setNeedsReset(false);
}, [ isVisible, isInitalized, needsReset, loadAvatarInEditor ]); }, [ isVisible, isInitalized, needsReset, loadAvatarInEditor ]);
if(!isVisible) return null; if(!isVisible || !figureData) return null;
return ( return (
<NitroCardView className="nitro-avatar-editor"> <NitroCardView className="nitro-avatar-editor">
@ -215,16 +242,15 @@ export const AvatarEditorView: FC<AvatarEditorViewProps> = props =>
{ activeCategory && <AvatarEditorModelView model={ activeCategory } gender={ figureData.gender } setGender={ setGender } /> } { activeCategory && <AvatarEditorModelView model={ activeCategory } gender={ figureData.gender } setGender={ setGender } /> }
</div> </div>
<div className="col-3 d-flex flex-column h-100"> <div className="col-3 d-flex flex-column h-100">
{ figureData && <div className="figure-preview-container">
<div className="figure-preview-container"> <AvatarEditorFigurePreviewView figureData={ figureData } />
<AvatarEditorFigurePreviewView figureData={ figureData } /> <div className="avatar-spotlight" />
<div className="avatar-spotlight" /> <div className="avatar-shadow" />
<div className="avatar-shadow" /> <div className="arrow-container">
<div className="arrow-container"> <i className="icon arrow-left-icon" onClick={ event => rotateFigure(figureData.direction + 1) } />
<i className="icon arrow-left-icon" onClick={ event => rotateFigure(figureData.direction + 1) } /> <i className="icon arrow-right-icon" onClick={ event => rotateFigure(figureData.direction - 1) } />
<i className="icon arrow-right-icon" onClick={ event => rotateFigure(figureData.direction - 1) } /> </div>
</div> </div>
</div> }
<div className="d-flex flex-column mt-1"> <div className="d-flex flex-column mt-1">
<div className="btn-group mb-1"> <div className="btn-group mb-1">
<button type="button" className="btn btn-sm btn-secondary" onClick={ resetFigure }> <button type="button" className="btn btn-sm btn-secondary" onClick={ resetFigure }>

View File

@ -11,6 +11,8 @@ export class AvatarEditorUtilities
private static MAX_PALETTES: number = 2; private static MAX_PALETTES: number = 2;
public static CURRENT_FIGURE: FigureData = null; public static CURRENT_FIGURE: FigureData = null;
public static FIGURE_SET_IDS: number[] = [];
public static BOUND_FURNITURE_NAMES: string[] = [];
public static getGender(gender: string): string public static getGender(gender: string): string
{ {
@ -33,6 +35,11 @@ export class AvatarEditorUtilities
return gender; return gender;
} }
public static hasFigureSetId(setId: number): boolean
{
return (this.FIGURE_SET_IDS.indexOf(setId) >= 0);
}
public static createCategory(model: CategoryBaseModel, name: string): CategoryData public static createCategory(model: CategoryBaseModel, name: string): CategoryData
{ {
if(!model || !name || !this.CURRENT_FIGURE) return null; if(!model || !name || !this.CURRENT_FIGURE) return null;
@ -145,16 +152,9 @@ export class AvatarEditorUtilities
let isValid = true; let isValid = true;
if(partSet.isSellable) if(partSet.isSellable) isValid = this.hasFigureSetId(partSet.id);
{
isValid = false;
//isValid = (this._inventoryService && this._inventoryService.hasFigureSetId(partSet.id));
}
if(isValid) if(isValid) partItems.push(new AvatarEditorGridPartItem(partSet, partColors, usesColors, isDisabled));
{
partItems.push(new AvatarEditorGridPartItem(partSet, partColors, usesColors, isDisabled));
}
} }
i--; i--;

View File

@ -25,8 +25,9 @@ export const AvatarEditorFigureSetItemView: FC<AvatarEditorFigureSetItemViewProp
return ( return (
<NitroCardGridItemView itemImage={ (partItem.isClear ? undefined : partItem.imageUrl) } itemActive={ partItem.isSelected } onClick={ () => onClick(partItem) }> <NitroCardGridItemView itemImage={ (partItem.isClear ? undefined : partItem.imageUrl) } itemActive={ partItem.isSelected } onClick={ () => onClick(partItem) }>
{ partItem.isHC && <CurrencyIcon type={ 'hc' } /> } { partItem.isHC && <CurrencyIcon className="position-absolute end-1 bottom-1" type={ 'hc' } /> }
{ partItem.isClear && <i className="icon clear-icon" /> } { partItem.isClear && <i className="icon clear-icon" /> }
{ partItem.isSellable && <i className="position-absolute icon sellable-icon end-1 bottom-1" /> }
</NitroCardGridItemView> </NitroCardGridItemView>
); );
} }

View File

@ -1,16 +1,21 @@
import { FC } from 'react'; import { FC, useMemo } from 'react';
import { GetConfiguration } from '../../../api'; import { GetConfiguration } from '../../../api';
import { CurrencyIconProps } from './CurrencyIcon.types'; import { CurrencyIconProps } from './CurrencyIcon.types';
export const CurrencyIcon: FC<CurrencyIconProps> = props => export const CurrencyIcon: FC<CurrencyIconProps> = props =>
{ {
let url = GetConfiguration<string>('currency.asset.icon.url', ''); const { type = '', className = '', style = {}, ...rest } = props;
url = url.replace('%type%', props.type.toString()); const urlString = useMemo(() =>
{
let url = GetConfiguration<string>('currency.asset.icon.url', '');
url = `url(${ url })`; url = url.replace('%type%', type.toString());
return `url(${ url })`;
}, [ type ]);
return ( return (
<div className="nitro-currency-icon" style={ (url && url.length) ? { backgroundImage: url } : {} } /> <div className={ 'nitro-currency-icon ' + className } style={ { ...style, backgroundImage: urlString } } { ...rest } />
); );
} }

View File

@ -1,4 +1,6 @@
export interface CurrencyIconProps import { DetailsHTMLAttributes } from 'react';
export interface CurrencyIconProps extends DetailsHTMLAttributes<HTMLDivElement>
{ {
type: number | string; type: number | string;
} }