feat: item models generation simple & remove core:item_models
This commit is contained in:
parent
7a5fe3b2b0
commit
fae372d19f
@ -1,5 +1,3 @@
|
||||
local item_models = require "core:item_models"
|
||||
|
||||
local tsf = entity.transform
|
||||
local body = entity.rigidbody
|
||||
local rig = entity.skeleton
|
||||
@ -27,7 +25,7 @@ end
|
||||
|
||||
do -- setup visuals
|
||||
local matrix = mat4.idt()
|
||||
scale = item_models.setup(dropitem.id, rig, 0)
|
||||
rig:set_model(0, item.name(dropitem.id)..".model")
|
||||
local bodysize = math.min(scale[1], scale[2], scale[3]) * DROP_SCALE
|
||||
body:set_size({scale[1] * DROP_SCALE, bodysize, scale[3] * DROP_SCALE})
|
||||
mat4.mul(matrix, rotation, matrix)
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
local item_models = require "core:item_models"
|
||||
|
||||
local tsf = entity.transform
|
||||
local body = entity.rigidbody
|
||||
local rig = entity.skeleton
|
||||
@ -9,12 +7,7 @@ local itemIndex = rig:index("item")
|
||||
|
||||
local function refresh_model(id)
|
||||
itemid = id
|
||||
if id == 0 then
|
||||
rig:set_model(itemIndex, "")
|
||||
else
|
||||
local scale = item_models.setup(itemid, rig, itemIndex)
|
||||
rig:set_matrix(itemIndex, mat4.scale(scale))
|
||||
end
|
||||
rig:set_model(itemIndex, item.name(itemid)..".model")
|
||||
end
|
||||
|
||||
function on_render()
|
||||
|
||||
@ -1,33 +0,0 @@
|
||||
local function setup(id, rig, index)
|
||||
rig:set_model(index, "drop-block")
|
||||
local icon = item.icon(id)
|
||||
local size = {1.0, 1.0, 1.0}
|
||||
if icon:find("^block%-previews%:") then
|
||||
local bid = block.index(icon:sub(16))
|
||||
model = block.get_model(bid)
|
||||
if model == "X" then
|
||||
size = {1.0, 0.3, 1.0}
|
||||
rig:set_model(index, "drop-item")
|
||||
rig:set_texture("$0", icon)
|
||||
else
|
||||
if model == "aabb" then
|
||||
local rot = block.get_rotation_profile(bid) == "pipe" and 4 or 0
|
||||
size = block.get_hitbox(bid, rot)[2]
|
||||
vec3.mul(size, 2.0, size)
|
||||
end
|
||||
local textures = block.get_textures(bid)
|
||||
for i,t in ipairs(textures) do
|
||||
rig:set_texture("$"..tostring(i-1), "blocks:"..textures[i])
|
||||
end
|
||||
end
|
||||
else
|
||||
size = {1.0, 0.3, 1.0}
|
||||
rig:set_model(index, "drop-item")
|
||||
rig:set_texture("$0", icon)
|
||||
end
|
||||
return size
|
||||
end
|
||||
|
||||
return {
|
||||
setup=setup,
|
||||
}
|
||||
@ -5,11 +5,13 @@
|
||||
#include <optional>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <typeindex>
|
||||
#include <typeinfo>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "util/stringutil.hpp"
|
||||
#include "graphics/core/TextureAnimation.hpp"
|
||||
|
||||
class Assets;
|
||||
@ -84,6 +86,15 @@ public:
|
||||
return static_cast<T*>(found->second.get());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T& require(const std::string& name) const {
|
||||
T* asset = get<T>(name);
|
||||
if (asset == nullptr) {
|
||||
throw std::runtime_error(util::quote(name) + " not found");
|
||||
}
|
||||
return *asset;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
std::optional<const assets_map*> getMap() const {
|
||||
const auto& mapIter = assets.find(typeid(T));
|
||||
|
||||
@ -418,11 +418,11 @@ void ContentLoader::loadItem(
|
||||
std::string iconTypeStr = "";
|
||||
root.at("icon-type").get(iconTypeStr);
|
||||
if (iconTypeStr == "none") {
|
||||
def.iconType = item_icon_type::none;
|
||||
def.iconType = ItemIconType::NONE;
|
||||
} else if (iconTypeStr == "block") {
|
||||
def.iconType = item_icon_type::block;
|
||||
def.iconType = ItemIconType::BLOCK;
|
||||
} else if (iconTypeStr == "sprite") {
|
||||
def.iconType = item_icon_type::sprite;
|
||||
def.iconType = ItemIconType::SPRITE;
|
||||
} else if (iconTypeStr.length()) {
|
||||
logger.error() << name << ": unknown icon type" << iconTypeStr;
|
||||
}
|
||||
@ -532,7 +532,7 @@ void ContentLoader::loadBlock(
|
||||
auto& item = builder.items.create(full + BLOCK_ITEM_SUFFIX);
|
||||
item.generated = true;
|
||||
item.caption = def.caption;
|
||||
item.iconType = item_icon_type::block;
|
||||
item.iconType = ItemIconType::BLOCK;
|
||||
item.icon = full;
|
||||
item.placingBlock = full;
|
||||
|
||||
|
||||
@ -25,7 +25,7 @@ void corecontent::setup(EnginePaths* paths, ContentBuilder* builder) {
|
||||
}
|
||||
{
|
||||
ItemDef& item = builder->items.create(CORE_EMPTY);
|
||||
item.iconType = item_icon_type::none;
|
||||
item.iconType = ItemIconType::NONE;
|
||||
}
|
||||
|
||||
auto bindsFile = paths->getResourcesFolder()/fs::path("bindings.toml");
|
||||
@ -43,7 +43,7 @@ void corecontent::setup(EnginePaths* paths, ContentBuilder* builder) {
|
||||
block.hitboxes = {AABB()};
|
||||
block.breakable = false;
|
||||
ItemDef& item = builder->items.create(CORE_OBSTACLE+".item");
|
||||
item.iconType = item_icon_type::block;
|
||||
item.iconType = ItemIconType::BLOCK;
|
||||
item.icon = CORE_OBSTACLE;
|
||||
item.placingBlock = CORE_OBSTACLE;
|
||||
item.caption = block.caption;
|
||||
@ -59,7 +59,7 @@ void corecontent::setup(EnginePaths* paths, ContentBuilder* builder) {
|
||||
block.hitboxes = {AABB()};
|
||||
block.obstacle = false;
|
||||
ItemDef& item = builder->items.create(CORE_STRUCT_AIR+".item");
|
||||
item.iconType = item_icon_type::block;
|
||||
item.iconType = ItemIconType::BLOCK;
|
||||
item.icon = CORE_STRUCT_AIR;
|
||||
item.placingBlock = CORE_STRUCT_AIR;
|
||||
item.caption = block.caption;
|
||||
|
||||
@ -20,6 +20,7 @@
|
||||
#include "frontend/menu.hpp"
|
||||
#include "frontend/screens/Screen.hpp"
|
||||
#include "frontend/screens/MenuScreen.hpp"
|
||||
#include "graphics/render/ModelsGenerator.hpp"
|
||||
#include "graphics/core/Batch2D.hpp"
|
||||
#include "graphics/core/DrawContext.hpp"
|
||||
#include "graphics/core/ImageData.hpp"
|
||||
@ -280,6 +281,17 @@ void Engine::loadAssets() {
|
||||
}
|
||||
}
|
||||
assets = std::move(new_assets);
|
||||
|
||||
if (content) {
|
||||
for (auto& [name, def] : content->items.getDefs()) {
|
||||
assets->store(
|
||||
std::make_unique<model::Model>(
|
||||
ModelsGenerator::generate(*def, *content, *assets)
|
||||
),
|
||||
name + ".model"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void load_configs(const fs::path& root) {
|
||||
|
||||
@ -29,6 +29,11 @@ void Mesh::addBox(glm::vec3 pos, glm::vec3 size) {
|
||||
addPlane(pos-X*size, Z*size, Y*size, -X);
|
||||
}
|
||||
|
||||
void Mesh::scale(const glm::vec3& size) {
|
||||
for (auto& vertex : vertices) {
|
||||
vertex.coord *= size;
|
||||
}
|
||||
}
|
||||
|
||||
void Model::clean() {
|
||||
meshes.erase(
|
||||
|
||||
@ -17,6 +17,7 @@ namespace model {
|
||||
|
||||
void addPlane(glm::vec3 pos, glm::vec3 right, glm::vec3 up, glm::vec3 norm);
|
||||
void addBox(glm::vec3 pos, glm::vec3 size);
|
||||
void scale(const glm::vec3& size);
|
||||
};
|
||||
|
||||
struct Model {
|
||||
|
||||
71
src/graphics/render/ModelsGenerator.cpp
Normal file
71
src/graphics/render/ModelsGenerator.cpp
Normal file
@ -0,0 +1,71 @@
|
||||
#include "ModelsGenerator.hpp"
|
||||
|
||||
#include "assets/Assets.hpp"
|
||||
#include "items/ItemDef.hpp"
|
||||
#include "voxels/Block.hpp"
|
||||
#include "content/Content.hpp"
|
||||
#include "debug/Logger.hpp"
|
||||
|
||||
static debug::Logger logger("models-generator");
|
||||
|
||||
static void configure_textures(
|
||||
model::Model& model,
|
||||
const Block& blockDef,
|
||||
const Assets& assets
|
||||
) {
|
||||
for (auto& mesh : model.meshes) {
|
||||
auto& texture = mesh.texture;
|
||||
if (texture.empty() || texture.at(0) != '$') {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
int index = std::stoi(texture.substr(1));
|
||||
texture = "blocks:"+blockDef.textureFaces.at(index);
|
||||
} catch (const std::invalid_argument& err) {
|
||||
} catch (const std::runtime_error& err) {
|
||||
logger.error() << err.what();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static model::Model create_flat_model(
|
||||
const std::string& texture, const Assets& assets
|
||||
) {
|
||||
auto model = assets.require<model::Model>("drop-item");
|
||||
for (auto& mesh : model.meshes) {
|
||||
if (mesh.texture == "$0") {
|
||||
mesh.texture = texture;
|
||||
}
|
||||
}
|
||||
return model;
|
||||
}
|
||||
|
||||
model::Model ModelsGenerator::generate(
|
||||
const ItemDef& def, const Content& content, const Assets& assets
|
||||
) {
|
||||
if (def.iconType == ItemIconType::BLOCK) {
|
||||
auto model = assets.require<model::Model>("block");
|
||||
const auto& blockDef = content.blocks.require(def.icon);
|
||||
if (blockDef.model == BlockModel::xsprite) {
|
||||
return create_flat_model(
|
||||
"blocks:" + blockDef.textureFaces.at(0), assets
|
||||
);
|
||||
}
|
||||
for (auto& mesh : model.meshes) {
|
||||
switch (blockDef.model) {
|
||||
case BlockModel::aabb:
|
||||
mesh.scale(blockDef.hitboxes.at(0).size());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
mesh.scale(glm::vec3(0.3f));
|
||||
}
|
||||
configure_textures(model, blockDef, assets);
|
||||
return model;
|
||||
} else if (def.iconType == ItemIconType::SPRITE) {
|
||||
return create_flat_model(def.icon, assets);
|
||||
} else {
|
||||
return model::Model();
|
||||
}
|
||||
}
|
||||
14
src/graphics/render/ModelsGenerator.hpp
Normal file
14
src/graphics/render/ModelsGenerator.hpp
Normal file
@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include "graphics/core/Model.hpp"
|
||||
|
||||
struct ItemDef;
|
||||
class Assets;
|
||||
class Content;
|
||||
|
||||
class ModelsGenerator {
|
||||
public:
|
||||
static model::Model generate(
|
||||
const ItemDef& def, const Content& content, const Assets& assets
|
||||
);
|
||||
};
|
||||
@ -161,9 +161,9 @@ void SlotView::draw(const DrawContext* pctx, Assets* assets) {
|
||||
|
||||
auto& item = indices->items.require(stack.getItemId());
|
||||
switch (item.iconType) {
|
||||
case item_icon_type::none:
|
||||
case ItemIconType::NONE:
|
||||
break;
|
||||
case item_icon_type::block: {
|
||||
case ItemIconType::BLOCK: {
|
||||
const Block& cblock = content->blocks.require(item.icon);
|
||||
batch->texture(previews->getTexture());
|
||||
|
||||
@ -173,7 +173,7 @@ void SlotView::draw(const DrawContext* pctx, Assets* assets) {
|
||||
0, 0, 0, region, false, true, tint);
|
||||
break;
|
||||
}
|
||||
case item_icon_type::sprite: {
|
||||
case ItemIconType::SPRITE: {
|
||||
size_t index = item.icon.find(':');
|
||||
std::string name = item.icon.substr(index+1);
|
||||
UVRegion region(0.0f, 0.0, 1.0f, 1.0f);
|
||||
|
||||
@ -12,10 +12,10 @@ struct item_funcs_set {
|
||||
bool on_block_break_by : 1;
|
||||
};
|
||||
|
||||
enum class item_icon_type {
|
||||
none, // invisible (core:empty) must not be rendered
|
||||
sprite, // textured quad: icon is `atlas_name:texture_name`
|
||||
block, // block preview: icon is string block id
|
||||
enum class ItemIconType {
|
||||
NONE, // invisible (core:empty) must not be rendered
|
||||
SPRITE, // textured quad: icon is `atlas_name:texture_name`
|
||||
BLOCK, // block preview: icon is string block id
|
||||
};
|
||||
|
||||
struct ItemDef {
|
||||
@ -29,7 +29,7 @@ struct ItemDef {
|
||||
bool generated = false;
|
||||
uint8_t emission[4] {0, 0, 0, 0};
|
||||
|
||||
item_icon_type iconType = item_icon_type::sprite;
|
||||
ItemIconType iconType = ItemIconType::SPRITE;
|
||||
std::string icon = "blocks:notfound";
|
||||
|
||||
std::string placingBlock = "core:air";
|
||||
|
||||
@ -36,11 +36,11 @@ static int l_item_defs_count(lua::State* L) {
|
||||
static int l_item_get_icon(lua::State* L) {
|
||||
if (auto def = get_item_def(L, 1)) {
|
||||
switch (def->iconType) {
|
||||
case item_icon_type::none:
|
||||
case ItemIconType::NONE:
|
||||
return 0;
|
||||
case item_icon_type::sprite:
|
||||
case ItemIconType::SPRITE:
|
||||
return lua::pushstring(L, def->icon);
|
||||
case item_icon_type::block:
|
||||
case ItemIconType::BLOCK:
|
||||
return lua::pushstring(L, "block-previews:" + def->icon);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <array>
|
||||
|
||||
#include "maths/UVRegion.hpp"
|
||||
#include "maths/aabb.hpp"
|
||||
@ -111,7 +112,7 @@ public:
|
||||
std::string caption;
|
||||
|
||||
/// @brief Textures set applied to block sides
|
||||
std::string textureFaces[6]; // -x,x, -y,y, -z,z
|
||||
std::array<std::string, 6> textureFaces; // -x,x, -y,y, -z,z
|
||||
|
||||
std::vector<std::string> modelTextures = {};
|
||||
std::vector<BoxModel> modelBoxes = {};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user