Merge branch 'main' into dev

This commit is contained in:
MihailRis 2026-04-06 00:54:06 +03:00
commit 77ab9ac4d7
19 changed files with 76 additions and 46 deletions

View file

@ -104,7 +104,7 @@
Определяет массу сущности. За стандарт приняты килограммы. Определяет массу сущности. За стандарт приняты килограммы.
В случае `kinematic` тела вместо указанной используется бесконечная масса. В случае `kinematic` тела вместо указанной используется бесконечная масса.
### Эластичность - *elasticity* ### Упругость - *elasticity*
Определяет упругость сущности. Определяет упругость сущности.

View file

@ -54,7 +54,10 @@ function audio.input.request_open(callback)
_gui_confirm(gui.str(GRANT_PERMISSION_MSG):gsub("%%{0}", caller), function() _gui_confirm(gui.str(GRANT_PERMISSION_MSG):gsub("%%{0}", caller), function()
audio_input_tokens_store[token] = caller audio_input_tokens_store[token] = caller
callback(token) callback(token)
menu:reset() if not menu:back() then
menu:reset()
gui.set_active_frame("")
end
end) end)
end end

View file

@ -16,6 +16,14 @@ end
-- remove undefined properties and build tags set -- remove undefined properties and build tags set
local function process_properties(lib) local function process_properties(lib)
for id, props in pairs(lib.properties) do for id, props in pairs(lib.properties) do
if props.parent then
local parent_props = lib.properties[block.index(props.parent)] or {}
for propname, value in pairs(parent_props) do
if not props[propname] then
props[propname] = value
end
end
end
for propname, _ in pairs(props) do for propname, _ in pairs(props) do
if not table.has(names, propname) then if not table.has(names, propname) then
props[propname] = nil props[propname] = nil

View file

@ -66,9 +66,7 @@ Decorator::Decorator(
continue; continue;
} }
playerTexts[id] = renderer.texts->add(std::make_unique<TextNote>( playerTexts[id] = renderer.texts->add(std::make_unique<TextNote>(
util::str2wstr_utf8(player->getName()), player->getName(), playerNamePreset, player->getPosition()
playerNamePreset,
player->getPosition()
)); ));
} }
} }
@ -296,9 +294,7 @@ void Decorator::updateTextNotes() {
continue; continue;
} }
playerTexts[id] = renderer.texts->add(std::make_unique<TextNote>( playerTexts[id] = renderer.texts->add(std::make_unique<TextNote>(
util::str2wstr_utf8(player->getName()), player->getName(), playerNamePreset, player->getPosition()
playerNamePreset,
player->getPosition()
)); ));
} }
@ -315,6 +311,9 @@ void Decorator::updateTextNotes() {
position = entity->getInterpolatedPosition(); position = entity->getInterpolatedPosition();
} }
note->setPosition(position + glm::vec3(0, 1, 0)); note->setPosition(position + glm::vec3(0, 1, 0));
if (note->getText() != player->getName()) {
note->setText(player->getName());
}
++textsIter; ++textsIter;
} }
} }

View file

@ -7,9 +7,9 @@ using namespace rigging;
NamedSkeletons::NamedSkeletons() = default; NamedSkeletons::NamedSkeletons() = default;
std::shared_ptr<rigging::Skeleton> NamedSkeletons::createSkeleton( std::shared_ptr<rigging::Skeleton> NamedSkeletons::createSkeleton(
const std::string& name, const SkeletonConfig* config const std::string& name, std::shared_ptr<const SkeletonConfig> config
) { ) {
auto skeleton = std::make_shared<Skeleton>(config); auto skeleton = std::make_shared<Skeleton>(std::move(config));
skeletons[name] = skeleton; skeletons[name] = skeleton;
return skeleton; return skeleton;
} }

View file

@ -14,7 +14,8 @@ public:
NamedSkeletons(); NamedSkeletons();
std::shared_ptr<rigging::Skeleton> createSkeleton( std::shared_ptr<rigging::Skeleton> createSkeleton(
const std::string& name, const rigging::SkeletonConfig* config const std::string& name,
std::shared_ptr<const rigging::SkeletonConfig> config
); );
rigging::Skeleton* getSkeleton(const std::string& name); rigging::Skeleton* getSkeleton(const std::string& name);

View file

