summaryrefslogtreecommitdiff
path: root/src/client/content_cao.cpp
diff options
context:
space:
mode:
authorJordan Snelling <jordach.snelling@gmail.com>2020-10-04 14:10:34 +0100
committerGitHub <noreply@github.com>2020-10-04 15:10:34 +0200
commit3068853e8a58ccc7370a5ce977c08223601c497a (patch)
tree07463fe9e41197a743bac3a4cea5d63c22402297 /src/client/content_cao.cpp
parent0f98b54aa4b2361575002d92b29fe222703ba557 (diff)
downloadminetest-3068853e8a58ccc7370a5ce977c08223601c497a.tar.gz
minetest-3068853e8a58ccc7370a5ce977c08223601c497a.tar.bz2
minetest-3068853e8a58ccc7370a5ce977c08223601c497a.zip
Add First Person Attachments (#10360)
Fixes some other third person camera specific attachments. Implements a single new flag for entities to be forced visible in first person mode. Old mods do not need to be updated to use the new flag and are fully backwards compatible.
Diffstat (limited to 'src/client/content_cao.cpp')
-rw-r--r--src/client/content_cao.cpp56
1 files changed, 50 insertions, 6 deletions
diff --git a/src/client/content_cao.cpp b/src/client/content_cao.cpp
index c1715a289..fae06554a 100644
--- a/src/client/content_cao.cpp
+++ b/src/client/content_cao.cpp
@@ -456,7 +456,8 @@ void GenericCAO::setChildrenVisible(bool toset)
for (u16 cao_id : m_attachment_child_ids) {
GenericCAO *obj = m_env->getGenericCAO(cao_id);
if (obj) {
- obj->setVisible(toset);
+ // Check if the entity is forced to appear in first person.
+ obj->setVisible(obj->isForcedVisible() ? true : toset);
}
}
}
@@ -477,8 +478,6 @@ void GenericCAO::setAttachment(int parent_id, const std::string &bone, v3f posit
if (parent)
parent->addAttachmentChild(m_id);
}
-
-
updateAttachments();
}
@@ -498,7 +497,7 @@ void GenericCAO::clearChildAttachments()
int child_id = *m_attachment_child_ids.begin();
if (ClientActiveObject *child = m_env->getActiveObject(child_id))
- child->setAttachment(0, "", v3f(), v3f());
+ child->setAttachment(0, "", v3f(), v3f(), false);
removeAttachmentChild(child_id);
}
@@ -800,6 +799,7 @@ void GenericCAO::addToScene(ITextureSource *tsrc)
updateBonePosition();
updateAttachments();
setNodeLight(m_last_light);
+ updateMeshCulling();
}
void GenericCAO::updateLight(u32 day_night_ratio)
@@ -1411,6 +1411,9 @@ void GenericCAO::updateTextures(std::string mod)
setMeshColor(mesh, m_prop.colors[0]);
}
}
+ // Prevent showing the player after changing texture
+ if (m_is_local_player)
+ updateMeshCulling();
}
void GenericCAO::updateAnimation()
@@ -1739,12 +1742,25 @@ void GenericCAO::processMessage(const std::string &data)
std::string bone = deSerializeString16(is);
v3f position = readV3F32(is);
v3f rotation = readV3F32(is);
+ m_force_visible = readU8(is); // Returns false for EOF
setAttachment(parent_id, bone, position, rotation);
+ // Forcibly show attachments if required by set_attach
+ if (m_force_visible)
+ m_is_visible = true;
// localplayer itself can't be attached to localplayer
- if (!m_is_local_player)
- m_is_visible = !m_attached_to_local;
+ else if (!m_is_local_player) {
+ // Objects attached to the local player should be hidden in first
+ // person provided the forced boolean isn't set.
+ m_is_visible = !m_attached_to_local ||
+ m_client->getCamera()->getCameraMode() != CAMERA_MODE_FIRST;
+ m_force_visible = false;
+ } else {
+ // Local players need to have this set,
+ // otherwise first person attachments fail.
+ m_is_visible = true;
+ }
} else if (cmd == AO_CMD_PUNCHED) {
u16 result_hp = readU16(is);
@@ -1858,5 +1874,33 @@ std::string GenericCAO::debugInfoText()
return os.str();
}
+void GenericCAO::updateMeshCulling()
+{
+ if (!m_is_local_player)
+ return;
+
+ // Grab the active player scene node so we know there's
+ // at least a mesh to occlude from the camera.
+ irr::scene::ISceneNode *node = getSceneNode();
+ if (!node)
+ return;
+
+ if (m_client->getCamera()->getCameraMode() == CAMERA_MODE_FIRST) {
+ // Hide the mesh by culling both front and
+ // back faces. Serious hackyness but it works for our
+ // purposes. This also preserves the skeletal armature.
+ node->setMaterialFlag(video::EMF_BACK_FACE_CULLING,
+ true);
+ node->setMaterialFlag(video::EMF_FRONT_FACE_CULLING,
+ true);
+ } else {
+ // Restore mesh visibility.
+ node->setMaterialFlag(video::EMF_BACK_FACE_CULLING,
+ m_prop.backface_culling);
+ node->setMaterialFlag(video::EMF_FRONT_FACE_CULLING,
+ false);
+ }
+}
+
// Prototype
GenericCAO proto_GenericCAO(NULL, NULL);