mirror of
https://github.com/minetest/minetest.git
synced 2024-11-23 16:13:46 +01:00
Hardware coloring for itemstacks
Adds the possibility to colorize item stacks based on their metadata. In the item/node definition you can specify palette (an image file) and color (fallback color if the item has no palette or metadata). Then you can add palette_index to the metadata. Dropped itemstacks with different colors do not merge.
This commit is contained in:
parent
d4e9dd4643
commit
58d83a7bb2
@ -53,6 +53,8 @@ core.register_entity(":__builtin:item", {
|
|||||||
if itemtable then
|
if itemtable then
|
||||||
itemname = stack:to_table().name
|
itemname = stack:to_table().name
|
||||||
end
|
end
|
||||||
|
-- Backwards compatibility: old clients use the texture
|
||||||
|
-- to get the type of the item
|
||||||
local item_texture = nil
|
local item_texture = nil
|
||||||
local item_type = ""
|
local item_type = ""
|
||||||
if core.registered_items[itemname] then
|
if core.registered_items[itemname] then
|
||||||
@ -66,6 +68,7 @@ core.register_entity(":__builtin:item", {
|
|||||||
visual_size = {x = s, y = s},
|
visual_size = {x = s, y = s},
|
||||||
collisionbox = {-c, -c, -c, c, c, c},
|
collisionbox = {-c, -c, -c, c, c, c},
|
||||||
automatic_rotate = math.pi * 0.5,
|
automatic_rotate = math.pi * 0.5,
|
||||||
|
wield_item = itemstring,
|
||||||
}
|
}
|
||||||
self.object:set_properties(prop)
|
self.object:set_properties(prop)
|
||||||
end,
|
end,
|
||||||
@ -101,31 +104,39 @@ core.register_entity(":__builtin:item", {
|
|||||||
self:set_item(self.itemstring)
|
self:set_item(self.itemstring)
|
||||||
end,
|
end,
|
||||||
|
|
||||||
|
-- moves items from this stack to an other stack
|
||||||
try_merge_with = function(self, own_stack, object, obj)
|
try_merge_with = function(self, own_stack, object, obj)
|
||||||
|
-- other item's stack
|
||||||
local stack = ItemStack(obj.itemstring)
|
local stack = ItemStack(obj.itemstring)
|
||||||
if own_stack:get_name() == stack:get_name() and stack:get_free_space() > 0 then
|
-- only merge if items are the same
|
||||||
|
if own_stack:get_name() == stack:get_name() and
|
||||||
|
own_stack:get_meta() == stack:get_meta() and
|
||||||
|
own_stack:get_wear() == stack:get_wear() and
|
||||||
|
stack:get_free_space() > 0 then
|
||||||
local overflow = false
|
local overflow = false
|
||||||
local count = stack:get_count() + own_stack:get_count()
|
local count = stack:get_count() + own_stack:get_count()
|
||||||
local max_count = stack:get_stack_max()
|
local max_count = stack:get_stack_max()
|
||||||
if count > max_count then
|
if count > max_count then
|
||||||
overflow = true
|
overflow = true
|
||||||
|
stack:set_count(max_count)
|
||||||
count = count - max_count
|
count = count - max_count
|
||||||
|
own_stack:set_count(count)
|
||||||
else
|
else
|
||||||
self.itemstring = ''
|
self.itemstring = ''
|
||||||
|
stack:set_count(count)
|
||||||
end
|
end
|
||||||
local pos = object:getpos()
|
local pos = object:getpos()
|
||||||
pos.y = pos.y + (count - stack:get_count()) / max_count * 0.15
|
pos.y = pos.y + (count - stack:get_count()) / max_count * 0.15
|
||||||
object:moveto(pos, false)
|
object:moveto(pos, false)
|
||||||
local s, c
|
local s, c
|
||||||
local max_count = stack:get_stack_max()
|
|
||||||
local name = stack:get_name()
|
|
||||||
if not overflow then
|
if not overflow then
|
||||||
obj.itemstring = name .. " " .. count
|
obj.itemstring = stack:to_string()
|
||||||
s = 0.2 + 0.1 * (count / max_count)
|
s = 0.2 + 0.1 * (count / max_count)
|
||||||
c = s
|
c = s
|
||||||
object:set_properties({
|
object:set_properties({
|
||||||
visual_size = {x = s, y = s},
|
visual_size = {x = s, y = s},
|
||||||
collisionbox = {-c, -c, -c, c, c, c}
|
collisionbox = {-c, -c, -c, c, c, c},
|
||||||
|
wield_item = obj.itemstring
|
||||||
})
|
})
|
||||||
self.object:remove()
|
self.object:remove()
|
||||||
-- merging succeeded
|
-- merging succeeded
|
||||||
@ -133,18 +144,20 @@ core.register_entity(":__builtin:item", {
|
|||||||
else
|
else
|
||||||
s = 0.4
|
s = 0.4
|
||||||
c = 0.3
|
c = 0.3
|
||||||
|
obj.itemstring = stack:to_string()
|
||||||
object:set_properties({
|
object:set_properties({
|
||||||
visual_size = {x = s, y = s},
|
visual_size = {x = s, y = s},
|
||||||
collisionbox = {-c, -c, -c, c, c, c}
|
collisionbox = {-c, -c, -c, c, c, c},
|
||||||
|
wield_item = obj.itemstring
|
||||||
})
|
})
|
||||||
obj.itemstring = name .. " " .. max_count
|
|
||||||
s = 0.2 + 0.1 * (count / max_count)
|
s = 0.2 + 0.1 * (count / max_count)
|
||||||
c = s
|
c = s
|
||||||
|
self.itemstring = own_stack:to_string()
|
||||||
self.object:set_properties({
|
self.object:set_properties({
|
||||||
visual_size = {x = s, y = s},
|
visual_size = {x = s, y = s},
|
||||||
collisionbox = {-c, -c, -c, c, c, c}
|
collisionbox = {-c, -c, -c, c, c, c},
|
||||||
|
wield_item = self.itemstring
|
||||||
})
|
})
|
||||||
self.itemstring = name .. " " .. count
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
-- merging didn't succeed
|
-- merging didn't succeed
|
||||||
|
@ -1480,6 +1480,9 @@ Item metadata only contains a key-value store.
|
|||||||
Some of the values in the key-value store are handled specially:
|
Some of the values in the key-value store are handled specially:
|
||||||
|
|
||||||
* `description`: Set the itemstack's description. Defaults to idef.description
|
* `description`: Set the itemstack's description. Defaults to idef.description
|
||||||
|
* `color`: A `ColorString`, which sets the stack's color.
|
||||||
|
* `palette_index`: If the item has a palette, this is used to get the
|
||||||
|
current color from the palette.
|
||||||
|
|
||||||
Example stuff:
|
Example stuff:
|
||||||
|
|
||||||
@ -2855,6 +2858,8 @@ See `StorageRef`, `NodeMetaRef` and `ItemStackMetaRef`.
|
|||||||
* Any non-table value will clear the metadata
|
* Any non-table value will clear the metadata
|
||||||
* See "Node Metadata" for an example
|
* See "Node Metadata" for an example
|
||||||
* returns `true` on success
|
* returns `true` on success
|
||||||
|
* `equals(other)`
|
||||||
|
* returns `true` if this metadata has the same key-value pairs as `other`
|
||||||
|
|
||||||
### `NodeMetaRef`
|
### `NodeMetaRef`
|
||||||
Node metadata: reference extra data and functionality stored in a node.
|
Node metadata: reference extra data and functionality stored in a node.
|
||||||
@ -3735,6 +3740,19 @@ Definition tables
|
|||||||
{hard = 1, metal = 1, spikes = 1}
|
{hard = 1, metal = 1, spikes = 1}
|
||||||
inventory_image = "default_tool_steelaxe.png",
|
inventory_image = "default_tool_steelaxe.png",
|
||||||
wield_image = "",
|
wield_image = "",
|
||||||
|
palette = "",
|
||||||
|
--[[
|
||||||
|
^ An image file containing the palette of a node.
|
||||||
|
^ You can set the currently used color as the
|
||||||
|
^ "palette_index" field of the item stack metadata.
|
||||||
|
^ The palette is always stretched to fit indices
|
||||||
|
^ between 0 and 255, to ensure compatibility with
|
||||||
|
^ "colorfacedir" and "colorwallmounted" nodes.
|
||||||
|
]]
|
||||||
|
color = "0xFFFFFFFF",
|
||||||
|
--[[
|
||||||
|
^ The color of the item. The palette overrides this.
|
||||||
|
]]
|
||||||
wield_scale = {x = 1, y = 1, z = 1},
|
wield_scale = {x = 1, y = 1, z = 1},
|
||||||
stack_max = 99,
|
stack_max = 99,
|
||||||
range = 4.0,
|
range = 4.0,
|
||||||
|
@ -501,7 +501,8 @@ void Camera::setDigging(s32 button)
|
|||||||
|
|
||||||
void Camera::wield(const ItemStack &item)
|
void Camera::wield(const ItemStack &item)
|
||||||
{
|
{
|
||||||
if (item.name != m_wield_item_next.name) {
|
if (item.name != m_wield_item_next.name ||
|
||||||
|
item.metadata != m_wield_item_next.metadata) {
|
||||||
m_wield_item_next = item;
|
m_wield_item_next = item;
|
||||||
if (m_wield_change_timer > 0)
|
if (m_wield_change_timer > 0)
|
||||||
m_wield_change_timer = -m_wield_change_timer;
|
m_wield_change_timer = -m_wield_change_timer;
|
||||||
|
@ -341,6 +341,8 @@ public:
|
|||||||
*/
|
*/
|
||||||
video::ITexture* getTextureForMesh(const std::string &name, u32 *id);
|
video::ITexture* getTextureForMesh(const std::string &name, u32 *id);
|
||||||
|
|
||||||
|
virtual Palette* getPalette(const std::string &name);
|
||||||
|
|
||||||
// Returns a pointer to the irrlicht device
|
// Returns a pointer to the irrlicht device
|
||||||
virtual IrrlichtDevice* getDevice()
|
virtual IrrlichtDevice* getDevice()
|
||||||
{
|
{
|
||||||
@ -377,8 +379,6 @@ public:
|
|||||||
video::ITexture* generateTextureFromMesh(
|
video::ITexture* generateTextureFromMesh(
|
||||||
const TextureFromMeshParams ¶ms);
|
const TextureFromMeshParams ¶ms);
|
||||||
|
|
||||||
video::IImage* generateImage(const std::string &name);
|
|
||||||
|
|
||||||
video::ITexture* getNormalTexture(const std::string &name);
|
video::ITexture* getNormalTexture(const std::string &name);
|
||||||
video::SColor getTextureAverageColor(const std::string &name);
|
video::SColor getTextureAverageColor(const std::string &name);
|
||||||
video::ITexture *getShaderFlagsTexture(bool normamap_present);
|
video::ITexture *getShaderFlagsTexture(bool normamap_present);
|
||||||
@ -401,6 +401,13 @@ private:
|
|||||||
// if baseimg is NULL, it is created. Otherwise stuff is made on it.
|
// if baseimg is NULL, it is created. Otherwise stuff is made on it.
|
||||||
bool generateImagePart(std::string part_of_name, video::IImage *& baseimg);
|
bool generateImagePart(std::string part_of_name, video::IImage *& baseimg);
|
||||||
|
|
||||||
|
/*! Generates an image from a full string like
|
||||||
|
* "stone.png^mineral_coal.png^[crack:1:0".
|
||||||
|
* Shall be called from the main thread.
|
||||||
|
* The returned Image should be dropped.
|
||||||
|
*/
|
||||||
|
video::IImage* generateImage(const std::string &name);
|
||||||
|
|
||||||
// Thread-safe cache of what source images are known (true = known)
|
// Thread-safe cache of what source images are known (true = known)
|
||||||
MutexedMap<std::string, bool> m_source_image_existence;
|
MutexedMap<std::string, bool> m_source_image_existence;
|
||||||
|
|
||||||
@ -419,6 +426,9 @@ private:
|
|||||||
// but can't be deleted because the ITexture* might still be used
|
// but can't be deleted because the ITexture* might still be used
|
||||||
std::vector<video::ITexture*> m_texture_trash;
|
std::vector<video::ITexture*> m_texture_trash;
|
||||||
|
|
||||||
|
// Maps image file names to loaded palettes.
|
||||||
|
UNORDERED_MAP<std::string, Palette> m_palettes;
|
||||||
|
|
||||||
// Cached settings needed for making textures from meshes
|
// Cached settings needed for making textures from meshes
|
||||||
bool m_setting_trilinear_filter;
|
bool m_setting_trilinear_filter;
|
||||||
bool m_setting_bilinear_filter;
|
bool m_setting_bilinear_filter;
|
||||||
@ -682,6 +692,61 @@ video::ITexture* TextureSource::getTextureForMesh(const std::string &name, u32 *
|
|||||||
return getTexture(name + "^[applyfiltersformesh", id);
|
return getTexture(name + "^[applyfiltersformesh", id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Palette* TextureSource::getPalette(const std::string &name)
|
||||||
|
{
|
||||||
|
// Only the main thread may load images
|
||||||
|
sanity_check(thr_is_current_thread(m_main_thread));
|
||||||
|
|
||||||
|
if (name == "")
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
UNORDERED_MAP<std::string, Palette>::iterator it = m_palettes.find(name);
|
||||||
|
if (it == m_palettes.end()) {
|
||||||
|
// Create palette
|
||||||
|
video::IImage *img = generateImage(name);
|
||||||
|
if (!img) {
|
||||||
|
warningstream << "TextureSource::getPalette(): palette \"" << name
|
||||||
|
<< "\" could not be loaded." << std::endl;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
Palette new_palette;
|
||||||
|
u32 w = img->getDimension().Width;
|
||||||
|
u32 h = img->getDimension().Height;
|
||||||
|
// Real area of the image
|
||||||
|
u32 area = h * w;
|
||||||
|
if (area == 0)
|
||||||
|
return NULL;
|
||||||
|
if (area > 256) {
|
||||||
|
warningstream << "TextureSource::getPalette(): the specified"
|
||||||
|
<< " palette image \"" << name << "\" is larger than 256"
|
||||||
|
<< " pixels, using the first 256." << std::endl;
|
||||||
|
area = 256;
|
||||||
|
} else if (256 % area != 0)
|
||||||
|
warningstream << "TextureSource::getPalette(): the "
|
||||||
|
<< "specified palette image \"" << name << "\" does not "
|
||||||
|
<< "contain power of two pixels." << std::endl;
|
||||||
|
// We stretch the palette so it will fit 256 values
|
||||||
|
// This many param2 values will have the same color
|
||||||
|
u32 step = 256 / area;
|
||||||
|
// For each pixel in the image
|
||||||
|
for (u32 i = 0; i < area; i++) {
|
||||||
|
video::SColor c = img->getPixel(i % w, i / w);
|
||||||
|
// Fill in palette with 'step' colors
|
||||||
|
for (u32 j = 0; j < step; j++)
|
||||||
|
new_palette.push_back(c);
|
||||||
|
}
|
||||||
|
img->drop();
|
||||||
|
// Fill in remaining elements
|
||||||
|
while (new_palette.size() < 256)
|
||||||
|
new_palette.push_back(video::SColor(0xFFFFFFFF));
|
||||||
|
m_palettes[name] = new_palette;
|
||||||
|
it = m_palettes.find(name);
|
||||||
|
}
|
||||||
|
if (it != m_palettes.end())
|
||||||
|
return &((*it).second);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
void TextureSource::processQueue()
|
void TextureSource::processQueue()
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@ -33,6 +33,8 @@ class IGameDef;
|
|||||||
struct TileSpec;
|
struct TileSpec;
|
||||||
struct TileDef;
|
struct TileDef;
|
||||||
|
|
||||||
|
typedef std::vector<video::SColor> Palette;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
tile.{h,cpp}: Texture handling stuff.
|
tile.{h,cpp}: Texture handling stuff.
|
||||||
*/
|
*/
|
||||||
@ -106,14 +108,15 @@ public:
|
|||||||
const std::string &name, u32 *id = NULL)=0;
|
const std::string &name, u32 *id = NULL)=0;
|
||||||
virtual video::ITexture* getTextureForMesh(
|
virtual video::ITexture* getTextureForMesh(
|
||||||
const std::string &name, u32 *id = NULL) = 0;
|
const std::string &name, u32 *id = NULL) = 0;
|
||||||
|
/*!
|
||||||
|
* Returns a palette from the given texture name.
|
||||||
|
* The pointer is valid until the texture source is
|
||||||
|
* destructed.
|
||||||
|
* Should be called from the main thread.
|
||||||
|
*/
|
||||||
|
virtual Palette* getPalette(const std::string &name) = 0;
|
||||||
virtual IrrlichtDevice* getDevice()=0;
|
virtual IrrlichtDevice* getDevice()=0;
|
||||||
virtual bool isKnownSourceImage(const std::string &name)=0;
|
virtual bool isKnownSourceImage(const std::string &name)=0;
|
||||||
/*! Generates an image from a full string like
|
|
||||||
* "stone.png^mineral_coal.png^[crack:1:0".
|
|
||||||
* Shall be called from the main thread.
|
|
||||||
* The returned Image should be dropped.
|
|
||||||
*/
|
|
||||||
virtual video::IImage* generateImage(const std::string &name)=0;
|
|
||||||
virtual video::ITexture* generateTextureFromMesh(
|
virtual video::ITexture* generateTextureFromMesh(
|
||||||
const TextureFromMeshParams ¶ms)=0;
|
const TextureFromMeshParams ¶ms)=0;
|
||||||
virtual video::ITexture* getNormalTexture(const std::string &name)=0;
|
virtual video::ITexture* getNormalTexture(const std::string &name)=0;
|
||||||
|
@ -933,23 +933,30 @@ void GenericCAO::addToScene(scene::ISceneManager *smgr,
|
|||||||
errorstream<<"GenericCAO::addToScene(): Could not load mesh "<<m_prop.mesh<<std::endl;
|
errorstream<<"GenericCAO::addToScene(): Could not load mesh "<<m_prop.mesh<<std::endl;
|
||||||
}
|
}
|
||||||
else if(m_prop.visual == "wielditem") {
|
else if(m_prop.visual == "wielditem") {
|
||||||
infostream<<"GenericCAO::addToScene(): wielditem"<<std::endl;
|
ItemStack item;
|
||||||
infostream<<"textures: "<<m_prop.textures.size()<<std::endl;
|
infostream << "GenericCAO::addToScene(): wielditem" << std::endl;
|
||||||
if(m_prop.textures.size() >= 1){
|
if (m_prop.wield_item == "") {
|
||||||
infostream<<"textures[0]: "<<m_prop.textures[0]<<std::endl;
|
// Old format, only textures are specified.
|
||||||
IItemDefManager *idef = m_client->idef();
|
infostream << "textures: " << m_prop.textures.size() << std::endl;
|
||||||
ItemStack item(m_prop.textures[0], 1, 0, idef);
|
if (m_prop.textures.size() >= 1) {
|
||||||
|
infostream << "textures[0]: " << m_prop.textures[0]
|
||||||
m_wield_meshnode = new WieldMeshSceneNode(
|
<< std::endl;
|
||||||
smgr->getRootSceneNode(), smgr, -1);
|
IItemDefManager *idef = m_client->idef();
|
||||||
m_wield_meshnode->setItem(item, m_client);
|
item = ItemStack(m_prop.textures[0], 1, 0, idef);
|
||||||
|
}
|
||||||
m_wield_meshnode->setScale(v3f(m_prop.visual_size.X/2,
|
} else {
|
||||||
m_prop.visual_size.Y/2,
|
infostream << "serialized form: " << m_prop.wield_item << std::endl;
|
||||||
m_prop.visual_size.X/2));
|
item.deSerialize(m_prop.wield_item, m_client->idef());
|
||||||
u8 li = m_last_light;
|
|
||||||
m_wield_meshnode->setColor(video::SColor(255,li,li,li));
|
|
||||||
}
|
}
|
||||||
|
m_wield_meshnode = new WieldMeshSceneNode(smgr->getRootSceneNode(),
|
||||||
|
smgr, -1);
|
||||||
|
m_wield_meshnode->setItem(item, m_client);
|
||||||
|
|
||||||
|
m_wield_meshnode->setScale(
|
||||||
|
v3f(m_prop.visual_size.X / 2, m_prop.visual_size.Y / 2,
|
||||||
|
m_prop.visual_size.X / 2));
|
||||||
|
u8 li = m_last_light;
|
||||||
|
m_wield_meshnode->setColor(video::SColor(255, li, li, li));
|
||||||
} else {
|
} else {
|
||||||
infostream<<"GenericCAO::addToScene(): \""<<m_prop.visual
|
infostream<<"GenericCAO::addToScene(): \""<<m_prop.visual
|
||||||
<<"\" not supported"<<std::endl;
|
<<"\" not supported"<<std::endl;
|
||||||
|
20
src/hud.cpp
20
src/hud.cpp
@ -32,6 +32,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "fontengine.h"
|
#include "fontengine.h"
|
||||||
#include "guiscalingfilter.h"
|
#include "guiscalingfilter.h"
|
||||||
#include "mesh.h"
|
#include "mesh.h"
|
||||||
|
#include "wieldmesh.h"
|
||||||
#include <IGUIStaticText.h>
|
#include <IGUIStaticText.h>
|
||||||
|
|
||||||
#ifdef HAVE_TOUCHSCREENGUI
|
#ifdef HAVE_TOUCHSCREENGUI
|
||||||
@ -642,9 +643,10 @@ void drawItemStack(video::IVideoDriver *driver,
|
|||||||
}
|
}
|
||||||
|
|
||||||
const ItemDefinition &def = item.getDefinition(client->idef());
|
const ItemDefinition &def = item.getDefinition(client->idef());
|
||||||
scene::IMesh* mesh = client->idef()->getWieldMesh(def.name, client);
|
ItemMesh *imesh = client->idef()->getWieldMesh(def.name, client);
|
||||||
|
|
||||||
if (mesh) {
|
if (imesh && imesh->mesh) {
|
||||||
|
scene::IMesh *mesh = imesh->mesh;
|
||||||
driver->clearZBuffer();
|
driver->clearZBuffer();
|
||||||
s32 delta = 0;
|
s32 delta = 0;
|
||||||
if (rotation_kind < IT_ROT_NONE) {
|
if (rotation_kind < IT_ROT_NONE) {
|
||||||
@ -667,16 +669,28 @@ void drawItemStack(video::IVideoDriver *driver,
|
|||||||
matrix.makeIdentity();
|
matrix.makeIdentity();
|
||||||
|
|
||||||
if (enable_animations) {
|
if (enable_animations) {
|
||||||
float timer_f = (float)delta / 5000.0;
|
float timer_f = (float) delta / 5000.0;
|
||||||
matrix.setRotationDegrees(core::vector3df(0, 360 * timer_f, 0));
|
matrix.setRotationDegrees(core::vector3df(0, 360 * timer_f, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
driver->setTransform(video::ETS_WORLD, matrix);
|
driver->setTransform(video::ETS_WORLD, matrix);
|
||||||
driver->setViewPort(rect);
|
driver->setViewPort(rect);
|
||||||
|
|
||||||
|
video::SColor basecolor =
|
||||||
|
client->idef()->getItemstackColor(item, client);
|
||||||
|
|
||||||
u32 mc = mesh->getMeshBufferCount();
|
u32 mc = mesh->getMeshBufferCount();
|
||||||
for (u32 j = 0; j < mc; ++j) {
|
for (u32 j = 0; j < mc; ++j) {
|
||||||
scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
|
scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
|
||||||
|
// we can modify vertices relatively fast,
|
||||||
|
// because these meshes are not buffered.
|
||||||
|
assert(buf->getHardwareMappingHint_Vertex() == scene::EHM_NEVER);
|
||||||
|
video::SColor c = basecolor;
|
||||||
|
if (imesh->buffer_colors.size() > j) {
|
||||||
|
std::pair<bool, video::SColor> p = imesh->buffer_colors[j];
|
||||||
|
c = p.first ? p.second : basecolor;
|
||||||
|
}
|
||||||
|
colorizeMeshBuffer(buf, &c);
|
||||||
video::SMaterial &material = buf->getMaterial();
|
video::SMaterial &material = buf->getMaterial();
|
||||||
material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||||
material.Lighting = false;
|
material.Lighting = false;
|
||||||
|
@ -82,6 +82,8 @@ ItemDefinition& ItemDefinition::operator=(const ItemDefinition &def)
|
|||||||
sound_place = def.sound_place;
|
sound_place = def.sound_place;
|
||||||
sound_place_failed = def.sound_place_failed;
|
sound_place_failed = def.sound_place_failed;
|
||||||
range = def.range;
|
range = def.range;
|
||||||
|
palette_image = def.palette_image;
|
||||||
|
color = def.color;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,6 +106,8 @@ void ItemDefinition::reset()
|
|||||||
description = "";
|
description = "";
|
||||||
inventory_image = "";
|
inventory_image = "";
|
||||||
wield_image = "";
|
wield_image = "";
|
||||||
|
palette_image = "";
|
||||||
|
color = video::SColor(0xFFFFFFFF);
|
||||||
wield_scale = v3f(1.0, 1.0, 1.0);
|
wield_scale = v3f(1.0, 1.0, 1.0);
|
||||||
stack_max = 99;
|
stack_max = 99;
|
||||||
usable = false;
|
usable = false;
|
||||||
@ -153,6 +157,8 @@ void ItemDefinition::serialize(std::ostream &os, u16 protocol_version) const
|
|||||||
writeF1000(os, range);
|
writeF1000(os, range);
|
||||||
os << serializeString(sound_place_failed.name);
|
os << serializeString(sound_place_failed.name);
|
||||||
writeF1000(os, sound_place_failed.gain);
|
writeF1000(os, sound_place_failed.gain);
|
||||||
|
os << serializeString(palette_image);
|
||||||
|
writeU32(os, color.color);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ItemDefinition::deSerialize(std::istream &is)
|
void ItemDefinition::deSerialize(std::istream &is)
|
||||||
@ -209,6 +215,8 @@ void ItemDefinition::deSerialize(std::istream &is)
|
|||||||
try {
|
try {
|
||||||
sound_place_failed.name = deSerializeString(is);
|
sound_place_failed.name = deSerializeString(is);
|
||||||
sound_place_failed.gain = readF1000(is);
|
sound_place_failed.gain = readF1000(is);
|
||||||
|
palette_image = deSerializeString(is);
|
||||||
|
color.set(readU32(is));
|
||||||
} catch(SerializationError &e) {};
|
} catch(SerializationError &e) {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,11 +232,13 @@ class CItemDefManager: public IWritableItemDefManager
|
|||||||
struct ClientCached
|
struct ClientCached
|
||||||
{
|
{
|
||||||
video::ITexture *inventory_texture;
|
video::ITexture *inventory_texture;
|
||||||
scene::IMesh *wield_mesh;
|
ItemMesh wield_mesh;
|
||||||
|
Palette *palette;
|
||||||
|
|
||||||
ClientCached():
|
ClientCached():
|
||||||
inventory_texture(NULL),
|
inventory_texture(NULL),
|
||||||
wield_mesh(NULL)
|
wield_mesh(),
|
||||||
|
palette(NULL)
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
@ -250,8 +260,8 @@ public:
|
|||||||
i = values.begin(); i != values.end(); ++i)
|
i = values.begin(); i != values.end(); ++i)
|
||||||
{
|
{
|
||||||
ClientCached *cc = *i;
|
ClientCached *cc = *i;
|
||||||
if (cc->wield_mesh)
|
if (cc->wield_mesh.mesh)
|
||||||
cc->wield_mesh->drop();
|
cc->wield_mesh.mesh->drop();
|
||||||
delete cc;
|
delete cc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -335,8 +345,9 @@ public:
|
|||||||
ItemStack item = ItemStack();
|
ItemStack item = ItemStack();
|
||||||
item.name = def.name;
|
item.name = def.name;
|
||||||
|
|
||||||
scene::IMesh *mesh = getItemMesh(client, item);
|
getItemMesh(client, item, &(cc->wield_mesh));
|
||||||
cc->wield_mesh = mesh;
|
|
||||||
|
cc->palette = tsrc->getPalette(def.palette_image);
|
||||||
|
|
||||||
// Put in cache
|
// Put in cache
|
||||||
m_clientcached.set(name, cc);
|
m_clientcached.set(name, cc);
|
||||||
@ -390,13 +401,41 @@ public:
|
|||||||
return cc->inventory_texture;
|
return cc->inventory_texture;
|
||||||
}
|
}
|
||||||
// Get item wield mesh
|
// Get item wield mesh
|
||||||
virtual scene::IMesh* getWieldMesh(const std::string &name,
|
virtual ItemMesh* getWieldMesh(const std::string &name,
|
||||||
Client *client) const
|
Client *client) const
|
||||||
{
|
{
|
||||||
ClientCached *cc = getClientCached(name, client);
|
ClientCached *cc = getClientCached(name, client);
|
||||||
if(!cc)
|
if(!cc)
|
||||||
return NULL;
|
return NULL;
|
||||||
return cc->wield_mesh;
|
return &(cc->wield_mesh);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get item palette
|
||||||
|
virtual Palette* getPalette(const std::string &name,
|
||||||
|
Client *client) const
|
||||||
|
{
|
||||||
|
ClientCached *cc = getClientCached(name, client);
|
||||||
|
if(!cc)
|
||||||
|
return NULL;
|
||||||
|
return cc->palette;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual video::SColor getItemstackColor(const ItemStack &stack,
|
||||||
|
Client *client) const
|
||||||
|
{
|
||||||
|
// Look for direct color definition
|
||||||
|
const std::string &colorstring = stack.metadata.getString("color", 0);
|
||||||
|
video::SColor directcolor;
|
||||||
|
if ((colorstring != "")
|
||||||
|
&& parseColorString(colorstring, directcolor, true))
|
||||||
|
return directcolor;
|
||||||
|
// See if there is a palette
|
||||||
|
Palette *palette = getPalette(stack.name, client);
|
||||||
|
const std::string &index = stack.metadata.getString("palette_index", 0);
|
||||||
|
if ((palette != NULL) && (index != ""))
|
||||||
|
return (*palette)[mystoi(index, 0, 255)];
|
||||||
|
// Fallback color
|
||||||
|
return get(stack.name).color;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
void clear()
|
void clear()
|
||||||
|
@ -30,6 +30,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
class IGameDef;
|
class IGameDef;
|
||||||
class Client;
|
class Client;
|
||||||
struct ToolCapabilities;
|
struct ToolCapabilities;
|
||||||
|
#ifndef SERVER
|
||||||
|
#include "client/tile.h"
|
||||||
|
struct ItemMesh;
|
||||||
|
struct ItemStack;
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Base item definition
|
Base item definition
|
||||||
@ -57,6 +62,8 @@ struct ItemDefinition
|
|||||||
*/
|
*/
|
||||||
std::string inventory_image; // Optional for nodes, mandatory for tools/craftitems
|
std::string inventory_image; // Optional for nodes, mandatory for tools/craftitems
|
||||||
std::string wield_image; // If empty, inventory_image or mesh (only nodes) is used
|
std::string wield_image; // If empty, inventory_image or mesh (only nodes) is used
|
||||||
|
std::string palette_image; // If specified, the item will be colorized based on this
|
||||||
|
video::SColor color; // The fallback color of the node.
|
||||||
v3f wield_scale;
|
v3f wield_scale;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -110,8 +117,15 @@ public:
|
|||||||
virtual video::ITexture* getInventoryTexture(const std::string &name,
|
virtual video::ITexture* getInventoryTexture(const std::string &name,
|
||||||
Client *client) const=0;
|
Client *client) const=0;
|
||||||
// Get item wield mesh
|
// Get item wield mesh
|
||||||
virtual scene::IMesh* getWieldMesh(const std::string &name,
|
virtual ItemMesh* getWieldMesh(const std::string &name,
|
||||||
Client *client) const=0;
|
Client *client) const=0;
|
||||||
|
// Get item palette
|
||||||
|
virtual Palette* getPalette(const std::string &name,
|
||||||
|
Client *client) const = 0;
|
||||||
|
// Returns the base color of an item stack: the color of all
|
||||||
|
// tiles that do not define their own color.
|
||||||
|
virtual video::SColor getItemstackColor(const ItemStack &stack,
|
||||||
|
Client *client) const = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
virtual void serialize(std::ostream &os, u16 protocol_version)=0;
|
virtual void serialize(std::ostream &os, u16 protocol_version)=0;
|
||||||
@ -136,7 +150,7 @@ public:
|
|||||||
virtual video::ITexture* getInventoryTexture(const std::string &name,
|
virtual video::ITexture* getInventoryTexture(const std::string &name,
|
||||||
Client *client) const=0;
|
Client *client) const=0;
|
||||||
// Get item wield mesh
|
// Get item wield mesh
|
||||||
virtual scene::IMesh* getWieldMesh(const std::string &name,
|
virtual ItemMesh* getWieldMesh(const std::string &name,
|
||||||
Client *client) const=0;
|
Client *client) const=0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -786,6 +786,8 @@ void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc
|
|||||||
tiledef_special[j].backface_culling, material_type);
|
tiledef_special[j].backface_culling, material_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
palette = tsrc->getPalette(palette_name);
|
||||||
|
|
||||||
if ((drawtype == NDT_MESH) && (mesh != "")) {
|
if ((drawtype == NDT_MESH) && (mesh != "")) {
|
||||||
// Meshnode drawtype
|
// Meshnode drawtype
|
||||||
// Read the mesh and apply scale
|
// Read the mesh and apply scale
|
||||||
@ -859,9 +861,6 @@ public:
|
|||||||
virtual void removeNode(const std::string &name);
|
virtual void removeNode(const std::string &name);
|
||||||
virtual void updateAliases(IItemDefManager *idef);
|
virtual void updateAliases(IItemDefManager *idef);
|
||||||
virtual void applyTextureOverrides(const std::string &override_filepath);
|
virtual void applyTextureOverrides(const std::string &override_filepath);
|
||||||
//! Returns a palette or NULL if not found. Only on client.
|
|
||||||
std::vector<video::SColor> *getPalette(const ContentFeatures &f,
|
|
||||||
const IGameDef *gamedef);
|
|
||||||
virtual void updateTextures(IGameDef *gamedef,
|
virtual void updateTextures(IGameDef *gamedef,
|
||||||
void (*progress_cbk)(void *progress_args, u32 progress, u32 max_progress),
|
void (*progress_cbk)(void *progress_args, u32 progress, u32 max_progress),
|
||||||
void *progress_cbk_args);
|
void *progress_cbk_args);
|
||||||
@ -910,9 +909,6 @@ private:
|
|||||||
// Next possibly free id
|
// Next possibly free id
|
||||||
content_t m_next_id;
|
content_t m_next_id;
|
||||||
|
|
||||||
// Maps image file names to loaded palettes.
|
|
||||||
UNORDERED_MAP<std::string, std::vector<video::SColor> > m_palettes;
|
|
||||||
|
|
||||||
// NodeResolvers to callback once node registration has ended
|
// NodeResolvers to callback once node registration has ended
|
||||||
std::vector<NodeResolver *> m_pending_resolve_callbacks;
|
std::vector<NodeResolver *> m_pending_resolve_callbacks;
|
||||||
|
|
||||||
@ -1401,78 +1397,6 @@ void CNodeDefManager::applyTextureOverrides(const std::string &override_filepath
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<video::SColor> *CNodeDefManager::getPalette(
|
|
||||||
const ContentFeatures &f, const IGameDef *gamedef)
|
|
||||||
{
|
|
||||||
#ifndef SERVER
|
|
||||||
// This works because colors always use the most significant bits
|
|
||||||
// of param2. If you add a new colored type which uses param2
|
|
||||||
// in a more advanced way, you should change this code, too.
|
|
||||||
u32 palette_pixels = 0;
|
|
||||||
switch (f.param_type_2) {
|
|
||||||
case CPT2_COLOR:
|
|
||||||
palette_pixels = 256;
|
|
||||||
break;
|
|
||||||
case CPT2_COLORED_FACEDIR:
|
|
||||||
palette_pixels = 8;
|
|
||||||
break;
|
|
||||||
case CPT2_COLORED_WALLMOUNTED:
|
|
||||||
palette_pixels = 32;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
// This many param2 values will have the same color
|
|
||||||
u32 step = 256 / palette_pixels;
|
|
||||||
const std::string &name = f.palette_name;
|
|
||||||
if (name == "")
|
|
||||||
return NULL;
|
|
||||||
Client *client = (Client *) gamedef;
|
|
||||||
ITextureSource *tsrc = client->tsrc();
|
|
||||||
|
|
||||||
UNORDERED_MAP<std::string, std::vector<video::SColor> >::iterator it =
|
|
||||||
m_palettes.find(name);
|
|
||||||
if (it == m_palettes.end()) {
|
|
||||||
// Create palette
|
|
||||||
if (!tsrc->isKnownSourceImage(name)) {
|
|
||||||
warningstream << "CNodeDefManager::getPalette(): palette \"" << name
|
|
||||||
<< "\" could not be loaded." << std::endl;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
video::IImage *img = tsrc->generateImage(name);
|
|
||||||
std::vector<video::SColor> new_palette;
|
|
||||||
u32 w = img->getDimension().Width;
|
|
||||||
u32 h = img->getDimension().Height;
|
|
||||||
// Real area of the image
|
|
||||||
u32 area = h * w;
|
|
||||||
if (area != palette_pixels)
|
|
||||||
warningstream << "CNodeDefManager::getPalette(): the "
|
|
||||||
<< "specified palette image \"" << name << "\" does not "
|
|
||||||
<< "contain exactly " << palette_pixels
|
|
||||||
<< " pixels." << std::endl;
|
|
||||||
if (area > palette_pixels)
|
|
||||||
area = palette_pixels;
|
|
||||||
// For each pixel in the image
|
|
||||||
for (u32 i = 0; i < area; i++) {
|
|
||||||
video::SColor c = img->getPixel(i % w, i / w);
|
|
||||||
// Fill in palette with 'step' colors
|
|
||||||
for (u32 j = 0; j < step; j++)
|
|
||||||
new_palette.push_back(c);
|
|
||||||
}
|
|
||||||
img->drop();
|
|
||||||
// Fill in remaining elements
|
|
||||||
while (new_palette.size() < 256)
|
|
||||||
new_palette.push_back(video::SColor(0xFFFFFFFF));
|
|
||||||
m_palettes[name] = new_palette;
|
|
||||||
it = m_palettes.find(name);
|
|
||||||
}
|
|
||||||
if (it != m_palettes.end())
|
|
||||||
return &((*it).second);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CNodeDefManager::updateTextures(IGameDef *gamedef,
|
void CNodeDefManager::updateTextures(IGameDef *gamedef,
|
||||||
void (*progress_callback)(void *progress_args, u32 progress, u32 max_progress),
|
void (*progress_callback)(void *progress_args, u32 progress, u32 max_progress),
|
||||||
void *progress_callback_args)
|
void *progress_callback_args)
|
||||||
@ -1489,12 +1413,10 @@ void CNodeDefManager::updateTextures(IGameDef *gamedef,
|
|||||||
TextureSettings tsettings;
|
TextureSettings tsettings;
|
||||||
tsettings.readSettings();
|
tsettings.readSettings();
|
||||||
|
|
||||||
m_palettes.clear();
|
|
||||||
u32 size = m_content_features.size();
|
u32 size = m_content_features.size();
|
||||||
|
|
||||||
for (u32 i = 0; i < size; i++) {
|
for (u32 i = 0; i < size; i++) {
|
||||||
ContentFeatures *f = &(m_content_features[i]);
|
ContentFeatures *f = &(m_content_features[i]);
|
||||||
f->palette = getPalette(*f, gamedef);
|
|
||||||
f->updateTextures(tsrc, shdsrc, meshmanip, client, tsettings);
|
f->updateTextures(tsrc, shdsrc, meshmanip, client, tsettings);
|
||||||
progress_callback(progress_callback_args, i, size);
|
progress_callback(progress_callback_args, i, size);
|
||||||
}
|
}
|
||||||
|
@ -117,6 +117,7 @@ void ObjectProperties::serialize(std::ostream &os) const
|
|||||||
writeARGB8(os, nametag_color);
|
writeARGB8(os, nametag_color);
|
||||||
writeF1000(os, automatic_face_movement_max_rotation_per_sec);
|
writeF1000(os, automatic_face_movement_max_rotation_per_sec);
|
||||||
os << serializeString(infotext);
|
os << serializeString(infotext);
|
||||||
|
os << serializeString(wield_item);
|
||||||
|
|
||||||
// Add stuff only at the bottom.
|
// Add stuff only at the bottom.
|
||||||
// Never remove anything, because we don't want new versions of this
|
// Never remove anything, because we don't want new versions of this
|
||||||
@ -159,6 +160,7 @@ void ObjectProperties::deSerialize(std::istream &is)
|
|||||||
nametag_color = readARGB8(is);
|
nametag_color = readARGB8(is);
|
||||||
automatic_face_movement_max_rotation_per_sec = readF1000(is);
|
automatic_face_movement_max_rotation_per_sec = readF1000(is);
|
||||||
infotext = deSerializeString(is);
|
infotext = deSerializeString(is);
|
||||||
|
wield_item = deSerializeString(is);
|
||||||
}catch(SerializationError &e){}
|
}catch(SerializationError &e){}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -52,6 +52,8 @@ struct ObjectProperties
|
|||||||
video::SColor nametag_color;
|
video::SColor nametag_color;
|
||||||
f32 automatic_face_movement_max_rotation_per_sec;
|
f32 automatic_face_movement_max_rotation_per_sec;
|
||||||
std::string infotext;
|
std::string infotext;
|
||||||
|
//! For dropped items, this contains item information.
|
||||||
|
std::string wield_item;
|
||||||
|
|
||||||
ObjectProperties();
|
ObjectProperties();
|
||||||
std::string dump();
|
std::string dump();
|
||||||
|
@ -58,6 +58,12 @@ ItemDefinition read_item_definition(lua_State* L,int index,
|
|||||||
getstringfield(L, index, "description", def.description);
|
getstringfield(L, index, "description", def.description);
|
||||||
getstringfield(L, index, "inventory_image", def.inventory_image);
|
getstringfield(L, index, "inventory_image", def.inventory_image);
|
||||||
getstringfield(L, index, "wield_image", def.wield_image);
|
getstringfield(L, index, "wield_image", def.wield_image);
|
||||||
|
getstringfield(L, index, "palette", def.palette_image);
|
||||||
|
|
||||||
|
// Read item color.
|
||||||
|
lua_getfield(L, index, "color");
|
||||||
|
read_color(L, -1, &def.color);
|
||||||
|
lua_pop(L, 1);
|
||||||
|
|
||||||
lua_getfield(L, index, "wield_scale");
|
lua_getfield(L, index, "wield_scale");
|
||||||
if(lua_istable(L, -1)){
|
if(lua_istable(L, -1)){
|
||||||
@ -118,7 +124,7 @@ ItemDefinition read_item_definition(lua_State* L,int index,
|
|||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
void read_object_properties(lua_State *L, int index,
|
void read_object_properties(lua_State *L, int index,
|
||||||
ObjectProperties *prop)
|
ObjectProperties *prop, IItemDefManager *idef)
|
||||||
{
|
{
|
||||||
if(index < 0)
|
if(index < 0)
|
||||||
index = lua_gettop(L) + 1 + index;
|
index = lua_gettop(L) + 1 + index;
|
||||||
@ -216,6 +222,10 @@ void read_object_properties(lua_State *L, int index,
|
|||||||
}
|
}
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
getstringfield(L, -1, "infotext", prop->infotext);
|
getstringfield(L, -1, "infotext", prop->infotext);
|
||||||
|
lua_getfield(L, -1, "wield_item");
|
||||||
|
if (!lua_isnil(L, -1))
|
||||||
|
prop->wield_item = read_item(L, -1, idef).getItemString();
|
||||||
|
lua_pop(L, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
@ -284,6 +294,8 @@ void push_object_properties(lua_State *L, ObjectProperties *prop)
|
|||||||
lua_setfield(L, -2, "automatic_face_movement_max_rotation_per_sec");
|
lua_setfield(L, -2, "automatic_face_movement_max_rotation_per_sec");
|
||||||
lua_pushlstring(L, prop->infotext.c_str(), prop->infotext.size());
|
lua_pushlstring(L, prop->infotext.c_str(), prop->infotext.size());
|
||||||
lua_setfield(L, -2, "infotext");
|
lua_setfield(L, -2, "infotext");
|
||||||
|
lua_pushlstring(L, prop->wield_item.c_str(), prop->wield_item.size());
|
||||||
|
lua_setfield(L, -2, "wield_item");
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
@ -89,7 +89,8 @@ void push_tool_capabilities (lua_State *L,
|
|||||||
ItemDefinition read_item_definition (lua_State *L, int index,
|
ItemDefinition read_item_definition (lua_State *L, int index,
|
||||||
ItemDefinition default_def);
|
ItemDefinition default_def);
|
||||||
void read_object_properties (lua_State *L, int index,
|
void read_object_properties (lua_State *L, int index,
|
||||||
ObjectProperties *prop);
|
ObjectProperties *prop,
|
||||||
|
IItemDefManager *idef);
|
||||||
void push_object_properties (lua_State *L,
|
void push_object_properties (lua_State *L,
|
||||||
ObjectProperties *prop);
|
ObjectProperties *prop);
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "object_properties.h"
|
#include "object_properties.h"
|
||||||
#include "common/c_converter.h"
|
#include "common/c_converter.h"
|
||||||
#include "common/c_content.h"
|
#include "common/c_content.h"
|
||||||
|
#include "server.h"
|
||||||
|
|
||||||
bool ScriptApiEntity::luaentity_Add(u16 id, const char *name)
|
bool ScriptApiEntity::luaentity_Add(u16 id, const char *name)
|
||||||
{
|
{
|
||||||
@ -187,11 +188,11 @@ void ScriptApiEntity::luaentity_GetProperties(u16 id,
|
|||||||
getstringfield(L, -1, "mesh", prop->mesh);
|
getstringfield(L, -1, "mesh", prop->mesh);
|
||||||
|
|
||||||
// Deprecated: read object properties directly
|
// Deprecated: read object properties directly
|
||||||
read_object_properties(L, -1, prop);
|
read_object_properties(L, -1, prop, getServer()->idef());
|
||||||
|
|
||||||
// Read initial_properties
|
// Read initial_properties
|
||||||
lua_getfield(L, -1, "initial_properties");
|
lua_getfield(L, -1, "initial_properties");
|
||||||
read_object_properties(L, -1, prop);
|
read_object_properties(L, -1, prop, getServer()->idef());
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,6 +92,10 @@ void ItemStackMetaRef::Register(lua_State *L)
|
|||||||
lua_pushcfunction(L, gc_object);
|
lua_pushcfunction(L, gc_object);
|
||||||
lua_settable(L, metatable);
|
lua_settable(L, metatable);
|
||||||
|
|
||||||
|
lua_pushliteral(L, "__eq");
|
||||||
|
lua_pushcfunction(L, l_equals);
|
||||||
|
lua_settable(L, metatable);
|
||||||
|
|
||||||
lua_pop(L, 1); // drop metatable
|
lua_pop(L, 1); // drop metatable
|
||||||
|
|
||||||
luaL_openlib(L, 0, methods, 0); // fill methodtable
|
luaL_openlib(L, 0, methods, 0); // fill methodtable
|
||||||
@ -111,5 +115,6 @@ const luaL_Reg ItemStackMetaRef::methods[] = {
|
|||||||
luamethod(MetaDataRef, set_float),
|
luamethod(MetaDataRef, set_float),
|
||||||
luamethod(MetaDataRef, to_table),
|
luamethod(MetaDataRef, to_table),
|
||||||
luamethod(MetaDataRef, from_table),
|
luamethod(MetaDataRef, from_table),
|
||||||
|
luamethod(MetaDataRef, equals),
|
||||||
{0,0}
|
{0,0}
|
||||||
};
|
};
|
||||||
|
@ -250,3 +250,17 @@ bool MetaDataRef::handleFromTable(lua_State *L, int table, Metadata *meta)
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// equals(self, other)
|
||||||
|
int MetaDataRef::l_equals(lua_State *L)
|
||||||
|
{
|
||||||
|
MetaDataRef *ref1 = checkobject(L, 1);
|
||||||
|
Metadata *data1 = ref1->getmeta(false);
|
||||||
|
MetaDataRef *ref2 = checkobject(L, 2);
|
||||||
|
Metadata *data2 = ref2->getmeta(false);
|
||||||
|
if (data1 == NULL || data2 == NULL)
|
||||||
|
lua_pushboolean(L, data1 == data2);
|
||||||
|
else
|
||||||
|
lua_pushboolean(L, *data1 == *data2);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
@ -67,6 +67,9 @@ protected:
|
|||||||
|
|
||||||
// from_table(self, table)
|
// from_table(self, table)
|
||||||
static int l_from_table(lua_State *L);
|
static int l_from_table(lua_State *L);
|
||||||
|
|
||||||
|
// equals(self, other)
|
||||||
|
static int l_equals(lua_State *L);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* L_NODEMETA_H_ */
|
#endif /* L_NODEMETA_H_ */
|
||||||
|
@ -204,6 +204,10 @@ void NodeMetaRef::RegisterCommon(lua_State *L)
|
|||||||
lua_pushcfunction(L, gc_object);
|
lua_pushcfunction(L, gc_object);
|
||||||
lua_settable(L, metatable);
|
lua_settable(L, metatable);
|
||||||
|
|
||||||
|
lua_pushliteral(L, "__eq");
|
||||||
|
lua_pushcfunction(L, l_equals);
|
||||||
|
lua_settable(L, metatable);
|
||||||
|
|
||||||
lua_pop(L, 1); // drop metatable
|
lua_pop(L, 1); // drop metatable
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -225,6 +229,7 @@ const luaL_Reg NodeMetaRef::methodsServer[] = {
|
|||||||
luamethod(MetaDataRef, to_table),
|
luamethod(MetaDataRef, to_table),
|
||||||
luamethod(MetaDataRef, from_table),
|
luamethod(MetaDataRef, from_table),
|
||||||
luamethod(NodeMetaRef, get_inventory),
|
luamethod(NodeMetaRef, get_inventory),
|
||||||
|
luamethod(MetaDataRef, equals),
|
||||||
{0,0}
|
{0,0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -737,7 +737,7 @@ int ObjectRef::l_set_properties(lua_State *L)
|
|||||||
ObjectProperties *prop = co->accessObjectProperties();
|
ObjectProperties *prop = co->accessObjectProperties();
|
||||||
if (!prop)
|
if (!prop)
|
||||||
return 0;
|
return 0;
|
||||||
read_object_properties(L, 2, prop);
|
read_object_properties(L, 2, prop, getServer(L)->idef());
|
||||||
co->notifyObjectPropertiesModified();
|
co->notifyObjectPropertiesModified();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -98,6 +98,10 @@ void StorageRef::Register(lua_State *L)
|
|||||||
lua_pushcfunction(L, gc_object);
|
lua_pushcfunction(L, gc_object);
|
||||||
lua_settable(L, metatable);
|
lua_settable(L, metatable);
|
||||||
|
|
||||||
|
lua_pushliteral(L, "__eq");
|
||||||
|
lua_pushcfunction(L, l_equals);
|
||||||
|
lua_settable(L, metatable);
|
||||||
|
|
||||||
lua_pop(L, 1); // drop metatable
|
lua_pop(L, 1); // drop metatable
|
||||||
|
|
||||||
luaL_openlib(L, 0, methods, 0); // fill methodtable
|
luaL_openlib(L, 0, methods, 0); // fill methodtable
|
||||||
@ -138,5 +142,6 @@ const luaL_Reg StorageRef::methods[] = {
|
|||||||
luamethod(MetaDataRef, set_float),
|
luamethod(MetaDataRef, set_float),
|
||||||
luamethod(MetaDataRef, to_table),
|
luamethod(MetaDataRef, to_table),
|
||||||
luamethod(MetaDataRef, from_table),
|
luamethod(MetaDataRef, from_table),
|
||||||
|
luamethod(MetaDataRef, equals),
|
||||||
{0,0}
|
{0,0}
|
||||||
};
|
};
|
||||||
|
@ -318,11 +318,15 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, Client *client)
|
|||||||
u32 shader_id = shdrsrc->getShader("wielded_shader", TILE_MATERIAL_BASIC, NDT_NORMAL);
|
u32 shader_id = shdrsrc->getShader("wielded_shader", TILE_MATERIAL_BASIC, NDT_NORMAL);
|
||||||
m_material_type = shdrsrc->getShaderInfo(shader_id).material;
|
m_material_type = shdrsrc->getShaderInfo(shader_id).material;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Color-related
|
||||||
m_colors.clear();
|
m_colors.clear();
|
||||||
|
video::SColor basecolor = idef->getItemstackColor(item, client);
|
||||||
|
|
||||||
// If wield_image is defined, it overrides everything else
|
// If wield_image is defined, it overrides everything else
|
||||||
if (def.wield_image != "") {
|
if (def.wield_image != "") {
|
||||||
setExtruded(def.wield_image, def.wield_scale, tsrc, 1);
|
setExtruded(def.wield_image, def.wield_scale, tsrc, 1);
|
||||||
|
m_colors.push_back(basecolor);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Handle nodes
|
// Handle nodes
|
||||||
@ -371,7 +375,7 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, Client *client)
|
|||||||
} else {
|
} else {
|
||||||
material.setTexture(0, tile->texture);
|
material.setTexture(0, tile->texture);
|
||||||
}
|
}
|
||||||
m_colors.push_back(tile->color);
|
m_colors.push_back(tile->has_color ? tile->color : basecolor);
|
||||||
material.MaterialType = m_material_type;
|
material.MaterialType = m_material_type;
|
||||||
if (m_enable_shaders) {
|
if (m_enable_shaders) {
|
||||||
if (tile->normal_texture) {
|
if (tile->normal_texture) {
|
||||||
@ -389,6 +393,7 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, Client *client)
|
|||||||
}
|
}
|
||||||
else if (def.inventory_image != "") {
|
else if (def.inventory_image != "") {
|
||||||
setExtruded(def.inventory_image, def.wield_scale, tsrc, 1);
|
setExtruded(def.inventory_image, def.wield_scale, tsrc, 1);
|
||||||
|
m_colors.push_back(basecolor);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -455,7 +460,7 @@ void WieldMeshSceneNode::changeToMesh(scene::IMesh *mesh)
|
|||||||
m_meshnode->setVisible(true);
|
m_meshnode->setVisible(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
scene::IMesh *getItemMesh(Client *client, const ItemStack &item)
|
void getItemMesh(Client *client, const ItemStack &item, ItemMesh *result)
|
||||||
{
|
{
|
||||||
ITextureSource *tsrc = client->getTextureSource();
|
ITextureSource *tsrc = client->getTextureSource();
|
||||||
IItemDefManager *idef = client->getItemDefManager();
|
IItemDefManager *idef = client->getItemDefManager();
|
||||||
@ -475,12 +480,13 @@ scene::IMesh *getItemMesh(Client *client, const ItemStack &item)
|
|||||||
// If inventory_image is defined, it overrides everything else
|
// If inventory_image is defined, it overrides everything else
|
||||||
if (def.inventory_image != "") {
|
if (def.inventory_image != "") {
|
||||||
mesh = getExtrudedMesh(tsrc, def.inventory_image);
|
mesh = getExtrudedMesh(tsrc, def.inventory_image);
|
||||||
return mesh;
|
result->mesh = mesh;
|
||||||
|
result->buffer_colors.push_back(
|
||||||
|
std::pair<bool, video::SColor>(false, video::SColor(0xFFFFFFFF)));
|
||||||
} else if (def.type == ITEM_NODE) {
|
} else if (def.type == ITEM_NODE) {
|
||||||
if (f.mesh_ptr[0]) {
|
if (f.mesh_ptr[0]) {
|
||||||
mesh = cloneMesh(f.mesh_ptr[0]);
|
mesh = cloneMesh(f.mesh_ptr[0]);
|
||||||
scaleMesh(mesh, v3f(0.12, 0.12, 0.12));
|
scaleMesh(mesh, v3f(0.12, 0.12, 0.12));
|
||||||
setMeshColor(mesh, video::SColor (255, 255, 255, 255));
|
|
||||||
} else if (f.drawtype == NDT_PLANTLIKE) {
|
} else if (f.drawtype == NDT_PLANTLIKE) {
|
||||||
mesh = getExtrudedMesh(tsrc,
|
mesh = getExtrudedMesh(tsrc,
|
||||||
tsrc->getTextureName(f.tiles[0].texture_id));
|
tsrc->getTextureName(f.tiles[0].texture_id));
|
||||||
@ -515,6 +521,8 @@ scene::IMesh *getItemMesh(Client *client, const ItemStack &item)
|
|||||||
for (u32 i = 0; i < mc; ++i) {
|
for (u32 i = 0; i < mc; ++i) {
|
||||||
const TileSpec *tile = &(f.tiles[i]);
|
const TileSpec *tile = &(f.tiles[i]);
|
||||||
scene::IMeshBuffer *buf = mesh->getMeshBuffer(i);
|
scene::IMeshBuffer *buf = mesh->getMeshBuffer(i);
|
||||||
|
result->buffer_colors.push_back(
|
||||||
|
std::pair<bool, video::SColor>(tile->has_color, tile->color));
|
||||||
colorizeMeshBuffer(buf, &tile->color);
|
colorizeMeshBuffer(buf, &tile->color);
|
||||||
video::SMaterial &material = buf->getMaterial();
|
video::SMaterial &material = buf->getMaterial();
|
||||||
material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||||
@ -532,9 +540,8 @@ scene::IMesh *getItemMesh(Client *client, const ItemStack &item)
|
|||||||
|
|
||||||
rotateMeshXZby(mesh, -45);
|
rotateMeshXZby(mesh, -45);
|
||||||
rotateMeshYZby(mesh, -30);
|
rotateMeshYZby(mesh, -30);
|
||||||
return mesh;
|
result->mesh = mesh;
|
||||||
}
|
}
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
scene::IMesh * getExtrudedMesh(ITextureSource *tsrc,
|
scene::IMesh * getExtrudedMesh(ITextureSource *tsrc,
|
||||||
|
@ -28,6 +28,22 @@ class Client;
|
|||||||
class ITextureSource;
|
class ITextureSource;
|
||||||
struct TileSpec;
|
struct TileSpec;
|
||||||
|
|
||||||
|
struct ItemMesh
|
||||||
|
{
|
||||||
|
scene::IMesh* mesh;
|
||||||
|
/*!
|
||||||
|
* Stores the color of each mesh buffer.
|
||||||
|
* If the boolean is true, the color is fixed, else
|
||||||
|
* palettes can modify it.
|
||||||
|
*/
|
||||||
|
std::vector<std::pair<bool, video::SColor> > buffer_colors;
|
||||||
|
|
||||||
|
ItemMesh():
|
||||||
|
mesh(NULL),
|
||||||
|
buffer_colors()
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Wield item scene node, renders the wield mesh of some item
|
Wield item scene node, renders the wield mesh of some item
|
||||||
*/
|
*/
|
||||||
@ -79,7 +95,7 @@ private:
|
|||||||
aabb3f m_bounding_box;
|
aabb3f m_bounding_box;
|
||||||
};
|
};
|
||||||
|
|
||||||
scene::IMesh *getItemMesh(Client *client, const ItemStack &item);
|
void getItemMesh(Client *client, const ItemStack &item, ItemMesh *result);
|
||||||
|
|
||||||
scene::IMesh *getExtrudedMesh(ITextureSource *tsrc, const std::string &imagename);
|
scene::IMesh *getExtrudedMesh(ITextureSource *tsrc, const std::string &imagename);
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user