structure editing tab
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good
This commit is contained in:
parent
4c6c30db0f
commit
1ded83c968
@ -1581,6 +1581,8 @@ Grid alignment actually aligns entity to grid
|
||||
|
||||
(04/29/2025)
|
||||
Fix door tree physics
|
||||
BlockFab metadata
|
||||
Structure editing tab in editor view
|
||||
|
||||
|
||||
|
||||
|
||||
@ -79,6 +79,16 @@ public class ClientBlockSelection {
|
||||
* Exports currently selected area of voxels
|
||||
*/
|
||||
public static void exportSelection(){
|
||||
BlockFab fab = ClientBlockSelection.convertSelectionToFab();
|
||||
File exportLoc = new File("./assets/Data/fab/struct.block");
|
||||
fab.write(exportLoc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the current selection by the player into a fab
|
||||
* @return The fab
|
||||
*/
|
||||
public static BlockFab convertSelectionToFab(){
|
||||
AreaSelection selection = Globals.cursorState.getAreaSelection();
|
||||
Vector3i startChunk = Globals.clientWorldData.convertRealToWorldSpace(selection.getRectStart());
|
||||
Vector3i endChunk = Globals.clientWorldData.convertRealToWorldSpace(selection.getRectEnd());
|
||||
@ -114,8 +124,7 @@ public class ClientBlockSelection {
|
||||
);
|
||||
|
||||
BlockFab fab = BlockFab.create(dimensions, types, metadata);
|
||||
File exportLoc = new File("./assets/Data/fab/struct.block");
|
||||
fab.write(exportLoc);
|
||||
return fab;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,56 @@
|
||||
package electrosphere.client.leveledit;
|
||||
|
||||
import org.joml.Vector3d;
|
||||
|
||||
import electrosphere.game.data.block.BlockFab;
|
||||
|
||||
/**
|
||||
* Stores the data for the client's level edits
|
||||
*/
|
||||
public class ClientLevelEditorData {
|
||||
|
||||
/**
|
||||
* The currently edited fab
|
||||
*/
|
||||
private BlockFab currentFab;
|
||||
|
||||
/**
|
||||
* The origin point of the current fab
|
||||
*/
|
||||
private Vector3d currentFabOrigin;
|
||||
|
||||
/**
|
||||
* Gets the currently edited fab
|
||||
* @return The fab if it exists, null otherwise
|
||||
*/
|
||||
public BlockFab getCurrentFab() {
|
||||
return currentFab;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the fab currently being edited
|
||||
* @param currentFab The fab
|
||||
*/
|
||||
public void setCurrentFab(BlockFab currentFab) {
|
||||
this.currentFab = currentFab;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the origin point of the current fab
|
||||
* @return The origin point
|
||||
*/
|
||||
public Vector3d getCurrentFabOrigin() {
|
||||
return currentFabOrigin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the origin point of the current fab
|
||||
* @param currentFabOrigin The origin point
|
||||
*/
|
||||
public void setCurrentFabOrigin(Vector3d currentFabOrigin) {
|
||||
this.currentFabOrigin = currentFabOrigin;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@ -18,6 +18,9 @@ public class ImGuiAreaTab {
|
||||
if(ImGui.button("Export Selected Blocks")){
|
||||
ClientBlockSelection.exportSelection();
|
||||
}
|
||||
if(ImGui.button("Add Area Selection As Room")){
|
||||
ClientBlockSelection.exportSelection();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -32,10 +32,27 @@ public class ImGuiEditorDetailsWindow {
|
||||
detailsWindow.setCallback(new ImGuiWindowCallback() {
|
||||
@Override
|
||||
public void exec() {
|
||||
ImGui.text("Some details or smthn");
|
||||
//close button
|
||||
if(ImGui.button("Close")){
|
||||
detailsWindow.setOpen(false);
|
||||
switch(ImGuiEditorWindows.getCurrentTab()){
|
||||
case 0: {
|
||||
//general tab
|
||||
ImGui.text("General tab");
|
||||
} break;
|
||||
case 1: {
|
||||
//assets tab
|
||||
ImGui.text("Asset tab");
|
||||
} break;
|
||||
case 2: {
|
||||
//hierarchy tab
|
||||
ImGui.text("Hierarchy tab");
|
||||
} break;
|
||||
case 3: {
|
||||
//area tab
|
||||
ImGui.text("Area tab");
|
||||
} break;
|
||||
case 4: {
|
||||
//structure tab
|
||||
ImGuiStructureTab.drawDetails();
|
||||
} break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@ -19,6 +19,11 @@ public class ImGuiEditorWindows {
|
||||
//tracks if the editor menu is open
|
||||
private static boolean editorIsOpen = false;
|
||||
|
||||
/**
|
||||
* The current tab
|
||||
*/
|
||||
private static int currentTab = 0;
|
||||
|
||||
/**
|
||||
* Initializes imgui windows
|
||||
*/
|
||||
@ -46,10 +51,12 @@ public class ImGuiEditorWindows {
|
||||
public void exec() {
|
||||
if(ImGui.beginTabBar("Tabs")){
|
||||
if(ImGui.beginTabItem("General")){
|
||||
currentTab = 0;
|
||||
ImGui.text("hello :)");
|
||||
ImGui.endTabItem();
|
||||
}
|
||||
if(ImGui.beginTabItem("Assets")){
|
||||
currentTab = 1;
|
||||
ImGui.text("asset selector here");
|
||||
if(ImGui.button("testasset")){
|
||||
|
||||
@ -61,13 +68,20 @@ public class ImGuiEditorWindows {
|
||||
ImGui.endTabItem();
|
||||
}
|
||||
if(ImGui.beginTabItem("Hierarchy")){
|
||||
currentTab = 2;
|
||||
ImGui.text("hierarchy controls here");
|
||||
ImGui.endTabItem();
|
||||
}
|
||||
if(ImGui.beginTabItem("Areas")){
|
||||
currentTab = 3;
|
||||
ImGuiAreaTab.draw();
|
||||
ImGui.endTabItem();
|
||||
}
|
||||
if(ImGui.beginTabItem("Structure")){
|
||||
currentTab = 4;
|
||||
ImGuiStructureTab.draw();
|
||||
ImGui.endTabItem();
|
||||
}
|
||||
|
||||
ImGui.endTabBar();
|
||||
}
|
||||
@ -105,4 +119,12 @@ public class ImGuiEditorWindows {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current tab
|
||||
* @return The current tab
|
||||
*/
|
||||
protected static int getCurrentTab(){
|
||||
return currentTab;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,75 @@
|
||||
package electrosphere.client.ui.menu.editor;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.joml.Vector3d;
|
||||
|
||||
import electrosphere.client.block.ClientBlockSelection;
|
||||
import electrosphere.client.interact.select.AreaSelection;
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.game.data.block.BlockFab;
|
||||
import electrosphere.game.data.block.BlockFabMetadata;
|
||||
import imgui.ImGui;
|
||||
|
||||
/**
|
||||
* Tab for editing structures
|
||||
*/
|
||||
public class ImGuiStructureTab {
|
||||
|
||||
/**
|
||||
* Draws the contents of the structure tab
|
||||
*/
|
||||
protected static void draw(){
|
||||
if(Globals.clientLevelEditorData.getCurrentFab() == null){
|
||||
ImGui.text("No structure currently being edited");
|
||||
if(ImGui.button("Discover structure")){
|
||||
ClientBlockSelection.selectAllBlocks();
|
||||
AreaSelection area = Globals.cursorState.getAreaSelection();
|
||||
if(area != null){
|
||||
BlockFab blockFab = ClientBlockSelection.convertSelectionToFab();
|
||||
Globals.clientLevelEditorData.setCurrentFab(blockFab);
|
||||
Globals.clientLevelEditorData.setCurrentFabOrigin(area.getRectStart());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
BlockFab currentFab = Globals.clientLevelEditorData.getCurrentFab();
|
||||
if(ImGui.button("Convert current selection to room")){
|
||||
AreaSelection currentSelection = Globals.cursorState.getAreaSelection();
|
||||
if(currentSelection != null){
|
||||
currentFab.getFabMetadata().getAreas().add(currentSelection);
|
||||
}
|
||||
}
|
||||
if(ImGui.button("Save")){
|
||||
File exportLoc = new File("./assets/Data/fab/struct.block");
|
||||
currentFab.write(exportLoc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws the details tab
|
||||
*/
|
||||
protected static void drawDetails(){
|
||||
if(Globals.clientLevelEditorData.getCurrentFab() == null){
|
||||
ImGui.text("Select a fab to show details here");
|
||||
} else {
|
||||
BlockFab currentFab = Globals.clientLevelEditorData.getCurrentFab();
|
||||
ImGui.text("Origin: " + Globals.clientLevelEditorData.getCurrentFabOrigin());
|
||||
ImGui.text("Dimensions: " + currentFab.getDimensions());
|
||||
BlockFabMetadata fabMetadata = currentFab.getFabMetadata();
|
||||
if(fabMetadata.getAreas() != null){
|
||||
if(ImGui.collapsingHeader("Areas in fab: " + fabMetadata.getAreas().size())){
|
||||
int i = 0;
|
||||
for(AreaSelection area : fabMetadata.getAreas()){
|
||||
Vector3d dims = new Vector3d(area.getRectEnd()).sub(area.getRectStart());
|
||||
ImGui.text("Area " + i + " dimensions " + dims);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ImGui.text("Areas undefined in metadata");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -506,7 +506,11 @@ public class CursorState {
|
||||
* Hints to show the block cursor
|
||||
*/
|
||||
public void hintShowBlockCursor(){
|
||||
if(!Globals.clientSceneWrapper.getScene().getEntitiesWithTag(EntityTags.DRAWABLE).contains(CursorState.playerFabCursor)){
|
||||
if(
|
||||
!Globals.clientSceneWrapper.getScene().getEntitiesWithTag(EntityTags.DRAWABLE).contains(CursorState.playerFabCursor) &&
|
||||
!Globals.clientSceneWrapper.getScene().getEntitiesWithTag(EntityTags.DRAWABLE).contains(Globals.playerAreaCursor) &&
|
||||
!Globals.clientSceneWrapper.getScene().getEntitiesWithTag(EntityTags.DRAWABLE).contains(Globals.playerCursor)
|
||||
){
|
||||
CursorState.makeBlockVisible(AssetDataStrings.TEXTURE_RED_TRANSPARENT);
|
||||
}
|
||||
}
|
||||
|
||||
@ -20,6 +20,7 @@ import electrosphere.client.entity.character.ClientCharacterManager;
|
||||
import electrosphere.client.entity.particle.ParticleService;
|
||||
import electrosphere.client.fluid.cells.FluidCellManager;
|
||||
import electrosphere.client.fluid.manager.ClientFluidManager;
|
||||
import electrosphere.client.leveledit.ClientLevelEditorData;
|
||||
import electrosphere.client.player.ClientPlayerData;
|
||||
import electrosphere.client.scene.ClientSceneWrapper;
|
||||
import electrosphere.client.scene.ClientWorldData;
|
||||
@ -399,6 +400,9 @@ public class Globals {
|
||||
|
||||
//structure manager
|
||||
public static StructureManager structureManager;
|
||||
|
||||
//client level editor data management
|
||||
public static ClientLevelEditorData clientLevelEditorData = new ClientLevelEditorData();
|
||||
|
||||
|
||||
//the player camera entity
|
||||
|
||||
@ -8,6 +8,8 @@ import java.nio.ShortBuffer;
|
||||
|
||||
import org.joml.Vector3i;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
|
||||
import electrosphere.client.block.BlockChunkData;
|
||||
import electrosphere.logger.LoggerInterface;
|
||||
import electrosphere.renderer.meshgen.BlockMeshgenData;
|
||||
@ -21,7 +23,7 @@ public class BlockFab implements BlockMeshgenData {
|
||||
/**
|
||||
* File version format
|
||||
*/
|
||||
public static final int FILE_VER = 1;
|
||||
public static final int FILE_VER = 2;
|
||||
|
||||
/**
|
||||
* Size of the header for a block fab file
|
||||
@ -47,6 +49,11 @@ public class BlockFab implements BlockMeshgenData {
|
||||
* Block metadata
|
||||
*/
|
||||
short[] metadata;
|
||||
|
||||
/**
|
||||
* The metadata of the fab
|
||||
*/
|
||||
BlockFabMetadata fabMetadata;
|
||||
|
||||
/**
|
||||
* Creates a block fab
|
||||
@ -60,6 +67,7 @@ public class BlockFab implements BlockMeshgenData {
|
||||
rVal.dimensions = dimensions;
|
||||
rVal.types = types;
|
||||
rVal.metadata = metadata;
|
||||
rVal.fabMetadata = new BlockFabMetadata();
|
||||
return rVal;
|
||||
}
|
||||
|
||||
@ -70,8 +78,11 @@ public class BlockFab implements BlockMeshgenData {
|
||||
public void write(File file){
|
||||
int blockCount = dimensions.x * dimensions.y * dimensions.z;
|
||||
|
||||
Gson gson = new Gson();
|
||||
String serializedMetadata = gson.toJson(this.fabMetadata);
|
||||
byte[] serializedMetadataBytes = serializedMetadata.getBytes();
|
||||
|
||||
ByteBuffer buff = ByteBuffer.allocate(HEADER_SIZE + blockCount * BlockChunkData.BYTES_PER_BLOCK);
|
||||
ByteBuffer buff = ByteBuffer.allocate(HEADER_SIZE + blockCount * BlockChunkData.BYTES_PER_BLOCK + serializedMetadataBytes.length);
|
||||
|
||||
IntBuffer intView = buff.asIntBuffer();
|
||||
intView.put(FILE_VER);
|
||||
@ -84,6 +95,8 @@ public class BlockFab implements BlockMeshgenData {
|
||||
|
||||
shortView.put(types);
|
||||
shortView.put(metadata);
|
||||
buff.position(HEADER_SIZE + types.length * 2 + metadata.length * 2);
|
||||
buff.put(serializedMetadataBytes);
|
||||
shortView.flip();
|
||||
|
||||
try {
|
||||
@ -106,6 +119,9 @@ public class BlockFab implements BlockMeshgenData {
|
||||
IntBuffer intView = buff.asIntBuffer();
|
||||
int fileVer = intView.get();
|
||||
LoggerInterface.loggerFileIO.DEBUG("Read fab file with ver " + fileVer);
|
||||
if(fileVer != FILE_VER){
|
||||
LoggerInterface.loggerFileIO.WARNING("Reading unsupported fab file with version: " + fileVer);
|
||||
}
|
||||
|
||||
int dimX = intView.get();
|
||||
int dimY = intView.get();
|
||||
@ -137,10 +153,25 @@ public class BlockFab implements BlockMeshgenData {
|
||||
}
|
||||
}
|
||||
|
||||
//read the fab metadata
|
||||
buff.position(HEADER_SIZE + blockCount * 2 + blockCount * 2);
|
||||
BlockFabMetadata fabMetadata = new BlockFabMetadata();
|
||||
if(buff.remaining() > 0){
|
||||
byte[] fabMetadataBytes = new byte[buff.remaining()];
|
||||
buff.get(fabMetadataBytes);
|
||||
String fabMetadataString = new String(fabMetadataBytes);
|
||||
Gson gson = new Gson();
|
||||
fabMetadata = gson.fromJson(fabMetadataString, BlockFabMetadata.class);
|
||||
} else {
|
||||
LoggerInterface.loggerFileIO.WARNING("Fab file does not have metadata defined! " + file.getAbsolutePath());
|
||||
}
|
||||
|
||||
//construct returned object
|
||||
rVal = new BlockFab();
|
||||
rVal.dimensions = dims;
|
||||
rVal.types = types;
|
||||
rVal.metadata = metadata;
|
||||
rVal.fabMetadata = fabMetadata;
|
||||
} catch (IOException e) {
|
||||
LoggerInterface.loggerFileIO.ERROR(e);
|
||||
throw new Error("Failed to read BlockFab " + file);
|
||||
@ -183,4 +214,12 @@ public class BlockFab implements BlockMeshgenData {
|
||||
return this.types[x * dimensions.y * dimensions.z + y * dimensions.z + z];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the fab metadata for the fab
|
||||
* @return The metadata
|
||||
*/
|
||||
public BlockFabMetadata getFabMetadata(){
|
||||
return fabMetadata;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,42 @@
|
||||
package electrosphere.game.data.block;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import electrosphere.client.interact.select.AreaSelection;
|
||||
|
||||
/**
|
||||
* Metdata associated with the fab
|
||||
*/
|
||||
public class BlockFabMetadata {
|
||||
|
||||
/**
|
||||
* Area data for the fab
|
||||
*/
|
||||
private List<AreaSelection> areas;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
protected BlockFabMetadata(){
|
||||
this.areas = new LinkedList<AreaSelection>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the areas defined in the metadata
|
||||
* @return The areas
|
||||
*/
|
||||
public List<AreaSelection> getAreas() {
|
||||
return areas;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the areas defined in the metadata
|
||||
* @param areas The areas
|
||||
*/
|
||||
public void setAreas(List<AreaSelection> areas) {
|
||||
this.areas = areas;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user