make wielded item visible to other players

This commit is contained in:
darkrose 2014-09-22 04:55:15 +10:00
parent 7bf52ed570
commit 6dd0db19c1
7 changed files with 338 additions and 283 deletions

View File

@ -526,234 +526,3 @@ void Camera::drawWieldedTool()
m_wieldmgr->drawAll();
}
ExtrudedSpriteSceneNode::ExtrudedSpriteSceneNode(
scene::ISceneNode* parent,
scene::ISceneManager* mgr,
s32 id,
const v3f& position,
const v3f& rotation,
const v3f& scale
):
ISceneNode(parent, mgr, id, position, rotation, scale)
{
m_meshnode = mgr->addMeshSceneNode(NULL, this, -1, v3f(0,0,0), v3f(0,0,0), v3f(1,1,1), true);
m_thickness = 0.1;
m_cubemesh = NULL;
m_is_cube = false;
m_light = LIGHT_MAX;
}
ExtrudedSpriteSceneNode::~ExtrudedSpriteSceneNode()
{
removeChild(m_meshnode);
if (m_cubemesh)
m_cubemesh->drop();
}
void ExtrudedSpriteSceneNode::setSprite(video::ITexture* texture)
{
const v3f sprite_scale(1.0,1.0, 1.0); // width, height, thickness
if (texture == NULL) {
m_meshnode->setVisible(false);
return;
}
io::path name = getExtrudedName(texture);
scene::IMeshCache* cache = SceneManager->getMeshCache();
scene::IAnimatedMesh* mesh = cache->getMeshByName(name);
if (mesh != NULL)
{
// Extruded texture has been found in cache.
m_meshnode->setMesh(mesh);
}
else
{
// Texture was not yet extruded, do it now and save in cache
mesh = createExtrudedMesh(texture, SceneManager->getVideoDriver(), sprite_scale);
if (mesh == NULL)
{
dstream << "Warning: failed to extrude sprite" << std::endl;
m_meshnode->setVisible(false);
return;
}
cache->addMesh(name, mesh);
m_meshnode->setMesh(mesh);
mesh->drop();
}
m_meshnode->setScale(v3f(1, 1, m_thickness));
m_meshnode->getMaterial(0).setTexture(0, texture);
m_meshnode->getMaterial(0).setFlag(video::EMF_LIGHTING, false);
m_meshnode->getMaterial(0).setFlag(video::EMF_BILINEAR_FILTER, false);
m_meshnode->getMaterial(0).MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
m_meshnode->setVisible(true);
m_is_cube = false;
updateLight(m_light);
}
void ExtrudedSpriteSceneNode::setCube(const TileSpec tiles[6])
{
const v3f cube_scale(1.0, 1.0, 1.0);
if (m_cubemesh)
m_cubemesh->drop();
m_cubemesh = createCubeMesh(cube_scale);
m_meshnode->setMesh(m_cubemesh);
m_meshnode->setScale(v3f(1));
for (int i = 0; i < 6; ++i)
{
// Get the tile texture and atlas transformation
video::ITexture* atlas = tiles[i].texture.atlas;
v2f pos = tiles[i].texture.pos;
v2f size = tiles[i].texture.size;
// Set material flags and texture
video::SMaterial& material = m_meshnode->getMaterial(i);
material.setFlag(video::EMF_LIGHTING, false);
material.setFlag(video::EMF_BILINEAR_FILTER, false);
tiles[i].applyMaterialOptions(material);
material.setTexture(0, atlas);
material.getTextureMatrix(0).setTextureTranslate(pos.X, pos.Y);
material.getTextureMatrix(0).setTextureScale(size.X, size.Y);
}
m_meshnode->setVisible(true);
m_is_cube = true;
updateLight(m_light);
}
void ExtrudedSpriteSceneNode::setNodeBox(content_t c)
{
const v3f cube_scale(1.0, 1.0, 1.0);
if (m_cubemesh)
m_cubemesh->drop();
std::vector<aabb3f> boxes = content_features(c).getWieldNodeBoxes();
m_cubemesh = createNodeBoxMesh(boxes,cube_scale);
for (u16 i=0; i < boxes.size(); i++) {
for (int t=0; t<6; t++) {
video::ITexture* atlas = content_features(c).tiles[t].texture.atlas;
v2f pos = content_features(c).tiles[t].texture.pos;
v2f size = content_features(c).tiles[t].texture.size;
video::SMaterial& material = m_cubemesh->getMeshBuffer((i*6)+t)->getMaterial();
material.setFlag(video::EMF_LIGHTING, false);
material.setFlag(video::EMF_BILINEAR_FILTER, false);
content_features(c).tiles[i].applyMaterialOptions(material);
material.setTexture(0, atlas);
material.getTextureMatrix(0).setTextureTranslate(pos.X, pos.Y);
material.getTextureMatrix(0).setTextureScale(size.X, size.Y);
}
}
m_meshnode->setMesh(m_cubemesh);
m_meshnode->setScale(v3f(1));
m_meshnode->setVisible(true);
m_is_cube = true;
updateLight(m_light);
}
void ExtrudedSpriteSceneNode::setArm()
{
const v3f cube_scale(0.3, 1.0, 0.3);
if (m_cubemesh)
m_cubemesh->drop();
m_cubemesh = createCubeMesh(cube_scale);
m_meshnode->setMesh(m_cubemesh);
m_meshnode->setScale(v3f(1));
// Get the tile texture and atlas transformation
std::string tex;
if (getTexturePath("player.png") != "") {
tex = "player.png^[forcesingle";
}else{
tex = "character.png^[forcesingle";
}
video::ITexture* atlas = g_texturesource->getTextureRaw(tex);
v2f pos(0.625,0.5);
v2f size(0.0625,-0.0625);
// Set material flags and texture
video::SMaterial& material = m_meshnode->getMaterial(0);
material.setFlag(video::EMF_LIGHTING, false);
material.setFlag(video::EMF_BILINEAR_FILTER, false);
material.MaterialType = video::EMT_SOLID;
material.BackfaceCulling = true;
material.setTexture(0, atlas);
material.getTextureMatrix(0).setTextureTranslate(pos.X, pos.Y);
material.getTextureMatrix(0).setTextureScale(size.X, size.Y);
for (int i = 1; i < 6; ++i) {
// Get the tile texture and atlas transformation
v2f pos(0.625,1);
v2f size(0.0625,-0.375);
// Set material flags and texture
video::SMaterial& material = m_meshnode->getMaterial(i);
material.setFlag(video::EMF_LIGHTING, false);
material.setFlag(video::EMF_BILINEAR_FILTER, false);
material.MaterialType = video::EMT_SOLID;
material.BackfaceCulling = true;
material.setTexture(0, atlas);
material.getTextureMatrix(0).setTextureTranslate(pos.X, pos.Y);
material.getTextureMatrix(0).setTextureScale(size.X, size.Y);
}
m_meshnode->setVisible(true);
m_is_cube = true;
updateLight(m_light);
}
void ExtrudedSpriteSceneNode::updateLight(u8 light)
{
m_light = light;
u8 li = decode_light(light);
// Set brightness one lower than incoming light
diminish_light(li);
video::SColor color(255,li,li,li);
setMeshVerticesColor(m_meshnode->getMesh(), color);
}
void ExtrudedSpriteSceneNode::removeSpriteFromCache(video::ITexture* texture)
{
scene::IMeshCache* cache = SceneManager->getMeshCache();
scene::IAnimatedMesh* mesh = cache->getMeshByName(getExtrudedName(texture));
if (mesh != NULL)
cache->removeMesh(mesh);
}
void ExtrudedSpriteSceneNode::setSpriteThickness(f32 thickness)
{
m_thickness = thickness;
if (!m_is_cube)
m_meshnode->setScale(v3f(1, 1, thickness));
}
const core::aabbox3d<f32>& ExtrudedSpriteSceneNode::getBoundingBox() const
{
return m_meshnode->getBoundingBox();
}
void ExtrudedSpriteSceneNode::OnRegisterSceneNode()
{
if (IsVisible)
SceneManager->registerNodeForRendering(this);
ISceneNode::OnRegisterSceneNode();
}
void ExtrudedSpriteSceneNode::render()
{
// do nothing
}
io::path ExtrudedSpriteSceneNode::getExtrudedName(video::ITexture* texture)
{
io::path path = texture->getName();
path.append("/[extruded]");
return path;
}

