442 lines
14 KiB
TypeScript
442 lines
14 KiB
TypeScript
import {
|
|
IAssetData,
|
|
IRoomGeometry,
|
|
IRoomObjectController,
|
|
IRoomObjectModel,
|
|
IVector3D,
|
|
MouseEventType,
|
|
NitroConfiguration,
|
|
RoomObjectVariable,
|
|
Vector3d,
|
|
} from "../../../../../api";
|
|
import {
|
|
RoomObjectMouseEvent,
|
|
RoomObjectRoomAdEvent,
|
|
RoomObjectStateChangedEvent,
|
|
RoomObjectWidgetRequestEvent,
|
|
RoomSpriteMouseEvent,
|
|
} from "../../../../../events";
|
|
import {RoomObjectUpdateMessage} from "../../../../../room";
|
|
import {
|
|
ObjectDataUpdateMessage,
|
|
ObjectHeightUpdateMessage,
|
|
ObjectItemDataUpdateMessage,
|
|
ObjectMoveUpdateMessage,
|
|
ObjectSelectedMessage,
|
|
} from "../../../messages";
|
|
import {MovingObjectLogic} from "../MovingObjectLogic";
|
|
|
|
export class FurnitureLogic extends MovingObjectLogic {
|
|
private static BOUNCING_STEPS: number = -1;
|
|
private static BOUNCING_Z: number = -1;
|
|
|
|
private _sizeX: number;
|
|
private _sizeY: number;
|
|
private _sizeZ: number;
|
|
private _centerX: number;
|
|
private _centerY: number;
|
|
private _centerZ: number;
|
|
|
|
private _directions: number[];
|
|
|
|
private _mouseOver: boolean;
|
|
|
|
private _locationOffset: IVector3D;
|
|
private _bouncingStep: number;
|
|
private _storedRotateMessage: RoomObjectUpdateMessage;
|
|
private _directionInitialized: boolean;
|
|
|
|
constructor() {
|
|
super();
|
|
|
|
this._sizeX = 0;
|
|
this._sizeY = 0;
|
|
this._sizeZ = 0;
|
|
this._centerX = 0;
|
|
this._centerY = 0;
|
|
this._centerZ = 0;
|
|
|
|
this._directions = [];
|
|
|
|
this._mouseOver = false;
|
|
|
|
this._locationOffset = new Vector3d();
|
|
this._bouncingStep = 0;
|
|
this._storedRotateMessage = null;
|
|
this._directionInitialized = false;
|
|
|
|
if (FurnitureLogic.BOUNCING_STEPS === -1) {
|
|
FurnitureLogic.BOUNCING_STEPS = NitroConfiguration.getValue<number>("furni.rotation.bounce.steps", 8);
|
|
}
|
|
|
|
if (FurnitureLogic.BOUNCING_Z === -1) {
|
|
FurnitureLogic.BOUNCING_Z = NitroConfiguration.getValue<number>("furni.rotation.bounce.height", 0.0625);
|
|
}
|
|
}
|
|
|
|
public override getEventTypes(): string[] {
|
|
const types = [
|
|
RoomObjectStateChangedEvent.STATE_CHANGE,
|
|
RoomObjectMouseEvent.CLICK,
|
|
RoomObjectMouseEvent.MOUSE_DOWN,
|
|
RoomObjectMouseEvent.MOUSE_DOWN_LONG,
|
|
RoomObjectRoomAdEvent.ROOM_AD_TOOLTIP_SHOW,
|
|
RoomObjectRoomAdEvent.ROOM_AD_TOOLTIP_HIDE,
|
|
RoomObjectRoomAdEvent.ROOM_AD_FURNI_DOUBLE_CLICK,
|
|
RoomObjectRoomAdEvent.ROOM_AD_FURNI_CLICK,
|
|
];
|
|
|
|
if (this.widget) types.push(RoomObjectWidgetRequestEvent.OPEN_WIDGET, RoomObjectWidgetRequestEvent.CLOSE_WIDGET);
|
|
|
|
if (this.contextMenu) types.push(RoomObjectWidgetRequestEvent.OPEN_FURNI_CONTEXT_MENU, RoomObjectWidgetRequestEvent.CLOSE_FURNI_CONTEXT_MENU);
|
|
|
|
return this.mergeTypes(super.getEventTypes(), types);
|
|
}
|
|
|
|
public override initialize(asset: IAssetData): void {
|
|
if (!asset) return;
|
|
|
|
const model = this.object && this.object.model;
|
|
|
|
if (!model) return;
|
|
|
|
if (asset.logic) {
|
|
if (asset.logic.model) {
|
|
const dimensions = asset.logic.model.dimensions;
|
|
|
|
if (dimensions) {
|
|
this._sizeX = dimensions.x;
|
|
this._sizeY = dimensions.y;
|
|
this._sizeZ = dimensions.z;
|
|
|
|
this._centerX = this._sizeX / 2;
|
|
this._centerY = this._sizeY / 2;
|
|
this._centerZ = this._sizeZ / 2;
|
|
}
|
|
|
|
const directions = asset.logic.model.directions;
|
|
|
|
if (directions && directions.length) {
|
|
for (const direction of directions) this._directions.push(direction);
|
|
|
|
this._directions.sort((a, b) => a - b);
|
|
}
|
|
}
|
|
|
|
if (asset.logic.customVars) {
|
|
const variables = asset.logic.customVars.variables;
|
|
|
|
if (variables && variables.length) {
|
|
model.setValue(RoomObjectVariable.FURNITURE_CUSTOM_VARIABLES, variables);
|
|
}
|
|
}
|
|
}
|
|
|
|
model.setValue(RoomObjectVariable.FURNITURE_SIZE_X, this._sizeX);
|
|
model.setValue(RoomObjectVariable.FURNITURE_SIZE_Y, this._sizeY);
|
|
model.setValue(RoomObjectVariable.FURNITURE_SIZE_Z, this._sizeZ);
|
|
model.setValue(RoomObjectVariable.FURNITURE_CENTER_X, this._centerX);
|
|
model.setValue(RoomObjectVariable.FURNITURE_CENTER_Y, this._centerY);
|
|
model.setValue(RoomObjectVariable.FURNITURE_CENTER_Z, this._centerZ);
|
|
model.setValue(RoomObjectVariable.FURNITURE_ALLOWED_DIRECTIONS, this._directions);
|
|
model.setValue(RoomObjectVariable.FURNITURE_ALPHA_MULTIPLIER, 1);
|
|
}
|
|
|
|
protected override onDispose(): void {
|
|
this._storedRotateMessage = null;
|
|
this._directions = null;
|
|
|
|
super.onDispose();
|
|
}
|
|
|
|
public override setObject(object: IRoomObjectController): void {
|
|
super.setObject(object);
|
|
|
|
if (object && object.getLocation().length) this._directionInitialized = true;
|
|
}
|
|
|
|
protected getAdClickUrl(model: IRoomObjectModel): string {
|
|
return model.getValue<string>(RoomObjectVariable.FURNITURE_AD_URL);
|
|
}
|
|
|
|
protected handleAdClick(objectId: number, objectType: string, clickUrl: string): void {
|
|
if (!this.eventDispatcher) return;
|
|
|
|
this.eventDispatcher.dispatchEvent(new RoomObjectRoomAdEvent(RoomObjectRoomAdEvent.ROOM_AD_FURNI_CLICK, this.object));
|
|
}
|
|
|
|
public override update(time: number): void {
|
|
super.update(time);
|
|
|
|
if (this._bouncingStep > 0) {
|
|
this._bouncingStep++;
|
|
|
|
if (this._bouncingStep > FurnitureLogic.BOUNCING_STEPS) this._bouncingStep = 0;
|
|
}
|
|
}
|
|
|
|
public override processUpdateMessage(message: RoomObjectUpdateMessage): void {
|
|
if (message instanceof ObjectDataUpdateMessage) {
|
|
this.processDataUpdateMessage(message);
|
|
|
|
return;
|
|
}
|
|
|
|
if (message instanceof ObjectHeightUpdateMessage) {
|
|
this.processObjectHeightUpdateMessage(message);
|
|
|
|
return;
|
|
}
|
|
|
|
if (message instanceof ObjectItemDataUpdateMessage) {
|
|
this.processItemDataUpdateMessage(message);
|
|
|
|
return;
|
|
}
|
|
|
|
this._mouseOver = false;
|
|
|
|
if (message.location && message.direction) {
|
|
if (!(message instanceof ObjectMoveUpdateMessage)) {
|
|
const direction = this.object.getDirection();
|
|
const location = this.object.getLocation();
|
|
|
|
if (direction.x !== message.direction.x && this._directionInitialized) {
|
|
if (location.x === message.location.x && location.y === message.location.y && location.z === message.location.z) {
|
|
this._bouncingStep = 1;
|
|
this._storedRotateMessage = new RoomObjectUpdateMessage(message.location, message.direction);
|
|
|
|
message = null;
|
|
}
|
|
}
|
|
}
|
|
|
|
this._directionInitialized = true;
|
|
}
|
|
|
|
if (message instanceof ObjectSelectedMessage) {
|
|
if (this.contextMenu && this.eventDispatcher && this.object) {
|
|
const eventType = message.selected ? RoomObjectWidgetRequestEvent.OPEN_FURNI_CONTEXT_MENU : RoomObjectWidgetRequestEvent.CLOSE_FURNI_CONTEXT_MENU;
|
|
|
|
this.eventDispatcher.dispatchEvent(new RoomObjectWidgetRequestEvent(eventType, this.object));
|
|
}
|
|
}
|
|
|
|
super.processUpdateMessage(message);
|
|
}
|
|
|
|
private processDataUpdateMessage(message: ObjectDataUpdateMessage): void {
|
|
if (!message) return;
|
|
|
|
this.object.setState(message.state, 0);
|
|
|
|
if (message.data) message.data.writeRoomObjectModel(this.object.model);
|
|
|
|
if (message.extra !== null) this.object.model.setValue(RoomObjectVariable.FURNITURE_EXTRAS, message.extra.toString());
|
|
|
|
this.object.model.setValue(RoomObjectVariable.FURNITURE_STATE_UPDATE_TIME, this.lastUpdateTime);
|
|
}
|
|
|
|
private processObjectHeightUpdateMessage(message: ObjectHeightUpdateMessage): void {
|
|
if (!message) return;
|
|
|
|
this.object.model.setValue(RoomObjectVariable.FURNITURE_SIZE_Z, message.height);
|
|
}
|
|
|
|
private processItemDataUpdateMessage(message: ObjectItemDataUpdateMessage): void {
|
|
if (!message) return;
|
|
|
|
this.object.model.setValue(RoomObjectVariable.FURNITURE_ITEMDATA, message.data);
|
|
}
|
|
|
|
public override mouseEvent(event: RoomSpriteMouseEvent, geometry: IRoomGeometry): void {
|
|
const adUrl = this.getAdClickUrl(this.object.model);
|
|
|
|
switch (event.type) {
|
|
case MouseEventType.MOUSE_MOVE:
|
|
if (this.eventDispatcher) {
|
|
const mouseEvent = new RoomObjectMouseEvent(
|
|
RoomObjectMouseEvent.MOUSE_MOVE,
|
|
this.object,
|
|
event.eventId,
|
|
event.altKey,
|
|
event.ctrlKey,
|
|
event.shiftKey,
|
|
event.buttonDown
|
|
);
|
|
|
|
mouseEvent.localX = event.localX;
|
|
mouseEvent.localY = event.localY;
|
|
mouseEvent.spriteOffsetX = event.spriteOffsetX;
|
|
mouseEvent.spriteOffsetY = event.spriteOffsetY;
|
|
|
|
this.eventDispatcher.dispatchEvent(mouseEvent);
|
|
}
|
|
return;
|
|
case MouseEventType.ROLL_OVER:
|
|
if (!this._mouseOver) {
|
|
if (this.eventDispatcher) {
|
|
if (adUrl && adUrl.indexOf("http") === 0) {
|
|
this.eventDispatcher.dispatchEvent(new RoomObjectRoomAdEvent(RoomObjectRoomAdEvent.ROOM_AD_TOOLTIP_SHOW, this.object));
|
|
}
|
|
|
|
const mouseEvent = new RoomObjectMouseEvent(
|
|
RoomObjectMouseEvent.MOUSE_ENTER,
|
|
this.object,
|
|
event.eventId,
|
|
event.altKey,
|
|
event.ctrlKey,
|
|
event.shiftKey,
|
|
event.buttonDown
|
|
);
|
|
|
|
mouseEvent.localX = event.localX;
|
|
mouseEvent.localY = event.localY;
|
|
mouseEvent.spriteOffsetX = event.spriteOffsetX;
|
|
mouseEvent.spriteOffsetY = event.spriteOffsetY;
|
|
|
|
this.eventDispatcher.dispatchEvent(mouseEvent);
|
|
}
|
|
|
|
this._mouseOver = true;
|
|
}
|
|
return;
|
|
case MouseEventType.ROLL_OUT:
|
|
if (this._mouseOver) {
|
|
if (this.eventDispatcher) {
|
|
if (adUrl && adUrl.indexOf("http") === 0) {
|
|
this.eventDispatcher.dispatchEvent(new RoomObjectRoomAdEvent(RoomObjectRoomAdEvent.ROOM_AD_TOOLTIP_HIDE, this.object));
|
|
}
|
|
|
|
const mouseEvent = new RoomObjectMouseEvent(
|
|
RoomObjectMouseEvent.MOUSE_LEAVE,
|
|
this.object,
|
|
event.eventId,
|
|
event.altKey,
|
|
event.ctrlKey,
|
|
event.shiftKey,
|
|
event.buttonDown
|
|
);
|
|
|
|
mouseEvent.localX = event.localX;
|
|
mouseEvent.localY = event.localY;
|
|
mouseEvent.spriteOffsetX = event.spriteOffsetX;
|
|
mouseEvent.spriteOffsetY = event.spriteOffsetY;
|
|
|
|
this.eventDispatcher.dispatchEvent(mouseEvent);
|
|
}
|
|
|
|
this._mouseOver = false;
|
|
}
|
|
return;
|
|
case MouseEventType.DOUBLE_CLICK:
|
|
this.useObject();
|
|
return;
|
|
case MouseEventType.MOUSE_CLICK:
|
|
if (this.eventDispatcher) {
|
|
const mouseEvent = new RoomObjectMouseEvent(
|
|
RoomObjectMouseEvent.CLICK,
|
|
this.object,
|
|
event.eventId,
|
|
event.altKey,
|
|
event.ctrlKey,
|
|
event.shiftKey,
|
|
event.buttonDown
|
|
);
|
|
|
|
mouseEvent.localX = event.localX;
|
|
mouseEvent.localY = event.localY;
|
|
mouseEvent.spriteOffsetX = event.spriteOffsetX;
|
|
mouseEvent.spriteOffsetY = event.spriteOffsetY;
|
|
|
|
this.eventDispatcher.dispatchEvent(mouseEvent);
|
|
|
|
if (adUrl && adUrl.indexOf("http") === 0) {
|
|
this.eventDispatcher.dispatchEvent(new RoomObjectRoomAdEvent(RoomObjectRoomAdEvent.ROOM_AD_TOOLTIP_HIDE, this.object));
|
|
}
|
|
|
|
if (adUrl && adUrl.length) this.handleAdClick(this.object.id, this.object.type, adUrl);
|
|
}
|
|
return;
|
|
case MouseEventType.MOUSE_DOWN:
|
|
if (this.eventDispatcher) {
|
|
const mouseEvent = new RoomObjectMouseEvent(
|
|
RoomObjectMouseEvent.MOUSE_DOWN,
|
|
this.object,
|
|
event.eventId,
|
|
event.altKey,
|
|
event.ctrlKey,
|
|
event.shiftKey,
|
|
event.buttonDown
|
|
);
|
|
|
|
this.eventDispatcher.dispatchEvent(mouseEvent);
|
|
}
|
|
return;
|
|
case MouseEventType.MOUSE_DOWN_LONG:
|
|
if (this.eventDispatcher) {
|
|
const mouseEvent = new RoomObjectMouseEvent(
|
|
RoomObjectMouseEvent.MOUSE_DOWN_LONG,
|
|
this.object,
|
|
event.eventId,
|
|
event.altKey,
|
|
event.ctrlKey,
|
|
event.shiftKey,
|
|
event.buttonDown
|
|
);
|
|
|
|
this.eventDispatcher.dispatchEvent(mouseEvent);
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
|
|
protected override getLocationOffset(): IVector3D {
|
|
if (this._bouncingStep <= 0) return null;
|
|
|
|
this._locationOffset.x = 0;
|
|
this._locationOffset.y = 0;
|
|
|
|
if (this._bouncingStep <= FurnitureLogic.BOUNCING_STEPS / 2) {
|
|
this._locationOffset.z = FurnitureLogic.BOUNCING_Z * this._bouncingStep;
|
|
} else {
|
|
if (this._bouncingStep <= FurnitureLogic.BOUNCING_STEPS) {
|
|
if (this._storedRotateMessage) {
|
|
super.processUpdateMessage(this._storedRotateMessage);
|
|
|
|
this._storedRotateMessage = null;
|
|
}
|
|
|
|
this._locationOffset.z = FurnitureLogic.BOUNCING_Z * (FurnitureLogic.BOUNCING_STEPS - this._bouncingStep);
|
|
}
|
|
}
|
|
|
|
return this._locationOffset;
|
|
}
|
|
|
|
public override useObject(): void {
|
|
if (!this.object || !this.eventDispatcher) return;
|
|
|
|
const clickUrl = this.getAdClickUrl(this.object.model);
|
|
|
|
if (clickUrl && clickUrl.length) {
|
|
this.eventDispatcher.dispatchEvent(new RoomObjectRoomAdEvent(RoomObjectRoomAdEvent.ROOM_AD_FURNI_DOUBLE_CLICK, this.object, null, clickUrl));
|
|
}
|
|
|
|
if (this.widget) this.eventDispatcher.dispatchEvent(new RoomObjectWidgetRequestEvent(RoomObjectWidgetRequestEvent.OPEN_WIDGET, this.object));
|
|
|
|
this.eventDispatcher.dispatchEvent(new RoomObjectStateChangedEvent(RoomObjectStateChangedEvent.STATE_CHANGE, this.object));
|
|
}
|
|
|
|
public override tearDown(): void {
|
|
if (this.object.model.getValue<number>(RoomObjectVariable.FURNITURE_REAL_ROOM_OBJECT) === 1) {
|
|
if (this.widget) this.eventDispatcher.dispatchEvent(new RoomObjectWidgetRequestEvent(RoomObjectWidgetRequestEvent.CLOSE_WIDGET, this.object));
|
|
|
|
if (this.contextMenu)
|
|
this.eventDispatcher.dispatchEvent(new RoomObjectWidgetRequestEvent(RoomObjectWidgetRequestEvent.CLOSE_FURNI_CONTEXT_MENU, this.object));
|
|
}
|
|
|
|
super.tearDown();
|
|
}
|
|
}
|