From 4a2aecf9c8f94276121cb4fb240ff77cfc845f74 Mon Sep 17 00:00:00 2001 From: austin Date: Wed, 14 May 2025 19:47:36 -0400 Subject: [PATCH] furniture placement cursor --- docs/src/progress/renderertodo.md | 2 + .../controls/cursor/CursorState.java | 65 +++++++++++++++++++ .../data/common/CommonEntityType.java | 8 +++ .../java/electrosphere/data/item/Item.java | 5 ++ .../state/equip/ClientToolbarState.java | 7 ++ 5 files changed, 87 insertions(+) diff --git a/docs/src/progress/renderertodo.md b/docs/src/progress/renderertodo.md index 5312972b..104e8eca 100644 --- a/docs/src/progress/renderertodo.md +++ b/docs/src/progress/renderertodo.md @@ -1777,6 +1777,8 @@ Break out collidable template edit into dedicated component Fix virtual scrollable Fix engine not closing when X button is hit on main menu Sorting imgui debug windows +Grid alignment cursor +Furniture spawner items triggers grid alignment cursor diff --git a/src/main/java/electrosphere/controls/cursor/CursorState.java b/src/main/java/electrosphere/controls/cursor/CursorState.java index 89071780..f1affe7d 100644 --- a/src/main/java/electrosphere/controls/cursor/CursorState.java +++ b/src/main/java/electrosphere/controls/cursor/CursorState.java @@ -10,6 +10,7 @@ import electrosphere.client.entity.camera.CameraEntityUtils; import electrosphere.client.interact.select.AreaSelection; import electrosphere.collision.CollisionEngine; import electrosphere.data.block.BlockFab; +import electrosphere.data.grident.GridAlignedData; import electrosphere.data.item.Item; import electrosphere.engine.Globals; import electrosphere.engine.assetmanager.AssetDataStrings; @@ -50,6 +51,11 @@ public class CursorState { */ public static final String CURSOR_FAB_TOKEN = "CURSOR_FAB"; + /** + * Cursor that displays a grid-aligned model + */ + public static final String CURSOR_GRID_ALIGNED_TOKEN = "CURSOR_GRID_ALIGNED"; + /** * Minimum size of the block cursor */ @@ -91,6 +97,16 @@ public class CursorState { */ static Entity playerFabCursor; + /** + * The grid-aligned cursor + */ + static Entity playerGridAlignedCursor; + + /** + * Data for the grid alignment + */ + private GridAlignedData gridAlignmentData; + /** * Maximum value to rotate to */ @@ -151,6 +167,14 @@ public class CursorState { fabCursorActor.addTextureMask(new ActorTextureMask("cube", Arrays.asList(new String[]{AssetDataStrings.TEXTURE_RED_TRANSPARENT}))); DrawableUtils.makeEntityTransparent(playerFabCursor); Globals.clientSceneWrapper.getScene().removeEntityFromTag(playerFabCursor, EntityTags.DRAWABLE); + + //player's grid-aligned cursor + playerGridAlignedCursor = EntityCreationUtils.createClientSpatialEntity(); + EntityCreationUtils.makeEntityDrawable(playerGridAlignedCursor, AssetDataStrings.UNITCUBE); + Actor gridAlignedCursorActor = EntityUtils.getActor(playerGridAlignedCursor); + gridAlignedCursorActor.addTextureMask(new ActorTextureMask("cube", Arrays.asList(new String[]{AssetDataStrings.TEXTURE_RED_TRANSPARENT}))); + DrawableUtils.makeEntityTransparent(playerGridAlignedCursor); + Globals.clientSceneWrapper.getScene().removeEntityFromTag(playerGridAlignedCursor, EntityTags.DRAWABLE); } /** @@ -180,6 +204,10 @@ public class CursorState { EntityUtils.getPosition(Globals.playerBlockCursor).set(cursorPos); cursorPos.sub(BlockChunkData.BLOCK_SIZE_MULTIPLIER / 2.0,BlockChunkData.BLOCK_SIZE_MULTIPLIER / 2.0,BlockChunkData.BLOCK_SIZE_MULTIPLIER / 2.0); EntityUtils.getPosition(CursorState.playerFabCursor).set(cursorPos); + if(gridAlignmentData != null){ + CursorState.nudgeGridAlignment(cursorPos,gridAlignmentData); + } + EntityUtils.getPosition(CursorState.playerGridAlignedCursor).set(cursorPos); } } @@ -219,6 +247,17 @@ public class CursorState { Globals.cursorState.fabCursorRotation = 0; } + /** + * Makes the grid-aligned placement cursor visible + */ + public static void makeGridAlignedVisible(String modelPath){ + CursorState.hide(); + Globals.cursorState.setClampToExistingBlock(true); + Globals.clientSceneWrapper.getScene().registerEntityToTag(CursorState.playerGridAlignedCursor, EntityTags.DRAWABLE); + EntityCreationUtils.makeEntityDrawable(playerGridAlignedCursor, modelPath); + Globals.cursorState.fabCursorRotation = 0; + } + /** * Hides the cursor */ @@ -227,6 +266,7 @@ public class CursorState { Globals.clientSceneWrapper.getScene().removeEntityFromTag(Globals.playerBlockCursor, EntityTags.DRAWABLE); Globals.clientSceneWrapper.getScene().removeEntityFromTag(Globals.playerAreaCursor, EntityTags.DRAWABLE); Globals.clientSceneWrapper.getScene().removeEntityFromTag(CursorState.playerFabCursor, EntityTags.DRAWABLE); + Globals.clientSceneWrapper.getScene().removeEntityFromTag(CursorState.playerGridAlignedCursor, EntityTags.DRAWABLE); } /** @@ -301,6 +341,23 @@ public class CursorState { return new Vector3d(x,y,z); } + /** + * Nudges the position to align with the grid alignment data + * @param position The position + * @param data The data + */ + private static void nudgeGridAlignment(Vector3d position, GridAlignedData data){ + if(data.getWidth() / 2 == 1){ + position.x = position.x + BlockChunkData.BLOCK_SIZE_MULTIPLIER / 2.0f; + } + if(data.getHeight() / 2 == 1){ + position.y = position.y + BlockChunkData.BLOCK_SIZE_MULTIPLIER / 2.0f; + } + if(data.getLength() / 2 == 1){ + position.z = position.z + BlockChunkData.BLOCK_SIZE_MULTIPLIER / 2.0f; + } + } + /** * Gets the block cursor position * @return The block cursor position @@ -536,5 +593,13 @@ public class CursorState { public int getFabCursorRotation(){ return this.fabCursorRotation; } + + /** + * Sets the grid alignment data + * @param gridAlignedData The grid alignment data + */ + public void setGridAlignmentData(GridAlignedData gridAlignedData){ + this.gridAlignmentData = gridAlignedData; + } } diff --git a/src/main/java/electrosphere/data/common/CommonEntityType.java b/src/main/java/electrosphere/data/common/CommonEntityType.java index a8fdf88e..22137ce1 100644 --- a/src/main/java/electrosphere/data/common/CommonEntityType.java +++ b/src/main/java/electrosphere/data/common/CommonEntityType.java @@ -443,6 +443,14 @@ public class CommonEntityType { return gridAlignedData; } + /** + * Sets the grid-aligned data + * @param data The grid-aligned data + */ + public void setGridAlignedData(GridAlignedData data){ + this.gridAlignedData = data; + } + /** * Gets the data for furniture behaviors * @return The data for furniture behaviors diff --git a/src/main/java/electrosphere/data/item/Item.java b/src/main/java/electrosphere/data/item/Item.java index c4534593..e98c83ec 100644 --- a/src/main/java/electrosphere/data/item/Item.java +++ b/src/main/java/electrosphere/data/item/Item.java @@ -113,6 +113,11 @@ public class Item extends CommonEntityType { rVal.setMaxStack(Item.SPAWN_ITEM_DEFAULT_MAX_STACK); } + //grid-alignment data + if(objectData.getGridAlignedData() != null){ + rVal.setGridAlignedData(objectData.getGridAlignedData()); + } + if(description.getItemIcon() != null){ rVal.iconPath = description.getItemIcon(); diff --git a/src/main/java/electrosphere/entity/state/equip/ClientToolbarState.java b/src/main/java/electrosphere/entity/state/equip/ClientToolbarState.java index 82cd429e..fc991d76 100644 --- a/src/main/java/electrosphere/entity/state/equip/ClientToolbarState.java +++ b/src/main/java/electrosphere/entity/state/equip/ClientToolbarState.java @@ -197,6 +197,13 @@ public class ClientToolbarState implements BehaviorTree { Globals.cursorState.setSelectedFab(BlockFab.read(FileUtils.getAssetFile(itemData.getFabData().getFabPath()))); Globals.cursorState.setSelectedFabPath(FileUtils.getAssetFileString(itemData.getFabData().getFabPath())); CursorState.makeFabVisible(); + } else if(itemData.getGridAlignedData() != null){ + String modelPath = AssetDataStrings.UNITCUBE; + if(itemData.getGraphicsTemplate() != null && itemData.getGraphicsTemplate().getModel() != null){ + modelPath = itemData.getGraphicsTemplate().getModel().getPath(); + } + Globals.cursorState.setGridAlignmentData(itemData.getGridAlignedData()); + CursorState.makeGridAlignedVisible(modelPath); } } }