View File

@ -183,53 +183,4 @@ private:
s32 m_digging_button;
};
/*
A scene node that displays a 2D mesh extruded into the third dimension,
to add an illusion of depth.
Since this class was created to display the wielded tool of the local
player, and only tools and items are rendered like this (but not solid
content like stone and mud, which are shown as cubes), the option to
draw a textured cube instead is provided.
*/
class ExtrudedSpriteSceneNode: public scene::ISceneNode
{
public:
ExtrudedSpriteSceneNode(
scene::ISceneNode* parent,
scene::ISceneManager* mgr,
s32 id = -1,
const v3f& position = v3f(0,0,0),
const v3f& rotation = v3f(0,0,0),
const v3f& scale = v3f(1,1,1));
~ExtrudedSpriteSceneNode();
void setSprite(video::ITexture* texture);
void setCube(const TileSpec tiles[6]);
void setNodeBox(content_t c);
void setArm();
f32 getSpriteThickness() const { return m_thickness; }
void setSpriteThickness(f32 thickness);
void updateLight(u8 light);
void removeSpriteFromCache(video::ITexture* texture);
virtual const core::aabbox3d<f32>& getBoundingBox() const;
virtual void OnRegisterSceneNode();
virtual void render();
private:
scene::IMeshSceneNode* m_meshnode;
f32 m_thickness;
scene::IMesh* m_cubemesh;
bool m_is_cube;
u8 m_light;
// internal extrusion helper methods
io::path getExtrudedName(video::ITexture* texture);
};
#endif

