mirror of
https://github.com/4ian/GDevelop.git
synced 2025-10-15 10:19:04 +00:00
547 lines
18 KiB
TypeScript
547 lines
18 KiB
TypeScript
namespace gdjs {
|
|
/** Base parameters for {@link gdjs.Cube3DRuntimeObject} */
|
|
export interface Cube3DObjectData extends Object3DData {
|
|
/** The base parameters of the Cube3D object */
|
|
content: Object3DDataContent & {
|
|
enableTextureTransparency: boolean | undefined;
|
|
facesOrientation: 'Y' | 'Z' | undefined;
|
|
frontFaceResourceName: string;
|
|
backFaceResourceName: string;
|
|
backFaceUpThroughWhichAxisRotation: 'X' | 'Y' | undefined;
|
|
leftFaceResourceName: string;
|
|
rightFaceResourceName: string;
|
|
topFaceResourceName: string;
|
|
bottomFaceResourceName: string;
|
|
frontFaceResourceRepeat: boolean | undefined;
|
|
backFaceResourceRepeat: boolean | undefined;
|
|
leftFaceResourceRepeat: boolean | undefined;
|
|
rightFaceResourceRepeat: boolean | undefined;
|
|
topFaceResourceRepeat: boolean | undefined;
|
|
bottomFaceResourceRepeat: boolean | undefined;
|
|
frontFaceVisible: boolean;
|
|
backFaceVisible: boolean;
|
|
leftFaceVisible: boolean;
|
|
rightFaceVisible: boolean;
|
|
topFaceVisible: boolean;
|
|
bottomFaceVisible: boolean;
|
|
tint: string | undefined;
|
|
materialType: 'Basic' | 'StandardWithoutMetalness';
|
|
};
|
|
}
|
|
type FaceName = 'front' | 'back' | 'left' | 'right' | 'top' | 'bottom';
|
|
const faceNameToBitmaskIndex = {
|
|
front: 0,
|
|
back: 1,
|
|
left: 2,
|
|
right: 3,
|
|
top: 4,
|
|
bottom: 5,
|
|
};
|
|
|
|
type Cube3DObjectNetworkSyncDataType = {
|
|
fo: 'Y' | 'Z';
|
|
bfu: 'X' | 'Y';
|
|
vfb: integer;
|
|
trfb: integer;
|
|
frn: [string, string, string, string, string, string];
|
|
mt: number;
|
|
tint: string;
|
|
};
|
|
|
|
type Cube3DObjectNetworkSyncData = Object3DNetworkSyncData &
|
|
Cube3DObjectNetworkSyncDataType;
|
|
|
|
/**
|
|
* Shows a 3D box object.
|
|
*/
|
|
export class Cube3DRuntimeObject extends gdjs.RuntimeObject3D {
|
|
private _renderer: Cube3DRuntimeObjectRenderer;
|
|
private _facesOrientation: 'Y' | 'Z';
|
|
private _backFaceUpThroughWhichAxisRotation: 'X' | 'Y';
|
|
private _shouldUseTransparentTexture: boolean;
|
|
// `_rotationZ` is `angle` from `gdjs.RuntimeObject`.
|
|
private _visibleFacesBitmask: integer;
|
|
private _textureRepeatFacesBitmask: integer;
|
|
private _faceResourceNames: [
|
|
string,
|
|
string,
|
|
string,
|
|
string,
|
|
string,
|
|
string,
|
|
];
|
|
_materialType: gdjs.Cube3DRuntimeObject.MaterialType =
|
|
gdjs.Cube3DRuntimeObject.MaterialType.Basic;
|
|
_tint: string;
|
|
|
|
constructor(
|
|
instanceContainer: gdjs.RuntimeInstanceContainer,
|
|
objectData: Cube3DObjectData
|
|
) {
|
|
super(instanceContainer, objectData);
|
|
this._shouldUseTransparentTexture =
|
|
objectData.content.enableTextureTransparency || false;
|
|
this._facesOrientation = objectData.content.facesOrientation || 'Y';
|
|
this._visibleFacesBitmask = 0;
|
|
if (objectData.content.frontFaceVisible)
|
|
this._visibleFacesBitmask |= 1 << faceNameToBitmaskIndex['front'];
|
|
if (objectData.content.backFaceVisible)
|
|
this._visibleFacesBitmask |= 1 << faceNameToBitmaskIndex['back'];
|
|
if (objectData.content.leftFaceVisible)
|
|
this._visibleFacesBitmask |= 1 << faceNameToBitmaskIndex['left'];
|
|
if (objectData.content.rightFaceVisible)
|
|
this._visibleFacesBitmask |= 1 << faceNameToBitmaskIndex['right'];
|
|
if (objectData.content.topFaceVisible)
|
|
this._visibleFacesBitmask |= 1 << faceNameToBitmaskIndex['top'];
|
|
if (objectData.content.bottomFaceVisible)
|
|
this._visibleFacesBitmask |= 1 << faceNameToBitmaskIndex['bottom'];
|
|
this._textureRepeatFacesBitmask = 0;
|
|
if (objectData.content.frontFaceResourceRepeat)
|
|
this._textureRepeatFacesBitmask |= 1 << faceNameToBitmaskIndex['front'];
|
|
if (objectData.content.backFaceResourceRepeat)
|
|
this._textureRepeatFacesBitmask |= 1 << faceNameToBitmaskIndex['back'];
|
|
if (objectData.content.leftFaceResourceRepeat)
|
|
this._textureRepeatFacesBitmask |= 1 << faceNameToBitmaskIndex['left'];
|
|
if (objectData.content.rightFaceResourceRepeat)
|
|
this._textureRepeatFacesBitmask |= 1 << faceNameToBitmaskIndex['right'];
|
|
if (objectData.content.topFaceResourceRepeat)
|
|
this._textureRepeatFacesBitmask |= 1 << faceNameToBitmaskIndex['top'];
|
|
if (objectData.content.bottomFaceResourceRepeat)
|
|
this._textureRepeatFacesBitmask |=
|
|
1 << faceNameToBitmaskIndex['bottom'];
|
|
this._backFaceUpThroughWhichAxisRotation =
|
|
objectData.content.backFaceUpThroughWhichAxisRotation || 'X';
|
|
this._faceResourceNames = [
|
|
objectData.content.frontFaceResourceName,
|
|
objectData.content.backFaceResourceName,
|
|
objectData.content.leftFaceResourceName,
|
|
objectData.content.rightFaceResourceName,
|
|
objectData.content.topFaceResourceName,
|
|
objectData.content.bottomFaceResourceName,
|
|
];
|
|
|
|
this._tint = objectData.content.tint || '255;255;255';
|
|
|
|
this._materialType = this._convertMaterialType(
|
|
objectData.content.materialType
|
|
);
|
|
|
|
this._renderer = new gdjs.Cube3DRuntimeObjectRenderer(
|
|
this,
|
|
instanceContainer
|
|
);
|
|
|
|
// *ALWAYS* call `this.onCreated()` at the very end of your object constructor.
|
|
this.onCreated();
|
|
}
|
|
|
|
/**
|
|
* Sets the visibility of a face of the 3D box.
|
|
*
|
|
* @param faceName - The name of the face to set visibility for.
|
|
* @param enable - The visibility value to set.
|
|
*/
|
|
setFaceVisibility(faceName: FaceName, enable: boolean) {
|
|
const faceIndex = faceNameToBitmaskIndex[faceName];
|
|
if (faceIndex === undefined) {
|
|
return;
|
|
}
|
|
if (enable === this.isFaceAtIndexVisible(faceIndex)) {
|
|
return;
|
|
}
|
|
|
|
if (enable) {
|
|
this._visibleFacesBitmask |= 1 << faceIndex;
|
|
} else {
|
|
this._visibleFacesBitmask &= ~(1 << faceIndex);
|
|
}
|
|
this._renderer.updateFace(faceIndex);
|
|
}
|
|
|
|
/**
|
|
* Sets the texture repeat of a face of the 3D box.
|
|
*
|
|
* @param faceName - The name of the face to set visibility for.
|
|
* @param enable - The visibility value to set.
|
|
*/
|
|
setRepeatTextureOnFace(faceName: FaceName, enable: boolean) {
|
|
const faceIndex = faceNameToBitmaskIndex[faceName];
|
|
if (faceIndex === undefined) {
|
|
return;
|
|
}
|
|
if (enable === this.shouldRepeatTextureOnFaceAtIndex(faceIndex)) {
|
|
return;
|
|
}
|
|
|
|
if (enable) {
|
|
this._textureRepeatFacesBitmask |= 1 << faceIndex;
|
|
} else {
|
|
this._textureRepeatFacesBitmask &= ~(1 << faceIndex);
|
|
}
|
|
this._renderer.updateFace(faceIndex);
|
|
}
|
|
|
|
isFaceVisible(faceName: FaceName): boolean {
|
|
const faceIndex = faceNameToBitmaskIndex[faceName];
|
|
if (faceIndex === undefined) {
|
|
return false;
|
|
}
|
|
|
|
return this.isFaceAtIndexVisible(faceIndex);
|
|
}
|
|
|
|
/** @internal */
|
|
isFaceAtIndexVisible(faceIndex): boolean {
|
|
return (this._visibleFacesBitmask & (1 << faceIndex)) !== 0;
|
|
}
|
|
|
|
/** @internal */
|
|
shouldRepeatTextureOnFaceAtIndex(faceIndex): boolean {
|
|
return (this._textureRepeatFacesBitmask & (1 << faceIndex)) !== 0;
|
|
}
|
|
|
|
setFaceResourceName(faceName: FaceName, resourceName: string): void {
|
|
const faceIndex = faceNameToBitmaskIndex[faceName];
|
|
if (faceIndex === undefined) {
|
|
return;
|
|
}
|
|
if (this._faceResourceNames[faceIndex] === resourceName) {
|
|
return;
|
|
}
|
|
this._faceResourceNames[faceIndex] = resourceName;
|
|
this._renderer.updateFace(faceIndex);
|
|
}
|
|
|
|
setColor(tint: string): void {
|
|
if (this._tint === tint) {
|
|
return;
|
|
}
|
|
this._tint = tint;
|
|
this._renderer.updateTint();
|
|
}
|
|
|
|
getColor(): string {
|
|
return this._tint;
|
|
}
|
|
|
|
/** @internal */
|
|
getFaceAtIndexResourceName(faceIndex: integer): string {
|
|
return this._faceResourceNames[faceIndex];
|
|
}
|
|
|
|
getRenderer(): gdjs.RuntimeObject3DRenderer {
|
|
return this._renderer;
|
|
}
|
|
|
|
getBackFaceUpThroughWhichAxisRotation(): 'X' | 'Y' {
|
|
return this._backFaceUpThroughWhichAxisRotation;
|
|
}
|
|
|
|
setBackFaceUpThroughWhichAxisRotation(axis: 'X' | 'Y'): void {
|
|
this._backFaceUpThroughWhichAxisRotation = axis;
|
|
this._renderer.updateFace(faceNameToBitmaskIndex['back']);
|
|
}
|
|
|
|
getFacesOrientation(): 'Y' | 'Z' {
|
|
return this._facesOrientation;
|
|
}
|
|
|
|
setFacesOrientation(orientation: 'Y' | 'Z'): void {
|
|
this._facesOrientation = orientation;
|
|
this._renderer.updateFace(faceNameToBitmaskIndex['left']);
|
|
this._renderer.updateFace(faceNameToBitmaskIndex['right']);
|
|
this._renderer.updateFace(faceNameToBitmaskIndex['top']);
|
|
// Bottom texture should not change based on that setting.
|
|
}
|
|
|
|
updateFromObjectData(
|
|
oldObjectData: Cube3DObjectData,
|
|
newObjectData: Cube3DObjectData
|
|
): boolean {
|
|
super.updateFromObjectData(oldObjectData, newObjectData);
|
|
if (
|
|
oldObjectData.content.frontFaceVisible !==
|
|
newObjectData.content.frontFaceVisible
|
|
) {
|
|
this.setFaceVisibility('front', newObjectData.content.frontFaceVisible);
|
|
}
|
|
if (
|
|
oldObjectData.content.backFaceVisible !==
|
|
newObjectData.content.backFaceVisible
|
|
) {
|
|
this.setFaceVisibility('back', newObjectData.content.backFaceVisible);
|
|
}
|
|
if (
|
|
oldObjectData.content.leftFaceVisible !==
|
|
newObjectData.content.leftFaceVisible
|
|
) {
|
|
this.setFaceVisibility('left', newObjectData.content.leftFaceVisible);
|
|
}
|
|
if (
|
|
oldObjectData.content.rightFaceVisible !==
|
|
newObjectData.content.rightFaceVisible
|
|
) {
|
|
this.setFaceVisibility('right', newObjectData.content.rightFaceVisible);
|
|
}
|
|
if (
|
|
oldObjectData.content.topFaceVisible !==
|
|
newObjectData.content.topFaceVisible
|
|
) {
|
|
this.setFaceVisibility('top', newObjectData.content.topFaceVisible);
|
|
}
|
|
if (
|
|
oldObjectData.content.bottomFaceVisible !==
|
|
newObjectData.content.bottomFaceVisible
|
|
) {
|
|
this.setFaceVisibility(
|
|
'bottom',
|
|
newObjectData.content.bottomFaceVisible
|
|
);
|
|
}
|
|
if (
|
|
oldObjectData.content.frontFaceResourceName !==
|
|
newObjectData.content.frontFaceResourceName
|
|
) {
|
|
this.setFaceResourceName(
|
|
'front',
|
|
newObjectData.content.frontFaceResourceName
|
|
);
|
|
}
|
|
if (oldObjectData.content.tint !== newObjectData.content.tint) {
|
|
this.setColor(newObjectData.content.tint || '255;255;255');
|
|
}
|
|
|
|
if (
|
|
oldObjectData.content.backFaceResourceName !==
|
|
newObjectData.content.backFaceResourceName
|
|
) {
|
|
this.setFaceResourceName(
|
|
'back',
|
|
newObjectData.content.backFaceResourceName
|
|
);
|
|
}
|
|
if (
|
|
oldObjectData.content.leftFaceResourceName !==
|
|
newObjectData.content.leftFaceResourceName
|
|
) {
|
|
this.setFaceResourceName(
|
|
'left',
|
|
newObjectData.content.leftFaceResourceName
|
|
);
|
|
}
|
|
if (
|
|
oldObjectData.content.rightFaceResourceName !==
|
|
newObjectData.content.rightFaceResourceName
|
|
) {
|
|
this.setFaceResourceName(
|
|
'right',
|
|
newObjectData.content.rightFaceResourceName
|
|
);
|
|
}
|
|
if (
|
|
oldObjectData.content.topFaceResourceName !==
|
|
newObjectData.content.topFaceResourceName
|
|
) {
|
|
this.setFaceResourceName(
|
|
'top',
|
|
newObjectData.content.topFaceResourceName
|
|
);
|
|
}
|
|
if (
|
|
oldObjectData.content.bottomFaceResourceName !==
|
|
newObjectData.content.bottomFaceResourceName
|
|
) {
|
|
this.setFaceResourceName(
|
|
'bottom',
|
|
newObjectData.content.bottomFaceResourceName
|
|
);
|
|
}
|
|
if (
|
|
oldObjectData.content.frontFaceResourceRepeat !==
|
|
newObjectData.content.frontFaceResourceRepeat
|
|
) {
|
|
this.setRepeatTextureOnFace(
|
|
'front',
|
|
newObjectData.content.frontFaceResourceRepeat || false
|
|
);
|
|
}
|
|
if (
|
|
oldObjectData.content.backFaceResourceRepeat !==
|
|
newObjectData.content.backFaceResourceRepeat
|
|
) {
|
|
this.setRepeatTextureOnFace(
|
|
'back',
|
|
newObjectData.content.backFaceResourceRepeat || false
|
|
);
|
|
}
|
|
if (
|
|
oldObjectData.content.leftFaceResourceRepeat !==
|
|
newObjectData.content.leftFaceResourceRepeat
|
|
) {
|
|
this.setRepeatTextureOnFace(
|
|
'left',
|
|
newObjectData.content.leftFaceResourceRepeat || false
|
|
);
|
|
}
|
|
if (
|
|
oldObjectData.content.rightFaceResourceRepeat !==
|
|
newObjectData.content.rightFaceResourceRepeat
|
|
) {
|
|
this.setRepeatTextureOnFace(
|
|
'right',
|
|
newObjectData.content.rightFaceResourceRepeat || false
|
|
);
|
|
}
|
|
if (
|
|
oldObjectData.content.topFaceResourceRepeat !==
|
|
newObjectData.content.topFaceResourceRepeat
|
|
) {
|
|
this.setRepeatTextureOnFace(
|
|
'top',
|
|
newObjectData.content.topFaceResourceRepeat || false
|
|
);
|
|
}
|
|
if (
|
|
oldObjectData.content.bottomFaceResourceRepeat !==
|
|
newObjectData.content.bottomFaceResourceRepeat
|
|
) {
|
|
this.setRepeatTextureOnFace(
|
|
'bottom',
|
|
newObjectData.content.bottomFaceResourceRepeat || false
|
|
);
|
|
}
|
|
if (
|
|
oldObjectData.content.backFaceUpThroughWhichAxisRotation !==
|
|
newObjectData.content.backFaceUpThroughWhichAxisRotation
|
|
) {
|
|
this.setBackFaceUpThroughWhichAxisRotation(
|
|
newObjectData.content.backFaceUpThroughWhichAxisRotation || 'X'
|
|
);
|
|
}
|
|
if (
|
|
oldObjectData.content.facesOrientation !==
|
|
newObjectData.content.facesOrientation
|
|
) {
|
|
this.setFacesOrientation(newObjectData.content.facesOrientation || 'Y');
|
|
}
|
|
if (
|
|
oldObjectData.content.materialType !==
|
|
newObjectData.content.materialType
|
|
) {
|
|
this.setMaterialType(newObjectData.content.materialType);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
getNetworkSyncData(
|
|
syncOptions: GetNetworkSyncDataOptions
|
|
): Cube3DObjectNetworkSyncData {
|
|
return {
|
|
...super.getNetworkSyncData(syncOptions),
|
|
mt: this._materialType,
|
|
fo: this._facesOrientation,
|
|
bfu: this._backFaceUpThroughWhichAxisRotation,
|
|
vfb: this._visibleFacesBitmask,
|
|
trfb: this._textureRepeatFacesBitmask,
|
|
frn: this._faceResourceNames,
|
|
tint: this._tint,
|
|
};
|
|
}
|
|
|
|
updateFromNetworkSyncData(
|
|
networkSyncData: Cube3DObjectNetworkSyncData,
|
|
options: UpdateFromNetworkSyncDataOptions
|
|
): void {
|
|
super.updateFromNetworkSyncData(networkSyncData, options);
|
|
|
|
if (networkSyncData.mt !== undefined) {
|
|
this._materialType = networkSyncData.mt;
|
|
}
|
|
if (networkSyncData.fo !== undefined) {
|
|
if (this._facesOrientation !== networkSyncData.fo) {
|
|
this.setFacesOrientation(networkSyncData.fo);
|
|
}
|
|
}
|
|
if (networkSyncData.bfu !== undefined) {
|
|
if (this._backFaceUpThroughWhichAxisRotation !== networkSyncData.bfu) {
|
|
this.setBackFaceUpThroughWhichAxisRotation(networkSyncData.bfu);
|
|
}
|
|
}
|
|
if (networkSyncData.vfb !== undefined) {
|
|
// If it is different, update all the faces.
|
|
if (this._visibleFacesBitmask !== networkSyncData.vfb) {
|
|
this._visibleFacesBitmask = networkSyncData.vfb;
|
|
for (let i = 0; i < this._faceResourceNames.length; i++) {
|
|
this._renderer.updateFace(i);
|
|
}
|
|
}
|
|
}
|
|
if (networkSyncData.trfb !== undefined) {
|
|
// If it is different, update all the faces.
|
|
if (this._textureRepeatFacesBitmask !== networkSyncData.trfb) {
|
|
this._textureRepeatFacesBitmask = networkSyncData.trfb;
|
|
for (let i = 0; i < this._faceResourceNames.length; i++) {
|
|
this._renderer.updateFace(i);
|
|
}
|
|
}
|
|
}
|
|
if (networkSyncData.frn !== undefined) {
|
|
// If one element is different, update all the faces.
|
|
if (
|
|
!this._faceResourceNames.every(
|
|
(value, index) => value === networkSyncData.frn[index]
|
|
)
|
|
) {
|
|
this._faceResourceNames = networkSyncData.frn;
|
|
// Update all faces. (Could optimize to only update the changed ones)
|
|
for (let i = 0; i < this._faceResourceNames.length; i++) {
|
|
this._renderer.updateFace(i);
|
|
}
|
|
}
|
|
}
|
|
if (networkSyncData.tint !== undefined) {
|
|
if (this._tint !== networkSyncData.tint) {
|
|
this._tint = networkSyncData.tint;
|
|
this._renderer.updateTint();
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Return true if the texture transparency should be enabled.
|
|
*/
|
|
shouldUseTransparentTexture(): boolean {
|
|
return this._shouldUseTransparentTexture;
|
|
}
|
|
|
|
_convertMaterialType(
|
|
materialTypeString: string
|
|
): gdjs.Cube3DRuntimeObject.MaterialType {
|
|
if (materialTypeString === 'StandardWithoutMetalness') {
|
|
return gdjs.Cube3DRuntimeObject.MaterialType.StandardWithoutMetalness;
|
|
} else {
|
|
return gdjs.Cube3DRuntimeObject.MaterialType.Basic;
|
|
}
|
|
}
|
|
|
|
setMaterialType(materialTypeString: string) {
|
|
const newMaterialType = this._convertMaterialType(materialTypeString);
|
|
if (this._materialType === newMaterialType) {
|
|
return;
|
|
}
|
|
|
|
this._materialType = newMaterialType;
|
|
this._renderer._updateMaterials();
|
|
}
|
|
}
|
|
|
|
export namespace Cube3DRuntimeObject {
|
|
export enum MaterialType {
|
|
Basic,
|
|
StandardWithoutMetalness,
|
|
}
|
|
}
|
|
gdjs.registerObject('Scene3D::Cube3DObject', gdjs.Cube3DRuntimeObject);
|
|
}
|