diff --git a/docs/rooms.md b/docs/rooms.md index 4ebf35aa..996705e0 100644 --- a/docs/rooms.md +++ b/docs/rooms.md @@ -27,7 +27,7 @@ _TODO: explain the rooms file format_ define room-no-ceiling { ceiling arx alpha.bmp # transparent texture from arx' builtin textures wall arx aliciaroom_mur02.jpg - floor custom textures [fabric]-carpet.jpg # custom texture from assets/textures/ + floor custom textures [fabric]-carpet.jpg # custom texture from assets/textures/, optionally you can write either fit-x or fit-y after the texture name } $roomHeight = 300 # variable (or more like constant) diff --git a/src/prefabs/rooms/loadRooms.ts b/src/prefabs/rooms/loadRooms.ts index 59a5b281..022f2658 100644 --- a/src/prefabs/rooms/loadRooms.ts +++ b/src/prefabs/rooms/loadRooms.ts @@ -7,7 +7,7 @@ import { Vector3 } from '@src/Vector3.js' import { TextureOrMaterial } from '@src/types.js' import { Cursor, CursorDir } from '@prefabs/rooms/Cursor.js' import { Rooms } from '@prefabs/rooms/Rooms.js' -import { RoomProps } from '@prefabs/rooms/room.js' +import { RoomProps, TextureDefinition } from '@prefabs/rooms/room.js' import { createLight } from '@tools/createLight.js' export const loadRooms = async (filename: string, settings: Settings) => { @@ -17,9 +17,9 @@ export const loadRooms = async (filename: string, settings: Settings) => { const roomDefinitions: Record = { default: { textures: { - ceiling: Texture.missingTexture, - wall: Texture.missingTexture, - floor: Texture.missingTexture, + ceiling: { texture: Texture.missingTexture, fitX: false, fitY: false }, + wall: { texture: Texture.missingTexture, fitX: false, fitY: false }, + floor: { texture: Texture.missingTexture, fitX: false, fitY: false }, }, }, } @@ -55,13 +55,13 @@ export const loadRooms = async (filename: string, settings: Settings) => { case 'ceiling': { if (tokens[1] === 'custom') { - roomDefinitions[currentBlock.name].textures[tokens[0]] = Texture.fromCustomFile({ + roomDefinitions[currentBlock.name].textures[tokens[0]].texture = Texture.fromCustomFile({ filename: tokens[3], sourcePath: tokens[2], }) } else if (tokens[1] === 'arx') { // TODO: an arx texture might not always be 128x128 - roomDefinitions[currentBlock.name].textures[tokens[0]] = new Texture({ + roomDefinitions[currentBlock.name].textures[tokens[0]].texture = new Texture({ filename: tokens[2], size: 128, }) @@ -74,21 +74,29 @@ export const loadRooms = async (filename: string, settings: Settings) => { break case 'wall': { - const wall = roomDefinitions[currentBlock.name].textures.wall as QuadrupleOf + const wall = roomDefinitions[currentBlock.name].textures.wall as QuadrupleOf if (tokens[1] === 'custom') { const texture = Texture.fromCustomFile({ filename: tokens[3], sourcePath: tokens[2] }) - wall[0] = texture - wall[1] = texture - wall[2] = texture - wall[3] = texture + const fitX = tokens[4] === 'fit-x' + const fitY = tokens[4] === 'fit-y' + + wall[0] = { texture, fitX, fitY } + wall[1] = { texture, fitX, fitY } + wall[2] = { texture, fitX, fitY } + wall[3] = { texture, fitX, fitY } } else if (tokens[1] === 'arx') { // TODO: an arx texture might not always be 128x128 - const texture = new Texture({ filename: tokens[2], size: 128 }) - wall[0] = texture - wall[1] = texture - wall[2] = texture - wall[3] = texture + const textureSize = 128 + + const texture = new Texture({ filename: tokens[2], size: textureSize }) + const fitX = tokens[3] === 'fit-x' + const fitY = tokens[3] === 'fit-y' + + wall[0] = { texture, fitX, fitY } + wall[1] = { texture, fitX, fitY } + wall[2] = { texture, fitX, fitY } + wall[3] = { texture, fitX, fitY } } else { console.error( `Unknown texture type "${tokens[1]}" at line ${i + 1}, expected either "custom" or "arx"`, @@ -101,28 +109,30 @@ export const loadRooms = async (filename: string, settings: Settings) => { case 'wall-south': case 'wall-west': { - const wall = roomDefinitions[currentBlock.name].textures.wall as QuadrupleOf + const wallIdx = tokens[0].endsWith('north') + ? 0 + : tokens[0].endsWith('east') + ? 1 + : tokens[0].endsWith('south') + ? 2 + : 3 + + const wall = roomDefinitions[currentBlock.name].textures.wall as QuadrupleOf if (tokens[1] === 'custom') { const texture = Texture.fromCustomFile({ filename: tokens[3], sourcePath: tokens[2] }) - const wallIdx = tokens[0].endsWith('north') - ? 0 - : tokens[0].endsWith('east') - ? 1 - : tokens[0].endsWith('south') - ? 2 - : 3 - wall[wallIdx] = texture + const fitX = tokens[4] === 'fit-x' + const fitY = tokens[4] === 'fit-y' + + wall[wallIdx] = { texture, fitX, fitY } } else if (tokens[1] === 'arx') { // TODO: an arx texture might not always be 128x128 - const texture = new Texture({ filename: tokens[2], size: 128 }) - const wallIdx = tokens[0].endsWith('north') - ? 0 - : tokens[0].endsWith('east') - ? 1 - : tokens[0].endsWith('south') - ? 2 - : 3 - wall[wallIdx] = texture + const textureSize = 128 + + const texture = new Texture({ filename: tokens[2], size: textureSize }) + const fitX = tokens[3] === 'fit-x' + const fitY = tokens[3] === 'fit-y' + + wall[wallIdx] = { texture, fitX, fitY } } else { console.error( `Unknown texture type "${tokens[1]}" at line ${i + 1}, expected either "custom" or "arx"`, @@ -154,14 +164,14 @@ export const loadRooms = async (filename: string, settings: Settings) => { if (typeof roomDefinitions[tokens[1]] === 'undefined') { roomDefinitions[tokens[1]] = { textures: { - ceiling: Texture.missingTexture, + ceiling: { texture: Texture.missingTexture, fitX: false, fitY: false }, wall: [ - Texture.missingTexture, - Texture.missingTexture, - Texture.missingTexture, - Texture.missingTexture, + { texture: Texture.missingTexture, fitX: false, fitY: false }, + { texture: Texture.missingTexture, fitX: false, fitY: false }, + { texture: Texture.missingTexture, fitX: false, fitY: false }, + { texture: Texture.missingTexture, fitX: false, fitY: false }, ], - floor: Texture.missingTexture, + floor: { texture: Texture.missingTexture, fitX: false, fitY: false }, }, } } diff --git a/src/prefabs/rooms/room.ts b/src/prefabs/rooms/room.ts index c5fbbf47..ebfa8f5b 100644 --- a/src/prefabs/rooms/room.ts +++ b/src/prefabs/rooms/room.ts @@ -10,14 +10,20 @@ import { TextureOrMaterial } from '@src/types.js' import { createPlaneMesh } from '@prefabs/mesh/plane.js' import { scaleUV } from '@tools/mesh/scaleUV.js' +export type TextureDefinition = { + texture: TextureOrMaterial + fitX: boolean + fitY: boolean +} + export type RoomTextures = { - wall: TextureOrMaterial | QuadrupleOf - floor: TextureOrMaterial - ceiling: TextureOrMaterial + wall: TextureDefinition | QuadrupleOf + floor: TextureDefinition + ceiling: TextureDefinition } export type RoomProps = { - decal?: TextureOrMaterial + decal?: TextureDefinition textures: RoomTextures /** * default value is 50 @@ -25,8 +31,9 @@ export type RoomProps = { tileSize?: number } -const createFloor = (size: Vector3, texture: TextureOrMaterial, tileSize: number) => { +const createFloor = (size: Vector3, textureDef: TextureDefinition, tileSize: number) => { const { x: width, y: height, z: depth } = size + const { texture } = textureDef const mesh = createPlaneMesh({ size: new Vector2(width, depth), @@ -41,8 +48,9 @@ const createFloor = (size: Vector3, texture: TextureOrMaterial, tileSize: number return mesh } -const createNorthWall = (size: Vector3, texture: TextureOrMaterial, tileSize: number, decal?: TextureOrMaterial) => { +const createNorthWall = (size: Vector3, textureDef: TextureDefinition, tileSize: number, decal?: TextureDefinition) => { const { x: width, y: height, z: depth } = size + const { texture, fitX, fitY } = textureDef const group = new Group() @@ -55,8 +63,6 @@ const createNorthWall = (size: Vector3, texture: TextureOrMaterial, tileSize: nu }) wall.translateZ(depth / 2).translateY(-height / 2) wall.rotateX(MathUtils.degToRad(90)) - const fitX = false - const fitY = texture.filename.toLowerCase().includes('forest') if (fitX) { scaleUV(new Vector2(tileSize / width, tileSize / width), wall.geometry) } else if (fitY) { @@ -70,7 +76,7 @@ const createNorthWall = (size: Vector3, texture: TextureOrMaterial, tileSize: nu const decalOnWall = createPlaneMesh({ size: new Vector2(width, tileSize), tileSize, - texture: Material.fromTexture(decal, { + texture: Material.fromTexture(decal.texture, { flags: ArxPolygonFlags.Tiled, }), }) @@ -83,8 +89,9 @@ const createNorthWall = (size: Vector3, texture: TextureOrMaterial, tileSize: nu return group } -const createSouthWall = (size: Vector3, texture: TextureOrMaterial, tileSize: number, decal?: TextureOrMaterial) => { +const createSouthWall = (size: Vector3, textureDef: TextureDefinition, tileSize: number, decal?: TextureDefinition) => { const { x: width, y: height, z: depth } = size + const { texture, fitX, fitY } = textureDef const group = new Group() @@ -97,8 +104,6 @@ const createSouthWall = (size: Vector3, texture: TextureOrMaterial, tileSize: nu }) wall.translateZ(-depth / 2).translateY(-height / 2) wall.rotateX(MathUtils.degToRad(90)).rotateZ(MathUtils.degToRad(180)) - const fitX = false - const fitY = texture.filename.toLowerCase().includes('forest') if (fitX) { scaleUV(new Vector2(tileSize / width, tileSize / width), wall.geometry) } else if (fitY) { @@ -112,7 +117,7 @@ const createSouthWall = (size: Vector3, texture: TextureOrMaterial, tileSize: nu const decalOnWall = createPlaneMesh({ size: new Vector2(width, tileSize), tileSize, - texture: Material.fromTexture(decal, { + texture: Material.fromTexture(decal.texture, { flags: ArxPolygonFlags.Tiled, }), tileUV: !texture.filename.toLowerCase().includes('forest'), @@ -126,8 +131,9 @@ const createSouthWall = (size: Vector3, texture: TextureOrMaterial, tileSize: nu return group } -const createWestWall = (size: Vector3, texture: TextureOrMaterial, tileSize: number, decal?: TextureOrMaterial) => { +const createWestWall = (size: Vector3, textureDef: TextureDefinition, tileSize: number, decal?: TextureDefinition) => { const { x: width, y: height, z: depth } = size + const { texture, fitX, fitY } = textureDef const group = new Group() @@ -140,8 +146,6 @@ const createWestWall = (size: Vector3, texture: TextureOrMaterial, tileSize: num }) wall.translateX(-width / 2).translateY(-height / 2) wall.rotateX(MathUtils.degToRad(90)).rotateZ(MathUtils.degToRad(90)) - const fitX = false - const fitY = texture.filename.toLowerCase().includes('forest') if (fitX) { scaleUV(new Vector2(tileSize / width, tileSize / width), wall.geometry) } else if (fitY) { @@ -155,7 +159,7 @@ const createWestWall = (size: Vector3, texture: TextureOrMaterial, tileSize: num const decalOnWall = createPlaneMesh({ size: new Vector2(depth, tileSize), tileSize, - texture: Material.fromTexture(decal, { + texture: Material.fromTexture(decal.texture, { flags: ArxPolygonFlags.Tiled, }), tileUV: !texture.filename.toLowerCase().includes('forest'), @@ -169,8 +173,9 @@ const createWestWall = (size: Vector3, texture: TextureOrMaterial, tileSize: num return group } -const createEastWall = (size: Vector3, texture: TextureOrMaterial, tileSize: number, decal?: TextureOrMaterial) => { +const createEastWall = (size: Vector3, textureDef: TextureDefinition, tileSize: number, decal?: TextureDefinition) => { const { x: width, y: height, z: depth } = size + const { texture, fitX, fitY } = textureDef const group = new Group() @@ -183,8 +188,6 @@ const createEastWall = (size: Vector3, texture: TextureOrMaterial, tileSize: num }) wall.translateX(width / 2).translateY(-height / 2) wall.rotateX(MathUtils.degToRad(90)).rotateZ(MathUtils.degToRad(-90)) - const fitX = false - const fitY = texture.filename.toLowerCase().includes('forest') if (fitX) { scaleUV(new Vector2(tileSize / width, tileSize / width), wall.geometry) } else if (fitY) { @@ -198,7 +201,7 @@ const createEastWall = (size: Vector3, texture: TextureOrMaterial, tileSize: num const decalOnWall = createPlaneMesh({ size: new Vector2(depth, tileSize), tileSize, - texture: Material.fromTexture(decal, { + texture: Material.fromTexture(decal.texture, { flags: ArxPolygonFlags.Tiled, }), tileUV: !texture.filename.toLowerCase().includes('forest'), @@ -212,8 +215,9 @@ const createEastWall = (size: Vector3, texture: TextureOrMaterial, tileSize: num return group } -const createCeiling = (size: Vector3, texture: TextureOrMaterial, tileSize: number) => { +const createCeiling = (size: Vector3, textureDef: TextureDefinition, tileSize: number) => { const { x: width, y: height, z: depth } = size + const { texture } = textureDef const mesh = createPlaneMesh({ size: new Vector2(width, depth),