View File

@ -1493,6 +1493,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
player->getWieldItem()->serialize(infostream);
infostream<<std::endl;
}
player->wieldItem(0);
}
}
}

View File

@ -30,6 +30,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "path.h"
#include <IMeshLoader.h>
#include <IMeshCache.h>
#include "main.h"
#include "settings.h"
// In Irrlicht 1.8 the signature of ITexture::lock was changed from
// (bool, u32) to (E_TEXTURE_LOCK_MODE, u32).
@ -569,3 +571,234 @@ video::ITexture *generateTextureFromMesh(scene::IMesh *mesh,
return rtt;
}
ExtrudedSpriteSceneNode::ExtrudedSpriteSceneNode(
scene::ISceneNode* parent,
scene::ISceneManager* mgr,
s32 id,
const v3f& position,
const v3f& rotation,
const v3f& scale
):
ISceneNode(parent, mgr, id, position, rotation, scale)
{
m_meshnode = mgr->addMeshSceneNode(NULL, this, -1, v3f(0,0,0), v3f(0,0,0), v3f(1,1,1), true);
m_thickness = 0.1;
m_cubemesh = NULL;
m_is_cube = false;
m_light = LIGHT_MAX;
}
ExtrudedSpriteSceneNode::~ExtrudedSpriteSceneNode()
{
removeChild(m_meshnode);
if (m_cubemesh)
m_cubemesh->drop();
}
void ExtrudedSpriteSceneNode::setSprite(video::ITexture* texture)
{
const v3f sprite_scale(1.0,1.0, 1.0); // width, height, thickness
if (texture == NULL) {
m_meshnode->setVisible(false);
return;
}
io::path name = getExtrudedName(texture);
scene::IMeshCache* cache = SceneManager->getMeshCache();
scene::IAnimatedMesh* mesh = cache->getMeshByName(name);
if (mesh != NULL)
{
// Extruded texture has been found in cache.
m_meshnode->setMesh(mesh);
}
else
{
// Texture was not yet extruded, do it now and save in cache
mesh = createExtrudedMesh(texture, SceneManager->getVideoDriver(), sprite_scale);
if (mesh == NULL)
{
dstream << "Warning: failed to extrude sprite" << std::endl;
m_meshnode->setVisible(false);
return;
}
cache->addMesh(name, mesh);
m_meshnode->setMesh(mesh);
mesh->drop();
}
m_meshnode->setScale(v3f(1, 1, m_thickness));
m_meshnode->getMaterial(0).setTexture(0, texture);
m_meshnode->getMaterial(0).setFlag(video::EMF_LIGHTING, false);
m_meshnode->getMaterial(0).setFlag(video::EMF_BILINEAR_FILTER, false);
m_meshnode->getMaterial(0).MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
m_meshnode->setVisible(true);
m_is_cube = false;
updateLight(m_light);
}
void ExtrudedSpriteSceneNode::setCube(const TileSpec tiles[6])
{
const v3f cube_scale(1.0, 1.0, 1.0);
if (m_cubemesh)
m_cubemesh->drop();
m_cubemesh = createCubeMesh(cube_scale);
m_meshnode->setMesh(m_cubemesh);
m_meshnode->setScale(v3f(1));
for (int i = 0; i < 6; ++i)
{
// Get the tile texture and atlas transformation
video::ITexture* atlas = tiles[i].texture.atlas;
v2f pos = tiles[i].texture.pos;
v2f size = tiles[i].texture.size;
// Set material flags and texture
video::SMaterial& material = m_meshnode->getMaterial(i);
material.setFlag(video::EMF_LIGHTING, false);
material.setFlag(video::EMF_BILINEAR_FILTER, false);
tiles[i].applyMaterialOptions(material);
material.setTexture(0, atlas);
material.getTextureMatrix(0).setTextureTranslate(pos.X, pos.Y);
material.getTextureMatrix(0).setTextureScale(size.X, size.Y);
}
m_meshnode->setVisible(true);
m_is_cube = true;
updateLight(m_light);
}
void ExtrudedSpriteSceneNode::setNodeBox(content_t c)
{
const v3f cube_scale(1.0, 1.0, 1.0);
if (m_cubemesh)
m_cubemesh->drop();
std::vector<aabb3f> boxes = content_features(c).getWieldNodeBoxes();
m_cubemesh = createNodeBoxMesh(boxes,cube_scale);
for (u16 i=0; i < boxes.size(); i++) {
for (int t=0; t<6; t++) {
video::ITexture* atlas = content_features(c).tiles[t].texture.atlas;
v2f pos = content_features(c).tiles[t].texture.pos;
v2f size = content_features(c).tiles[t].texture.size;
video::SMaterial& material = m_cubemesh->getMeshBuffer((i*6)+t)->getMaterial();
material.setFlag(video::EMF_LIGHTING, false);
material.setFlag(video::EMF_BILINEAR_FILTER, false);
content_features(c).tiles[i].applyMaterialOptions(material);
material.setTexture(0, atlas);
material.getTextureMatrix(0).setTextureTranslate(pos.X, pos.Y);
material.getTextureMatrix(0).setTextureScale(size.X, size.Y);
}
}
m_meshnode->setMesh(m_cubemesh);
m_meshnode->setScale(v3f(1));
m_meshnode->setVisible(true);
m_is_cube = true;
updateLight(m_light);
}
void ExtrudedSpriteSceneNode::setArm()
{
const v3f cube_scale(0.3, 1.0, 0.3);
if (m_cubemesh)
m_cubemesh->drop();
m_cubemesh = createCubeMesh(cube_scale);
m_meshnode->setMesh(m_cubemesh);
m_meshnode->setScale(v3f(1));
// Get the tile texture and atlas transformation
std::string tex;
if (getTexturePath("player.png") != "") {
tex = "player.png^[forcesingle";
}else{
tex = "character.png^[forcesingle";
}
video::ITexture* atlas = g_texturesource->getTextureRaw(tex);
v2f pos(0.625,0.5);
v2f size(0.0625,-0.0625);
// Set material flags and texture
video::SMaterial& material = m_meshnode->getMaterial(0);
material.setFlag(video::EMF_LIGHTING, false);
material.setFlag(video::EMF_BILINEAR_FILTER, false);
material.MaterialType = video::EMT_SOLID;
material.BackfaceCulling = true;
material.setTexture(0, atlas);
material.getTextureMatrix(0).setTextureTranslate(pos.X, pos.Y);
material.getTextureMatrix(0).setTextureScale(size.X, size.Y);
for (int i = 1; i < 6; ++i) {
// Get the tile texture and atlas transformation
v2f pos(0.625,1);
v2f size(0.0625,-0.375);
// Set material flags and texture
video::SMaterial& material = m_meshnode->getMaterial(i);
material.setFlag(video::EMF_LIGHTING, false);
material.setFlag(video::EMF_BILINEAR_FILTER, false);
material.MaterialType = video::EMT_SOLID;
material.BackfaceCulling = true;
material.setTexture(0, atlas);
material.getTextureMatrix(0).setTextureTranslate(pos.X, pos.Y);
material.getTextureMatrix(0).setTextureScale(size.X, size.Y);
}
m_meshnode->setVisible(true);
m_is_cube = true;
updateLight(m_light);
}
void ExtrudedSpriteSceneNode::updateLight(u8 light)
{
m_light = light;
u8 li = decode_light(light);
// Set brightness one lower than incoming light
diminish_light(li);
video::SColor color(255,li,li,li);
setMeshVerticesColor(m_meshnode->getMesh(), color);
}
void ExtrudedSpriteSceneNode::removeSpriteFromCache(video::ITexture* texture)
{
scene::IMeshCache* cache = SceneManager->getMeshCache();
scene::IAnimatedMesh* mesh = cache->getMeshByName(getExtrudedName(texture));
if (mesh != NULL)
cache->removeMesh(mesh);
}
void ExtrudedSpriteSceneNode::setSpriteThickness(f32 thickness)
{
m_thickness = thickness;
if (!m_is_cube)
m_meshnode->setScale(v3f(1, 1, thickness));
}
const core::aabbox3d<f32>& ExtrudedSpriteSceneNode::getBoundingBox() const
{
return m_meshnode->getBoundingBox();
}
void ExtrudedSpriteSceneNode::OnRegisterSceneNode()
{
if (IsVisible)
SceneManager->registerNodeForRendering(this);
ISceneNode::OnRegisterSceneNode();
}
void ExtrudedSpriteSceneNode::render()
{
// do nothing
}
io::path ExtrudedSpriteSceneNode::getExtrudedName(video::ITexture* texture)
{
io::path path = texture->getName();
path.append("/[extruded]");
return path;
}

