mirror of
https://github.com/billsonnn/nitro-react.git
synced 2025-02-18 18:02:36 +01:00
Add wired furni selector
This commit is contained in:
parent
06af222057
commit
663c84b8ca
27
src/events/wired/WiredSelectObjectEvent.ts
Normal file
27
src/events/wired/WiredSelectObjectEvent.ts
Normal file
@ -0,0 +1,27 @@
|
||||
import { WiredEvent } from './WiredEvent';
|
||||
|
||||
export class WiredSelectObjectEvent extends WiredEvent
|
||||
{
|
||||
public static SELECT_OBJECT: string = 'WE_SELECT_OBJECT';
|
||||
|
||||
private _objectId: number;
|
||||
private _category: number;
|
||||
|
||||
constructor(objectId = -1, category = -1)
|
||||
{
|
||||
super(WiredSelectObjectEvent.SELECT_OBJECT);
|
||||
|
||||
this._objectId = objectId;
|
||||
this._category = category;
|
||||
}
|
||||
|
||||
public get objectId(): number
|
||||
{
|
||||
return this._objectId;
|
||||
}
|
||||
|
||||
public get category(): number
|
||||
{
|
||||
return this._category;
|
||||
}
|
||||
}
|
@ -1 +1,2 @@
|
||||
export * from './WiredEvent';
|
||||
export * from './WiredSelectObjectEvent';
|
||||
|
@ -1,5 +1,7 @@
|
||||
import { IFurnitureData, Nitro, NitroEvent, ObjectDataFactory, PetFigureData, PetType, RoomAdsUpdateComposer, RoomControllerLevel, RoomModerationSettings, RoomObjectCategory, RoomObjectOperationType, RoomObjectType, RoomObjectVariable, RoomSessionPetInfoUpdateEvent, RoomSessionUserBadgesEvent, RoomTradingLevelEnum, RoomUnitDropHandItemComposer, RoomUnitGiveHandItemComposer, RoomUnitGiveHandItemPetComposer, RoomUserData, RoomWidgetEnumItemExtradataParameter, SecurityLevel, Vector3d } from 'nitro-renderer';
|
||||
import { GetConnection, GetRoomEngine, GetSessionDataManager, IsOwnerOfFurniture } from '../../../api';
|
||||
import { WiredSelectObjectEvent } from '../../../events';
|
||||
import { dispatchUiEvent } from '../../../hooks/events';
|
||||
import { LocalizeText } from '../../../utils/LocalizeText';
|
||||
import { RoomWidgetObjectNameEvent, RoomWidgetUpdateEvent, RoomWidgetUpdateInfostandFurniEvent, RoomWidgetUpdateInfostandPetEvent, RoomWidgetUpdateInfostandRentableBotEvent, RoomWidgetUpdateInfostandUserEvent } from '../events';
|
||||
import { RoomWidgetChangeMottoMessage, RoomWidgetFurniActionMessage, RoomWidgetMessage, RoomWidgetRoomObjectMessage, RoomWidgetUserActionMessage } from '../messages';
|
||||
@ -386,10 +388,7 @@ export class RoomWidgetInfostandHandler extends RoomWidgetHandler
|
||||
event.rentCouldBeUsedForBuyout = furnitureData.rentCouldBeUsedForBuyout;
|
||||
event.availableForBuildersClub = furnitureData.availableForBuildersClub;
|
||||
|
||||
// if(this._container.wiredService && (k.category === RoomObjectCategory.FLOOR))
|
||||
// {
|
||||
// this._container.wiredService.selectFurniture(roomObject.id, furnitureData.name);
|
||||
// }
|
||||
dispatchUiEvent(new WiredSelectObjectEvent(event.id, event.category));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,7 @@ export const WiredView: FC<WiredFurniSelectorViewProps> = props =>
|
||||
const [ trigger, setTrigger ] = useState<Triggerable>(null);
|
||||
const [ intParams, setIntParams ] = useState<number[]>(null);
|
||||
const [ stringParam, setStringParam ] = useState<string>(null);
|
||||
const [ furniIds, setFurniIds ] = useState<number[]>(null);
|
||||
const [ furniIds, setFurniIds ] = useState<number[]>([]);
|
||||
const [ actionDelay, setActionDelay ] = useState<number>(null);
|
||||
|
||||
const wiredLayout = useMemo(() =>
|
||||
|
@ -1,13 +1,6 @@
|
||||
import { ConditionDefinition, TriggerDefinition, WiredActionDefinition } from 'nitro-renderer';
|
||||
|
||||
export class WiredFurniSelectorViewProps
|
||||
{}
|
||||
|
||||
export class WiredLayoutViewProps
|
||||
{
|
||||
wiredDefinition: TriggerDefinition | WiredActionDefinition | ConditionDefinition;
|
||||
}
|
||||
|
||||
export class WiredFurniType
|
||||
{
|
||||
public static STUFF_SELECTION_OPTION_NONE: number = 0;
|
||||
|
95
src/views/wired/common/WiredSelectionFilter.ts
Normal file
95
src/views/wired/common/WiredSelectionFilter.ts
Normal file
@ -0,0 +1,95 @@
|
||||
import { ColorConverter, NitroFilter } from 'nitro-renderer';
|
||||
|
||||
const vertex = `
|
||||
attribute vec2 aVertexPosition;
|
||||
attribute vec2 aTextureCoord;
|
||||
uniform mat3 projectionMatrix;
|
||||
varying vec2 vTextureCoord;
|
||||
void main(void)
|
||||
{
|
||||
gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);
|
||||
vTextureCoord = aTextureCoord;
|
||||
}`;
|
||||
|
||||
const fragment = `
|
||||
varying vec2 vTextureCoord;
|
||||
uniform sampler2D uSampler;
|
||||
uniform vec3 lineColor;
|
||||
uniform vec3 color;
|
||||
void main(void) {
|
||||
vec4 currentColor = texture2D(uSampler, vTextureCoord);
|
||||
vec3 colorLine = lineColor * currentColor.a;
|
||||
vec3 colorOverlay = color * currentColor.a;
|
||||
|
||||
if(currentColor.r == 0.0 && currentColor.g == 0.0 && currentColor.b == 0.0 && currentColor.a > 0.0) {
|
||||
gl_FragColor = vec4(colorLine.r, colorLine.g, colorLine.b, currentColor.a);
|
||||
} else if(currentColor.a > 0.0) {
|
||||
gl_FragColor = vec4(colorOverlay.r, colorOverlay.g, colorOverlay.b, currentColor.a);
|
||||
}
|
||||
}`;
|
||||
|
||||
export class WiredSelectionFilter extends NitroFilter
|
||||
{
|
||||
private _lineColor: number;
|
||||
private _color: number;
|
||||
|
||||
constructor(lineColor: number | number[], color: number | number[])
|
||||
{
|
||||
super(vertex, fragment);
|
||||
|
||||
this.uniforms.lineColor = new Float32Array(3);
|
||||
this.uniforms.color = new Float32Array(3);
|
||||
this.lineColor = lineColor;
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
public get lineColor(): number | number[]
|
||||
{
|
||||
return this._lineColor;
|
||||
}
|
||||
|
||||
public set lineColor(value: number | number[])
|
||||
{
|
||||
const arr = this.uniforms.lineColor;
|
||||
|
||||
if(typeof value === 'number')
|
||||
{
|
||||
ColorConverter.hex2rgb(value, arr);
|
||||
|
||||
this._lineColor = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
arr[0] = value[0];
|
||||
arr[1] = value[1];
|
||||
arr[2] = value[2];
|
||||
|
||||
this._lineColor = ColorConverter.rgb2hex(arr);
|
||||
}
|
||||
}
|
||||
|
||||
public get color(): number | number[]
|
||||
{
|
||||
return this._color;
|
||||
}
|
||||
|
||||
public set color(value: number | number[])
|
||||
{
|
||||
const arr = this.uniforms.color;
|
||||
|
||||
if(typeof value === 'number')
|
||||
{
|
||||
ColorConverter.hex2rgb(value, arr);
|
||||
|
||||
this._color = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
arr[0] = value[0];
|
||||
arr[1] = value[1];
|
||||
arr[2] = value[2];
|
||||
|
||||
this._color = ColorConverter.rgb2hex(arr);
|
||||
}
|
||||
}
|
||||
}
|
68
src/views/wired/common/WiredSelectionVisualizer.ts
Normal file
68
src/views/wired/common/WiredSelectionVisualizer.ts
Normal file
@ -0,0 +1,68 @@
|
||||
import { IRoomObject, IRoomObjectSpriteVisualization, NitroFilter, RoomObjectCategory } from 'nitro-renderer';
|
||||
import { GetRoomEngine } from '../../../api';
|
||||
import { WiredSelectionFilter } from './WiredSelectionFilter';
|
||||
|
||||
export class WiredSelectionVisualizer
|
||||
{
|
||||
private static _selectionShader: NitroFilter = new WiredSelectionFilter([ 1, 1, 1 ], [ 0.6, 0.6, 0.6 ]);
|
||||
|
||||
public static show(furniId: number): void
|
||||
{
|
||||
WiredSelectionVisualizer.applySelectionShader(WiredSelectionVisualizer.getRoomObject(furniId));
|
||||
}
|
||||
|
||||
public static hide(furniId: number): void
|
||||
{
|
||||
WiredSelectionVisualizer.clearSelectionShader(WiredSelectionVisualizer.getRoomObject(furniId));
|
||||
}
|
||||
|
||||
public static clearSelectionShaderFromFurni(furniIds: number[]): void
|
||||
{
|
||||
for(const furniId of furniIds)
|
||||
{
|
||||
WiredSelectionVisualizer.clearSelectionShader(WiredSelectionVisualizer.getRoomObject(furniId));
|
||||
}
|
||||
}
|
||||
|
||||
public static applySelectionShaderToFurni(furniIds: number[]): void
|
||||
{
|
||||
for(const furniId of furniIds)
|
||||
{
|
||||
WiredSelectionVisualizer.applySelectionShader(WiredSelectionVisualizer.getRoomObject(furniId));
|
||||
}
|
||||
}
|
||||
|
||||
private static getRoomObject(objectId: number): IRoomObject
|
||||
{
|
||||
const roomEngine = GetRoomEngine();
|
||||
|
||||
return roomEngine.getRoomObject(roomEngine.activeRoomId, objectId, RoomObjectCategory.FLOOR);
|
||||
}
|
||||
|
||||
private static applySelectionShader(roomObject: IRoomObject): void
|
||||
{
|
||||
if(!roomObject) return;
|
||||
|
||||
const visualization = (roomObject.visualization as IRoomObjectSpriteVisualization);
|
||||
|
||||
if(!visualization) return;
|
||||
|
||||
for(const sprite of visualization.sprites)
|
||||
{
|
||||
if(sprite.blendMode === 1) continue; // BLEND_MODE: ADD
|
||||
|
||||
sprite.filters = [ WiredSelectionVisualizer._selectionShader ];
|
||||
}
|
||||
}
|
||||
|
||||
private static clearSelectionShader(roomObject: IRoomObject): void
|
||||
{
|
||||
if(!roomObject) return;
|
||||
|
||||
const visualization = (roomObject.visualization as IRoomObjectSpriteVisualization);
|
||||
|
||||
if(!visualization) return;
|
||||
|
||||
for(const sprite of visualization.sprites) sprite.filters = [];
|
||||
}
|
||||
}
|
@ -4,8 +4,10 @@ import { WiredEvent } from '../../../../events';
|
||||
import { dispatchUiEvent } from '../../../../hooks/events';
|
||||
import { NitroCardContentView, NitroCardView } from '../../../../layout';
|
||||
import { LocalizeText } from '../../../../utils/LocalizeText';
|
||||
import { WiredSelectionVisualizer } from '../../common/WiredSelectionVisualizer';
|
||||
import { useWiredContext } from '../../context/WiredContext';
|
||||
import { WiredFurniType } from '../../WiredView.types';
|
||||
import { WiredFurniSelectorView } from '../furni-selector/WiredFurniSelectorView';
|
||||
import { WiredBaseViewProps } from './WiredBaseView.types';
|
||||
|
||||
export const WiredBaseView: FC<WiredBaseViewProps> = props =>
|
||||
@ -36,7 +38,19 @@ export const WiredBaseView: FC<WiredBaseViewProps> = props =>
|
||||
|
||||
setIntParams(trigger.intData);
|
||||
setStringParam(trigger.stringData);
|
||||
setFurniIds(trigger.selectedItems);
|
||||
setFurniIds(prevValue =>
|
||||
{
|
||||
if(prevValue && prevValue.length) WiredSelectionVisualizer.clearSelectionShaderFromFurni(prevValue);
|
||||
|
||||
if(trigger.selectedItems && trigger.selectedItems.length)
|
||||
{
|
||||
WiredSelectionVisualizer.applySelectionShaderToFurni(trigger.selectedItems);
|
||||
|
||||
return trigger.selectedItems;
|
||||
}
|
||||
|
||||
return [];
|
||||
});
|
||||
}, [ trigger, setIntParams, setStringParam, setFurniIds ]);
|
||||
|
||||
const onSave = useCallback(() =>
|
||||
@ -52,10 +66,12 @@ export const WiredBaseView: FC<WiredBaseViewProps> = props =>
|
||||
}, [ setTrigger ]);
|
||||
|
||||
return (
|
||||
<NitroCardView className={`nitro-wired nitro-wired-${wiredType} ` + (wiredType == 'trigger' ? 'rounded-0' : 'rounded-2')}>
|
||||
<NitroCardView className={`nitro-wired nitro-wired-${wiredType} ` + (wiredType === 'trigger' ? 'rounded-0' : 'rounded-2')}>
|
||||
<div className="nitro-wired-header d-flex">
|
||||
<div className="nitro-wired-title rounded-start w-100 drag-handler">{LocalizeText('wiredfurni.title')}</div>
|
||||
<div className="nitro-wired-close rounded-end flex-shrink-0" onClick={ close }><i className="fas fa-times" /></div>
|
||||
<div className="nitro-wired-title rounded-start w-100 drag-handler">{ LocalizeText('wiredfurni.title') }</div>
|
||||
<div className="nitro-wired-close rounded-end flex-shrink-0" onClick={ close }>
|
||||
<i className="fas fa-times" />
|
||||
</div>
|
||||
</div>
|
||||
<NitroCardContentView>
|
||||
<div className="d-flex align-items-center">
|
||||
@ -69,11 +85,10 @@ export const WiredBaseView: FC<WiredBaseViewProps> = props =>
|
||||
{ children }
|
||||
</> }
|
||||
</div>
|
||||
{ (requiresFurni !== WiredFurniType.STUFF_SELECTION_OPTION_NONE) &&
|
||||
{ (requiresFurni > WiredFurniType.STUFF_SELECTION_OPTION_NONE) &&
|
||||
<>
|
||||
<hr className="my-1 mb-2 bg-dark" />
|
||||
<div className="fw-bold">{ LocalizeText('wiredfurni.pickfurnis.caption', [ 'count', 'limit' ], [ '0', trigger.maximumItemSelectionCount.toString() ]) }</div>
|
||||
<div>{ LocalizeText('wiredfurni.pickfurnis.desc') }</div>
|
||||
<WiredFurniSelectorView />
|
||||
</> }
|
||||
<div className="d-flex mt-3">
|
||||
<button className="btn btn-sm btn-success me-2 w-100" onClick={ onSave }>{ LocalizeText('wiredfurni.ready') }</button>
|
||||
|
@ -1,17 +1,84 @@
|
||||
import { FC } from 'react';
|
||||
import { FC, useCallback, useEffect } from 'react';
|
||||
import { WiredSelectObjectEvent } from '../../../../events';
|
||||
import { useUiEvent } from '../../../../hooks/events';
|
||||
import { LocalizeText } from '../../../../utils/LocalizeText';
|
||||
import { WiredSelectionVisualizer } from '../../common/WiredSelectionVisualizer';
|
||||
import { useWiredContext } from '../../context/WiredContext';
|
||||
import { WiredFurniSelectorViewProps } from './WiredFurniSelectorView.types';
|
||||
|
||||
export const WiredFurniSelectorView: FC<WiredFurniSelectorViewProps> = props =>
|
||||
{
|
||||
const { selectedItemsCount = null, maximumItemsCount = null } = props;
|
||||
const { trigger = null, furniIds = [], setFurniIds = null } = useWiredContext();
|
||||
|
||||
const onWiredSelectObjectEvent = useCallback((event: WiredSelectObjectEvent) =>
|
||||
{
|
||||
const furniId = event.objectId;
|
||||
|
||||
if(furniId === -1) return;
|
||||
|
||||
let newFurniIds: number[] = null;
|
||||
|
||||
setFurniIds(prevValue =>
|
||||
{
|
||||
newFurniIds = [ ...prevValue ];
|
||||
|
||||
const index = prevValue.indexOf(furniId);
|
||||
|
||||
if(index >= 0)
|
||||
{
|
||||
newFurniIds.splice(index, 1);
|
||||
|
||||
WiredSelectionVisualizer.hide(furniId);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(newFurniIds.length < trigger.maximumItemSelectionCount)
|
||||
{
|
||||
newFurniIds.push(furniId);
|
||||
|
||||
WiredSelectionVisualizer.show(furniId);
|
||||
}
|
||||
}
|
||||
|
||||
return newFurniIds;
|
||||
});
|
||||
}, [ trigger, setFurniIds ]);
|
||||
|
||||
useUiEvent(WiredSelectObjectEvent.SELECT_OBJECT, onWiredSelectObjectEvent);
|
||||
|
||||
useEffect(() =>
|
||||
{
|
||||
if(!trigger) return;
|
||||
|
||||
setFurniIds(prevValue =>
|
||||
{
|
||||
if(prevValue && prevValue.length) WiredSelectionVisualizer.clearSelectionShaderFromFurni(prevValue);
|
||||
|
||||
if(trigger.selectedItems && trigger.selectedItems.length)
|
||||
{
|
||||
WiredSelectionVisualizer.applySelectionShaderToFurni(trigger.selectedItems);
|
||||
|
||||
return trigger.selectedItems;
|
||||
}
|
||||
|
||||
return [];
|
||||
});
|
||||
|
||||
return () =>
|
||||
{
|
||||
setFurniIds(prevValue =>
|
||||
{
|
||||
WiredSelectionVisualizer.clearSelectionShaderFromFurni(prevValue);
|
||||
|
||||
return [];
|
||||
});
|
||||
}
|
||||
}, [ trigger, setFurniIds ]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<hr className="p-0 m-1" />
|
||||
<div className="fw-bold">{ LocalizeText('wiredfurni.pickfurnis.caption', ['count', 'limit'], [selectedItemsCount.toString(), maximumItemsCount.toString()]) }</div>
|
||||
<div>{ LocalizeText('wiredfurni.pickfurnis.desc') }</div>
|
||||
<hr className="p-0 m-1" />
|
||||
</>
|
||||
<div className="d-flex flex-column">
|
||||
<div className="fw-bold">{ LocalizeText('wiredfurni.pickfurnis.caption', ['count', 'limit'], [ furniIds.length.toString(), trigger.maximumItemSelectionCount.toString() ]) }</div>
|
||||
{ LocalizeText('wiredfurni.pickfurnis.desc') }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -1,5 +1,3 @@
|
||||
export class WiredFurniSelectorViewProps
|
||||
{
|
||||
selectedItemsCount: number;
|
||||
maximumItemsCount: number;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user