fab items
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good

This commit is contained in:
austin 2025-04-29 21:39:48 -04:00
parent ec7c1371c2
commit c083aaf05f
14 changed files with 203 additions and 7 deletions

View File

@ -7,6 +7,7 @@
"Data/entity/items/debug_tools.json",
"Data/entity/items/hand_tools.json",
"Data/entity/items/clothing.json",
"Data/entity/items/materials.json"
"Data/entity/items/materials.json",
"Data/entity/items/fabs.json"
]
}

View File

@ -0,0 +1,7 @@
{
"items" : [
],
"files" : [
"Data/entity/items/fabs/floors.json"
]
}

View File

@ -0,0 +1,40 @@
{
"items" : [
{
"id" : "woodfloor",
"tokens" : [
"GRAVITY",
"TARGETABLE"
],
"fabData" : {
"fabPath" : "Data/fab/wood_refined_floor.block"
},
"clientSideSecondary" : "PLACE_FAB",
"itemAudio": {
"uiGrabAudio" : "Audio/ui/items/specific/Pick Up Wood A.wav",
"uiReleaseAudio" : "Audio/ui/items/specific/Drop Wood A.wav"
},
"graphicsTemplate": {
"model": {
"path" : "Models/items/minicrate.glb"
}
},
"collidable": {
"type" : "CUBE",
"dimension1" : 0.1,
"dimension2" : 0.1,
"dimension3" : 0.35,
"rotX": 0,
"rotY": 0,
"rotZ": 0,
"rotW": 1,
"offsetX" : 0,
"offsetY" : 0.05,
"offsetZ" : 0
},
"iconPath" : "Textures/icons/itemIconItemGeneric.png"
}
],
"files" : [
]
}

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 981 KiB

View File

@ -1602,6 +1602,7 @@ Flower foliage item
Texture loading from model files (ie can load texture path from model file)
Clean up material class a bit
Cleaning up dead code
Fab items

View File