View File

@ -34,6 +34,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <SMeshBuffer.h>
#include <string>
#include <vector>
#include "mapnode.h"
/*
Create a new cube mesh.
@ -101,4 +102,53 @@ video::ITexture *generateTextureFromMesh(scene::IMesh *mesh,
video::SColorf light_color,
f32 light_radius);
/*
A scene node that displays a 2D mesh extruded into the third dimension,
to add an illusion of depth.
Since this class was created to display the wielded tool of the local
player, and only tools and items are rendered like this (but not solid
content like stone and mud, which are shown as cubes), the option to
draw a textured cube instead is provided.
*/
class ExtrudedSpriteSceneNode: public scene::ISceneNode
{
public:
ExtrudedSpriteSceneNode(
scene::ISceneNode* parent,
scene::ISceneManager* mgr,
s32 id = -1,
const v3f& position = v3f(0,0,0),
const v3f& rotation = v3f(0,0,0),
const v3f& scale = v3f(1,1,1));
~ExtrudedSpriteSceneNode();
void setSprite(video::ITexture* texture);
void setCube(const TileSpec tiles[6]);
void setNodeBox(content_t c);
void setArm();
f32 getSpriteThickness() const { return m_thickness; }
void setSpriteThickness(f32 thickness);
void updateLight(u8 light);
void removeSpriteFromCache(video::ITexture* texture);
virtual const core::aabbox3d<f32>& getBoundingBox() const;
virtual void OnRegisterSceneNode();
virtual void render();
private:
scene::IMeshSceneNode* m_meshnode;
f32 m_thickness;
scene::IMesh* m_cubemesh;
bool m_is_cube;
u8 m_light;
// internal extrusion helper methods
io::path getExtrudedName(video::ITexture* texture);
};
#endif