@ -113,7 +113,9 @@ WorldRenderer::WorldRenderer(
content.getDefaults()["hand-skeleton"].asString() content.getDefaults()["hand-skeleton"].asString()
); );
hands = std::make_unique<HandsRenderer>( hands = std::make_unique<HandsRenderer>(
assets, *modelBatch, skeletons->createSkeleton("hand", &skeletonConfig) assets,
*modelBatch,
skeletons->createSkeleton("hand", skeletonConfig.shared_from_this())
); );
shadowMapping = std::make_unique<Shadows>(level); shadowMapping = std::make_unique<Shadows>(level);
debugLines = std::make_unique<DebugLinesRenderer>(level); debugLines = std::make_unique<DebugLinesRenderer>(level);

View file

@ -108,13 +108,13 @@ static int l_set_skeleton(lua::State* L) {
} }
if (auto entity = get_entity(L, 1)) { if (auto entity = get_entity(L, 1)) {
std::string skeletonName = lua::require_string(L, 2); std::string skeletonName = lua::require_string(L, 2);
auto rigConfig = assets->get<rigging::SkeletonConfig>(skeletonName); auto rigConfig = assets->getShared<rigging::SkeletonConfig>(skeletonName);
if (rigConfig == nullptr) { if (rigConfig == nullptr) {
throw std::runtime_error( throw std::runtime_error(
"skeleton not found '" + skeletonName + "'" "skeleton not found '" + skeletonName + "'"
); );
} }
entity->setRig(rigConfig); entity->setRig(std::move(rigConfig));
} }
return 0; return 0;
} }

View file

@ -294,14 +294,14 @@ static int l_set_camera(lua::State* L) {
static int l_get_name(lua::State* L) { static int l_get_name(lua::State* L) {
if (auto player = get_player(L, 1)) { if (auto player = get_player(L, 1)) {
return lua::pushstring(L, player->getName()); return lua::pushwstring(L, player->getName());
} }
return 0; return 0;
} }
static int l_set_name(lua::State* L) { static int l_set_name(lua::State* L) {
if (auto player = get_player(L, 1)) { if (auto player = get_player(L, 1)) {
player->setName(lua::require_string(L, 2)); player->setName(lua::require_wstring(L, 2));
} }
return 0; return 0;
} }
@ -313,7 +313,7 @@ static int l_create(lua::State* L) {
} }
auto& level = require_level(); auto& level = require_level();
auto player = level.players->create(playerId); auto player = level.players->create(playerId);
player->setName(lua::require_string(L, 1)); player->setName(lua::require_wstring(L, 1));
return lua::pushinteger(L, player->getId()); return lua::pushinteger(L, player->getId());
} }

View file