@ -48,6 +48,11 @@ public class AssetDataStrings {
public static final String UI_FRAME_TEXTURE_DEFAULT_2 = "Textures/ui/uiFrame2.png";
public static final String UI_FRAME_TEXTURE_DEFAULT_3 = "Textures/ui/panel-001.png";
/**
* UI icon textures
*/
public static final String UI_TEXTURE_ITEM_ICON_GENERIC = "Textures/icons/itemIconItemGeneric.png";
/**
* UI generic audio
*/

View File

@ -211,6 +211,11 @@ public class EntityDataStrings {
public static final String ITEM_CONTAINING_PARENT = "itemContainingParent";
public static final String TREE_SERVERCHARGESTATE = "treeServerChargeState";
public static final String TREE_CLIENTCHARGESTATE = "treeClientChargeState";
/**
* Data for placing fabs with an item
*/
public static final String ITEM_FAB_DATA = "itemFabData";
/*

View File

@ -9,6 +9,7 @@ import electrosphere.entity.state.inventory.InventoryUtils;
import electrosphere.entity.state.inventory.RelationalInventoryState;
import electrosphere.entity.types.creature.CreatureUtils;
import electrosphere.entity.types.item.ItemUtils;
import electrosphere.game.data.block.BlockFab;
import electrosphere.game.data.common.treedata.TreeDataAnimation;
import electrosphere.game.data.creature.type.equip.EquipPoint;
import electrosphere.game.data.creature.type.equip.ToolbarData;
@ -31,6 +32,7 @@ import electrosphere.entity.EntityUtils;
import electrosphere.net.synchronization.enums.BehaviorTreeIdEnums;
import electrosphere.renderer.actor.Actor;
import electrosphere.renderer.actor.ActorMeshMask;
import electrosphere.util.FileUtils;
import electrosphere.net.parser.net.message.InventoryMessage;
import electrosphere.net.parser.net.message.NetworkMessage;
import electrosphere.net.synchronization.annotation.SyncedField;
@ -191,6 +193,10 @@ public class ClientToolbarState implements BehaviorTree {
} else if(itemData.getTokens().contains(CursorState.CURSOR_BLOCK_TOKEN)) {
Globals.cursorState.setClampToExistingBlock(true);
CursorState.makeBlockVisible(AssetDataStrings.TEXTURE_RED_TRANSPARENT);
} else if(itemData.getFabData() != null){
Globals.cursorState.setSelectedFab(BlockFab.read(FileUtils.getAssetFile(itemData.getFabData().getFabPath())));
Globals.cursorState.setSelectedFabPath(FileUtils.getAssetFileString(itemData.getFabData().getFabPath()));
CursorState.makeFabVisible();
}
}
}

View File

@ -7,9 +7,9 @@ import org.joml.Vector3d;
import org.ode4j.ode.DBody;
import electrosphere.collision.PhysicsEntityUtils;
import electrosphere.collision.PhysicsUtils;
import electrosphere.collision.collidable.Collidable;
import electrosphere.engine.Globals;
import electrosphere.engine.assetmanager.AssetDataStrings;
import electrosphere.entity.ClientEntityUtils;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityCreationUtils;
@ -47,9 +47,11 @@ import electrosphere.server.entity.poseactor.PoseActor;
*/
public class ItemUtils {
//generic item icon filepath
static final String genericItemIconPath = "Textures/icons/itemIconItemGeneric.png";
/**
* Spawns an item on the client
* @param name The name of the item type
* @return The item entity
*/
public static Entity clientSpawnBasicItem(String name){
Item item = Globals.gameConfigCurrent.getItemMap().getItem(name);
Entity rVal = EntityCreationUtils.createClientSpatialEntity();
@ -81,7 +83,7 @@ public class ItemUtils {
if(item.getIconPath() != null && !item.getIconPath().equals("")){
rVal.putData(EntityDataStrings.ITEM_ICON,item.getIconPath());
} else {
rVal.putData(EntityDataStrings.ITEM_ICON,genericItemIconPath);
rVal.putData(EntityDataStrings.ITEM_ICON,AssetDataStrings.UI_TEXTURE_ITEM_ICON_GENERIC);
}
if(item.getItemAudio() != null){
ItemAudio audio = item.getItemAudio();
@ -108,6 +110,14 @@ public class ItemUtils {
}
}
rVal.putData(EntityDataStrings.ITEM_IS_IN_INVENTORY, false);
//
// Fab data
//
if(item.getFabData() != null){
rVal.putData(EntityDataStrings.ITEM_FAB_DATA, item.getFabData());
}
Globals.clientSceneWrapper.getScene().registerEntityToTag(rVal, EntityTags.ITEM);
return rVal;
@ -174,7 +184,7 @@ public class ItemUtils {
if(item.getIconPath() != null && !item.getIconPath().equals("")){
rVal.putData(EntityDataStrings.ITEM_ICON,item.getIconPath());
} else {
rVal.putData(EntityDataStrings.ITEM_ICON,genericItemIconPath);
rVal.putData(EntityDataStrings.ITEM_ICON,AssetDataStrings.UI_TEXTURE_ITEM_ICON_GENERIC);
}
//
//
@ -191,6 +201,14 @@ public class ItemUtils {
}
}
rVal.putData(EntityDataStrings.ITEM_IS_IN_INVENTORY, false);
//
// Fab data
//
if(item.getFabData() != null){
rVal.putData(EntityDataStrings.ITEM_FAB_DATA, item.getFabData());
}
}
/**

View File

@ -81,6 +81,11 @@ public class Item extends CommonEntityType {
* The usage logic for a secondary usage of this item
*/
ItemUsage secondaryUsage;
/**
* Item fab data
*/
ItemFabData fabData;
/**
* Creates item data from a spawn item description
@ -261,4 +266,12 @@ public class Item extends CommonEntityType {
this.primaryUsage = primaryUsage;
}
/**
* Gets the fab data for this item
* @return The fab data
*/
public ItemFabData getFabData(){
return fabData;
}
}

View File

@ -0,0 +1,29 @@
package electrosphere.game.data.item;
/**
* Data for placing fabs
*/
public class ItemFabData {
/**
* The path for the fab to place when this item is consumed
*/
String fabPath;
/**
* Gets the path for the corresponding fab file
* @return The path for the corresponding fab file
*/
public String getFabPath() {
return fabPath;
}
/**
* Sets the path for the corresponding fab file
* @param fabPath The path for the corresponding fab file
*/
public void setFabPath(String fabPath) {
this.fabPath = fabPath;
}
}

View File

@ -8,6 +8,7 @@ import electrosphere.util.FileUtils;
import org.lwjgl.PointerBuffer;
import org.lwjgl.assimp.AIMaterial;
import org.lwjgl.assimp.AIMaterialProperty;
import org.lwjgl.assimp.AIScene;
import org.lwjgl.assimp.AIString;
import org.lwjgl.assimp.AITexture;
@ -94,6 +95,7 @@ public class Material {
texPaths[i] = tex.mFilename().dataString();
}
//discover diffuse
boolean foundDiffuse = false;
int textureCount = Assimp.aiGetMaterialTextureCount(input, Assimp.aiTextureType_DIFFUSE);
if(textureCount > 0){
//for the time being, only load the first diffuse
@ -118,6 +120,7 @@ public class Material {
rVal.usesFetch = true;
rVal.diffuse = resolved;
Globals.assetManager.addTexturePathtoQueue(rVal.diffuse);
foundDiffuse = true;
}
} else {
String resolved = Material.resolveTexturePath(path, texturePath);
@ -125,6 +128,45 @@ public class Material {
rVal.usesFetch = true;
rVal.diffuse = resolved;
Globals.assetManager.addTexturePathtoQueue(rVal.diffuse);
foundDiffuse = true;
}
}
}
if(!foundDiffuse){
textureCount = Assimp.aiGetMaterialTextureCount(input, Assimp.aiTextureType_BASE_COLOR);
if(textureCount > 0){
//for the time being, only load the first diffuse
int textureIndex = 0;
int retCode = Assimp.aiGetMaterialTexture(input, Assimp.aiTextureType_BASE_COLOR, textureIndex, aiPathString, (IntBuffer)null, null, null, null, null, null);
if(retCode != Assimp.aiReturn_SUCCESS){
throw new Error("Failed to read diffuse! " + textureCount + " " + Assimp.aiGetErrorString());
}
String texturePath = aiPathString.dataString();
if(texturePath == null || texturePath.length() <= 0){
throw new Error("Texture path is empty " + texturePath);
}
if(texturePath.length() == 2 && texturePath.startsWith("*")){
//older versions of Assimp require you to read the INDEX of the texture from the material, then look up that texture in the scene itself
//format looks like "*<index>" ie "*0"
int indexInLoadedTexturePaths = Integer.parseInt(texturePath.substring(1));
if(indexInLoadedTexturePaths >= texPaths.length){
throw new Error("Index discovered is outside the array's length " + indexInLoadedTexturePaths + " " + texPaths.length);
}
String resolved = Material.resolveTexturePath(path, texPaths[indexInLoadedTexturePaths]);
if(resolved != null && resolved.length() > 0){
rVal.usesFetch = true;
rVal.diffuse = resolved;
Globals.assetManager.addTexturePathtoQueue(rVal.diffuse);
foundDiffuse = true;
}
} else {
String resolved = Material.resolveTexturePath(path, texturePath);
if(resolved != null && resolved.length() > 0){
rVal.usesFetch = true;
rVal.diffuse = resolved;
Globals.assetManager.addTexturePathtoQueue(rVal.diffuse);
foundDiffuse = true;
}
}
}
}
@ -135,6 +177,25 @@ public class Material {
return rVal;
}
/**
* Describes the properties of a material
* @param material The material
*/
public static void listMaterialProps(AIMaterial material){
LoggerInterface.loggerRenderer.WARNING("Describing material");
for(int i = 0; i < material.mNumProperties(); i++){
AIMaterialProperty prop = AIMaterialProperty.create(material.mProperties().get(i));
String key = prop.mKey().dataString();
int propType = prop.mSemantic();
if(propType == Assimp.aiTextureType_NONE){
//non-texture prop
LoggerInterface.loggerRenderer.WARNING("Prop \"" + key + "\" is not a texture");
} else {
LoggerInterface.loggerRenderer.WARNING("Prop \"" + key + "\" is a texture");
}
}
}
/**
* Resolves the filepath of the texture
* @param path The path of the ai scene itself

View File

@ -209,6 +209,16 @@ public class FileUtils {
return targetFile;
}
/**
* Gets an assets file
* @param pathName The relative path in the assets folder
* @return The file
*/
public static String getAssetFileString(String pathName){
String sanitizedFilePath = sanitizeFilePath(pathName);
return "./assets" + sanitizedFilePath;
}
/**
* Gets an assets file as a byte buffer
* @param pathName The relative path in the assets folder