View File

@ -227,12 +227,12 @@ RemotePlayer::RemotePlayer(
scene::ISceneNode(parent, (device==NULL)?NULL:device->getSceneManager(), id),
m_node(NULL),
m_text(NULL),
m_wield(NULL),
m_anim_id(PLAYERANIM_STAND)
{
m_box = core::aabbox3d<f32>(-BS/2,0,-BS/2,BS/2,BS*2,BS/2);
if(parent != NULL && device != NULL)
{
if (parent != NULL && device != NULL) {
// ISceneNode stores a member called SceneManager
scene::ISceneManager* mgr = SceneManager;
video::IVideoDriver* driver = mgr->getVideoDriver();
@ -259,13 +259,16 @@ RemotePlayer::RemotePlayer(
setMeshColor(m_node->getMesh(), video::SColor(255,255,255,255));
// Set material flags and texture
m_node->setMaterialTexture( 0, driver->getTexture(getTexturePath("character.png").c_str()));
m_node->setMaterialTexture(0, driver->getTexture(getTexturePath("character.png").c_str()));
video::SMaterial& material = m_node->getMaterial(0);
material.setFlag(video::EMF_LIGHTING, false);
material.setFlag(video::EMF_BILINEAR_FILTER, false);
material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
m_node->setPosition(v3f(0,(f32)BS,0));
scene::IBoneSceneNode *arm = m_node->getJointNode("Arm_Low_Right");
if (arm)
m_wield = new ExtrudedSpriteSceneNode(arm,mgr,-1,v3f(0,5,1),v3f(-45,-90,45),v3f(4,4,4));
}
#if (IRRLICHT_VERSION_MAJOR >= 1 && IRRLICHT_VERSION_MINOR >= 8) || IRRLICHT_VERSION_MAJOR >= 2
mesh->drop();
@ -304,6 +307,51 @@ void RemotePlayer::updateName(const char *name)
}
}
void RemotePlayer::wieldItem(u16 item)
{
m_selected_item = item;
if (!m_wield)
return;
const InventoryItem *i = getWieldItem();
if (!i) {
m_wield->setVisible(false);
return;
}
bool haveWield = false;
// Try to make a MaterialItem cube.
if (std::string(i->getName()) == "MaterialItem") {
// A block-type material
MaterialItem* mat_item = (MaterialItem*)i;
content_t content = mat_item->getMaterial();
if (content_features(content).solidness || content_features(content).visual_solidness) {
m_wield->setCube(content_features(content).tiles);
haveWield = true;
}else if (
(
content_features(content).draw_type == CDT_NODEBOX
|| content_features(content).draw_type == CDT_NODEBOX_META
|| content_features(content).draw_type == CDT_FENCELIKE
|| content_features(content).draw_type == CDT_WALLLIKE
)
&& content_features(content).wield_nodebox == true
) {
m_wield->setNodeBox(content);
haveWield = true;
}
m_wield->setScale(v3f(3,3,3));
}else{
m_wield->setScale(v3f(4.5,4.5,4.5));
}
// If that failed, make an extruded sprite.
if (!haveWield) {
m_wield->setSprite(i->getImageRaw());
}
m_wield->setVisible(true);
}
void RemotePlayer::move(f32 dtime, Map &map, f32 pos_max_d)
{
m_pos_animation_time_counter += dtime;

View File

@ -302,6 +302,8 @@ public:
void updateName(const char *name);
virtual void wieldItem(u16 item);
virtual void updateAnim(u8 anim_id) {m_anim_id = anim_id;}
virtual void updateLight(u8 light_at_pos)
@ -326,6 +328,7 @@ public:
private:
scene::IAnimatedMeshSceneNode *m_node;
scene::ITextSceneNode* m_text;
class ExtrudedSpriteSceneNode *m_wield;
core::aabbox3d<f32> m_box;
v3f m_oldpos;