refactor Entities

This commit is contained in:
MihailRis 2025-08-09 21:19:01 +03:00
parent 36a522bee0
commit 3eae377024
23 changed files with 485 additions and 348 deletions

View File

@ -18,6 +18,7 @@
#include "objects/Players.hpp"
#include "objects/Entities.hpp"
#include "objects/EntityDef.hpp"
#include "objects/Entity.hpp"
#include "physics/Hitbox.hpp"
#include "util/stringutil.hpp"
#include "voxels/Block.hpp"

View File

@ -15,6 +15,7 @@
#include "objects/Player.hpp"
#include "objects/Players.hpp"
#include "objects/Entities.hpp"
#include "objects/Entity.hpp"
#include "logic/LevelController.hpp"
#include "util/stringutil.hpp"
#include "engine/Engine.hpp"

View File

@ -7,6 +7,7 @@
#include "window/Camera.hpp"
#include "graphics/core/Texture.hpp"
#include "objects/Entities.hpp"
#include "objects/Entity.hpp"
#include "world/Level.hpp"
Emitter::Emitter(

View File

@ -13,6 +13,7 @@
#include "items/ItemStack.hpp"
#include "lighting/Lighting.hpp"
#include "objects/Entities.hpp"
#include "objects/Entity.hpp"
#include "objects/Player.hpp"
#include "objects/Players.hpp"
#include "physics/Hitbox.hpp"
@ -309,16 +310,7 @@ void PlayerController::updateKeyboard(const Input& inputEvents) {
}
void PlayerController::resetKeyboard() {
input.zoom = false;
input.moveForward = false;
input.moveBack = false;
input.moveLeft = false;
input.moveRight = false;
input.sprint = false;
input.shift = false;
input.cheat = false;
input.jump = false;
input.delta = {};
input = {};
}
void PlayerController::updatePlayer(float delta) {
@ -338,7 +330,8 @@ static int determine_rotation(
if (norm.z > 0.0f) return BLOCK_DIR_NORTH;
if (norm.z < 0.0f) return BLOCK_DIR_SOUTH;
} else if (name == "pane" || name == "stairs") {
int verticalBit = (name == "stairs" && (norm.y - camDir.y * 0.5f) < 0.0) ? 4 : 0;
int verticalBit =
(name == "stairs" && (norm.y - camDir.y * 0.5f) < 0.0) ? 4 : 0;
if (abs(camDir.x) > abs(camDir.z)) {
if (camDir.x > 0.0f) return BLOCK_DIR_EAST | verticalBit;
if (camDir.x < 0.0f) return BLOCK_DIR_WEST | verticalBit;

View File

@ -4,6 +4,8 @@
#include "engine/Engine.hpp"
#include "objects/Entities.hpp"
#include "objects/EntityDef.hpp"
#include "objects/Entity.hpp"
#include "objects/Rigidbody.hpp"
#include "objects/Player.hpp"
#include "objects/rigging.hpp"
#include "physics/Hitbox.hpp"

View File

@ -4,6 +4,7 @@
#include "frontend/hud.hpp"
#include "objects/Entities.hpp"
#include "objects/Entity.hpp"
#include "world/Level.hpp"
#include "logic/LevelController.hpp"
#include "api_lua.hpp"

View File

@ -5,6 +5,7 @@
#include "objects/Entities.hpp"
#include "objects/Player.hpp"
#include "objects/Players.hpp"
#include "objects/Entity.hpp"
#include "physics/Hitbox.hpp"
#include "window/Camera.hpp"
#include "world/Level.hpp"

View File

@ -21,6 +21,7 @@
#include "maths/Heightmap.hpp"
#include "objects/Entities.hpp"
#include "objects/EntityDef.hpp"
#include "objects/Entity.hpp"
#include "objects/Player.hpp"
#include "util/stringutil.hpp"
#include "util/timeutil.hpp"

View File

@ -17,6 +17,7 @@
#include "maths/FrustumCulling.hpp"
#include "maths/rays.hpp"
#include "EntityDef.hpp"
#include "Entity.hpp"
#include "rigging.hpp"
#include "physics/Hitbox.hpp"
#include "physics/PhysicsSolver.hpp"
@ -24,103 +25,16 @@
static debug::Logger logger("entities");
static inline std::string COMP_TRANSFORM = "transform";
static inline std::string COMP_RIGIDBODY = "rigidbody";
static inline std::string COMP_SKELETON = "skeleton";
static inline std::string SAVED_DATA_VARNAME = "SAVED_DATA";
void Transform::refresh() {
combined = glm::mat4(1.0f);
combined = glm::translate(combined, pos);
combined = combined * glm::mat4(rot);
combined = glm::scale(combined, size);
displayPos = pos;
displaySize = size;
dirty = false;
}
void Entity::setInterpolatedPosition(const glm::vec3& position) {
getSkeleton().interpolation.refresh(position);
}
glm::vec3 Entity::getInterpolatedPosition() const {
const auto& skeleton = getSkeleton();
if (skeleton.interpolation.isEnabled()) {
return skeleton.interpolation.getCurrent();
}
return getTransform().pos;
}
void Entity::destroy() {
if (isValid()) {
entities.despawn(id);
}
}
rigging::Skeleton& Entity::getSkeleton() const {
return registry.get<rigging::Skeleton>(entity);
}
void Entity::setRig(const rigging::SkeletonConfig* rigConfig) {
auto& skeleton = registry.get<rigging::Skeleton>(entity);
skeleton.config = rigConfig;
skeleton.pose.matrices.resize(
rigConfig->getBones().size(), glm::mat4(1.0f)
);
skeleton.calculated.matrices.resize(
rigConfig->getBones().size(), glm::mat4(1.0f)
);
}
Entities::Entities(Level& level)
: level(level), sensorsTickClock(20, 3), updateTickClock(20, 3) {
}
template <void (*callback)(const Entity&, size_t, entityid_t)>
static sensorcallback create_sensor_callback(Entities* entities) {
return [=](auto entityid, auto index, auto otherid) {
if (auto entity = entities->get(entityid)) {
if (entity->isValid()) {
callback(*entity, index, otherid);
}
}
};
}
static void initialize_body(
const EntityDef& def, Rigidbody& body, entityid_t id, Entities* entities
) {
body.sensors.resize(def.radialSensors.size() + def.boxSensors.size());
for (auto& [i, box] : def.boxSensors) {
SensorParams params {};
params.aabb = box;
body.sensors[i] = Sensor {
true,
SensorType::AABB,
i,
id,
params,
params,
{},
{},
create_sensor_callback<scripting::on_sensor_enter>(entities),
create_sensor_callback<scripting::on_sensor_exit>(entities)};
}
for (auto& [i, radius] : def.radialSensors) {
SensorParams params {};
params.radial = glm::vec4(radius);
body.sensors[i] = Sensor {
true,
SensorType::RADIUS,
i,
id,
params,
params,
{},
{},
create_sensor_callback<scripting::on_sensor_enter>(entities),
create_sensor_callback<scripting::on_sensor_exit>(entities)};
std::optional<Entity> Entities::get(entityid_t id) {
const auto& found = entities.find(id);
if (found != entities.end() && registry.valid(found->second)) {
return Entity(*this, id, registry, found->second);
}
return std::nullopt;
}
entityid_t Entities::spawn(
@ -168,7 +82,7 @@ entityid_t Entities::spawn(
Hitbox {def.bodyType, position, def.hitbox * 0.5f},
std::vector<Sensor> {}
);
initialize_body(def, body, id, this);
body.initialize(def, id, *this);
auto& scripting = registry.emplace<ScriptComponents>(entity);
registry.emplace<rigging::Skeleton>(entity, skeleton->instance());
@ -232,8 +146,8 @@ void Entities::loadEntity(const dv::value& map, Entity entity) {
if (skeletonName != skeleton.config->getName()) {
skeleton.config = level.content.getSkeleton(skeletonName);
}
if (auto found = map.at(COMP_SKELETON)) {
auto& skeletonmap = *found;
if (auto foundSkeleton = map.at(COMP_SKELETON)) {
auto& skeletonmap = *foundSkeleton;
if (auto found = skeletonmap.at("textures")) {
auto& texturesmap = *found;
for (auto& [slot, _] : texturesmap.asObject()) {
@ -284,7 +198,7 @@ std::optional<Entities::RaycastResult> Entities::rayCast(
void Entities::loadEntities(dv::value root) {
clean();
auto& list = root["data"];
const auto& list = root["data"];
for (auto& map : list) {
try {
loadEntity(map);
@ -298,74 +212,6 @@ void Entities::onSave(const Entity& entity) {
scripting::on_entity_save(entity);
}
dv::value Entities::serialize(const Entity& entity) {
auto root = dv::object();
auto& eid = entity.getID();
auto& def = eid.def;
root["def"] = def.name;
root["uid"] = eid.uid;
{
auto& transform = entity.getTransform();
auto& tsfmap = root.object(COMP_TRANSFORM);
tsfmap["pos"] = dv::to_value(transform.pos);
if (transform.size != glm::vec3(1.0f)) {
tsfmap["size"] = dv::to_value(transform.size);
}
if (transform.rot != glm::mat3(1.0f)) {
tsfmap["rot"] = dv::to_value(transform.rot);
}
}
{
auto& rigidbody = entity.getRigidbody();
auto& hitbox = rigidbody.hitbox;
auto& bodymap = root.object(COMP_RIGIDBODY);
if (!rigidbody.enabled) {
bodymap["enabled"] = false;
}
if (def.save.body.velocity) {
bodymap["vel"] = dv::to_value(rigidbody.hitbox.velocity);
}
if (def.save.body.settings) {
bodymap["damping"] = rigidbody.hitbox.linearDamping;
if (hitbox.type != def.bodyType) {
bodymap["type"] = BodyTypeMeta.getNameString(hitbox.type);
}
if (hitbox.crouching) {
bodymap["crouch"] = hitbox.crouching;
}
}
}
auto& skeleton = entity.getSkeleton();
if (skeleton.config->getName() != def.skeletonName) {
root["skeleton"] = skeleton.config->getName();
}
if (def.save.skeleton.pose || def.save.skeleton.textures) {
auto& skeletonmap = root.object(COMP_SKELETON);
if (def.save.skeleton.textures) {
auto& map = skeletonmap.object("textures");
for (auto& [slot, texture] : skeleton.textures) {
map[slot] = texture;
}
}
if (def.save.skeleton.pose) {
auto& list = skeletonmap.list("pose");
for (auto& mat : skeleton.pose.matrices) {
list.add(dv::to_value(mat));
}
}
}
auto& scripts = entity.getScripting();
if (!scripts.components.empty()) {
auto& compsMap = root.object("comps");
for (auto& comp : scripts.components) {
auto data =
scripting::get_component_value(comp->env, SAVED_DATA_VARNAME);
compsMap[comp->name] = data;
}
}
return root;
}
dv::value Entities::serialize(const std::vector<Entity>& entities) {
auto list = dv::list();
for (auto& entity : entities) {
@ -375,7 +221,7 @@ dv::value Entities::serialize(const std::vector<Entity>& entities) {
}
level.entities->onSave(entity);
if (!eid.destroyFlag) {
list.add(level.entities->serialize(entity));
list.add(entity.serialize());
}
}
return list;

View File

@ -5,108 +5,21 @@
#include <optional>
#include <vector>
#include "data/dv.hpp"
#include "physics/Hitbox.hpp"
#include "Transform.hpp"
#include "Rigidbody.hpp"
#include "ScriptComponents.hpp"
#include "typedefs.hpp"
#include "util/Clock.hpp"
#define GLM_ENABLE_EXPERIMENTAL
#include <entt/entity/registry.hpp>
#include <glm/gtx/norm.hpp>
#include <unordered_map>
struct EntityFuncsSet {
bool init;
bool on_despawn;
bool on_grounded;
bool on_fall;
bool on_sensor_enter;
bool on_sensor_exit;
bool on_save;
bool on_aim_on;
bool on_aim_off;
bool on_attacked;
bool on_used;
};
#include <entt/entity/registry.hpp>
#include <unordered_map>
struct EntityDef;
struct EntityId {
entityid_t uid;
const EntityDef& def;
bool destroyFlag = false;
int64_t player = -1;
};
struct Transform {
static inline constexpr float EPSILON = 0.0000001f;
glm::vec3 pos;
glm::vec3 size;
glm::mat3 rot;
glm::mat4 combined;
bool dirty = true;
glm::vec3 displayPos;
glm::vec3 displaySize;
void refresh();
inline void setRot(glm::mat3 m) {
rot = m;
dirty = true;
}
inline void setSize(glm::vec3 v) {
if (glm::distance2(displaySize, v) >= EPSILON) {
dirty = true;
}
size = v;
}
inline void setPos(glm::vec3 v) {
if (glm::distance2(displayPos, v) >= EPSILON) {
dirty = true;
}
pos = v;
}
};
struct Rigidbody {
bool enabled = true;
Hitbox hitbox;
std::vector<Sensor> sensors;
};
struct UserComponent {
std::string name;
EntityFuncsSet funcsset;
scriptenv env;
dv::value params;
UserComponent(
const std::string& name,
EntityFuncsSet funcsset,
scriptenv env,
dv::value params
)
: name(name),
funcsset(funcsset),
env(std::move(env)),
params(std::move(params)) {
}
};
struct ScriptComponents {
std::vector<std::unique_ptr<UserComponent>> components;
ScriptComponents() = default;
ScriptComponents(ScriptComponents&& other)
: components(std::move(other.components)) {
}
};
class Level;
class Assets;
class Entity;
class LineBatch;
class ModelBatch;
class Frustum;
@ -118,72 +31,6 @@ namespace rigging {
class SkeletonConfig;
}
class Entity {
Entities& entities;
entityid_t id;
entt::registry& registry;
const entt::entity entity;
public:
Entity(
Entities& entities,
entityid_t id,
entt::registry& registry,
const entt::entity entity
)
: entities(entities), id(id), registry(registry), entity(entity) {
}
EntityId& getID() const {
return registry.get<EntityId>(entity);
}
bool isValid() const {
return registry.valid(entity);
}
const EntityDef& getDef() const {
return registry.get<EntityId>(entity).def;
}
Transform& getTransform() const {
return registry.get<Transform>(entity);
}
Rigidbody& getRigidbody() const {
return registry.get<Rigidbody>(entity);
}
ScriptComponents& getScripting() const {
return registry.get<ScriptComponents>(entity);
}
rigging::Skeleton& getSkeleton() const;
void setRig(const rigging::SkeletonConfig* rigConfig);
entityid_t getUID() const {
return registry.get<EntityId>(entity).uid;
}
entt::entity getHandler() const {
return entity;
}
int64_t getPlayer() const {
return registry.get<EntityId>(entity).player;
}
void setPlayer(int64_t id) {
registry.get<EntityId>(entity).player = id;
}
void setInterpolatedPosition(const glm::vec3& position);
glm::vec3 getInterpolatedPosition() const;
void destroy();
};
class Entities {
entt::registry registry;
Level& level;
@ -229,13 +76,7 @@ public:
entityid_t uid = 0
);
std::optional<Entity> get(entityid_t id) {
const auto& found = entities.find(id);
if (found != entities.end() && registry.valid(found->second)) {
return Entity(*this, id, registry, found->second);
}
return std::nullopt;
}
std::optional<Entity> get(entityid_t id);
/// @brief Entities raycast. No blocks check included, use combined with
/// Chunks.rayCast
@ -260,7 +101,6 @@ public:
std::vector<Entity> getAllInRadius(glm::vec3 center, float radius);
void despawn(entityid_t id);
void despawn(std::vector<Entity> entities);
dv::value serialize(const Entity& entity);
dv::value serialize(const std::vector<Entity>& entities);
void setNextID(entityid_t id) {

119
src/objects/Entity.cpp Normal file
View File

@ -0,0 +1,119 @@
#include "Entity.hpp"
#include "Transform.hpp"
#include "Rigidbody.hpp"
#include "ScriptComponents.hpp"
#include "Entities.hpp"
#include "EntityDef.hpp"
#include "rigging.hpp"
#include "logic/scripting/scripting.hpp"
#include <entt/entt.hpp>
static inline std::string SAVED_DATA_VARNAME = "SAVED_DATA";
void Entity::setInterpolatedPosition(const glm::vec3& position) {
getSkeleton().interpolation.refresh(position);
}
glm::vec3 Entity::getInterpolatedPosition() const {
const auto& skeleton = getSkeleton();
if (skeleton.interpolation.isEnabled()) {
return skeleton.interpolation.getCurrent();
}
return getTransform().pos;
}
void Entity::destroy() {
if (isValid()) {
entities.despawn(id);
}
}
rigging::Skeleton& Entity::getSkeleton() const {
return registry.get<rigging::Skeleton>(entity);
}
void Entity::setRig(const rigging::SkeletonConfig* rigConfig) {
auto& skeleton = registry.get<rigging::Skeleton>(entity);
skeleton.config = rigConfig;
skeleton.pose.matrices.resize(
rigConfig->getBones().size(), glm::mat4(1.0f)
);
skeleton.calculated.matrices.resize(
rigConfig->getBones().size(), glm::mat4(1.0f)
);
}
dv::value Entity::serialize() const {
const auto& eid = getID();
const auto& def = eid.def;
const auto& transform = getTransform();
const auto& rigidbody = getRigidbody();
const auto& skeleton = getSkeleton();
const auto& scripts = getScripting();
auto root = dv::object();
root["def"] = def.name;
root["uid"] = eid.uid;
root[COMP_TRANSFORM] = transform.serialize();
root[COMP_RIGIDBODY] =
rigidbody.serialize(def.save.body.velocity, def.save.body.settings);
if (skeleton.config->getName() != def.skeletonName) {
root["skeleton"] = skeleton.config->getName();
}
if (def.save.skeleton.pose || def.save.skeleton.textures) {
root[COMP_SKELETON] = skeleton.serialize(
def.save.skeleton.pose, def.save.skeleton.textures
);
}
if (!scripts.components.empty()) {
auto& compsMap = root.object("comps");
for (auto& comp : scripts.components) {
auto data =
scripting::get_component_value(comp->env, SAVED_DATA_VARNAME);
compsMap[comp->name] = data;
}
}
return root;
}
EntityId& Entity::getID() const {
return registry.get<EntityId>(entity);
}
bool Entity::isValid() const {
return registry.valid(entity);
}
Transform& Entity::getTransform() const {
return registry.get<Transform>(entity);
}
ScriptComponents& Entity::getScripting() const {
return registry.get<ScriptComponents>(entity);
}
const EntityDef& Entity::getDef() const {
return registry.get<EntityId>(entity).def;
}
Rigidbody& Entity::getRigidbody() const {
return registry.get<Rigidbody>(entity);
}
entityid_t Entity::getUID() const {
return registry.get<EntityId>(entity).uid;
}
int64_t Entity::getPlayer() const {
return registry.get<EntityId>(entity).player;
}
void Entity::setPlayer(int64_t id) {
registry.get<EntityId>(entity).player = id;
}

79
src/objects/Entity.hpp Normal file
View File

@ -0,0 +1,79 @@
#pragma once
#include "typedefs.hpp"
#include "data/dv_fwd.hpp"
#include <entt/fwd.hpp>
#include <glm/vec3.hpp>
class Entities;
struct EntityDef;
struct Transform;
struct Rigidbody;
struct ScriptComponents;
inline std::string COMP_TRANSFORM = "transform";
inline std::string COMP_RIGIDBODY = "rigidbody";
inline std::string COMP_SKELETON = "skeleton";
namespace rigging {
struct Skeleton;
class SkeletonConfig;
}
struct EntityId {
entityid_t uid;
const EntityDef& def;
bool destroyFlag = false;
int64_t player = -1;
};
class Entity {
Entities& entities;
entityid_t id;
entt::registry& registry;
const entt::entity entity;
public:
Entity(
Entities& entities,
entityid_t id,
entt::registry& registry,
const entt::entity entity
)
: entities(entities), id(id), registry(registry), entity(entity) {
}
dv::value serialize() const;
EntityId& getID() const;
bool isValid() const;
const EntityDef& getDef() const;
Transform& getTransform() const;
Rigidbody& getRigidbody() const;
ScriptComponents& getScripting() const;
rigging::Skeleton& getSkeleton() const;
void setRig(const rigging::SkeletonConfig* rigConfig);
entityid_t getUID() const;
int64_t getPlayer() const;
void setPlayer(int64_t id);
void setInterpolatedPosition(const glm::vec3& position);
glm::vec3 getInterpolatedPosition() const;
entt::entity getHandler() const {
return entity;
}
void destroy();
};

View File

@ -9,6 +9,7 @@
#include "content/ContentReport.hpp"
#include "items/Inventory.hpp"
#include "Entities.hpp"
#include "Entity.hpp"
#include "rigging.hpp"
#include "physics/Hitbox.hpp"
#include "physics/PhysicsSolver.hpp"
@ -137,7 +138,7 @@ void Player::updateInput(PlayerInput& input, float delta) {
}
if (glm::length(dir) > 0.0f) {
dir = glm::normalize(dir);
hitbox->velocity += dir * speed * delta * 9.0f;
doMove(dir, speed, delta);
}
if (flight) {
if (input.jump) {
@ -146,9 +147,22 @@ void Player::updateInput(PlayerInput& input, float delta) {
if (input.shift) {
hitbox->velocity.y -= speed * delta * 9;
}
} else if (input.jump) {
doJump();
}
if (input.jump && hitbox->grounded) {
hitbox->velocity.y = JUMP_FORCE;
}
void Player::doMove(const glm::vec3& dir, float speed, float delta) {
if (auto hitbox = getHitbox()) {
hitbox->velocity += dir * speed * delta * 9.0f;
}
}
void Player::doJump() {
if (auto hitbox = getHitbox()) {
if (hitbox->grounded) {
hitbox->velocity.y = JUMP_FORCE;
}
}
}

View File

@ -59,6 +59,9 @@ class Player : public Serializable {
entityid_t eid = ENTITY_AUTO;
entityid_t selectedEid = 0;
void doMove(const glm::vec3& dir, float speed, float delta);
void doJump();
glm::vec3 rotation {};
public:
util::VecInterpolation<3, float, true> rotationInterpolation {true};

74
src/objects/Rigidbody.cpp Normal file
View File

@ -0,0 +1,74 @@
#define VC_ENABLE_REFLECTION
#include "Rigidbody.hpp"
#include "EntityDef.hpp"
#include "Entities.hpp"
#include "Entity.hpp"
#include "data/dv_util.hpp"
#include "logic/scripting/scripting.hpp"
dv::value Rigidbody::serialize(bool saveVelocity, bool saveBodySettings) const {
auto bodymap = dv::object();
if (!enabled) {
bodymap["enabled"] = false;
}
if (saveVelocity) {
bodymap["vel"] = dv::to_value(hitbox.velocity);
}
if (saveBodySettings) {
bodymap["damping"] = hitbox.linearDamping;
bodymap["type"] = BodyTypeMeta.getNameString(hitbox.type);
if (hitbox.crouching) {
bodymap["crouch"] = hitbox.crouching;
}
}
return bodymap;
}
template <void (*callback)(const Entity&, size_t, entityid_t)>
static sensorcallback create_sensor_callback(Entities& entities) {
return [&entities](auto entityid, auto index, auto otherid) {
if (auto entity = entities.get(entityid)) {
if (entity->isValid()) {
callback(*entity, index, otherid);
}
}
};
}
void Rigidbody::initialize(
const EntityDef& def, entityid_t id, Entities& entities
) {
sensors.resize(def.radialSensors.size() + def.boxSensors.size());
for (auto& [i, box] : def.boxSensors) {
SensorParams params {};
params.aabb = box;
sensors[i] = Sensor {
true,
SensorType::AABB,
i,
id,
params,
params,
{},
{},
create_sensor_callback<scripting::on_sensor_enter>(entities),
create_sensor_callback<scripting::on_sensor_exit>(entities)};
}
for (auto& [i, radius] : def.radialSensors) {
SensorParams params {};
params.radial = glm::vec4(radius);
sensors[i] = Sensor {
true,
SensorType::RADIUS,
i,
id,
params,
params,
{},
{},
create_sensor_callback<scripting::on_sensor_enter>(entities),
create_sensor_callback<scripting::on_sensor_exit>(entities)};
}
}

22
src/objects/Rigidbody.hpp Normal file
View File

@ -0,0 +1,22 @@
#pragma once
#include "data/dv_fwd.hpp"
#include "physics/Hitbox.hpp"
#include <vector>
#include <entt/fwd.hpp>
class Entities;
struct EntityDef;
struct Rigidbody {
bool enabled = true;
Hitbox hitbox;
std::vector<Sensor> sensors;
dv::value serialize(bool saveVelocity, bool saveBodySettings) const;
void initialize(
const EntityDef& def, entityid_t id, Entities& entities
);
};

View File

@ -0,0 +1,49 @@
#pragma once
#include "typedefs.hpp"
#include "data/dv.hpp"
#include <string>
struct EntityFuncsSet {
bool init;
bool on_despawn;
bool on_grounded;
bool on_fall;
bool on_sensor_enter;
bool on_sensor_exit;
bool on_save;
bool on_aim_on;
bool on_aim_off;
bool on_attacked;
bool on_used;
};
struct UserComponent {
std::string name;
EntityFuncsSet funcsset;
scriptenv env;
dv::value params;
UserComponent(
const std::string& name,
EntityFuncsSet funcsset,
scriptenv env,
dv::value params
)
: name(name),
funcsset(funcsset),
env(std::move(env)),
params(std::move(params)) {
}
};
struct ScriptComponents {
std::vector<std::unique_ptr<UserComponent>> components;
ScriptComponents() = default;
ScriptComponents(ScriptComponents&& other)
: components(std::move(other.components)) {
}
};

25
src/objects/Transform.cpp Normal file
View File

@ -0,0 +1,25 @@
#include "Transform.hpp"
#include "data/dv_util.hpp"
void Transform::refresh() {
combined = glm::mat4(1.0f);
combined = glm::translate(combined, pos);
combined = combined * glm::mat4(rot);
combined = glm::scale(combined, size);
displayPos = pos;
displaySize = size;
dirty = false;
}
dv::value Transform::serialize() const {
auto tsfmap = dv::object();
tsfmap["pos"] = dv::to_value(pos);
if (size != glm::vec3(1.0f)) {
tsfmap["size"] = dv::to_value(size);
}
if (rot != glm::mat3(1.0f)) {
tsfmap["rot"] = dv::to_value(rot);
}
return tsfmap;
}

43
src/objects/Transform.hpp Normal file
View File

@ -0,0 +1,43 @@
#pragma once
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/vec3.hpp>
#include <glm/mat4x4.hpp>
#include <glm/gtx/norm.hpp>
#include <data/dv_fwd.hpp>
struct Transform {
static inline constexpr float EPSILON = 0.0000001f;
glm::vec3 pos;
glm::vec3 size;
glm::mat3 rot;
glm::mat4 combined;
bool dirty = true;
glm::vec3 displayPos;
glm::vec3 displaySize;
dv::value serialize() const;
void refresh();
inline void setRot(glm::mat3 m) {
rot = m;
dirty = true;
}
inline void setSize(glm::vec3 v) {
if (glm::distance2(displaySize, v) >= EPSILON) {
dirty = true;
}
size = v;
}
inline void setPos(glm::vec3 v) {
if (glm::distance2(displayPos, v) >= EPSILON) {
dirty = true;
}
pos = v;
}
};

View File

@ -23,7 +23,7 @@ Bone::Bone(
std::string name,
std::string model,
std::vector<std::unique_ptr<Bone>> bones,
glm::vec3 offset
const glm::vec3& offset
)
: index(index),
name(std::move(name)),
@ -53,6 +53,23 @@ Skeleton::Skeleton(const SkeletonConfig* config)
}
}
dv::value Skeleton::serialize(bool saveTextures, bool savePose) const {
auto root = dv::object();
if (saveTextures) {
auto& map = root.object("textures");
for (auto& [slot, texture] : textures) {
map[slot] = texture;
}
}
if (savePose) {
auto& list = root.list("pose");
for (auto& mat : pose.matrices) {
list.add(dv::to_value(mat));
}
}
return root;
}
static void get_all_nodes(std::vector<Bone*>& nodes, Bone* node) {
nodes[node->getIndex()] = node;
for (auto& subnode : node->getSubnodes()) {

View File

@ -9,6 +9,7 @@
#include <vector>
#include "typedefs.hpp"
#include "data/dv_fwd.hpp"
#include "util/Interpolation.hpp"
class Assets;
@ -50,7 +51,7 @@ namespace rigging {
std::string name,
std::string model,
std::vector<std::unique_ptr<Bone>> bones,
glm::vec3 offset
const glm::vec3& offset
);
void setModel(const std::string& name);
@ -89,6 +90,8 @@ namespace rigging {
util::VecInterpolation<3, float> interpolation {false};
Skeleton(const SkeletonConfig* config);
dv::value serialize(bool saveTextures, bool savePose) const;
};
class SkeletonConfig {

View File

@ -10,6 +10,7 @@
#include "lighting/Lightmap.hpp"
#include "maths/voxmaths.hpp"
#include "objects/Entities.hpp"
#include "objects/Entity.hpp"
#include "voxels/blocks_agent.hpp"
#include "typedefs.hpp"
#include "world/LevelEvents.hpp"

View File

@ -5,6 +5,7 @@
#include "items/Inventories.hpp"
#include "items/Inventory.hpp"
#include "objects/Entities.hpp"
#include "objects/Entity.hpp"
#include "objects/Player.hpp"
#include "objects/Players.hpp"
#include "physics/Hitbox.hpp"