mirror of
https://github.com/billsonnn/nitro-react.git
synced 2024-11-27 08:00:51 +01:00
More updates
This commit is contained in:
parent
918d2eb6bd
commit
8f883bc761
BIN
src/assets/images/avatareditor/sellable-icon.png
Normal file
BIN
src/assets/images/avatareditor/sellable-icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 229 B |
@ -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;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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,7 +242,6 @@ 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" />
|
||||||
@ -224,7 +250,7 @@ export const AvatarEditorView: FC<AvatarEditorViewProps> = props =>
|
|||||||
<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 }>
|
||||||
|
@ -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--;
|
||||||
|
@ -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>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -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 =>
|
||||||
|
{
|
||||||
|
const { type = '', className = '', style = {}, ...rest } = props;
|
||||||
|
|
||||||
|
const urlString = useMemo(() =>
|
||||||
{
|
{
|
||||||
let url = GetConfiguration<string>('currency.asset.icon.url', '');
|
let url = GetConfiguration<string>('currency.asset.icon.url', '');
|
||||||
|
|
||||||
url = url.replace('%type%', props.type.toString());
|
url = url.replace('%type%', type.toString());
|
||||||
|
|
||||||
url = `url(${ url })`;
|
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 } />
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
export interface CurrencyIconProps
|
import { DetailsHTMLAttributes } from 'react';
|
||||||
|
|
||||||
|
export interface CurrencyIconProps extends DetailsHTMLAttributes<HTMLDivElement>
|
||||||
{
|
{
|
||||||
type: number | string;
|
type: number | string;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user