commit
b5408d9117
@ -20,6 +20,7 @@ Subsections:
|
||||
- [gfx.blockwraps](scripting/builtins/libgfx-blockwraps.md)
|
||||
- [gfx.particles](particles.md#gfxparticles-library)
|
||||
- [gfx.posteffects](scripting/builtins/libgfx-posteffects.md)
|
||||
- [gfx.skeletons](scripting/builtins/libgfx-skeletons.md)
|
||||
- [gfx.text3d](3d-text.md#gfxtext3d-library)
|
||||
- [gfx.weather](scripting/builtins/libgfx-weather.md)
|
||||
- [gui](scripting/builtins/libgui.md)
|
||||
|
||||
48
doc/en/scripting/builtins/libgfx-skeletons.md
Normal file
48
doc/en/scripting/builtins/libgfx-skeletons.md
Normal file
@ -0,0 +1,48 @@
|
||||
# gfx.skeletons library
|
||||
|
||||
A library for working with named skeletons, such as 'hand',
|
||||
used to control the hand and the carried item displayed in first-person view.
|
||||
The set of functions is similar to the skeleton component of entities.
|
||||
|
||||
The first argument to the function is the name of the skeleton.
|
||||
|
||||
```lua
|
||||
-- Returns an object wrapper over the skeleton
|
||||
local skeleton = gfx.skeletons.get(name: str)
|
||||
|
||||
-- Returns the index of the bone by name or nil
|
||||
skeleton:index(name: str) -> int
|
||||
|
||||
-- Returns the name of the model assigned to the bone with the specified index
|
||||
skeleton:get_model(index: int) -> str
|
||||
|
||||
-- Reassigns the model of the bone with the specified index
|
||||
-- Resets to the original if you do not specify a name
|
||||
skeleton:set_model(index: int, name: str)
|
||||
|
||||
-- Returns the transformation matrix of the bone with the specified index
|
||||
skeleton:get_matrix(index: int) -> mat4
|
||||
|
||||
-- Sets the transformation matrix of the bone with the specified index
|
||||
skeleton:set_matrix(index: int, matrix: mat4)
|
||||
|
||||
-- Returns the texture by key (dynamically assigned textures - '$name')
|
||||
skeleton:get_texture(key: str) -> str
|
||||
|
||||
-- Assigns a texture by key
|
||||
skeleton:set_texture(key: str, value: str)
|
||||
|
||||
-- Checks the visibility status of a bone by index
|
||||
-- or the entire skeleton if index is not specified
|
||||
skeleton:is_visible([optional] index: int) -> bool
|
||||
|
||||
-- Sets the visibility status of a bone by index
|
||||
-- or the entire skeleton if index is not specified
|
||||
skeleton:set_visible([optional] index: int, status: bool)
|
||||
|
||||
-- Returns the color of the entity
|
||||
skeleton:get_color() -> vec3
|
||||
|
||||
-- Sets the color of the entity
|
||||
skeleton:set_color(color: vec3)
|
||||
```
|
||||
@ -65,4 +65,7 @@ hud.is_inventory_open() -> bool
|
||||
|
||||
-- Sets whether to allow pausing. If false, the pause menu will not pause the game.
|
||||
hud.set_allow_pause(flag: bool)
|
||||
|
||||
-- Function that controls the named skeleton 'hand' (see gfx.skeletons)
|
||||
hud.hand_controller: function()
|
||||
```
|
||||
|
||||
@ -20,6 +20,7 @@
|
||||
- [gfx.blockwraps](scripting/builtins/libgfx-blockwraps.md)
|
||||
- [gfx.particles](particles.md#библиотека-gfxparticles)
|
||||
- [gfx.posteffects](scripting/builtins/libgfx-posteffects.md)
|
||||
- [gfx.skeletons](scripting/builtins/libgfx-skeletons.md)
|
||||
- [gfx.text3d](3d-text.md#библиотека-gfxtext3d)
|
||||
- [gfx.weather](scripting/builtins/libgfx-weather.md)
|
||||
- [gui](scripting/builtins/libgui.md)
|
||||
|
||||
49
doc/ru/scripting/builtins/libgfx-skeletons.md
Normal file
49
doc/ru/scripting/builtins/libgfx-skeletons.md
Normal file
@ -0,0 +1,49 @@
|
||||
# Библиотека gfx.skeletons
|
||||
|
||||
Библиотека для работы с именованными скелетами, такими как 'hand',
|
||||
использующийся для управления, отображаемыми при виде от первого лица,
|
||||
рукой и переносимым предметом. Набор функций аналогичен компоненту skeleton
|
||||
у сущностей.
|
||||
|
||||
Первым аргументом в функции передаётся имя скелета.
|
||||
|
||||
```lua
|
||||
-- Возвращает объектную обёртку над скелетом
|
||||
local skeleton = gfx.skeletons.get(name: str)
|
||||
|
||||
-- Возвращает индекс кости по имени или nil
|
||||
skeleton:index(name: str) -> int
|
||||
|
||||
-- Возвращает имя модели, назначенной на кость с указанным индексом
|
||||
skeleton:get_model(index: int) -> str
|
||||
|
||||
-- Переназначает модель кости с указанным индексом
|
||||
-- Сбрасывает до изначальной, если не указывать имя
|
||||
skeleton:set_model(index: int, name: str)
|
||||
|
||||
-- Возвращает матрицу трансформации кости с указанным индексом
|
||||
skeleton:get_matrix(index: int) -> mat4
|
||||
|
||||
-- Устанавливает матрицу трансформации кости с указанным индексом
|
||||
skeleton:set_matrix(index: int, matrix: mat4)
|
||||
|
||||
-- Возвращает текстуру по ключу (динамически назначаемые текстуры - '$имя')
|
||||
skeleton:get_texture(key: str) -> str
|
||||
|
||||
-- Назначает текстуру по ключу
|
||||
skeleton:set_texture(key: str, value: str)
|
||||
|
||||
-- Проверяет статус видимости кости по индесу
|
||||
-- или всего скелета, если индекс не указан
|
||||
skeleton:is_visible([опционально] index: int) -> bool
|
||||
|
||||
-- Устанавливает статус видимости кости по индексу
|
||||
-- или всего скелета, если индекс не указан
|
||||
skeleton:set_visible([опционально] index: int, status: bool)
|
||||
|
||||
-- Возвращает цвет сущности
|
||||
skeleton:get_color() -> vec3
|
||||
|
||||
-- Устанавливает цвет сущности
|
||||
skeleton:set_color(color: vec3)
|
||||
```
|
||||
@ -68,4 +68,7 @@ hud.is_inventory_open() -> bool
|
||||
|
||||
-- Устанавливает разрешение на паузу. При значении false меню паузы не приостанавливает игру.
|
||||
hud.set_allow_pause(flag: bool)
|
||||
|
||||
-- Функция, управляющая именованным скелетом 'hand' (см. gfx.skeletons)
|
||||
hud.hand_controller: function()
|
||||
```
|
||||
|
||||
@ -1,2 +1,3 @@
|
||||
generator = "base:demo"
|
||||
player-entity = "base:player"
|
||||
hand-skeleton = "base:hand"
|
||||
|
||||
9
res/content/base/skeletons/hand.json
Normal file
9
res/content/base/skeletons/hand.json
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"root": {
|
||||
"nodes": [
|
||||
{
|
||||
"name": "item"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -82,3 +82,44 @@ function on_hud_open()
|
||||
|
||||
configure_SSAO()
|
||||
end
|
||||
|
||||
local function update_hand()
|
||||
local skeleton = gfx.skeletons
|
||||
local pid = hud.get_player()
|
||||
local invid, slot = player.get_inventory(pid)
|
||||
local itemid = inventory.get(invid, slot)
|
||||
|
||||
local cam = cameras.get("core:first-person")
|
||||
local bone = skeleton.index("hand", "item")
|
||||
|
||||
local offset = vec3.mul(vec3.sub(cam:get_pos(), {player.get_pos(pid)}), -1)
|
||||
|
||||
local rotation = cam:get_rot()
|
||||
|
||||
local angle = player.get_rot() - 90
|
||||
local cos = math.cos(angle / (180 / math.pi))
|
||||
local sin = math.sin(angle / (180 / math.pi))
|
||||
|
||||
local newX = offset[1] * cos - offset[3] * sin
|
||||
local newZ = offset[1] * sin + offset[3] * cos
|
||||
|
||||
offset[1] = newX
|
||||
offset[3] = newZ
|
||||
|
||||
local mat = mat4.translate(mat4.idt(), {0.06, 0.035, -0.1})
|
||||
mat4.scale(mat, {0.1, 0.1, 0.1}, mat)
|
||||
mat4.mul(rotation, mat, mat)
|
||||
mat4.rotate(mat, {0, 1, 0}, -90, mat)
|
||||
mat4.translate(mat, offset, mat)
|
||||
|
||||
skeleton.set_matrix("hand", bone, mat)
|
||||
skeleton.set_model("hand", bone, item.model_name(itemid))
|
||||
end
|
||||
|
||||
function on_hud_render()
|
||||
if hud.hand_controller then
|
||||
hud.hand_controller()
|
||||
else
|
||||
update_hand()
|
||||
end
|
||||
end
|
||||
|
||||
@ -12,7 +12,27 @@ local Text3D = {__index={
|
||||
update_settings=function(self, t) return gfx.text3d.update_settings(self.id, t) end,
|
||||
}}
|
||||
|
||||
local Skeleton = {__index={
|
||||
index=function(self, s) return gfx.skeletons.index(self.name, s) end,
|
||||
get_model=function(self, i) return gfx.skeletons.get_model(self.name, i) end,
|
||||
set_model=function(self, i, s) return gfx.skeletons.set_model(self.name, i, s) end,
|
||||
get_matrix=function(self, i) return gfx.skeletons.get_matrix(self.name, i) end,
|
||||
set_matrix=function(self, i, m) return gfx.skeletons.set_matrix(self.name, i, m) end,
|
||||
get_texture=function(self, i) return gfx.skeletons.get_texture(self.name, i) end,
|
||||
set_texture=function(self, i, s) return gfx.skeletons.set_texture(self.name, i, s) end,
|
||||
is_visible=function(self, i) return gfx.skeletons.is_visible(self.name, i) end,
|
||||
set_visible=function(self, i, b) return gfx.skeletons.set_visible(self.name, i, b) end,
|
||||
get_color=function(self, i) return gfx.skeletons.get_color(self.name, i) end,
|
||||
set_color=function(self, i, c) return gfx.skeletons.set_color(self.name, i, c) end,
|
||||
}}
|
||||
|
||||
gfx.text3d.new = function(pos, text, preset, extension)
|
||||
local id = gfx.text3d.show(pos, text, preset, extension)
|
||||
return setmetatable({id=id}, Text3D)
|
||||
end
|
||||
|
||||
gfx.skeletons.get = function(name)
|
||||
if gfx.skeletons.exists(name) then
|
||||
return setmetatable({name=name}, Skeleton)
|
||||
end
|
||||
end
|
||||
|
||||
@ -396,6 +396,8 @@ function _rules.clear()
|
||||
end
|
||||
|
||||
function __vc_on_hud_open()
|
||||
gfx.skeletons = __skeleton
|
||||
|
||||
_rules.create("allow-cheats", true)
|
||||
|
||||
_rules.create("allow-content-access", hud._is_content_access(), function(value)
|
||||
|
||||
@ -63,6 +63,14 @@ const rigging::SkeletonConfig* Content::getSkeleton(const std::string& id
|
||||
return found->second.get();
|
||||
}
|
||||
|
||||
const rigging::SkeletonConfig& Content::requireSkeleton(const std::string& id) const {
|
||||
auto skeleton = getSkeleton(id);
|
||||
if (skeleton == nullptr) {
|
||||
throw std::runtime_error("skeleton '" + id + "' not loaded");
|
||||
}
|
||||
return *skeleton;
|
||||
}
|
||||
|
||||
const BlockMaterial* Content::findBlockMaterial(const std::string& id) const {
|
||||
auto found = blockMaterials.find(id);
|
||||
if (found == blockMaterials.end()) {
|
||||
|
||||
@ -212,6 +212,7 @@ public:
|
||||
}
|
||||
|
||||
const rigging::SkeletonConfig* getSkeleton(const std::string& id) const;
|
||||
const rigging::SkeletonConfig& requireSkeleton(const std::string& id) const;
|
||||
const BlockMaterial* findBlockMaterial(const std::string& id) const;
|
||||
const ContentPackRuntime* getPackRuntime(const std::string& id) const;
|
||||
ContentPackRuntime* getPackRuntime(const std::string& id);
|
||||
|
||||
34
src/graphics/render/HandsRenderer.cpp
Normal file
34
src/graphics/render/HandsRenderer.cpp
Normal file
@ -0,0 +1,34 @@
|
||||
#include "HandsRenderer.hpp"
|
||||
|
||||
#include <glm/ext.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
|
||||
#include "ModelBatch.hpp"
|
||||
#include "content/Content.hpp"
|
||||
#include "graphics/commons/Model.hpp"
|
||||
#include "objects/rigging.hpp"
|
||||
#include "window/Camera.hpp"
|
||||
|
||||
using namespace rigging;
|
||||
|
||||
HandsRenderer::HandsRenderer(
|
||||
const Assets& assets,
|
||||
ModelBatch& modelBatch,
|
||||
std::shared_ptr<Skeleton> skeleton
|
||||
)
|
||||
: assets(assets),
|
||||
modelBatch(modelBatch),
|
||||
skeleton(std::move(skeleton)) {
|
||||
}
|
||||
|
||||
void HandsRenderer::renderHands(
|
||||
const Camera& camera, float delta
|
||||
) {
|
||||
auto& skeleton = *this->skeleton;
|
||||
const auto& config = *skeleton.config;
|
||||
|
||||
// render
|
||||
modelBatch.setLightsOffset(camera.position);
|
||||
config.update(skeleton, glm::mat4(1.0f), glm::vec3());
|
||||
config.render(assets, modelBatch, skeleton, glm::mat4(1.0f), glm::vec3());
|
||||
}
|
||||
26
src/graphics/render/HandsRenderer.hpp
Normal file
26
src/graphics/render/HandsRenderer.hpp
Normal file
@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
class Assets;
|
||||
class Camera;
|
||||
class ModelBatch;
|
||||
|
||||
namespace rigging {
|
||||
struct Skeleton;
|
||||
}
|
||||
|
||||
class HandsRenderer {
|
||||
public:
|
||||
HandsRenderer(
|
||||
const Assets& assets,
|
||||
ModelBatch& modelBatch,
|
||||
std::shared_ptr<rigging::Skeleton> skeleton
|
||||
);
|
||||
|
||||
void renderHands(const Camera& camera, float delta);
|
||||
private:
|
||||
const Assets& assets;
|
||||
ModelBatch& modelBatch;
|
||||
std::shared_ptr<rigging::Skeleton> skeleton;
|
||||
};
|
||||
23
src/graphics/render/NamedSkeletons.cpp
Normal file
23
src/graphics/render/NamedSkeletons.cpp
Normal file
@ -0,0 +1,23 @@
|
||||
#include "NamedSkeletons.hpp"
|
||||
|
||||
#include "objects/rigging.hpp"
|
||||
|
||||
using namespace rigging;
|
||||
|
||||
NamedSkeletons::NamedSkeletons() = default;
|
||||
|
||||
std::shared_ptr<rigging::Skeleton> NamedSkeletons::createSkeleton(
|
||||
const std::string& name, const SkeletonConfig* config
|
||||
) {
|
||||
auto skeleton = std::make_shared<Skeleton>(config);
|
||||
skeletons[name] = skeleton;
|
||||
return skeleton;
|
||||
}
|
||||
|
||||
rigging::Skeleton* NamedSkeletons::getSkeleton(const std::string& name) {
|
||||
const auto& found = skeletons.find(name);
|
||||
if (found == skeletons.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
return found->second.get();
|
||||
}
|
||||
23
src/graphics/render/NamedSkeletons.hpp
Normal file
23
src/graphics/render/NamedSkeletons.hpp
Normal file
@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace rigging {
|
||||
struct Skeleton;
|
||||
class SkeletonConfig;
|
||||
}
|
||||
|
||||
class NamedSkeletons {
|
||||
public:
|
||||
NamedSkeletons();
|
||||
|
||||
std::shared_ptr<rigging::Skeleton> createSkeleton(
|
||||
const std::string& name, const rigging::SkeletonConfig* config
|
||||
);
|
||||
|
||||
rigging::Skeleton* getSkeleton(const std::string& name);
|
||||
private:
|
||||
std::unordered_map<std::string, std::shared_ptr<rigging::Skeleton>> skeletons;
|
||||
};
|
||||
@ -47,6 +47,8 @@
|
||||
#include "BlockWrapsRenderer.hpp"
|
||||
#include "ParticlesRenderer.hpp"
|
||||
#include "PrecipitationRenderer.hpp"
|
||||
#include "HandsRenderer.hpp"
|
||||
#include "NamedSkeletons.hpp"
|
||||
#include "TextsRenderer.hpp"
|
||||
#include "ChunksRenderer.hpp"
|
||||
#include "GuidesRenderer.hpp"
|
||||
@ -107,6 +109,15 @@ WorldRenderer::WorldRenderer(
|
||||
settings.graphics.skyboxResolution.get(),
|
||||
assets->require<Shader>("skybox_gen")
|
||||
);
|
||||
|
||||
const auto& content = level.content;
|
||||
skeletons = std::make_unique<NamedSkeletons>();
|
||||
const auto& skeletonConfig = content.requireSkeleton(
|
||||
content.getDefaults()["hand-skeleton"].asString()
|
||||
);
|
||||
hands = std::make_unique<HandsRenderer>(
|
||||
*assets, *modelBatch, skeletons->createSkeleton("hand", &skeletonConfig)
|
||||
);
|
||||
}
|
||||
|
||||
WorldRenderer::~WorldRenderer() = default;
|
||||
@ -273,70 +284,6 @@ void WorldRenderer::renderLines(
|
||||
}
|
||||
}
|
||||
|
||||
void WorldRenderer::renderHands(
|
||||
const Camera& camera, float delta
|
||||
) {
|
||||
auto& entityShader = assets.require<Shader>("entity");
|
||||
auto indices = level.content.getIndices();
|
||||
|
||||
// get current chosen item
|
||||
const auto& inventory = player.getInventory();
|
||||
int slot = player.getChosenSlot();
|
||||
const ItemStack& stack = inventory->getSlot(slot);
|
||||
const auto& def = indices->items.require(stack.getItemId());
|
||||
|
||||
// prepare modified HUD camera
|
||||
Camera hudcam = camera;
|
||||
hudcam.far = 10.0f;
|
||||
hudcam.setFov(0.9f);
|
||||
hudcam.position = {};
|
||||
|
||||
// configure model matrix
|
||||
const glm::vec3 itemOffset(0.06f, 0.035f, -0.1);
|
||||
|
||||
static glm::mat4 prevRotation(1.0f);
|
||||
|
||||
const float speed = 24.0f;
|
||||
glm::mat4 matrix = glm::translate(glm::mat4(1.0f), itemOffset);
|
||||
matrix = glm::scale(matrix, glm::vec3(0.1f));
|
||||
glm::mat4 rotation = camera.rotation;
|
||||
glm::quat rot0 = glm::quat_cast(prevRotation);
|
||||
glm::quat rot1 = glm::quat_cast(rotation);
|
||||
glm::quat finalRot =
|
||||
glm::slerp(rot0, rot1, static_cast<float>(delta * speed));
|
||||
rotation = glm::mat4_cast(finalRot);
|
||||
matrix = rotation * matrix *
|
||||
glm::rotate(
|
||||
glm::mat4(1.0f), -glm::pi<float>() * 0.5f, glm::vec3(0, 1, 0)
|
||||
);
|
||||
prevRotation = rotation;
|
||||
glm::vec3 cameraRotation = player.getRotation();
|
||||
auto offset = -(camera.position - player.getPosition());
|
||||
float angle = glm::radians(cameraRotation.x - 90);
|
||||
float cos = glm::cos(angle);
|
||||
float sin = glm::sin(angle);
|
||||
|
||||
float newX = offset.x * cos - offset.z * sin;
|
||||
float newZ = offset.x * sin + offset.z * cos;
|
||||
offset = glm::vec3(newX, offset.y, newZ);
|
||||
matrix = matrix * glm::translate(glm::mat4(1.0f), offset);
|
||||
|
||||
// render
|
||||
modelBatch->setLightsOffset(camera.position);
|
||||
modelBatch->draw(
|
||||
matrix,
|
||||
glm::vec3(1.0f),
|
||||
assets.get<model::Model>(def.modelName),
|
||||
nullptr
|
||||
);
|
||||
display::clearDepth();
|
||||
setupWorldShader(entityShader, hudcam, engine.getSettings(), 0.0f);
|
||||
skybox->bind();
|
||||
modelBatch->render();
|
||||
modelBatch->setLightsOffset(glm::vec3());
|
||||
skybox->unbind();
|
||||
}
|
||||
|
||||
void WorldRenderer::generateShadowsMap(
|
||||
const Camera& camera,
|
||||
const DrawContext& pctx,
|
||||
@ -568,7 +515,22 @@ void WorldRenderer::draw(
|
||||
DrawContext ctx = pctx.sub();
|
||||
ctx.setDepthTest(true);
|
||||
ctx.setCullFace(true);
|
||||
renderHands(camera, delta);
|
||||
|
||||
// prepare modified HUD camera
|
||||
Camera hudcam = camera;
|
||||
hudcam.far = 10.0f;
|
||||
hudcam.setFov(0.9f);
|
||||
hudcam.position = {};
|
||||
|
||||
hands->renderHands(camera, delta);
|
||||
|
||||
display::clearDepth();
|
||||
setupWorldShader(entityShader, hudcam, engine.getSettings(), 0.0f);
|
||||
|
||||
skybox->bind();
|
||||
modelBatch->render();
|
||||
modelBatch->setLightsOffset(glm::vec3());
|
||||
skybox->unbind();
|
||||
}
|
||||
renderBlockOverlay(pctx);
|
||||
|
||||
|
||||
@ -20,6 +20,8 @@ class ChunksRenderer;
|
||||
class ParticlesRenderer;
|
||||
class BlockWrapsRenderer;
|
||||
class PrecipitationRenderer;
|
||||
class HandsRenderer;
|
||||
class NamedSkeletons;
|
||||
class GuidesRenderer;
|
||||
class TextsRenderer;
|
||||
class Shader;
|
||||
@ -52,6 +54,7 @@ class WorldRenderer {
|
||||
std::unique_ptr<ModelBatch> modelBatch;
|
||||
std::unique_ptr<GuidesRenderer> guides;
|
||||
std::unique_ptr<ChunksRenderer> chunks;
|
||||
std::unique_ptr<HandsRenderer> hands;
|
||||
std::unique_ptr<Skybox> skybox;
|
||||
std::unique_ptr<ShadowMap> shadowMap;
|
||||
std::unique_ptr<ShadowMap> wideShadowMap;
|
||||
@ -69,8 +72,6 @@ class WorldRenderer {
|
||||
|
||||
/// @brief Render block selection lines
|
||||
void renderBlockSelection();
|
||||
|
||||
void renderHands(const Camera& camera, float delta);
|
||||
|
||||
/// @brief Render lines (selection and debug)
|
||||
/// @param camera active camera
|
||||
@ -100,6 +101,7 @@ public:
|
||||
std::unique_ptr<TextsRenderer> texts;
|
||||
std::unique_ptr<BlockWrapsRenderer> blockWraps;
|
||||
std::unique_ptr<PrecipitationRenderer> precipitation;
|
||||
std::unique_ptr<NamedSkeletons> skeletons;
|
||||
|
||||
static bool showChunkBorders;
|
||||
static bool showEntitiesDebug;
|
||||
|
||||
@ -1,6 +1,13 @@
|
||||
#include "objects/rigging.hpp"
|
||||
#include "libentity.hpp"
|
||||
|
||||
#include "graphics/render/WorldRenderer.hpp"
|
||||
#include "graphics/render/NamedSkeletons.hpp"
|
||||
|
||||
namespace scripting {
|
||||
extern WorldRenderer* renderer;
|
||||
}
|
||||
|
||||
static int index_range_check(
|
||||
const rigging::Skeleton& skeleton, lua::Integer index
|
||||
) {
|
||||
@ -13,25 +20,33 @@ static int index_range_check(
|
||||
return static_cast<int>(index);
|
||||
}
|
||||
|
||||
static int l_get_model(lua::State* L) {
|
||||
static rigging::Skeleton* get_skeleton(lua::State* L) {
|
||||
if (lua::isstring(L, 1)) {
|
||||
return scripting::renderer->skeletons->getSkeleton(lua::tostring(L, 1));
|
||||
}
|
||||
if (auto entity = get_entity(L, 1)) {
|
||||
auto& skeleton = entity->getSkeleton();
|
||||
auto* rigConfig = skeleton.config;
|
||||
auto index = index_range_check(skeleton, lua::tointeger(L, 2));
|
||||
const auto& modelOverride = skeleton.modelOverrides[index];
|
||||
return &entity->getSkeleton();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static int l_get_model(lua::State* L) {
|
||||
if (auto skeleton = get_skeleton(L)) {
|
||||
auto& rigConfig = *skeleton->config;
|
||||
auto index = index_range_check(*skeleton, lua::tointeger(L, 2));
|
||||
const auto& modelOverride = skeleton->modelOverrides[index];
|
||||
if (!modelOverride.model) {
|
||||
return lua::pushstring(L, modelOverride.name);
|
||||
}
|
||||
return lua::pushstring(L, rigConfig->getBones()[index]->model.name);
|
||||
return lua::pushstring(L, rigConfig.getBones()[index]->model.name);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_set_model(lua::State* L) {
|
||||
if (auto entity = get_entity(L, 1)) {
|
||||
auto& skeleton = entity->getSkeleton();
|
||||
auto index = index_range_check(skeleton, lua::tointeger(L, 2));
|
||||
auto& modelOverride = skeleton.modelOverrides[index];
|
||||
if (auto skeleton = get_skeleton(L)) {
|
||||
auto index = index_range_check(*skeleton, lua::tointeger(L, 2));
|
||||
auto& modelOverride = skeleton->modelOverrides[index];
|
||||
if (lua::isnoneornil(L, 3)) {
|
||||
modelOverride = {"", nullptr, true};
|
||||
} else {
|
||||
@ -42,28 +57,25 @@ static int l_set_model(lua::State* L) {
|
||||
}
|
||||
|
||||
static int l_get_matrix(lua::State* L) {
|
||||
if (auto entity = get_entity(L, 1)) {
|
||||
auto& skeleton = entity->getSkeleton();
|
||||
auto index = index_range_check(skeleton, lua::tointeger(L, 2));
|
||||
return lua::pushmat4(L, skeleton.pose.matrices[index]);
|
||||
if (auto skeleton = get_skeleton(L)) {
|
||||
auto index = index_range_check(*skeleton, lua::tointeger(L, 2));
|
||||
return lua::pushmat4(L, skeleton->pose.matrices[index]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_set_matrix(lua::State* L) {
|
||||
if (auto entity = get_entity(L, 1)) {
|
||||
auto& skeleton = entity->getSkeleton();
|
||||
auto index = index_range_check(skeleton, lua::tointeger(L, 2));
|
||||
skeleton.pose.matrices[index] = lua::tomat4(L, 3);
|
||||
if (auto skeleton = get_skeleton(L)) {
|
||||
auto index = index_range_check(*skeleton, lua::tointeger(L, 2));
|
||||
skeleton->pose.matrices[index] = lua::tomat4(L, 3);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_get_texture(lua::State* L) {
|
||||
if (auto entity = get_entity(L, 1)) {
|
||||
auto& skeleton = entity->getSkeleton();
|
||||
const auto& found = skeleton.textures.find(lua::require_string(L, 2));
|
||||
if (found != skeleton.textures.end()) {
|
||||
if (auto skeleton = get_skeleton(L)) {
|
||||
const auto& found = skeleton->textures.find(lua::require_string(L, 2));
|
||||
if (found != skeleton->textures.end()) {
|
||||
return lua::pushstring(L, found->second);
|
||||
}
|
||||
}
|
||||
@ -71,18 +83,16 @@ static int l_get_texture(lua::State* L) {
|
||||
}
|
||||
|
||||
static int l_set_texture(lua::State* L) {
|
||||
if (auto entity = get_entity(L, 1)) {
|
||||
auto& skeleton = entity->getSkeleton();
|
||||
skeleton.textures[lua::require_string(L, 2)] =
|
||||
if (auto skeleton = get_skeleton(L)) {
|
||||
skeleton->textures[lua::require_string(L, 2)] =
|
||||
lua::require_string(L, 3);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_index(lua::State* L) {
|
||||
if (auto entity = get_entity(L, 1)) {
|
||||
auto& skeleton = entity->getSkeleton();
|
||||
if (auto bone = skeleton.config->find(lua::require_string(L, 2))) {
|
||||
if (auto skeleton= get_skeleton(L)) {
|
||||
if (auto bone = skeleton->config->find(lua::require_string(L, 2))) {
|
||||
return lua::pushinteger(L, bone->getIndex());
|
||||
}
|
||||
}
|
||||
@ -90,62 +100,60 @@ static int l_index(lua::State* L) {
|
||||
}
|
||||
|
||||
static int l_is_visible(lua::State* L) {
|
||||
if (auto entity = get_entity(L, 1)) {
|
||||
auto& skeleton = entity->getSkeleton();
|
||||
if (auto skeleton = get_skeleton(L)) {
|
||||
if (!lua::isnoneornil(L, 2)) {
|
||||
auto index = index_range_check(skeleton, lua::tointeger(L, 2));
|
||||
return lua::pushboolean(L, skeleton.flags.at(index).visible);
|
||||
auto index = index_range_check(*skeleton, lua::tointeger(L, 2));
|
||||
return lua::pushboolean(L, skeleton->flags.at(index).visible);
|
||||
}
|
||||
return lua::pushboolean(L, skeleton.visible);
|
||||
return lua::pushboolean(L, skeleton->visible);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_set_visible(lua::State* L) {
|
||||
if (auto entity = get_entity(L, 1)) {
|
||||
auto& skeleton = entity->getSkeleton();
|
||||
if (auto skeleton = get_skeleton(L)) {
|
||||
if (!lua::isnoneornil(L, 3)) {
|
||||
auto index = index_range_check(skeleton, lua::tointeger(L, 2));
|
||||
skeleton.flags.at(index).visible = lua::toboolean(L, 3);
|
||||
auto index = index_range_check(*skeleton, lua::tointeger(L, 2));
|
||||
skeleton->flags.at(index).visible = lua::toboolean(L, 3);
|
||||
} else {
|
||||
skeleton.visible = lua::toboolean(L, 2);
|
||||
skeleton->visible = lua::toboolean(L, 2);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_get_color(lua::State* L) {
|
||||
if (auto entity = get_entity(L, 1)) {
|
||||
auto& skeleton = entity->getSkeleton();
|
||||
return lua::pushvec(L, skeleton.tint);
|
||||
if (auto skeleton = get_skeleton(L)) {
|
||||
return lua::pushvec(L, skeleton->tint);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_set_color(lua::State* L) {
|
||||
if (auto entity = get_entity(L, 1)) {
|
||||
auto& skeleton = entity->getSkeleton();
|
||||
skeleton.tint = lua::tovec3(L, 2);
|
||||
if (auto skeleton = get_skeleton(L)) {
|
||||
skeleton->tint = lua::tovec3(L, 2);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_is_interpolated(lua::State* L) {
|
||||
if (auto entity = get_entity(L, 1)) {
|
||||
auto& skeleton = entity->getSkeleton();
|
||||
return lua::pushboolean(L, skeleton.interpolation.isEnabled());
|
||||
if (auto skeleton = get_skeleton(L)) {
|
||||
return lua::pushboolean(L, skeleton->interpolation.isEnabled());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_set_interpolated(lua::State* L) {
|
||||
if (auto entity = get_entity(L, 1)) {
|
||||
auto& skeleton = entity->getSkeleton();
|
||||
skeleton.interpolation.setEnabled(lua::toboolean(L, 2));
|
||||
if (auto skeleton = get_skeleton(L)) {
|
||||
skeleton->interpolation.setEnabled(lua::toboolean(L, 2));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_exists(lua::State* L) {
|
||||
return lua::pushboolean(L, get_skeleton(L));
|
||||
}
|
||||
|
||||
const luaL_Reg skeletonlib[] = {
|
||||
{"get_model", lua::wrap<l_get_model>},
|
||||
{"set_model", lua::wrap<l_set_model>},
|
||||
@ -160,4 +168,6 @@ const luaL_Reg skeletonlib[] = {
|
||||
{"set_color", lua::wrap<l_set_color>},
|
||||
{"is_interpolated", lua::wrap<l_is_interpolated>},
|
||||
{"set_interpolated", lua::wrap<l_set_interpolated>},
|
||||
{NULL, NULL}};
|
||||
{"exists", lua::wrap<l_exists>},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user