@ -402,7 +402,7 @@ namespace lua {
pop(L); pop(L);
pop(L); pop(L);
return glm::quat(x, y, z, w); return glm::quat(w, x, y, z);
} }
inline glm::vec3 tovec3_stack(lua::State* L, int idx) { inline glm::vec3 tovec3_stack(lua::State* L, int idx) {

View file

@ -155,7 +155,7 @@ void Entities::loadEntity(const dv::value& map, Entity entity) {
std::string skeletonName = skeleton->config->getName(); std::string skeletonName = skeleton->config->getName();
map.at("skeleton-name").get(skeletonName); map.at("skeleton-name").get(skeletonName);
if (skeletonName != skeleton->config->getName()) { if (skeletonName != skeleton->config->getName()) {
skeleton->config = assets->get<rigging::SkeletonConfig>(skeletonName); skeleton->config = assets->getShared<rigging::SkeletonConfig>(skeletonName);
} }
if (auto foundSkeleton = map.at(COMP_SKELETON)) { if (auto foundSkeleton = map.at(COMP_SKELETON)) {
skeleton->deserialize(*foundSkeleton); skeleton->deserialize(*foundSkeleton);
@ -470,7 +470,7 @@ void Entities::render(
continue; continue;
} }
const auto* rigConfig = skeleton.config; const auto& rigConfig = skeleton.config;
if (rigConfig) { if (rigConfig) {
rigConfig->render( rigConfig->render(
assets, batch, skeleton, transform.rot, pos, size assets, batch, skeleton, transform.rot, pos, size
@ -482,7 +482,9 @@ void Entities::render(
bool Entities::hasBlockingInside(AABB aabb) { bool Entities::hasBlockingInside(AABB aabb) {
auto view = registry->view<EntityId, Rigidbody>(); auto view = registry->view<EntityId, Rigidbody>();
for (auto [entity, eid, body] : view.each()) { for (auto [entity, eid, body] : view.each()) {
if (eid.def.blocking && aabb.intersects(body.hitbox.getAABB(), -0.05f)) { AABB bodyAABB(body.hitbox.getAABB());
bodyAABB.scale({1, 0.95f, 1});
if (eid.def.blocking && aabb.intersects(bodyAABB)) {
return true; return true;
} }
} }

View file

@ -37,15 +37,9 @@ rigging::Skeleton* Entity::getSkeleton() const {
return registry.try_get<rigging::Skeleton>(entity); return registry.try_get<rigging::Skeleton>(entity);
} }
void Entity::setRig(const rigging::SkeletonConfig* rigConfig) { void Entity::setRig(std::shared_ptr<const rigging::SkeletonConfig> rigConfig) {
auto& skeleton = registry.get<rigging::Skeleton>(entity); auto& skeleton = registry.get<rigging::Skeleton>(entity);
skeleton.config = rigConfig; skeleton.setConfig(std::move(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 { dv::value Entity::serialize() const {

View file

@ -60,7 +60,7 @@ public:
rigging::Skeleton* getSkeleton() const; rigging::Skeleton* getSkeleton() const;
void setRig(const rigging::SkeletonConfig* rigConfig); void setRig(std::shared_ptr<const rigging::SkeletonConfig> rigConfig);
entityid_t getUID() const; entityid_t getUID() const;

View file

@ -20,6 +20,7 @@
#include "world/generator/GeneratorDef.hpp" #include "world/generator/GeneratorDef.hpp"
#include "data/dv_util.hpp" #include "data/dv_util.hpp"
#include "debug/Logger.hpp" #include "debug/Logger.hpp"
#include "util/stringutil.hpp"
static debug::Logger logger("player"); static debug::Logger logger("player");
@ -28,7 +29,7 @@ constexpr int SPAWN_ATTEMPTS_PER_UPDATE = 64;
Player::Player( Player::Player(
Level& level, Level& level,
int64_t id, int64_t id,
const std::string& name, const std::wstring& name,
glm::vec3 position, glm::vec3 position,
float speed, float speed,
std::shared_ptr<Inventory> inv, std::shared_ptr<Inventory> inv,
@ -230,11 +231,11 @@ entityid_t Player::getSelectedEntity() const {
return selectedEid; return selectedEid;
} }
void Player::setName(const std::string& name) { void Player::setName(const std::wstring& name) {
this->name = name; this->name = name;
} }
const std::string& Player::getName() const { const std::wstring& Player::getName() const {
return name; return name;
} }
@ -266,7 +267,7 @@ dv::value Player::serialize() const {
auto root = dv::object(); auto root = dv::object();
root["id"] = id; root["id"] = id;
root["name"] = name; root["name"] = util::wstr2str_utf8(name);
root["position"] = dv::to_value(position); root["position"] = dv::to_value(position);
root["rotation"] = dv::to_value(rotation); root["rotation"] = dv::to_value(rotation);
@ -293,7 +294,10 @@ dv::value Player::serialize() const {
void Player::deserialize(const dv::value& src) { void Player::deserialize(const dv::value& src) {
src.at("id").get(id); src.at("id").get(id);
src.at("name").get(name);
std::string utf8name;
src.at("name").get(utf8name);
name = util::str2wstr_utf8(utf8name);
const auto& posarr = src["position"]; const auto& posarr = src["position"];

View file

@ -45,7 +45,7 @@ struct CursorSelection {
class Player : public Serializable { class Player : public Serializable {
Level& level; Level& level;
int64_t id; int64_t id;
std::string name; std::wstring name;
float speed; float speed;
int chosenSlot; int chosenSlot;
@ -79,7 +79,7 @@ public:
Player( Player(
Level& level, Level& level,
int64_t id, int64_t id,
const std::string& name, const std::wstring& name,
glm::vec3 position, glm::vec3 position,
float speed, float speed,
std::shared_ptr<Inventory> inv, std::shared_ptr<Inventory> inv,
@ -124,8 +124,8 @@ public:
entityid_t getSelectedEntity() const; entityid_t getSelectedEntity() const;
void setName(const std::string& name); void setName(const std::wstring& name);
const std::string& getName() const; const std::wstring& getName() const;
const std::shared_ptr<Inventory>& getInventory() const; const std::shared_ptr<Inventory>& getInventory() const;

View file

@ -79,7 +79,7 @@ Player* Players::create(int64_t id) {
auto playerPtr = std::make_unique<Player>( auto playerPtr = std::make_unique<Player>(
level, level,
id, id,
"", L"",
glm::vec3(0, DEF_PLAYER_Y, 0), glm::vec3(0, DEF_PLAYER_Y, 0),
DEF_PLAYER_SPEED, DEF_PLAYER_SPEED,
level.inventories->create(DEF_PLAYER_INVENTORY_SIZE), level.inventories->create(DEF_PLAYER_INVENTORY_SIZE),
@ -134,7 +134,7 @@ void Players::deserialize(const dv::value& src) {
auto playerPtr = std::make_unique<Player>( auto playerPtr = std::make_unique<Player>(
level, level,
0, 0,
"", L"",
glm::vec3(0, DEF_PLAYER_Y, 0), glm::vec3(0, DEF_PLAYER_Y, 0),
DEF_PLAYER_SPEED, DEF_PLAYER_SPEED,
level.inventories->create(DEF_PLAYER_INVENTORY_SIZE), level.inventories->create(DEF_PLAYER_INVENTORY_SIZE),

View file

@ -39,7 +39,7 @@ void Bone::setModel(const std::string& name) {
model = {name, nullptr, true}; model = {name, nullptr, true};
} }
Skeleton::Skeleton(const SkeletonConfig* config) Skeleton::Skeleton(std::shared_ptr<const SkeletonConfig> config)
: config(config), : config(config),
pose(config->getBones().size()), pose(config->getBones().size()),
calculated(config->getBones().size()), calculated(config->getBones().size()),
@ -86,6 +86,16 @@ void Skeleton::deserialize(const dv::value& root) {
} }
} }
void Skeleton::setConfig(std::shared_ptr<const SkeletonConfig> rigConfig) {
config = std::move(rigConfig);
pose.matrices.resize(
config->getBones().size(), glm::mat4(1.0f)
);
calculated.matrices.resize(
config->getBones().size(), glm::mat4(1.0f)
);
}
static void get_all_nodes(std::vector<Bone*>& nodes, Bone* node) { static void get_all_nodes(std::vector<Bone*>& nodes, Bone* node) {
nodes[node->getIndex()] = node; nodes[node->getIndex()] = node;
for (auto& subnode : node->getBones()) { for (auto& subnode : node->getBones()) {
@ -97,6 +107,7 @@ SkeletonConfig::SkeletonConfig(
const std::string& name, std::unique_ptr<Bone> root, size_t nodesCount const std::string& name, std::unique_ptr<Bone> root, size_t nodesCount
) )
: name(name), root(std::move(root)), nodes(nodesCount) { : name(name), root(std::move(root)), nodes(nodesCount) {
assert(this->root.get() != nullptr);
get_all_nodes(nodes, this->root.get()); get_all_nodes(nodes, this->root.get());
} }
@ -159,6 +170,9 @@ void SkeletonConfig::render(
const glm::vec3& position, const glm::vec3& position,
const glm::vec3& scale const glm::vec3& scale
) const { ) const {
if (skeleton.config->root == nullptr) {
return;
}
update(skeleton, rotation, position, scale); update(skeleton, rotation, position, scale);
if (!skeleton.visible) { if (!skeleton.visible) {

View file

@ -78,7 +78,7 @@ namespace rigging {
}; };
struct Skeleton { struct Skeleton {
const SkeletonConfig* config; std::shared_ptr<const SkeletonConfig> config;
Pose pose; Pose pose;
Pose calculated; Pose calculated;
std::vector<BoneFlags> flags; std::vector<BoneFlags> flags;
@ -89,13 +89,15 @@ namespace rigging {
util::VecInterpolation<3, float> interpolation {false}; util::VecInterpolation<3, float> interpolation {false};
Skeleton(const SkeletonConfig* config); Skeleton(std::shared_ptr<const SkeletonConfig> config);
dv::value serialize(bool saveTextures, bool savePose) const; dv::value serialize(bool saveTextures, bool savePose) const;
void deserialize(const dv::value& root); void deserialize(const dv::value& root);
void setConfig(std::shared_ptr<const SkeletonConfig> config);
}; };
class SkeletonConfig { class SkeletonConfig : public std::enable_shared_from_this<SkeletonConfig> {
std::string name; std::string name;
std::unique_ptr<Bone> root; std::unique_ptr<Bone> root;
std::unordered_map<std::string, size_t> indices; std::unordered_map<std::string, size_t> indices;
@ -135,7 +137,7 @@ namespace rigging {
) const; ) const;
Skeleton instance() const { Skeleton instance() const {
return Skeleton(this); return Skeleton(shared_from_this());
} }
const Bone* find(std::string_view str) const; const Bone* find(std::string_view str) const;

View file

@ -294,6 +294,7 @@ public:
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
} else { } else {
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
glfwSetCursor(window, nullptr);
} }
cursorLocked = !cursorLocked; cursorLocked = !cursorLocked;
} }