mirror of
https://github.com/minetest/minetest.git
synced 2024-11-30 03:23:45 +01:00
Degrotate support for mesh nodes (#7840)
This commit is contained in:
parent
fde2785fe3
commit
3b78a22371
@ -157,7 +157,7 @@ end
|
|||||||
|
|
||||||
function core.is_colored_paramtype(ptype)
|
function core.is_colored_paramtype(ptype)
|
||||||
return (ptype == "color") or (ptype == "colorfacedir") or
|
return (ptype == "color") or (ptype == "colorfacedir") or
|
||||||
(ptype == "colorwallmounted")
|
(ptype == "colorwallmounted") or (ptype == "colordegrotate")
|
||||||
end
|
end
|
||||||
|
|
||||||
function core.strip_param2_color(param2, paramtype2)
|
function core.strip_param2_color(param2, paramtype2)
|
||||||
@ -168,6 +168,8 @@ function core.strip_param2_color(param2, paramtype2)
|
|||||||
param2 = math.floor(param2 / 32) * 32
|
param2 = math.floor(param2 / 32) * 32
|
||||||
elseif paramtype2 == "colorwallmounted" then
|
elseif paramtype2 == "colorwallmounted" then
|
||||||
param2 = math.floor(param2 / 8) * 8
|
param2 = math.floor(param2 / 8) * 8
|
||||||
|
elseif paramtype2 == "colordegrotate" then
|
||||||
|
param2 = math.floor(param2 / 32) * 32
|
||||||
end
|
end
|
||||||
-- paramtype2 == "color" requires no modification.
|
-- paramtype2 == "color" requires no modification.
|
||||||
return param2
|
return param2
|
||||||
@ -345,6 +347,8 @@ function core.item_place_node(itemstack, placer, pointed_thing, param2,
|
|||||||
color_divisor = 8
|
color_divisor = 8
|
||||||
elseif def.paramtype2 == "colorfacedir" then
|
elseif def.paramtype2 == "colorfacedir" then
|
||||||
color_divisor = 32
|
color_divisor = 32
|
||||||
|
elseif def.paramtype2 == "colordegrotate" then
|
||||||
|
color_divisor = 32
|
||||||
end
|
end
|
||||||
if color_divisor then
|
if color_divisor then
|
||||||
local color = math.floor(metatable.palette_index / color_divisor)
|
local color = math.floor(metatable.palette_index / color_divisor)
|
||||||
|
@ -1048,9 +1048,9 @@ The function of `param2` is determined by `paramtype2` in node definition.
|
|||||||
* The height of the 'plantlike' section is stored in `param2`.
|
* The height of the 'plantlike' section is stored in `param2`.
|
||||||
* The height is (`param2` / 16) nodes.
|
* The height is (`param2` / 16) nodes.
|
||||||
* `paramtype2 = "degrotate"`
|
* `paramtype2 = "degrotate"`
|
||||||
* Only valid for "plantlike" drawtype. The rotation of the node is stored in
|
* Valid for `plantlike` and `mesh` drawtypes. The rotation of the node is
|
||||||
`param2`.
|
stored in `param2`.
|
||||||
* Values range 0 - 179. The value stored in `param2` is multiplied by two to
|
* Values range 0–239. The value stored in `param2` is multiplied by 1.5 to
|
||||||
get the actual rotation in degrees of the node.
|
get the actual rotation in degrees of the node.
|
||||||
* `paramtype2 = "meshoptions"`
|
* `paramtype2 = "meshoptions"`
|
||||||
* Only valid for "plantlike" drawtype. `param2` encodes the shape and
|
* Only valid for "plantlike" drawtype. `param2` encodes the shape and
|
||||||
@ -1088,6 +1088,11 @@ The function of `param2` is determined by `paramtype2` in node definition.
|
|||||||
* `param2` values 0-63 define 64 levels of internal liquid, 0 being empty
|
* `param2` values 0-63 define 64 levels of internal liquid, 0 being empty
|
||||||
and 63 being full.
|
and 63 being full.
|
||||||
* Liquid texture is defined using `special_tiles = {"modname_tilename.png"}`
|
* Liquid texture is defined using `special_tiles = {"modname_tilename.png"}`
|
||||||
|
* `paramtype2 = "colordegrotate"`
|
||||||
|
* Same as `degrotate`, but with colors.
|
||||||
|
* The first (most-significant) three bits of `param2` tells which color
|
||||||
|
is picked from the palette. The palette should have 8 pixels.
|
||||||
|
* Remaining 5 bits store rotation in range 0–23 (i.e. in 15° steps)
|
||||||
* `paramtype2 = "none"`
|
* `paramtype2 = "none"`
|
||||||
* `param2` will not be used by the engine and can be used to store
|
* `param2` will not be used by the engine and can be used to store
|
||||||
an arbitrary value
|
an arbitrary value
|
||||||
|
@ -223,6 +223,30 @@ minetest.register_node("testnodes:plantlike_waving", {
|
|||||||
|
|
||||||
|
|
||||||
-- param2 will rotate
|
-- param2 will rotate
|
||||||
|
local function rotate_on_rightclick(pos, node, clicker)
|
||||||
|
local def = minetest.registered_nodes[node.name]
|
||||||
|
local aux1 = clicker:get_player_control().aux1
|
||||||
|
|
||||||
|
local deg, deg_max
|
||||||
|
local color, color_mult = 0, 0
|
||||||
|
if def.paramtype2 == "degrotate" then
|
||||||
|
deg = node.param2
|
||||||
|
deg_max = 240
|
||||||
|
elseif def.paramtype2 == "colordegrotate" then
|
||||||
|
-- MSB [3x color, 5x rotation] LSB
|
||||||
|
deg = node.param2 % 2^5
|
||||||
|
deg_max = 24
|
||||||
|
color_mult = 2^5
|
||||||
|
color = math.floor(node.param2 / color_mult)
|
||||||
|
end
|
||||||
|
|
||||||
|
deg = (deg + (aux1 and 10 or 1)) % deg_max
|
||||||
|
node.param2 = color * color_mult + deg
|
||||||
|
minetest.swap_node(pos, node)
|
||||||
|
minetest.chat_send_player(clicker:get_player_name(),
|
||||||
|
"Rotation is now " .. deg .. " / " .. deg_max)
|
||||||
|
end
|
||||||
|
|
||||||
minetest.register_node("testnodes:plantlike_degrotate", {
|
minetest.register_node("testnodes:plantlike_degrotate", {
|
||||||
description = S("Degrotate Plantlike Drawtype Test Node"),
|
description = S("Degrotate Plantlike Drawtype Test Node"),
|
||||||
drawtype = "plantlike",
|
drawtype = "plantlike",
|
||||||
@ -230,12 +254,42 @@ minetest.register_node("testnodes:plantlike_degrotate", {
|
|||||||
paramtype2 = "degrotate",
|
paramtype2 = "degrotate",
|
||||||
tiles = { "testnodes_plantlike_degrotate.png" },
|
tiles = { "testnodes_plantlike_degrotate.png" },
|
||||||
|
|
||||||
|
on_rightclick = rotate_on_rightclick,
|
||||||
|
place_param2 = 7,
|
||||||
walkable = false,
|
walkable = false,
|
||||||
sunlight_propagates = true,
|
sunlight_propagates = true,
|
||||||
groups = { dig_immediate = 3 },
|
groups = { dig_immediate = 3 },
|
||||||
})
|
})
|
||||||
|
|
||||||
|
minetest.register_node("testnodes:mesh_degrotate", {
|
||||||
|
description = S("Degrotate Mesh Drawtype Test Node"),
|
||||||
|
drawtype = "mesh",
|
||||||
|
paramtype = "light",
|
||||||
|
paramtype2 = "degrotate",
|
||||||
|
mesh = "testnodes_pyramid.obj",
|
||||||
|
tiles = { "testnodes_mesh_stripes2.png" },
|
||||||
|
|
||||||
|
on_rightclick = rotate_on_rightclick,
|
||||||
|
place_param2 = 7,
|
||||||
|
sunlight_propagates = true,
|
||||||
|
groups = { dig_immediate = 3 },
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_node("testnodes:mesh_colordegrotate", {
|
||||||
|
description = S("Color Degrotate Mesh Drawtype Test Node"),
|
||||||
|
drawtype = "mesh",
|
||||||
|
paramtype2 = "colordegrotate",
|
||||||
|
palette = "testnodes_palette_facedir.png",
|
||||||
|
mesh = "testnodes_pyramid.obj",
|
||||||
|
tiles = { "testnodes_mesh_stripes2.png" },
|
||||||
|
|
||||||
|
on_rightclick = rotate_on_rightclick,
|
||||||
|
-- color index 1, 7 steps rotated
|
||||||
|
place_param2 = 1 * 2^5 + 7,
|
||||||
|
sunlight_propagates = true,
|
||||||
|
groups = { dig_immediate = 3 },
|
||||||
|
})
|
||||||
|
|
||||||
-- param2 will change height
|
-- param2 will change height
|
||||||
minetest.register_node("testnodes:plantlike_leveled", {
|
minetest.register_node("testnodes:plantlike_leveled", {
|
||||||
description = S("Leveled Plantlike Drawtype Test Node"),
|
description = S("Leveled Plantlike Drawtype Test Node"),
|
||||||
|
@ -968,7 +968,7 @@ void MapblockMeshGenerator::drawPlantlike()
|
|||||||
draw_style = PLANT_STYLE_CROSS;
|
draw_style = PLANT_STYLE_CROSS;
|
||||||
scale = BS / 2 * f->visual_scale;
|
scale = BS / 2 * f->visual_scale;
|
||||||
offset = v3f(0, 0, 0);
|
offset = v3f(0, 0, 0);
|
||||||
rotate_degree = 0;
|
rotate_degree = 0.0f;
|
||||||
random_offset_Y = false;
|
random_offset_Y = false;
|
||||||
face_num = 0;
|
face_num = 0;
|
||||||
plant_height = 1.0;
|
plant_height = 1.0;
|
||||||
@ -988,7 +988,8 @@ void MapblockMeshGenerator::drawPlantlike()
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case CPT2_DEGROTATE:
|
case CPT2_DEGROTATE:
|
||||||
rotate_degree = n.param2 * 2;
|
case CPT2_COLORED_DEGROTATE:
|
||||||
|
rotate_degree = 1.5f * n.getDegRotate(nodedef);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CPT2_LEVELED:
|
case CPT2_LEVELED:
|
||||||
@ -1343,6 +1344,7 @@ void MapblockMeshGenerator::drawMeshNode()
|
|||||||
u8 facedir = 0;
|
u8 facedir = 0;
|
||||||
scene::IMesh* mesh;
|
scene::IMesh* mesh;
|
||||||
bool private_mesh; // as a grab/drop pair is not thread-safe
|
bool private_mesh; // as a grab/drop pair is not thread-safe
|
||||||
|
int degrotate = 0;
|
||||||
|
|
||||||
if (f->param_type_2 == CPT2_FACEDIR ||
|
if (f->param_type_2 == CPT2_FACEDIR ||
|
||||||
f->param_type_2 == CPT2_COLORED_FACEDIR) {
|
f->param_type_2 == CPT2_COLORED_FACEDIR) {
|
||||||
@ -1354,9 +1356,12 @@ void MapblockMeshGenerator::drawMeshNode()
|
|||||||
facedir = n.getWallMounted(nodedef);
|
facedir = n.getWallMounted(nodedef);
|
||||||
if (!enable_mesh_cache)
|
if (!enable_mesh_cache)
|
||||||
facedir = wallmounted_to_facedir[facedir];
|
facedir = wallmounted_to_facedir[facedir];
|
||||||
|
} else if (f->param_type_2 == CPT2_DEGROTATE ||
|
||||||
|
f->param_type_2 == CPT2_COLORED_DEGROTATE) {
|
||||||
|
degrotate = n.getDegRotate(nodedef);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!data->m_smooth_lighting && f->mesh_ptr[facedir]) {
|
if (!data->m_smooth_lighting && f->mesh_ptr[facedir] && !degrotate) {
|
||||||
// use cached meshes
|
// use cached meshes
|
||||||
private_mesh = false;
|
private_mesh = false;
|
||||||
mesh = f->mesh_ptr[facedir];
|
mesh = f->mesh_ptr[facedir];
|
||||||
@ -1364,7 +1369,10 @@ void MapblockMeshGenerator::drawMeshNode()
|
|||||||
// no cache, clone and rotate mesh
|
// no cache, clone and rotate mesh
|
||||||
private_mesh = true;
|
private_mesh = true;
|
||||||
mesh = cloneMesh(f->mesh_ptr[0]);
|
mesh = cloneMesh(f->mesh_ptr[0]);
|
||||||
|
if (facedir)
|
||||||
rotateMeshBy6dFacedir(mesh, facedir);
|
rotateMeshBy6dFacedir(mesh, facedir);
|
||||||
|
else if (degrotate)
|
||||||
|
rotateMeshXZby(mesh, 1.5f * degrotate);
|
||||||
recalculateBoundingBox(mesh);
|
recalculateBoundingBox(mesh);
|
||||||
meshmanip->recalculateNormals(mesh, true, false);
|
meshmanip->recalculateNormals(mesh, true, false);
|
||||||
} else
|
} else
|
||||||
|
@ -139,7 +139,7 @@ public:
|
|||||||
// plantlike-specific
|
// plantlike-specific
|
||||||
PlantlikeStyle draw_style;
|
PlantlikeStyle draw_style;
|
||||||
v3f offset;
|
v3f offset;
|
||||||
int rotate_degree;
|
float rotate_degree;
|
||||||
bool random_offset_Y;
|
bool random_offset_Y;
|
||||||
int face_num;
|
int face_num;
|
||||||
float plant_height;
|
float plant_height;
|
||||||
|
@ -177,6 +177,16 @@ v3s16 MapNode::getWallMountedDir(const NodeDefManager *nodemgr) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u8 MapNode::getDegRotate(const NodeDefManager *nodemgr) const
|
||||||
|
{
|
||||||
|
const ContentFeatures &f = nodemgr->get(*this);
|
||||||
|
if (f.param_type_2 == CPT2_DEGROTATE)
|
||||||
|
return getParam2() % 240;
|
||||||
|
if (f.param_type_2 == CPT2_COLORED_DEGROTATE)
|
||||||
|
return 10 * ((getParam2() & 0x1F) % 24);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void MapNode::rotateAlongYAxis(const NodeDefManager *nodemgr, Rotation rot)
|
void MapNode::rotateAlongYAxis(const NodeDefManager *nodemgr, Rotation rot)
|
||||||
{
|
{
|
||||||
ContentParamType2 cpt2 = nodemgr->get(*this).param_type_2;
|
ContentParamType2 cpt2 = nodemgr->get(*this).param_type_2;
|
||||||
@ -230,6 +240,17 @@ void MapNode::rotateAlongYAxis(const NodeDefManager *nodemgr, Rotation rot)
|
|||||||
Rotation oldrot = wallmounted_to_rot[wmountface - 2];
|
Rotation oldrot = wallmounted_to_rot[wmountface - 2];
|
||||||
param2 &= ~7;
|
param2 &= ~7;
|
||||||
param2 |= rot_to_wallmounted[(oldrot - rot) & 3];
|
param2 |= rot_to_wallmounted[(oldrot - rot) & 3];
|
||||||
|
} else if (cpt2 == CPT2_DEGROTATE) {
|
||||||
|
int angle = param2; // in 1.5°
|
||||||
|
angle += 60 * rot; // don’t do that on u8
|
||||||
|
angle %= 240;
|
||||||
|
param2 = angle;
|
||||||
|
} else if (cpt2 == CPT2_COLORED_DEGROTATE) {
|
||||||
|
int angle = param2 & 0x1F; // in 15°
|
||||||
|
int color = param2 & 0xE0;
|
||||||
|
angle += 6 * rot;
|
||||||
|
angle %= 24;
|
||||||
|
param2 = color | angle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -240,6 +240,9 @@ struct MapNode
|
|||||||
u8 getWallMounted(const NodeDefManager *nodemgr) const;
|
u8 getWallMounted(const NodeDefManager *nodemgr) const;
|
||||||
v3s16 getWallMountedDir(const NodeDefManager *nodemgr) const;
|
v3s16 getWallMountedDir(const NodeDefManager *nodemgr) const;
|
||||||
|
|
||||||
|
/// @returns Rotation in range 0–239 (in 1.5° steps)
|
||||||
|
u8 getDegRotate(const NodeDefManager *nodemgr) const;
|
||||||
|
|
||||||
void rotateAlongYAxis(const NodeDefManager *nodemgr, Rotation rot);
|
void rotateAlongYAxis(const NodeDefManager *nodemgr, Rotation rot);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -944,7 +944,8 @@ void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc
|
|||||||
|
|
||||||
if (param_type_2 == CPT2_COLOR ||
|
if (param_type_2 == CPT2_COLOR ||
|
||||||
param_type_2 == CPT2_COLORED_FACEDIR ||
|
param_type_2 == CPT2_COLORED_FACEDIR ||
|
||||||
param_type_2 == CPT2_COLORED_WALLMOUNTED)
|
param_type_2 == CPT2_COLORED_WALLMOUNTED ||
|
||||||
|
param_type_2 == CPT2_COLORED_DEGROTATE)
|
||||||
palette = tsrc->getPalette(palette_name);
|
palette = tsrc->getPalette(palette_name);
|
||||||
|
|
||||||
if (drawtype == NDT_MESH && !mesh.empty()) {
|
if (drawtype == NDT_MESH && !mesh.empty()) {
|
||||||
|
@ -67,7 +67,7 @@ enum ContentParamType2
|
|||||||
CPT2_WALLMOUNTED,
|
CPT2_WALLMOUNTED,
|
||||||
// Block level like FLOWINGLIQUID
|
// Block level like FLOWINGLIQUID
|
||||||
CPT2_LEVELED,
|
CPT2_LEVELED,
|
||||||
// 2D rotation for things like plants
|
// 2D rotation
|
||||||
CPT2_DEGROTATE,
|
CPT2_DEGROTATE,
|
||||||
// Mesh options for plants
|
// Mesh options for plants
|
||||||
CPT2_MESHOPTIONS,
|
CPT2_MESHOPTIONS,
|
||||||
@ -79,6 +79,8 @@ enum ContentParamType2
|
|||||||
CPT2_COLORED_WALLMOUNTED,
|
CPT2_COLORED_WALLMOUNTED,
|
||||||
// Glasslike framed drawtype internal liquid level, param2 values 0 to 63
|
// Glasslike framed drawtype internal liquid level, param2 values 0 to 63
|
||||||
CPT2_GLASSLIKE_LIQUID_LEVEL,
|
CPT2_GLASSLIKE_LIQUID_LEVEL,
|
||||||
|
// 3 bits of palette index, then degrotate
|
||||||
|
CPT2_COLORED_DEGROTATE,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum LiquidType
|
enum LiquidType
|
||||||
|
@ -685,7 +685,8 @@ void read_content_features(lua_State *L, ContentFeatures &f, int index)
|
|||||||
if (!f.palette_name.empty() &&
|
if (!f.palette_name.empty() &&
|
||||||
!(f.param_type_2 == CPT2_COLOR ||
|
!(f.param_type_2 == CPT2_COLOR ||
|
||||||
f.param_type_2 == CPT2_COLORED_FACEDIR ||
|
f.param_type_2 == CPT2_COLORED_FACEDIR ||
|
||||||
f.param_type_2 == CPT2_COLORED_WALLMOUNTED))
|
f.param_type_2 == CPT2_COLORED_WALLMOUNTED ||
|
||||||
|
f.param_type_2 == CPT2_COLORED_DEGROTATE))
|
||||||
warningstream << "Node " << f.name.c_str()
|
warningstream << "Node " << f.name.c_str()
|
||||||
<< " has a palette, but not a suitable paramtype2." << std::endl;
|
<< " has a palette, but not a suitable paramtype2." << std::endl;
|
||||||
|
|
||||||
|
@ -65,6 +65,7 @@ struct EnumString ScriptApiNode::es_ContentParamType2[] =
|
|||||||
{CPT2_COLORED_FACEDIR, "colorfacedir"},
|
{CPT2_COLORED_FACEDIR, "colorfacedir"},
|
||||||
{CPT2_COLORED_WALLMOUNTED, "colorwallmounted"},
|
{CPT2_COLORED_WALLMOUNTED, "colorwallmounted"},
|
||||||
{CPT2_GLASSLIKE_LIQUID_LEVEL, "glasslikeliquidlevel"},
|
{CPT2_GLASSLIKE_LIQUID_LEVEL, "glasslikeliquidlevel"},
|
||||||
|
{CPT2_COLORED_DEGROTATE, "colordegrotate"},
|
||||||
{0, NULL},
|
{0, NULL},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user